SlideShare a Scribd company logo
1 of 28
ActionScript3 collection query
OO STYLE - LINQ TO OBJECTS
IMPLEMENTATION PROPOSAL
Introduction
 Draft implementation, just an idea, would be great if

we have something like this in ActionScript (but
more robust, complex, optimized of course)
 Purpose – collection sorting, filtering, grouping
wrapper
 OO-Style LINQ to Objects lib for flex
Usage examples – first, last, any, itemAt
//get first with title containing case insensitive string “Voislav Seselj”
var query:IQuery = new CollectionQuery(_news);
var firstItem:NewsFeed = query.where(new
Conditions().contains("title", “Voislav Seselj", false)).first() as NewsFeed;
//last item published in 2013 or 2014
var lastItem:NewsFeed = query.where(new
Conditions().eq("year", 2014).OR.eq("year", 2013)).last() as NewsFeed;
var usersQuery:IQuery = new CollectionQuery();
if(usersQuery.from(users).where(new Conditions().eq("name", "Peter Pan")).any())
{
//excellent, there is a user (or users) with name "Peter Pan“
}
//get third adault from the end of the collection ordered by name ascending and lastname
//descending.
var user:User = new CollectionQuery(users)
.where(new Conditions().gte("years", 18))
.orderBy("name").orderBy("lastname", false)
.itemAt(2) as User;
Usage examples – where, select, limit
//get users for given conditions ordered by company and then by years property
var users:IList = usersQuery.where(new Conditions().lt("years", 18).gt("years", 5).OR
.eq("company", "Company 1"))
.orderBy("company“).orderBy("years")
.execute() as IList;
//select collection containing anonymous objects with properties given in select clause
//extracted from user objects, for given conditions, ordered by salary with ascending order
//and compare as numerics.
//Limit to maximum 10 results
var users:IList = new CollectionQuery()
.select("name, lastname, company, salary")
.from(users)
.where(new Conditions().gte("salary", 40000).lte("salary", 45000)) //AND by default
.orderBy("salary", true, true)
.limit(10).execute() as IList;
Usage examples – nested complex objects
//select streets from complex member “address” for each user in users collection
var streets:IList = usersQuery.select("address.street").from(users).execute() as IList;
//select anonymous objects containing user’s name, lastname, address->number, address//>street, address->uniqueId->value, for users having address number greater then 400 in
//Kragujevac city, or having address number lower then 400 and live in Belgrade city.
//Order list by city ascending and by address number descending comparing address.number
//property as numbers.
var users:IList = usersQuery
.select("name, lastname, address.number, address.street, address.uniqueId.value")
.from(users)
.where(new Conditions()
.gt("address.number", 400).eq("address.city", "Kragujevac").OR.
lt("address.number", 400).eq("address.city", "Belgrade"))
.orderBy("address.city")
.orderBy("address.number", false, true)
.execute() as IList;
Usage examples – groupBy
//group users named Marija or Slavisa by city, ordere by name and then by lastname
var query:IQuery = new CollectionQuery();
var groupResults:IQueryGroupResult = query
.select("id, name, lastname, address.street") //get anonimous objects
.from(users)
.where(new Conditions()
.eq("name", "Slaviša").OR
.eq("name“,"Marija").AND.contains("lastname", "ić"))
.orderBy("name").orderBy("lastname", false) //order by name , lastname descending
.groupBy("address.city")
//group by city
.execute() as IQueryGroupResult;
//get grouped results
for each(var city:Object in groupResults.keys) //iterate through key collection
{
printUsersFromCity(key, groupResults[key] as IList); //and print collection for each key
}
if(groupResults.keys.contains("Kragujevac")) //test if there is a key
{
var kragujevcani:IList = groupResults["Kragujevac"] as IList; //print the collection
}
API
 ICondition
 IQuery
 IQueryGroupResult
 IQueryItemResult
 CollectionQuery
 Conditions
 Predicate
 QueryGroupResult
 QueryResultItem
IQuery
/**
* Query interface
* @author Slavisa
*/
public interface IQuery
{
function select(value:String = null):IQuery;
//select columns
function from(coll:IList):IQuery;
//sets collection to be queried
function where(conditions:ICondition):IQuery;
//sets condition chain
function groupBy(property:String):IQuery;
//sets group keys
function orderBy(property:String, ascending:Boolean = true, numeric:Boolean = false):IQuery; //order
by given property
function limit(count:int = 100):IQuery;
//limits result’s item count
function first():Object;
//returns first or null
function last():Object;
//returns last or null
function itemAt(index:int):Object;
//returns item by the given index, or null
function execute():Object;
//actual execution, returns IList or IQueryGroupResult object
function any():Boolean;
//determines if at least one result exists
}
ICondition
/**
* Condition interface
* @author Slavisa
*/
public interface ICondition
{
function eq(prop:String, value:Object):ICondition;
//equal
function diff(prop:String, value:Object):ICondition;
//not equal
function contains(prop:String, value:String, caseSensitive:Boolean = true):ICondition; //contains
function lt(prop:String, value:Object):ICondition;
//lower than
function lte(prop:String, value:Object):ICondition;
//lower than or equal
function gt(prop:String, value:Object):ICondition;
//greater than
function gte(prop:String, value:Object):ICondition;
//greater than or equal
function get OR():ICondition;
function get AND():ICondition;
function get root():ICondition;
}

//OR – new condition group
//AND – new condition group
//get root condition
IQueryItemResult, QueryResultItem, IQueryGroupResult
/**
* Query Item result interface
* @author Slavisa
*/
public interface IQueryItemResult
{
}

/**
* Query Item result dynamic class
* Stores custom selection (anonimous object)
* @author Slavisa
*/
public dynamic class QueryResultItem
implements IQueryItemResult
{
}

/**
* Query Grouped results
* @author pokimsla
*/
public interface IQueryGroupResult
{
function get keys():ArrayCollection;
function get length():int;
}

//gets keys collection
//gets number of groups
QueryGroupResult
public dynamic class QueryGroupResult extends Dictionary implements IQueryGroupResult
{
//Gets array collection of group keys
public function get keys():ArrayCollection
{
var keys:ArrayCollection = new ArrayCollection();
for(var key:Object in this)
{
keys.addItem(key);
}
return keys;
}

//number of keys
public function get length():int
{
return keys.length;
}
}
Predicate
/**
* Predicate class
* @author Slavisa
* Used for combining multiple conditions joined with AND operator
*/
[Bindable]
public class Predicate implements ICondition
{
/* Predicate types */
public static const EQ:String = "equal";
public static const DIFF:String = "different";
public static const CONTAINS:String = "contains";
public static const LT:String = "less";
public static const GT:String = "greater";
public static const GTE:String = "greater or equal";
public static const LTE:String = "lower or equal";
/* operators */
public static const OPERATOR_OR:String = "or";
public static const OPERATOR_AND:String = "and";
public var property:String;
//property for comparison
public var value:Object;
//value to compare with
public var type:String;
//predicate type
public var conditions:Conditions; //joining conditions (group of predicates to which this predicate belongs)
public var attributes:Object;
//additional attributes
private var _root:ICondition;
//root condition
Predicate
public function Predicate(cond:ICondition, prop:String, val:Object, type:String, attributes:Object = null)
{
this._root = cond.root; //set the root condition
this.property = prop;
this.value = val;
this.type = type;
this.conditions = cond as Conditions;
this.conditions.addPredicate(this); //authomaticly add me to the predicate list
this.attributes = attributes;
}
//creates next predicate (not equal)
public function diff(prop:String, value:Object):ICondition
{
return createNextPredicate(prop, value, DIFF);
}
//creates next predicate (equal)
public function eq(prop:String, value:Object):ICondition
{
return createNextPredicate(prop, value, EQ);
}
…
//create next predicate for given values
private function createNextPredicate(prop:String, value:Object, type:String, attributes:Object = null):ICondition
{
var pred:Predicate = new Predicate(conditions, prop, value, type, attributes);
return pred;
}
Predicate
// Creates new condition with OR relation
public function get OR():ICondition
{
var condition:Conditions = new Conditions();
condition.type = OPERATOR_OR;
condition.root = root;
this.conditions.next = condition;
return condition;
}
//creates new condition with AND relation
public function get AND():ICondition
{
var condition:Conditions = new Conditions();
condition.type = OPERATOR_AND;
condition.root = root;
this.conditions.next = condition;
return condition;
}
//gets root condition
public function get root():ICondition
{
return _root;
}
}
Conditions
/**
* Condition contains group of predicates, used for joining multiple condition groups (predicates)
* @author Slavisa
* <br/>
* Condition chain boolean result is calculated from last to root condition group
*/
public class Conditions implements ICondition
{
private var _predicates:ArrayCollection=new ArrayCollection();
//predicate collection
private var _next:ICondition;
//next condition in a row
private var _root:Conditions;
//starting condition
public var type:String;
//starting condition shouldn't have a type property populated. EQ, OR, AND, LT...
//Condition contains group of predicates, used for joining multiple condition groups (predicates)
public function Conditions()
{
_root = this;
}
/**
* add predicates to a collection
* @param predicate
* predicates are validated in groups with ANR logical operator
*/
public function addPredicate(predicate:ICondition):void
{
_predicates.addItem(predicate);
}
Conditions
//creates and appends diff predicate
public function diff(prop:String, value:Object):ICondition
{
return new Predicate(this, prop, value, Predicate.DIFF);
}
//creates and appends eq predicate
public function eq(prop:String, value:Object):ICondition
{
return new Predicate(this, prop, value, Predicate.EQ);
}
//… other predicates, getters and setters
//OR condition does nothing on Conditions instance
public function get OR():ICondition
{
return this;
}
//AND condition does nothing on Conditions instance
public function get AND():ICondition
{
return this;
}
}
CollectionQuery
/**
* Actual collection query implementation
* @author Slavisa
*/
public class CollectionQuery implements IQuery
{
private var _coll:IList; //collection
private var _conditions:ICondition; //conditions
private var _comparatorGroups:ArrayCollection; //comparator groups built before collection iteration
private const _comparatorMap:Object = createComparatorMap(); //comparator delegates
private var _selectColumns:String = null; //select columns. If null, row items are selected
private var _limitCount:int = 0; //limited item count
private var _groupBy:String = null; //group by this property
private var _orderBy:ArrayCollection = new ArrayCollection(); //order by these properties
private var _hasGroupBy:Boolean = false;
private var _hasOrderBy:Boolean = false;
//ctor
public function CollectionQuery(coll:IList = null, selectColumns:String = null)
{
_coll = coll;
this._selectColumns = selectColumns;
}
CollectionQuery
//creates comparator delegate map
private function createComparatorMap():Object
{
var map:Object = new Object();
map[Predicate.DIFF] = diff;
map[Predicate.EQ] = eq;
map[Predicate.GT] = gt;
map[Predicate.GTE] = gte;
map[Predicate.LT] = lt;
map[Predicate.LTE] = lte;
map[Predicate.CONTAINS] = contains;
return map;
}
//contains comparator
private function contains(a:Object, b:Object, attributes:Object = null):Boolean
{
var strA:String = attributes && attributes.caseSensitive ? String(a) : String(a).toLowerCase();
var strB:String = attributes && attributes.caseSensitive ? String(b) : String(b).toLowerCase();
return strA.indexOf(strB) > -1;
}
//equal comparator
private function eq(a:Object, b:Object, attributes:Object = null):Boolean
{
return a == b;
}
//…other comparators
CollectionQuery
//sets select properties
public function select(value:String = null):IQuery
{
_selectColumns = value;
return this;
}
//sets target collection
public function from(coll:IList):IQuery
{
_coll = coll;
return this;
}
//sets conditions root
public function where(conditions:ICondition):IQuery
{
this._conditions = conditions.root;
return this;
}
/*
Similar for :
groupBy
orderBy
limit
*/
CollectionQuery
public function first():Object
{
if(_hasGroupBy)
throw new Error("First() is allowed only for non-grouped results");
var result:IList = runExecution(1) as IList;
return result.length > 0 ? result[0] : null;
}
public function last():Object
{
if(_hasGroupBy)
throw new Error("Last() is allowed only for non-grouped results");
var result:IList = runExecution(1, true) as IList;
return result.length > 0 ? result[0] : null;
}
public function itemAt(index:int):Object
{
if(_hasGroupBy)
throw new Error("ItemAt() is allowed only for non-grouped results");
if(index < 0)
throw new ArgumentError("Invalid argument for itemAt method");
var result:IList = runExecution(index + 1) as IList;
return result.length > (index + 1) ? null : result[index];
}
CollectionQuery
public function execute():Object //interface impl
{
return runExecution(_limitCount);
}
//actual query execution
private function runExecution(limit:int = 0, reverse:Boolean = false):Object
{
implementation details excluded for insufficient space, if anyone cares send me an email to slavisapokimica@yahoo.com, I’ll
be happy to provide all you need
}
private function orderCollection(collection:ArrayCollection):void
{
if(_orderBy.length == 0)
return;
var sort:Sort = new Sort();
sort.fields = new Array();
for each(var fieldDef:Object in _orderBy)
{
var sortField:SortField = new SortField(fieldDef.field, false, !fieldDef.ascending, fieldDef.numeric);
sort.fields.push(sortField);
}
collection.sort = sort;
collection.refresh();
}
CollectionQuery
/**
* Creates result item
* @param item
* @return Row Item or anonymous object with properties generated from selectColumns variable
*/
private function createResultItem(item:Object):Object
{
if(_selectColumns == null) //return row item
return item;
var columns:Array = _selectColumns.split(",");

//split columns

if(columns.length == 1)
return extractPropertyValue(item, columns[0]);

//if only one property, than return it

var res:QueryResultItem = new QueryResultItem();

//anonymous dynamic object

for each(var column:String in columns)
//populate anonymous object
{
var col:String = StringUtil.trim(column);
var newPropname:String = col.replace(/[.]/g, '_');
res[newPropname] = extractPropertyValue(item, col); //set property value
}
return res;
}
CollectionQuery
/**
* extracts property from given item
*/
private function extractPropertyValue(item:Object, property:String):Object
{
var single:String = StringUtil.trim(property);
if(single.indexOf(".") == -1)
{
if( !item.hasOwnProperty(single) )
throw new ArgumentError("Property with name "" + single + "" does not exist!");
return item[single];
}
//recursive call when extracting complex member’s properties
return
extractPropertyValue(item[property.substring(0, property.indexOf("."))], property.substring(property.indexOf(".") + 1));
}
CollectionQuery
/**
* Actual filtering logic
* @param item collection item currently being validated
* @param validationGroups condition groups to be validated with
* @return Boolean
* <ul>
* <li>validation groups empty - return true</li>
* <li>single item in validation group - return predicate validation result</li>
* <li>iterate through all condition groups and its predicates and validate them all</li>
* </ul>
*/
private function filterFunction(item:Object, validationGroups:ArrayCollection):Boolean
{
if(validationGroups.length == 0)
return true;
if(validationGroups.length == 1)
return validatePredicates(item, _comparatorGroups[0].predicates);
var result:Boolean = validatePredicates(item, _comparatorGroups[0].predicates);
for (var i:int = 0; i < _comparatorGroups.length - 1; i++)
{
result = _comparatorGroups[i].operation == Predicate.OPERATOR_AND ?
result && validatePredicates(item, _comparatorGroups[i + 1].predicates) :
result || validatePredicates(item, _comparatorGroups[i + 1].predicates);
}
return result;
}
What’s next
 Optimization
 Validation
 Interface expansion
 “In” and “Between” conditions
 Joins
 Comparison between two properties
 Query reset
 Nested conditions
 And much more…
Also kewl to have - code snippets I
<template autoinsert="true"
context="com.adobe.flexide.as.core.codetemplates.action_script"
deleted="false" description="Query first item by the given conditions"
enabled="true" name="query_first">
var query:IQuery = new CollectionQuery(${_collection});
var firstItem:${type} = query.where(new
Conditions().${operation:values(eq, lt, lte, gt, gte, diff,
contains)}("${prop}", ${value})).first() as ${type};
</template>
<template autoinsert="true"
context="com.adobe.flexide.as.core.codetemplates.action_script"
deleted="false" description="Order queried collection"
enabled="true" name="query_order">
var query:IQuery = new CollectionQuery(${_collection});
var orderedResults:IList = query.where(new Conditions()
.${operation:values(eq, lt, lte, gt, gte, diff, contains)}("${prop}", ${value}))
.orderBy("${orderProp}", ${ascending:values(true, false)}, ${numeric:values(false, true)})
.execute() as IList;
</template>
Code snippets II
<template autoinsert="true"
context="com.adobe.flexide.as.core.codetemplates.action_script"
deleted="false" description="Grouping query results"
enabled="true" name="query_group">
var query:IQuery = new
CollectionQuery(${_collection});
var groups:IQueryGroupResult = query
.where(new Conditions()
.${operation:values(eq, lt, lte, gt, gte, diff, contains)}("${prop}", ${value}))
.groupBy("${groupProperty}")
.execute() as IQueryGroupResult;
for each(var key:Object in groups.keys)
{
var groupedItems:ArrayCollection = groups[key] as ArrayCollection;
}
</template>
Contact details

 Email> slavisapokimica@yahoo.com

More Related Content

What's hot

Building a Pluggable Plugin
Building a Pluggable PluginBuilding a Pluggable Plugin
Building a Pluggable PluginBrandon Dove
 
Synapseindia object oriented programming in php
Synapseindia object oriented programming in phpSynapseindia object oriented programming in php
Synapseindia object oriented programming in phpSynapseindiappsdevelopment
 
descriptive programming
descriptive programmingdescriptive programming
descriptive programmingAnand Dhana
 
Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...go_oh
 
Funcitonal Swift Conference: The Functional Way
Funcitonal Swift Conference: The Functional WayFuncitonal Swift Conference: The Functional Way
Funcitonal Swift Conference: The Functional WayNatasha Murashev
 
Art of Javascript
Art of JavascriptArt of Javascript
Art of JavascriptTarek Yehia
 
Building DSLs With Eclipse
Building DSLs With EclipseBuilding DSLs With Eclipse
Building DSLs With EclipsePeter Friese
 
Intro programacion funcional
Intro programacion funcionalIntro programacion funcional
Intro programacion funcionalNSCoder Mexico
 
3.1 javascript objects_DOM
3.1 javascript objects_DOM3.1 javascript objects_DOM
3.1 javascript objects_DOMJalpesh Vasa
 
Models Best Practices (ZF MVC)
Models Best Practices (ZF MVC)Models Best Practices (ZF MVC)
Models Best Practices (ZF MVC)eddiejaoude
 
Your code sucks, let's fix it
Your code sucks, let's fix itYour code sucks, let's fix it
Your code sucks, let's fix itRafael Dohms
 
javascript objects
javascript objectsjavascript objects
javascript objectsVijay Kalyan
 
Generics in .NET, C++ and Java
Generics in .NET, C++ and JavaGenerics in .NET, C++ and Java
Generics in .NET, C++ and JavaSasha Goldshtein
 
JavaScript: The Good Parts Or: How A C# Developer Learned To Stop Worrying An...
JavaScript: The Good Parts Or: How A C# Developer Learned To Stop Worrying An...JavaScript: The Good Parts Or: How A C# Developer Learned To Stop Worrying An...
JavaScript: The Good Parts Or: How A C# Developer Learned To Stop Worrying An...Doug Jones
 

What's hot (20)

Building a Pluggable Plugin
Building a Pluggable PluginBuilding a Pluggable Plugin
Building a Pluggable Plugin
 
Synapseindia object oriented programming in php
Synapseindia object oriented programming in phpSynapseindia object oriented programming in php
Synapseindia object oriented programming in php
 
Prototype Framework
Prototype FrameworkPrototype Framework
Prototype Framework
 
descriptive programming
descriptive programmingdescriptive programming
descriptive programming
 
Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...
 
Funcitonal Swift Conference: The Functional Way
Funcitonal Swift Conference: The Functional WayFuncitonal Swift Conference: The Functional Way
Funcitonal Swift Conference: The Functional Way
 
Art of Javascript
Art of JavascriptArt of Javascript
Art of Javascript
 
Building DSLs With Eclipse
Building DSLs With EclipseBuilding DSLs With Eclipse
Building DSLs With Eclipse
 
Intro programacion funcional
Intro programacion funcionalIntro programacion funcional
Intro programacion funcional
 
3.1 javascript objects_DOM
3.1 javascript objects_DOM3.1 javascript objects_DOM
3.1 javascript objects_DOM
 
Models Best Practices (ZF MVC)
Models Best Practices (ZF MVC)Models Best Practices (ZF MVC)
Models Best Practices (ZF MVC)
 
Python: Basic Inheritance
Python: Basic InheritancePython: Basic Inheritance
Python: Basic Inheritance
 
Your code sucks, let's fix it
Your code sucks, let's fix itYour code sucks, let's fix it
Your code sucks, let's fix it
 
javascript objects
javascript objectsjavascript objects
javascript objects
 
Generics in .NET, C++ and Java
Generics in .NET, C++ and JavaGenerics in .NET, C++ and Java
Generics in .NET, C++ and Java
 
JavaScript: The Good Parts Or: How A C# Developer Learned To Stop Worrying An...
JavaScript: The Good Parts Or: How A C# Developer Learned To Stop Worrying An...JavaScript: The Good Parts Or: How A C# Developer Learned To Stop Worrying An...
JavaScript: The Good Parts Or: How A C# Developer Learned To Stop Worrying An...
 
iOS Session-2
iOS Session-2iOS Session-2
iOS Session-2
 
Intro to JavaScript
Intro to JavaScriptIntro to JavaScript
Intro to JavaScript
 
Python dictionary
Python dictionaryPython dictionary
Python dictionary
 
C# Generics
C# GenericsC# Generics
C# Generics
 

Viewers also liked

Tipos de memoria
Tipos de memoriaTipos de memoria
Tipos de memoriasonia-fares
 
A Narrative Display for Sports Tournament Recap
A Narrative Display for Sports Tournament RecapA Narrative Display for Sports Tournament Recap
A Narrative Display for Sports Tournament RecapKrist Wongsuphasawat
 
Krist Wongsuphasawat's Dissertation Proposal Slides: Interactive Exploration ...
Krist Wongsuphasawat's Dissertation Proposal Slides: Interactive Exploration ...Krist Wongsuphasawat's Dissertation Proposal Slides: Interactive Exploration ...
Krist Wongsuphasawat's Dissertation Proposal Slides: Interactive Exploration ...Krist Wongsuphasawat
 
Krist Wongsuphasawat's Dissertation Defense: Interactive Exploration of Tempo...
Krist Wongsuphasawat's Dissertation Defense: Interactive Exploration of Tempo...Krist Wongsuphasawat's Dissertation Defense: Interactive Exploration of Tempo...
Krist Wongsuphasawat's Dissertation Defense: Interactive Exploration of Tempo...Krist Wongsuphasawat
 

Viewers also liked (7)

Tipos de memoria
Tipos de memoriaTipos de memoria
Tipos de memoria
 
Usability of Google Docs
Usability of Google DocsUsability of Google Docs
Usability of Google Docs
 
A Narrative Display for Sports Tournament Recap
A Narrative Display for Sports Tournament RecapA Narrative Display for Sports Tournament Recap
A Narrative Display for Sports Tournament Recap
 
Krist Wongsuphasawat's Dissertation Proposal Slides: Interactive Exploration ...
Krist Wongsuphasawat's Dissertation Proposal Slides: Interactive Exploration ...Krist Wongsuphasawat's Dissertation Proposal Slides: Interactive Exploration ...
Krist Wongsuphasawat's Dissertation Proposal Slides: Interactive Exploration ...
 
Finding Patterns in Temporal Data
Finding Patterns in Temporal DataFinding Patterns in Temporal Data
Finding Patterns in Temporal Data
 
Krist Wongsuphasawat's Dissertation Defense: Interactive Exploration of Tempo...
Krist Wongsuphasawat's Dissertation Defense: Interactive Exploration of Tempo...Krist Wongsuphasawat's Dissertation Defense: Interactive Exploration of Tempo...
Krist Wongsuphasawat's Dissertation Defense: Interactive Exploration of Tempo...
 
d3Kit
d3Kitd3Kit
d3Kit
 

Similar to ActionScript3 collection query API proposal

Object Oriented JavaScript
Object Oriented JavaScriptObject Oriented JavaScript
Object Oriented JavaScriptDonald Sipe
 
Understanding backbonejs
Understanding backbonejsUnderstanding backbonejs
Understanding backbonejsNick Lee
 
Backbone js
Backbone jsBackbone js
Backbone jsrstankov
 
Hello Swift Final 5/5 - Structures and Classes
Hello Swift Final 5/5 - Structures and ClassesHello Swift Final 5/5 - Structures and Classes
Hello Swift Final 5/5 - Structures and ClassesCody Yun
 
Uncommon Design Patterns
Uncommon Design PatternsUncommon Design Patterns
Uncommon Design PatternsStefano Fago
 
Aplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneAplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneRafael Felix da Silva
 
Ian 20150116 java script oop
Ian 20150116 java script oopIan 20150116 java script oop
Ian 20150116 java script oopLearningTech
 
Object Oriented JavaScript
Object Oriented JavaScriptObject Oriented JavaScript
Object Oriented JavaScriptJulie Iskander
 
Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)Fabien Potencier
 
Link.javaLink.javapackage com.bookstore.domain.model;import .docx
Link.javaLink.javapackage com.bookstore.domain.model;import .docxLink.javaLink.javapackage com.bookstore.domain.model;import .docx
Link.javaLink.javapackage com.bookstore.domain.model;import .docxSHIVA101531
 
Object-oriented Javascript
Object-oriented JavascriptObject-oriented Javascript
Object-oriented JavascriptDaniel Ku
 
Dpilot Source Code With ScreenShots
Dpilot Source Code With ScreenShots Dpilot Source Code With ScreenShots
Dpilot Source Code With ScreenShots DeepAnshu Sharma
 
Dpilot - Source Code with Snapshots
Dpilot - Source Code with SnapshotsDpilot - Source Code with Snapshots
Dpilot - Source Code with SnapshotsKritika Phulli
 
Source Code for Dpilot
Source Code for Dpilot Source Code for Dpilot
Source Code for Dpilot Nidhi Chauhan
 
JavaScript Literacy
JavaScript LiteracyJavaScript Literacy
JavaScript LiteracyDavid Jacobs
 

Similar to ActionScript3 collection query API proposal (20)

OO in JavaScript
OO in JavaScriptOO in JavaScript
OO in JavaScript
 
Object Oriented JavaScript
Object Oriented JavaScriptObject Oriented JavaScript
Object Oriented JavaScript
 
Understanding backbonejs
Understanding backbonejsUnderstanding backbonejs
Understanding backbonejs
 
Backbone js
Backbone jsBackbone js
Backbone js
 
Hello Swift Final 5/5 - Structures and Classes
Hello Swift Final 5/5 - Structures and ClassesHello Swift Final 5/5 - Structures and Classes
Hello Swift Final 5/5 - Structures and Classes
 
OOP Lab Report.docx
OOP Lab Report.docxOOP Lab Report.docx
OOP Lab Report.docx
 
Uncommon Design Patterns
Uncommon Design PatternsUncommon Design Patterns
Uncommon Design Patterns
 
Aplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneAplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com Backbone
 
Ian 20150116 java script oop
Ian 20150116 java script oopIan 20150116 java script oop
Ian 20150116 java script oop
 
Object Oriented JavaScript
Object Oriented JavaScriptObject Oriented JavaScript
Object Oriented JavaScript
 
Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)
 
Link.javaLink.javapackage com.bookstore.domain.model;import .docx
Link.javaLink.javapackage com.bookstore.domain.model;import .docxLink.javaLink.javapackage com.bookstore.domain.model;import .docx
Link.javaLink.javapackage com.bookstore.domain.model;import .docx
 
Lecture 5
Lecture 5Lecture 5
Lecture 5
 
Object-oriented Javascript
Object-oriented JavascriptObject-oriented Javascript
Object-oriented Javascript
 
Dpilot Source Code With ScreenShots
Dpilot Source Code With ScreenShots Dpilot Source Code With ScreenShots
Dpilot Source Code With ScreenShots
 
Dpilot - Source Code with Snapshots
Dpilot - Source Code with SnapshotsDpilot - Source Code with Snapshots
Dpilot - Source Code with Snapshots
 
Source Code for Dpilot
Source Code for Dpilot Source Code for Dpilot
Source Code for Dpilot
 
JavaScript Literacy
JavaScript LiteracyJavaScript Literacy
JavaScript Literacy
 
Java Script Best Practices
Java Script Best PracticesJava Script Best Practices
Java Script Best Practices
 
JNDI
JNDIJNDI
JNDI
 

Recently uploaded

Employee wellbeing at the workplace.pptx
Employee wellbeing at the workplace.pptxEmployee wellbeing at the workplace.pptx
Employee wellbeing at the workplace.pptxNirmalaLoungPoorunde1
 
Crayon Activity Handout For the Crayon A
Crayon Activity Handout For the Crayon ACrayon Activity Handout For the Crayon A
Crayon Activity Handout For the Crayon AUnboundStockton
 
Class 11 Legal Studies Ch-1 Concept of State .pdf
Class 11 Legal Studies Ch-1 Concept of State .pdfClass 11 Legal Studies Ch-1 Concept of State .pdf
Class 11 Legal Studies Ch-1 Concept of State .pdfakmcokerachita
 
Solving Puzzles Benefits Everyone (English).pptx
Solving Puzzles Benefits Everyone (English).pptxSolving Puzzles Benefits Everyone (English).pptx
Solving Puzzles Benefits Everyone (English).pptxOH TEIK BIN
 
Final demo Grade 9 for demo Plan dessert.pptx
Final demo Grade 9 for demo Plan dessert.pptxFinal demo Grade 9 for demo Plan dessert.pptx
Final demo Grade 9 for demo Plan dessert.pptxAvyJaneVismanos
 
History Class XII Ch. 3 Kinship, Caste and Class (1).pptx
History Class XII Ch. 3 Kinship, Caste and Class (1).pptxHistory Class XII Ch. 3 Kinship, Caste and Class (1).pptx
History Class XII Ch. 3 Kinship, Caste and Class (1).pptxsocialsciencegdgrohi
 
Science 7 - LAND and SEA BREEZE and its Characteristics
Science 7 - LAND and SEA BREEZE and its CharacteristicsScience 7 - LAND and SEA BREEZE and its Characteristics
Science 7 - LAND and SEA BREEZE and its CharacteristicsKarinaGenton
 
Call Girls in Dwarka Mor Delhi Contact Us 9654467111
Call Girls in Dwarka Mor Delhi Contact Us 9654467111Call Girls in Dwarka Mor Delhi Contact Us 9654467111
Call Girls in Dwarka Mor Delhi Contact Us 9654467111Sapana Sha
 
Mastering the Unannounced Regulatory Inspection
Mastering the Unannounced Regulatory InspectionMastering the Unannounced Regulatory Inspection
Mastering the Unannounced Regulatory InspectionSafetyChain Software
 
Alper Gobel In Media Res Media Component
Alper Gobel In Media Res Media ComponentAlper Gobel In Media Res Media Component
Alper Gobel In Media Res Media ComponentInMediaRes1
 
Science lesson Moon for 4th quarter lesson
Science lesson Moon for 4th quarter lessonScience lesson Moon for 4th quarter lesson
Science lesson Moon for 4th quarter lessonJericReyAuditor
 
Pharmacognosy Flower 3. Compositae 2023.pdf
Pharmacognosy Flower 3. Compositae 2023.pdfPharmacognosy Flower 3. Compositae 2023.pdf
Pharmacognosy Flower 3. Compositae 2023.pdfMahmoud M. Sallam
 
Presiding Officer Training module 2024 lok sabha elections
Presiding Officer Training module 2024 lok sabha electionsPresiding Officer Training module 2024 lok sabha elections
Presiding Officer Training module 2024 lok sabha electionsanshu789521
 
Enzyme, Pharmaceutical Aids, Miscellaneous Last Part of Chapter no 5th.pdf
Enzyme, Pharmaceutical Aids, Miscellaneous Last Part of Chapter no 5th.pdfEnzyme, Pharmaceutical Aids, Miscellaneous Last Part of Chapter no 5th.pdf
Enzyme, Pharmaceutical Aids, Miscellaneous Last Part of Chapter no 5th.pdfSumit Tiwari
 
CARE OF CHILD IN INCUBATOR..........pptx
CARE OF CHILD IN INCUBATOR..........pptxCARE OF CHILD IN INCUBATOR..........pptx
CARE OF CHILD IN INCUBATOR..........pptxGaneshChakor2
 
internship ppt on smartinternz platform as salesforce developer
internship ppt on smartinternz platform as salesforce developerinternship ppt on smartinternz platform as salesforce developer
internship ppt on smartinternz platform as salesforce developerunnathinaik
 
ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPT
ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPTECONOMIC CONTEXT - LONG FORM TV DRAMA - PPT
ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPTiammrhaywood
 
EPANDING THE CONTENT OF AN OUTLINE using notes.pptx
EPANDING THE CONTENT OF AN OUTLINE using notes.pptxEPANDING THE CONTENT OF AN OUTLINE using notes.pptx
EPANDING THE CONTENT OF AN OUTLINE using notes.pptxRaymartEstabillo3
 

Recently uploaded (20)

Employee wellbeing at the workplace.pptx
Employee wellbeing at the workplace.pptxEmployee wellbeing at the workplace.pptx
Employee wellbeing at the workplace.pptx
 
Crayon Activity Handout For the Crayon A
Crayon Activity Handout For the Crayon ACrayon Activity Handout For the Crayon A
Crayon Activity Handout For the Crayon A
 
Class 11 Legal Studies Ch-1 Concept of State .pdf
Class 11 Legal Studies Ch-1 Concept of State .pdfClass 11 Legal Studies Ch-1 Concept of State .pdf
Class 11 Legal Studies Ch-1 Concept of State .pdf
 
Solving Puzzles Benefits Everyone (English).pptx
Solving Puzzles Benefits Everyone (English).pptxSolving Puzzles Benefits Everyone (English).pptx
Solving Puzzles Benefits Everyone (English).pptx
 
Final demo Grade 9 for demo Plan dessert.pptx
Final demo Grade 9 for demo Plan dessert.pptxFinal demo Grade 9 for demo Plan dessert.pptx
Final demo Grade 9 for demo Plan dessert.pptx
 
History Class XII Ch. 3 Kinship, Caste and Class (1).pptx
History Class XII Ch. 3 Kinship, Caste and Class (1).pptxHistory Class XII Ch. 3 Kinship, Caste and Class (1).pptx
History Class XII Ch. 3 Kinship, Caste and Class (1).pptx
 
Science 7 - LAND and SEA BREEZE and its Characteristics
Science 7 - LAND and SEA BREEZE and its CharacteristicsScience 7 - LAND and SEA BREEZE and its Characteristics
Science 7 - LAND and SEA BREEZE and its Characteristics
 
Model Call Girl in Tilak Nagar Delhi reach out to us at 🔝9953056974🔝
Model Call Girl in Tilak Nagar Delhi reach out to us at 🔝9953056974🔝Model Call Girl in Tilak Nagar Delhi reach out to us at 🔝9953056974🔝
Model Call Girl in Tilak Nagar Delhi reach out to us at 🔝9953056974🔝
 
Call Girls in Dwarka Mor Delhi Contact Us 9654467111
Call Girls in Dwarka Mor Delhi Contact Us 9654467111Call Girls in Dwarka Mor Delhi Contact Us 9654467111
Call Girls in Dwarka Mor Delhi Contact Us 9654467111
 
Mastering the Unannounced Regulatory Inspection
Mastering the Unannounced Regulatory InspectionMastering the Unannounced Regulatory Inspection
Mastering the Unannounced Regulatory Inspection
 
Alper Gobel In Media Res Media Component
Alper Gobel In Media Res Media ComponentAlper Gobel In Media Res Media Component
Alper Gobel In Media Res Media Component
 
Science lesson Moon for 4th quarter lesson
Science lesson Moon for 4th quarter lessonScience lesson Moon for 4th quarter lesson
Science lesson Moon for 4th quarter lesson
 
9953330565 Low Rate Call Girls In Rohini Delhi NCR
9953330565 Low Rate Call Girls In Rohini  Delhi NCR9953330565 Low Rate Call Girls In Rohini  Delhi NCR
9953330565 Low Rate Call Girls In Rohini Delhi NCR
 
Pharmacognosy Flower 3. Compositae 2023.pdf
Pharmacognosy Flower 3. Compositae 2023.pdfPharmacognosy Flower 3. Compositae 2023.pdf
Pharmacognosy Flower 3. Compositae 2023.pdf
 
Presiding Officer Training module 2024 lok sabha elections
Presiding Officer Training module 2024 lok sabha electionsPresiding Officer Training module 2024 lok sabha elections
Presiding Officer Training module 2024 lok sabha elections
 
Enzyme, Pharmaceutical Aids, Miscellaneous Last Part of Chapter no 5th.pdf
Enzyme, Pharmaceutical Aids, Miscellaneous Last Part of Chapter no 5th.pdfEnzyme, Pharmaceutical Aids, Miscellaneous Last Part of Chapter no 5th.pdf
Enzyme, Pharmaceutical Aids, Miscellaneous Last Part of Chapter no 5th.pdf
 
CARE OF CHILD IN INCUBATOR..........pptx
CARE OF CHILD IN INCUBATOR..........pptxCARE OF CHILD IN INCUBATOR..........pptx
CARE OF CHILD IN INCUBATOR..........pptx
 
internship ppt on smartinternz platform as salesforce developer
internship ppt on smartinternz platform as salesforce developerinternship ppt on smartinternz platform as salesforce developer
internship ppt on smartinternz platform as salesforce developer
 
ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPT
ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPTECONOMIC CONTEXT - LONG FORM TV DRAMA - PPT
ECONOMIC CONTEXT - LONG FORM TV DRAMA - PPT
 
EPANDING THE CONTENT OF AN OUTLINE using notes.pptx
EPANDING THE CONTENT OF AN OUTLINE using notes.pptxEPANDING THE CONTENT OF AN OUTLINE using notes.pptx
EPANDING THE CONTENT OF AN OUTLINE using notes.pptx
 

ActionScript3 collection query API proposal

  • 1. ActionScript3 collection query OO STYLE - LINQ TO OBJECTS IMPLEMENTATION PROPOSAL
  • 2. Introduction  Draft implementation, just an idea, would be great if we have something like this in ActionScript (but more robust, complex, optimized of course)  Purpose – collection sorting, filtering, grouping wrapper  OO-Style LINQ to Objects lib for flex
  • 3. Usage examples – first, last, any, itemAt //get first with title containing case insensitive string “Voislav Seselj” var query:IQuery = new CollectionQuery(_news); var firstItem:NewsFeed = query.where(new Conditions().contains("title", “Voislav Seselj", false)).first() as NewsFeed; //last item published in 2013 or 2014 var lastItem:NewsFeed = query.where(new Conditions().eq("year", 2014).OR.eq("year", 2013)).last() as NewsFeed; var usersQuery:IQuery = new CollectionQuery(); if(usersQuery.from(users).where(new Conditions().eq("name", "Peter Pan")).any()) { //excellent, there is a user (or users) with name "Peter Pan“ } //get third adault from the end of the collection ordered by name ascending and lastname //descending. var user:User = new CollectionQuery(users) .where(new Conditions().gte("years", 18)) .orderBy("name").orderBy("lastname", false) .itemAt(2) as User;
  • 4. Usage examples – where, select, limit //get users for given conditions ordered by company and then by years property var users:IList = usersQuery.where(new Conditions().lt("years", 18).gt("years", 5).OR .eq("company", "Company 1")) .orderBy("company“).orderBy("years") .execute() as IList; //select collection containing anonymous objects with properties given in select clause //extracted from user objects, for given conditions, ordered by salary with ascending order //and compare as numerics. //Limit to maximum 10 results var users:IList = new CollectionQuery() .select("name, lastname, company, salary") .from(users) .where(new Conditions().gte("salary", 40000).lte("salary", 45000)) //AND by default .orderBy("salary", true, true) .limit(10).execute() as IList;
  • 5. Usage examples – nested complex objects //select streets from complex member “address” for each user in users collection var streets:IList = usersQuery.select("address.street").from(users).execute() as IList; //select anonymous objects containing user’s name, lastname, address->number, address//>street, address->uniqueId->value, for users having address number greater then 400 in //Kragujevac city, or having address number lower then 400 and live in Belgrade city. //Order list by city ascending and by address number descending comparing address.number //property as numbers. var users:IList = usersQuery .select("name, lastname, address.number, address.street, address.uniqueId.value") .from(users) .where(new Conditions() .gt("address.number", 400).eq("address.city", "Kragujevac").OR. lt("address.number", 400).eq("address.city", "Belgrade")) .orderBy("address.city") .orderBy("address.number", false, true) .execute() as IList;
  • 6. Usage examples – groupBy //group users named Marija or Slavisa by city, ordere by name and then by lastname var query:IQuery = new CollectionQuery(); var groupResults:IQueryGroupResult = query .select("id, name, lastname, address.street") //get anonimous objects .from(users) .where(new Conditions() .eq("name", "Slaviša").OR .eq("name“,"Marija").AND.contains("lastname", "ić")) .orderBy("name").orderBy("lastname", false) //order by name , lastname descending .groupBy("address.city") //group by city .execute() as IQueryGroupResult; //get grouped results for each(var city:Object in groupResults.keys) //iterate through key collection { printUsersFromCity(key, groupResults[key] as IList); //and print collection for each key } if(groupResults.keys.contains("Kragujevac")) //test if there is a key { var kragujevcani:IList = groupResults["Kragujevac"] as IList; //print the collection }
  • 7. API  ICondition  IQuery  IQueryGroupResult  IQueryItemResult  CollectionQuery  Conditions  Predicate  QueryGroupResult  QueryResultItem
  • 8. IQuery /** * Query interface * @author Slavisa */ public interface IQuery { function select(value:String = null):IQuery; //select columns function from(coll:IList):IQuery; //sets collection to be queried function where(conditions:ICondition):IQuery; //sets condition chain function groupBy(property:String):IQuery; //sets group keys function orderBy(property:String, ascending:Boolean = true, numeric:Boolean = false):IQuery; //order by given property function limit(count:int = 100):IQuery; //limits result’s item count function first():Object; //returns first or null function last():Object; //returns last or null function itemAt(index:int):Object; //returns item by the given index, or null function execute():Object; //actual execution, returns IList or IQueryGroupResult object function any():Boolean; //determines if at least one result exists }
  • 9. ICondition /** * Condition interface * @author Slavisa */ public interface ICondition { function eq(prop:String, value:Object):ICondition; //equal function diff(prop:String, value:Object):ICondition; //not equal function contains(prop:String, value:String, caseSensitive:Boolean = true):ICondition; //contains function lt(prop:String, value:Object):ICondition; //lower than function lte(prop:String, value:Object):ICondition; //lower than or equal function gt(prop:String, value:Object):ICondition; //greater than function gte(prop:String, value:Object):ICondition; //greater than or equal function get OR():ICondition; function get AND():ICondition; function get root():ICondition; } //OR – new condition group //AND – new condition group //get root condition
  • 10. IQueryItemResult, QueryResultItem, IQueryGroupResult /** * Query Item result interface * @author Slavisa */ public interface IQueryItemResult { } /** * Query Item result dynamic class * Stores custom selection (anonimous object) * @author Slavisa */ public dynamic class QueryResultItem implements IQueryItemResult { } /** * Query Grouped results * @author pokimsla */ public interface IQueryGroupResult { function get keys():ArrayCollection; function get length():int; } //gets keys collection //gets number of groups
  • 11. QueryGroupResult public dynamic class QueryGroupResult extends Dictionary implements IQueryGroupResult { //Gets array collection of group keys public function get keys():ArrayCollection { var keys:ArrayCollection = new ArrayCollection(); for(var key:Object in this) { keys.addItem(key); } return keys; } //number of keys public function get length():int { return keys.length; } }
  • 12. Predicate /** * Predicate class * @author Slavisa * Used for combining multiple conditions joined with AND operator */ [Bindable] public class Predicate implements ICondition { /* Predicate types */ public static const EQ:String = "equal"; public static const DIFF:String = "different"; public static const CONTAINS:String = "contains"; public static const LT:String = "less"; public static const GT:String = "greater"; public static const GTE:String = "greater or equal"; public static const LTE:String = "lower or equal"; /* operators */ public static const OPERATOR_OR:String = "or"; public static const OPERATOR_AND:String = "and"; public var property:String; //property for comparison public var value:Object; //value to compare with public var type:String; //predicate type public var conditions:Conditions; //joining conditions (group of predicates to which this predicate belongs) public var attributes:Object; //additional attributes private var _root:ICondition; //root condition
  • 13. Predicate public function Predicate(cond:ICondition, prop:String, val:Object, type:String, attributes:Object = null) { this._root = cond.root; //set the root condition this.property = prop; this.value = val; this.type = type; this.conditions = cond as Conditions; this.conditions.addPredicate(this); //authomaticly add me to the predicate list this.attributes = attributes; } //creates next predicate (not equal) public function diff(prop:String, value:Object):ICondition { return createNextPredicate(prop, value, DIFF); } //creates next predicate (equal) public function eq(prop:String, value:Object):ICondition { return createNextPredicate(prop, value, EQ); } … //create next predicate for given values private function createNextPredicate(prop:String, value:Object, type:String, attributes:Object = null):ICondition { var pred:Predicate = new Predicate(conditions, prop, value, type, attributes); return pred; }
  • 14. Predicate // Creates new condition with OR relation public function get OR():ICondition { var condition:Conditions = new Conditions(); condition.type = OPERATOR_OR; condition.root = root; this.conditions.next = condition; return condition; } //creates new condition with AND relation public function get AND():ICondition { var condition:Conditions = new Conditions(); condition.type = OPERATOR_AND; condition.root = root; this.conditions.next = condition; return condition; } //gets root condition public function get root():ICondition { return _root; } }
  • 15. Conditions /** * Condition contains group of predicates, used for joining multiple condition groups (predicates) * @author Slavisa * <br/> * Condition chain boolean result is calculated from last to root condition group */ public class Conditions implements ICondition { private var _predicates:ArrayCollection=new ArrayCollection(); //predicate collection private var _next:ICondition; //next condition in a row private var _root:Conditions; //starting condition public var type:String; //starting condition shouldn't have a type property populated. EQ, OR, AND, LT... //Condition contains group of predicates, used for joining multiple condition groups (predicates) public function Conditions() { _root = this; } /** * add predicates to a collection * @param predicate * predicates are validated in groups with ANR logical operator */ public function addPredicate(predicate:ICondition):void { _predicates.addItem(predicate); }
  • 16. Conditions //creates and appends diff predicate public function diff(prop:String, value:Object):ICondition { return new Predicate(this, prop, value, Predicate.DIFF); } //creates and appends eq predicate public function eq(prop:String, value:Object):ICondition { return new Predicate(this, prop, value, Predicate.EQ); } //… other predicates, getters and setters //OR condition does nothing on Conditions instance public function get OR():ICondition { return this; } //AND condition does nothing on Conditions instance public function get AND():ICondition { return this; } }
  • 17. CollectionQuery /** * Actual collection query implementation * @author Slavisa */ public class CollectionQuery implements IQuery { private var _coll:IList; //collection private var _conditions:ICondition; //conditions private var _comparatorGroups:ArrayCollection; //comparator groups built before collection iteration private const _comparatorMap:Object = createComparatorMap(); //comparator delegates private var _selectColumns:String = null; //select columns. If null, row items are selected private var _limitCount:int = 0; //limited item count private var _groupBy:String = null; //group by this property private var _orderBy:ArrayCollection = new ArrayCollection(); //order by these properties private var _hasGroupBy:Boolean = false; private var _hasOrderBy:Boolean = false; //ctor public function CollectionQuery(coll:IList = null, selectColumns:String = null) { _coll = coll; this._selectColumns = selectColumns; }
  • 18. CollectionQuery //creates comparator delegate map private function createComparatorMap():Object { var map:Object = new Object(); map[Predicate.DIFF] = diff; map[Predicate.EQ] = eq; map[Predicate.GT] = gt; map[Predicate.GTE] = gte; map[Predicate.LT] = lt; map[Predicate.LTE] = lte; map[Predicate.CONTAINS] = contains; return map; } //contains comparator private function contains(a:Object, b:Object, attributes:Object = null):Boolean { var strA:String = attributes && attributes.caseSensitive ? String(a) : String(a).toLowerCase(); var strB:String = attributes && attributes.caseSensitive ? String(b) : String(b).toLowerCase(); return strA.indexOf(strB) > -1; } //equal comparator private function eq(a:Object, b:Object, attributes:Object = null):Boolean { return a == b; } //…other comparators
  • 19. CollectionQuery //sets select properties public function select(value:String = null):IQuery { _selectColumns = value; return this; } //sets target collection public function from(coll:IList):IQuery { _coll = coll; return this; } //sets conditions root public function where(conditions:ICondition):IQuery { this._conditions = conditions.root; return this; } /* Similar for : groupBy orderBy limit */
  • 20. CollectionQuery public function first():Object { if(_hasGroupBy) throw new Error("First() is allowed only for non-grouped results"); var result:IList = runExecution(1) as IList; return result.length > 0 ? result[0] : null; } public function last():Object { if(_hasGroupBy) throw new Error("Last() is allowed only for non-grouped results"); var result:IList = runExecution(1, true) as IList; return result.length > 0 ? result[0] : null; } public function itemAt(index:int):Object { if(_hasGroupBy) throw new Error("ItemAt() is allowed only for non-grouped results"); if(index < 0) throw new ArgumentError("Invalid argument for itemAt method"); var result:IList = runExecution(index + 1) as IList; return result.length > (index + 1) ? null : result[index]; }
  • 21. CollectionQuery public function execute():Object //interface impl { return runExecution(_limitCount); } //actual query execution private function runExecution(limit:int = 0, reverse:Boolean = false):Object { implementation details excluded for insufficient space, if anyone cares send me an email to slavisapokimica@yahoo.com, I’ll be happy to provide all you need } private function orderCollection(collection:ArrayCollection):void { if(_orderBy.length == 0) return; var sort:Sort = new Sort(); sort.fields = new Array(); for each(var fieldDef:Object in _orderBy) { var sortField:SortField = new SortField(fieldDef.field, false, !fieldDef.ascending, fieldDef.numeric); sort.fields.push(sortField); } collection.sort = sort; collection.refresh(); }
  • 22. CollectionQuery /** * Creates result item * @param item * @return Row Item or anonymous object with properties generated from selectColumns variable */ private function createResultItem(item:Object):Object { if(_selectColumns == null) //return row item return item; var columns:Array = _selectColumns.split(","); //split columns if(columns.length == 1) return extractPropertyValue(item, columns[0]); //if only one property, than return it var res:QueryResultItem = new QueryResultItem(); //anonymous dynamic object for each(var column:String in columns) //populate anonymous object { var col:String = StringUtil.trim(column); var newPropname:String = col.replace(/[.]/g, '_'); res[newPropname] = extractPropertyValue(item, col); //set property value } return res; }
  • 23. CollectionQuery /** * extracts property from given item */ private function extractPropertyValue(item:Object, property:String):Object { var single:String = StringUtil.trim(property); if(single.indexOf(".") == -1) { if( !item.hasOwnProperty(single) ) throw new ArgumentError("Property with name "" + single + "" does not exist!"); return item[single]; } //recursive call when extracting complex member’s properties return extractPropertyValue(item[property.substring(0, property.indexOf("."))], property.substring(property.indexOf(".") + 1)); }
  • 24. CollectionQuery /** * Actual filtering logic * @param item collection item currently being validated * @param validationGroups condition groups to be validated with * @return Boolean * <ul> * <li>validation groups empty - return true</li> * <li>single item in validation group - return predicate validation result</li> * <li>iterate through all condition groups and its predicates and validate them all</li> * </ul> */ private function filterFunction(item:Object, validationGroups:ArrayCollection):Boolean { if(validationGroups.length == 0) return true; if(validationGroups.length == 1) return validatePredicates(item, _comparatorGroups[0].predicates); var result:Boolean = validatePredicates(item, _comparatorGroups[0].predicates); for (var i:int = 0; i < _comparatorGroups.length - 1; i++) { result = _comparatorGroups[i].operation == Predicate.OPERATOR_AND ? result && validatePredicates(item, _comparatorGroups[i + 1].predicates) : result || validatePredicates(item, _comparatorGroups[i + 1].predicates); } return result; }
  • 25. What’s next  Optimization  Validation  Interface expansion  “In” and “Between” conditions  Joins  Comparison between two properties  Query reset  Nested conditions  And much more…
  • 26. Also kewl to have - code snippets I <template autoinsert="true" context="com.adobe.flexide.as.core.codetemplates.action_script" deleted="false" description="Query first item by the given conditions" enabled="true" name="query_first"> var query:IQuery = new CollectionQuery(${_collection}); var firstItem:${type} = query.where(new Conditions().${operation:values(eq, lt, lte, gt, gte, diff, contains)}("${prop}", ${value})).first() as ${type}; </template> <template autoinsert="true" context="com.adobe.flexide.as.core.codetemplates.action_script" deleted="false" description="Order queried collection" enabled="true" name="query_order"> var query:IQuery = new CollectionQuery(${_collection}); var orderedResults:IList = query.where(new Conditions() .${operation:values(eq, lt, lte, gt, gte, diff, contains)}("${prop}", ${value})) .orderBy("${orderProp}", ${ascending:values(true, false)}, ${numeric:values(false, true)}) .execute() as IList; </template>
  • 27. Code snippets II <template autoinsert="true" context="com.adobe.flexide.as.core.codetemplates.action_script" deleted="false" description="Grouping query results" enabled="true" name="query_group"> var query:IQuery = new CollectionQuery(${_collection}); var groups:IQueryGroupResult = query .where(new Conditions() .${operation:values(eq, lt, lte, gt, gte, diff, contains)}("${prop}", ${value})) .groupBy("${groupProperty}") .execute() as IQueryGroupResult; for each(var key:Object in groups.keys) { var groupedItems:ArrayCollection = groups[key] as ArrayCollection; } </template>
  • 28. Contact details  Email> slavisapokimica@yahoo.com