////////////////////////////////////////////////////////////////////////////////
//
//  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 org.apache.flex.utils
{
	/**
	 *  The StringUtil utility class is an all-static class with methods for
	 *  working with String objects.
	 *  You do not create instances of StringUtil;
	 *  instead you call methods such as
	 *  the StringUtil.substitute() method.
	 *
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 *  @productversion FlexJS 0.0
	 */
	public class StringUtil extends StringTrimmer
	{
		public function StringUtil()
		{
			throw new Error("StringUtil should not be instantiated.");
		}

		/**
		 *  Substitutes "{n}" tokens within the specified string
		 *  with the respective arguments passed in.
		 *
		 *  Note that this uses String.replace and "$" can have special
		 *  meaning in the argument strings escape by using "$$".
		 *
		 *  @param str The string to make substitutions in.
		 *  This string can contain special tokens of the form
		 *  {n}, where n is a zero based index,
		 *  that will be replaced with the additional parameters
		 *  found at that index if specified.
		 *
		 *  @param rest Additional parameters that can be substituted
		 *  in the str parameter at each {n}
		 *  location, where n is an integer (zero based)
		 *  index value into the array of values specified.
		 *  If the first parameter is an array this array will be used as
		 *  a parameter list.
		 *  This allows reuse of this routine in other methods that want to
		 *  use the ... rest signature.
		 *  For example

		 *     public function myTracer(str:String, ... rest):void
		 *     {
		 *         label.text += StringUtil.substitute(str, rest) + "\n";
		 *     }

		 *
		 *  @return New string with all of the {n} tokens
		 *  replaced with the respective arguments specified.
		 *
		 *  @example
		 *
		 *  var str:String = "here is some info '{0}' and {1}";
		 *  trace(StringUtil.substitute(str, 15.4, true));
		 *
		 *  // this will output the following string:
		 *  // "here is some info '15.4' and true"
		 *
		 *  @langversion 3.0
		 *  @playerversion Flash 9
		 *  @playerversion AIR 1.1
		 *  @productversion Flex 3
		 *  @productversion FlexJS 0.0
		 */
		public static function substitute(str:String, ... rest):String
		{
			if (str == null) return '';

			// Replace all of the parameters in the msg string.
			var len:uint = rest.length;
			var args:Array;
			if (len == 1 && rest[0] is Array)
			{
				args = rest[0] as Array;
				len = args.length;
			}
			else
			{
				args = rest;
			}

			for (var i:int = 0; i < len; i++)
			{
				str = str.replace(new RegExp("\\{"+i+"\\}", "g"), args[i]);
			}

			return str;
		}

		/**
		 *  Returns a string consisting of a specified string
		 *  concatenated with itself a specified number of times.
		 *
		 *  @param str The string to be repeated.
		 *
		 *  @param n The repeat count.
		 *
		 *  @return The repeated string.
		 *
		 *  @langversion 3.0
		 *  @playerversion Flash 10
		 *  @playerversion AIR 1.5
		 *  @productversion Flex 4.1
		 *  @productversion FlexJS 0.0
		 */
		public static function repeat(str:String, n:int):String
		{
			if (n == 0)
				return "";
			var a:Array = [];
			for (var i:int = 0; i < n; i++)
			{
				a.push(str);
			}
			return a.join("");
		}

		/**
		 *  Removes "unallowed" characters from a string.
		 *  A "restriction string" such as "A-Z0-9"
		 *  is used to specify which characters are allowed.
		 *  This method uses the same logic as the restrict
		 *  property of TextField.
		 *
		 *  @param str The input string.
		 *
		 *  @param restrict The restriction string.
		 *
		 *  @return The input string, minus any characters
		 *  that are not allowed by the restriction string.
		 *
		 *  @langversion 3.0
		 *  @playerversion Flash 10
		 *  @playerversion AIR 1.5
		 *  @productversion Flex 4.1
		 *  @productversion FlexJS 0.0
		 */
		public static function restrict(str:String, restrict:String):String
		{
			// A null 'restrict' string means all characters are allowed.
			if (restrict == null)
				return str;

			// An empty 'restrict' string means no characters are allowed.
			if (restrict == "")
				return "";

			// Otherwise, we need to test each character in 'str'
			// to determine whether the 'restrict' string allows it.
			var charCodes:Array = [];

			var n:int = str.length;
			for (var i:int = 0; i < n; i++)
			{
				var charCode:uint = str.charCodeAt(i);
				if (testCharacter(charCode, restrict))
					charCodes.push(charCode);
			}

			return String.fromCharCode.apply(null, charCodes);
		}

		/**
		 *  @private
		 *  Helper method used by restrict() to test each character
		 *  in the input string against the restriction string.
		 *  The logic in this method implements the same algorithm
		 *  as in TextField's 'restrict' property (which is quirky,
		 *  such as how it handles a '-' at the beginning of the
		 *  restriction string).
		 */
		private static function testCharacter(charCode:uint,
											  restrict:String):Boolean
		{
			var allowIt:Boolean = false;

			var inBackSlash:Boolean = false;
			var inRange:Boolean = false;
			var setFlag:Boolean = true;
			var lastCode:uint = 0;

			var n:int = restrict.length;
			var code:uint;

			if (n > 0)
			{
				code = restrict.charCodeAt(0);
				if (code == 94) // caret
					allowIt = true;
			}

			for (var i:int = 0; i < n; i++)
			{
				code = restrict.charCodeAt(i)

				var acceptCode:Boolean = false;
				if (!inBackSlash)
				{
					if (code == 45) // hyphen
						inRange = true;
					else if (code == 94) // caret
						setFlag = !setFlag;
					else if (code == 92) // backslash
						inBackSlash = true;
					else
						acceptCode = true;
				}
				else
				{
					acceptCode = true;
					inBackSlash = false;
				}

				if (acceptCode)
				{
					if (inRange)
					{
						if (lastCode <= charCode && charCode <= code)
							allowIt = setFlag;
						inRange = false;
						lastCode = 0;
					}
					else
					{
						if (charCode == code)
							allowIt = setFlag;
						lastCode = code;
					}
				}
			}

			return allowIt;
		}
	}
}

////////////////////////////////////////////////////////////////////////////////
//
//  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 org.apache.flex.utils
{
	/**
	 *  The StringUtil utility class is an all-static class with methods for
	 *  working with String objects.
	 *  You do not create instances of StringUtil;
	 *  instead you call methods such as
	 *  the StringUtil.substitute() method.
	 *
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 *  @productversion FlexJS 0.0
	 */
	public class StringUtil
	{
		public function StringUtil()
		{
			throw new Error("StringUtil should not be instantiated.");
		}

		/**
		 *  Substitutes "{n}" tokens within the specified string
		 *  with the respective arguments passed in.
		 *
		 *  Note that this uses String.replace and "$" can have special
		 *  meaning in the argument strings escape by using "$$".
		 *
		 *  @param str The string to make substitutions in.
		 *  This string can contain special tokens of the form
		 *  {n}, where n is a zero based index,
		 *  that will be replaced with the additional parameters
		 *  found at that index if specified.
		 *
		 *  @param rest Additional parameters that can be substituted
		 *  in the str parameter at each {n}
		 *  location, where n is an integer (zero based)
		 *  index value into the array of values specified.
		 *  If the first parameter is an array this array will be used as
		 *  a parameter list.
		 *  This allows reuse of this routine in other methods that want to
		 *  use the ... rest signature.
		 *  For example

		 *     public function myTracer(str:String, ... rest):void
		 *     {
		 *         label.text += StringUtil.substitute(str, rest) + "\n";
		 *     }

		 *
		 *  @return New string with all of the {n} tokens
		 *  replaced with the respective arguments specified.
		 *
		 *  @example
		 *
		 *  var str:String = "here is some info '{0}' and {1}";
		 *  trace(StringUtil.substitute(str, 15.4, true));
		 *
		 *  // this will output the following string:
		 *  // "here is some info '15.4' and true"
		 *
		 *  @langversion 3.0
		 *  @playerversion Flash 9
		 *  @playerversion AIR 1.1
		 *  @productversion Flex 3
		 *  @productversion FlexJS 0.0
		 */
		public static function substitute(str:String, ... rest):String
		{
			if (str == null) return '';

			// Replace all of the parameters in the msg string.
			var len:uint = rest.length;
			var args:Array;
			if (len == 1 && rest[0] is Array)
			{
				args = rest[0] as Array;
				len = args.length;
			}
			else
			{
				args = rest;
			}

			for (var i:int = 0; i < len; i++)
			{
				str = str.replace(new RegExp("\\{"+i+"\\}", "g"), args[i]);
			}

			return str;
		}

		/**
		 *  Returns a string consisting of a specified string
		 *  concatenated with itself a specified number of times.
		 *
		 *  @param str The string to be repeated.
		 *
		 *  @param n The repeat count.
		 *
		 *  @return The repeated string.
		 *
		 *  @langversion 3.0
		 *  @playerversion Flash 10
		 *  @playerversion AIR 1.5
		 *  @productversion Flex 4.1
		 *  @productversion FlexJS 0.0
		 */
		public static function repeat(str:String, n:int):String
		{
			if (n == 0)
				return "";
			var a:Array = [];
			for (var i:int = 0; i < n; i++)
			{
				a.push(str);
			}
			return a.join("");
		}

		/**
		 *  Removes "unallowed" characters from a string.
		 *  A "restriction string" such as "A-Z0-9"
		 *  is used to specify which characters are allowed.
		 *  This method uses the same logic as the restrict
		 *  property of TextField.
		 *
		 *  @param str The input string.
		 *
		 *  @param restrict The restriction string.
		 *
		 *  @return The input string, minus any characters
		 *  that are not allowed by the restriction string.
		 *
		 *  @langversion 3.0
		 *  @playerversion Flash 10
		 *  @playerversion AIR 1.5
		 *  @productversion Flex 4.1
		 *  @productversion FlexJS 0.0
		 */
		public static function restrict(str:String, restrict:String):String
		{
			// A null 'restrict' string means all characters are allowed.
			if (restrict == null)
				return str;

			// An empty 'restrict' string means no characters are allowed.
			if (restrict == "")
				return "";

			// Otherwise, we need to test each character in 'str'
			// to determine whether the 'restrict' string allows it.
			var charCodes:Array = [];

			var n:int = str.length;
			for (var i:int = 0; i < n; i++)
			{
				var charCode:uint = str.charCodeAt(i);
				if (testCharacter(charCode, restrict))
					charCodes.push(charCode);
			}

			return String.fromCharCode.apply(null, charCodes);
		}

        /**
         *  Removes all whitespace characters from the beginning and end
         *  of the specified string.
         *
         *  @param str The String whose whitespace should be trimmed.
         *
         *  @return Updated String where whitespace was removed from the
         *  beginning and end.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public static function trim(str:String):String
        {
            return StringTrimmer.trim(str);
        }

        /**
         *  Removes all whitespace characters from the beginning and end
         *  of each element in an Array, where the Array is stored as a String.
         *
         *  @param value The String whose whitespace should be trimmed.
         *
         *  @param separator The String that delimits each Array element in the string.
         *
         *  @return Array where whitespace was removed from the
         *  beginning and end of each element.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public static function splitAndTrim(value:String, delimiter:String):Array
        {
            return StringTrimmer.splitAndTrim(value,delimiter);
        }

        /**
         *  Removes all whitespace characters from the beginning and end
         *  of each element in an Array, where the Array is stored as a String.
         *
         *  @param value The String whose whitespace should be trimmed.
         *
         *  @param separator The String that delimits each Array element in the string.
         *
         *  @return Updated String where whitespace was removed from the
         *  beginning and end of each element.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public static function trimArrayElements(value:String, delimiter:String):String
        {
            return StringTrimmer.trimArrayElements(value,delimiter);
        }

        /**
         *  Returns true if the specified string is
         *  a single space, tab, carriage return, newline, or formfeed character.
         *
         *  @param str The String that is is being queried.
         *
         *  @return true if the specified string is
         *  a single space, tab, carriage return, newline, or formfeed character.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public static function isWhitespace(character:String):Boolean
        {
            return StringTrimmer.isWhitespace(character);
        }

		/**
		 *  @private
		 *  Helper method used by restrict() to test each character
		 *  in the input string against the restriction string.
		 *  The logic in this method implements the same algorithm
		 *  as in TextField's 'restrict' property (which is quirky,
		 *  such as how it handles a '-' at the beginning of the
		 *  restriction string).
		 */
		private static function testCharacter(charCode:uint,
											  restrict:String):Boolean
		{
			var allowIt:Boolean = false;

			var inBackSlash:Boolean = false;
			var inRange:Boolean = false;
			var setFlag:Boolean = true;
			var lastCode:uint = 0;

			var n:int = restrict.length;
			var code:uint;

			if (n > 0)
			{
				code = restrict.charCodeAt(0);
				if (code == 94) // caret
					allowIt = true;
			}

			for (var i:int = 0; i < n; i++)
			{
				code = restrict.charCodeAt(i)

				var acceptCode:Boolean = false;
				if (!inBackSlash)
				{
					if (code == 45) // hyphen
						inRange = true;
					else if (code == 94) // caret
						setFlag = !setFlag;
					else if (code == 92) // backslash
						inBackSlash = true;
					else
						acceptCode = true;
				}
				else
				{
					acceptCode = true;
					inBackSlash = false;
				}

				if (acceptCode)
				{
					if (inRange)
					{
						if (lastCode <= charCode && charCode <= code)
							allowIt = setFlag;
						inRange = false;
						lastCode = 0;
					}
					else
					{
						if (charCode == code)
							allowIt = setFlag;
						lastCode = code;
					}
				}
			}

			return allowIt;
		}
	}
}

Make StringUtil not extend StringTrimmer, and delegate relevant methods instead.


package aerys.minko.render.shader.part.phong.attenuation
{
	import aerys.minko.render.material.phong.PhongProperties;
	import aerys.minko.render.shader.SFloat;
	import aerys.minko.render.shader.Shader;
	import aerys.minko.render.shader.part.phong.LightAwareShaderPart;
	import aerys.minko.type.enum.SamplerDimension;
	import aerys.minko.type.enum.SamplerFiltering;
	import aerys.minko.type.enum.SamplerMipMapping;
	import aerys.minko.type.enum.SamplerWrapping;

	public class CubeShadowMapAttenuationShaderPart extends LightAwareShaderPart implements IAttenuationShaderPart
	{
		private static const DEFAULT_BIAS : Number = 1 / 10000;

		public function CubeShadowMapAttenuationShaderPart(main : Shader)
		{
			super(main);
		}

		public function getAttenuation(lightId : uint) : SFloat
		{
			// retrieve shadow bias
			var shadowBias : SFloat;
			if (meshBindings.propertyExists(PhongProperties.SHADOW_BIAS))
				shadowBias = meshBindings.getParameter(PhongProperties.SHADOW_BIAS, 1);
			else if (sceneBindings.propertyExists(PhongProperties.SHADOW_BIAS))
				shadowBias = sceneBindings.getParameter(PhongProperties.SHADOW_BIAS, 1);
			else
				shadowBias = float(DEFAULT_BIAS);

			// retrieve depthmap, transformation matrix, zNear and zFar
			var worldToLight		: SFloat = getLightParameter(lightId, 'worldToLocal', 16);
			var zNear				: SFloat = getLightParameter(lightId, 'zNear', 1);
			var zFar				: SFloat = getLightParameter(lightId, 'zFar', 1);
			var cubeDepthMap		: SFloat = getLightTextureParameter(lightId, 'shadowMapCube',
				SamplerFiltering.NEAREST,
				SamplerMipMapping.DISABLE,
				SamplerWrapping.CLAMP,
				SamplerDimension.CUBE);

			// retrieve precompute depth
			var positionFromLight	: SFloat = interpolate(multiply4x4(vsWorldPosition, worldToLight));
			var precomputedDepth	: SFloat = unpack(sampleTexture(cubeDepthMap, positionFromLight));

			// retrieve real depth
			var currentDepth		: SFloat = divide(subtract(length(positionFromLight.xyz), zNear), subtract(zFar, zNear));
			currentDepth = min(subtract(1, shadowBias), currentDepth);

			return lessEqual(currentDepth, add(shadowBias, precomputedDepth));
		}
	}
}

package aerys.minko.render.shader.part.phong.attenuation
{
	import aerys.minko.render.material.phong.PhongProperties;
	import aerys.minko.render.shader.SFloat;
	import aerys.minko.render.shader.Shader;
	import aerys.minko.render.shader.part.phong.LightAwareShaderPart;
	import aerys.minko.type.enum.SamplerDimension;
	import aerys.minko.type.enum.SamplerFiltering;
	import aerys.minko.type.enum.SamplerMipMapping;
	import aerys.minko.type.enum.SamplerWrapping;

	public class CubeShadowMapAttenuationShaderPart extends LightAwareShaderPart implements IAttenuationShaderPart
	{
		private static const DEFAULT_BIAS : Number = 1 / 10000;

		public function CubeShadowMapAttenuationShaderPart(main : Shader)
		{
			super(main);
		}

		public function getAttenuation(lightId : uint) : SFloat
		{
			// retrieve shadow bias
			var shadowBias : SFloat;
			if (meshBindings.propertyExists(PhongProperties.SHADOW_BIAS))
				shadowBias = meshBindings.getParameter(PhongProperties.SHADOW_BIAS, 1);
			else if (sceneBindings.propertyExists(PhongProperties.SHADOW_BIAS))
				shadowBias = sceneBindings.getParameter(PhongProperties.SHADOW_BIAS, 1);
			else
				shadowBias = float(DEFAULT_BIAS);

			// retrieve depthmap, transformation matrix, zNear and zFar
			var worldToLight		: SFloat = getLightParameter(lightId, 'worldToLocal', 16);
			var zNear				: SFloat = getLightParameter(lightId, 'shadowZNear', 1);
			var zFar				: SFloat = getLightParameter(lightId, 'shadowZFar', 1);
			var cubeDepthMap		: SFloat = getLightTextureParameter(lightId, 'shadowMapCube',
				SamplerFiltering.NEAREST,
				SamplerMipMapping.DISABLE,
				SamplerWrapping.CLAMP,
				SamplerDimension.CUBE);

			// retrieve precompute depth
			var positionFromLight	: SFloat = interpolate(multiply4x4(vsWorldPosition, worldToLight));
			var precomputedDepth	: SFloat = unpack(sampleTexture(cubeDepthMap, positionFromLight));

			// retrieve real depth
			var currentDepth		: SFloat = divide(subtract(length(positionFromLight.xyz), zNear), subtract(zFar, zNear));
			currentDepth = min(subtract(1, shadowBias), currentDepth);

			return lessEqual(currentDepth, add(shadowBias, precomputedDepth));
		}
	}
}

fix broken references to the 'zFar' and 'zNear' light properties in CubeShadowMapAttenuationShaderPart


////////////////////////////////////////////////////////////////////////////////
//
//  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 org.apache.flex.utils
{

	/**
	 *  The StringTrimmer class is a collection of static functions that provide utility
	 *  features for trimming whitespace off Strings.
	 *
	 *  @langversion 3.0
	 *  @playerversion Flash 10.2
	 *  @playerversion AIR 2.6
	 *  @productversion FlexJS 0.0
	 */
	public class StringTrimmer
	{
		/**
		 * @private
		 */
		public function StringTrimmer()
		{
			throw new Error("StringTrimmer should not be instantiated.");
		}

        /**
         *  Removes all whitespace characters from the beginning and end
         *  of the specified string.
         *
         *  @param str The String whose whitespace should be trimmed.
         *
         *  @return Updated String where whitespace was removed from the
         *  beginning and end.
         *
		 *  @langversion 3.0
		 *  @playerversion Flash 10.2
		 *  @playerversion AIR 2.6
		 *  @productversion FlexJS 0.0
         */
        public static function trim(str:String):String
        {
            if (str == null) return '';

            var startIndex:int = 0;
            while (isWhitespace(str.charAt(startIndex)))
                ++startIndex;

            var endIndex:int = str.length - 1;
            while (isWhitespace(str.charAt(endIndex)))
                --endIndex;

            if (endIndex >= startIndex)
                return str.slice(startIndex, endIndex + 1);
            else
                return "";
        }

        /**
         *  Removes all whitespace characters from the beginning and end
         *  of each element in an Array, where the Array is stored as a String.
         *
         *  @param value The String whose whitespace should be trimmed.
         *
         *  @param separator The String that delimits each Array element in the string.
         *
         *  @return Array where whitespace was removed from the
         *  beginning and end of each element.
         *
		 *  @langversion 3.0
		 *  @playerversion Flash 10.2
		 *  @playerversion AIR 2.6
		 *  @productversion FlexJS 0.0
         */
        public static function splitAndTrim(value:String, delimiter:String):Array
        {
            if (value != "" && value != null)
            {
                var items:Array = value.split(delimiter);

                var len:int = items.length;
                for (var i:int = 0; i < len; i++)
                {
                    items[i] = StringTrimmer.trim(items[i]);
                }
                return items;
            }

            return [];
        }

        /**
         *  Removes all whitespace characters from the beginning and end
         *  of each element in an Array, where the Array is stored as a String.
         *
         *  @param value The String whose whitespace should be trimmed.
         *
         *  @param separator The String that delimits each Array element in the string.
         *
         *  @return Updated String where whitespace was removed from the
         *  beginning and end of each element.
         *
		 *  @langversion 3.0
		 *  @playerversion Flash 10.2
		 *  @playerversion AIR 2.6
		 *  @productversion FlexJS 0.0
         */
        public static function trimArrayElements(value:String, delimiter:String):String
        {
            if (value != "" && value != null)
            {
                var items:Array = splitAndTrim(value, delimiter);
                if (items.length > 0)
                {
                    value = items.join(delimiter);
                }
            }

            return value;
        }

        /**
         *  Returns true if the specified string is
         *  a single space, tab, carriage return, newline, or formfeed character.
         *
         *  @param str The String that is is being queried.
         *
         *  @return true if the specified string is
         *  a single space, tab, carriage return, newline, or formfeed character.
         *
		 *  @langversion 3.0
		 *  @playerversion Flash 10.2
		 *  @playerversion AIR 2.6
		 *  @productversion FlexJS 0.0
         */
        public static function isWhitespace(character:String):Boolean
        {
            switch (character)
            {
                case " ":
                case "\t":
                case "\r":
                case "\n":
                case "\f":
                    // non breaking space
                case "\u00A0":
                    // line seperator
                case "\u2028":
                    // paragraph seperator
                case "\u2029":
                    // ideographic space
                case "\u3000":
                    return true;

                default:
                    return false;
            }
        }

	}
}

////////////////////////////////////////////////////////////////////////////////
//
//  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 org.apache.flex.utils
{

	/**
	 *  The StringTrimmer class is a collection of static functions that provide utility
	 *  features for trimming whitespace off Strings.
	 *
	 *  @langversion 3.0
	 *  @playerversion Flash 10.2
	 *  @playerversion AIR 2.6
	 *  @productversion FlexJS 0.0
	 */
	public class StringTrimmer
	{
		/**
		 * @private
		 */
		public function StringTrimmer()
		{
			throw new Error("StringTrimmer should not be instantiated.");
		}

        /**
         *  Removes all whitespace characters from the beginning and end
         *  of the specified string.
         *
         *  @param str The String whose whitespace should be trimmed.
         *
         *  @return Updated String where whitespace was removed from the
         *  beginning and end.
         *
		 *  @langversion 3.0
		 *  @playerversion Flash 10.2
		 *  @playerversion AIR 2.6
		 *  @productversion FlexJS 0.0
         */
		COMPILE::SWF
        public static function trim(str:String):String
        {
            if (str == null) return '';

            var startIndex:int = 0;
            while (isWhitespace(str.charAt(startIndex)))
                ++startIndex;

            var endIndex:int = str.length - 1;
            while (isWhitespace(str.charAt(endIndex)))
                --endIndex;

            if (endIndex >= startIndex)
                return str.slice(startIndex, endIndex + 1);
            else
                return "";
        }

		COMPILE::JS
		public static function trim(str:String):String
		{
			if (str == null) return '';
			return str.trim();
		}

        /**
         *  Removes all whitespace characters from the beginning and end
         *  of each element in an Array, where the Array is stored as a String.
         *
         *  @param value The String whose whitespace should be trimmed.
         *
         *  @param separator The String that delimits each Array element in the string.
         *
         *  @return Array where whitespace was removed from the
         *  beginning and end of each element.
         *
		 *  @langversion 3.0
		 *  @playerversion Flash 10.2
		 *  @playerversion AIR 2.6
		 *  @productversion FlexJS 0.0
         */
        public static function splitAndTrim(value:String, delimiter:String):Array
        {
            if (value != "" && value != null)
            {
                var items:Array = value.split(delimiter);

                var len:int = items.length;
                for (var i:int = 0; i < len; i++)
                {
                    items[i] = StringTrimmer.trim(items[i]);
                }
                return items;
            }

            return [];
        }

        /**
         *  Removes all whitespace characters from the beginning and end
         *  of each element in an Array, where the Array is stored as a String.
         *
         *  @param value The String whose whitespace should be trimmed.
         *
         *  @param separator The String that delimits each Array element in the string.
         *
         *  @return Updated String where whitespace was removed from the
         *  beginning and end of each element.
         *
		 *  @langversion 3.0
		 *  @playerversion Flash 10.2
		 *  @playerversion AIR 2.6
		 *  @productversion FlexJS 0.0
         */
        public static function trimArrayElements(value:String, delimiter:String):String
        {
            if (value != "" && value != null)
            {
                var items:Array = splitAndTrim(value, delimiter);
                if (items.length > 0)
                {
                    value = items.join(delimiter);
                }
            }

            return value;
        }

        /**
         *  Returns true if the specified string is
         *  a single space, tab, carriage return, newline, or formfeed character.
         *
         *  @param str The String that is is being queried.
         *
         *  @return true if the specified string is
         *  a single space, tab, carriage return, newline, or formfeed character.
         *
		 *  @langversion 3.0
		 *  @playerversion Flash 10.2
		 *  @playerversion AIR 2.6
		 *  @productversion FlexJS 0.0
         */
        public static function isWhitespace(character:String):Boolean
        {
            switch (character)
            {
                case " ":
                case "\t":
                case "\r":
                case "\n":
                case "\f":
                    // non breaking space
                case "\u00A0":
                    // line seperator
                case "\u2028":
                    // paragraph seperator
                case "\u2029":
                    // ideographic space
                case "\u3000":
                    return true;

                default:
                    return false;
            }
        }

	}
}

Use native trim() method in JS

Use native trim() method in JS


package org.jbei.registry.utils
{
	import mx.collections.ArrayCollection;

	import org.jbei.bio.enzymes.RestrictionEnzyme;
	import org.jbei.registry.models.DNAFeature;
	import org.jbei.registry.models.FeaturedDNASequence;
	import org.jbei.registry.models.UserPreferences;
	import org.jbei.registry.models.UserRestrictionEnzymes;

    /**
     * @author Zinovii Dmytriv
     */
	public class StandaloneUtils
	{
		public static function standaloneSequence():FeaturedDNASequence {
			var sequence:FeaturedDNASequence = new FeaturedDNASequence();

            sequence.name = "pUC19"
			sequence.sequence = "tcgcgcgtttcggtgatgacggtgaaaacctctgacacatgcagctcccggagacggtcacagcttgtctgtaagcggatgccgggagcagacaagcccgtcagggcgcgtcagcgggtgttggcgggtgtcggggctggcttaactatgcggcatcagagcagattgtactgagagtgcaccatatgcggtgtgaaataccgcacagatgcgtaaggagaaaataccgcatcaggcgccattcgccattcaggctgcgcaactgttgggaagggcgatcggtgcgggcctcttcgctattacgccagctggcgaaagggggatgtgctgcaaggcgattaagttgggtaacgccagggttttcccagtcacgacgttgtaaaacgacggccagtgaattcgagctcggtacccggggatcctctagagtcgacctgcaggcatgcaagcttggcgtaatcatggtcatagctgtttcctgtgtgaaattgttatccgctcacaattccacacaacatacgagccggaagcataaagtgtaaagcctggggtgcctaatgagtgagctaactcacattaattgcgttgcgctcactgcccgctttccagtcgggaaacctgtcgtgccagctgcattaatgaatcggccaacgcgcggggagaggcggtttgcgtattgggcgctcttccgcttcctcgctcactgactcgctgcgctcggtcgttcggctgcggcgagcggtatcagctcactcaaaggcggtaatacggttatccacagaatcaggggataacgcaggaaagaacatgtgagcaaaaggccagcaaaaggccaggaaccgtaaaaaggccgcgttgctggcgtttttccataggctccgcccccctgacgagcatcacaaaaatcgacgctcaagtcagaggtggcgaaacccgacaggactataaagataccaggcgtttccccctggaagctccctcgtgcgctctcctgttccgaccctgccgcttaccggatacctgtccgcctttctcccttcgggaagcgtggcgctttctcatagctcacgctgtaggtatctcagttcggtgtaggtcgttcgctccaagctgggctgtgtgcacgaaccccccgttcagcccgaccgctgcgccttatccggtaactatcgtcttgagtccaacccggtaagacacgacttatcgccactggcagcagccactggtaacaggattagcagagcgaggtatgtaggcggtgctacagagttcttgaagtggtggcctaactacggctacactagaagaacagtatttggtatctgcgctctgctgaagccagttaccttcggaaaaagagttggtagctcttgatccggcaaacaaaccaccgctggtagcggtggtttttttgtttgcaagcagcagattacgcgcagaaaaaaaggatctcaagaagatcctttgatcttttctacggggtctgacgctcagtggaacgaaaactcacgttaagggattttggtcatgagattatcaaaaaggatcttcacctagatccttttaaattaaaaatgaagttttaaatcaatctaaagtatatatgagtaaacttggtctgacagttaccaatgcttaatcagtgaggcacctatctcagcgatctgtctatttcgttcatccatagttgcctgactccccgtcgtgtagataactacgatacgggagggcttaccatctggccccagtgctgcaatgataccgcgagacccacgctcaccggctccagatttatcagcaataaaccagccagccggaagggccgagcgcagaagtggtcctgcaactttatccgcctccatccagtctattaattgttgccgggaagctagagtaagtagttcgccagttaatagtttgcgcaacgttgttgccattgctacaggcatcgtggtgtcacgctcgtcgtttggtatggcttcattcagctccggttcccaacgatcaaggcgagttacatgatcccccatgttgtgcaaaaaagcggttagctccttcggtcctccgatcgttgtcagaagtaagttggccgcagtgttatcactcatggttatggcagcactgcataattctcttactgtcatgccatccgtaagatgcttttctgtgactggtgagtactcaaccaagtcattctgagaatagtgtatgcggcgaccgagttgctcttgcccggcgtcaatacgggataataccgcgccacatagcagaactttaaaagtgctcatcattggaaaacgttcttcggggcgaaaactctcaaggatcttaccgctgttgagatccagttcgatgtaacccactcgtgcacccaactgatcttcagcatcttttactttcaccagcgtttctgggtgagcaaaaacaggaaggcaaaatgccgcaaaaaagggaataagggcgacacggaaatgttgaatactcatactcttcctttttcaatattattgaagcatttatcagggttattgtctcatgagcggatacatatttgaatgtatttagaaaaataaacaaataggggttccgcgcacatttccccgaaaagtgccacctgacgtctaagaaaccattattatcatgacattaacctataaaaataggcgtatcacgaggccctttcgtc";
			sequence.features = new ArrayCollection();
			sequence.features.addItem(new DNAFeature(146, 469, -1, "lacZalpha", null, "CDS"));
			sequence.features.addItem(new DNAFeature(396, 452, -1, "multple cloning site", null, "misc_feature"));
			sequence.features.addItem(new DNAFeature(514, 519, -1, "Plac promoter", null, "-10_signal"));
			sequence.features.addItem(new DNAFeature(538, 543, -1, "Plac promoter", null, "-35_signal"));
			sequence.features.addItem(new DNAFeature(563, 575, -1, "CAP protein binding site", null, "protein_bind"));
			sequence.features.addItem(new DNAFeature(867, 1445, -1, "pMB1 origin of replication", null, "rep_origin"));
			sequence.features.addItem(new DNAFeature(876, 1419, -1, "RNAII transcript", null, "misc_RNA"));
			sequence.features.addItem(new DNAFeature(1273, 1278, 1, "RNAI promoter (clockwise); TTGAAG", null, "-35_signal"));
			sequence.features.addItem(new DNAFeature(1295, 1300, 1, "RNAI promoter (clockwise) GCTACA", null, "-10_signal"));
			sequence.features.addItem(new DNAFeature(1309, 1416, 1, "RNAI transcript", null, "misc_RNA"));
			sequence.features.addItem(new DNAFeature(1429, 1434, -1, "RNAII promoter", null, "-10_signal"));
			sequence.features.addItem(new DNAFeature(1450, 1455, -1, "RNAII promoter", null, "-35_signal"));
			sequence.features.addItem(new DNAFeature(1626, 2486, -1, "bla", null, "CDS"));
			sequence.features.addItem(new DNAFeature(2418, 2486, -1, "bla", null, "sig_peptide"));
			sequence.features.addItem(new DNAFeature(2530, 2535, -1, "bla promoter", null, "-10_signal"));
			sequence.features.addItem(new DNAFeature(2551, 2556, -1, "bla promoter", null, "-35_signal"));

            /*CONFIG::digestion {
                sequence.sequence = "CCTAATGAGTGAGCTAACTTACATTAATTGCGTTGCGCTCACTGCCCGGAATTCTTTCCAGTCGGGAAACCTGTCGTGCCAGCTGCATTAATGAATCGGCCAACGCGCGGGGAGAGGCGGTTTGCGTATTGGGCGCCAGGGTGGTTTTTCTTTTCACCAGTGAGACGGGCAACAGCTGATTGCCCTTCACCGCCTGGCCCTGAGAGAGTTGCAGCAAGCGGTCCACGCTGGTTTGCCCCAGCAGGCGAAAATCCTGTTTGATGGTGGTTAACGGCGGGATATAACATGAGCTGTCTTCGGTATCGTCGTATCCCACTACCGAGATGTCCGCACCAACGCGCAGCCCGGACTCGGTAATGGCGCGCATTGCGCCCAGCGCCATCTGATCGTTGGCAACCAGCATCGCAGTGGGAACGATGCCCTCATTCAGCATTTGCATGGTTTGTTGAAAACCGGACATGGCACTCCAGTCGCCTTCCCGTTCCGCTATCGGCTGAATTTGATTGCGAGTGAGATATTTATGCCAGCCAGCCAGACGCAGACGCGCCGAGACAGAACTTAATGGGCCCGCTAACAGCGCGATTTGCTGGTGACCCAATGCGACCAGATGCTCCACGCCCAGTCGCGTACCGTCTTCATGGGAGAAAATAATACTGTTGATGGGTGTCTGGTCAGAGACATCAAGAAATAACGCCGGAACATTAGTGCAGGCAGCTTCCACAGCAATGGCATCCTGGTCATCCAGCGGATAGTTAATGATCAGCCCACTGACGCGTTGCGCGAGAAGATTGTGCACCGCCGCTTTACAGGCTTCGACGCGCCAATCAGCAACGACTGTTTGCCCGCCAGTTGTTGTGCCACGCGGTTGGGAATGTAATTCAGCTCCGCCATCGCCGCTTCCACTTTTTCCCGCGTTTTCGCAGAAACGTGGCTGGCCTGGTTCACCACGCGGGAAACGGTCTGATAAGAGACACCGGCATACTCTGCGACATCGTATAACGTTACTGGTTTCACATTCACCACCCTGAATTGACTCTCTTCCGGGCGCTATCATGCCATACCGCGAAAGGTTTTGCGCCATTCGATGGTGTCCGGGATCTCGACGCTCTCCCTTATGCGACTCCTGCATTAGGAAGCAGCCCAGTAGTAGGTTGAGGCCGTTGAGCACCGCCGCCGCAAGGAATGGTGCATGCAAGGAAAGGCGATCGCGTTGCGTTGATGATGCCTAATTTATTGCAATATCCGGTGGCGCTGTTTGGCATTTTGCGTGCCGGGATGATCGTCGTAAACGTTAACCCGTTGTATACCCCGCGTGAGCTTGAGCATCAGCTTAACGATAGCGGCGCATCGGCGATTGTTATCGTGTCTAACTTTGCTCACACACTGGAAAAAGTGGTTGATAAAACCGCCGTTCAGCACGTAATTCTGACCCGTATGGGCGATCAGCTATCTACGGCAAAAGGCACGGTAGTCAATTTCGTTGTTAAATACATCAAGCGTTTGGTGCCGAAATACCATCTCGAGCTGCCAGATGCCATTTCATTTCGTAGCGCACTGCATAACGGCTACCGGATGCAGTACGTCAAACCCGAACTGGTGCCGGAAGATTTAGCTTTTCTGCAATACACCGGCGGCACCACTGGTGTGGCGAAAATCGGTTTGCCGGTGCCGTCGACGGAAGCCAAACTGGTGGATGATGATGATAATGAAGTACCACCAGGTCAACCGGGTGAGCTTTGTGTCAAAGGACCGCAGGTGATGCTGGGTTACTGGCAGCGTCCCGATGCTACCGATGAAATCATCAAAAATGGCTGGTTACACACCGGCGACCGGATATCAAAATCAATCCCTGTTCCACCATTCAACAATAAACTGAATGGGCTTTTTTGGGATGAAGATGAAGAGTTTGATTTAGGAGGAAACAGAATGCGCCCATTACATCCGATTGATTTTATATTCCTGTCACTAGAAAAAAGACAACAGCCTATGCATGTAGGTGGTTTATTTTTGTTTCAGATTCCTGATAACGCCCCAGACACCTTTATTCAGGATCTGGTGAATGATATCC";
                sequence.features = new ArrayCollection();
                sequence.features.addItem(new DNAFeature(1500, 1575, 1, "lacUV5 promoter", null, "promoter"));
                sequence.features.addItem(new DNAFeature(1516, 1579, 1, "lac operator", null, "misc_binding"));
                sequence.features.addItem(new DNAFeature(1595, 1614, 1, "RBS", null, "RBS"));
                sequence.features.addItem(new DNAFeature(1615, 1800, 1, "fadD", null, "CDS"));
                sequence.features.addItem(new DNAFeature(49, 1131, -1, "lacI", null, "CDS"));
            }*/

			return sequence;
		}

		public static function standaloneUserPreferences():UserPreferences
		{
			var userPreferences:UserPreferences = new UserPreferences();

			userPreferences.bpPerRow = -1;
			userPreferences.orfMinimumLength = 300;
			userPreferences.sequenceFontSize = 11;

			return userPreferences;
		}

		public static function standaloneUserRestrictionEnzymes():UserRestrictionEnzymes
		{
			return new UserRestrictionEnzymes();
		}
	}
}

package org.jbei.registry.utils
{
	import mx.collections.ArrayCollection;

	import org.jbei.bio.enzymes.RestrictionEnzyme;
	import org.jbei.registry.models.DNAFeature;
	import org.jbei.registry.models.FeaturedDNASequence;
	import org.jbei.registry.models.UserPreferences;
	import org.jbei.registry.models.UserRestrictionEnzymes;

    /**
     * @author Zinovii Dmytriv
     */
	public class StandaloneUtils
	{
		public static function standaloneSequence():FeaturedDNASequence {
			var sequence:FeaturedDNASequence = new FeaturedDNASequence();

            sequence.name = "pUC19"
			sequence.sequence = "tcgcgcgtttcggtgatgacggtgaaaacctctgacacatgcagctcccggagacggtcacagcttgtctgtaagcggatgccgggagcagacaagcccgtcagggcgcgtcagcgggtgttggcgggtgtcggggctggcttaactatgcggcatcagagcagattgtactgagagtgcaccatatgcggtgtgaaataccgcacagatgcgtaaggagaaaataccgcatcaggcgccattcgccattcaggctgcgcaactgttgggaagggcgatcggtgcgggcctcttcgctattacgccagctggcgaaagggggatgtgctgcaaggcgattaagttgggtaacgccagggttttcccagtcacgacgttgtaaaacgacggccagtgaattcgagctcggtacccggggatcctctagagtcgacctgcaggcatgcaagcttggcgtaatcatggtcatagctgtttcctgtgtgaaattgttatccgctcacaattccacacaacatacgagccggaagcataaagtgtaaagcctggggtgcctaatgagtgagctaactcacattaattgcgttgcgctcactgcccgctttccagtcgggaaacctgtcgtgccagctgcattaatgaatcggccaacgcgcggggagaggcggtttgcgtattgggcgctcttccgcttcctcgctcactgactcgctgcgctcggtcgttcggctgcggcgagcggtatcagctcactcaaaggcggtaatacggttatccacagaatcaggggataacgcaggaaagaacatgtgagcaaaaggccagcaaaaggccaggaaccgtaaaaaggccgcgttgctggcgtttttccataggctccgcccccctgacgagcatcacaaaaatcgacgctcaagtcagaggtggcgaaacccgacaggactataaagataccaggcgtttccccctggaagctccctcgtgcgctctcctgttccgaccctgccgcttaccggatacctgtccgcctttctcccttcgggaagcgtggcgctttctcatagctcacgctgtaggtatctcagttcggtgtaggtcgttcgctccaagctgggctgtgtgcacgaaccccccgttcagcccgaccgctgcgccttatccggtaactatcgtcttgagtccaacccggtaagacacgacttatcgccactggcagcagccactggtaacaggattagcagagcgaggtatgtaggcggtgctacagagttcttgaagtggtggcctaactacggctacactagaagaacagtatttggtatctgcgctctgctgaagccagttaccttcggaaaaagagttggtagctcttgatccggcaaacaaaccaccgctggtagcggtggtttttttgtttgcaagcagcagattacgcgcagaaaaaaaggatctcaagaagatcctttgatcttttctacggggtctgacgctcagtggaacgaaaactcacgttaagggattttggtcatgagattatcaaaaaggatcttcacctagatccttttaaattaaaaatgaagttttaaatcaatctaaagtatatatgagtaaacttggtctgacagttaccaatgcttaatcagtgaggcacctatctcagcgatctgtctatttcgttcatccatagttgcctgactccccgtcgtgtagataactacgatacgggagggcttaccatctggccccagtgctgcaatgataccgcgagacccacgctcaccggctccagatttatcagcaataaaccagccagccggaagggccgagcgcagaagtggtcctgcaactttatccgcctccatccagtctattaattgttgccgggaagctagagtaagtagttcgccagttaatagtttgcgcaacgttgttgccattgctacaggcatcgtggtgtcacgctcgtcgtttggtatggcttcattcagctccggttcccaacgatcaaggcgagttacatgatcccccatgttgtgcaaaaaagcggttagctccttcggtcctccgatcgttgtcagaagtaagttggccgcagtgttatcactcatggttatggcagcactgcataattctcttactgtcatgccatccgtaagatgcttttctgtgactggtgagtactcaaccaagtcattctgagaatagtgtatgcggcgaccgagttgctcttgcccggcgtcaatacgggataataccgcgccacatagcagaactttaaaagtgctcatcattggaaaacgttcttcggggcgaaaactctcaaggatcttaccgctgttgagatccagttcgatgtaacccactcgtgcacccaactgatcttcagcatcttttactttcaccagcgtttctgggtgagcaaaaacaggaaggcaaaatgccgcaaaaaagggaataagggcgacacggaaatgttgaatactcatactcttcctttttcaatattattgaagcatttatcagggttattgtctcatgagcggatacatatttgaatgtatttagaaaaataaacaaataggggttccgcgcacatttccccgaaaagtgccacctgacgtctaagaaaccattattatcatgacattaacctataaaaataggcgtatcacgaggccctttcgtc";
			sequence.features = new ArrayCollection();
			sequence.features.addItem(new DNAFeature(146, 469, -1, "lacZalpha", null, "CDS"));
			sequence.features.addItem(new DNAFeature(396, 452, -1, "multple cloning site", null, "misc_feature"));
			sequence.features.addItem(new DNAFeature(514, 519, -1, "Plac promoter", null, "-10_signal"));
			sequence.features.addItem(new DNAFeature(538, 543, -1, "Plac promoter", null, "-35_signal"));
			sequence.features.addItem(new DNAFeature(563, 575, -1, "CAP protein binding site", null, "protein_bind"));
			sequence.features.addItem(new DNAFeature(867, 1445, -1, "pMB1 origin of replication", null, "rep_origin"));
			sequence.features.addItem(new DNAFeature(876, 1419, -1, "RNAII transcript", null, "misc_RNA"));
			sequence.features.addItem(new DNAFeature(1273, 1278, 1, "RNAI promoter (clockwise); TTGAAG", null, "-35_signal"));
			sequence.features.addItem(new DNAFeature(1295, 1300, 1, "RNAI promoter (clockwise) GCTACA", null, "-10_signal"));
			sequence.features.addItem(new DNAFeature(1309, 1416, 1, "RNAI transcript", null, "misc_RNA"));
			sequence.features.addItem(new DNAFeature(1429, 1434, -1, "RNAII promoter", null, "-10_signal"));
			sequence.features.addItem(new DNAFeature(1450, 1455, -1, "RNAII promoter", null, "-35_signal"));
			sequence.features.addItem(new DNAFeature(1626, 2486, -1, "bla", null, "CDS"));
			sequence.features.addItem(new DNAFeature(2418, 2486, -1, "bla", null, "sig_peptide"));
			sequence.features.addItem(new DNAFeature(2530, 2535, -1, "bla promoter", null, "-10_signal"));
			sequence.features.addItem(new DNAFeature(2551, 2556, -1, "bla promoter", null, "-35_signal"));

            /*CONFIG::digestion {
                sequence.sequence = "CCTAATGAGTGAGCTAACTTACATTAATTGCGTTGCGCTCACTGCCCGGAATTCTTTCCAGTCGGGAAACCTGTCGTGCCAGCTGCATTAATGAATCGGCCAACGCGCGGGGAGAGGCGGTTTGCGTATTGGGCGCCAGGGTGGTTTTTCTTTTCACCAGTGAGACGGGCAACAGCTGATTGCCCTTCACCGCCTGGCCCTGAGAGAGTTGCAGCAAGCGGTCCACGCTGGTTTGCCCCAGCAGGCGAAAATCCTGTTTGATGGTGGTTAACGGCGGGATATAACATGAGCTGTCTTCGGTATCGTCGTATCCCACTACCGAGATGTCCGCACCAACGCGCAGCCCGGACTCGGTAATGGCGCGCATTGCGCCCAGCGCCATCTGATCGTTGGCAACCAGCATCGCAGTGGGAACGATGCCCTCATTCAGCATTTGCATGGTTTGTTGAAAACCGGACATGGCACTCCAGTCGCCTTCCCGTTCCGCTATCGGCTGAATTTGATTGCGAGTGAGATATTTATGCCAGCCAGCCAGACGCAGACGCGCCGAGACAGAACTTAATGGGCCCGCTAACAGCGCGATTTGCTGGTGACCCAATGCGACCAGATGCTCCACGCCCAGTCGCGTACCGTCTTCATGGGAGAAAATAATACTGTTGATGGGTGTCTGGTCAGAGACATCAAGAAATAACGCCGGAACATTAGTGCAGGCAGCTTCCACAGCAATGGCATCCTGGTCATCCAGCGGATAGTTAATGATCAGCCCACTGACGCGTTGCGCGAGAAGATTGTGCACCGCCGCTTTACAGGCTTCGACGCGCCAATCAGCAACGACTGTTTGCCCGCCAGTTGTTGTGCCACGCGGTTGGGAATGTAATTCAGCTCCGCCATCGCCGCTTCCACTTTTTCCCGCGTTTTCGCAGAAACGTGGCTGGCCTGGTTCACCACGCGGGAAACGGTCTGATAAGAGACACCGGCATACTCTGCGACATCGTATAACGTTACTGGTTTCACATTCACCACCCTGAATTGACTCTCTTCCGGGCGCTATCATGCCATACCGCGAAAGGTTTTGCGCCATTCGATGGTGTCCGGGATCTCGACGCTCTCCCTTATGCGACTCCTGCATTAGGAAGCAGCCCAGTAGTAGGTTGAGGCCGTTGAGCACCGCCGCCGCAAGGAATGGTGCATGCAAGGAAAGGCGATCGCGTTGCGTTGATGATGCCTAATTTATTGCAATATCCGGTGGCGCTGTTTGGCATTTTGCGTGCCGGGATGATCGTCGTAAACGTTAACCCGTTGTATACCCCGCGTGAGCTTGAGCATCAGCTTAACGATAGCGGCGCATCGGCGATTGTTATCGTGTCTAACTTTGCTCACACACTGGAAAAAGTGGTTGATAAAACCGCCGTTCAGCACGTAATTCTGACCCGTATGGGCGATCAGCTATCTACGGCAAAAGGCACGGTAGTCAATTTCGTTGTTAAATACATCAAGCGTTTGGTGCCGAAATACCATCTCGAGCTGCCAGATGCCATTTCATTTCGTAGCGCACTGCATAACGGCTACCGGATGCAGTACGTCAAACCCGAACTGGTGCCGGAAGATTTAGCTTTTCTGCAATACACCGGCGGCACCACTGGTGTGGCGAAAATCGGTTTGCCGGTGCCGTCGACGGAAGCCAAACTGGTGGATGATGATGATAATGAAGTACCACCAGGTCAACCGGGTGAGCTTTGTGTCAAAGGACCGCAGGTGATGCTGGGTTACTGGCAGCGTCCCGATGCTACCGATGAAATCATCAAAAATGGCTGGTTACACACCGGCGACCGGATATCAAAATCAATCCCTGTTCCACCATTCAACAATAAACTGAATGGGCTTTTTTGGGATGAAGATGAAGAGTTTGATTTAGGAGGAAACAGAATGCGCCCATTACATCCGATTGATTTTATATTCCTGTCACTAGAAAAAAGACAACAGCCTATGCATGTAGGTGGTTTATTTTTGTTTCAGATTCCTGATAACGCCCCAGACACCTTTATTCAGGATCTGGTGAATGATATCC";
                sequence.features = new ArrayCollection();
                sequence.features.addItem(new DNAFeature(1500, 1575, 1, "lacUV5 promoter", null, "promoter"));
                sequence.features.addItem(new DNAFeature(1516, 1579, 1, "lac operator", null, "misc_binding"));
                sequence.features.addItem(new DNAFeature(1595, 1614, 1, "RBS", null, "RBS"));
                sequence.features.addItem(new DNAFeature(1615, 1800, 1, "fadD", null, "CDS"));
                sequence.features.addItem(new DNAFeature(49, 1131, -1, "lacI", null, "CDS"));
            }*/

            sequence = new FeaturedDNASequence();
            sequence.features = new ArrayCollection();
            sequence.name = "unknown";

			return sequence;
		}

		public static function standaloneUserPreferences():UserPreferences
		{
			var userPreferences:UserPreferences = new UserPreferences();

			userPreferences.bpPerRow = -1;
			userPreferences.orfMinimumLength = 300;
			userPreferences.sequenceFontSize = 11;

			return userPreferences;
		}

		public static function standaloneUserRestrictionEnzymes():UserRestrictionEnzymes
		{
			return new UserRestrictionEnzymes();
		}
	}
}

clean standalone sequence

[VectorEditor] clean standalone sequence

git-svn-id: adbdea8fc1759bd16b0eaf24a244a7e5f870a654@261 fe3f0490-d73e-11de-a956-c71e7d3a9d2f


/*
Copyright 2009, Matthew Eernisse (mde@fleegix.org) and Slide, Inc.

 Licensed 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 org.windmill.astest {
  import org.windmill.WMLogger;
  import flash.utils.*;
  import flash.external.ExternalInterface;

  public class ASTest {
    // How long to wait between each test action
    private static const TEST_INTERVAL:int = 10;
    // List of all the test classes for this test run
    public static var testClassList:Array = [];
    // The complete list of all methods for each class
    // in this test run
    private static var testListComplete:Array = [];
    // Copy of the list of tests -- items are popped
    // of to run the tests
    private static var testList:Array = [];
    // The last test action -- used to do reporting on
    // success/failure of each test. Waits happen
    // async in a setTimeout loop, so reporting happens
    // for the *previous* test at the beginning of each
    // runNextTest call, before grabbing and running the
    // next test
    private static var previousTest:Object = null;
    // Error for the previous test if it was unsuccessful
    // Used in the reporting as described above
    public static var previousError:Object = false;
    // Tests are running or not
    public static var inProgress:Boolean = false;
    // In waiting mode, the runNextTest loop just idles
    public static var waiting:Boolean = false;

    public static function run(files:* = null):void {
      //['/flash/TestFoo.swf', '/flash/TestBar.swf']
      // If we're passed some files, load 'em up first
      // the loader will call back to this again when
      // it's done, with no args
      if (files) {
        // **** Ugly hack ****
        // -------------
        if (!(files is Array)) {
          // The files param passed in from XPCOM trusted JS
          // loses its Array-ness -- fails the 'is Array' test,
          // and has no 'length' property. It's just a generic
          // Object with integers for keys
          // In that case, reconstitute the Array by manually
          // stepping through it until we run out of items
          var filesTemp:Array = [];
          var incr:int = 0;
          var item:*;
          var keepGoing:Boolean = true;
          while (keepGoing) {
            item = files[incr];
            if (item) {
              filesTemp.push(item);
            }
            else {
              keepGoing = false;
            }
            incr++;
          }
          files = filesTemp;
        }
        // -------------
        ASTest.loadTestFiles(files);
        return;
      }
      ASTest.getCompleteListOfTests();
      ASTest.start();
    }

    public static function loadTestFiles(files:Array):void {
      // Clear out the list of tests before loading
      ASTest.testClassList = [];
      ASTest.testList = [];
      // Load the shit
      WMLoader.load(files);
    }

    public static function start():void {
      // Make a copy of the tests to work on
      ASTest.testList = ASTest.testListComplete.slice();
      ASTest.inProgress = true;
      // Run recursively in a setTimeout loop so
      // we can implement sleeps and waits
      ASTest.runNextTest();
    }

    public static function runNextTest():void {
      var test:Object = null;
      var res:*; // Result from ExternalInterface calls
      var data:Object;
      // If we're idling in a wait, just move along ...
      // Nothing to see here
      if (ASTest.waiting) {
        // Let's try again in a second or so
        setTimeout(function ():void {
          ASTest.runNextTest.call(ASTest);
        }, 1000);
        return;
      }
      // Do reporting for the previous test -- we do this here
      // because waits happen async in a setTimeout loop,
      // and we only know when it has finished by when the next
      // test actually starts
      if (ASTest.previousTest) {
        test = ASTest.previousTest;
        data = {
          test: {
            className: test.className,
            methodName: test.methodName
          },
          error: null
        };
        // Error
        if (ASTest.previousError) {
          data.error = ASTest.previousError;
          ASTest.previousError = null;
        }

        // Report via ExternalInterface, or log results
        res = ExternalInterface.call('wm_asTestResult', data);
        if (!res) {
          if (data.error) {
            WMLogger.log('FAILURE: ' + data.error.message);
          }
          else {
            WMLogger.log('SUCCESS');
          }
        }
        ASTest.previousTest = null;
      }

      // If we're out of tests, we're all done
      // TODO: Add some kind of final report
      if (ASTest.testList.length == 0) {
        ASTest.inProgress = false;
      }
      // If we still have tests to run, grab the next one
      // and run that bitch
      else {
        test = ASTest.testList.shift();
        // Save a ref to this test to use for reporting
        // at the beginning of the next call
        ASTest.previousTest = test;

        data = {
          test: {
            className: test.className,
            methodName: test.methodName
          }
        };
        res = ExternalInterface.call('wm_asTestStart', data);
        if (!res) {
          WMLogger.log('Running ' + test.className + '.' + test.methodName + ' ...');
        }

        // Run the test
        // -----------
        try {
          test.instance[test.methodName].call(test.instance);
        }
        catch (e:Error) {
          // Save a ref to the error to use for reporting
          // at the beginning of the next call
          ASTest.previousError = e;
        }

        // Recurse until done -- note this is not actually a
        // tail call because the setTimeout invokes the function
        // in the global execution context
        setTimeout(function ():void {
          ASTest.runNextTest.call(ASTest);
        }, ASTest.TEST_INTERVAL);
      }
    }

    public static function getCompleteListOfTests():void {
      var createTestItem:Function = function (item:Object,
          methodName:String):Object {
        return {
          methodName: methodName,
          instance: item.instance,
          className: item.className,
          classDescription: item.classDescription
        };
      }
      var testList:Array = [];
      // No args -- this is being re-invoked from WMLoader
      // now that we have our tests loaded
      for each (var item:Object in ASTest.testClassList) {
        var currTestList:Array = [];
        var descr:XML;
        var hasSetup:Boolean = false;
        var hasTeardown:Boolean = false;
        descr = flash.utils.describeType(
            item.classDescription);
        var meth:*;
        var methods:Object = {};
        for each (meth in descr..method) {
          var methodName:String = meth.@name.toXMLString();
          if (/^test/.test(methodName)) {
            methods[methodName] = item;
          }
          // If there's a setup or teardown somewhere in there
          // flag them so we can prepend/append after adding all
          // the tests
          if (methodName == 'setup') {
            hasSetup = true;
          }
          if (methodName == 'teardown') {
            hasTeardown = true;
          }
        }

        // Normal test methods
        // -----
        // If there's an 'order' array defined, run any tests
        // it contains in the defined order
        var key:String;
        if ('order' in item.instance) {
          for each (key in item.instance.order) {
            if (!key in methods) {
              throw new Error(key + ' is not a method in ' + item.className);
            }
            currTestList.push(createTestItem(methods[key], key));
            delete methods[key];
          }
        }
        // Run any other methods in whatever order
        for (key in methods) {
          currTestList.push(createTestItem(methods[key], key));
        }

        // Setup/teardown
        // -----
        // Prepend list with setup if one exists
        if (hasSetup) {
          currTestList.unshift(createTestItem(item, 'setup'));
        }
        // Append list with teardown if one exists
        if (hasTeardown) {
          currTestList.push(createTestItem(item, 'teardown'));
        }
        testList = testList.concat.apply(testList, currTestList);
      }
      ASTest.testListComplete = testList;
    }
  }
}

/*
Copyright 2009, Matthew Eernisse (mde@fleegix.org) and Slide, Inc.

 Licensed 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 org.windmill.astest {
  import org.windmill.WMLogger;
  import flash.utils.*;
  import flash.external.ExternalInterface;

  public class ASTest {
    // How long to wait between each test action
    private static const TEST_INTERVAL:int = 10;
    // List of all the test classes for this test run
    public static var testClassList:Array = [];
    // The complete list of all methods for each class
    // in this test run
    private static var testListComplete:Array = [];
    // Copy of the list of tests -- items are popped
    // of to run the tests
    private static var testList:Array = [];
    // The last test action -- used to do reporting on
    // success/failure of each test. Waits happen
    // async in a setTimeout loop, so reporting happens
    // for the *previous* test at the beginning of each
    // runNextTest call, before grabbing and running the
    // next test
    private static var previousTest:Object = null;
    // Error for the previous test if it was unsuccessful
    // Used in the reporting as described above
    public static var previousError:Object = false;
    // Tests are running or not
    public static var inProgress:Boolean = false;
    // In waiting mode, the runNextTest loop just idles
    public static var waiting:Boolean = false;

    public static function run(files:* = null):void {
      //['/flash/TestFoo.swf', '/flash/TestBar.swf']
      // If we're passed some files, load 'em up first
      // the loader will call back to this again when
      // it's done, with no args
      if (files) {
        // **** Ugly hack ****
        // -------------
        if (!(files is Array)) {
          // The files param passed in from XPCOM trusted JS
          // loses its Array-ness -- fails the 'is Array' test,
          // and has no 'length' property. It's just a generic
          // Object with integers for keys
          // In that case, reconstitute the Array by manually
          // stepping through it until we run out of items
          var filesTemp:Array = [];
          var incr:int = 0;
          var item:*;
          var keepGoing:Boolean = true;
          while (keepGoing) {
            item = files[incr];
            if (item) {
              filesTemp.push(item);
            }
            else {
              keepGoing = false;
            }
            incr++;
          }
          files = filesTemp;
        }
        // -------------
        ASTest.loadTestFiles(files);
        return;
      }
      ASTest.getCompleteListOfTests();
      ASTest.start();
    }

    public static function loadTestFiles(files:Array):void {
      // Clear out the list of tests before loading
      ASTest.testClassList = [];
      ASTest.testList = [];
      // Load the shit
      WMLoader.load(files);
    }

    public static function start():void {
      // Make a copy of the tests to work on
      ASTest.testList = ASTest.testListComplete.slice();
      ASTest.inProgress = true;
      // Run recursively in a setTimeout loop so
      // we can implement sleeps and waits
      ASTest.runNextTest();
    }

    public static function runNextTest():void {
      var test:Object = null;
      var res:*; // Result from ExternalInterface calls
      var data:Object;
      // If we're idling in a wait, just move along ...
      // Nothing to see here
      if (ASTest.waiting) {
        // Let's try again in a second or so
        setTimeout(function ():void {
          ASTest.runNextTest.call(ASTest);
        }, 1000);
        return;
      }
      // Do reporting for the previous test -- we do this here
      // because waits happen async in a setTimeout loop,
      // and we only know when it has finished by when the next
      // test actually starts
      if (ASTest.previousTest) {
        test = ASTest.previousTest;
        data = {
          test: {
            className: test.className,
            methodName: test.methodName
          },
          error: null
        };
        // Error
        if (ASTest.previousError) {
          data.error = ASTest.previousError;
          ASTest.previousError = null;
        }

        // Report via ExternalInterface, or log results
        res = ExternalInterface.call('wm_asTestResult', data);
        if (!res) {
          if (data.error) {
            WMLogger.log('FAILURE: ' + data.error.message);
          }
          else {
            WMLogger.log('SUCCESS');
          }
        }
        ASTest.previousTest = null;
      }

      // If we're out of tests, we're all done
      // TODO: Add some kind of final report
      if (ASTest.testList.length == 0) {
        ASTest.inProgress = false;
      }
      // If we still have tests to run, grab the next one
      // and run that bitch
      else {
        test = ASTest.testList.shift();
        // Save a ref to this test to use for reporting
        // at the beginning of the next call
        ASTest.previousTest = test;

        data = {
          test: {
            className: test.className,
            methodName: test.methodName
          }
        };
        res = ExternalInterface.call('wm_asTestStart', data);
        if (!res) {
          WMLogger.log('Running ' + test.className + '.' + test.methodName + ' ...');
        }

        // Run the test
        // -----------
        try {
          if (!(test.methodName in test.instance)) {
            throw new Error('"' + test.methodName +
                '" is not a valid method in' + test.instance.toString());
          }
          test.instance[test.methodName].call(test.instance);
        }
        catch (e:Error) {
          // Save a ref to the error to use for reporting
          // at the beginning of the next call
          ASTest.previousError = e;
        }

        // Recurse until done -- note this is not actually a
        // tail call because the setTimeout invokes the function
        // in the global execution context
        setTimeout(function ():void {
          ASTest.runNextTest.call(ASTest);
        }, ASTest.TEST_INTERVAL);
      }
    }

    public static function getCompleteListOfTests():void {
      var createTestItem:Function = function (item:Object,
          methodName:String):Object {
        return {
          methodName: methodName,
          instance: item.instance,
          className: item.className,
          classDescription: item.classDescription
        };
      }
      var testList:Array = [];
      // No args -- this is being re-invoked from WMLoader
      // now that we have our tests loaded
      for each (var item:Object in ASTest.testClassList) {
        var currTestList:Array = [];
        var descr:XML;
        var hasSetup:Boolean = false;
        var hasTeardown:Boolean = false;
        descr = flash.utils.describeType(
            item.classDescription);
        var meth:*;
        var methods:Object = {};
        for each (meth in descr..method) {
          var methodName:String = meth.@name.toXMLString();
          if (/^test/.test(methodName)) {
            methods[methodName] = item;
          }
          // If there's a setup or teardown somewhere in there
          // flag them so we can prepend/append after adding all
          // the tests
          if (methodName == 'setup') {
            hasSetup = true;
          }
          if (methodName == 'teardown') {
            hasTeardown = true;
          }
        }

        // Normal test methods
        // -----
        // If there's an 'order' array defined, run any tests
        // it contains in the defined order
        var key:String;
        if ('order' in item.instance) {
          for each (key in item.instance.order) {
            // If the item specified in the 'order' list is an actual
            // method, add it to the list -- if it doesn't actually exist
            // (e.g., if the method has been commented out), just ignore it
            if (key in methods) {
              currTestList.push(createTestItem(methods[key], key));
              delete methods[key];
            }
          }
        }
        // Run any other methods in whatever order
        for (key in methods) {
          currTestList.push(createTestItem(methods[key], key));
        }

        // Setup/teardown
        // -----
        // Prepend list with setup if one exists
        if (hasSetup) {
          currTestList.unshift(createTestItem(item, 'setup'));
        }
        // Append list with teardown if one exists
        if (hasTeardown) {
          currTestList.push(createTestItem(item, 'teardown'));
        }
        testList = testList.concat.apply(testList, currTestList);
      }
      ASTest.testListComplete = testList;
    }
  }
}

Check to make sure the method in the test-ordering actually, you know, exists, before trying to use it.


package stutter
{
	import org.flexunit.assertThat;
	import org.hamcrest.collection.array;
	import org.hamcrest.collection.emptyArray;
	import org.hamcrest.object.equalTo;
	import org.hamcrest.object.isFalse;
	import org.hamcrest.object.isTrue;

	public class StutterTest
	{
		private var runtime:StutterRunTime;
		private var reader:StutterReader;

		[Before]
		public function setup():void
		{
			runtime = new StutterRunTime();
			reader = new StutterReader();
		}

		[Test]
		public function math():void
		{
			assertThat('+', eval('(+ 2 3)'), equalTo(5));
			assertThat('-', eval('(- 2 3)'), equalTo(-1));
			assertThat('*', eval('(* 2 3)'), equalTo(6));
			assertThat('/', eval('(/ 6 2)'), equalTo(3));
		}

		[Test]
		public function lambdas():void
		{
			eval('(label second (quote (lambda (x) (car (cdr x)))))');

			assertThat(eval('(second (quote (1 2 3)))'), equalTo(2));
		}

		[Test]
		public function truth():void
		{
			assertThat(eval('t'), equalTo(TRUE));
		}

		[Test]
		public function falsey():void
		{
			assertThat(eval('nil'), equalTo(FALSE));
		}

		[Test]
		public function scoping():void
		{
			eval(<![CDATA[
(label test (quote (lambda (a b c)
					(+ a (* b c) 4)
				]]>.toString())

			assertThat(eval('(test 1 2 3)'), equalTo(11));
		}

		[Ignore]
		[Test]
		public function and_():void
		{
			eval(<![CDATA[
(label and (quote (lambda (and_x and_y)
             			  (if (eq and_x t)
             			  	  (if (eq and_y t) nil)
             			  	  nil))))
				]]>.toString());

			assertThat('true?', eval('(and (eq 2 2) (eq 3 3))'), equalTo(TRUE));
			assertThat('false?', eval('(and (eq 2 2) (eq 3 4))'), equalTo(FALSE));
		}

		private function eval(expression:String):*
		{
			return runtime.eval(reader.read(expression));
		}
	}
}

package stutter
{
	import org.flexunit.assertThat;
	import org.hamcrest.Matcher;
	import org.hamcrest.collection.array;
	import org.hamcrest.collection.emptyArray;
	import org.hamcrest.object.equalTo;
	import org.hamcrest.object.isFalse;
	import org.hamcrest.object.isTrue;

	public class StutterTest
	{
		private var runtime:StutterRunTime;
		private var reader:StutterReader;

		[Before]
		public function setup():void
		{
			runtime = new StutterRunTime();
			reader = new StutterReader();
		}

		private function eval(expression:String):*
		{
			reader.load(expression);

			var sexp:*;
			var result:*;

			while (reader.hasTokens() && (sexp = reader.parse()))
			{
				result = runtime.eval(sexp);
			}

			return result;
		}

		private function assert(expression:String, result:*):void
		{
			assertThat(expression, eval(expression), result is Matcher ? result : equalTo(result));
		}

		[Test]
		public function math():void
		{
			assertThat('+', eval('(+ 2 3)'), equalTo(5));
			assertThat('-', eval('(- 2 3)'), equalTo(-1));
			assertThat('*', eval('(* 2 3)'), equalTo(6));
			assertThat('/', eval('(/ 6 2)'), equalTo(3));
		}

		[Test]
		public function lambdas():void
		{
			eval('(label second (quote (lambda (x) (car (cdr x)))))');

			assertThat(eval('(second (quote (1 2 3)))'), equalTo(2));
		}

		[Test]
		public function truth():void
		{
			assertThat(eval('t'), equalTo(TRUE));
		}

		[Test]
		public function falsey():void
		{
			assertThat(eval('nil'), equalTo(FALSE));
		}

		[Test]
		public function scoping():void
		{
			eval(<![CDATA[
(label test (quote (lambda (a b c)
					(+ a (* b c) 4)
				]]>.toString())

			assertThat(eval('(test 1 2 3)'), equalTo(11));
		}

		[Ignore]
		[Test]
		public function and_():void
		{
			eval(<![CDATA[
(label and (quote (lambda (and_x and_y)
             			  (if (eq and_x t)
             			  	  (if (eq and_y t) nil)
             			  	  nil))))
				]]>.toString());

			assertThat('true?', eval('(and (eq 2 2) (eq 3 3))'), equalTo(TRUE));
			assertThat('false?', eval('(and (eq 2 2) (eq 3 4))'), equalTo(FALSE));
		}

		[Test]
		public function cond_():void
		{
			assert('(cond)', FALSE);
			assert('(cond (t 1))', 1);
			assert('(cond (nil 1) (t 2))', 2);
			assert('(cond (else 3))', 3);
			assert('(cond ((= 1 2) 3) (else 4))', 4);

			eval(<![CDATA[

				(label cond-test (quote (lambda (x)
					(cond ((= x 1) 1)
					  	  ((= x 2) 2)
					  	  ((= x 3) 3)))))

				]]>.toString());

			assert('(cond-test 3)', 3);
		}
	}
}

add cond tests

runtime: add cond tests


/******************************************************************************
 * LzText.as
 *****************************************************************************/

//* A_LZ_COPYRIGHT_BEGIN ******************************************************
//* Copyright 2001-2004 Laszlo Systems, Inc.  All Rights Reserved.            *
//* Use is subject to license terms.                                          *
//* A_LZ_COPYRIGHT_END ********************************************************

//=============================================================================
// DEFINE OBJECT: LzNewInputText
// This class is used for input text.
//
//=============================================================================
var LzInputText = Class ( "LzInputText" , LzText  );

// +++ Hey, are we still saying that input text is non- HTML ?
// If so then we need to override a number of methods in LzText which

LzInputText.prototype.defaultattrs.selectable = true;
LzInputText.prototype.defaultattrs.enabled = true;

//-----------------------------------------------------------------------------
// @keywords private
//-----------------------------------------------------------------------------
LzInputText.prototype.construct = function ( parent , args ){

    super.construct(  parent , args );

    var mc = this.__LZtextclip;

    // We do not support html in input fields.
    if (this.enabled) {
        mc.type = 'input';
    } else {
        mc.type = 'dynamic';
    }

    // set a pointer back to this view from the TextField object
    this.__LZtextclip.__lzview = this;
    mc.onSetFocus = TextField.prototype.__gotFocus;
    mc.onKillFocus = TextField.prototype.__lostFocus;
    mc.onChanged = TextField.prototype.__onChanged;

    // handle onkeydown events

    this.onfocusDel = new _root.LzDelegate( this , "handleOnFocus" , this ,
                                            "onfocus" );
    this.onblurDel = new _root.LzDelegate( this , "handleOnBlur" , this ,
                                            "onblur" );

    this.hasFocus = false;

}

// [hqm]??? what did this do?
//Object.class.extends( LzText, LzInputText );

LzInputText.prototype.focusable = true;

//-----------------------------------------------------------------------------
// @keywords private
//-----------------------------------------------------------------------------
LzInputText.prototype.handleOnFocus = function (  ){
    if ( this.hasFocus ) { return; }
    var sf = targetPath(this.__LZtextclip);

    // calling setFocus() seems to bash the scroll value, so save it
    var myscroll = this.__LZtextclip.scroll;
    if( Selection.getFocus() != sf ) {
        Selection.setFocus( sf );
    }
    this.__LZtextclip.hscroll = 0;
    // restore the scroll value
    this.__LZtextclip.scroll = myscroll;
    this.hasFocus = true;
    this.__LZtextclip.background = false;
}

//-----------------------------------------------------------------------------
// @keywords private
//-----------------------------------------------------------------------------
LzInputText.prototype.handleOnBlur = function (  ){
    this.hasFocus = false;
    var sf =  targetPath(this.__LZtextclip);
    if( Selection.getFocus() == sf ) {
        Selection.setFocus( null );
    }
}

//-----------------------------------------------------------------------------
// Register for update on every frame when the text field gets the focus.
// Set the behavior of the enter key depending on whether the field is
// multiline or not.
//
// @keywords private
//-----------------------------------------------------------------------------
TextField.prototype.__gotFocus = function ( oldfocus ){
    // scroll text fields horizontally back to start
    if (!(LzFocus.getFocus() == this.__lzview)) {
        var tabdown = LzKeys.isKeyDown('tab');
        _root.LzFocus.setFocus(this.__lzview, tabdown);
    }
}

//-----------------------------------------------------------------------------
// Register to be called when the text field is modified. Convert this
// into a LFC ontext event.
// @keywords private
//-----------------------------------------------------------------------------
TextField.prototype.__onChanged = function ( ){
    //this.__lzview.setText(this.text);
    this.__lzview.ontext.sendEvent( );
}

//-----------------------------------------------------------------------------
// @keywords private
//-----------------------------------------------------------------------------
TextField.prototype.__lostFocus = function ( ){
    if (this['__handlelostFocusdel'] == null) this.__handlelostFocusdel = new LzDelegate(this, "__handlelostFocus");
    _root.LzIdle.callOnIdle(this.__handlelostFocusdel);
}

//-----------------------------------------------------------------------------
// must be called after an idle event to prevent the selection from being
// cleared prematurely, e.g. before a button click.  If the selection is
// cleared, the button doesn't send mouse events.
// @keywords private
//-----------------------------------------------------------------------------
TextField.prototype.__handlelostFocus = function ( ){
    //_root.Debug.write('lostfocus', this.__lzview.hasFocus, dunno, LzFocus.lastfocus, this, LzFocus.getFocus(), this.__lzview);
    if (this.__lzview.hasFocus) LzFocus.clearFocus();
}

//------------------------------------------------------------------------------
// Retrieves the contents of the text field for use by a datapath. See
// LzDatapath.updateData for more on this.
// @keywords protected
//------------------------------------------------------------------------------
LzInputText.prototype.updateData = function (){
    return this.__LZtextclip.text;
}

//------------------------------------------------------------------------------
// Sets whether user can modify input text field
// @param Boolean enabled: true if the text field can be edited
//------------------------------------------------------------------------------
LzInputText.prototype.setEnabled = function (enabled){
    var mc = this.__LZtextclip;
    this.enabled = enabled;
    if (enabled) {
        mc.type = 'input';
    } else {
        mc.type = 'dynamic';
    }
}

//---
//@keywords private
//---
LzInputText.prototype.setters.enabled = "setEnabled";

//-----------------------------------------------------------------------------
// @keywords private
//-----------------------------------------------------------------------------
LzInputText.prototype.getText = function ( ){
    return this.__LZtextclip.text;
}

LzInputText.prototype.getText.dependencies = function ( who , self){
      return [ self , "text" ];
}

//-----------------------------------------------------------------------------
// Set the html flag on this text view
//-----------------------------------------------------------------------------
LzInputText.prototype.setHTML = function (htmlp) {
    this.__LZtextclip.html = htmlp;
}

//-----------------------------------------------------------------------------
// setText sets the text of the field to display
//
// @param String t: the string to which to set the text
//-----------------------------------------------------------------------------
LzInputText.prototype.setText = function ( t ){
    if (typeof(t) == 'undefined' || t == null) {
        t = "";
    } else if (typeof(t) != "string") {
        t = t.toString();
    }

    this.text =  t;// this.format + t if proper measurement were working
    var mc = this.__LZtextclip;

    // these must be done in this order, to get Flash to take the HTML styling
    // but not to ignore CR linebreak chars that might be in the string.
    if (mc.html) {
        mc.htmlText = this.format;
    }
    mc.text = t;

    if (this.resize && (this.multiline == false)) {
        // single line resizable fields adjust their width to match the text
        this.setWidth(this.getTextWidth());
    }

    //multiline resizable fields adjust their height
    if (this.multiline && this.sizeToHeight) {
        this.setHeight(mc._height);
    }

    if (this.multiline && this.scroll == 0 ) {
        var scrolldel = new LzDelegate(this, "__LZforceScrollAttrs");
        _root.LzIdle.callOnIdle(scrolldel);
    }

    //@event ontext: Sent whenever the text in the field changes.
    this.ontext.sendEvent( );
}

/******************************************************************************
 * LzText.as
 *****************************************************************************/

//* A_LZ_COPYRIGHT_BEGIN ******************************************************
//* Copyright 2001-2007 Laszlo Systems, Inc.  All Rights Reserved.            *
//* Use is subject to license terms.                                          *
//* A_LZ_COPYRIGHT_END ********************************************************

//=============================================================================
// DEFINE OBJECT: LzNewInputText
// This class is used for input text.
//
//=============================================================================
var LzInputText = Class ( "LzInputText" , LzText  );

// +++ Hey, are we still saying that input text is non- HTML ?
// If so then we need to override a number of methods in LzText which

LzInputText.prototype.defaultattrs.selectable = true;
LzInputText.prototype.defaultattrs.enabled = true;

//-----------------------------------------------------------------------------
// @keywords private
//-----------------------------------------------------------------------------
LzInputText.prototype.construct = function ( parent , args ){

    super.construct(  parent , args );

    var mc = this.__LZtextclip;

    // We do not support html in input fields.
    if (this.enabled) {
        mc.type = 'input';
    } else {
        mc.type = 'dynamic';
    }

    // set a pointer back to this view from the TextField object
    this.__LZtextclip.__lzview = this;
    mc.onSetFocus = TextField.prototype.__gotFocus;
    mc.onKillFocus = TextField.prototype.__lostFocus;
    mc.onChanged = TextField.prototype.__onChanged;

    // handle onkeydown events

    this.onfocusDel = new _root.LzDelegate( this , "handleOnFocus" , this ,
                                            "onfocus" );
    this.onblurDel = new _root.LzDelegate( this , "handleOnBlur" , this ,
                                            "onblur" );

    this.hasFocus = false;

}

// [hqm]??? what did this do?
//Object.class.extends( LzText, LzInputText );

LzInputText.prototype.focusable = true;

//-----------------------------------------------------------------------------
// @keywords private
//-----------------------------------------------------------------------------
LzInputText.prototype.handleOnFocus = function (  ){
    if ( this.hasFocus ) { return; }
    var sf = targetPath(this.__LZtextclip);

    // calling setFocus() seems to bash the scroll value, so save it
    var myscroll = this.__LZtextclip.scroll;
    if( Selection.getFocus() != sf ) {
        Selection.setFocus( sf );
    }
    this.__LZtextclip.hscroll = 0;
    // restore the scroll value
    this.__LZtextclip.scroll = myscroll;
    this.hasFocus = true;
    this.__LZtextclip.background = false;
}

//-----------------------------------------------------------------------------
// @keywords private
//-----------------------------------------------------------------------------
LzInputText.prototype.handleOnBlur = function (  ){
    this.hasFocus = false;
    var sf =  targetPath(this.__LZtextclip);
    if( Selection.getFocus() == sf ) {
        Selection.setFocus( null );
    }
}

//-----------------------------------------------------------------------------
// Register for update on every frame when the text field gets the focus.
// Set the behavior of the enter key depending on whether the field is
// multiline or not.
//
// @keywords private
//-----------------------------------------------------------------------------
TextField.prototype.__gotFocus = function ( oldfocus ){
    // scroll text fields horizontally back to start
    if (!(LzFocus.getFocus() == this.__lzview)) {
        var tabdown = LzKeys.isKeyDown('tab');
        _root.LzFocus.setFocus(this.__lzview, tabdown);
    }
}

//-----------------------------------------------------------------------------
// Register to be called when the text field is modified. Convert this
// into a LFC ontext event.
// @keywords private
//-----------------------------------------------------------------------------
TextField.prototype.__onChanged = function ( ){
    //this.__lzview.setText(this.text);

    //multiline resizable fields adjust their height
    if ( this.__lzview.multiline &&
         this.__lzview.sizeToHeight &&
         this.__lzview.height != this._height ) {
        this.__lzview.setHeight(this._height);
    }
    this.__lzview.ontext.sendEvent( );
}

//-----------------------------------------------------------------------------
// @keywords private
//-----------------------------------------------------------------------------
TextField.prototype.__lostFocus = function ( ){
    if (this['__handlelostFocusdel'] == null) this.__handlelostFocusdel = new LzDelegate(this, "__handlelostFocus");
    _root.LzIdle.callOnIdle(this.__handlelostFocusdel);
}

//-----------------------------------------------------------------------------
// must be called after an idle event to prevent the selection from being
// cleared prematurely, e.g. before a button click.  If the selection is
// cleared, the button doesn't send mouse events.
// @keywords private
//-----------------------------------------------------------------------------
TextField.prototype.__handlelostFocus = function ( ){
    //_root.Debug.write('lostfocus', this.__lzview.hasFocus, dunno, LzFocus.lastfocus, this, LzFocus.getFocus(), this.__lzview);
    if (this.__lzview.hasFocus) LzFocus.clearFocus();
}

//------------------------------------------------------------------------------
// Retrieves the contents of the text field for use by a datapath. See
// LzDatapath.updateData for more on this.
// @keywords protected
//------------------------------------------------------------------------------
LzInputText.prototype.updateData = function (){
    return this.__LZtextclip.text;
}

//------------------------------------------------------------------------------
// Sets whether user can modify input text field
// @param Boolean enabled: true if the text field can be edited
//------------------------------------------------------------------------------
LzInputText.prototype.setEnabled = function (enabled){
    var mc = this.__LZtextclip;
    this.enabled = enabled;
    if (enabled) {
        mc.type = 'input';
    } else {
        mc.type = 'dynamic';
    }
}

//---
//@keywords private
//---
LzInputText.prototype.setters.enabled = "setEnabled";

//-----------------------------------------------------------------------------
// @keywords private
//-----------------------------------------------------------------------------
LzInputText.prototype.getText = function ( ){
    return this.__LZtextclip.text;
}

LzInputText.prototype.getText.dependencies = function ( who , self){
      return [ self , "text" ];
}

//-----------------------------------------------------------------------------
// Set the html flag on this text view
//-----------------------------------------------------------------------------
LzInputText.prototype.setHTML = function (htmlp) {
    this.__LZtextclip.html = htmlp;
}

//-----------------------------------------------------------------------------
// setText sets the text of the field to display
//
// @param String t: the string to which to set the text
//-----------------------------------------------------------------------------
LzInputText.prototype.setText = function ( t ){
    if (typeof(t) == 'undefined' || t == null) {
        t = "";
    } else if (typeof(t) != "string") {
        t = t.toString();
    }

    this.text =  t;// this.format + t if proper measurement were working
    var mc = this.__LZtextclip;

    // these must be done in this order, to get Flash to take the HTML styling
    // but not to ignore CR linebreak chars that might be in the string.
    if (mc.html) {
        mc.htmlText = this.format;
    }
    mc.text = t;

    if (this.resize && (this.multiline == false)) {
        // single line resizable fields adjust their width to match the text
        this.setWidth(this.getTextWidth());
    }

    //multiline resizable fields adjust their height
    if (this.multiline && this.sizeToHeight) {
        this.setHeight(mc._height);
    }

    if (this.multiline && this.scroll == 0 ) {
        var scrolldel = new LzDelegate(this, "__LZforceScrollAttrs");
        _root.LzIdle.callOnIdle(scrolldel);
    }

    //@event ontext: Sent whenever the text in the field changes.
    this.ontext.sendEvent( );
}

Summary: Fix height resizing for multiline text fields

New Features:

Bugs Fixed: N/A

Technical Reviewer: max
QA Reviewer: pablo
Doc Reviewer: n/a

Documentation:

Release Notes:

Details: Multiline inputtext fields don't resize their height as they wrap
while the user is inputting text. There needs to be code to update the view
height when the text changes

Tests: See attached

git-svn-id: d62bde4b5aa582fdf07c8d403e53e0399a7ed285@3501 fa20e4f9-1d0a-0410-b5f3-dc9c16b8b17c