http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/ILogger.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/ILogger.as
 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/ILogger.as
new file mode 100644
index 0000000..37df37e
--- /dev/null
+++ 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/ILogger.as
@@ -0,0 +1,40 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.events.IEventDispatcher;
+
+public interface ILogger extends IEventDispatcher
+{
+    function get category():String;
+
+    function log(level:int, message:String, ... rest):void;
+    function debug(message:String, ... rest):void;
+    function error(message:String, ... rest):void;
+
+    function fatal(message:String, ... rest):void;
+    function info(message:String, ... rest):void;
+    function warn(message:String, ... rest):void;
+}
+
+}
\ 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/ILoggingTarget.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/ILoggingTarget.as
 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/ILoggingTarget.as
new file mode 100644
index 0000000..47ed7ac
--- /dev/null
+++ 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/ILoggingTarget.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.logging
+{
+public interface ILoggingTarget 
+{
+    function get filters():Array;
+    
+    function set filters(value:Array):void;
+    function get level():int;
+
+    function set level(value:int):void;
+    
+    function get mask():int;
+
+    function addLogger(logger:ILogger):void;
+
+    function removeLogger(logger:ILogger):void;
+}
+
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/Log.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/Log.as
 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/Log.as
new file mode 100644
index 0000000..e9a720d
--- /dev/null
+++ 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/Log.as
@@ -0,0 +1,210 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 Log
+{
+
+    private static var _targetLevel:int = LogEventLevel.NONE;
+        // Initialize target level to a value out of range.
+
+    private static var _loggers:Array;
+
+    private static var _targets:Array = [];
+
+       
+    public static function isFatal():Boolean
+    {
+        return (_targetLevel & LogEventLevel.FATAL) ? true : false;
+    }
+    
+    public static function isError():Boolean
+    {
+        return (_targetLevel & LogEventLevel.ERROR) ? true : false;
+    }
+    
+    public static function isWarn():Boolean
+    {
+        return (_targetLevel & LogEventLevel.WARN) ? true : false;
+    }
+
+    public static function isInfo():Boolean
+    {
+        return (_targetLevel & LogEventLevel.INFO) ? true : false;
+    }
+    
+    public static function isDebug():Boolean
+    {
+        return (_targetLevel & LogEventLevel.DEBUG) ? true : false;
+    }
+
+    public static function addTarget(target:ILoggingTarget):void
+    {
+        if (target)
+        {
+            var filters:Array = target.filters;
+            var logger:ILogger;
+            // need to find what filters this target matches and set the 
specified
+            // target as a listener for that logger.
+            for (var i:String in _loggers)
+            {
+                if (categoryMatchInFilterList(i, filters))
+                    target.addLogger(ILogger(_loggers[i]));
+            }
+            // if we found a match all is good, otherwise we need to
+            // put the target in a waiting queue in the event that a logger
+            // is created that this target cares about.
+            _targets.push(target);
+            
+            if (_targetLevel == LogEventLevel.NONE)
+                _targetLevel = target.mask;
+            else{
+               _targetLevel = _targetLevel | target.mask;
+            }
+        }
+        else
+        {
+            throw new IllegalOperationError("addTarget function did not 
receive null object.");
+        }
+    }
+
+    public static function removeTarget(target:ILoggingTarget):void
+    {
+        if (target)
+        {
+            var filters:Array = target.filters;
+            var logger:ILogger;
+            // Disconnect this target from any matching loggers.
+            for (var i:String in _loggers)
+            {
+                if (categoryMatchInFilterList(i, filters))
+                {
+                    target.removeLogger(ILogger(_loggers[i]));
+                }                
+            }
+            // Remove the target.
+            for (var j:int = 0; j<_targets.length; j++)
+            {
+                if (target == _targets[j])
+                {
+                    _targets.splice(j, 1);
+                    j--;
+                }
+            }
+            resetTargetLevel();
+        }
+        else
+        {
+            throw new IllegalOperationError("addHandle function did not 
receive null object.");
+        }
+    }
+
+    public static function getLogger(category:String):ILogger
+    {
+        checkCategory(category);
+        if (!_loggers)
+            _loggers = [];
+               var newFlag:Boolean = false;
+        // get the logger for the specified category or create one if it
+        // doesn't exist
+        var result:ILogger = _loggers[category];
+        if (result == null)
+        {
+            result = new LogLogger(category);
+            _loggers[category] = result;
+            newFlag = true;
+        }
+
+        // check to see if there are any targets waiting for this logger.
+        var target:ILoggingTarget;
+        for (var i:int = 0; (i < _targets.length)&&(newFlag); i++)
+        {
+            target = ILoggingTarget(_targets[i]);
+            if (categoryMatchInFilterList(category, target.filters))
+                target.addLogger(result);
+        }
+
+        return result;
+    }
+
+    public static function flush():void
+    {
+        _loggers = [];
+        _targets = [];
+        _targetLevel = LogEventLevel.NONE;
+    }
+
+    public static function hasIllegalCharacters(value:String):Boolean
+    {
+        return value.search(/[\[\]\~\$\^\&\\(\)\{\}\+\?\/=`!@#%,:;'"<>\s]/) != 
-1;
+    }
+
+    private static function categoryMatchInFilterList(category:String, 
filters:Array):Boolean
+    {
+        var result:Boolean = false;
+        var filter:String;
+        var index:int = -1;
+        for (var i:uint = 0; i < filters.length; i++)
+        {
+            filter = filters[i];
+            // first check to see if we need to do a partial match
+            // do we have an asterisk?
+            index = filter.indexOf("*");
+
+            if (index == 0)
+                return true;
+
+            index = index < 0 ? index = category.length : index -1;
+
+            if (category.substring(0, index) == filter.substring(0, index))
+                return true;
+        }
+        return false;
+    }
+
+    private static function checkCategory(category:String):void
+    {
+        var message:String;
+        
+        if (category == null || category.length == 0)
+        {
+            throw new IllegalOperationError("checkCategory function did not 
receive null object.");
+        }
+
+        if (hasIllegalCharacters(category) || (category.indexOf("*") != -1))
+        {
+            throw new IllegalOperationError("checkCategory function did not 
receive invalid characters.");
+        }
+    }
+    
+    private static function resetTargetLevel():void
+    {  
+       var res:int = 0;
+        for (var i:int = 0; i < _targets.length; i++)
+        {
+            res = ( res | (_targets[i].mask) );
+        }
+        _targetLevel = res;
+    }
+}
+
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/LogEvent.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/LogEvent.as
 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/LogEvent.as
new file mode 100644
index 0000000..d90098d
--- /dev/null
+++ 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/LogEvent.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.logging
+{
+
+import flash.events.Event;
+
+public class LogEvent extends Event
+{
+    public static const eventID:String = 
"com.adobe.linguistics.spelling.core.logging.LogEvent";
+
+    public static function getLevelString(value:uint):String
+    {
+        switch (value)
+        {
+            case LogEventLevel.INFO:
+                       {
+                return "INFO";
+                       }
+
+            case LogEventLevel.DEBUG:
+                       {
+                return "DEBUG";
+            }
+
+            case LogEventLevel.ERROR:
+                       {
+                return "ERROR";
+            }
+
+            case LogEventLevel.WARN:
+                       {
+                return "WARN";
+            }
+
+            case LogEventLevel.FATAL:
+                       {
+                return "FATAL";
+            }
+
+            case LogEventLevel.ALL:
+                       {
+                return "ALL";
+            }
+               }
+
+               return "UNKNOWN";
+    }
+
+    public function LogEvent(message:String = "",
+                                                        level:int = 31 /* 
LogEventLevel.ALL */)
+    {
+        super(LogEvent.eventID, false, false);
+
+        this.message = message;
+        this.level = level;
+    }
+
+    public var level:int;
+
+    public var message:String;
+
+    override public function clone():Event
+    {
+        return new LogEvent(message, /*type,*/ level);
+    }
+}
+
+}
\ 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/LogEventLevel.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/LogEventLevel.as
 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/LogEventLevel.as
new file mode 100644
index 0000000..a12098b
--- /dev/null
+++ 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/LogEventLevel.as
@@ -0,0 +1,76 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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 final class LogEventLevel
+{
+           public static const FATAL:int = 16;
+       
+           public static const ERROR:int = 8;
+           
+           public static const WARN:int = 4;
+           
+           public static const INFO:int = 2;
+           
+           public static const DEBUG:int = 1;
+           
+           public static const ALL:int = (DEBUG | INFO | WARN | ERROR | FATAL);
+       
+           public static const NONE:int = 0;
+           
+           public static const LoggerLevelList:Array = [DEBUG, INFO, WARN, 
ERROR, FATAL, ALL];
+    
+               public static function isValidLevel(level:int) :Boolean {
+                       for ( var i:int = 0; i < LoggerLevelList.length ; ++i ) 
{
+                               if ( (LoggerLevelList[i] == level) )
+                                       return true;
+                       }
+                       return false;
+               }
+               
+               public static function isValidMask(mask:int ):Boolean {
+                       var allMask:int = 0;
+                       for ( var i:int = 0; i< LoggerLevelList.length; ++i ) {
+                               allMask = (allMask | (LoggerLevelList[i]));
+                       }
+                       if ( (allMask | mask ) == allMask ) return true;
+                       return false;
+               }
+               
+               public static function getUpperMask(level:int ) :int {
+                       var result:int = 0;
+                       if ( !isValidLevel(level) ) {
+                               throw new IllegalOperationError("Please input 
an valid level for getUpperMask.");
+                       } 
+                       if ( level == ALL) return level;
+                       for ( var i:int =0; i< LoggerLevelList.length; ++i ) {
+                               if ( (LoggerLevelList[i] >= level) && 
(LoggerLevelList[i] < ALL) ) {
+                                       result =result | LoggerLevelList[i];
+                               }
+                       }
+                       return result;
+               }
+
+
+}
+
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/LogLogger.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/LogLogger.as
 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/LogLogger.as
new file mode 100644
index 0000000..b5a23be
--- /dev/null
+++ 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/LogLogger.as
@@ -0,0 +1,102 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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;
+       import flash.events.EventDispatcher;
+public class LogLogger extends EventDispatcher implements ILogger
+{
+       public function LogLogger(category:String)
+       {
+               super();
+
+               _category = category;
+       }
+
+       /**
+        *  @private
+        *  Storage for the category property.
+        */
+       private var _category:String;
+
+       /**
+        *  The category this logger send messages for.
+        *  
+        */     
+       public function get category():String
+       {
+               return _category;
+       }
+       
+       public function log(level:int, msg:String, ... rest):void
+       {
+               dispatchLoggerEvent( level, msg, rest);
+       }
+
+       public function debug(msg:String, ... rest):void
+       {
+               dispatchLoggerEvent( LogEventLevel.DEBUG, msg, rest);
+       }
+
+       public function error(msg:String, ... rest):void
+       {
+               dispatchLoggerEvent( LogEventLevel.ERROR, msg, rest);
+       }
+
+       public function fatal(msg:String, ... rest):void
+       {
+               dispatchLoggerEvent( LogEventLevel.FATAL, msg, rest);
+       }
+
+       public function info(msg:String, ... rest):void
+       {
+               dispatchLoggerEvent( LogEventLevel.INFO, msg, rest);
+       }
+
+       public function warn(msg:String, ... rest):void
+       {
+               dispatchLoggerEvent( LogEventLevel.WARN, msg, rest);
+       }
+       
+       private function dispatchLoggerEvent(level:int, msg:String, 
options:Array):void {
+               // we don't want to allow people to log messages at the 
+               // Log.Level.ALL level, so throw a RTE if they do
+               if ( !LogEventLevel.isValidLevel( level ) )
+               {
+                       throw new IllegalOperationError("Please check for level 
permit.");
+               }
+               
+               if (hasEventListener(LogEvent.eventID))
+               {
+                       // replace all of the parameters in the msg string
+                       for (var i:int = 0; i < options.length; i++)
+                       {
+                               msg = msg.replace(new RegExp("\\{"+i+"\\}", 
"g"), options[i]);
+                       }
+
+                       dispatchEvent(new LogEvent(msg, level));
+               }
+               
+       }
+       
+}
+
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/ArrayTarget.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/ArrayTarget.as
 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/ArrayTarget.as
new file mode 100644
index 0000000..61a5a4a
--- /dev/null
+++ 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/ArrayTarget.as
@@ -0,0 +1,35 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.targets
+{
+       public class ArrayTarget extends CollectionTarget
+       {
+               public var items:Array;
+               public function ArrayTarget(arr:Array, 
usingLevelMaskMode:Boolean = false)
+               {
+                       this.items = arr;
+                       super(usingLevelMaskMode);
+               }
+               public override function internalLog(msg:String,lvl:int):void {
+                       items.push( {date:this.date, time:this.time, 
category:this.category, levelString:this.levelString, message:msg, level:lvl } 
);
+               }
+       }
+}
\ 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/targets/CollectionTarget.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/CollectionTarget.as
 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/CollectionTarget.as
new file mode 100644
index 0000000..b355f04
--- /dev/null
+++ 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/CollectionTarget.as
@@ -0,0 +1,107 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.targets
+{
+       import com.adobe.linguistics.spelling.core.logging.*;
+       public class CollectionTarget extends AbstractTarget
+       {
+           public var fieldSeparator:String = " ";
+       
+           public var includeCategory:Boolean;
+       
+           public var includeDate:Boolean;
+       
+           public var includeLevel:Boolean;
+       
+           public var includeTime:Boolean;
+
+           protected var date:String = "";
+           protected var time:String = "";
+           protected var levelString:String = "";
+           protected var category:String = "";
+               
+               public function CollectionTarget(usingLevelMaskMode:Boolean = 
false)
+               {
+               super(usingLevelMaskMode);
+               includeTime = false;
+               includeDate = false;
+               includeCategory = false;
+               includeLevel = false;
+               }
+
+           override public function logEvent(event:LogEvent):void
+           {
+               date = "";
+               time = "";
+               levelString = "";
+               category = "";
+               if (includeDate || includeTime)
+               {
+                   var d:Date = new Date();
+                   if (includeDate)
+                   {
+                       date = Number(d.getMonth() + 1).toString() + "/" +
+                              d.getDate().toString() + "/" + 
+                              d.getFullYear();
+                   }   
+                   if (includeTime)
+                   {
+                       time += padTime(d.getHours()) + ":" +
+                               padTime(d.getMinutes()) + ":" +
+                               padTime(d.getSeconds()) + "." +
+                               padTime(d.getMilliseconds(), true);
+                   }
+               }
+               
+               if (includeLevel)
+               {
+                   levelString = LogEvent.getLevelString(event.level);
+               }
+       
+               category = includeCategory ? ILogger(event.target).category:"";
+       
+               internalLog(event.message,event.level);
+           }
+           
+           private function padTime(num:Number, millis:Boolean = false):String
+           {
+               if (millis)
+               {
+                   if (num < 10)
+                       return "00" + num.toString();
+                   else if (num < 100)
+                       return "0" + num.toString();
+                   else 
+                       return num.toString();
+               }
+               else
+               {
+                   return num > 9 ? num.toString() : "0" + num.toString();
+               }
+           }
+       
+           public function internalLog(message:String, level:int):void
+           {
+               // override this method to perform the redirection to the 
desired output
+           }
+
+       }
+}
\ 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/targets/LineFormattedTarget.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/LineFormattedTarget.as
 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/LineFormattedTarget.as
new file mode 100644
index 0000000..c1b66eb
--- /dev/null
+++ 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/LineFormattedTarget.as
@@ -0,0 +1,104 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.targets
+{
+       import com.adobe.linguistics.spelling.core.logging.*;
+public class LineFormattedTarget extends AbstractTarget
+{
+    public function LineFormattedTarget(usingLevelMaskMode:Boolean = false)
+    {
+        super(usingLevelMaskMode);
+
+        includeTime = false;
+        includeDate = false;
+        includeCategory = false;
+        includeLevel = false;
+    }
+
+    public var fieldSeparator:String = " ";
+
+    public var includeCategory:Boolean;
+
+    public var includeDate:Boolean;
+
+    public var includeLevel:Boolean;
+
+    public var includeTime:Boolean;
+
+    override public function logEvent(event:LogEvent):void
+    {
+        var date:String = ""
+        if (includeDate || includeTime)
+        {
+            var d:Date = new Date();
+            if (includeDate)
+            {
+                date = Number(d.getMonth() + 1).toString() + "/" +
+                       d.getDate().toString() + "/" + 
+                       d.getFullYear() + fieldSeparator;
+            }   
+            if (includeTime)
+            {
+                date += padTime(d.getHours()) + ":" +
+                        padTime(d.getMinutes()) + ":" +
+                        padTime(d.getSeconds()) + "." +
+                        padTime(d.getMilliseconds(), true) + fieldSeparator;
+            }
+        }
+        
+        var level:String = "";
+        if (includeLevel)
+        {
+            level = "[" + LogEvent.getLevelString(event.level) +
+                    "]" + fieldSeparator;
+        }
+
+        var category:String = includeCategory ?
+                              ILogger(event.target).category + fieldSeparator :
+                              "";
+
+        internalLog(date + category+ level  + event.message,event.level);
+    }
+    
+    private function padTime(num:Number, millis:Boolean = false):String
+    {
+        if (millis)
+        {
+            if (num < 10)
+                return "00" + num.toString();
+            else if (num < 100)
+                return "0" + num.toString();
+            else 
+                return num.toString();
+        }
+        else
+        {
+            return num > 9 ? num.toString() : "0" + num.toString();
+        }
+    }
+
+    public function internalLog(message:String, level:int):void
+    {
+        // override this method to perform the redirection to the desired 
output
+    }
+}
+
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/TextFieldTarget.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/TextFieldTarget.as
 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/TextFieldTarget.as
new file mode 100644
index 0000000..bb4d75b
--- /dev/null
+++ 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/TextFieldTarget.as
@@ -0,0 +1,52 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.targets
+{
+    
+    import flash.text.TextField;
+    public class TextFieldTarget extends LineFormattedTarget 
+    {
+        public var autoScroll:Boolean = true ;
+        public var textfield:TextField ;
+
+        public function TextFieldTarget( 
textfield:TextField,usingLevelMaskMode:Boolean = false )
+        {
+            super(usingLevelMaskMode);
+            this.textfield = textfield ;
+        }
+        
+        public override function internalLog( message:String , level:int ):void
+        {
+            if ( textfield != null )
+            {
+                               textfield.appendText( message + "\r");
+                if ( autoScroll )
+                {
+                    textfield.scrollV  = textfield.maxScrollV ;
+                }
+            }
+            else
+            {
+                throw new ReferenceError( "The internal textfield reference of 
the target not must be null." ) ;
+            }
+        }
+    }
+}
\ 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/targets/TraceTarget.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/TraceTarget.as
 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/TraceTarget.as
new file mode 100644
index 0000000..5571fcd
--- /dev/null
+++ 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/logging/targets/TraceTarget.as
@@ -0,0 +1,37 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.targets
+{
+
+public class TraceTarget extends LineFormattedTarget
+{
+    public function TraceTarget(usingLevelMaskMode:Boolean = false)
+    {
+        super(usingLevelMaskMode);
+    }
+
+    public override function internalLog(message:String,level:int):void
+    {
+        trace(message);
+    }
+}
+
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/4e4f9830/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/rule/AffixEntry.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/rule/AffixEntry.as
 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/rule/AffixEntry.as
new file mode 100644
index 0000000..4ec678d
--- /dev/null
+++ 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/rule/AffixEntry.as
@@ -0,0 +1,137 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.rule
+{
+       import com.adobe.linguistics.spelling.core.LinguisticRule;
+       
+       public class AffixEntry
+       {
+               private var _flag:int;
+               private var _stripValue:String; /*stripping characters from 
beginning (at prefix rules) or end (at suffix rules) of the word  */
+               private var _affixValue:String; /* affix (optionally with flags 
of continuation classes, separated by a slash)  */
+               private var _conditionString:String; /*Zero stripping or affix 
are indicated by zero. 
+               Zero condition is indicated by dot. Condition is a simplified, 
regular expression-like pattern, 
+               which must be met before the affix can be applied. (Dot signs 
an arbitrary character. Characters 
+               in braces sign an arbitrary character from the character 
subset. Dash hasn’t got special meaning, 
+               but circumflex (^) next the first brace sets the complementer 
character set.)  */
+               private var _conditionPattern:RegExp;
+               private var _permissionToCombine:Boolean; /* Cross product 
(permission to combine prefixes and suffixes). Possible values: Y (yes) or N 
(no) */
+               private var _type:int; // 0 means prefix, 1 means suffix...
+               private var _morphologicalFields:String; //Optional 
morphological fields separated by spaces or tabulators. 
+               private var _contclass:String; //Added for Double affix support
+               
+               private var _attrMgr:LinguisticRule;            
+
+               
+               public function AffixEntry(affixFlag:int, stripString:String, 
affixValue:String, conditionStr:String, morph:String = "", permission:Boolean = 
false, affixType:int = 0, contclass:String=null)
+               {
+                       this.flag = affixFlag;
+                       this.conditionString = conditionStr;
+                       this.stripValue = stripString;
+                       this.affixKey = affixValue;
+                       this.permissionToCombine = permission;
+                       this.type = affixType;
+                       this.morphologicalFields = morph;
+                       this.attributeManager = null;
+                       this.contclass=contclass;//can be null too
+                       this._conditionPattern = (affixType == 0) ? new 
RegExp("^"+conditionStr+".*"+"$"): new RegExp("^"+".*"+conditionStr+"$");
+               }
+               
+               public function set attributeManager( 
attrMgr:LinguisticRule):void {
+                       this._attrMgr = attrMgr;
+               }
+               
+               public function get attributeManager( ):LinguisticRule {
+                       return this._attrMgr;
+               }
+               
+               public function set morphologicalFields(value:String):void {
+                       this._morphologicalFields = value;
+               }
+               
+               public function get morphologicalFields():String {
+                       return this._morphologicalFields;
+               }
+               
+               public function set permissionToCombine(value:Boolean) : void {
+                       this._permissionToCombine = value;
+               }
+               
+               public function get permissionToCombine():Boolean {
+                       return this._permissionToCombine;
+               }
+               
+               public function get flag():int {
+                       return this._flag;
+               }
+               public function set flag(affixFlag:int):void {
+                       this._flag = affixFlag;
+               }
+               
+               public function get type():int {
+                       return this._type;
+               }
+               
+               public function set type(affixType:int):void {
+                       this._type = affixType;
+               }
+               
+               public function set stripValue(value:String):void {
+                       this._stripValue = value;
+               } 
+               
+               public function get stripValue():String {
+                       return this._stripValue;
+               }
+               
+               public function set affixKey(value:String):void {
+                       this._affixValue = value;
+               }
+               
+               public function get affixKey():String {
+                       return this._affixValue;
+               }
+               
+               public function set contclass(value:String):void {
+                       this._contclass = value;
+               }
+               
+               public function get contclass():String {
+                       return this._contclass;
+               }
+               
+               public function get conditionString():String {
+                       return this._conditionString;
+               }
+               
+               public function set conditionString(value:String):void {
+                       this._conditionString  = value;
+               }
+               
+               public function get conditionPattern():RegExp {
+                       return this._conditionPattern;
+               }
+               public function set conditionPattern(value:RegExp):void {
+                       this._conditionPattern = value;
+               }
+
+       }
+}
\ 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/rule/AffixRule.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/rule/AffixRule.as
 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/rule/AffixRule.as
new file mode 100644
index 0000000..2633bd6
--- /dev/null
+++ 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/rule/AffixRule.as
@@ -0,0 +1,92 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.rule
+{
+       
+       public class AffixRule
+       {
+               private var _name:String;
+               private var _type:uint;
+               private var _stripValue:String;
+               private var _affixValue:String;
+               private var _conditionPattern:String;
+               private var _permissionToCombine:Boolean;
+               
+               public function AffixRule(affixName:String, affixType:uint, 
stripString:String, affixString:String, conditionString:String, 
permission:Boolean = true)
+               {
+                       this.name = affixName;
+                       this._conditionPattern = conditionString;
+                       this.type = affixType;
+                       this.stripValue = stripString;
+                       this.affixValue = affixString;
+                       this.permissionToCombine = permission;
+                       
+               }
+               
+               public function set permissionToCombine(value:Boolean) : void {
+                       this._permissionToCombine = value;
+               }
+               
+               public function get permissionToCombine():Boolean {
+                       return this._permissionToCombine;
+               }
+               
+               public function get name():String {
+                       return this._name;
+               }
+               public function set name(affixName:String):void {
+                       this._name = affixName;
+               }
+               
+               public function get type():uint {
+                       return this._type;
+               }
+               
+               public function set type(affixType:uint):void {
+                       this._type = affixType;
+               }
+               
+               public function set stripValue(value:String):void {
+                       this._stripValue = value;
+               } 
+               
+               public function get stripValue():String {
+                       return this._stripValue;
+               }
+               
+               public function set affixValue(value:String):void {
+                       this._affixValue = value;
+               }
+               
+               public function get affixValue():String {
+                       return this._affixValue;
+               }
+               
+               public function get conditionPattern():String {
+                       return this._conditionPattern;
+               }
+               
+               public function set conditionPattern(value:String):void {
+                       this._conditionPattern  = value;
+               }
+
+       }
+}
\ 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/rule/MapFilter.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/rule/MapFilter.as
 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/rule/MapFilter.as
new file mode 100644
index 0000000..3c241ed
--- /dev/null
+++ 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/rule/MapFilter.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.rule
+{
+       
+       public class MapFilter
+       {
+               private var _mapCharSet:String;
+               public function MapFilter(mapString:String)
+               {
+                       this.mapCharSet = mapString;
+               }
+               public function get mapCharSet():String {
+                       return this._mapCharSet;
+               }
+               public function set mapCharSet(value:String) : void {
+                       this._mapCharSet = value;
+               }
+
+       }
+}
\ 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/rule/OptimizedPrefixEntry.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/rule/OptimizedPrefixEntry.as
 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/rule/OptimizedPrefixEntry.as
new file mode 100644
index 0000000..b448338
--- /dev/null
+++ 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/rule/OptimizedPrefixEntry.as
@@ -0,0 +1,245 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.rule
+{
+       import com.adobe.linguistics.spelling.core.HashEntry;
+       import com.adobe.linguistics.spelling.core.env.InternalConstants;
+       public class OptimizedPrefixEntry extends AffixEntry
+       {
+               private var _flagNext:OptimizedPrefixEntry;
+               private var _keyNext:OptimizedPrefixEntry;
+               private var _flags:Array;
+               private var _pfxTable:Array;
+               public function OptimizedPrefixEntry(pfxEntry:PrefixEntry)
+               {
+                       
+                       
super(pfxEntry.flag,pfxEntry.stripValue,pfxEntry.affixKey,pfxEntry.conditionString,pfxEntry.morphologicalFields,
 pfxEntry.permissionToCombine, 0,pfxEntry.contclass);
+                       _flags = new Array();
+                       this._pfxTable = new Array();
+                       this.nextElementWithFlag = null;
+                       this.nextElementWithKey = null;
+                       _flags.push(this.flag);
+                       this._pfxTable.push(pfxEntry);
+                       this.flag = -1;
+                       this.conditionString = "";
+               }
+
+               public function isSimilarObject(pfxEntry:PrefixEntry):Boolean {
+                       var chkString:String=this.contclass+pfxEntry.contclass;
+                       
if(chkString)chkString=chkString.split('').sort().join('').replace(/(.)\1+/gi,'$1');//this
 pattern removes any repetition from strings. this will work only because we 
are converting n' or q' to Long numbers in decode flags
+                       if ( (this.stripValue == pfxEntry.stripValue) && 
(this.affixKey == pfxEntry.affixKey) && (this.permissionToCombine == 
pfxEntry.permissionToCombine) && (this.morphologicalFields == 
pfxEntry.morphologicalFields)&&(this.contclass==chkString) )        return true;
+                       return false;
+               } 
+               
+               public function extendObject( pfxEntry:PrefixEntry ):Boolean {
+                       if ( !isSimilarObject(pfxEntry) )       {
+                               return false;
+                       }
+                       _flags.push( pfxEntry.flag);
+                       this._pfxTable.push( pfxEntry );
+               
+                       var newConditionString:String;
+                       newConditionString = this.conditionPattern.source + "|" 
+ "^"+pfxEntry.conditionString+".*"+"$";
+                       this.conditionPattern  = new RegExp ( 
newConditionString);
+                       this.contclass=pfxEntry.contclass;
+                       return true;
+               }
+
+               public function get nextElementWithKey():OptimizedPrefixEntry {
+                       return this._keyNext;
+               }
+               
+               public function set 
nextElementWithKey(pfxEntry:OptimizedPrefixEntry):void {
+                       this._keyNext = pfxEntry;
+               }
+               
+               public function get nextElementWithFlag():OptimizedPrefixEntry {
+                       return this._flagNext;
+               }
+               
+               public function set 
nextElementWithFlag(pfxEntry:OptimizedPrefixEntry):void {
+                       this._flagNext = pfxEntry;
+               }
+               
+               public function get flags():Array {
+                       return this._flags;
+               }
+
+               /*
+                * Deprecated function for now...
+                * History: 
+                *          A pre-version of implementation for error 
detection. 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.
+                */
+               // check if this prefix entry matches
+               public function checkWord( word:String, sfxopts:int, 
ppfx:AffixEntry, inCompound:int, needFlag:int):HashEntry {
+                       var disLen:int = word.length - this.affixKey.length;
+                       var he:HashEntry = null;
+                       var i:int;
+                       // if this suffix is being cross checked with a prefix
+                       // but it does not support cross products skip it
+                       if ( (sfxopts& InternalConstants.aeXPRODUCT) != 0 && 
this.permissionToCombine != true ) return null;
+                       // on entry prefix is 0 length or already matches the 
beginning of the word.
+                       // So if the remaining root word has positive length
+                       // and if there are enough chars in root word and added 
back strip chars
+                       // to meet the number of characters conditions, then 
test it
+                       if ( disLen > 0 || (disLen == 0 && 
this.attributeManager.fullStrip) ) {
+                               // generate new root word by removing prefix 
and adding
+                               // back any characters that would have been 
stripped
+                               word = this.stripValue + 
word.substr(this.affixKey.length);
+                               // now make sure all of the conditions on 
characters
+                               // are met.  Please see the appendix at the end 
of
+                               // this file for more info on exactly what is 
being
+                               // tested
+                               // if all conditions are met then check if 
resulting
+                               // root word in the dictionary
+                               if ( this.conditionPattern.test( word ) ) {
+                                       // look word in hash table
+                                       for ( i=0; i < 
this.attributeManager.dictionaryManager.dictonaryList.length && !he; ++i ) {
+                                               he = 
this.attributeManager.dictionaryManager.dictonaryList[i].getElement(word);
+                                               while( he ) {
+                                                       if ( 
he.testAffixs(this._flags) && ( (!needFlag) || he.testAffix(needFlag) ) ) {
+                                                               return he;
+                                                       }
+                                                       he = he.next;
+                                               }
+                                       }
+                               } 
+                               
+                       }
+                       return he;
+               }
+
+               // check if this prefix entry matches
+               public function checkWord2( word:String, inCompound:int, 
needFlag:int):HashEntry {
+                       var disLen:int = word.length - this.affixKey.length;
+                       var he:HashEntry = null;
+                       var i:int,j:int;
+                       // on entry prefix is 0 length or already matches the 
beginning of the word.
+                       // So if the remaining root word has positive length
+                       // and if there are enough chars in root word and added 
back strip chars
+                       // to meet the number of characters conditions, then 
test it
+                       if ( disLen > 0 || (disLen == 0 && 
this.attributeManager.fullStrip) ) {
+                               // generate new root word by removing prefix 
and adding
+                               // back any characters that would have been 
stripped
+                               word = this.stripValue + 
word.substr(this.affixKey.length);
+                               // now make sure all of the conditions on 
characters
+                               // are met.  Please see the appendix at the end 
of
+                               // this file for more info on exactly what is 
being
+                               // tested
+                               // if all conditions are met then check if 
resulting
+                               // root word in the dictionary
+                               if ( this.conditionPattern.test( word ) ) {
+                                       // look word in hash table
+                                       for ( i=0; i < 
this.attributeManager.dictionaryManager.dictonaryList.length && !he; ++i ) {
+                                               he = 
this.attributeManager.dictionaryManager.dictonaryList[i].getElement(word);
+                                               while( he ) {
+                                                       if ( 
he.testAffixs(this._flags) && ( (!needFlag) || he.testAffix(needFlag) ) ) {
+                                                               for ( 
j=0;j<this._pfxTable.length;++j) {
+                                                                       if ( 
(this._pfxTable[j] ).conditionPattern.test(word) ) {
+                                                                               
if ( he.testAffix(this._flags[j]) ){
+                                                                               
        return he;
+                                                                               
}
+                                                                       }
+                                                               }
+                                                       }
+                                                       he = he.next;
+                                               }
+                                       }
+                                       //if ((opts & aeXPRODUCT) && 
in_compound)
+                                       if ( this.permissionToCombine ) {
+                                               for(i=0; j<this.flags[i];i++)
+                                               {
+                                                       he = 
this.attributeManager.optSuffixCheck2(word, InternalConstants.aeXPRODUCT,this, 
needFlag, inCompound,this.flags[i]);
+                                                       
+                                                       if (he) 
+                                                       {
+                                                       
+                                                               for ( 
j=0;j<this._pfxTable.length;++j) 
+                                                               {
+                                                                       if ( 
(this._pfxTable[j] ).conditionPattern.test(word) && (this._pfxTable[j].flag 
==this.flags[i]) )
+                                                                       {
+                                                                               
+                                                                               
        return he;
+                                                                               
+                                                                       }
+                                                               }
+                                                       he = null;      
+                                                       } 
+                                               }
+                                       }
+                               } 
+                               
+                       }
+                       return he;
+               }
+                
+               //checkTwoWord
+               public function checkTwoWord( word:String, inCompound:int, 
needFlag:int):HashEntry {
+                       var disLen:int = word.length - this.affixKey.length;
+                       var he:HashEntry = null;
+                       var i:int,j:int;
+                       // on entry prefix is 0 length or already matches the 
beginning of the word.
+                       // So if the remaining root word has positive length
+                       // and if there are enough chars in root word and added 
back strip chars
+                       // to meet the number of characters conditions, then 
test it
+                       if ( disLen > 0 || (disLen == 0 && 
this.attributeManager.fullStrip) ) {
+                               // generate new root word by removing prefix 
and adding
+                               // back any characters that would have been 
stripped
+                               word = this.stripValue + 
word.substr(this.affixKey.length);
+                               // now make sure all of the conditions on 
characters
+                               // are met.  Please see the appendix at the end 
of
+                               // this file for more info on exactly what is 
being
+                               // tested
+                               // if all conditions are met then check if 
resulting
+                               // root word in the dictionary
+                               if ( this.conditionPattern.test( word ) ) {
+                                       // do not look word in hash table
+                                       
+                                       //if ((opts & aeXPRODUCT) && 
in_compound)
+                                       if ( this.permissionToCombine && 
inCompound!=1/*IN_CPD_BEGIN*/) {//TODO: figure this constant
+                                               for(i=0; j<this.flags[i];i++)
+                                               {
+                                               
+                                                       he = 
this.attributeManager.optTwoSuffixCheck(word, 
InternalConstants.aeXPRODUCT,this,needFlag,this.flags[i]);//this is the c2
+                                                       if (he) {
+                                                               for ( 
j=0;j<this._pfxTable.length;++j) { //Squiggly will handle undrinkables from here
+                                                                       if ( 
(this._pfxTable[j] ).conditionPattern.test(word)&& (this._pfxTable[j].flag 
==this.flags[i]) ) 
+                                                                       {
+                                                                       
+                                                                               
        return he;
+                                                                               
+                                                                       }
+                                                               }
+                                                               he = null;
+                                                       }
+                                               }
+                                       }
+                               } 
+                               
+                       }
+                       return he;
+               }
+               //--
+
+       }
+}
\ 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/rule/OptimizedSuffixEntry.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/rule/OptimizedSuffixEntry.as
 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/rule/OptimizedSuffixEntry.as
new file mode 100644
index 0000000..7d6ee58
--- /dev/null
+++ 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/rule/OptimizedSuffixEntry.as
@@ -0,0 +1,301 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.rule
+{
+       import com.adobe.linguistics.spelling.core.HashEntry;
+       import com.adobe.linguistics.spelling.core.env.InternalConstants;
+       import com.adobe.linguistics.spelling.core.utils.StringUtils;
+       
+       public class OptimizedSuffixEntry  extends AffixEntry
+       {
+               private var _flagNext:OptimizedSuffixEntry;
+               private var _keyNext:OptimizedSuffixEntry;
+               private var _flags:Array;
+               private var _sfxTable:Array;
+               private var _reverseAffixKey:String;
+               public function OptimizedSuffixEntry(sfxEntry:SuffixEntry)
+               {
+                       
super(sfxEntry.flag,sfxEntry.stripValue,sfxEntry.affixKey,sfxEntry.conditionString,sfxEntry.morphologicalFields,
 sfxEntry.permissionToCombine, sfxEntry.type,sfxEntry.contclass);
+                       _flags = new Array();
+                       _sfxTable = new Array();
+                       this.nextElementWithFlag = null;
+                       this.nextElementWithKey = null;
+                       _flags.push(this.flag);
+                       _sfxTable.push(sfxEntry);
+                       this.reverseAffixKey = 
StringUtils.reverseString(this.affixKey);
+                       this.flag = -1;
+                       this.conditionString = "";
+               }
+               
+               public function isSimilarObject(sfxEntry:SuffixEntry):Boolean {
+                       var chkString:String=this.contclass+sfxEntry.contclass;
+                       
if(chkString)chkString=chkString.split('').sort().join('').replace(/(.)\1+/gi,'$1');//this
 pattern removes any repetition from strings. this will work only because we 
are converting n' or q' to Long numbers in decode flags
+                       if ( (this.stripValue == sfxEntry.stripValue) && 
(this.affixKey == sfxEntry.affixKey) && (this.permissionToCombine == 
sfxEntry.permissionToCombine) && (this.morphologicalFields == 
sfxEntry.morphologicalFields) &&(this.contclass==chkString) )       return true;
+                       return false;
+               } 
+               
+               public function extendObject( sfxEntry:SuffixEntry ):Boolean {
+                       
+                        if ( !isSimilarObject(sfxEntry) ) return false;
+                       _flags.push(sfxEntry.flag);
+                       _sfxTable.push(sfxEntry);
+                       var newConditionString:String;
+                       newConditionString = this.conditionPattern.source + "|" 
+ "^"+".*"+sfxEntry.conditionString+"$";
+                       this.conditionPattern  = new RegExp ( 
newConditionString);
+                       //now add in contclass
+                       this.contclass=sfxEntry.contclass;
+                       return true;
+               }
+               
+               public function set reverseAffixKey(value:String):void {
+                       this._reverseAffixKey = value;
+               }
+               
+               public function get reverseAffixKey():String {
+                       return this._reverseAffixKey;
+               }
+               
+               public function get nextElementWithKey():OptimizedSuffixEntry {
+                       return this._keyNext;
+               }
+               
+               public function set 
nextElementWithKey(pfxEntry:OptimizedSuffixEntry):void {
+                       this._keyNext = pfxEntry;
+               }
+               
+               public function get nextElementWithFlag():OptimizedSuffixEntry {
+                       return this._flagNext;
+               }
+               
+               public function set 
nextElementWithFlag(pfxEntry:OptimizedSuffixEntry):void {
+                       this._flagNext = pfxEntry;
+               }
+               
+               public function get flags():Array {
+                       return this._flags;
+               }
+               
+               /*
+                * Deprecated function for now...
+                * History: 
+                *          A pre-version of implementation for error 
detection. 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.
+                */
+               // see if this suffix is present in the word
+               public function checkWord( word:String, needFlag:int, 
inCompound:int):HashEntry {
+                       var disLen:int = word.length - this.affixKey.length;
+                       var he:HashEntry = null;
+                       var i:int;
+
+                       // upon entry suffix is 0 length or already matches the 
end of the word.
+                       // So if the remaining root word has positive length
+                       // and if there are enough chars in root word and added 
back strip chars
+                       // to meet the number of characters conditions, then 
test it
+                       if ( (disLen > 0 || (disLen == 0 && 
this.attributeManager.fullStrip)) ) {
+                               // generate new root word by removing suffix 
and adding
+                               // back any characters that would have been 
stripped or
+                               // or null terminating the shorter string
+                               word = word.substr(0, word.length - 
this.affixKey.length) + this.stripValue;
+                               // now make sure all of the conditions on 
characters
+                               // are met.  Please see the appendix at the end 
of
+                               // this file for more info on exactly what is 
being
+                               // tested
+                               // if all conditions are met then check if 
resulting
+                               // root word in the dictionary
+                               if ( this.conditionPattern.test( word ) ) {
+                                       // look word in hash table
+                                       for ( i=0; i < 
this.attributeManager.dictionaryManager.dictonaryList.length && !he; ++i ) {
+                                               he = 
this.attributeManager.dictionaryManager.dictonaryList[i].getElement(word);
+                                               while( he ) {
+                                                       if ( 
he.testAffixs(this._flags) && ( (!needFlag) || he.testAffix(needFlag) ) ) {
+                                                               return he;
+                                                       }
+                                                       he = he.next;
+                                               }
+                                       }
+                                       //if ((opts & aeXPRODUCT) && 
in_compound)
+                                       if ( this.permissionToCombine ) {
+                                               he = 
this.attributeManager.optPrefixCheck(word, InternalConstants.aeXPRODUCT,this, 
needFlag, inCompound);
+                                               if (he) return he; 
+                                       }
+                               } 
+                               
+                       }
+                       return he;
+               }
+               
+               //for develepors only, function used for printing flags when 
flag_mode=FLAG.LONG presently not being called anywhere
+               public function printFlag(flag:Number):void{
+                       var result:String =  String.fromCharCode(flag>>8) + 
String.fromCharCode(flag-((flag>>8)<<8));
+                       var x:String= this.affixKey;
+               }
+               // see if this suffix is present in the word
+               public function checkWord2( word:String, sfxopts:int, 
ppfx:AffixEntry, needFlag:int, inCompound:int, cclass:int, 
pfxcclass:int=0):HashEntry {
+                       var disLen:int = word.length - this.affixKey.length;
+                       var he:HashEntry = null;
+                       var i:int;
+
+                       // if this suffix is being cross checked with a prefix
+                       // but it does not support cross products skip it
+                       if ( (sfxopts& InternalConstants.aeXPRODUCT) != 0 && 
this.permissionToCombine != true ) return null;
+
+                       // upon entry suffix is 0 length or already matches the 
end of the word.
+                       // So if the remaining root word has positive length
+                       // and if there are enough chars in root word and added 
back strip chars
+                       // to meet the number of characters conditions, then 
test it
+                       if ( (disLen > 0 || (disLen == 0 && 
this.attributeManager.fullStrip)) ) {
+                               // generate new root word by removing suffix 
and adding
+                               // back any characters that would have been 
stripped or
+                               // or null terminating the shorter string
+                               word = word.substr(0, word.length - 
this.affixKey.length) + this.stripValue;
+                               // now make sure all of the conditions on 
characters
+                               // are met.  Please see the appendix at the end 
of
+                               // this file for more info on exactly what is 
being
+                               // tested
+                               // if all conditions are met then check if 
resulting
+                               // root word in the dictionary
+                               if ( this.conditionPattern.test( word ) ) {
+                                       // look word in hash table
+                                       for ( i=0; i < 
this.attributeManager.dictionaryManager.dictonaryList.length && !he; ++i ) {
+                                               he = 
this.attributeManager.dictionaryManager.dictonaryList[i].getElement(word);
+                                               while( he ) {
+                                                       if (  (( 
he.testAffixs(this._flags) ) && ( (!needFlag) || he.testAffix(needFlag) 
))||(ppfx && ppfx.contclass) ) {
+                                                               for ( var 
j:int=0;j<this._sfxTable.length;++j) {
+                                                                       if ( 
(this._sfxTable[j] ).conditionPattern.test(word) ) {
+                                                                               
if(!ppfx)
+                                                                               
{
+                                                                               
        if(cclass)
+                                                                               
        {
+                                                                               
                if (he.testAffix(this._flags[j]) && 
HashEntry.TESTAFF(this.contclass,cclass) )//should handle cases like 
drink->able->s also in un-run-able-s if run-->able and able-->s and s-->un this 
should suffice
+                                                                               
                        return he;
+                                                                               
        }
+                                                                               
        else                                                                    
                
+                                                                               
        {       if(he.testAffix(this._flags[j]))//should handle all normal 
cases like drink->able or drink->s
+                                                                               
                return he;
+                                                                               
        }
+                                                                               
        
+                                                                               
                                                                                
                
+                                                                               
}
+                                                                               
else
+                                                                               
{
+                                                                               
        if(this.contclass && he.testAffix(this._flags[j]) && 
HashEntry.TESTAFF(this.contclass,cclass) && !pfxcclass) // handle when suffix 
has contclass like l'->autre->s
+                                                                               
        {
+                                                                               
        return he;
+                                                                               
        }
+                                                                               
        if(ppfx.contclass && HashEntry.TESTAFF(ppfx.contclass,this._flags[j]) 
&& he.testAffix(cclass) && !pfxcclass) //handle when prefix has contclass like 
milli->litre->s
+                                                                               
        {
+                                                                               
                return he;      
+                                                                               
        }
+                                                                               
        if(he.testAffix(this._flags[j]) && he.testAffix(cclass))//handle normal 
cases when both pfx and sfx exist in hash affix string
+                                                                               
        {
+                                                                               
        return he;
+                                                                               
        }
+                                                                               
        
+                                                                               
        //special case of un-drink-able-s
+                                                                               
        if(    (he.testAffix(pfxcclass) && ppfx.contclass && 
HashEntry.TESTAFF(ppfx.contclass,this._flags[j]) && this.contclass && 
HashEntry.TESTAFF(this.contclass,cclass)) 
+                                                                               
           ||  (he.testAffix(this._flags[j]) && this.contclass && 
HashEntry.TESTAFF(this.contclass,cclass) && 
HashEntry.TESTAFF(this.contclass,pfxcclass))
+                                                                               
           )
+                                                                               
        {
+                                                                               
                return he;
+                                                                               
        }
+                                                                               
        
+                                                                               
                                                                                
                
+                                                                               
}
+                                                                               
        
+                                                                               
}
+                                                               }
+                                                       }
+                                                       he = he.next;
+                                               }
+                                       }
+
+                               } 
+                               
+                       }
+                       return he;
+               }
+               
+               // Function for two level suffix checkword
+               // see if this suffix is present in the word
+               public function checkTwoWord( word:String, sfxopts:int, 
ppfx:AffixEntry, needFlag:int, cclass:int, pfxcclass:int=0):HashEntry {
+                       var disLen:int = word.length - this.affixKey.length;
+                       var he:HashEntry = null;
+                       var i:int;
+                       
+                       // if this suffix is being cross checked with a prefix
+                       // but it does not support cross products skip it
+                       if ( (sfxopts& InternalConstants.aeXPRODUCT) != 0 && 
this.permissionToCombine != true ) return null;
+                       
+                       // upon entry suffix is 0 length or already matches the 
end of the word.
+                       // So if the remaining root word has positive length
+                       // and if there are enough chars in root word and added 
back strip chars
+                       // to meet the number of characters conditions, then 
test it
+                       if ( (disLen > 0 || (disLen == 0 && 
this.attributeManager.fullStrip)) ) {
+                               // generate new root word by removing suffix 
and adding
+                               // back any characters that would have been 
stripped or
+                               // or null terminating the shorter string
+                               word = word.substr(0, word.length - 
this.affixKey.length) + this.stripValue;
+                               // now make sure all of the conditions on 
characters
+                               // are met.  Please see the appendix at the end 
of
+                               // this file for more info on exactly what is 
being
+                               // tested
+                               // if all conditions are met then see if for 
conditional suffix and if this has been stripped by a possible
+                               // contclass check the remaining word 
+                               // eg: if drinkables was original word and 
after possible stripping of s we have drinkable very if 
+                               // now check drinkable, able will be stripped 
and drink will be found that hash entry will then be returned
+                               if ( this.conditionPattern.test( word ) ) 
{//checks a whole group of 
+                                       
+                                       if(ppfx)
+                                       { //check for conditional suffix
+                                               if( contclass!=null && 
HashEntry.TESTAFF(contclass, pfxcclass))
+                                               {
+                                                       he = 
this.attributeManager.optSuffixCheck2(word, 0, 
null,needFlag,0,cclass,pfxcclass);//we are not sending ppfx here as it will not 
be needed.
+                                               }
+                                               else
+                                               {
+                                                       he = 
this.attributeManager.optSuffixCheck2(word, sfxopts, 
ppfx,needFlag,0,cclass,pfxcclass);
+                                               }
+                                       }
+                                       else
+                                       {
+                                               he = 
this.attributeManager.optSuffixCheck2(word, 0, null,needFlag,0,cclass,0);
+                                       }
+                                       if (he) {
+                                               for ( var 
j:int=0;j<this._sfxTable.length;++j) { //Squiggly will handle drink->able->s 
from here
+                                                       if ( 
(this._sfxTable[j]).conditionPattern.test(word) && 
cclass==(this._sfxTable[j]).flag) {//only permit words which end with s in 
drinkables
+                                                               
+                                                                       return 
he;
+                                                       
+                                                       }
+                                               }
+                                               he = null;
+                                       }
+                                       
+                               } 
+                               
+                       }
+                       
+                       return he;
+               }
+               //--
+       }
+}
\ 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/rule/PrefixEntry.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/rule/PrefixEntry.as
 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/rule/PrefixEntry.as
new file mode 100644
index 0000000..7df2e55
--- /dev/null
+++ 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/rule/PrefixEntry.as
@@ -0,0 +1,102 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.rule
+{
+       import com.adobe.linguistics.spelling.core.HashEntry;
+       import com.adobe.linguistics.spelling.core.env.InternalConstants;
+       public class PrefixEntry extends AffixEntry
+       {
+               private var _flagNext:PrefixEntry;
+               private var _keyNext:PrefixEntry;
+               public function PrefixEntry(affixFlag:int, stripString:String, 
affixValue:String, conditionString:String, morph:String = "", 
permission:Boolean = false,contclass:String=null)
+               {
+                       
super(affixFlag,stripString,affixValue,conditionString,morph, permission, 
0,contclass);
+                       this.nextElementWithFlag = null;
+                       this.nextElementWithKey = null;
+               }
+               
+               public function add(root:String):String {
+                       if ( this.conditionPattern.test(root) )
+                               return this.affixKey + 
root.substring(this.stripValue.length );
+                       return null; 
+               }
+               
+               public function get nextElementWithKey():PrefixEntry {
+                       return this._keyNext;
+               }
+               
+               public function set 
nextElementWithKey(pfxEntry:PrefixEntry):void {
+                       this._keyNext = pfxEntry;
+               }
+               
+               public function get nextElementWithFlag():PrefixEntry {
+                       return this._flagNext;
+               }
+               
+               public function set 
nextElementWithFlag(pfxEntry:PrefixEntry):void {
+                       this._flagNext = pfxEntry;
+               }
+               
+               // check if this prefix entry matches
+               public function checkWord( word:String, inCompound:int, 
needFlag:int):HashEntry {
+                       var disLen:int = word.length - this.affixKey.length;
+                       var he:HashEntry = null;
+                       var i:int;
+                       // on entry prefix is 0 length or already matches the 
beginning of the word.
+                       // So if the remaining root word has positive length
+                       // and if there are enough chars in root word and added 
back strip chars
+                       // to meet the number of characters conditions, then 
test it
+                       if ( disLen > 0 || (disLen == 0 && 
this.attributeManager.fullStrip) ) {
+                               // generate new root word by removing prefix 
and adding
+                               // back any characters that would have been 
stripped
+                               word = this.stripValue + 
word.substr(this.affixKey.length);
+                               // now make sure all of the conditions on 
characters
+                               // are met.  Please see the appendix at the end 
of
+                               // this file for more info on exactly what is 
being
+                               // tested
+                               // if all conditions are met then check if 
resulting
+                               // root word in the dictionary
+                               if ( this.conditionPattern.test( word ) ) {
+                                       // look word in hash table
+                                       for ( i=0; i < 
this.attributeManager.dictionaryManager.dictonaryList.length && !he; ++i ) {
+                                               he = 
this.attributeManager.dictionaryManager.dictonaryList[i].getElement(word);
+                                               while( he ) {
+                                                       if ( 
he.testAffix(this.flag) && ( (!needFlag) || he.testAffix(needFlag) ) ) {
+                                                               return he;
+                                                       }
+                                                       he = he.next;
+                                               }
+                                       }
+                                       //if ((opts & aeXPRODUCT) && 
in_compound)
+                                       if ( this.permissionToCombine ) {
+                                               he = 
this.attributeManager.suffixCheck2(word, InternalConstants.aeXPRODUCT,this, 
needFlag, inCompound);
+                                               if (he) return he; 
+                                       }
+                               } 
+                               
+                       }
+                       return he;
+               }
+
+
+
+       }
+}
\ 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/rule/ReplacementFilter.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/rule/ReplacementFilter.as
 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/rule/ReplacementFilter.as
new file mode 100644
index 0000000..8f0b1d9
--- /dev/null
+++ 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/rule/ReplacementFilter.as
@@ -0,0 +1,34 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.rule
+{
+               /*
+                * Deprecated class for now...
+                * ToDo: It is a place holder for metaphone algorithm in the 
rule based engine.
+                */
+       public class ReplacementFilter
+       {
+               public function ReplacementFilter()
+               {
+               }
+
+       }
+}
\ 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/rule/SimpleFilter.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/rule/SimpleFilter.as
 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/rule/SimpleFilter.as
new file mode 100644
index 0000000..4763059
--- /dev/null
+++ 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/rule/SimpleFilter.as
@@ -0,0 +1,48 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.rule
+{
+       public class SimpleFilter
+       {
+               private var _matchString:String;
+               private var _replacementString:String;
+               public function SimpleFilter(matchingString:String, 
replacementString:String)
+               {
+                       this.matchString = matchingString;
+                       this.replacement = replacementString;
+               }
+               
+               public function set matchString(value:String) :void {
+                       this._matchString = value;
+               }
+               public function get matchString():String {
+                       return this._matchString;
+               }
+               
+               public function set replacement(value:String) :void {
+                       this._replacementString = value;
+               }
+               public function get replacement() :String {
+                       return this._replacementString;
+               }
+
+       }
+}
\ 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/rule/SuffixEntry.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/rule/SuffixEntry.as
 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/rule/SuffixEntry.as
new file mode 100644
index 0000000..313ada3
--- /dev/null
+++ 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/rule/SuffixEntry.as
@@ -0,0 +1,126 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.rule
+{
+       import com.adobe.linguistics.spelling.core.HashEntry;
+       import com.adobe.linguistics.spelling.core.env.InternalConstants;
+
+       public class SuffixEntry extends AffixEntry
+       {
+               private var _flagNext:SuffixEntry;
+               private var _keyNext:SuffixEntry;
+               private var _conditionPattern2:RegExp = null;;
+               private var _noTestFlag:Boolean = false;
+               public function SuffixEntry(affixFlag:int, stripString:String, 
affixValue:String, conditionString:String, morph:String = "", 
permission:Boolean = false, contclass:String=null)
+               {
+                       
super(affixFlag,stripString,affixValue,conditionString,morph, permission, 
1,contclass);
+                       this.nextElementWithFlag = null;
+                       this.nextElementWithKey = null;
+                       if ( this.stripValue != "" ) {
+                               if ( this.conditionString == "." ) {
+                                               this._conditionPattern2 = null;
+                                               this._noTestFlag = true;
+                                       
+                               }else {
+                                       var stripPattern:RegExp = new RegExp ( 
"^(.*)"+this.stripValue+"$" );
+                                       var strArr:Array;
+                                       if ( (strArr = 
this.conditionString.match(stripPattern) ) != null ) {
+                                               if ( strArr[1] != "" ) {
+                                                       this._conditionPattern2 
= new RegExp( "^.*" + strArr[1] + "$" );
+                                               }else {
+                                                       this._conditionPattern2 
= null;
+                                                       this._noTestFlag = true;
+                                               }
+                                       }else {
+                                               this._conditionPattern2 = 
this.conditionPattern;
+                                       }
+                               }
+                       }
+                       
+               }
+               
+               public function add(root:String):String {
+                       if ( this.conditionPattern.test(root) )
+                               return root.substring(0, 
(root.length-this.stripValue.length) ) + this.affixKey;
+                       return null; 
+               }
+               
+               public function get nextElementWithKey():SuffixEntry {
+                       return this._keyNext;
+               }
+               
+               public function set 
nextElementWithKey(pfxEntry:SuffixEntry):void {
+                       this._keyNext = pfxEntry;
+               }
+               
+               public function get nextElementWithFlag():SuffixEntry {
+                       return this._flagNext;
+               }
+               
+               public function set 
nextElementWithFlag(pfxEntry:SuffixEntry):void {
+                       this._flagNext = pfxEntry;
+               }
+
+               // see if this suffix is present in the word
+               public function checkWord( word:String, sfxopts:int, 
ppfx:AffixEntry, needFlag:int, inCompound:int):HashEntry {
+                       var disLen:int = word.length - this.affixKey.length;
+                       var he:HashEntry = null;
+                       var i:int;
+
+                       // if this suffix is being cross checked with a prefix
+                       // but it does not support cross products skip it
+                       if ( (sfxopts& InternalConstants.aeXPRODUCT) != 0 && 
this.permissionToCombine != true ) return null;
+
+                       // upon entry suffix is 0 length or already matches the 
end of the word.
+                       // So if the remaining root word has positive length
+                       // and if there are enough chars in root word and added 
back strip chars
+                       // to meet the number of characters conditions, then 
test it
+                       if ( (disLen > 0 || (disLen == 0 && 
this.attributeManager.fullStrip)) ) {
+                               // generate new root word by removing suffix 
and adding
+                               // back any characters that would have been 
stripped or
+                               // or null terminating the shorter string
+                               word = word.substr(0, word.length - 
this.affixKey.length) + this.stripValue;
+                               // now make sure all of the conditions on 
characters
+                               // are met.  Please see the appendix at the end 
of
+                               // this file for more info on exactly what is 
being
+                               // tested
+                               // if all conditions are met then check if 
resulting
+                               // root word in the dictionary
+                               if ( this._noTestFlag || 
this.conditionPattern.test( word ) ) {
+                                       // look word in hash table
+                                       for ( i=0; i < 
this.attributeManager.dictionaryManager.dictonaryList.length && !he; ++i ) {
+                                               he = 
this.attributeManager.dictionaryManager.dictonaryList[i].getElement(word);
+                                               while( he ) {
+                                                       if ( 
he.testAffix(this.flag) && ( (!needFlag) || he.testAffix(needFlag) ) ) {
+                                                               return he;
+                                                       }
+                                                       he = he.next;
+                                               }
+                                       }
+
+                               } 
+                               
+                       }
+                       return he;
+               }
+
+       }
+}
\ 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/utils/DictionaryLoader.as
----------------------------------------------------------------------
diff --git 
a/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/utils/DictionaryLoader.as
 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/utils/DictionaryLoader.as
new file mode 100644
index 0000000..1092179
--- /dev/null
+++ 
b/Squiggly/main/SpellingEngine/src/com/adobe/linguistics/spelling/core/utils/DictionaryLoader.as
@@ -0,0 +1,94 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  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.utils
+{
+       import flash.events.Event;
+       import flash.events.EventDispatcher;
+       import flash.events.IOErrorEvent;
+       import flash.events.SecurityErrorEvent;
+       import flash.net.URLLoader;
+       import flash.net.URLLoaderDataFormat;
+       import flash.net.URLRequest;
+       import flash.utils.ByteArray;
+       import flash.utils.getTimer;
+       
+       public class DictionaryLoader extends EventDispatcher
+       {
+               private var dataloader:URLLoader;
+               private var _data:ByteArray;
+               public function DictionaryLoader(request:URLRequest=null)
+               {
+                       dataloader = new URLLoader();
+                       dataloader.dataFormat = URLLoaderDataFormat.BINARY;
+                       
dataloader.addEventListener(Event.COMPLETE,handleComplete);
+                       
dataloader.addEventListener(IOErrorEvent.IO_ERROR,handleError);
+                       
dataloader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,handleError);
+                       if (request) { 
+                               try {
+                                       load(request); 
+                               }
+                               catch (error:Error) {
+                                                                       
+                               }
+                       }
+                       else 
+                       {
+                               dispatchEvent(new Event(Event.COMPLETE));
+                       }
+               }
+               
+               public function get bytesTotal():uint {
+                       return dataloader.bytesTotal;
+               }
+               
+               public function get data():ByteArray {
+                       return this._data;
+               }
+
+               public function load(request:URLRequest):void {
+                       _data = null;
+                       //trace("Before Actual load: "+getTimer()+" 
"+dataloader.bytesLoaded);
+                       dataloader.load(request);
+                       
+               }
+
+               private function handleComplete(evt:Event):void {
+                       // add to-do function.
+                       this._data = (dataloader.data as ByteArray);
+                       dispatchEvent(new Event(Event.COMPLETE));
+               }
+
+               private function handleError(evt:Event):void {
+                       bounceEvent(evt);
+               }
+               
+               private function bounceEvent(evt:Event):void {
+                       dispatchEvent(evt.clone());
+               }
+               
+               public function getData(): ByteArray {
+                       return this._data;
+               }
+               
+
+       }
+}
\ No newline at end of file

Reply via email to