Looks like some nice new capabilities for ArrayUtil and ObjectUtil.  Did
you rule out using describeType for isDynamicObject?  I know it is slow,
but it should always be right.  What should isDynamicObject return for
XML, Proxy and ObjectProxy?

Thanks,
-Alex

On 2/17/16, 8:00 AM, "mih...@apache.org" <mih...@apache.org> wrote:

>FLEX-35031
>-Since I'm planning to use ObjectUtil.isDynamicObject() in the fix, I
>wanted to unit test it.
>-Also, I introduced a new function in ObjectUtil to be used in the
>solution, getEnumerableProperties(), which returns all the dynamic
>properties of an object. In order to unit test this new method I needed a
>function with which to compare Arrays. So I added it to ArrayUtil,
>including the unit tests needed to validate it.
>-Also edited an asdoc entry and renamed a function parameter.
>
>
>Project: http://git-wip-us.apache.org/repos/asf/flex-sdk/repo
>Commit: http://git-wip-us.apache.org/repos/asf/flex-sdk/commit/680b405d
>Tree: http://git-wip-us.apache.org/repos/asf/flex-sdk/tree/680b405d
>Diff: http://git-wip-us.apache.org/repos/asf/flex-sdk/diff/680b405d
>
>Branch: refs/heads/develop
>Commit: 680b405dfc4559ecf81239352b5bd9676d00adc8
>Parents: e68c148
>Author: Mihai Chira <mih...@apache.org>
>Authored: Wed Feb 17 13:35:31 2016 +0100
>Committer: Mihai Chira <mih...@apache.org>
>Committed: Wed Feb 17 13:35:31 2016 +0100
>
>----------------------------------------------------------------------
> .../framework/src/mx/utils/ArrayUtil.as         |  92 ++++++
> .../framework/src/mx/utils/ObjectUtil.as        |  33 ++-
> .../framework/tests/mx/utils/ArrayUtil_Tests.as | 293 +++++++++++++++++++
> .../tests/mx/utils/ObjectUtil_Tests.as          | 167 +++++++++++
> 4 files changed, 581 insertions(+), 4 deletions(-)
>----------------------------------------------------------------------
>
>
>http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/680b405d/frameworks/p
>rojects/framework/src/mx/utils/ArrayUtil.as
>----------------------------------------------------------------------
>diff --git a/frameworks/projects/framework/src/mx/utils/ArrayUtil.as
>b/frameworks/projects/framework/src/mx/utils/ArrayUtil.as
>index c41cccf..85ec79c 100644
>--- a/frameworks/projects/framework/src/mx/utils/ArrayUtil.as
>+++ b/frameworks/projects/framework/src/mx/utils/ArrayUtil.as
>@@ -107,6 +107,98 @@ public class ArrayUtil
> 
>         return -1;
>     }
>+
>+    /**
>+     *  Checks if the Array instances contain the same values
>+     *  against the same indexes.
>+     *
>+     *  @param a The first Array instance.
>+     *  @param b The second Array instance.
>+     *  @return true if the two Arrays contain the same values
>+     *  (determined using the strict equality operator) associated
>+     *  with the same indexes.
>+     *
>+     *  @langversion 3.0
>+     *  @playerversion Flash 9
>+     *  @playerversion AIR 1.1
>+     *  @productversion Flex 3
>+     */
>+    public static function arraysMatch(a:Array, b:Array):Boolean
>+    {
>+        if(!a || !b)
>+            return false;
>+
>+        if(a.length != b.length)
>+            return false;
>+
>+        var indexesA:Array = ObjectUtil.getEnumerableProperties(a);
>+
>+        for (var i:int = 0; i < indexesA.length; i++)
>+        {
>+            var index:String = indexesA[i];
>+
>+            if(!b.hasOwnProperty(index) || a[index] !== b[index])
>+                return false;
>+        }
>+
>+        return true;
>+    }
>+
>+    /**
>+     *  Checks if the Array instances contain the same values,
>+     *  even if in different orders.
>+     *
>+     *  @param a The first Array instance.
>+     *  @param b The second Array instance.
>+     *  @return true if the two Arrays contain the same values.
>+     *
>+     *  @langversion 3.0
>+     *  @playerversion Flash 9
>+     *  @playerversion AIR 1.1
>+     *  @productversion Flex 3
>+     */
>+    public static function arrayValuesMatch(a:Array, b:Array):Boolean
>+    {
>+        if(!a || !b)
>+            return false;
>+
>+        var valuesOfA:Array = getArrayValues(a);
>+        valuesOfA.sort();
>+
>+        var valuesOfB:Array = getArrayValues(b);
>+        valuesOfB.sort();
>+
>+        return arraysMatch(valuesOfA, valuesOfB);
>+    }
>+
>+    /**
>+     *  Used to obtain the values in an Array, whether indexed
>+     *  or associative.
>+     *
>+     *  @param value The Array instance.
>+     *  @return an indexed Array with the values found in
><code>value</code>.
>+     *
>+     *  @langversion 3.0
>+     *  @playerversion Flash 9
>+     *  @playerversion AIR 1.1
>+     *  @productversion Flex 3
>+     */
>+    public static function getArrayValues(value:Array):Array
>+    {
>+        var result:Array = [];
>+
>+        if(!value)
>+            return result;
>+
>+        var indexes:Array = ObjectUtil.getEnumerableProperties(value);
>+
>+        for each(var index:String in indexes)
>+        {
>+            result.push(value[index]);
>+        }
>+
>+        return result;
>+    }
> }
> 
> }
>
>http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/680b405d/frameworks/p
>rojects/framework/src/mx/utils/ObjectUtil.as
>----------------------------------------------------------------------
>diff --git a/frameworks/projects/framework/src/mx/utils/ObjectUtil.as
>b/frameworks/projects/framework/src/mx/utils/ObjectUtil.as
>index 6b1e79a..b1f23cc 100644
>--- a/frameworks/projects/framework/src/mx/utils/ObjectUtil.as
>+++ b/frameworks/projects/framework/src/mx/utils/ObjectUtil.as
>@@ -1173,7 +1173,7 @@ public class ObjectUtil
>     /**
>      *  Returns <code>true</code> if the object is an instance of a
>dynamic class.
>      *
>-     *  @param obj The object.
>+     *  @param object The object.
>      *
>      *  @return <code>true</code> if the object is an instance of a
>dynamic class.
>      *  
>@@ -1182,24 +1182,49 @@ public class ObjectUtil
>      *  @playerversion AIR 1.1
>      *  @productversion Flex 3
>      */
>-    public static function isDynamicObject(obj:Object):Boolean
>+    public static function isDynamicObject(object:Object):Boolean
>     {
>         try
>         {
>             // this test for checking whether an object is dynamic or
>not is 
>             // pretty hacky, but it assumes that no-one actually has a
>             // property defined called "wootHackwoot"
>-            obj["wootHackwoot"];
>+            object["wootHackwoot"];
>         }
>         catch (e:Error)
>         {
>-            // our object isn't from a dynamic class
>+            // our object isn't an instance of a dynamic class
>             return false;
>         }
>         return true;
>     }
> 
>     /**
>+     *  Returns all the properties defined dynamically on an object.
>+     *
>+     *  @param object The object to inspect.
>+     *
>+     *  @return an <code>Array</code> of the enumerable properties of
>the object.
>+     *
>+     *  @langversion 3.0
>+     *  @playerversion Flash 9
>+     *  @playerversion AIR 1.1
>+     *  @productversion Flex 3
>+     */
>+    public static function getEnumerableProperties(object:Object):Array
>+    {
>+        var result:Array = [];
>+
>+        if(!isDynamicObject(object))
>+            return result;
>+
>+        for (var property:String in object)
>+            result.push(property);
>+
>+        return result;
>+    }
>+
>+    /**
>      *  Returns the value at the end of the property chain
><code>path</code>.
>      *  If the value cannot be reached due to null links on the chain,
>      *  <code>undefined</code> is returned.
>
>http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/680b405d/frameworks/p
>rojects/framework/tests/mx/utils/ArrayUtil_Tests.as
>----------------------------------------------------------------------
>diff --git 
>a/frameworks/projects/framework/tests/mx/utils/ArrayUtil_Tests.as
>b/frameworks/projects/framework/tests/mx/utils/ArrayUtil_Tests.as
>new file mode 100644
>index 0000000..d11f468
>--- /dev/null
>+++ b/frameworks/projects/framework/tests/mx/utils/ArrayUtil_Tests.as
>@@ -0,0 +1,293 @@
>+/////////////////////////////////////////////////////////////////////////
>///////
>+//
>+//  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 mx.utils
>+{
>+    import org.flexunit.asserts.assertEquals;
>+    import org.flexunit.asserts.assertFalse;
>+    import org.flexunit.asserts.assertNotNull;
>+    import org.flexunit.asserts.assertTrue;
>+
>+    public class ArrayUtil_Tests
>+    {
>+        
>//------------------------------------------------------------------------
>--
>+        //
>+        //  arraysMatch()
>+        //
>+        
>//------------------------------------------------------------------------
>--
>+
>+        [Test]
>+        public function test_array_matches_with_itself():void
>+        {
>+            //given
>+            var array:Array = [1, 2, 3];
>+
>+            //then
>+            assertTrue(ArrayUtil.arraysMatch(array, array));
>+        }
>+
>+        [Test]
>+        public function test_empty_arrays_match():void
>+        {
>+            //then
>+            assertTrue(ArrayUtil.arraysMatch([], []));
>+        }
>+
>+        [Test]
>+        public function
>test_arrays_with_same_values_in_different_indexes_dont_match():void
>+        {
>+            //then
>+            assertFalse(ArrayUtil.arraysMatch(["name", "age"], ["age",
>"name"]));
>+        }
>+
>+        [Test]
>+        public function
>test_arrays_match_when_properties_created_in_different_orders():void
>+        {
>+            //given
>+            var arrayA:Array = [];
>+            var arrayB:Array = [];
>+
>+            //when
>+            arrayA["name"] = "AName";
>+            arrayA["age"] = 22;
>+
>+            arrayB["age"] = 22;
>+            arrayB["name"] = "AName";
>+
>+            //then
>+            assertTrue(ArrayUtil.arraysMatch(arrayA, arrayB));
>+        }
>+
>+        [Test]
>+        public function
>test_arrays_dont_match_when_indexes_match_but_values_different():void
>+        {
>+            //given
>+            var arrayA:Array = [];
>+            var arrayB:Array = [];
>+
>+            //when
>+            arrayA["name"] = "AName";
>+            arrayA["age"] = 444;
>+
>+            arrayB["age"] = 22;
>+            arrayB["name"] = "BName";
>+
>+            //then
>+            assertFalse(ArrayUtil.arraysMatch(arrayA, arrayB));
>+        }
>+
>+        [Test]
>+        public function
>test_arrays_dont_match_when_they_have_same_number_of_different_indexes():v
>oid
>+        {
>+            //given
>+            var arrayA:Array = [];
>+            var arrayB:Array = [];
>+
>+            //when
>+            arrayA["name"] = "AName";
>+            arrayA["age"] = 444;
>+
>+            arrayB["radius"] = "AName";
>+            arrayB[9] = 444;
>+
>+            //then
>+            assertFalse(ArrayUtil.arraysMatch(arrayA, arrayB));
>+        }
>+
>+        [Test]
>+        public function
>test_arrays_match_when_indexes_expressed_in_string_and_int():void
>+        {
>+            //given
>+            var arrayA:Array = [];
>+            var arrayB:Array = [];
>+
>+            //when
>+            arrayA[3] = "value";
>+            arrayA["4"] = "value";
>+
>+            arrayB["3"] = "value";
>+            arrayB[4] = "value";
>+
>+            //then
>+            assertTrue(ArrayUtil.arraysMatch(arrayA, arrayB));
>+        }
>+
>+        [Test]
>+        public function
>test_arrays_dont_match_when_values_expressed_in_string_and_int():void
>+        {
>+            //given
>+            var arrayA:Array = [];
>+            var arrayB:Array = [];
>+
>+            //when
>+            arrayA[3] = 3;
>+            arrayA[4] = 4;
>+
>+            arrayB[3] = "3";
>+            arrayB[4] = "4";
>+
>+            //then
>+            assertFalse(ArrayUtil.arraysMatch(arrayA, arrayB));
>+        }
>+
>+        [Test]
>+        public function test_array_and_null_dont_match():void
>+        {
>+            //then
>+            assertFalse(ArrayUtil.arraysMatch([1, 2, 3], null));
>+        }
>+
>+        [Test]
>+        public function test_null_and_null_dont_match():void
>+        {
>+            //then
>+            assertFalse(ArrayUtil.arraysMatch(null, null));
>+        }
>+
>+        [Test]
>+        public function
>test_arrays_with_null_in_different_positions_dont_match():void
>+        {
>+            //then
>+            assertFalse(ArrayUtil.arraysMatch([null, 0], [0, null]));
>+        }
>+
>+        
>//------------------------------------------------------------------------
>--
>+        //
>+        //  arrayValuesMatch()
>+        //
>+        
>//------------------------------------------------------------------------
>--
>+
>+        [Test]
>+        public function
>test_arrays_with_same_values_in_different_indexes_match_in_terms_of_values
>():void
>+        {
>+            //then
>+            assertTrue(ArrayUtil.arrayValuesMatch(["name", "age"],
>["age", "name"]));
>+        }
>+
>+        [Test]
>+        public function test_array_values_dont_match_with_null():void
>+        {
>+            //then
>+            assertFalse(ArrayUtil.arrayValuesMatch(["name", "age"],
>null));
>+        }
>+
>+        [Test]
>+        public function test_null_doesnt_match_values_with_array():void
>+        {
>+            //then
>+            assertFalse(ArrayUtil.arrayValuesMatch(null, ["name",
>"age"]));
>+        }
>+
>+        [Test]
>+        public function
>test_null_and_null_dont_have_matching_values():void
>+        {
>+            //then
>+            assertFalse(ArrayUtil.arrayValuesMatch(null, null));
>+        }
>+
>+        [Test]
>+        public function
>test_array_values_match_although_they_have_different_indexes():void
>+        {
>+            //given
>+            var arrayA:Array = [];
>+            var arrayB:Array = [];
>+
>+            //when
>+            arrayA["name"] = "AName";
>+            arrayA["age"] = 444;
>+
>+            arrayB["label"] = "AName";
>+            arrayB["spin"] = 444;
>+
>+            //then
>+            assertTrue(ArrayUtil.arrayValuesMatch(arrayA, arrayB));
>+        }
>+
>+        [Test]
>+        public function
>test_array_values_dont_match_although_they_have_same_indexes():void
>+        {
>+            //given
>+            var arrayA:Array = [];
>+            var arrayB:Array = [];
>+
>+            //when
>+            arrayA["name"] = "AName";
>+            arrayA["age"] = 444;
>+
>+            arrayB["name"] = "BName";
>+            arrayB["age"] = 21;
>+
>+            //then
>+            assertFalse(ArrayUtil.arrayValuesMatch(arrayA, arrayB));
>+        }
>+
>+        [Test]
>+        //relevant because the array length is changed when a numeric
>index is used
>+        public function
>test_array_values_match_even_when_one_of_their_indexes_is_numeric():void
>+        {
>+            //given
>+            var arrayA:Array = [];
>+            var arrayB:Array = [];
>+
>+            //when
>+            arrayA["name"] = "AName";
>+            arrayA["age"] = 444;
>+
>+            arrayB["label"] = "AName";
>+            arrayB[9] = 444;
>+
>+            //then
>+            assertTrue(ArrayUtil.arrayValuesMatch(arrayA, arrayB));
>+        }
>+
>+
>+        
>//------------------------------------------------------------------------
>--
>+        //
>+        //  getArrayValues()
>+        //
>+        
>//------------------------------------------------------------------------
>--
>+        [Test]
>+        public function test_values_of_null_is_an_empty_array():void
>+        {
>+            //when
>+            var values:Array = ArrayUtil.getArrayValues(null);
>+
>+            //then
>+            assertNotNull(values);
>+            assertEquals(0, values.length);
>+        }
>+
>+        [Test]
>+        public function
>test_values_of_array_whose_index_was_set_manually_to_a_number_include_only
>_that_value():void
>+        {
>+            //given
>+            var array:Array = [];
>+            array[2] = "hey";
>+
>+            //when
>+            var values:Array = ArrayUtil.getArrayValues(array);
>+
>+            //then
>+            assertNotNull(values);
>+            assertEquals(3, array.length);
>+            assertEquals(1, values.length);
>+            assertEquals("hey", values[0]);
>+        }
>+    }
>+}
>\ No newline at end of file
>
>http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/680b405d/frameworks/p
>rojects/framework/tests/mx/utils/ObjectUtil_Tests.as
>----------------------------------------------------------------------
>diff --git 
>a/frameworks/projects/framework/tests/mx/utils/ObjectUtil_Tests.as
>b/frameworks/projects/framework/tests/mx/utils/ObjectUtil_Tests.as
>new file mode 100644
>index 0000000..a373267
>--- /dev/null
>+++ b/frameworks/projects/framework/tests/mx/utils/ObjectUtil_Tests.as
>@@ -0,0 +1,167 @@
>+/////////////////////////////////////////////////////////////////////////
>///////
>+//
>+//  Licensed to the Apache Software Foundation (ASF) under one or more
>+//  contributor license agreements.  See the NOTICE file distributed with
>+//  this work for additional information regarding copyright ownership.
>+//  The ASF licenses this file to You under the Apache License, Version
>2.0
>+//  (the "License"); you may not use this file except in compliance with
>+//  the License.  You may obtain a copy of the License at
>+//
>+//      http://www.apache.org/licenses/LICENSE-2.0
>+//
>+//  Unless required by applicable law or agreed to in writing, software
>+//  distributed under the License is distributed on an "AS IS" BASIS,
>+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>implied.
>+//  See the License for the specific language governing permissions and
>+//  limitations under the License.
>+//
>+/////////////////////////////////////////////////////////////////////////
>///////
>+
>+package mx.utils {
>+    import flash.utils.Dictionary;
>+
>+    import org.flexunit.asserts.assertEquals;
>+
>+    import org.flexunit.asserts.assertFalse;
>+    import org.flexunit.asserts.assertTrue;
>+
>+    public class ObjectUtil_Tests
>+    {
>+        
>//------------------------------------------------------------------------
>--
>+        //
>+        //  isDynamicObject()
>+        //
>+        
>//------------------------------------------------------------------------
>--
>+
>+        [Test]
>+        public function
>test_dynamic_class_instance_recognized_as_dynamic_object():void
>+        {
>+            //then
>+            assertTrue(ObjectUtil.isDynamicObject(new
>DynamicVO("John")));
>+        }
>+
>+        [Test]
>+        public function
>test_anonymous_class_instance_recognized_as_dynamic_object():void
>+        {
>+            //then
>+            assertTrue(ObjectUtil.isDynamicObject({name:"John"}));
>+        }
>+
>+        [Test]
>+        public function
>test_array_instance_recognized_as_dynamic_object():void
>+        {
>+            //then
>+            assertTrue(ObjectUtil.isDynamicObject([]));
>+        }
>+
>+        [Test]
>+        public function
>test_dictionary_instance_recognized_as_dynamic_object():void
>+        {
>+            //then
>+            assertTrue(ObjectUtil.isDynamicObject(new Dictionary()));
>+        }
>+
>+        [Test]
>+        public function
>test_sealed_class_instance_recognized_as_non_dynamic_object():void
>+        {
>+            //then
>+            assertFalse(ObjectUtil.isDynamicObject(new
>NonDynamicVO("John")));
>+        }
>+
>+        [Test]
>+        public function test_null_does_not_throw_fatal():void
>+        {
>+            //then
>+            assertFalse(ObjectUtil.isDynamicObject(null));
>+        }
>+
>+        
>//------------------------------------------------------------------------
>--
>+        //
>+        //  getEnumerableProperties()
>+        //
>+        
>//------------------------------------------------------------------------
>--
>+
>+        [Test]
>+        public function
>test_enumerable_properties_of_anonymous_object():void
>+        {
>+            //given
>+            var object:Object = {name:"John", age:32};
>+
>+            //when
>+            var enumerableProperties:Array =
>ObjectUtil.getEnumerableProperties(object);
>+
>+            //then
>+            assertTrue(ArrayUtil.arrayValuesMatch(["age", "name"],
>enumerableProperties));
>+        }
>+
>+        [Test]
>+        public function test_enumerable_properties_of_null():void
>+        {
>+            //when
>+            var enumerableProperties:Array =
>ObjectUtil.getEnumerableProperties(null);
>+
>+            //then
>+            assertEquals(0, enumerableProperties.length);
>+        }
>+
>+        [Test]
>+        public function test_enumerable_properties_of_dictionary():void
>+        {
>+            //given
>+            var object:Object = new Dictionary(false);
>+            object["name"] = "John";
>+            object["age"] = 9;
>+
>+            //when
>+            var enumerableProperties:Array =
>ObjectUtil.getEnumerableProperties(object);
>+
>+            //then
>+            assertTrue(ArrayUtil.arrayValuesMatch(["age", "name"],
>enumerableProperties));
>+        }
>+
>+        [Test]
>+        public function
>test_enumerable_properties_of_dynamic_object():void
>+        {
>+            //given
>+            var object:Object = new DynamicVO("John");
>+            object["age"] = 9;
>+
>+            //when
>+            var enumerableProperties:Array =
>ObjectUtil.getEnumerableProperties(object);
>+
>+            //then
>+            assertTrue(ArrayUtil.arrayValuesMatch(["age", "name"],
>enumerableProperties));
>+        }
>+
>+        [Test]
>+        public function
>test_enumerable_properties_of_sealed_class_instance():void
>+        {
>+            //given
>+            var object:Object = new NonDynamicVO("John");
>+
>+            //when
>+            var enumerableProperties:Array =
>ObjectUtil.getEnumerableProperties(object);
>+
>+            //then
>+            assertEquals(0, enumerableProperties.length);
>+        }
>+    }
>+}
>+
>+dynamic class DynamicVO
>+{
>+    public function DynamicVO(name:String)
>+    {
>+        this.name = name;
>+    }
>+}
>+
>+class NonDynamicVO
>+{
>+    public var name:String;
>+
>+    public function NonDynamicVO(name:String)
>+    {
>+        this.name = name;
>+    }
>+}
>\ No newline at end of file
>

Reply via email to