WebObjects 5.2.3

com.webobjects.appserver.xml
Class WOXMLDecoder

java.lang.Object
  extended bycom.webobjects.appserver.xml.WOXMLDecoder
All Implemented Interfaces:
NSKeyValueCoding

public class WOXMLDecoder
extends Object
implements NSKeyValueCoding

Use this class to decode an object from XML data. Decoding can take place either with or without a mapping model. The mapping model provides greater control over the decoding process and is typically used when you are encoding and decoding XML that is destined for, or originates from, an external source. When the WOXMLCoder and WOXMLDecoder are used as a simple archiving mechanism, the mapping model is usually not necessary. For more information on the mapping model, see the "The Format of the Mapping Model" in the package description.

Decoding XML Without a Mapping Model

On its own, WOXMLDecoder is able to decode an object without modifications if the object is Else, the object's Class has to adhere to a protocol that allows the contruction of the object from the XML data: The following simple Person class implements both the WOXMLCoding interface and the single-argument constructor needed to later decode objects of this class.
   import com.webobjects.appserver.xml.*;
   import com.webobjects.foundation.*;
   import java.lang.*;
   import java.net.*;
   import java.math.*;

   public class Person implements WOXMLCoding {
       String name;
       boolean married;
       int children;
       public Person() {
           name = "John Smith";
           married = true;
           children = 2;
       }

       public void encodeWithWOXMLCoder(WOXMLCoder coder) {
           coder.encodeObjectForKey(name, "Name");
           coder.encodeBooleanForKey(married, "MaritalStatus");
           coder.encodeIntForKey(children, "NumberOfChildren");
       }

       // constructor required for decoding
       public Person(WOXMLDecoder decoder) {
           name = (String)decoder.decodeObjectForKey("Name");
           married = decoder.decodeBooleanForKey("MaritalStatus");
           children = decoder.decodeIntForKey("NumberOfChildren");
       }
   }
 

Decoding XML With a Mapping Model

The mapping decoder gives you greater control over the decoding process, since it operates under the direction of an XML-format mapping model that you create. This mapping model allows you to specify how XML elements and attributes are to be mapped to objects and object properties. Because of the added power and flexibility the mapping model provides, the mapping decoder is well-suited to decode XML that wasn't generated by the WOXMLCoder.

Under this scheme, the object's Class needs to either implement WOXMLCoding or belong to one of the standard classes that WOXMLDecoder takes care of automatically (e.g. EOEnterpriseObject) in order to be decoded properly. Let's see an example. Suppose you had the following XML:

    <command>
      <customer>
        <name>Ringle</name>
        <rental_date>1989-12-07 23:46:11 Etc/GMT</rental_date>
      </customer>
      <fullMovie name="Alien">
        <cat>Horror</cat>
        <role name="Ash"></role>
        <role name="Ripley"></role>
      </fullMovie>
    </command>
 
and the following mapping file:
 <model>
   <entity name="Command" xmlTag="command">
     <property name="movie" xmlTag="fullmovie"/>
     <property name="customer" xmlTag="customer"/>
   </entity>
   <entity name="MyMovie" xmlTag="fullmovie">
     <property name="title" xmlTag="name" attribute="YES"/>
     <property name="roles" xmlTag="role">
     <property name="category" xmlTag="cat"/>
   </entity>
   <entity name="com.webobjects.eocontrol.EOGenericRecord" xmlTag="role">
     <property name="roleName" xmlTag="name" attribute="YES"/>
   </entity>
   <entity name="Customer" xmlTag="customer">
     <property name="name" xmlTag="name"/>
     <property name="date" xmlTag="rental_date"/>
   </entity>
 </model>
 
then, in order for the mapping decoder to construct a meaningful object, you would need the Class to look something like this:
   public class Command implements WOXMLCoding {
       public EOGenericRecord movie;
       public Customer customer;
       public int qty;

	 // Definitions following WOXMLCoding.
       ...
   }
 
There is a subtle but important aspect of decoding with a mapping model that you should be aware of. WOXMLDecoder makes use of an underlying XML parser, which always parses content data in the XML file as Strings. This is expected and fortunately WOXMLDecoder (without mapping model) takes care of coercing a string to the correct data type for all the types that we take care of automatically (e.g. EOEnterpriseObjects). As for classes that implement WOXMLCoding, if you ensure that you call the correct decoding method (e.g. decodeBooleanForKey()) or do the coercion yourself when using decodeObjectForKey(), then you will have no problems with WOXMLDecoder (without mapping model).

Unfortunately, some coercions do not happen when decoding with a mapping model. If you see error messages implying that you have to use a formatter to convert string values, you can use this workaround that involves changing the class that encapsulates a member variable of the problematic type:

For example, the Customer Class needs to be changed so that the String "1989-12-07 23:46:11 Etc/GMT" can be decoded as an NSTimestamp object:
 public class Customer implements NSValidation, NSKeyValueCoding {

   ...

   protected NSTimestamp date;
   protected String name;

   ...

   private static NSTimestampFormatter _DEFAULT_FORMATTER;
   static {
       _DEFAULT_FORMATTER = new NSTimestampFormatter();
   }

   public NSTimestamp validateDate(String dateStr) throws NSValidation.ValidationException {
       NSTimestamp ts;
       try {
           ts = (NSTimestamp)_DEFAULT_FORMATTER.parseObject(dateStr);
       }
       catch (java.text.ParseException e) {
           throw new NSValidation.ValidationException(e.getMessage());
       }
       return ts;
   }

   // Standard NSKeyValueCoding methods
   public NSTimestamp date() {
      return date;
   }

   public void setDate(NSTimestamp date) {
      this.date = date;
   }

   public String message() {
      return message;
   }

   public void setMessage(String message) {
      this.message = message;
   }
 }
 
To decode an object from XML data, invoke one of the decodeRootObject() methods.

See Also:
WOXMLCoder, WOXMLCoding, decodeRootObject(java.lang.String), NSKeyValueCoding

Nested Class Summary
 
Nested classes inherited from class com.webobjects.foundation.NSKeyValueCoding
NSKeyValueCoding.DefaultImplementation, NSKeyValueCoding.ErrorHandling, NSKeyValueCoding.Null, NSKeyValueCoding.UnknownKeyException, NSKeyValueCoding.Utility, NSKeyValueCoding.ValueAccessor
 
Field Summary
 
Fields inherited from interface com.webobjects.foundation.NSKeyValueCoding
NullValue
 
Constructor Summary
protected WOXMLDecoder()
           
 
Method Summary
protected  void addObjectToCache(com.webobjects.appserver.xml._private._DecodingNode childNode, Object anObject)
           
 boolean decodeBooleanForKey(String aKey)
          Decodes the XML data in the internal state of this decoder and returns a boolean value based on the key specified.
 double decodeDoubleForKey(String aKey)
          Decodes the XML data in the internal state of this decoder and returns a double value based on the key specified.
 float decodeFloatForKey(String aKey)
          Decodes the XML data in the internal state of this decoder and returns a float value based on the key specified.
 int decodeIntForKey(String aKey)
          Decodes the XML data in the internal state of this decoder and returns an int value based on the key specified.
 Object decodeObjectForKey(String key)
          Decodes the XML data in the internal state of this decoder and constructs an object based on the key specified.
static WOXMLDecoder decoder()
          Returns a default decoder capable of decoding objects into XML data without using a mapping model.
 Object decodeRootObject(InputSource is)
          Decodes the XML specified by an InputSource is and constructs a corresponding object.
 Object decodeRootObject(NSData data)
          Decodes the XML specified by an NSData data and constructs a corresponding object.
 Object decodeRootObject(String xmlFile)
          Decodes the XML specified by the URL xmlFile and constructs a corresponding object.
static WOXMLDecoder decoderWithMapping(String mappingModelFile)
          Returns a coder object initialized with the mapping model specified by mappingModelFile.
 String encoding()
          Gets the character encoding set previously for the decoding process.
protected  String getChildNodeType(com.webobjects.appserver.xml._private._DecodingNode childNode)
           
protected  com.webobjects.appserver.xml._private._DecodingHandler handler()
           
 Parser parser()
          Gets the current parser used for parsing XML data.
 String parserClassName()
          Gets the class name of the current parser used for parsing the XML data.
 void setEncoding(String encoding)
          Sets the character encoding.
 void setParserClassName(String newValue)
          Sets the current parser's class name so that a new parser of that class can be used.
 void takeValueForKey(Object value, String key)
          Conformance to NSKeyValueCoding.
 String toString()
           
 Object valueForKey(String key)
          Conformance to NSKeyValueCoding.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Constructor Detail

WOXMLDecoder

protected WOXMLDecoder()
Method Detail

addObjectToCache

protected void addObjectToCache(com.webobjects.appserver.xml._private._DecodingNode childNode,
                                Object anObject)

decodeBooleanForKey

public boolean decodeBooleanForKey(String aKey)
Decodes the XML data in the internal state of this decoder and returns a boolean value based on the key specified. Use this method within the single-argument constructor that follows the protocol described in the class description. It is used to set a boolean instance variable to the value of the key element within the XML being decoded. For example, to extract the marital status from the following XML:
 <element type="Person" objectID="4">
   <Name type="java.lang.String" objectID="5">John Smith</Name>
   <MaritalStatus type="boolean">True</MaritalStatus>
   <NumberOfChildren type="int">2</NumberOfChildren>
 </element>
 
You could use something similar to the following:

 boolean married = decoder.decodeBooleanForKey("MaritalStatus");
 

Parameters:
aKey - the tag in the XML data that corresponds to the boolean value being constructed
Returns:
the decoded boolean value

decodeDoubleForKey

public double decodeDoubleForKey(String aKey)
Decodes the XML data in the internal state of this decoder and returns a double value based on the key specified. Use this method within the single-argument constructor that follows the protocol described in the class description. It is used to set a double instance variable to the value of the key element within the XML being decoded.

Parameters:
aKey - the tag in the XML data that corresponds to the double value being constructed
Returns:
the decoded double value

decodeFloatForKey

public float decodeFloatForKey(String aKey)
Decodes the XML data in the internal state of this decoder and returns a float value based on the key specified. Use this method within the single-argument constructor that follows the protocol described in the class description. It is used to set a float instance variable to the value of the key element within the XML being decoded.

Parameters:
aKey - the tag in the XML data that corresponds to the float value being constructed
Returns:
the decoded float value

decodeIntForKey

public int decodeIntForKey(String aKey)
Decodes the XML data in the internal state of this decoder and returns an int value based on the key specified. Use this method within the single-argument constructor that follows the protocol described in the class description. It is used to set a int instance variable to the value of the key element within the XML being decoded. For example, to extract the number of children from the following XML:
 <element type="Person" objectID="4">
   <Name type="java.lang.String" objectID="5">John Smith</Name>
   <MaritalStatus type="boolean">True</MaritalStatus>
   <NumberOfChildren type="int">2</NumberOfChildren>
 </element>
 
You could use something similar to the following:

 int children = decoder.decodeIntForKey("NumberOfChildren");
 

Parameters:
aKey - the tag in the XML data that corresponds to the int value being constructed
Returns:
the decoded int value

decodeObjectForKey

public Object decodeObjectForKey(String key)
Decodes the XML data in the internal state of this decoder and constructs an object based on the key specified. It is called either implicitly from decodeRootObject or directly from the single-argument constructor that follows the protocol described in the class description. When used in the single-argument constructor, it is used to set up an instance variable to a newly constructed object whose class and content depends upon the value of the key.

Parameters:
key - the tag in the XML data that corresponds to the object being constructed
Returns:
the decoded object
See Also:
decodeRootObject(java.lang.String)

decodeRootObject

public Object decodeRootObject(String xmlFile)
Decodes the XML specified by the URL xmlFile and constructs a corresponding object. The file can either contain a complete XML document or an XML segment. If decoding an XML segment (where there's no XML declaration), you can change the character encoding of the data) by using setEncoding.

Parameters:
xmlFile - an URL that points to the file containing the XML data
Returns:
the decoded object
See Also:
setEncoding(java.lang.String)

decodeRootObject

public Object decodeRootObject(NSData data)
Decodes the XML specified by an NSData data and constructs a corresponding object. It can either contain a complete XML document or an XML segment. If decoding an XML segment (where there's no XML declaration), you can change the character encoding of the data) by using setEncoding.

Parameters:
data - an NSData containing the XML data
Returns:
the decoded object
See Also:
setEncoding(java.lang.String), NSData

decodeRootObject

public Object decodeRootObject(InputSource is)
Decodes the XML specified by an InputSource is and constructs a corresponding object. You can learn more about org.xml.sax.InputSource from Apache. The input source can either contain a complete XML document or an XML segment. If decoding an XML segment (where there's no XML declaration), you can change the character encoding of the data) by using setEncoding.

Parameters:
is - an InputSource containing the XML data
Returns:
the decoded object
See Also:
setEncoding(java.lang.String)

decoder

public static WOXMLDecoder decoder()
Returns a default decoder capable of decoding objects into XML data without using a mapping model. This method corresponds directly with the coder factory method in WOXMLCoder. See class description for details on how this coder can be used.

See Also:
WOXMLCoder.coder()

decoderWithMapping

public static WOXMLDecoder decoderWithMapping(String mappingModelFile)
Returns a coder object initialized with the mapping model specified by mappingModelFile. For more information on the mapping model, see the "The Format of the Mapping Model" in the package description. This method corresponds directly with the coderWithMapping factory method in WOXMLCoder. See class description for details on how this coder can be used.

Parameters:
mappingModelFile - an URL to the mapping file that specifies the mapping model
See Also:
WOXMLCoder.coderWithMapping(java.lang.String)

encoding

public String encoding()
Gets the character encoding set previously for the decoding process.

Returns:
the encoding, or null if none was previously set
See Also:
setEncoding(java.lang.String)

getChildNodeType

protected String getChildNodeType(com.webobjects.appserver.xml._private._DecodingNode childNode)

handler

protected com.webobjects.appserver.xml._private._DecodingHandler handler()

parser

public Parser parser()
Gets the current parser used for parsing XML data. The default parser can be changed by using setParserClassName.

Returns:
the current parser
See Also:
setParserClassName(java.lang.String)

parserClassName

public String parserClassName()
Gets the class name of the current parser used for parsing the XML data. An example is "org.apache.xerces.parsers.SAXParser".

Returns:
the class name of the current parser

setEncoding

public void setEncoding(String encoding)
Sets the character encoding. The encoding must be a string acceptable for an XML encoding declaration (see section 4.3.3 of the XML 1.0 recommendation). Use judiciously as the encoding overrides the encoding specified in the XML declaration of the data to be parsed.

This method has no effect when the application provides a character stream since by definition, the characters had already been extracted using a particular encoding.

Parameters:
encoding - a string describing the character encoding
See Also:
encoding()

setParserClassName

public void setParserClassName(String newValue)
Sets the current parser's class name so that a new parser of that class can be used. Unless there is a problem with the default parser, you should not need to change it.

This method must be invoked before the parser is instantiated (by the parser method); once the parser has been instantiated, calling this method has no effect.

Parameters:
newValue - the class name of the new XML parser to use
See Also:
parser()

takeValueForKey

public void takeValueForKey(Object value,
                            String key)
Conformance to NSKeyValueCoding.

Specified by:
takeValueForKey in interface NSKeyValueCoding
Parameters:
key - identifies the property to be set
value - the value to which the property specified by key should be set
See Also:
NSKeyValueCoding.NullValue, NSKeyValueCoding.valueForKey(java.lang.String), NSKeyValueCoding.DefaultImplementation, NSKeyValueCoding.ErrorHandling, NSKeyValueCoding.ErrorHandling.handleTakeValueForUnboundKey(java.lang.Object, java.lang.String)

toString

public String toString()

valueForKey

public Object valueForKey(String key)
Conformance to NSKeyValueCoding.

Specified by:
valueForKey in interface NSKeyValueCoding
Parameters:
key - identifies the property of an object
Returns:
the receiver's value for the property identified by key
See Also:
NSKeyValueCoding.NullValue, NSKeyValueCoding.takeValueForKey(java.lang.Object, java.lang.String), NSKeyValueCoding.DefaultImplementation, NSKeyValueCoding.ErrorHandling, NSKeyValueCoding.ErrorHandling.handleQueryWithUnboundKey(java.lang.String)

Last updated Thu Oct 21 15:04:16 PDT 2004.

Copyright © 2004 Apple Computer, Inc.