Hi and thanks for that code - nice!

If I'm getting it right... The Translator determines the type of Object it
is looking at and 'converts' it to that Class Data Type?...

So you still need to have all the Classes defined in your flex package in
order for the Translator to convert all the properties to Class fields,
etc...


Is this correct?


Thanks,
Nick




On 4 February 2010 09:33, claudiu ursica <the_bran...@yahoo.com> wrote:

>
>
> I am working agasinst very large API. Lots of Enumerations and codes (both
> errors and others). If I make the calls myself I can have the flexibility
> that I want. Use only what I need at any certain time. I build the
> architecture around Pure MVC Framework and it seemed better for my to go
> that way instead of generating a bunch of automated classes. If you go with
> type objects you get a better compile time checking. It depends on your
> project, and what you want to achieve in the end. I just didn't like what I
> saw in the generated code though is less prone to error than the one I
> wrote.
>
> I make the calls within delegate classes created inside proxy classes and
> use this utility to interpret the result inside proxy classes:
>
> package whatever.utils
> {
>     import mx.collections.ArrayCollection;
>
>     public class ObjectTranslator
>     {
>         import mx.utils.ArrayUtil;
>         import flash.utils.*;
>         import mx.core.DeferredInstanceFromClass;
>
>         public static function translateArrayObjects(arrayOfObjects:Array,
> translateToClass:Class, upperCaseFromVar:Boolean=false):Array
>         {
>             // describeType describes a class and all of its properties
>             var classInfo:XML = describeType(translateToClass);
>
>             // get the class name, in order to instantiate more classes
>             var className:String = classin...@name;
>             var i:Number = new Number();
>             var returnArray:Array = new Array();
>
>             // get a reference to the class to create new classes
>             var classRef:Class = Class(getDefinitionByName(className ));
>             var tempObj:Object = new classRef();
>
>             if (arrayOfObjects != null)
>             {
>                 for (i=0; i <arrayOfObjects.length; i++)
>                 {
>                     // for each new object, create a new class of the class
> type that was passed in.
>                     tempObj = new classRef();
>                     // send it off to translateObject function. send it the
> class to populate
>                     returnArray.push(translateObject(arrayOfObjects[i],
> tempObj, classInfo, upperCaseFromVar));
>                 }
>             }
>             return returnArray;  // return the translated array
>         }
>
>
>         public static function translateObject(translateFrom:Object,
> translateTo:Object, classInfo:XML = null, upperCaseFromVar:Boolean =
> false):Object
>         {
>             var vType:String;
>             var vName:String;
>             var fromName:String;
>
>             // if class information has already been sent in, we don't need
> to re-fetch it.
>             if (classInfo == null)
>             {
>                 classInfo = describeType(translateTo);
>             }
>
>             for each (var v:XML in classInfo..variable)
>             {
>                 try
>                 {
>                     // xml values don't exactly match the variable name
> unless it knows for sure it's a string
>                     vName = v...@name;
>                     vType = v...@type;
>
>                     if (upperCaseFromVar)
>                     {
>                         fromName = vName.toUpperCase();
>                     }
>                     else
>                     {
>                         fromName = vName;
>                     }
>
>                     // check to see if the untyped object has a property
> that matches the typed property
>                     // if it does, then translate it.  if not, skip it.
>                     // this is done to maintain integrity with the
> application and the internal classes.
>                     // internal classes are static (unless they've been
> made dynamic) an error will result if
>                     // and unknown variable is set in it.
>                     if (translateFrom.hasOwnProperty(vName) &&
> translateFrom[vName] != null)
>                     {
>                         // Only need to check for a few types here.
> variables should come across
>                         // in a limited number of base object types, ie
> numbers, ints, dates, strings, etc.
>                         // anything else is assumed to be a class and will
> be sent for translation as well.
>                         // the one case that is not dealt with here is when
> an array of objects underneath
>                         // an array of objects.  This can be theoretically
> set up, but there's no clear
>                         // an array of objects has to be a special type of
> array, which in most cases only limits
>                         // the objects that can be store in it to a
> specific class.  the simplest way around
>                         // this is to send back a simple array of untyped
> objects which can then be translated
>                         // at the point that they are needed.
>
>                         switch (vType)
>                         {
>                             case "Array":
>                                 // in beta 3 SOAP sequences were typed as
> arrays by FLEX.
>                                 if (translateFrom[vName] is
> ArrayCollection)
>                                 {
>                                     translateTo[vName] =
> translateFrom[fromName].source;
>                                 }
>                                 else if (translateFrom[fromName] is Array)
>
>                                 {
>                                     translateTo[vName] =
> translateFrom[fromName];
>                                 }
>                                 break;
>                             case "mx.collections::ArrayCollection":
>                                 // in the GA release it looks like SOAP
> sequences are
>                                 // typed as arrayCollections.  Support has
> been left in for both
>                                 // types... just in case, so this function
> can be used for both types.
>                                 if (translateFrom[fromName] is
> ArrayCollection)
>                                 {
>                                     translateTo[vName] =
> translateFrom[fromName];
>                                 }
>                                 else if (translateFrom[fromName] is Array)
>
>                                 {
>                                     translateTo[vName].source =
> translateFrom[fromName];
>                                 }
>                                 break;
>                             case "Number" :
>                                 // sometimes numbers come across as a
> complexString.  this can
>                                 // cause a mess at runtime if there is a
> need to check against a
>                                 // simple number type.
>                                 translateTo[vName] = new
> Number(translateFrom[fromName]);
>                                 break;
>                             case "int" :
>                                 // ditto for ints
>                                 translateTo[vName] = new
> int(translateFrom[fromName]);
>                                 break;
>                             case "uint" :
>                                 // ditto for uints
>                                 translateTo[vName] = new
> uint(translateFrom[fromName]);
>                                 break;
>                             case "Date":
>                                 // ditto for dates.  what's nice about this
> function is that with a little
>                                 // work, dates can automatically be
> transfered from a UTC format or a string
>                                 // format (used sometimes for easy
> transport)  into an actual date format
>                                 // which should be easier to use.
>
>                                 if (translateFrom[fromName] is Date)
>                                 {
>                                     translateTo[vName] =
> translateFrom[fromName];
>                                 }
>                                 else if (translateFrom[fromName] is String)
>
>                                 {
>                                     translateTo[vName] =
> parseDateFromString(translateFrom[fromName]);
>                                 }
>                                 else if (translateFrom[fromName] is Number
> || translateFrom[fromName] is int ||    translateFrom[fromName] is uint)
>                                 {
>                                     translateTo[vName] =
> parseUtcDate(translateFrom[fromName]);
>                                 }
>                                 break;
>                             case "Boolean":
>                                 // Booleans get typed as a complexString
> sometimes too.
>                                 translateTo[vName] =
> getBooleanValue(translateFrom[fromName]);
>                                 break;
>                             case "String":
>                                 translateTo[vName] = new
> String(translateFrom[fromName]);
>                                 break;
>                             case "Object":
>                                 translateTo[vName] =
> translateFrom[fromName];
>                                 break;
>                             default:
>                                 // assuming that anything that makes it
> here is a sub class...
>                                 // send it to the this function again to
> decode it...
>                                 var definition:Class =
> getDefinitionByName(vType.replace(/::/, ".")) as Class;
>                                 translateTo[vName] =
> translateObject(translateFrom[fromName], new definition());
>                                 break;
>                         }
>                     }
>                 }
>                 catch (e:Error)
>                 {
>                     // do nothing // we will loose data, but our app will
> stay in tact;
>                     //if (translateFrom.hasOwnProperty(v...@name))     {
>                     //    translateto...@name] = translatefrom...@name];
>                     //}
>                     trace("an error occured in ObjectTranslator. The
> following fields were not captured correctly - to:" + vName + "  from:" +
> fromName);
>                     trace(translateTo[vName]);
>                     trace(translateFrom[fromName]);
>                 }
>
>             }
>
>             return translateTo;
>         }
>
>         public static function
> translateArrayCollection(collection:ArrayCollection, translateToClass:Class,
> upperCaseFromVar:Boolean=false):ArrayCollection
>         {
>             // this is a convenience function.  in the GA release of FLEX
> 2, objects are now coming back as
>             // array collections.  if an array collection is expected, this
> function will check to make sure
>             // that it is not null.  it returns a completely new
> collection, which may or may not be what is desired.
>             var returnCollection:ArrayCollection = new ArrayCollection();
>             if (collection != null)
>             {
>                 if (collection.length > 0)
>                 {
>                     returnCollection.source =
> translateArrayObjects(collection.source, translateToClass,
> upperCaseFromVar);
>                 }
>             }
>             return returnCollection;
>         }
>
>         public static function
> translateArrayCollectionAsArray(collection:ArrayCollection,
> translateToClass:Class, upperCaseFromVar:Boolean=false):Array
>         {
>             // this is a convenience function.  in the GA release of FLEX
> 2, objects are now coming back as
>             // array collections.  if an array collection is expected, this
> function will check to make sure
>             // that it is not null.  it returns a completely new Array,
> which may or may not be what is desired
>             var returnArray:Array = new Array;
>             if (collection != null)
>             {
>                 if (collection.length > 0 )
>                 {
>                     returnArray =
> translateArrayObjects(collection.source,translateToClass,upperCaseFromVar);
>                 }
>             }
>             return returnArray;
>         }
>
>         public static function parseUtcDate(utcNumber:Number):Date
>         {
>             var returnDate:Date;
>             // there should be a minimum length here for a valid utc Date
>             if (utcNumber.toString().length > 6)
>             {
>                 returnDate = new Date;
>                 returnDate.setTime(utcNumber);
>             }
>             return returnDate;
>         }
>
>         public static function parseDateFromString(dateString:String):Date
>
>         {
>             var returnDate:Date;
>             // check to see if we have a utc date as a string
>             // guessing that dateString should be at least 6 chars long in
> order to be
>             // considered a viable date.... this could be a problem though,
> because theoretically,
>             // a time of zero should still be valid.
>             if (dateString.length > 6 &&
> parseInt(dateString).toString().length > 6)
>             {
>                 // we probaly have a utc date here
>                 returnDate = parseUtcDate(parseInt(dateString));
>             }
>             else
>             {
>                 //  we didn't get a utc date so let's try to parse it...
>                 returnDate = parseUtcDate(Date.parse(dateString));
>             }
>
>             return returnDate;
>         }
>
>         public static function getBooleanValue(bValue:Object):Boolean
>
>         {
>             var returnBoolean:Boolean = false;
>             var stringBoolean:String = bValue.toString().toLowerCase();
>             if (stringBoolean == "true" || stringBoolean == "yes" ||
> stringBoolean == "1" || stringBoolean == "-1")
>             {
>                 returnBoolean = true;
>             }
>             return returnBoolean;
>         }
>
>         public static function clone(source:Object):*
>         {
>             var myBA:ByteArray = new ByteArray();
>             myBA.writeObject(source);
>             myBA.position = 0;
>             return(myBA.readObject());
>         }
>
>     }
> }
>
>
> iside the result function (My proxy class implements IResponder)
>
> public function result(event:Object):void     {
>             //translating the response into typed objects using the
>             //ObjectTranslator utility class
>             var response:LoginResponse =
> ObjectTranslator.translateObject(event.result, new LoginResponse());
>
>             //handiling the response.
>             switch (response.errorCode)
>             {
>                 case LoginErrorEnum.OK:
>                 {
>                     //populate the data object with the username, apssword
> and
>                     loginVO.authToken = (response.header as
> GlobalAPIResponseHeader).sessionToken;
>                     //user autenticated successfully send the session token
>
>                     //further
>                     sendNotification(LOGIN_SUCCESS, authToken);
>                     break;
>                 }
> etc...
>
> you could use here also the generated code, it is a matter of choice in the
> end I guess.
>
> C
>
> ------------------------------
> *From:* Nick Middleweek <n...@middleweek.co.uk>
> *To:* flexcoders@yahoogroups.com
> *Sent:* Thu, February 4, 2010 10:21:59 AM
>
> *Subject:* Re: [flexcoders] WSDL objects -> Flex value objects
>
>
>
> Hi,
>
>
> Is there any article on how to use your method and does it work with
> nth-level nested data structures? It could be that your way is easier and
> saves recoding/ recreating classes?...
>
> Is there a benefit though to using Typed objects rather than untyped? Does
> your way use untyped?
>
> Or perhaps I'm confused? :)
>
>
> Cheers,
> Nick
>
>
>
> On 4 February 2010 09:12, claudiu ursica <the_braniak@ 
> yahoo.com<the_bran...@yahoo.com>
> > wrote:
>
>>
>>
>>
>> As Peeyush Tuli menstioned, you can go with the automatic conversion also.
>> I just don't like the bunch of generated classes it is one abstract and one
>> implementation for almost everything in there. However there's no room for
>> error in there.
>> It is a matter of choice in the end :).
>>
>> C
>>
>
>  
>

Reply via email to