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);
+    }
+}
+
+}

Reply via email to