Flex utility classes

NameUtil Flex utility class

The NameUtil class provides two methods for creating names for DisplayObjects. In particular, these two methods are used in FlexSprite and FlexShape to set the name property and the return value of toString().

UIDUtil Flex class

The UIDUtil class is a utility class for manipulating UIDs (universal identifiers) in Flex. A UID is a very unique String which is hopefully fully unique. The UID is intended to be a unique index to a particular instance of a class in Flex. The UIDUtil class has static methods that can create and fetch UIDs for any Object in a Flash application. UIDUtil is commonly used by the list classes to index their contents and provide lookups for various purposes.

The most commonly used method on UIDUtil is the public static getUID(item:Object):String method. It is worth looking at in full detail:

  1.     public static function getUID(item:Object):String
  2.     {
  3.         var result:String = null;
  4.  
  5.         if (item == null)
  6.             return result;

If the value passed in is null, then it is simply returned.

  1.         if (item is IUID)
  2.         {
  3.             result = IUID(item).uid;
  4.             if (result == null || result.length == 0)
  5.             {
  6.                 result = createUID();
  7.                 IUID(item).uid = result;
  8.             }
  9.         }

If the value passed in implements the IUID interface, then the uid property is inspected. If it is not set, then createUID() is called and the value is set. The method will return the result variable at the end.

  1.         else if ((item is IPropertyChangeNotifier) &&
  2.                  !(item is IUIComponent))
  3.         {
  4.             result = IPropertyChangeNotifier(item).uid;
  5.             if (result == null || result.length == 0)
  6.             {
  7.                 result = createUID();
  8.                 IPropertyChangeNotifier(item).uid = result;
  9.             }
  10.         }

This piece of code is a puzzle to me. If the item is an IPropertyChangeNotifier, and not an IUIComponent, then the code does the same as the above code for the IUID interface. This is puzzling because IPropertyChangeNotifier extends IUID, so any class that implements IPropertyChangeNotifier should have been handled by the first condition.

  1.         else if (item is String)
  2.         {
  3.             return item as String;
  4.         }

If the item is a String, then it is simply returned as is.

The next block handles XML and everything else. I'm not too familiar with the XML code, so I won't try to explain it all. Apparently there is a mechanism to perform notifications from XML objects and that mechanism will store a UID. Here is the code:

  1.                     var xitem:XML = XML(item);
  2.                     var nodeKind:String = xitem.nodeKind();
  3.                     if (nodeKind == "text" || nodeKind == "attribute")
  4.                         return xitem.toString();
  5.  
  6.                     var notificationFunction:Function = xitem.notification();
  7.                     if (!(notificationFunction is Function))
  8.                     {
  9.                         // The xml node hasn't already been initialized
  10.                         // for notification, so do so now.
  11.                         notificationFunction =
  12.                             XMLNotifier.initializeXMLForNotification();
  13.                         xitem.setNotification(notificationFunction);
  14.                     }
  15.  
  16.                     // Generate a new uid for the node if necessary.
  17.                     if (notificationFunction["uid"] == undefined)
  18.                         result = notificationFunction["uid"] = createUID();
  19.  
  20.                     result = notificationFunction["uid"];

The last block handles objects which haven't been handled elsewhere. First, it will check for a property called mx_internal_uid, then a property called uid, returning those if found:

  1.                     if ("mx_internal_uid" in item)
  2.                         return item.mx_internal_uid;
  3.  
  4.                     if ("uid" in item)
  5.                         return item.uid;

Lastly, it will attempt to lookup the object in an internal Dictionary and, if it can't find the object there, it will create a new UID and either put it into the mx_internal_uid property or into the Dictionary

  1.                     result = uidDictionary[item];
  2.  
  3.                     if (!result)
  4.                     {
  5.                         result = createUID();
  6.                         try
  7.                         {
  8.                             item.mx_internal_uid = result;
  9.                         }
  10.                         catch(e:Error)
  11.                         {
  12.                             uidDictionary[item] = result;
  13.                         }
  14.                     }

Notice the try..catch block. This block will add a new property to a dynamic class called mx_internal_uid. A dynamic class can have properties added and removed at runtime. Object and Array are dynamic classes, and you can declare your own dynamic class by including the dynamic keyword in your class declaration.

There is also a try..catch block that begins the final else and uses the results of calling toString() on the item if an exception is thrown:

  1.             catch(e:Error)
  2.             {
  3.                 result = item.toString();
  4.             }

The end of the method returns whatever value was assigned to result:

  1.         return result;

The other method of primary importance is the createUID() method which actually creates the UID. It does this by generating a string in the form "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" where X is a hexadecimal digit. The first four groups of characters are generated by this code:

  1.             uid[index++] = ALPHA_CHAR_CODES[Math.floor(Math.random() *  16)];

The last group is generated by grabbing the lowest 8 hexadecimal digits of the current timestamp (which is in milliseconds since 1970), and then 4 more random digits using the same method as above.

This algorithm will generate a UID that has a very good chance of being universally unique even among Flash player instances and servers. However, it is not as unique as a true GUID would be.

Lastly, I want to mention the internal Dictionary that stores the UIDs of instances that don't support storing the UID on them. This Dictionary is defined as:

  1.     private static var uidDictionary:Dictionary = new Dictionary(true);

The true parameter indicates that the Dictionary should store weak keys. This means that the references that the Dictionary keeps to your objects will be ignored for the sake of garbage collection. Also noticed that the Dictionary is static. This means that your Flash application will always return the same UID for a given instance over its lifetime, whether or not that instance stores the UID on itself or not.