http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/SuggestionManager.as ---------------------------------------------------------------------- diff --git a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/SuggestionManager.as b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/SuggestionManager.as new file mode 100644 index 0000000..f792b5d --- /dev/null +++ b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/SuggestionManager.as @@ -0,0 +1,1026 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + + +package com.adobe.linguistics.spelling.core +{ + import com.adobe.linguistics.spelling.core.env.InternalConstants; + import com.adobe.linguistics.spelling.core.rule.PrefixEntry; + import com.adobe.linguistics.spelling.core.rule.SuffixEntry; + import com.adobe.linguistics.spelling.core.utils.*; + + import flash.utils.Dictionary; + import flash.utils.getTimer; + + public class SuggestionManager + { + + private var _attributeMgr:LinguisticRule; + private var _maxSug:int; + private var _languageCode:String; + private var _ckey:String; + private var _cUpperTry:String; + private var _cLowerTry:String; + private var _cAllTry:String; + private var _maxngramsugs:int; + private var _fastMode:Boolean; + + private var _word:String; + private var _guessSuggestions:SuggestionsResult; + private var _guessWordList:SuggestionsResult; + private var guess:Array = new Array (InternalConstants.MAX_GUESS); + private var gscore:Array = new Array ( InternalConstants.MAX_GUESS); + + public function SuggestionManager( attrMgr:LinguisticRule, fastMode:Boolean = true ) + { + this._maxSug = InternalConstants.MAXSUGGESTION; + this._attributeMgr = attrMgr; + this._ckey = this._attributeMgr.keyString; + + this._cAllTry = this._attributeMgr.tryString; + this._cUpperTry = ""; + this._cLowerTry = ""; // lower and netual... + for ( var i:int = 0; (this._attributeMgr.tryString != null)&&(i < this._attributeMgr.tryString.length); ++i ) { + if ( this._attributeMgr.tryString.charAt(i) == this._attributeMgr.tryString.charAt(i).toLocaleLowerCase() ) { + this._cLowerTry+=this._attributeMgr.tryString.charAt(i); + } else { + this._cUpperTry+= this._attributeMgr.tryString.charAt(i); + } + + } + + this._maxngramsugs = InternalConstants.MAXNGRAMSUGS; + this._fastMode = fastMode; + + //initialized viriable for performance... + _word=null; + _guessSuggestions = new SuggestionsResult(InternalConstants.MAX_ROOTS, compareSuggestion ); + _guessWordList = new SuggestionsResult( InternalConstants.MAX_GUESS, compareSuggestion ); + if ( this._attributeMgr.maxNgramSuggestions > 0 ) this._maxngramsugs = this._attributeMgr.maxNgramSuggestions; + } + + public function get fastMode():Boolean { + return this._fastMode; + } + + public function set fastMode( value:Boolean ) :void { + this._fastMode = value; + } + + private static function compareSuggestion( obj1:*, obj2:*):int { + return (obj1.score-obj2.score); + } + + + public function set languageCode(value:String) :void { + this._languageCode = value; + } + + public function get languageCode():String { + return this._languageCode; + } + + public function nsuggest( result:Array, word:String ):int { + + if ( !((result.length+this._maxngramsugs) <= this._maxSug) ) return result.length; + + + var nsug:int = result.length; + var i:int,j:int,sc:int, opt:int, n:int = word.length; + var arr:Array; + var sd:SquigglyDictionary; + var dict:Dictionary; + _word = word; + var initCap:Boolean = (word.charAt(0) == word.charAt(0).toLocaleLowerCase() )? false:true; + var wordCapValue:int = word.charAt(0).toLocaleUpperCase().charCodeAt(0); + _guessSuggestions.clear(); + + /* A filter based on string length, it could be */ + var rangeOffset:int =5; + var endRange:int = word.length + (rangeOffset-2); + var startRange:int = (word.length>(rangeOffset+2)) ? (word.length-rangeOffset):2 ; + + var counter:Number=0 + var startTime:Number = getTimer(); + + // exhaustively search through all root words + // keeping track of the MAX_ROOTS most similar root words + + // word reversing wrapper for complex prefixes + + // set character based ngram suggestion for words with non-BMP Unicode characters + + //a filter for performance improvement... + var firstCodeValue:Number =word.charCodeAt(0), lastCodeValue:Number = word.charCodeAt(word.length-1); + + + for ( i=0;i<this._attributeMgr.dictionaryManager.dictonaryList.length; ++i ) { + sd = this._attributeMgr.dictionaryManager.dictonaryList[i]; + dict = sd.dictionary; + + var lowerS:String; + var he:HashEntry; + opt = InternalConstants.NGRAM_LONGER_WORSE + InternalConstants.NGRAM_LOWERING; + for( var key:String in dict ) { + if ( (key.length < startRange) || (key.length > endRange) ) continue; + if ( (this._fastMode) && (firstCodeValue != key.charCodeAt(0)) && (lastCodeValue != key.charCodeAt(key.length-1)) ) continue; + counter++; + + sc = ngram( 3, _word,key,opt) + leftCommonSubString(_word, key, initCap, wordCapValue); + + if ( sc > 0 ) { + if ( _guessSuggestions.size < InternalConstants.MAX_ROOTS ) { + if ( dict[key].affixFlagVector && + (dict[key].testAffix( this._attributeMgr.forbiddenWord ) || + dict[key].testAffix( this._attributeMgr.onlyInCompound) || + dict[key].testAffix( this._attributeMgr.noSuggest ) || + dict[key].testAffix( InternalConstants.ONLYUPCASEFLAG ) + )) continue; + _guessSuggestions.insert( new SuggestionEntry(sc,key, dict[key] ) ); + if ( _guessSuggestions.size == InternalConstants.MAX_ROOTS ) { + _guessSuggestions.buildheap(); + } + }else { + if ( sc > _guessSuggestions.front.score ) { + _guessSuggestions.front.score = sc; + _guessSuggestions.front.key = key; + _guessSuggestions.front.hashEntry = dict[key]; + _guessSuggestions.updateFront(); + } + } + } + } + } + + var thresh:int = 0; + var mw:String; + for ( var sp:int = 1; sp < 4; ++sp) { + mw = word; + for ( var k:int=sp; k<n; k+=4) { + mw = mw.substring(0,k) + "*" + mw.substring(k+1); + } + thresh = thresh + ngram( n, word, mw, InternalConstants.NGRAM_ANY_MISMATCH + InternalConstants.NGRAM_LOWERING); + } + thresh = thresh /3; + thresh --; + + // now expand affixes on each of these root words and + // and use length adjusted ngram scores to select + // possible suggestions + _guessWordList.clear(); + + + //work arround for inconsitent ordered Dictionary table. bof + if ( _guessSuggestions.isEmpty() ) return result.length; + var lowestScore:int = _guessSuggestions.front.score; + var indexArr:Array; + if ( _guessSuggestions.size != _guessSuggestions.maxSize ){ + indexArr=_guessSuggestions.data.slice(0,_guessSuggestions.size).sortOn("key",Array.DESCENDING | Array.RETURNINDEXEDARRAY); + }else{ + indexArr=_guessSuggestions.data.sortOn("key",Array.DESCENDING | Array.RETURNINDEXEDARRAY); + } + //work arround for inconsitent ordered Dictionary table. bof + + // root list; + for each ( i in indexArr ) { + //work arround for inconsitent ordered Dictionary table. bof + if ( i==0 || _guessSuggestions.data[i].score == lowestScore ) continue; + //work arround for inconsitent ordered Dictionary table. bof + + var candList:Array = new Array(); + var candOriginalList:Array = new Array(); + expandRootWord(candList,candOriginalList, InternalConstants.MAX_WORDS, _guessSuggestions.data[i].key, _guessSuggestions.data[i].hashEntry, word ); + for ( j=0; j < candList.length; ++j) { + sc = ngram ( n, word, candList[j], InternalConstants.NGRAM_ANY_MISMATCH + InternalConstants.NGRAM_LOWERING) + leftCommonSubString(word, candList[j],initCap, wordCapValue); + if ( (sc>thresh) ) { + if ( _guessWordList.size < InternalConstants.MAX_GUESS ) { + _guessWordList.insert( new GuessWord(sc,candList[j], null ) ); + if ( _guessWordList.size == InternalConstants.MAX_GUESS ) { + _guessWordList.buildheap(); + } + }else { + if ( sc > _guessWordList.front.score ) { + _guessWordList.front.score = sc; + _guessWordList.front.key = candList[j]; + _guessWordList.front.original = null; + _guessWordList.updateFront(); + } + } + + } + } + } + + // now we are done generating guesses + // sort in order of decreasing score + var guessArr:Array = _guessWordList.toArray().sortOn("score",Array.NUMERIC | Array.DESCENDING); + + + // weight suggestions with a similarity index, based on + // the longest common subsequent algorithm and resort + var refobj:RefObject = new RefObject(0); + var gl:String; + for ( i=guessArr.length-1;i>= 0; --i ) { + gl = guessArr[i].key.toLocaleLowerCase(); + var _lcs:int = StringUtils.lcslen(word, gl); + // same characters with different casing + if ( (n==gl.length) && (n == _lcs) ) { + guessArr[i].score += 2000; + break; + } + // heuristic weigthing of ngram scores + guessArr[i].score += + // length of longest common subsequent minus length difference + 2 * _lcs - Math.abs((int) (n - guessArr[i].key.length)) + + // weight length of the left common substring + leftCommonSubString(word, gl,initCap, wordCapValue) + + // weight equal character positions + ((_lcs == StringUtils.commonCharacterPositions(word, gl, refobj)) ? 1: 0) + + // swap character (not neighboring) + ((refobj.ref) ? 1000 : 0); + } + + guessArr = guessArr.sortOn("score", Array.NUMERIC | Array.DESCENDING); + + + // copy over + var oldnsug:int = nsug; + var same:int = 0; + for ( i=0;i< guessArr.length; ++i ) { + if ( (nsug < this._maxSug) && (result.length < (oldnsug + this._maxngramsugs)) && (!same || (guessArr[i].score > 1000)) ) { + var unique:int = 1; + // leave only excellent suggestions, if exists + if ( guessArr[i].score > 1000 ) same = 1; + // don't suggest previous suggestions or a previous suggestion with prefixes or affixes + for ( j=0;j< result.length; ++j) { + if ( ( guessArr[i].key.indexOf(result[j]) != -1) || !checkWord(guessArr[i].key) ) unique = 0; + } + if ( unique ) { + result.push( guessArr[i].key ); + } + } + + } + + var endTime:Number = getTimer(); + return nsug; + } + + private function testValidSuggestion(element:*, gw:GuessWord):Boolean { + if ( gw.key.indexOf( element ) ) + return false; + if ( !checkWord(element) ) return false; + return true; + } + + private function expandRootWord(guessWordList:Array, guessOriginalList:Array, maxn:int, root:String, he:HashEntry, badWord:String) :void { + // first add root word to list + var nh:int = 0, i:int, j:int; + var sfx:SuffixEntry; + var pfx:PrefixEntry; + var newWord:String; + var crossFlagArray:Array = new Array(); + if ( (guessWordList.length < maxn) && + !( (he.affixFlagVector != null) && + ( (this._attributeMgr.needAffix && he.testAffix(this._attributeMgr.needAffix)) || ( this._attributeMgr.onlyInCompound && he.testAffix(this._attributeMgr.onlyInCompound)))) + ){ + guessWordList[nh] = root; + guessOriginalList[nh] = root; + crossFlagArray[nh] = false; + nh++; + } + + // handle suffixes + for ( i=0; (he.affixFlagVector !=null) && (i<he.affixFlagVector.length);++i) { + sfx= this._attributeMgr.suffixFlagTable[he.affixFlagVector.charAt(i)]; + while( sfx ) { + var index:int = badWord.lastIndexOf(sfx.affixKey); + if ( (index != -1) && ( index== (badWord.length-sfx.affixKey.length)) ) { + newWord = sfx.add(root); + if ( newWord) { + guessWordList[nh] = newWord; + guessOriginalList[nh] = root; + crossFlagArray[nh] = sfx.permissionToCombine; + nh++; + } + } + sfx = sfx.nextElementWithFlag; + } + } + + // handle cross products of prefixes and suffixes + var n:int = nh; + for ( j=1;j<n;++j) { + if( crossFlagArray[j] ) { + for ( i=0;(he.affixFlagVector !=null) && (i<he.affixFlagVector.length);++i) { + pfx = this._attributeMgr.prefixFlagTable[he.affixFlagVector.charAt(i)]; + while( pfx ) { + if ( badWord.indexOf(pfx.affixKey)== 0 ) { + newWord = pfx.add(guessWordList[j]); + if ( newWord) { + guessWordList[nh] = newWord; + guessOriginalList[nh] = root; + crossFlagArray[nh] = pfx.permissionToCombine; + nh++; + } + } + pfx = pfx.nextElementWithFlag; + } + } + } + } + + // now handle pure prefixes + for ( i=0; (he.affixFlagVector !=null) && (i<he.affixFlagVector.length);++i) { + pfx= this._attributeMgr.prefixFlagTable[he.affixFlagVector.charAt(i)]; + while( pfx ) { + if ( badWord.indexOf(pfx.affixKey) == 0 ) { + newWord = pfx.add(root); + if ( newWord) { + guessWordList[nh] = newWord; + guessOriginalList[nh] = root; + crossFlagArray[nh] = pfx.permissionToCombine; + nh++; + } + } + pfx = pfx.nextElementWithFlag; + } + } + + } + + /* + * ToDo: Since this is a generic algorithm, we might want move this code to StringUtils class. + */ + private function ngram(n:int, s1:String, s2:String, opt:int):int { + + var i:int,j:int,k:int,m:int,n:int; + var nscore:int = 0, ns:int, l1:int, l2:int; + + l1 = s1.length; + l2 = s2.length; + if ( opt & InternalConstants.NGRAM_LOWERING ) s2=s2.toLowerCase(); + for ( i = 0; i<l1; i++ ) { + if ( s2.indexOf( s1.charAt(i) ) != -1 ) ns++; + } + nscore = nscore + ns; + if ( ns >= 2 ) { + for ( j = 2; j<=n; j++ ) { + ns = 0; + for ( i = 0; i <=(l1-j); i++ ) { + // var tmp:String = s1.substr(i,i+j); + // tmp = s1.substring(i,i+j); + if ( s2.indexOf( s1.substring(i,i+j) ) != -1 ) ns++; // it could be signaficantly optimized If we can avoid to use substr() function.... + } + nscore = nscore + ns; + if (ns < 2) break; + } + } + ns = 0; + if (opt & InternalConstants.NGRAM_LONGER_WORSE) ns = (l2-l1)-2; + if (opt & InternalConstants.NGRAM_ANY_MISMATCH) ns = Math.abs(l2-l1)-2; + ns = (nscore - ((ns > 0) ? ns : 0)); + return ns; + return 1; + } + + + /* + * Deprecated function for now... + * History: + * A pre-version of implementation for error correction. After I optimized the code for performance, + * I drop this function by that time, but you know performance meassuring is a tricky problem... + * ToDo: Need a revisit when we implementing complex-affix support and compound-word support. + */ + private function ngram1(n:int, s1:String, s2:String, opt:int):int { + var nscore:int = 0, ns:int, l1:int, l2:int; + + var i:int,j:int,k:int,m:int,n:int; + + l1 = s1.length; + l2 = s2.length; + if ( opt & InternalConstants.NGRAM_LOWERING ) s2=s2.toLowerCase(); + for ( j = 1; j<=n; j++ ) { + ns = 0; + for ( i = 0; i <=(l1-j); i++ ) { +// var tmp:String = s1.substr(i,i+j); +// tmp = s1.substring(i,i+j); + if ( s2.indexOf( s1.substring(i,i+j) ) != -1 ) ns++; // it could be signaficantly optimized If we can avoid to use substr() function.... + } + nscore = nscore + ns; + if (ns < 2) break; + } + ns = 0; + if (opt & InternalConstants.NGRAM_LONGER_WORSE) ns = (l2-l1)-2; + if (opt & InternalConstants.NGRAM_ANY_MISMATCH) ns = Math.abs(l2-l1)-2; + ns = (nscore - ((ns > 0) ? ns : 0)); + return ns; + return 1; + } + + /* + * ToDo: since this is a generic algorithm, we might want to move this function to StringUtils class. + */ + private function leftCommonSubString(s1:String,s2:String, initCap:Boolean, s1CapValue:int):int { + var res:int = 1; + if ( s1.charCodeAt(0) != s2.charCodeAt(0) && ( !initCap ) && (s1CapValue != s2.charCodeAt(0)) ) return 0; + for( var i:int=1; (i< s1.length) && (s1.charCodeAt(i) == s2.charCodeAt(i)); ++i ) { + res++; + } + return res; + } + + + public function suggest( result:Array, word:String, capType:int):int { + var nsug:int = 0; + + // suggestions for an uppercase word (html -> HTML) + if ( (nsug < this._maxSug) && (nsug > -1 ) ) { + nsug = capchars(result,word,nsug); + } + + // perhaps we made a typical fault of spelling + if ( (nsug < this._maxSug) && (nsug > -1 ) ) { + nsug = replchars( result, word, nsug ); + } + + // perhaps we made chose the wrong char from a related set + if ( (nsug < this._maxSug) && (nsug > -1 ) ) { + nsug = mapchars( result, word, nsug ); + } + + // did we swap the order of chars by mistake + if ( (nsug < this._maxSug) && (nsug > -1 ) ) { + nsug = swapchar( result, word, nsug ); + } + + // did we swap the order of non adjacent chars by mistake + if ( (nsug < this._maxSug) && (nsug > -1 ) ) { + nsug = longswapchar( result, word, nsug ); + } + + // did we just hit the wrong key in place of a good char (case and keyboard) + if ( (nsug < this._maxSug) && (nsug > -1 ) ) { + nsug = badcharkey( result, word, nsug ); + } + // did we add a char that should not be there + if ( (nsug < this._maxSug) && (nsug > -1 ) ) { + nsug = extrachar( result, word, nsug ); + } + + // did we forgot a char + if ( (nsug < this._maxSug) && (nsug > -1 ) ) { + nsug = forgotchar( result, word, nsug, capType ); + } + + // did we move a char + if ( (nsug < this._maxSug) && (nsug > -1 ) ) { + nsug = movechar( result, word, nsug ); + } + + // did we just hit the wrong key in place of a good char + if ( (nsug < this._maxSug) && (nsug > -1 ) ) { + nsug = badchar( result, word, nsug, capType ); + } + + // did we double two characters + if ( (nsug < this._maxSug) && (nsug > -1 ) ) { + nsug = doubletwochars( result, word, nsug ); + } + + // perhaps we forgot to hit space and two words ran together + if ( (nsug < this._maxSug) && (nsug > -1 ) ) { + nsug = twowords( result, word, nsug ); + } + + return nsug; + } + + + + private function mapchars( result:Array, word:String, nsug:int ) :int { + if (word.length < 2) return nsug; + if ( (nsug == this._maxSug) || (this._attributeMgr.mapFilterTable.length == 0) ) return nsug; + var mapTable:Array = this._attributeMgr.mapFilterTable; + var counter:int = 0; + nsug = map_related(result, word, nsug, 0 ,mapTable, counter); + + return nsug; + } + + private function map_related( result:Array, word:String, nsug:int, startIndex:int, mapTable:Array, counter:int) :int { + var totalCheckCount:int = 8; // for performance issue only... 8 means four level detection... + var candidate:String; + var in_map:int = 0; + var j:int; + counter++; + if ( counter > totalCheckCount ) return nsug; // for performance issue only... + if ( nsug == this._maxSug ) return nsug; + if ( startIndex == word.length ) { + var cwrd:int = 1; + for ( j=0; j < result.length; ++j ) { + if ( result[j]== word ) cwrd=0; + } + if ( cwrd && checkWord(word) ) { + result.push(word); + nsug++; + } + return nsug; + + } + for ( var i:int = 0;i<mapTable.length ;++i ) { + if ( mapTable[i].mapCharSet.indexOf(word.charAt(startIndex)) != -1 ) { + in_map= 1; + for ( j =0; j< mapTable[i].mapCharSet.length; ++j ) { + candidate = word.substring(0,startIndex) +mapTable[i].mapCharSet.charAt(j)+word.substring(startIndex+1); + nsug = map_related(result,candidate,nsug,(startIndex+1),mapTable, counter); + } + } + } + + if( !in_map) { + nsug = map_related(result,word,nsug,(startIndex+1),mapTable, counter); + } + return nsug; + } + + private function twowords( result:Array, word:String, nsug:int ) :int { + var candidate:String; + var cwrd:int=1; + var count:int=0; + if (word.length < 3) return result.length; + if ( result.length >= this._maxSug ) return result.length; + + for( var i:int=1;i<word.length;++i) { + candidate = word.substring(0,i); + if ( !checkWord(candidate) ) continue; + candidate = word.substring(i); + if ( checkWord(candidate) ) { + candidate = word.substring(0,i) +" " + word.substring(i); + for ( var j:int=0; j < result.length; ++j ) { + if ( result[j]== candidate ) cwrd=0; + } + if ( cwrd ) { + if ( result.length >= this._maxSug ) return result.length; + result.push(candidate); + nsug++; + } + } + } + + return nsug; + } + + private function doubletwochars( result:Array, word:String, nsug:int ) :int { + var candidate:String; + var nstate:int=0; + if (word.length < 5) return nsug; + for (var i:int=2;i<word.length;++i) { + if( word.charCodeAt(i) == word.charCodeAt(i-2) ) { + nstate++; + if ( nstate==3) { + candidate = word.substring(0,i-1)+word.substring(i+1); + nsug = testSuggestion( result,candidate, nsug); + if ( nsug == -1 || nsug == this._maxSug ) return nsug; + nstate = 0; + } + }else { + nstate=0; + } + } + return nsug; + } + + private function badchar( result:Array, word:String, nsug:int, capType:int ) :int { + if ( this._cAllTry == null ) return nsug; + if (word.length < 2) return nsug; + var candidate:String; + var i:int, j:int; + switch(capType) { + case InternalConstants.NOCAP: { + // first for init capticalized case... + for ( i = 0; i< this._cAllTry.length;++i) { + candidate = this._cAllTry.charAt(i)+word.substring(1); + nsug = testSuggestion( result,candidate, nsug); + if ( nsug == -1 || nsug == this._maxSug ) return nsug; + } + // for the rest of the word... + for ( i = 0; i< this._cLowerTry.length;++i) { + for ( j=1;j<word.length;++j) { + candidate = word.substring(0,j)+this._cLowerTry.charAt(i)+word.substring(j+1); + nsug = testSuggestion( result,candidate, nsug); + if ( nsug == -1 || nsug == this._maxSug ) return nsug; + } + } + break; + } + case InternalConstants.INITCAP:{ + // first for init capticalized case... + for ( i = 0; i< this._cAllTry.length;++i) { + candidate = this._cAllTry.charAt(i)+word.substring(1); + nsug = testSuggestion( result,candidate, nsug); + if ( nsug == -1 || nsug == this._maxSug ) return nsug; + } + // for the rest of the word... + for ( i = 0; i< this._cLowerTry.length;++i) { + for ( j=1;j<word.length;++j) { + candidate = word.substring(0,j)+this._cLowerTry.charAt(i)+word.substring(j+1); + nsug = testSuggestion( result,candidate, nsug); + if ( nsug == -1 || nsug == this._maxSug ) return nsug; + } + } + break; + } + case InternalConstants.HUHCAP: { + } + case InternalConstants.HUHINITCAP:{ + for ( i = 0; i< this._cAllTry.length;++i) { + for ( j=0;j<word.length;++j) { + candidate = word.substring(0,j)+this._cAllTry.charAt(i)+word.substring(j+1); + nsug = testSuggestion( result,candidate, nsug); + if ( nsug == -1 || nsug == this._maxSug ) return nsug; + } + } + break; + } + case InternalConstants.ALLCAP: { + for ( i = 0; i< this._cUpperTry.length;++i) { + for ( j=0;j<word.length;++j) { + candidate = word.substring(0,j)+this._cUpperTry.charAt(i)+word.substring(j+1); + nsug = testSuggestion( result,candidate, nsug); + if ( nsug == -1 || nsug == this._maxSug ) return nsug; + } + } + break; + } + } + + return nsug; + } + + // did we move a char + private function movechar( result:Array, word:String, nsug:int ) :int { + var candidate:String; + var i:int,j:int; + var char:String; + if (word.length < 3) return nsug; + for ( i=0;i<word.length-2;++i) { + char = word.charAt(i); + for ( j=i+2;j<word.length;++j) { + candidate = word.substring(0,i)+word.substring(i+1,j+1)+char+word.substring(j+1); + nsug = testSuggestion( result,candidate, nsug); + if ( nsug == -1 || nsug == this._maxSug ) return nsug; + } + } + + for ( i=word.length-1;i>=2;--i) { + char = word.charAt(i); + for ( j=i-2;j>=0; --j) { + candidate = word.substring(0,j)+char+word.substring(j,i)+word.substring(i+1); + nsug = testSuggestion( result,candidate, nsug); + if ( nsug == -1 || nsug == this._maxSug ) return nsug; + } + } + + return nsug; + } + + private function forgotchar( result:Array, word:String, nsug:int, capType:int ) :int { + if ( this._cAllTry == null ) return nsug; + var candidate:String; + var i:int, j:int; + if (word.length < 2) return nsug; + switch(capType) { + case InternalConstants.NOCAP: { + for (i =0; i< this._cAllTry.length; ++i ) { + candidate= _cAllTry.charAt(i) + word.substring(0); + nsug = testSuggestion( result,candidate, nsug); + if ( nsug == -1 || nsug == this._maxSug ) return nsug; + } + + for (i =0; i< this._cLowerTry.length; ++i ) { + for ( j=1; j< word.length;j++) { + candidate= word.substring(0,j)+_cLowerTry.charAt(i) + word.substring(j); + nsug = testSuggestion( result,candidate, nsug); + if ( nsug == -1 || nsug == this._maxSug ) return nsug; + } + candidate= word+_cLowerTry.charAt(i); + nsug = testSuggestion( result,candidate, nsug); + if ( nsug == -1 || nsug == this._maxSug ) return nsug; + } + break; + } + case InternalConstants.INITCAP:{ + // first for init capticalized case... + for (i =0; i< this._cAllTry.length; ++i ) { + candidate= _cAllTry.charAt(i) + word.substring(0); + nsug = testSuggestion( result,candidate, nsug); + if ( nsug == -1 || nsug == this._maxSug ) return nsug; + } + + for (i =0; i< this._cLowerTry.length; ++i ) { + for ( j=1; j< word.length;j++) { + candidate= word.substring(0,j)+_cLowerTry.charAt(i) + word.substring(j); + nsug = testSuggestion( result,candidate, nsug); + if ( nsug == -1 || nsug == this._maxSug ) return nsug; + } + candidate= word+_cLowerTry.charAt(i); + nsug = testSuggestion( result,candidate, nsug); + if ( nsug == -1 || nsug == this._maxSug ) return nsug; + } + break; + } + case InternalConstants.HUHCAP: { + } + case InternalConstants.HUHINITCAP:{ + for (i =0; i< this._cAllTry.length; ++i ) { + for ( j=1; j< word.length;j++) { + candidate= word.substring(0,j)+_cAllTry.charAt(i) + word.substring(j); + nsug = testSuggestion( result,candidate, nsug); + if ( nsug == -1 || nsug == this._maxSug ) return nsug; + } + candidate= word+_cAllTry.charAt(i); + nsug = testSuggestion( result,candidate, nsug); + if ( nsug == -1 || nsug == this._maxSug ) return nsug; + } + break; + } + case InternalConstants.ALLCAP: { + for (i =0; i< this._cUpperTry.length; ++i ) { + for ( j=0; j< word.length;j++) { + candidate= word.substring(0,j)+_cUpperTry.charAt(i) + word.substring(j); + nsug = testSuggestion( result,candidate, nsug); + if ( nsug == -1 || nsug == this._maxSug ) return nsug; + } + candidate= word+_cUpperTry.charAt(i); + nsug = testSuggestion( result,candidate, nsug); + if ( nsug == -1 || nsug == this._maxSug ) return nsug; + } + break; + } + } + return nsug; + } + + // error is word has an extra letter it does not need + private function extrachar( result:Array, word:String, nsug:int ) :int { + var candidate:String; + if (word.length < 2) return nsug; + for ( var i:int=0; i< word.length ; ++i ) { + candidate = word.substring(0,i) + word.substring(i+1); + nsug = testSuggestion( result,candidate, nsug); + if ( nsug == -1 || nsug == this._maxSug ) return nsug; + } + return nsug; + } + + // error is wrong char in place of correct one (case and keyboard related version) + private function badcharkey( result:Array, word:String, nsug:int ) :int { + var candidate:String; + if (word.length < 2) return nsug; + var startIndex:int = 0; + // swap out each char one by one and try uppercase and neighbor + // keyboard chars in its place to see if that makes a good word + for ( var i:int =0; i<word.length; ++i) { + // check with uppercase letters + if ( word.charAt(i).toLocaleUpperCase() != word.charAt(i) ) { + candidate = word.substring(0,i)+word.charAt(i).toLocaleUpperCase()+word.substring(i+1); + nsug = testSuggestion( result,candidate, nsug); + if ( nsug == -1 || nsug == this._maxSug ) return nsug; + } + // check neighbor characters in keyboard string + if ( this._ckey == null ) continue; + startIndex = this._ckey.indexOf(word.charAt(i),startIndex); + while ( startIndex != -1 ) { + if ( (startIndex!=0) && (_ckey.charAt(startIndex-1) != "|" ) ) { + candidate = word.substring(0,i)+_ckey.charAt(startIndex-1)+word.substring(i+1); + nsug = testSuggestion( result,candidate, nsug); + if ( nsug == -1 || nsug == this._maxSug ) return nsug; + } + if ( (_ckey.charAt(startIndex+1)!="|") && (startIndex != _ckey.length - 1) ) { + candidate = word.substring(0,i)+_ckey.charAt(startIndex+1) + word.substring(i+1); + nsug = testSuggestion( result,candidate, nsug); + if ( nsug == -1 || nsug == this._maxSug ) return nsug; + } + startIndex = this._ckey.indexOf(word.charAt(i),startIndex+1); + } + } + + return nsug; + } + + private function longswapchar( result:Array, word:String, nsug:int ) :int { + var candidate:String; + if (word.length < 2) return nsug; + for ( var i:int =0 ; i< word.length-2; ++i ) { + for ( var j:int = i+2;j< word.length;++j) { + candidate = word.substring(0,i)+ word.charAt(j) + word.substring(i+1,j) + word.charAt(i) + word.substring(j+1); + nsug = testSuggestion( result,candidate, nsug); + if ( nsug == -1 || nsug == this._maxSug ) return nsug; + } + } + return nsug; + } + + private function swapchar( result:Array, word:String, nsug:int ) :int { + var candidate:String; + if (word.length < 2) return nsug; + var i:int; + var wl:int = word.length; + // try swapping adjacent chars one by one + for (i=0;i< wl-1;++i) { + candidate = word.substring(0,i)+word.charAt(i+1)+word.charAt(i) + word.substring(i+2); + nsug = testSuggestion( result,candidate, nsug); + if ( nsug == -1 || nsug == this._maxSug ) return nsug; + } + + if ( wl == 4 || wl == 5 ) { + candidate = word.charAt(1) + word.charAt(0); + if ( wl == 5) candidate +=word.charAt(2); + candidate += word.charAt(wl - 1) + word.charAt(wl - 2); + nsug = testSuggestion( result,candidate, nsug); + if ( nsug == -1 || nsug == this._maxSug ) return nsug; + if ( wl == 5 ) { + candidate = word.charAt(0) + word.charAt(2) + word.charAt(1) + candidate.substr(3); + nsug = testSuggestion( result,candidate, nsug); + if ( nsug == -1 || nsug == this._maxSug ) return nsug; + } + } + return nsug; + + } + private function replchars( result:Array, word:String, nsug:int ) :int { + var candidate:String; + if (word.length < 2) return nsug; + var searchIndex:int=0; + if ( (this._attributeMgr.simpleFilterTable==null) || (this._attributeMgr.simpleFilterTable.length == 0) ) return nsug; + for ( var i:int = 0; i < this._attributeMgr.simpleFilterTable.length; ++i ) { + while ( (searchIndex = word.indexOf( this._attributeMgr.simpleFilterTable[i].matchString,searchIndex)) != -1 ){ + searchIndex = searchIndex + this._attributeMgr.simpleFilterTable[i].matchString.length; + candidate = word.substr(0, searchIndex-this._attributeMgr.simpleFilterTable[i].matchString.length) + + this._attributeMgr.simpleFilterTable[i].replacement + + word.substr(searchIndex); + nsug = testSuggestion( result,candidate, nsug); + if ( nsug == -1 || nsug == this._maxSug ) return nsug; + } + + } + return nsug; + } + + private function capchars( result:Array, word:String, nsug:int) : int { + var candidate:String = word.toLocaleUpperCase(); + return testSuggestion(result,candidate,nsug); + } + + private function testSuggestion(result:Array, word:String, nsug:int):int { + var cwrd:int=1; + if ( result.length >= this._maxSug ) return nsug; + for ( var i:int=0; i < result.length; ++i ) { + if ( result[i]== word ) cwrd=0; + } + + if ( (cwrd) && checkWord(word) ) { + result.push(word); + nsug++; + } + return nsug; + } + + // see if a candidate suggestion is spelled correctly + // needs to check both root words and words with affixes + + // ToDo the following in next release... + // obsolote MySpell-HU modifications: + // return value 2 and 3 marks compounding with hyphen (-) + // `3' marks roots without suffix + + private function checkWord(word:String):int { + var rv:HashEntry = null; + var nosuffix:int =0; + if ( this._attributeMgr ) { + rv = _attributeMgr.lookup(word); + if ( rv ) { + if ( (rv.affixFlagVector) && ( rv.testAffix(this._attributeMgr.forbiddenWord) || rv.testAffix(this._attributeMgr.noSuggest) ) ){ + return 0; + } + while ( rv ) { + if ( (rv.affixFlagVector) && ( rv.testAffix(this._attributeMgr.needAffix) || rv.testAffix(InternalConstants.ONLYUPCASEFLAG) || rv.testAffix(this._attributeMgr.onlyInCompound) ) ) { + rv = rv.next + }else break; + } + }else rv = _attributeMgr.optPrefixCheck2(word, 0,0) // only prefix, and prefix + suffix XXX + + if ( rv ) { + nosuffix = 1; + }else { + rv = _attributeMgr.optSuffixCheck2(word,0,null,0,0); + } + //this is added after we have two level suffix stripping + if (!rv && this._attributeMgr.haveContClass) { + rv = this._attributeMgr.optTwoSuffixCheck(word, 0, null, 0); + if (!rv) rv = this._attributeMgr.optTwoPrefixCheck(word,1, 0); + } + + // check forbidden words + if ( (rv) && (rv.affixFlagVector) && ( rv.testAffix(this._attributeMgr.forbiddenWord) || rv.testAffix(InternalConstants.ONLYUPCASEFLAG) + || rv.testAffix(this._attributeMgr.noSuggest) || rv.testAffix(this._attributeMgr.onlyInCompound) ) ) { + return 0; + } + if ( rv ) { + //// XXX obsolote ToDo + return 1; + } + + } + return 0; + } + + } +} + + +internal class GuessWord { + private var _score:int; + private var _key:String; + private var _original:String; + + public function GuessWord(score:int, key:String, original:String){ + this.key = key; + this.score = score; + this.original = original; + } + + public function get score():int { + return this._score; + } + public function set score(value:int) :void { + this._score = value; + } + + public function get key():String { + return this._key; + } + public function set key(value:String) :void { + this._key = value; + } + public function get original():String { + return this._original; + } + public function set original(value:String) :void { + this._original = value; + } +} + +internal class SuggestionEntry { + import com.adobe.linguistics.spelling.core.HashEntry; + private var _score:int; + private var _key:String; + private var _hashEntry:HashEntry; + + public function SuggestionEntry(score:int, key:String, hashEntry:HashEntry) { + this.key = key; + this.score = score; + this.hashEntry = hashEntry; + + } + + public function get score():int { + return this._score; + } + public function set score(value:int) :void { + this._score = value; + } + + public function get key():String { + return this._key; + } + public function set key(value:String) :void { + this._key = value; + } + + public function get hashEntry():HashEntry { + return this._hashEntry; + } + + public function set hashEntry(value:HashEntry ) :void { + this._hashEntry = value; + } + +}
http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/UserDictionaryEngine.as ---------------------------------------------------------------------- diff --git a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/UserDictionaryEngine.as b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/UserDictionaryEngine.as new file mode 100644 index 0000000..93ba707 --- /dev/null +++ b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/UserDictionaryEngine.as @@ -0,0 +1,71 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + + +package com.adobe.linguistics.spelling.core +{ + import com.adobe.linguistics.spelling.UserDictionaryInternal; + + public class UserDictionaryEngine + { + // Private properties + private var _dictionaryList:Array; // get only + private var _userDict:UserDictionaryInternal; + + public function UserDictionaryEngine(ud:UserDictionaryInternal=null) + { + _dictionaryList = new Array(); + } + public function addDictionary(userDictionary:UserDictionaryInternal):Boolean + { + if ( (userDictionary == null) ) return false; + + for ( var i:int = 0;i < _dictionaryList.length; ++i ) { + if ( userDictionary == _dictionaryList[i] ) + return false; + } + _dictionaryList.push(userDictionary); + return true; + } + + public function removeDictionary(userDictionary:UserDictionaryInternal):Boolean + { + + for ( var i:int =0; i < _dictionaryList.length; ++i ) { + if ( userDictionary == _dictionaryList[i] ) { + _dictionaryList.splice(i,1); + return true; + } + } + return false; + } + + public function spell( word:String ) :Boolean { + var result:Boolean = false; + for ( var i:int =0; (i < _dictionaryList.length) && (!result);++i ) { + _userDict = _dictionaryList[i]; + if ( _userDict ) { + result = (_userDict._wordList.lookup(word) != -1); + } + } + return result; + } + + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/container/Collection.as ---------------------------------------------------------------------- diff --git a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/container/Collection.as b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/container/Collection.as new file mode 100644 index 0000000..5954c21 --- /dev/null +++ b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/container/Collection.as @@ -0,0 +1,89 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + + + + +package com.adobe.linguistics.spelling.core.container +{ + /** + * public interface Collection The root interface in the collection + * hierarchy. A collection represents a group of objects, known as + * its elements. Some collections allow duplicate elements and others + * do not. Some are ordered and others unordered. The SDK does not + * provide any direct implementations of this interface: it provides + * implementations of more specific subinterfaces like Set and List. + */ + + /** + * ToDo: add hashCode() function + * add remove()/add() function + */ + + public interface Collection + { + + /** + * The number of elements in this collection. + * @Returns the number of elements in this collection. + */ + function get size():int; + + /** + * Tests if the collection is empty. + * + * @ Returns true if this collection contains no elements. + */ + function isEmpty():Boolean + + /** + * Determines if the collection contains the specified element. + * + * @ obj: element whose presence in this collection is to be tested. + * + * @ Returns true if this collection contains the specified element. + */ + function contains( obj:* ) : Boolean + + /** + * Removes all of the elements from this collection (optional operation). + */ + function clear():void + + /** + * Returns an iterator over the elements in this collection. There are + * no guarantees concerning the order in which the elements are returned + * (unless this collection is an instance of some class that provides a guarantee). + * + * @an Iterator over the elements in this collection + */ + function getIterator():Iterator + + /** + * Returns an array containing all of the elements in this collection. + * If the collection makes any guarantees as to what order its elements + * are returned by its iterator, this method must return the elements + * in the same order. + * + * @return An array. + */ + function toArray():Array + + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/container/Enumeration.as ---------------------------------------------------------------------- diff --git a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/container/Enumeration.as b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/container/Enumeration.as new file mode 100644 index 0000000..16611ad --- /dev/null +++ b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/container/Enumeration.as @@ -0,0 +1,28 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + + +package com.adobe.linguistics.spelling.core.container +{ + public interface Enumeration + { + function hasMoreElements():Boolean; + function nextElement():*; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/container/HashTable.as ---------------------------------------------------------------------- diff --git a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/container/HashTable.as b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/container/HashTable.as new file mode 100644 index 0000000..cf38c81 --- /dev/null +++ b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/container/HashTable.as @@ -0,0 +1,179 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + + +package com.adobe.linguistics.spelling.core.container +{ + import flash.utils.Dictionary; + + /** + * A hash table + */ + public class HashTable implements Collection + { + protected var _map:Dictionary; + protected var _elementNum:int; + + /** + * Initializes a new hash table. + * + * @param size The size of the hash table. + * @param hash A hashing function. + */ + public function HashTable(useWeakReferences:Boolean = true) + { + _map = new Dictionary( useWeakReferences ); + _elementNum = 0; + } + + public function put(key:*, value:*) : void + { + _map[key] = value; + ++_elementNum; + } + + public function remove(key:*) : void + { + delete _map[key]; + --_elementNum; + } + + public function containsKey(key:*) : Boolean + { + return _map.hasOwnProperty( key ); + } + + public function containsValue(value:*) : Boolean + { + for ( var key:* in _map ) + { + if ( _map[key] == value ) + { + return true; + } + } + return false; + } + + public function contains(value:*):Boolean { + return containsValue(value); + } + + public function getElement(key:* ):* { + return _map[key]; + } + + /** + * @inheritDoc + */ + public function clear() : void + { + for ( var key:* in _map ) + { + remove( key ); + } + } + + /** + * @inheritDoc + */ + public function getIterator():Iterator + { + return null; + } + + /** + * @inheritDoc + */ + public function get size():int + { + return _elementNum; + } + + /** + * @inheritDoc + */ + public function isEmpty():Boolean + { + return _elementNum == 0; + } + + public function get keys() : Array + { + var _keys:Array = []; + + for (var key:* in _map) + { + _keys.push( key ); + } + return _keys; + } + + public function get elements() : Array + { + var _values:Array = []; + + for each ( var value:* in _map ) { + _values.push( value ); + } + return _values; + } + + /** + * @inheritDoc + */ + public function toArray():Array + { + return keys; + } + + /** + * Prints out a string representing the current object. + * + * @return A string representing the current object. + */ + public function toString():String + { + return "[HashTable, size=" + size + "]"; + } + + public function get hashMap():Dictionary { + return this._map; + } + + /** + * Need refine... Possible solution is that we can use two function paramter to control the input and output. + * + * + */ + public function watchEntries(func:Function=null):Array { + if ( func == null ) + return null; + var res:Array = new Array(); + for (var curKey:* in _map) + { + if ( func( curKey, _map[curKey] ) ) { + res.push( curKey ); + } + } + return (res.length == 0)? null: res; + } + + } +} http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/container/Heap.as ---------------------------------------------------------------------- diff --git a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/container/Heap.as b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/container/Heap.as new file mode 100644 index 0000000..555d6a3 --- /dev/null +++ b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/container/Heap.as @@ -0,0 +1,263 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + + + +package com.adobe.linguistics.spelling.core.container +{ + /** + * BinaryHeap implementation of priority queue. The heap is either a + * minimum or maximum heap as determined by parameters passed to constructor. + * + */ + public final class Heap implements Collection + { + private var __size:int; + private var __count:int; + private var __compare:Function; + public var __heap:Array; + + /** + * Create a new heap. + * + * @param size The heap's maximum capacity. + * @param compare A comparison function for sorting the heap's data. + * If no function is passed, the heap uses default function. + */ + public function Heap(size:int=1000, compare:Function = null) + { + __count = 0; + __heap = new Array(__size = size + 1); + + if (compare == null) + __compare = function(a:int, b:int):int { return a - b; }; + else + __compare = compare; + } + + /** + * The maximum capacity. + */ + public function get maxSize():int + { + return __size; + } + + public function isEmpty():Boolean + { + return false; + } + + public function toArray():Array + { + return __heap.slice(1, __count + 1); + } + + public function toString():String + { + return "[Heap, size=" + __size +"]"; + } + + public function dump():String + { + var k:int = __count + 1; + var s:String = "Heap\n{\n"; + for (var i:int = 1; i < k; i++) + s += "\t" + __heap[i] + "\n"; + s += "\n}"; + return s; + } + + /** + * The front item. + */ + public function get front():* + { + return __heap[1]; + } + + /** + * Enqueues. + * @param obj The data to enqueue. + * @return False if the queue is full, otherwise true. + */ + public function enqueue(obj:*):Boolean + { + if (__count + 1 < __size){ + __heap[++__count] = obj; + + var i:int = __count; + var tmp:* = __heap[i]; + var v:*; + var parent:int = i >> 1; + + if (__compare != null) + { + while (parent > 0){ + v = __heap[parent]; + if (__compare(tmp, v) < 0){ + __heap[i] = v; + i = parent; + parent >>= 1; + } + else break; + } + }else{ + while (parent > 0){ + v = __heap[parent]; + if (tmp - v < 0){ + __heap[i] = v; + i = parent; + parent >>= 1; + } + else break; + } + } + __heap[i] = tmp; + return true; + } + return false; + } + + /** + * Dequeues. + * @return The heap's front item or null if it is empty. + */ + public function dequeue():* + { + if (__count >= 1){ + var o:* = __heap[1]; + + __heap[1] = __heap[__count]; + delete __heap[__count]; + + var tmp:* = __heap[i]; + var i:int = 1; + var v:*; + var child:int = i << 1; + + if (__compare != null) { + while (child < __count) { + if (child < __count - 1) { + if (__compare(__heap[child], __heap[int(child + 1)]) > 0) + child++; + } + v = __heap[child]; + if (__compare(tmp, v) > 0){ + __heap[i] = v; + i = child; + child <<= 1; + } + else break; + } + }else{ + while (child < __count){ + if (child < __count - 1){ + if (__heap[child] - __heap[int(child + 1)] > 0) + child++; + } + v = __heap[child]; + if (tmp - v > 0){ + __heap[i] = v; + i = child; + child <<= 1; + } + else break; + } + } + __count--; + __heap[i] = tmp; + return o; + } + return null; + } + + /** + * Tests if a given item exists. + */ + public function contains(obj:*):Boolean + { + for (var i:int = 1; i <= __count; i++){ + if (__heap[i] === obj) + return true; + } + return false; + } + + public function clear():void + { + __heap = new Array(__size); + __count = 0; + } + + public function getIterator():Iterator + { + return new HeapIterator(this); + } + + public function get size():int + { + return __count; + } + + } +} + +import com.adobe.linguistics.spelling.core.container.Heap; +import com.adobe.linguistics.spelling.core.container.Iterator; + +internal class HeapIterator implements Iterator +{ + private var __values:Array; + private var __length:int; + private var __cursor:int; + + public function HeapIterator(heap:Heap) + { + __values = heap.toArray(); + __cursor = 0; + __length = __values.length; + } + + public function get data():* + { + return __values[__cursor]; + } + + public function set data(obj:*):void + { + __values[__cursor] = obj; + } + + public function start():void + { + __cursor = 0; + } + + public function hasNext():Boolean + { + return __cursor < __length; + } + + public function next():* + { + return __values[__cursor++]; + } +} + http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/container/Iterator.as ---------------------------------------------------------------------- diff --git a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/container/Iterator.as b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/container/Iterator.as new file mode 100644 index 0000000..4abe889 --- /dev/null +++ b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/container/Iterator.as @@ -0,0 +1,64 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + + + + +package com.adobe.linguistics.spelling.core.container +{ + /** + * public interface Iterator + * An iterator over a collection. Iterator takes the place of Enumeration + * in the AS collections framework. Iterators differ from enumerations in + * two ways: + * Iterators allow the caller to remove elements from the underlying + * collection during the iteration with well-defined semantics. + * Method names have been improved. + */ + public interface Iterator + { + + /** + * Grants access to the current item being referenced by the iterator. + * This provides a quick way to read or write the current data. + * Dirty interface, will remove in next version. + */ + function get data():* + function set data(obj:*):void + + /** + * Seek the iterator to the first item in the collection. + */ + function start():void + + /** + * Returns the next element in the iteration. + * + */ + function next():* + + /** + * Returns true if the iteration has more elements. + * + * @Returns true if the iteration has more elements. + */ + function hasNext():Boolean + + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/container/Set.as ---------------------------------------------------------------------- diff --git a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/container/Set.as b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/container/Set.as new file mode 100644 index 0000000..32525e7 --- /dev/null +++ b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/container/Set.as @@ -0,0 +1,195 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + + + + +package com.adobe.linguistics.spelling.core.container +{ + import flash.utils.Dictionary; + + /** + * A collection that contains no duplicate elements. More formally, sets + * contain no pair of elements e1 and e2 such that e1.equals(e2), and at + * most one null element. As implied by its name, this interface models + * the mathematical set abstraction. + */ + public final class Set implements Collection + { + private var __size:int; + private var __set:Dictionary = new Dictionary(true); + + /** + * Creates a empty set. + */ + public function Set() + { + __set = new Dictionary(); + } + + + public function contains(obj:*):Boolean + { + return __set[obj] != undefined; + } + + public function clear():void + { + __set = new Dictionary(); + __size = 0; + } + + public function get data():Dictionary { + return this.__set; + } + + public function getIterator():Iterator + { + return new SetIterator(this); + } + + public function get size():int + { + return __size; + } + + public function isEmpty():Boolean + { + return __size == 0; + } + + /** + * Reads an item from the set. + * + * @param obj The item to retrieve. + * @return The item matching the obj parameter or null. + */ + public function lookup(obj:*):* + { + var val:* = __set[obj]; + return val != undefined ? val : null; + } + + /** + * Adds the specified element to this set if it is not already present (optional operation). + * + * @param obj The item to be added. + */ + public function insert(obj:*):void + { + if (obj == null) return; + if (obj == undefined) return; + if (__set[obj]) return; + + __set[obj] = obj; + __size++; + } + + /** + * Removes the specified element from this set if it is present (optional operation). + * + * @param obj The item to be removed + * @return The removed item or null. + */ + public function remove(obj:*):Boolean + { + if (__set[obj] != undefined) + { + delete __set[obj]; + __size--; + return true; + } + return false; + } + + public function toArray():Array + { + var a:Array = new Array(__size); + var j:int; + for (var i:* in __set) a[j++] = i; + return a; + } + + /** + * Return a string representing the current object. + */ + public function toString():String + { + return "[Set, size=" + size + "]"; + } + + /** + * Prints out all elements (debug use only). + */ + public function dump():String + { + var s:String = "Set:\n"; + for each (var i:* in __set) + s += "[val: " + i + "]\n"; + return s; + } + } + +} + + +import com.adobe.linguistics.spelling.core.container.Iterator +import com.adobe.linguistics.spelling.core.container.Set; + +internal class SetIterator implements Iterator +{ + private var __cursor:int; + private var __size:int; + private var __s:Set; + private var __a:Array; + + public function start():void + { + __cursor = 0; + } + + public function get data():* + { + return __a[__cursor]; + } + + public function set data(obj:*):void + { + __s.remove(__a[__cursor]); + __s.insert(obj); + } + + public function SetIterator(s:Set) + { + __cursor = 0; + __size = s.size; + __s = s; + __a = s.toArray(); + } + + public function next():* + { + return __a[__cursor++]; + } + + public function hasNext():Boolean + { + return __cursor < __size; + } +} http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/container/SparseHashTable.as ---------------------------------------------------------------------- diff --git a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/container/SparseHashTable.as b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/container/SparseHashTable.as new file mode 100644 index 0000000..3a0e8d1 --- /dev/null +++ b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/container/SparseHashTable.as @@ -0,0 +1,283 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + + +package com.adobe.linguistics.spelling.core.container +{ + import com.adobe.linguistics.spelling.core.utils.*; + public final class SparseHashTable implements Collection + { + + private var _keyTable:Array; + private var _elementTable:Array; + private var _hashSize:int; + private var _tableCapacity:int; + private var _loadFactor:Number; + private var _elementNum:int; + private var _deletedObject:Object = new Object(); + + /** + * A simple function for hashing strings. + */ + private function hashString(s:String):int + { + var hash:int = 0, i:int, k:int = s.length, ROTATE_LEN:int = 5; + for ( i =0; i < 4 && !isNaN(s.charCodeAt(i)); ++i ) { + hash = ( hash << 8 ) | ( s.charCodeAt(i) ) + } + while ( !isNaN(s.charCodeAt(i)) ) { + (hash) = ((hash) << (ROTATE_LEN)) | (((hash) >> (32 - ROTATE_LEN)) & ((1 << (ROTATE_LEN))-1)); + hash ^= ( s.charCodeAt(i) ); + ++i; + } + return (hash > 0) ? hash : -hash; // or use uint conversion to convert minus number to plus number.... still debate// + } +// private function hashString(s:String):int +// { +// var hash:int = 0, i:int, k:int = s.length; +// for (i = 0; i < k; i++) hash += (i + 1) * s.charCodeAt(i); +// return hash; +// } + + /** + * A simple function for hashing integers. + */ + private function hashNumber(n:Number):int + { + var i:int = int(n); + return int(i>0? i:-i); + } + + private function hash(key:*):int { + if (key is Number ) { + return hashNumber(key); + }else if (key is String ) { + return hashString(key); + } + + if (key.hasOwnProperty("hashCode")) + return key.hashCode()>0 ? key.hashCode() : -key.hashCode(); + else + return int(key)>0 ? int(key) : -int(key); + } + + public function SparseHashTable(initialCapacity:int = 128, loadFactor:Number = 0.75) + { + initHash(initialCapacity, loadFactor); + } + + private function initHash(initialCapacity:int = 128, loadFactor:Number = 0.75):void { + if ( !(initialCapacity > 0) || !( loadFactor > 0 && loadFactor < 1) ) + return; //input is invalid, should through exception or ... + _loadFactor = loadFactor; + _hashSize = initialCapacity; + _tableCapacity = MathUtils.nextPrime( int(_hashSize/loadFactor) ); + _keyTable = new Array(_tableCapacity); + _elementTable = new Array(_tableCapacity); + _elementNum = 0; + clear(); + } + + private function getKeyPosition(key:*):int { + var hashValue:int = hash(key); + var pos:int; + if ( hashValue < 0 ) { + trace ( "hashValue shouldn't be negative integer" ); + return -1; + } + //Quadratic Probing + for ( var i:int =0; i < _tableCapacity; ++i ) { + pos = (hashValue+i*i)%_tableCapacity ; //hi=(h(key)+i*i)%m 0â¤iâ¤m-1 + if ( _keyTable[pos] == null ) + break; + if ( _keyTable[pos] == key ) { + return pos; + } + } + return -1; + } + + private function calculateKeyPostion(key:*):int { + var hashValue:int = hash(key); + var pos:int; + if ( hashValue < 0 ) { + trace ( "Position shouldn't be negative" ); + return -1; + } + //Quadratic Probing + for ( var i:int =0; i < _tableCapacity; ++i ) { + pos = (hashValue+i*i)%_tableCapacity ; //hi=(h(key)+i*i)%m 0â¤iâ¤m-1 + if ( (_keyTable[pos] == null ) || + ( _keyTable[pos] == _deletedObject ) ) { + // insert successfully + return pos; + } + } + return -1; // hash table is full now. it should never happen. + + } + + + protected function rehash():void { + if ( _hashSize == _elementNum ) { + var oldKeyTable:Array = _keyTable; + var oldElementTable:Array = _elementTable; + initHash(_hashSize*2, _loadFactor); + for ( var i:int =0 ; i < oldKeyTable.length; ++i ) { + if (oldKeyTable[i]==null + || oldKeyTable[i] == _deletedObject) { + continue; + } + put(oldKeyTable[i],oldElementTable[i] ); + } + oldKeyTable=null; + oldElementTable=null; + } + } + + public function put( key:*, value:* ) :Boolean { + if ( _hashSize == _elementNum ) { + rehash(); + } + + if ( containsKey(key) ) { + trace ( "Contains the same Key in the table" ); + return false; + } + + var pos:int = calculateKeyPostion(key); + if ( pos < 0 ) { + trace ( "SparseHash internal error." ); + return false; + } + + ++_elementNum; + _keyTable[pos] = key; + _elementTable[pos] = value; + return true; + } + + public function remove(key:*):* { + var pos:int = getKeyPosition(key); + var res:* = (pos < 0) ? null:_elementTable[pos]; + if ( pos >= 0 ) { + --_elementNum; + _keyTable[pos] =_deletedObject; + _elementTable[pos] = _deletedObject; + } + return res; + } + + public function contains(value:*):Boolean { + return containsValue(value); + } + + /** + * Determines if the collection contains the specified element. + * + * @ obj: element whose presence in this collection is to be tested. + * + * @ Returns true if this collection contains the specified element. + */ + public function containsKey(key:*):Boolean { + var pos:int = getKeyPosition(key); + return (pos >= 0); + } + + public function containsValue(value:*):Boolean { + for ( var i:int =0; i < _tableCapacity; ++i ) { + if ( (_keyTable[i] == null ) || + ( _keyTable[i] == _deletedObject ) ) { + continue; + } + if ( _elementTable[i].value == value ) + return true; + } + return false; + } + + public function getElement(key:* ):* { + var pos:int = getKeyPosition(key); + return (pos < 0) ? null:_elementTable[pos]; + + } + + /** + * The number of elements in this collection. + * @Returns the number of elements in this collection. + */ + public function get size():int { + return _elementNum; + } + + public function get elements():Enumeration { + return null; + } + + public function get keys():Enumeration { + return null; + } + + /** + * Tests if the collection is empty. + * + * @ Returns true if this collection contains no elements. + */ + public function isEmpty():Boolean { + return (_elementNum==0); + } + + + /** + * Removes all of the elements from this collection (optional operation). + */ + public function clear():void { + var i:int; + for( i=0;i< _tableCapacity;++i) { + _keyTable[i] = null; + _elementTable[i] = null; + } + } + + /** + * Returns an iterator over the elements in this collection. There are + * no guarantees concerning the order in which the elements are returned + * (unless this collection is an instance of some class that provides a guarantee). + * + * @an Iterator over the elements in this collection + */ + public function getIterator():Iterator { + return null; + } + + /** + * Returns an array containing all of the elements in this collection. + * If the collection makes any guarantees as to what order its elements + * are returned by its iterator, this method must return the elements + * in the same order. + * + * @return An array. + */ + public function toArray():Array { + return _keyTable; + } + + } +} + http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/env/ExternalConstants.as ---------------------------------------------------------------------- diff --git a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/env/ExternalConstants.as b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/env/ExternalConstants.as new file mode 100644 index 0000000..e38052e --- /dev/null +++ b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/env/ExternalConstants.as @@ -0,0 +1,47 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + + +package com.adobe.linguistics.spelling.core.env +{ + /* + * External-Internal public Constant properties... + * In the future, we might want to merge this class with InternalConstant class... + */ + + public class ExternalConstants + { + + // casing + static public const NOCAP:int = 0; + static public const INITCAP:int = 1; + + + static public const SPELL_COMPOUND:int= (1 << 0); + static public const SPELL_FORBIDDEN:int= (1 << 1); + static public const SPELL_ALLCAP:int= (1 << 2); + static public const SPELL_NOCAP:int= (1 << 3); + static public const SPELL_INITCAP:int= (1 << 4); + + public function ExternalConstants() + { + } + + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/env/InternalConstants.as ---------------------------------------------------------------------- diff --git a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/env/InternalConstants.as b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/env/InternalConstants.as new file mode 100644 index 0000000..e14fc31 --- /dev/null +++ b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/env/InternalConstants.as @@ -0,0 +1,87 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + + +package com.adobe.linguistics.spelling.core.env +{ + /* + * Internal-Internal public Constant properties... + * In the future, we might want to merge this class with ExternalConstant class... + * This one is sharing by HunSpell related algorithm... + */ + public class InternalConstants + { + // casing + static public const NOCAP:int = 1; + static public const INITCAP:int = 2; + static public const ALLCAP:int = 4; + static public const HUHCAP:int = 8; + static public const HUHINITCAP:int = 16; + + + static public const FLAG_LONG:int = 1; + static public const FLAG_NUM:int = 2; + static public const FLAG_UNI:int = 3; + static public const FLAG_CHAR:int = 0; + + // default flags + static public const DEFAULTFLAGS:int = 65510; + static public const FORBIDDENWORD:int = 65511; + static public const ONLYUPCASEFLAG:int = 65511; + + static public const MAXWORDLEN:int = 100; + + static public const FLAG_NULL:int = 0x00; + + // affentry options + static public const aeXPRODUCT:int = (1 << 0); + + static public const SPELL_KEYSTRING:String = "qwertyuiop|asdfghjkl|zxcvbnm"; + + // internal const for ngram algorithm. + public static const NGRAM_LOWERING:int = (1 << 2); + public static const NGRAM_LONGER_WORSE:int = (1 << 0); + public static const NGRAM_ANY_MISMATCH:int = (1 << 1); + + static public const MAX_ROOTS:int = 100; + static public const MAX_WORDS:int = 100; + static public const MAX_GUESS:int = 200; + static public const MAXNGRAMSUGS:int= 4; + static public const MAXPHONSUGS:int= 2; + + static public const DEFAULTENCODING:String = "utf-8"; + + + static public const MAXSUGGESTION:int = 10; + // internal const for ICONV or OCONV RULE. + static public const CONV_ICONV:Boolean= true; + static public const CONV_OCONV:Boolean= false; + + //Maximum word breaks allowed + static public const MAX_WORD_BREAKS:int= 10; + + //Constants for Loading of Dictionaries in Parts + static public const DICT_LOAD_DELAY:int= 10; //this is timeout delay between loading of two parts of dictionaries. In milliseconds + static public const WORDS_PER_SPLIT:int= 20000;// this is the default value of number of words to be loaded in each split. + public function InternalConstants() + { + } + + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/error/ContentError.as ---------------------------------------------------------------------- diff --git a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/error/ContentError.as b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/error/ContentError.as new file mode 100644 index 0000000..239b031 --- /dev/null +++ b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/error/ContentError.as @@ -0,0 +1,39 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + + +package com.adobe.linguistics.spelling.core.error +{ + /* + *@private + * Deprecated class for now... + * History: + * In the beginning, I would like to have our own error class for critical exception. + * After sharing this with Xie, I was convinced to drop this idea by discussing with Xie. + * ToDo: Need a revisit after we have compound word support. + */ + public class ContentError extends Error + { + public function ContentError(message:String, errorID:int) + { + super(message, errorID); + } + + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/error/ErrorTable.as ---------------------------------------------------------------------- diff --git a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/error/ErrorTable.as b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/error/ErrorTable.as new file mode 100644 index 0000000..d2dba8a --- /dev/null +++ b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/error/ErrorTable.as @@ -0,0 +1,41 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + + +package com.adobe.linguistics.spelling.core.error +{ + /* + *@private + * Deprecated class for now... + * History: + * In the beginning, I would like to have our own error class for critical exception. + * After sharing this with Xie, I was convinced to drop this idea by discussing with Xie. + * ToDo: Need a revisit after we have compound word support. + */ + public class ErrorTable + { + + static public const CONTENTPARSINGERROR_ID:int=11235; + static public const CONTENTPARSINGERROR_MSG:String="null cannot be parsed to a squiggly dictionary"; + public function ErrorTable() + { + } + + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/AbstractTarget.as ---------------------------------------------------------------------- diff --git a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/AbstractTarget.as b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/AbstractTarget.as new file mode 100644 index 0000000..52e5dd6 --- /dev/null +++ b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/AbstractTarget.as @@ -0,0 +1,167 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + + +package com.adobe.linguistics.spelling.core.logging +{ + import flash.errors.IllegalOperationError; +public class AbstractTarget implements ILoggingTarget +{ + private var _usingLevelMaskMode:Boolean; + public function AbstractTarget(usingLevelMaskMode:Boolean = false) + { + super(); + this._usingLevelMaskMode = usingLevelMaskMode; + +// _id = UIDUtil.createUID(); + } + + private var _loggerCount:uint = 0; + + private var _filters:Array = [ "*" ]; + + public function get filters():Array + { + return _filters; + } + + public function set filters(value:Array):void + { + if (value && value.length > 0) + { + // a valid filter value will be fully qualified or have a wildcard + // in it. the wild card can only be located at the end of the + // expression. valid examples xx*, xx.*, * + var filter:String; + var index:int; + var message:String; + for (var i:uint = 0; i<value.length; i++) + { + filter = value[i]; + // check for invalid characters + if (Log.hasIllegalCharacters(filter)) + { + throw new IllegalOperationError("Please check for invalid characters."); + } + + index = filter.indexOf("*"); + if ((index >= 0) && (index != (filter.length -1))) + { + throw new IllegalOperationError("Please check for invalid filters."); + } + } // for + } + else + { + // if null was specified then default to all + value = ["*"]; + } + + if (_loggerCount > 0) + { + Log.removeTarget(this); + _filters = value; + Log.addTarget(this); + } + else + { + _filters = value; + } + } + + private var _id:String; + + public function get id():String + { + return _id; + } + + private var _level:int = LogEventLevel.ALL; + + public function get level():int + { + return _level; + } + + /** + * @private + */ + public function set level(value:int):void + { + if ( this._usingLevelMaskMode == false ) { + if ( !LogEventLevel.isValidLevel(value) ) { + throw new IllegalOperationError("Please set an valid level in the level setter."); + } + + this._mask = LogEventLevel.getUpperMask(value); + }else { + if ( !LogEventLevel.isValidMask(value) ) { + throw new IllegalOperationError("Please set an valid mask in the mask setter."); + } + this._mask = value; + } + // A change of level may impact the target level for Log. + Log.removeTarget(this); + _level = value; + Log.addTarget(this); + } + + + private var _mask:int = LogEventLevel.ALL; + public function get mask():int { + return this._mask; + } + + + public function addLogger(logger:ILogger):void + { + if (logger) + { + _loggerCount++; + logger.addEventListener(LogEvent.eventID, logHandler); + } + } + + public function removeLogger(logger:ILogger):void + { + if (logger) + { + _loggerCount--; + logger.removeEventListener(LogEvent.eventID, logHandler); + } + } + + public function initialized(document:Object, id:String):void + { + _id = id; + Log.addTarget(this); + } + + public function logEvent(event:LogEvent):void + { + } + + private function logHandler(event:LogEvent):void + { + if ( (event.level & mask) != 0) + logEvent(event); + } +} + +}
