diff --git a/README.md b/README.md index b24460d..260e0cf 100644 --- a/README.md +++ b/README.md @@ -108,7 +108,8 @@ var result:Stream = s.filter(function(item:Item):Boolean{ }); // 2. using provided global functions(can compare Boolean, Number, Date, XML, String types) -var result:Stream = s.filter(gt(prop(_, "price"), 1)); +// supports nested properties i.e. prop("prop.prop.prop") +var result:Stream = s.filter(gt(prop("price"), 1)); // 3. using Proxy magick and global functions var result:Stream = s.price(gt(_, 1)); diff --git a/src/com/kemsky/filters/prop.as b/src/com/kemsky/filters/prop.as index 8958c9a..8f6b9d0 100644 --- a/src/com/kemsky/filters/prop.as +++ b/src/com/kemsky/filters/prop.as @@ -1,19 +1,73 @@ package com.kemsky.filters { - import com.kemsky.support.toValue; - /** * Creates function that extracts named property from value - * @param value item or function applied to item * @param name name of the property * @return function function that extracts named property from value */ - public function prop(value:*, name:String):Function + public function prop(name:String):Function { - return function (item:*):* + var path:Array = name.split("."); + + var p1:String = path.length > 0 ? path[0]: undefined; + var p2:String = path.length > 1 ? path[1]: undefined; + var p3:String = path.length > 2 ? path[2]: undefined; + var p4:String = path.length > 3 ? path[3]: undefined; + var p5:String = path.length > 4 ? path[4]: undefined; + + switch (path.length) { - item = toValue(item, value); - return item.hasOwnProperty(name) ? item[name] : undefined; - }; + case 1: + return function (item:*):* + { + return item.hasOwnProperty(p1) ? item[p1] : undefined; + }; + case 2: + return function (item:*):* + { + var result:* = undefined; + try + { + result = item[p1][p2]; + } + catch(e:Error){} + return result; + }; + case 3: + return function (item:*):* + { + var result:* = undefined; + try + { + result = item[p1][p2][p3]; + } + catch(e:Error){} + return result; + }; + case 4: + return function (item:*):* + { + var result:* = undefined; + try + { + result = item[p1][p2][p3][p4]; + } + catch(e:Error){} + return result; + }; + case 5: + return function (item:*):* + { + var result:* = undefined; + try + { + result = item[p1][p2][p3][p4][p5]; + } + catch(e:Error){} + return result; + }; + } + + throw new Error("Property is too deep: '" + name + "', maximum nesting is 5"); } } diff --git a/src/com/kemsky/support/toValue.as b/src/com/kemsky/support/toValue.as index 52fc72f..733771e 100644 --- a/src/com/kemsky/support/toValue.as +++ b/src/com/kemsky/support/toValue.as @@ -11,7 +11,7 @@ package com.kemsky.support { result = value(item); } - else if(value !== undefined) + else { result = value; } diff --git a/testSrc/Item.as b/testSrc/Item.as index f49b71f..8562264 100644 --- a/testSrc/Item.as +++ b/testSrc/Item.as @@ -7,6 +7,7 @@ package public var price:Number; public var vat:Number; public var bool:Boolean; + public var item:Item; public function Item(name:String = null, price:Number = 0, vat:Number = 0) { diff --git a/testSrc/com/kemsky/TestStream.as b/testSrc/com/kemsky/TestStream.as index 1a301e8..eae2210 100644 --- a/testSrc/com/kemsky/TestStream.as +++ b/testSrc/com/kemsky/TestStream.as @@ -45,13 +45,13 @@ package com.kemsky var s1:Stream = $(1, 2, 3); var i1:StreamIterator = new ValueIterator(s1); - var count:int = 0; + var count1:int = 0; for each (var item:* in i1) { // Print.items("for each: ", i1.current, item); - if (++count < 10) + if (++count1 < 10) { - i1.push(count); + i1.push(count1); } } @@ -167,7 +167,7 @@ package com.kemsky { var item:Item = new Item("name1", 5, 0); var s:Stream = $(item); - assertEquals(s.map(prop(_, "name")).first, "name1"); + assertEquals(s.map(prop("name")).first, "name1"); } [Test] @@ -463,6 +463,18 @@ package com.kemsky }); assertEquals(sum3, 10); + + try + { + $().foldLeft(function (prev:Number, current:Number):Number + { + return prev + current; + }); + assertTrue(false); + } + catch(e:Error) + { + } } [Test] @@ -488,6 +500,18 @@ package com.kemsky }); assertEquals(sum3, 10); + + try + { + $().foldRight(function (prev:Number, current:Number):Number + { + return prev + current; + }); + assertTrue(false); + } + catch(e:Error) + { + } } [Test] diff --git a/testSrc/com/kemsky/filters/TestFilters.as b/testSrc/com/kemsky/filters/TestFilters.as index d1f1c6c..ed97ad5 100644 --- a/testSrc/com/kemsky/filters/TestFilters.as +++ b/testSrc/com/kemsky/filters/TestFilters.as @@ -7,6 +7,7 @@ package com.kemsky.filters import org.flexunit.asserts.assertEquals; import org.flexunit.asserts.assertFalse; + import org.flexunit.asserts.assertTrue; public class TestFilters { @@ -64,8 +65,8 @@ package com.kemsky.filters var s:Stream = $(item1, item2); - assertEquals(s.filter(eq(prop(_, "bool"), true)).first, item2); - assertEquals(s.filter(eq(prop(_, "bool"), false)).first, item1); + assertEquals(s.filter(eq(prop("bool"), true)).first, item2); + assertEquals(s.filter(eq(prop("bool"), false)).first, item1); } [Test] @@ -155,7 +156,7 @@ package com.kemsky.filters var s:Stream = $(item1, item2); - var result:Stream = s.filter(gt(prop(_, "price"), 1)); + var result:Stream = s.filter(gt(prop("price"), 1)); assertEquals(result.length, 1); assertEquals(result.first, item2); @@ -167,27 +168,73 @@ package com.kemsky.filters assertEquals(result.length, 1); assertEquals(result.first, item2.price); - result = s.filter(ge(prop(_, "price"), 2)); + result = s.filter(ge(prop("price"), 2)); assertEquals(result.length, 1); assertEquals(result.first, item2); - result = s.filter(gt(add(prop(_, "price"), prop(_, "vat"), 0), 2)); + result = s.filter(gt(add(prop("price"), prop("vat"), 0), 2)); assertEquals(result.length, 1); assertEquals(result.first, item1); - result = s.filter(gt(subtract(prop(_, "price"), prop(_, "vat")), 0)); + result = s.filter(gt(subtract(prop("price"), prop("vat")), 0)); assertEquals(result.length, 1); assertEquals(result.first, item2); - result = s.filter(gt(subtract(prop(_, "price"), 1), 0)); + result = s.filter(gt(subtract(prop("price"), 1), 0)); assertEquals(result.length, 1); assertEquals(result.first, item2); result = s.filter(gt(0, 1)); assertEquals(result.length, 0); - result = s.filter(ge(prop(prop(_, "name"), "length"), 1)); - assertEquals(result.length, 2); + var obj:Item = new Item("p0"); + obj.item = new Item("p1"); + obj.item.item = new Item("p2"); + obj.item.item.item = new Item("p3"); + obj.item.item.item.item = new Item("p4"); + + var nested:Stream = $(obj); + + result = nested.filter(eq(prop("name"), "p0")); + assertEquals(result.length, 1); + + result = nested.filter(eq(prop("name1"), undefined)); + assertEquals(result.length, 1); + + + result = nested.filter(eq(prop("item.name"), "p1")); + assertEquals(result.length, 1); + + result = nested.filter(eq(prop("item.name1"), undefined)); + assertEquals(result.length, 1); + + + result = nested.filter(eq(prop("item.item.name"), "p2")); + assertEquals(result.length, 1); + + result = nested.filter(eq(prop("item.item.name1"), undefined)); + assertEquals(result.length, 1); + + + result = nested.filter(eq(prop("item.item.item.name"), "p3")); + assertEquals(result.length, 1); + + result = nested.filter(eq(prop("item.item.item.name1"), undefined)); + assertEquals(result.length, 1); + + + result = nested.filter(eq(prop("item.item.item.item.name"), "p4")); + assertEquals(result.length, 1); + + result = nested.filter(eq(prop("item.item.item.item.name1"), undefined)); + assertEquals(result.length, 1); + + try + { + nested.filter(eq(prop("item.item.item.item.item.name"), "p5")); + assertTrue(false); + } + catch(e:Error){} //some fun result = s.filter(ge(function (item:Item):Number @@ -221,8 +268,8 @@ package com.kemsky.filters var s:Stream = $(item); - assertEquals(s.filter(mapped(prop(_, "name"), d)).length, 1); - assertEquals(s.filter(mapped(prop(_, "name"), o)).length, 1); + assertEquals(s.filter(mapped(prop("name"), d)).length, 1); + assertEquals(s.filter(mapped(prop("name"), o)).length, 1); var p:Stream = $("name", "price", "vat"); diff --git a/testSrc/com/kemsky/support/TestSupport.as b/testSrc/com/kemsky/support/TestSupport.as index f3d945f..731d610 100644 --- a/testSrc/com/kemsky/support/TestSupport.as +++ b/testSrc/com/kemsky/support/TestSupport.as @@ -65,10 +65,10 @@ package com.kemsky.support assertTrue(toValue(undefined, undefined) === undefined); - assertEquals(toValue(1, undefined), 1); - assertEquals(toValue("test", undefined), "test"); - assertEquals(toValue(date, undefined), date); - assertEquals(toValue(null, undefined), null); + assertTrue(toValue(1, undefined) === undefined); + assertTrue(toValue("test", undefined) === undefined); + assertTrue(toValue(date, undefined) === undefined); + assertTrue(toValue(null, undefined) === undefined); var f:Function = function(value:*):* {