Skip to content

Instantly share code, notes, and snippets.

@andreiRS
Created March 4, 2012 11:17
Show Gist options
  • Save andreiRS/1972456 to your computer and use it in GitHub Desktop.
Save andreiRS/1972456 to your computer and use it in GitHub Desktop.
AS3 Object that can copy all properties(+recursive) from another object to himself
package com.rsurdu.utils
{
import flash.utils.Dictionary;
import flash.utils.describeType;
import flash.utils.getDefinitionByName;
import flash.utils.getQualifiedClassName;
import mx.utils.UIDUtil;
public class CloneableVO extends Object implements ICloneable
{
public var uid:String;
public function CloneableVO(data:Object = null)
{
super();
if (data)
clone(data);
if (uid == null || uid.length == 0)
uid = UIDUtil.createUID();
}
public function clone(o:Object, forceNewReference : Boolean = false):Object
{
if(forceNewReference)
clonedObjects = new Dictionary(true);
if (clonedObjects[o] == null)
cloneInternal(o, this);
else
return clonedObjects[o];
return this;
}
private var clonedObjects:Dictionary = new Dictionary(true);
private function cloneInternal(source:Object, target:Object):void
{
clonedObjects[source] = target;
var classInfo:XML = describeType(target);
var propertyList:XMLList = classInfo..variable + classInfo..accessor.(@access == "readwrite");
var propertyName:String;
var propertyType:String;
var propertyValue:*;
var fullClassName:String;
var viewClass:Class;
var instance:*;
var classIsDynamic:Boolean = classInfo.@isDynamic == "true";
if (classIsDynamic)
{
var dynamicTypeOf:String;
for (var dynamicProp:String in source)
{
dynamicTypeOf = typeof source[dynamicProp];
propertyList += <variable name={dynamicProp} type={dynamicTypeOf}/>;
}
}
for each (var propertyXML:XML in propertyList)
{
propertyName = propertyXML.@name;
propertyType = propertyXML.@type;
propertyType = propertyType.toLowerCase();
if (classIsDynamic == false && source.hasOwnProperty(propertyName) == false)
continue;
propertyValue = source[propertyName];
if (propertyValue == null)
continue;
if (isSimpleType(propertyType))
{
target[propertyName] = propertyValue;
} else if (propertyType == "date")
{
//TODO: Test with date
target[propertyName] = new Date(
(propertyValue as Date).fullYear,
(propertyValue as Date).month,
(propertyValue as Date).date,
(propertyValue as Date).hours,
(propertyValue as Date).minutes,
(propertyValue as Date).seconds
);
} else if (propertyType == "array")
{
if (target[propertyName] == null)
target[propertyName] = [];
var index:uint = 0;
//TODO: Must change the algoritm so it knows
//how to mach elements in array for correct cloning
// also to take in consideration when the arrays have different nr of elements
for each (var arrayElement:Object in propertyValue)
{
if (arrayElement == null)
{
index++;
continue;
}
if(clonedObjects[arrayElement] != null)
{
index++;
continue;
}
if (target[propertyName][index] == null)
{
fullClassName = getQualifiedClassName(arrayElement);
if (fullClassName == "String")
{
(target[propertyName] as Array)[index] = (source[propertyName] as Array)[index];
index++;
continue;
} else
{
viewClass = getDefinitionByName(fullClassName) as Class;
instance = new viewClass();
}
} else
{
instance = target[propertyName][index];
}
cloneInternal(arrayElement, instance);
(target[propertyName] as Array)[index] = instance;
index++;
}
} else
{
if(clonedObjects[propertyValue]==null){
fullClassName = getQualifiedClassName(propertyValue);
viewClass = getDefinitionByName(fullClassName) as Class;
if (target[propertyName] == null)
target[propertyName] = new viewClass();
cloneInternal(propertyValue, target[propertyName]);
}else
{
if (target[propertyName] == null)
target[propertyName] = clonedObjects[propertyValue];
}
}
}
}
private function isSimpleType(type:String):Boolean
{
switch (type.toLowerCase())
{
case "uint":
case "int":
case "number":
case "string":
case "boolean":
case "class":
{
return true;
}
}
return false;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment