Blog

PixLib – Tut 02 – What is and how to use the ConfigLoader class + Tweak

Hi there…

This small tutorial will deal with the ConfigLoader class. We will see what is this class for and how to use it in a project.
Of course you’ll need the pixlib framework to do so. You can download it HERE or you can use the repository HERE.
You will need as well some basic understanding of the framework. If you haven’t done it yet check the first tutorial giving you an introduction to the framework, PixLib – Understanding the basis of the framework

Ok, let’s start…

 

I. What is the ConfigLoader class

First, you will find the ConfigLoader class in the com.bourre.data.libs package.

The ConfigLoader class is the class that will help you loading datas from a xml file.
Better than that, you will be able to :

  • strong typing your nodes
  • create objects from the xml
  • create custom objects using a custom deserializer

Of course this class is not doing all of this but is the entry point for those tasks. The classes used through this one are :

  • Config which will return the object created from the xml
  • XMLToObject which is the entry point for the creation of your object
  • XMLToObjectDeserializer

 

II. How to use it?

a. The basis

The ConfigLoader work this way.

BY DEFAULT, the instance created from the ConfigLoader class will load the XML “config.xml”, will use the XMLToObject and XMLToObjectDeserializer to parse your XML file and will send back the result in the Config class singleton – which is only an empty object –

But you can specify the path of the XML, the deserializer you want to use ( if you have complex custom object – we will see that later – ) and the object that should hold all the data loaded from the XML file.
To specify the object holding the result and the deserializer you just need to give them as arguments when creating a new ConfigLoader instance ( new ConfigLoader( holder, deserializer ) )

A couple of things you need to know about your xml structure:

  • in your XML, you must have a node parent of all the others. This node will be the container and will not be visible in the result sent back by the parser ( usually we are calling it config )
  • by default if a XML node has children, the parser will create an object out of it and each child will be a property of this object

Anyway, here is the code using all default settings
[as]
private function _onLoadConfig( e : ConfigLoaderEvent ) : Void {
// Broadcast the onLoadComplete event
XEventBroadcaster.getInstance().broadcastEvent( new BasicEvent( EventList.CONFIG_LOADED ) );
}

// create a new ConfigLoader and set it up to load the desire xml file
_cl = new ConfigLoader();
_cl.addEventListener( ConfigLoader.onLoadInitEVENT, this, _onLoadConfig );
_cl.load();
[/as]
Keep in mind that in most of the case you will use the ConfigLoader class in the same way. The difference will come from your XML.

So here, you are creating the instance, then adding listener to events dispatch by the ConfigLoader and when loaded broadcasting an event to let the application know that you are ready to go…
Oh, and the events dispatched by the ConfigLoader are:

  • onLoadInitEVENT
  • onLoadProgressEVENT
  • onTimeOutEVENT

and are static property of the ConfigLoader class so can be accessed like ConfigLoader.onInitEVENT.

So saying that if we have this
[xml]



[/xml]

you’ll get a Config.getInstance() object like this
[xml]

|- property01 : “Property 1”
|- property02 : “Property 2”
[/xml]

Even if you’re using the default way to parse your XML you will need to know some things about the XMLToObjectDeserializer class.
There is some interesting features.

You can specify if you want the attributes of your nodes to be deserialized ( by default they are not ). To do so you need to define two static variables of the XMLToObjectDeserializer. Those properties are XMLToObjectDeserializer.ATTRIBUTE_TARGETED_PROPERTY_NAME which will get a string defining the property’s name of your object ( eg “attributes” so you’ll get yourCustomObject.attributes ( object ) created ) which will hold the object made from the attributes ( yourCustomObject.attributes will get all the object made from the attributes of your node ) and XMLToObjectDeserializer.DESERIALIZE_ATTRIBUTES which is a boolean saying if this feature is on ( true ) or off ( false, by default )

You can set up that if the XML has same nodes name ( with the same parent ) those nodes will be pushed in an array. To activate this feature you are doing XMLToObjectDeserializer.PUSHINARRAY_IDENTICAL_NODE_NAMES = true. The array name will be the nodes name.

Finally for debugging you can set up the XMLToObjectDeserializer.DEBUG_IDENTICAL_NODE_NAMES to true to have a warning in your logger everytime you ahve 2 nodes with identical names

Ok now you know how the “basis” works let’s see the interesting part of it 🙂

 

b. Typing your object

This is really easy to do. In your XML file in each node you can add an attribute named “type”. This attribute can have those values:

  • array: the object created will be an Array, eg of value in the node: 1,’toto’,true
  • boolean: the object created will be a Boolean, eg of value in the node: true
  • class: the object created will be an instance of a custom object. In the node value you are giving the path of the class and arguments like
    [xml]

    ‘net.webbymx.tutorial02.testObject’, argument01, argument02

    [/xml]
  • number: the object created will be a Number, eg of value in the node: 15
  • point: the object will be a Point, eg of value in the node: 5,2 – in the format x,y
  • string: the object created will be a String, eg of value: a string, or < ![CDATA[A string]] ( remove the white space after the < ) when you have specific characters
  • if you have no type, an Object will be created

That’s great isn’t it? You can already do lot’s of things.
But as you have probably notice the support of custom object here is not so good. In the example above you can see that when you are creating a custom object you cannot add node child ( properties ). The way it is set up is for simple objects that needs simple arguments ( that can be parse as string ). What if you need a more complex object?

 

III. I want full control when creating my Custom Objects

 

a. A custom deserializer

Since the rev35, PixLib offers developers to set up custom deserializer. The idea is simple. Extends the XMLToObjectDeserializer or create your own implementing the IXMLToObjectDeserializer. If extending the one from the framework you can simply add new types with the method yourDeserializer.addType( “yourTypeString”, yourDeserializer, functionToHandleThatType )… During my project I tried this way. But I’m a bit lazy see, and I don’t want everytime to do my own deserializer, so I tweak the XMLToObjectDeserializer. Let’s see what it is doing more.

 

b. The tweaked XMLToObjectDeserializer

I’ve tweak the file to be able to:

  • define a custom object class and the arguments of this constructor but still be able to add properties to the new created object by adding two keywords in the node attributes, clazz and arguments
  • define a setter attribute. The method ( given by the string of the setter attribute ) will be called passing the node value in it. This method will be called of course if the owner of your current object has a type=”class” – and if it has this method

So then you can have CustomObject with privates properties and setter to set them. So you sure you’ll not have undesired properties… Moreover you could create Custom Objects which will have Custom Objects as properties and have strong typing when setting them. This class of course keep as well all the features of the original one.

How does it work?
An example is better than any words… This example is taken from a new project I’m working on. As you can guess it’s a tile based engine.
[xml]

net.webbymx.project.goolash.tileset.village




0

0

[1, 1, 1, 1, 1, 1, 1, 1]
[1, 0, 0, 0, 0, 0, 0, 1]
[1, 0, 1, 0, 0, 0, 0, 1]
[1, 0, 0, 0, 0, 1, 0, 1]
[1, 0, 0, 0, 0, 0, 0, 1]
[1, 1, 1, 1, 1, 1, 1, 1]



1

[0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 4, 4, 0, 0, 0]
[0, 0, 0, 4, 4, 3, 3, 0]
[0, 0, 0, 0, 0, 0, 3, 0]
[0, 0, 0, 0, 0, 3, 3, 0]




[/xml]

I could have done something smaller but this example shows how helpful this tweak is ( I think ).
I have done my structure like this:

  • A map is a custom object having an array of level ( different area of the map ), a short name, a description and a link to a tileset ( bitmap data to take the tiles image from )
  • A level is a custom object that has a level number and an array of layer( ground, not movable object, movable object, … )
  • A layer is a custom object that has a depth and an array holding the info

So in my XML file starting from the smallest object, the layer.
I’m saying that this node will create a LevelLayer object, and I’m giving the arguments for the constructor
[xml]type=”class” clazz=”net.webbymx.bipcube.engines.tilebased.vos.LevelLayer” arguments=”6,8″[/xml]
then I’m setting the depth and the map info using setter ( as my properties are private )
[xml]
0

[1, 1, 1, 1, 1, 1, 1, 1]
[1, 0, 0, 0, 0, 0, 0, 1]
[1, 0, 1, 0, 0, 0, 0, 1]
[1, 0, 0, 0, 0, 1, 0, 1]
[1, 0, 0, 0, 0, 0, 0, 1]
[1, 1, 1, 1, 1, 1, 1, 1]

[/xml]

the lvl node:
I’m saying that this node will create a LevelLayer object. This one needs no arguments for the constructor
[xml]type=”class” clazz=”net.webbymx.bipcube.engines.tilebased.vos.Level”[/xml]
I’m setting up the level number, and my layers. You can see on the layer nodes that they have a setter attribute as well. So once created they will feed the setter of their owner.

And then the same for the map node which will pass the new created lvl in its setLevel setter.

 

IV. Conclusion

I hope you will like this. As usual if you have any feedbacks / comments feel free to post.

You can download the sources files here ( working example and the tweaked class )
[Download id not defined]

And if you’re reading this Francis, you reckon we could put it in the official release?

  • SunShine

    Hi,

    First, thanks for the tut 🙂
    The aprt about “the tweaked” it a bit “dark” for me. I don’t understand the roles of the setter ?
    Sorry if my question it’s stupid, but can you explain me ?

    Thank you

  • SunShine

    Hi,

    First, thanks for the tut 🙂
    The aprt about “the tweaked” it a bit “dark” for me. I don’t understand the roles of the setter ?
    Sorry if my question it’s stupid, but can you explain me ?

    Thank you

  • yes!

    thank you very much! 😀
    very interesting and informative; keep m comin 😉

    cheers

  • yes!

    thank you very much! 😀
    very interesting and informative; keep m comin 😉

    cheers

  • timbot

    Xavier, thanks very much for this tutorial. It is very well done. Keep going!

  • timbot

    Xavier, thanks very much for this tutorial. It is very well done. Keep going!

  • Marcelo Serpa

    Hey Xavier! Thanks for the tut. very useful. As the others said – Keep them coming!

  • Marcelo Serpa

    Hey Xavier! Thanks for the tut. very useful. As the others said – Keep them coming!

  • RYGAR

    I’m perplexed….Is there a better place to start? In particular i’m interested in XMLtoObject deal.

  • RYGAR

    I’m perplexed….Is there a better place to start? In particular i’m interested in XMLtoObject deal.

  • zeflasher

    Hello RYGAR, you can check in the mailing list archives for informations or you can ask questions there too…

  • zeflasher

    Hello RYGAR, you can check in the mailing list archives for informations or you can ask questions there too…

  • RYGAR

    Well if anyone can help me get the syntax down for this is would be a huge help. I really just need to know this one thing, while the entire framework looks interesting I just don’t have the time.

    My question is regarding XML2OBject

    Here’s what I’ve gots:
    AS:

    import com.bourre.data.libs.*;

    //Callback Function
    function run( e: XMLToObjectEvent) : Void
    {
    trace(e.getObject());
    trace(this);
    }

    _xto = new XMLToObject(new Object());
    _xto.addEventListener(XMLToObject.onLoadInitEVENT,this,run);
    _xto.load(“simple.xml”);

    and the XML:

    Meal 3
    12.10

    —–

    I’m having trouble just calling the XML variables. For instance I would just like do a trace(this.test.meal); and have it output ‘Meal 3’. Seems simple enough…HELP?!

  • RYGAR

    Well if anyone can help me get the syntax down for this is would be a huge help. I really just need to know this one thing, while the entire framework looks interesting I just don’t have the time.

    My question is regarding XML2OBject

    Here’s what I’ve gots:
    AS:

    import com.bourre.data.libs.*;

    //Callback Function
    function run( e: XMLToObjectEvent) : Void
    {
    trace(e.getObject());
    trace(this);
    }

    _xto = new XMLToObject(new Object());
    _xto.addEventListener(XMLToObject.onLoadInitEVENT,this,run);
    _xto.load(“simple.xml”);

    and the XML:

    Meal 3
    12.10

    —–

    I’m having trouble just calling the XML variables. For instance I would just like do a trace(this.test.meal); and have it output ‘Meal 3’. Seems simple enough…HELP?!

  • RYGAR

    Well the XML didn’t show in my last post… I’ll write it:

    ‘test’
    ‘meal’ and ‘cost’ child below that.

  • RYGAR

    Well the XML didn’t show in my last post… I’ll write it:

    ‘test’
    ‘meal’ and ‘cost’ child below that.

  • zeflasher

    Hello RYGAR, please post this on the mailling list.
    Pixlib [at] osflash [dot] org
    Attach your files as well. If I’m not having a look other people will do…

    And when you’ll get time you really should check for this framework. It’s a must know. 😉

  • zeflasher

    Hello RYGAR, please post this on the mailling list.
    Pixlib [at] osflash [dot] org
    Attach your files as well. If I’m not having a look other people will do…

    And when you’ll get time you really should check for this framework. It’s a must know. 😉

  • Thanks for your good tuto about pixlib.

    Keep going.

  • Thanks for your good tuto about pixlib.

    Keep going.

  • Pingback: Dev by MX» Blog Archive » Pixlib - Tut 03 - How to load assets at runtime()

  • isambard

    it might be worth chipping in that you need to set the DESERIALIZE_ATTRIBUTES property BEFORE instantiating the config loader. I mistakenly assumed that because this is a static property that as long as it was set prior to loading the xml, that it wouldn’t matter when it was set, but it is made into an instance property when an instance of xmlToObjectDeserializer is created.

  • isambard

    it might be worth chipping in that you need to set the DESERIALIZE_ATTRIBUTES property BEFORE instantiating the config loader. I mistakenly assumed that because this is a static property that as long as it was set prior to loading the xml, that it wouldn’t matter when it was set, but it is made into an instance property when an instance of xmlToObjectDeserializer is created.

  • Czartan

    i keep getting 2 compile time erors “There is no property with the name ‘DESERIALIZE_ATTRIBUTES’ and There is no property with the name ‘PUSHINARRAY_IDENTICAL_NODE_NAMES”. yes, i am using the modified XMLToObjectDeserializer and rev35 of pixlib. please help! thanks in advance

  • Czartan

    i keep getting 2 compile time erors “There is no property with the name ‘DESERIALIZE_ATTRIBUTES’ and There is no property with the name ‘PUSHINARRAY_IDENTICAL_NODE_NAMES”. yes, i am using the modified XMLToObjectDeserializer and rev35 of pixlib. please help! thanks in advance

  • zeflasher

    Czartan> You may point to the wrong classes. If you are opening the tweaked XMLTOObjectDeserializer you’ll see that there is

    public static var PUSHINARRAY_IDENTICAL_NODE_NAMES : Boolean = false;
    public static var DESERIALIZE_ATTRIBUTES : Boolean = false;

    So the class is good… It may come from your side.
    ++

  • zeflasher

    Czartan> You may point to the wrong classes. If you are opening the tweaked XMLTOObjectDeserializer you’ll see that there is

    public static var PUSHINARRAY_IDENTICAL_NODE_NAMES : Boolean = false;
    public static var DESERIALIZE_ATTRIBUTES : Boolean = false;

    So the class is good… It may come from your side.
    ++