YellowBadger Blog http://www.yellowbadger.com/blog/index.cfm YellowBadger technology blog. Fri, 30 Jul 2010 02:NN:45 +0800 http://www.yellowbadger.com en Singletons in ActionScript 3 http://www.yellowbadger.com/blog/showPost.cfm?id=SingletonsinActionScript3 http://www.yellowbager.com/blog/showPost.cfm?id=SingletonsinActionScript3#comments Wed, 07 Feb 2007 16:NN:00 +0800 Spike http://www.yellowbadger.com/blog/showPost.cfm?id=SingletonsinActionScript3 Mike Chambers posted an entry on his blog about using Application.application.foo as an approach to allow global variables in Flex Applications. A couple of people, myself included, mentioned in the comments that an alternative was to use one or more singleton classes instead and Dave asked for a more complete example of using singletons. Well here it is Dave, for you and anyone else who might...]]> Mike Chambers posted an entry on his blog about using Application.application.foo as an approach to allow global variables in Flex Applications. A couple of people, myself included, mentioned in the comments that an alternative was to use one or more singleton classes instead and Dave asked for a more complete example of using singletons. Well here it is Dave, for you and anyone else who might be interested.

As with many things, Wikipedia has an excellent overview of what a singleton class is. All I'm going to do here is show how to create and use one in ActionScript 3...

A simple user preferences singleton class might look something like this:

package com.yellowbadger.example {

  public class Preferences {

    private static var _instance:Preferences;

    public static function getCurrentPreferences():Preferences {

      if (_instance == null) {

        _instance = new Preferences();

      }

    }

  }

}

This satisfies the requirement that all code in your application *can* use the same instance of the Preferences class, but it doesn't satisfy the requirement that all *must* use the same instance. The standard way to enforce the second requirement in Java is to make the constructor for the Preferences class private so that only code within the Preferences class can create the single instance. ActionScript 3 does not permit private constructors but we can get around it using a little bit of lateral thinking.

package com.yellowbadger.example {

  public class Preferences {

    private static var _instance:Preferences;

   

    public function Preferences(enforcer:SingletonEnforcer) {}

   

    public static function getCurrentPreferences():Preferences {

      if (_instance == null) {

        _instance = new Preferences(new SingletonEnforcer());

      }

    }

  }

}

 

internal class SingletonEnforcer {}

By declaring the SingletonEnforcer class outside the package, the compiler allows us to have a second class declared in the same file, but the class is not visible to any code outside Preferences.as. Since SingletonEnforcer is a required argument in the constructor of the Preferences class, no code outside Preferences.as can create an instance of the Preferences class. We have effectively guaranteed that all code will use the same instance of the Preferences class.

Any time we want to use the Preferences class in the application the code would look something like this:

private var prefs:Preferences = Preferences.getCurrentPreferences();

]]>
Simply Java http://www.yellowbadger.com/blog/showPost.cfm?id=SimplyJava http://www.yellowbager.com/blog/showPost.cfm?id=SimplyJava#comments Wed, 07 Feb 2007 13:NN:00 +0800 Spike http://www.yellowbadger.com/blog/showPost.cfm?id=SimplyJava I've been working on my Flex 1.5 Eclipse plug-in, and I finally got round to adding something I've wanted to put in there for a long time. Namely, automatic detection of flex-config.xml. Now if you're going to automatically detect the config file, there isn't a whole lot of point in doing it unless you read the contents and make them available to the rest of the plug-in. Getting the contents of XML files into Java has it's fair share of quirks, but I can handle that because there's a lot of ...]]> I've been working on my Flex 1.5 Eclipse plug-in, and I finally got round to adding something I've wanted to put in there for a long time. Namely, automatic detection of flex-config.xml. Now if you're going to automatically detect the config file, there isn't a whole lot of point in doing it unless you read the contents and make them available to the rest of the plug-in. Getting the contents of XML files into Java has it's fair share of quirks, but I can handle that because there's a lot of quirky stuff you can do in XML if you so decide. Ultimately, the code to read the contents of the Flex config file is pretty simple. If you use SAX, the important part of the ContentHandler looks something like this:

        // New tag. Create a Tag, add relevant properties

        // and throw it on the stack.

        public void startElement(String namespaceURI, String localName,

                        String qName, Attributes atts) throws SAXException {

                Tag currentTag = new Tag();

                currentTag.name = qName;

                currentTag.value = "";

                Tag parent = null;

                if (!tagStack.isEmpty()) {

                        parent = (Tag)tagStack.peek();

                }

                if (parent != null) {

                        currentTag.parent = parent;

                        parent.children.add(currentTag);

                }

                tagStack.push(currentTag);

                if (rootNode == null) {

                        rootNode = currentTag;

                }

        }

 

        // We got some characters between tags. Read them and add them

        // to the value property of the tag on the top of the stack.

        public void characters(char[] ch, int start, int length)

                        throws SAXException {

               

                StringBuffer value = new StringBuffer();

                for (int i = start; i < start + length; i++) {

                        value.append(ch[i]);

                }

                Tag currentTag = (Tag)tagStack.peek();

                if (currentTag == null) {

                        return;

                }

                currentTag.value += value.toString();

               

        }

 

        // End of tag

        public void endElement(String namespaceURI, String localName, String qName)

                        throws SAXException {

                // Pop it off the stack. We're done with it

                tagStack.pop();

        }

Now that's almost elegant compared to some of the other XML reading code I've written.

Ok, so the SAX ContentHandler gives me a tree of Tag instances. The Tag class looks like this.:

        public class Tag {

                public Tag parent;

                public ArrayList children;

                public String name;

                public String value;

               

                public Tag() {

                        children = new ArrayList();

                }

       

        }

ok, that's not too bad either, in fact, I'd go as far as to say it's prety concise. A tag will have a parent unless it's the root, in which case its parent will be null, and it can have zero or more children. I like this because it allows me to handle, with the addition of a HashMap for attributes, pretty much any XML file I could care to think of.

Now I'm fairly familiar with the flex-config file, but not so familiar that I could just spit out the path to say the compiler manifest element without going and looking first. So I want to create a composite hierarchy of classes inside my FlexConfig object so that the content assist in Eclipse will throw me a bone and show me what can appear under each node. That's one of the nice things about Java you see, because it's all statically typed, the IDE can give me those handy hints.

Creating this hierarchy isn't exactly rocket science either. It runs to a few hundred lines of class declarations with various combinations of Strings, ints, booleans and other classes as the properties of each class, but the first 55 lines or so looks a bit like this:

public class FlexConfig {

       

       

        public boolean productionMode;

        public DebuggingSection debugging;

        public CompilerSection compiler;

        public CacheSection cache;

        public FlashPlayerSection flashPlayer;

        public WebServiceProxySection webServiceProxy;

        public HttpServiceProxySection httpServiceProxy;

        public RemoteObjectsSection remoteObjects;

        public LoggingSection logging;

        public FontsSection fonts;

       

        class DebuggingSection {

                public DebuggingSection(Tag tag) {

                       

                }

                public boolean processDebugQueryParams;

                public boolean generateDebugSwfs;

                public boolean generateProfileSwfs;

                public boolean keepGeneratedAs;

                public boolean keepGeneratedSwfs;

                public boolean showAllWarnings;

                public boolean showOverrideWarnings;

                public boolean showDeprecationWarnings;

                public boolean showBindingWarnings;

                public boolean webServiceProxyDebug;

                public boolean httpServiceProxyDebug;

                public boolean remoteObjectsDebug;

                public boolean showStacktracesInBrowser;

                public boolean showSourceInCompilerErrors;

                public boolean logCompilerErrors;

                public boolean createCompileReport;

        }

       

        class CompilerSection {

                public CompilerSection(Tag tag) {

                       

                }

                public String globalCssUrl;

                public boolean accessible;

                public String debugSwfPassword;

                public boolean optimize;

                public Namespace[] namespaces;

                public String[] actionScriptClasspath;

                public String systemClasses;

                public String[] libPath;

                public String[] debugLibPath;

                public boolean headlessServer;

        }

       

        class Namespace {

                public String manifest;

                public String URI;

        }

...

Righto, so I have a tree of Tag instances and all I have to do is read the tag name from each, put the values into the appropriate place in my composite FlexConfig object, and I'm done...

...

...

...

hmmm...

...

Maybe this isn't going to be as easy as I thought...

...

...

Let's see...

Inside the constructor for FlexConfig I can get the iterator for the children of the root node and iterate over that.

 

        public FlexConfig(Tag rootNode) {

                Iterator it = rootNode.children.iterator();

                while(it.hasNext()) {

                        Tag next = (Tag)it.next();

                        if (next.name.compareTo("production-mode") == 0) {

                                productionMode = Boolean.getBoolean(next.value);

                        } else if (next.name.compareTo("debugging") == 0) {

                                debugging = new DebuggingSection(next);

                        } else if (next.name.compareTo("compiler") == 0) {

                                compiler = new CompilerSection(next);

                        } else if (next.name.compareTo("cache") == 0) {

                                cache = new CacheSection(next);

                        } else if (next.name.compareTo("flash-player") == 0) {

                                flashPlayer = new FlashPlayerSection(next);

                        } else if (next.name.compareTo("web-service-proxy") == 0) {

                                webServiceProxy = new WebServiceProxySection(next);

                        } else if (next.name.compareTo("http-service-proxy") == 0) {

                                httpServiceProxy = new HttpServiceProxySection(next);

                        } else if (next.name.compareTo("remote-objects") == 0) {

                                remoteObjects = new RemoteObjectsSection(next);

                        } else if (next.name.compareTo("logging") == 0) {

                                logging = new LoggingSection(next);

                        } else if (next.name.compareTo("fonts") == 0) {

                                fonts = new FontsSection(next);

                        }

                }

        }

Ok, that's kinda ugly. I suppose it achieves the purpose, but I'm definitely going to have to rethink this if I need to make the approach re-usable for any old xml file.

Now how about the constructor for DebuggingSection which is the first composite child of the root node?

At this point I feel I should confess that I tried a few different approaches. Each of them progressively more tortured and ugly and was inspired to write this little diatribe. It gives my eyes a break from the horrors that they are going to endure when I get back to the code, and might just give my brain a break and some inspiration to come up with something that's vaguely maintainable and doesn't involve an absurd amount of copy and paste.

ok, for the record, here's the first couple of attempts:

1.

        class DebuggingSection {

                public DebuggingSection(Tag tag) {

                        Iterator it = tag.children.iterator();

                        while (it.hasNext()) {

                                Tag next = (Tag)it.next();

                                if (next.name.compareTo("process-debug-query-params") == 0) {

                                        processDebugQueryParams = Boolean.getBoolean(next.value);

                                } else if (next.name.compareTo("generate-debug-swfs") == 0) {

                                        generateDebugSwfs = Boolean.getBoolean(next.value);

                                } else if (next.name.compareTo("generate-profile-swfs") == 0) {

                                        generateProfileSwfs = Boolean.getBoolean(next.value);

                                } else if (next.name.compareTo("keep-generated-as") == 0) {

                                        keepGeneratedAs = Boolean.getBoolean(next.value);

                                }

                                // Good Lord! There has *got* to be a better way than this.

                                // There are over a hundred instance variables to be handled

                                // across the various classes and that doesn't even count

                                // the optional ones I decided to ignore for the first draft

                                // of the code.

                        }

                }

                public boolean processDebugQueryParams;

                public boolean generateDebugSwfs;

                public boolean generateProfileSwfs;

                public boolean keepGeneratedAs;

                public boolean keepGeneratedSwfs;

                public boolean showAllWarnings;

                public boolean showOverrideWarnings;

                public boolean showDeprecationWarnings;

                public boolean showBindingWarnings;

                public boolean webServiceProxyDebug;

                public boolean httpServiceProxyDebug;

                public boolean remoteObjectsDebug;

                public boolean showStacktracesInBrowser;

                public boolean showSourceInCompilerErrors;

                public boolean logCompilerErrors;

                public boolean createCompileReport;

        }

2.

        class DebuggingSection {

                public DebuggingSection(Tag tag) {

                       

                        HashMap fields = new HashMap();

                        fields.put("process-debug-query-params", processDebugQueryParams);

                        fields.put("generate-debug-swfs", generateDebugSwfs);

                        fields.put("generate-profile-swfs", generateProfileSwfs);

                        fields.put("keep-generated-as", keepGeneratedAs);

                       

                        Iterator it = tag.children.iterator();

                        while (it.hasNext()) {

                                Tag next = (Tag)it.next();

                                Iterator it2 = fields.keySet().iterator();

                                while (it2.hasNext()) {

                                        String tagName = (String)it2.next();

                                        if (tagName.compareTo(next.name) == 0) {

                                                Boolean field = (Boolean)fields.get(tagName);

                                                field = new Boolean(next.value);

                                                // Hmmm... will that last line update the instance

                                                // variable or just modify the local one?

                                        }

                                }

                                // This is still pretty ugly. It's a bit better, but I've got to check if

                                // the fields actually get updated. If they don't, this approach is toast.

                        }

                }

                public Boolean processDebugQueryParams;

                public Boolean generateDebugSwfs;

                public Boolean generateProfileSwfs;

                public Boolean keepGeneratedAs;

                public boolean keepGeneratedSwfs;

                public boolean showAllWarnings;

                public boolean showOverrideWarnings;

                public boolean showDeprecationWarnings;

                public boolean showBindingWarnings;

                public boolean webServiceProxyDebug;

                public boolean httpServiceProxyDebug;

                public boolean remoteObjectsDebug;

                public boolean showStacktracesInBrowser;

                public boolean showSourceInCompilerErrors;

                public boolean logCompilerErrors;

                public boolean createCompileReport;

        }

 

ok, at this point I'm starting to feel the pain all those people have been talking about when they complain about Java and its syntax/nanny compiler/static typing. I've got a healthy dose of all 3 going on here.

The syntax is forcing me into all sorts of things that feel unnatural. I want to be able to do this:

config.debugging[newName] = someNewName;

But Java just won't allow me to go with that sort of dyanmic "put your name here" type of assignment.

The complier throws fits if I don't stick (Whatever)((Boolean)((MyClass))) all over the place

and the static typing forces me to make up all these largely pointless classes. They really just need to be hashmaps, but you'll find out if you keep reading why the combination of syntax, compiler, and static typing convinced me I didn't want to go with that option either.

Let's be clear about this. The fundamental problem here is that I want to take a hierarchical set of objects and make them accessible through simple dot and array notation.This is hardly an edge case. It's hardly even unusual. In fact, I'm amazed that I've never run up against it before. I think the main reason I ran into this problem is that I have spent a lot of time recently working in ActionScript. ActionScript is a dynamic language very much like JavaScript.

For those of you who don't spend much time working with dynamic languages, here's the solution to the equivalent problem in JavaScript. Assuming I have the Tag classes in a tree of generic Objects called rootNode.

 

function doRename() {

        var config = new Object();

        buildTree(rootNode.children,config);

}

 

function rebuildTree(nodeArray,parent) {

        for (var i=0;i<nodeArray.length;i++) {

                var newName = camelize(nodeArray[i].name);

                if (nodeArray[i].children.length > 0) {

                        parent[newName] = {};

                        buildTree(nodeArray[i].children,parent[newName]);

                } else {

                        parent[newName] = nodeArray[i].value;

                }

        }

}

 

function camelize(name) {

        var newName = "";

        for (var i=0;i<name.length;i++) {

                var c = name.charAt(i);

                if (c == '-') {

                        i++;

                        c = name.charAt(i).toUpperCase();

                }

                newName += c;

        }

        return newName;

}

That's it!

The whole thing!

Regardless of how large or deep the tree is, regardless of how many nodes, regardless of how the structure of the xml may change, the JavaScript code does not need to change. The caveat being that in order to easily handle repeating xml nodes, you need to build the original anonymous tree with the index of repeating nodes appended to the name. I think I can live with that. Even if I couldn't, handling the repeating nodes and adding them as arrays of nodes to the result is relatively trivial.

It is probably worth pointing out, just in case you missed it, that in the Java examples above, I didn't even get to the end of the first nested node before I gave up. It's also worth pointing out that in order to reach my desired goal in Java I have to do one of two things. Either I write a Java code generator that will automatically spit out the required classes and that hideous instantiation code, or I have to accept that I have a huge amount of Java code to write if I happen to run up against a config file that runs to several thousand elements. I certainly wouldn't want to have to deal with it on a regular basis. It's also worth pointing out that more than half the code in the JavaScript example is just making the nodes camel case. The problem that is proving to be so hideously tortuous in Java is solved entirely in the rebuildTree function. That's right, 11 lines if you include the 3 at the bottom that are only there to make the formatting look nice. I have a 250 line Java class and all that does is define what I want to achieve. Never mind implementing the code that actually does the data transformation. It's also worth noting that the Java code will grow at least linearly with the number of possible nodes in the XML file, so my hope of making this some sort of simple generic solution appears to be dead in the water.

Now of course there are alternative approaches that I could use with xpath and goodness knows what not that would allow me to attack the problem in another way in Java. I could even have turned the Java code into a bunch of hashmaps which is basically what the JavaScript solution, but just looky at the bundle of joy it would be to get the values back out again:

String manifest = (String)((HashMap)((HashMap[])((HashMap)fields.get("compiler")).get("namespaces"))[0].get("namespace")).get("manifest");

Even the most zealous Java advocates would probably concede that's quite a long way from the desired access path which would be:

String manifest = compiler.namespaces[0].namespace.manifest;

Obviously I can also forego the whole thing and create a method that accepts "compiler.namespaces[0].namespace.manifest" as a string, tokenizes it, iterates through the tags, and returns the result, but that's not going to give me any compile time warm and fuzzies if I make a typo now is it?

Wasn't that supposed to be a major selling point of static typing?

I think the thing that really gets me about this. The thing that really makes me realize that Java has been very badly designed in some respects, is that the fundamental problem that Java just couldn't solve for me was taking a nested hierarchy of objects with known properties and turning them into something that would allow me to easily retrieve a specific item from that hierarchy. It's so utterly trivial to do in dynamic languages I didn't even give it a second thought when I embarked on this little escapade. It just goes to show how different your mental process needs to be, and it really does demonstrate that while Java may provide you with some benefits on compile time type checking and performance, the "nanny compiler", the static typing, and the syntax really do force you to bend to the will of the almighty JVM. I've read quite a few blog posts and articles on the subject, but I've never really encountered it before. I can honestly say I really do understand what they are getting at now. It feels like writing Java requires me to cover 100 yards going over the obstacle course, complete with 12 foot wall, crawl net, rope climb, and mud to swing across all in the name of making sure that if I got to the end, I definitely did everything along the way. Meanwhile, the dynamically typed languages have a nicely prepared flat track that is built for out and out speed. When they get to the end, they just need to run some unit tests to make sure the "duck quacks" so to speak. If I'm doing any sort of due diligence on my Java code I need to add the duck quacker at the end of the obstacle course anyway to account for those sneaky runtime errors that seem to keep creeping in no matter what Nanny Compiler says.

]]>