es.uc3m.it.xbe32
Class XBE32ObjectParser

java.lang.Object
  extended byes.uc3m.it.xbe32.XBE32ObjectParser
All Implemented Interfaces:
XBE32ParseListener

public class XBE32ObjectParser
extends Object
implements XBE32ParseListener

This class eases the parsing process of objects from XBE32-encoded streams by means of Class reflection.

The parsed Elements are matched against the attributes and methods of a root Object. All Objects to be parsed MUST have public classes, otherwise XBE32ObjectParser will be not able to access its fields and methods, even if they are public ones.

When a XBE32 Attribute is found, the parser tries to invoke its associated 'setter' method with the parsed Value(s) as the only parameter. Then, the parses searches an accessible (public) field with the same name to fill it with the Attribute value(s).

Although all XBE32 Attribute are able to carry multiple values, to ease the parsing of attribute values and the definition of XBE32-encoded classes, fields and 'setter' methods could be defined as a single value or an array of them. For example a class may define a short[] ports field and a setColor(boolean col) 'setter' method. Thus the XBE32ObjectParser is able to store all the XBE32 ports Attribute values as an array, whereas only the first value of the XBE32 color Attribute array will be employed as a parameter of the 'setter' method.

In the case of Complex Elements, first the associated 'create' method is invoked, then the Class field with the same name is search for. When the method or field returns a valid Object (or it is created with the empty Constructor from its field definition) this Object is employed to continue the parsing process (i.e. inner Attributes and child Complex Elements), until the Element ends and the process continues with its parent Object.

Finally, if neither an accessible field nor an appropiate 'setter'/'create' method are found, and the current Object being parsed implements the XBE32Parseable interface, the setXBE32Attribute() or createXBE32Element() methods are invoked.

When a Mandatory (Continue flag unset) Element, either Complex or Attribute, is parsed and no associated Object is found by any means, a XBE32ParseException is thrown. However, if an Optional (Continue Flag set) Complex Element is unknown, then all its Attributes or child Elements are ignored until the Optional Element finishes. Unknown Optional Elements with the Notify Error flag set are added to the unknown elements list (getUnknownElements()).

Field names must be equal to the XBE32 Element name being processed. 'setter'/'create' Method names follows Java Beans name conventions. That is 'set' or 'create' followed by the XBE32 Element name with the first letter in uppercase. For example when parsing a addr Opaque4 Attribute, the XBE32ObjectParser first tries with the setAddr(byte[][]) and setAddr(byte[]) methods, and then with the public byte[][] addr and public byte[] addr fields.

For example, a XBE32ObjectParser can be employed to easily parse a XBE32-stream into the following objects:

    public class Service
    {
        public String type;
        public InetAddress addr;
        public short[] ports;
        public Options options;

        public void setAddr( byte[] val )
            throws XBE32ParseException
        {
            try {
                addr = InetAddress.getByAddress(val);
            } catch (UnknownHostException ex) {
                throw new XBE32ParseException(ex);
            }
        }
    }

    public class Options implements XBE32Parseable
    {
        public boolean color;
        public Vector options;

        public Options()
        {
            options = new Vector();
        }

        public Object createXBE32Element
            ( boolean ext, int id, String name, boolean c, boolean e )
            throws XBE32ParseException
        {
            XBE32Element elem = new XBE32Element(ext, id, name, c, e);
            options.add(elem);
            return elem;
        }

        public void setXBE32Attribute
            ( boolean ext, int id, String name, boolean c, boolean e, int type, Object vals )
            throws XBE32ParseException
        {
            XBE32Element attr = new XBE32Element(ext, id, name, c, e, type, vals);
            options.add(attr);
        }
 

Therefore, given the following XBE32ParseListener event sequence:

    listener.startParsing();
    listener.complexElementStart(false, 0x0001, "service", false, false);
    listener.attributeElement(false, 0x2102, "type", false, false, 
                              XBE32Element.STRING_VALUE_TYPE, "printer");
    listener.attributeElement(false, 0x2C03, "addr", false, false, 
                              XBE32Element.OPAQUE4_VALUES_TYPE, new byte[][] {{ 0xA9, 0xFE, 0x55, 0x8B }});
    listener.attributeElement(false, 0x2904, "ports", false, false, 
                              XBE32Element.INT16_VALUES_TYPE, new short[] { 515, 631 });
    listener.complexElementStart(false, 0x0003, "options", true, true);
    listener.attributeElement(true, 0x000006, "color", false, true, 
                              XBE32Element.BOOLEAN_VALUES_TYPE, new boolean[] { false });
    listener.attributeElement(true, 0, "ppm", true, false, 
                              XBE32Element.FLOAT32_VALUES_TYPE, new float[] { 20.5 });
    listener.complexElementEnd(false, 0x0003, "options", true, true);
    listener.complexElementEnd(false, 0x0001, "service", false, false);
    listener.endParsing(76);
 
It would fill the service attribute of the root Object like this code:
   root.service.type = "printer";
   root.service.setAddr(new byte[] {0xA9, 0xFE, 0x55, 0x8B });
   root.service.ports = new short[] { 515, 631 };
   root.service.options = new Options();
   root.service.options.color = false;
   root.service.options.setXBE32Attribute(true, 0, "ppm", true, false, 
                                          XBE32Element.FLOAT32_VALUES_TYPE, new float[] { 20.5 });
 

See Also:
XBE32Parseable, XBE32Parser.setListener(), XBE32Reader.setListener()

Constructor Summary
XBE32ObjectParser(Object root)
          Creates a XBE32ObjectParser to parse a XB32-encoded stream into the specified Object.
 
Method Summary
 void attributeElement(boolean ext, int id, String name, boolean c, boolean e, int type, Object val)
          This method is called when an Attribute Element is processed by the XBE32Parser.
 void complexElementEnd(boolean ext, int id, String name, boolean c, boolean e)
          This method is called when a Complex Element has been just processed by the XBE32Parser.
 void complexElementStart(boolean ext, int id, String name, boolean c, boolean e)
          This method is called when a Complex Element is found by the XBE32Parser.
 void endParsing(int length)
          This method is called when the XBE32Parser successfully ends parsing the full XBE32-encoded stream.
 Object getCurrentObject()
          Returns the current Object being parsed
 Object getRootObject()
          Returns the root Object where the parsing process started at.
 Enumeration getUnknownElements()
          Returns the list of unknown XBE32Element with both flags set
 void startParsing()
          This method is called when the XBE32Parser.parse() method is called, thus the parsing process starts.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

XBE32ObjectParser

public XBE32ObjectParser(Object root)
Creates a XBE32ObjectParser to parse a XB32-encoded stream into the specified Object.

Parameters:
root - the root Object where parsing starts from
Method Detail

getRootObject

public Object getRootObject()
Returns the root Object where the parsing process started at.

Returns:
the root parsing Object

getCurrentObject

public Object getCurrentObject()
Returns the current Object being parsed

Returns:
the current parsing Object

getUnknownElements

public Enumeration getUnknownElements()
Returns the list of unknown XBE32Element with both flags set

Returns:
list of unknown XBE32 Elements

startParsing

public void startParsing()
Description copied from interface: XBE32ParseListener
This method is called when the XBE32Parser.parse() method is called, thus the parsing process starts.

Specified by:
startParsing in interface XBE32ParseListener
See Also:
XBE32Parser.parse()

complexElementStart

public void complexElementStart(boolean ext,
                                int id,
                                String name,
                                boolean c,
                                boolean e)
                         throws XBE32ParseException
Description copied from interface: XBE32ParseListener
This method is called when a Complex Element is found by the XBE32Parser.

Specified by:
complexElementStart in interface XBE32ParseListener
Parameters:
ext - whether the Complex Element that to be parsed is an Extensible or a Compact one
id - the identifier of the Complex Element to be parsed
name - the name of the Complex Element to be parsed
c - the Continue flag of the Complex Element to be parsed
e - the Notify Error flag of the Complex Element to be parsed
Throws:
XBE32ParseException - the listener may throw this exception if any syntax error occurs while processing this event
See Also:
XBE32Parser.parse(), XBE32Parser.parseElement()

complexElementEnd

public void complexElementEnd(boolean ext,
                              int id,
                              String name,
                              boolean c,
                              boolean e)
                       throws XBE32ParseException
Description copied from interface: XBE32ParseListener
This method is called when a Complex Element has been just processed by the XBE32Parser.

Specified by:
complexElementEnd in interface XBE32ParseListener
Parameters:
ext - whether the Complex Element that has been parsed is an extensible or a compact one
id - the identifier of the Complex Element that has been parsed
name - the name of the Complex Element that has been parsed
c - the Continue flag of the Complex Element that has been parsed
e - the Notify Error flag of the Complex Element that has beee parsed
Throws:
XBE32ParseException - the listener may throw this exception if any syntax error occurs while processing this event
See Also:
XBE32Parser.parse(), XBE32Parser.parseElement()

attributeElement

public void attributeElement(boolean ext,
                             int id,
                             String name,
                             boolean c,
                             boolean e,
                             int type,
                             Object val)
                      throws XBE32ParseException
Description copied from interface: XBE32ParseListener
This method is called when an Attribute Element is processed by the XBE32Parser.

Specified by:
attributeElement in interface XBE32ParseListener
Parameters:
ext - whether the Attrbiute Element being parsed is an Extensible or a Compact one
id - the identifier of the Attribute Element being parsed
name - the name of the Attribute Element being parsed
c - the Continue flag of the Attribute Element being parsed
e - the Notify Error flag of the Attribute Element being parsed
type - the Type of the Attribute's Value being parsed
val - the Values field of the Attribute Element being parsed
Throws:
XBE32ParseException - the listener may throw this exception if any syntax error occurs while processing this event
See Also:
XBE32Element.OPAQUE_VALUE_TYPE, XBE32Element.STRING_VALUE_TYPE, XBE32Element.OPAQUE1_VALUES_TYPE, XBE32Element.INT8_VALUES_TYPE, XBE32Element.BOOLEAN_VALUES_TYPE, XBE32Element.OPAQUE2_VALUES_TYPE, XBE32Element.INT16_VALUES_TYPE, XBE32Element.OPAQUE4_VALUES_TYPE, XBE32Element.INT32_VALUES_TYPE, XBE32Element.FLOAT32_VALUES_TYPE, XBE32Element.OPAQUE8_VALUES_TYPE, XBE32Element.INT64_VALUES_TYPE, XBE32Element.FLOAT64_VALUES_TYPE, XBE32Element.OPAQUE12_VALUES_TYPE, XBE32Element.OPAQUE16_VALUES_TYPE, XBE32Parser.parse(), XBE32Parser.parseElement()

endParsing

public void endParsing(int length)
Description copied from interface: XBE32ParseListener
This method is called when the XBE32Parser successfully ends parsing the full XBE32-encoded stream.

Specified by:
endParsing in interface XBE32ParseListener
See Also:
XBE32Parser.parse()