FlexによるArrayCollectionの再構築


プロジェクトの必要に応じて、ArrayCollectionを再構築します.次の機能が含まれます.
1、並べ替え
2,moveFirst moveLast moveNext movePreレコードナビゲーションとindexのオブジェクトの選択
3、削除、更新、挿入、レコードの追加機能
4、フィルタリング
次に例を示します.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init();">
<mx:Script>
	<![CDATA[
		import mx.collections.CursorBookmark;
		import com.hexagonstar.util.debug.Debug;
		import org.app.utils.common.collections.MyArrayCollection;
		import com.adobe.serialization.json.JSON;
		var arr:Array=[
			{a:1,b:1,c:1},
			{a:21,b:21,c:21},
			{a:12,b:12,c:12},
			{a:10,b:10,c:10},
			{a:2,b:2,c:2}
			];
		[Bindable]
		var coll:MyArrayCollection = null;
		[Bindable]
		var scc:String = null;
		private function init():void{
			coll =new MyArrayCollection(arr);
			//var sortArr:Array=[{name:"a"},{name:"b"}];
			//coll.sortCollection(sortArr);
			src.text= coll.toString();
			//dest.text = JSON.encode(coll.currentItem);
			scc = coll.toString();
			dest.text = scc;
			//keywords
			coll.keywords=["a"];
		}
		
		private function insert():void{
			var s:String = src.text;
			var o:Object = JSON.decode(s);
			coll.insertItem(o);
			scc = coll.toString();
			dest.text = scc;
		}
		private function append():void{
			var s:String = src.text;
			var o:Object = JSON.decode(s);
			coll.appendItem(o);
			scc = coll.toString();
			dest.text = scc;
		}
		private function moveFirst():void{
			var o:Object = coll.moveFirst();
			dest.text = JSON.encode(o);
		}
		private function moveLast():void{
			var o:Object = coll.moveLast();
			dest.text = JSON.encode(o);
		}
		private function moveNext():void{
			var o:Object = coll.moveNext();
			dest.text = JSON.encode(o);
		}
		private function movePre():void{
			var o:Object = coll.movePrevious();
			dest.text = JSON.encode(o);
		}
		private function doClear():void{
			dest.text = "";
		}
		private function doUpd():void{
			var o:Object = JSON.decode(src.text);
			coll.updateItem(o);
			o = coll.currentItem;
			dest.text = JSON.encode(o);
		}
		private function doDel():void{
			var o:Object = JSON.decode(src.text);
			var flg:Boolean = coll.remove();
			Debug.trace("--remove:"+flg);
			scc = coll.toString();
			dest.text = scc;
		}
	]]>
</mx:Script>
	<mx:TextArea id="src" x="25" y="40" width="267" height="103"/>
	<mx:Button x="25" y="10" label="  " click="doUpd();"/>
	<mx:Button x="188" y="10" label="  " click="doDel();"/>
	<mx:Button x="244" y="10" label="  "/>
	<mx:Button x="76" y="10" label="  " click="insert();"/>
	<mx:Button x="132" y="10" label="  " click="append();"/>
	<mx:TextArea id="dest" x="300" y="40" width="333" height="103" editable="false" text="{scc}"/>
	<mx:Button x="25" y="299" label="|&lt;" toolTip="   " click="moveFirst();"/>
	<mx:Button x="125" y="299" label="&gt;&gt;" toolTip="   " click="moveNext();"/>
	<mx:Button x="73" y="299" label="&lt;&lt;" toolTip="   " click="movePre();"/>
	<mx:Button x="177" y="299" label="&gt;|" toolTip="    " click="moveLast();"/>
	<mx:DataGrid x="25" y="151" width="608" height="143" dataProvider="{coll}">
		<mx:columns>
			<mx:DataGridColumn headerText="ColumnA" dataField="a"/>
			<mx:DataGridColumn headerText="ColumnB" dataField="b"/>
			<mx:DataGridColumn headerText="ColumnC" dataField="c"/>
		</mx:columns>
	</mx:DataGrid>
	<mx:Button x="585" y="10" label="  " toggle="true" click="doClear();"/>
</mx:Application>

ソースコードは次のとおりです.

/**
 *   :
 * coll=new ArrayCollection(
 * 			[
 * 			 {name: "Martin Foo", age: 25}, 
 * 			 {name: "Joe Bar", age: 15}, 
 *           {name: "John Baz", age: 23}
 *          ]
 * );
 * coll.addItemAt({name: "James Fez", age: 40}, 0);
 */
package org.app.utils.common.collections
{	
	import flash.events.Event;
	
	import mx.collections.ArrayCollection;
	import mx.collections.CursorBookmark;
	import mx.collections.IViewCursor;
	import mx.collections.Sort;
	import mx.collections.SortField;
	import mx.events.FlexEvent;
	import mx.logging.ILogger;
	
	import org.app.framework.AppContext;
	import org.app.utils.common.MyJSONUtils;
	import org.app.utils.log.MyLoggerManager;

	public class MyArrayCollection extends ArrayCollection
	{
		////////////////////////////////////////////////////////////////////////
		/*      */
		public static const RL_NAME:String = "name";//         。[String]
		public static const RL_CASEINSENSITIVE:String = "caseInsensitive";//Boolean                  。
		public static const RL_DESCENDING:String = "descending";//Boolean              。
		/*    */
		//          
		public static const EVENT_CURSOR_UPDATE:String = "event_cursor_update";
		/*Object                 (number/int/uint) 
		 *             ,             。*/
		public static const RL_NUMERIC:String = "numeric";
		////////////////////////////////////////////////////////////////////////
		private var logger:ILogger = MyLoggerManager.getLogger("MyArrayCollection",AppContext.getInstance().appLogTarget);
		////////////////////////////////////////////////////////////////////////
		/*  */
		private var _cursor:IViewCursor = null;//    
		private var _currentItem:Object = null;//        
		/*   JSON  ,   keys*/
		private var _keys:Array = null;//      json properties
		private var _keywords:Array = null;//  properties   ,      
		public function MyArrayCollection(source:Array=null)
		{
			super(source);
			//         
			this._cursor = this.createCursor();
			//          
			this._cursor.addEventListener(FlexEvent.CURSOR_UPDATE,fireCursorUpdate,false,0,true);
			//         --    cursor update  
			this._cursor.seek(CursorBookmark.CURRENT);
			//   keys      keys
			this.fetchKeys();
		}
		
		////////////////////////////////////////////////////////////////////////
		/**
		 *              ,            ,
		 *              currentItem   。
		 * @param FlexEvent
		 * @return
		 */
		private function fireCursorUpdate(event:FlexEvent):void{
			//      
			this._currentItem = (event.currentTarget as IViewCursor).current;
			//   moveLast moveFirst   2   ,         ,   
			var a:String = "   ";
			if (this._currentItem) {
				a="  ";
				this.dispatchEvent(new Event(EVENT_CURSOR_UPDATE));
			}
			var s:String = MyJSONUtils.encode(this._currentItem);
			logger.debug("--    cursor update   ,    :"+s+"["+a+"]");
		}
		////////////////////////////////////////////////////////////////////////
		////////////////////////////////////////////////////////////////////////
		public function set cursor(cursor:IViewCursor):void{
			this._cursor = cursor;
		}
		public function get cursor():IViewCursor{
			return this._cursor;
		}
		public function set currentItem(o:Object):void{
			//           
			this.updateItem(o);
			//this._currentItem = o;
		}
		public function get currentItem():Object{
			return this._currentItem;
		}
		////////////////////////////////////////////////////////////////////////
		public function fetchKeys():void{
			if(this.length>0){
				var o:Object = this.getItemAt(0);
				this._keys = MyJSONUtils.fetchKeys(o);
			}else{
				this._keys = [];
			}
		}
		public function getKeys():Array{
			if(this._keys.length<=0){
				this.fetchKeys();
			}
			return this._keys;
		}
		public function set keywords(k:Array):void{
			this._keywords = k;
		}
		public function get keywords():Array{
			return this._keywords;
		}
		////////////////////////////////////////////////////////////////////////
		////////////////////////////////////////////////////////////////////////
		
		/**
		 *              ??????
		 * @param Object  json object eg:{name:"xxx_name", age:34 .....}
		 * @param String        Sort       
		 * @return int      
		 * 
		 * @see mx.collections.Sort
		 */
		public function checkExist(conditionObj:Object,mode:String=Sort.ANY_INDEX_MODE):int{
			var sort:Sort = new Sort();
			return sort.findItem(this.source,conditionObj,mode);   
		}
		
		/**
		 * [       ]
		 *           ,  keys     key    ,    ,      key  
		 * @param Object
		 * @param Array     key
		 * @return Boolean true  
		 */
		public function isExist(o:Object,keys:Array=null):Boolean{
			var key1:Array = keys;
			if(key1==null){
				key1 = MyJSONUtils.fetchKeys(o);
			}
			var item1:String = null;
			var l:int=key1.length;
			for each(var obj:Object in this){
				var flg:int = 0;
				for(var i:int=0;i<l;i++){
					item1=key1[i];
					if(o[item1]==obj[item1]){
						flg++;
					}
				}
				if(flg==l)return true;
			}
			return false;
		}
		/**
		 *      ,      
		 * @param Object       
		 * @return Boolean true  
		 */
		override public function contains(item:Object):Boolean{
			return isExist(item,this._keywords);
		}
		////////////////////////////////////////////////////////////////////////
		/**
		 *          ,          :
		 * -- name : String          。 
		 * -- caseInsensitive : Boolean                  。 
		 * -- descending : Boolean              。
		 * -- numeric : Object                 (number/int/uint) 
		 *                          ,             。 
		 * eg:[{name:'age',caseInsensitive:true,descending:false,numeric:null},
		 *                   {name:'age',descending:false}...]
		 *       ,      json  ,      :name,caseInsensitive,descending,numeric,
		 *     ,name    ,     。
		 * @param Object       
		 * @return
		 * @see mx.colloections.SortField
		 * 
		 */
		public function sortCollection(conditionObj:Array):void{
			var leng:int = conditionObj.length;
			var fields:Array = [];
			var sortField:SortField = null;
			var o:Object=null;
			
			var name:String=null;
			var caseInsensitive:Boolean=false;
			var descending:Boolean = false;
			var numeric:Object = null;
			for(var i:int=0;i<leng;i++){
				o = conditionObj[i];
				sortField = new SortField();
				//    
				sortField.name=o[MyArrayCollection.RL_NAME];
				
				var tmp:Object = o[MyArrayCollection.RL_CASEINSENSITIVE];
				caseInsensitive=tmp==null?false:true;
				sortField.caseInsensitive=caseInsensitive;
				
				tmp = o[MyArrayCollection.RL_DESCENDING];
				descending=tmp==null?false:true;
				sortField.descending=descending;
				
				tmp = o[MyArrayCollection.RL_NUMERIC];
				numeric=tmp==null?null:tmp;
				sortField.numeric=numeric;
				//     
				fields.push(sortField);
			}
			var sort:Sort = new Sort();
			sort.fields=fields;
			this.sort = sort;
			this.refresh();
		}
		////////////////////////////////////////////////////////////////////////
		/**
		 *   ,                      ,
		 * coll = new ArrayCollection([
		 *                      {name:"Martin Foo", age:25},      
         *                      {name:"Joe Bar", age:15},      
         *                      {name:"John Baz", age:23},      
         *                      {name:"Matt Baz", age:21}]);
         *   func:
         * private function filterFunc(value:Object):Object {      
         *  if(Number(value.age) > 21) {      
        *    return true;      
         *  }
         *  return false;      
         *} 
         * @param Function   
         * @return
		 */
		public function filterCollection(filterFunc:Function):void{
			this.filterFunction = filterFunc;
			this.refresh();
		}
		////////////////////////////////////////////////////////////////////////
		
		////////////////////////////////////////////////////////////////////////
		////////////////////////////////////////////////////////////////////////
		/**
		 *        ,  cursorMove          
		 * @param Boolean         
		 * @return Object         
		 */
		public function firstItem(cursorMove:Boolean=true):Object{
			if(cursorMove){
				return this.moveFirst();
			}
			return this.getItemAt(0);
		}
		/**
		 *         ,  cursorMove          
		 * @param Boolean         
		 * @return Object          
		 */
		public function lastItem(cursorMove:Boolean=true):Object{
			if(cursorMove){
				return this.moveLast();
			}
			return this.getItemAt(this.length-1);
		}
		/**
		 *          ,            .
		 * @param Object
		 * @return Boolean true   false  
		 */
		public function appendItem(o:Object):Boolean{
			//            
			var exist:Boolean= this.contains(o);
			if(!exist){
				this.addItem(o);
				//      
				this.moveCursorTo(o);
				if(this._currentItem){
					return true;
				}
			}
			return false;
		}
		
		/**
		 *            
		 * @param Object 
		 * @return Boolean
		 */
		public function insertItem(o:Object):Boolean{
			//            
			var exist:Boolean= this.contains(o);
			if(!exist){
				this._cursor.insert(o);
				//      
				this.moveCursorTo(o);
				if(this._currentItem){
					return true;
				}
			}
			return false;
		}
		////////////////////////////////////////////////////////////////////////
		////////////////////////////////////////////////////////////////////////
		////////////////////////////////////////////////////////////////////////
		////////////////////////////////////////////////////////////////////////
		/**
		 *            ,        ,         ,        
		 * @return Object         
		 * 
		 */
		public function remove():Object {
			var o:Object=this._cursor.remove();
			if (!this._currentItem) {
				this._cursor.movePrevious();
			}
			return o;
		}
		/**
		 *        
		 * @param Object
		 * @return Boolean true   
		 */
		public function removeItem(o:Object):Boolean{
			this.moveCursorTo(o);
			var o:Object = this.remove();
			if(o)return true;
			return false;
		}
		
		/**
		 *       
		 */
		override public function removeAll():void{
			super.removeAll();
			this.source = [];
		}
		////////////////////////////////////////////////////////////////////////
		////////////////////////////////////////////////////////////////////////
		////////////////////////////////////////////////////////////////////////
		/**
		 *            
		 * @param Object     
		 * @return
		 */
		public function updateItem(o:Object):void{
			var keys:Array = MyJSONUtils.fetchKeys(o);
			var l:int = keys.length;
			var key:String=null;
			for(var i:int=0;i<l;i++){
				key = keys[i];
				if(this._currentItem[key]){
					this._currentItem[key]=o[key];
					this.itemUpdated(this._currentItem);//    ui  
				}
			}
		}
		////////////////////////////////////////////////////////////////////////
		////////////////////////////////////////////////////////////////////////
		/**
		 *            ,
		 * @param Object     
		 * @return Object        
		 */
		public function moveCursorTo(o:Object):Object {
			//      
			var index:int=this.getItemIndex(o);
			return this.moveCursorByIndex(index);
		}
		public function moveCursorByIndex(index:int):Object{
			if(index < 0 || index >= this.length)return null;
			var oldIndex:int = this.getItemIndex(this._currentItem);
			var offset:int = 0;
			if (oldIndex > index) {
				offset = -(oldIndex - index);
			} else if (oldIndex < index) {
				offset = index - oldIndex;
			}
			this._cursor.seek(this._cursor.bookmark, offset);
			return this._currentItem;
		}
		
		/**
		 *          ,          
		 * @return Object          
		 */
		public function moveFirst():Object{
			//      
			this._cursor.seek(CursorBookmark.FIRST);
			//       
			// cursor update        
			//      
			return this._currentItem;
		}
		
		/**
		 *           ,           
		 * @return Object          
		 */
		public function moveLast():Object{
			//      
			this._cursor.seek(CursorBookmark.LAST);
			//       
			// cursor update        
			//      
			return this._currentItem;
		}
		
		/**
		 *          ,           
		 * @return Object          
		 */
		public function moveNext():Object {
			if (!this._cursor.afterLast) {
				this._cursor.moveNext();
				//this._currentItem = this._cursor.current;
				if (!this._currentItem) {
					this._cursor.movePrevious();
				}
			}
			return this._currentItem;
		}
		
		/**
		 *          ,           
		 * @return Object          
		 */
		public function movePrevious():Object {
			if (!this._cursor.beforeFirst) {
				this._cursor.movePrevious();
				if (!this._currentItem) {
					this._cursor.moveNext();
				}
			}
			return this._currentItem;
		}
		////////////////////////////////////////////////////////////////////////
		////////////////////////////////////////////////////////////////////////
		/**
		 *        
		 * @return String 
		 */
		override public function toString():String{
			var s:String = "";
			var l:int=this.length;
			for(var i:int=0;i<l;i++){
				s+=MyJSONUtils.encode(this.getItemAt(i));
			}
			return s;
		}
		
		
	}//end class
}//end package