You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by jm...@apache.org on 2014/08/28 02:58:15 UTC
[10/21] remove Adobe from directory names (package name still
contains Adobe)
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);
+ }
+}
+
+}