<?xml version="1.0" encoding="UTF-8"?>
<!--

 Copyright 2004 The Apache Software Foundation.
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at
 
      http://www.apache.org/licenses/LICENSE-2.0
 
 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.

-->
<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.2//EN" "document-v12.dtd">
<document>
  <header><title>The generic parser</title></header>
  <body>
    <section><title>The generic parser</title>
      <p>The most basic part of JaxMeXS is its generic parser. This part is suited
        for arbitrary XML document types, for example configuration files and the
        like. The actual XML Schema parsers (the
        <link href="syntax.html">syntax parser</link> and the
        <link href="logical.html">logical parser</link>) are sitting on top of
        the generic parser. If you aren't interested in the generic part, you may
        safely skip to the <link href="syntax.html">next section</link>, which is basically
        self contained. However, some details are best described here.</p>
      <p>The generic parser follows an idea from the
        <link href="ext:ant">Ant</link> project: A SAX parser is responsible for the
        configuration of a bean. Any XML element is mapped to a Java bean. The XML
        elements attributes are mapped to properties of the bean and the child
        elements are mapped to other beans, which are part of the parent bean. If
        you know <link href="ext:antwritingowntask">how to write an Ant task</link>,
        you know how the generic parser works.</p>
      <p>The generic parser is specified by the interface
        <link href="../apidocs/org/apache/ws/jaxme/xs/parser/XsSAXParser.html">XsSAXParser</link> and
        implemented by the class
        <link href="../apidocs/org/apache/ws/jaxme/xs/parser/XsSAXParserImpl.html">XsSAXParserImpl</link>.
        There's few things to know about that. The most important parts are some other
        interfaces and classes which you might like to implement or extend:</p>
      <ol>
        <li>The <link href="#AttributeSetter">AttributeSetter</link>
          interface is responsible for mapping XML attributes to bean properties.</li>
        <li>The <link href="#TextSetter">TextSetter</link> handles character data contained
          in elements.</li>
        <li>And, finally, the <link href="#ChildSetter">ChildSetter</link> creates new beans
          for any child element.</li>
      </ol>
    </section>

    <anchor id="AttributeSetter"/>
    <section><title>The AttributeSetter interface</title>
      <p>The <link href="../apidocs/org/apache/ws/jaxme/xs/parser/AttributeSetter.html">AttributeSetter</link>
        interface consists of a single method:</p>
      <source>
  public void setAttribute(String pQName, String pNamespaceURI,
                           String pLocalName, String pValue) throws SAXException;
      </source>
      <p>This method is invoked for any attribute that the SAX parser finds.</p>
      <p>The AttributeSetters main idea is as follows: Suggest, that the attributes local
        name is <code>foo</code>. A method <code>setFoo(SomeClass pValue)</code> is searched.
        f such a method is found, the attribute value is converted into an instance of
        <code>SomeClass</code> and the method is invoked. More formally, the default
        implementation <link href="../apidocs/org/apache/ws/jaxme/xs/parser/impl/AttributeSetterImpl.html">
        AttributeSetterImpl</link> behaves as follows:</p>
      <ol>
        <li>If the bean has a method <code>setAttribute(String, String, String, String)</code>,
          it is invoked with the same arguments <code>pQName</code>, <code>pNamespaceURI</code>,
          <code>pLocalName</code>, <code>pValue</code>. If this method does not have
          the result types <code>boolean</code> or <code>Boolean</code>, or if the result
          is <code>true</code>, then the <code>AttributeSetterImpl</code> assumes that the
          property is set.</li>
        <li>If the property is not set, and the bean has a method
          <code>setProperty(String)</code>, then this method is invoked
          with the attribute value.</li>
        <li>Otherwise, if the bean has a method <code>setProperty(T)</code>, and
          the class <code>T</code> has either of a method
          <code>public static T valueOf(String)</code> or a constructor
          <code>public T(String)</code> (in that order), then the method
          <code>setProperty(T)</code> is invoked with the value obtained
          by an invocation of the method <code>valueOf()</code>, or
          the constructor, respectively. Note, that this applies in
          particular to the classes Long, Integer, Short, Byte, Double,
          Float, java.math.BigInteger, java.math.BigDecimal,
          java.io.File, and StringBuffer.</li>
        <li>If the bean has a method <code>setProperty(boolean)</code>,
          the method will be invoked with the value <code>true</code>
          (the value specified in the XML file is either of
          <code>true</code>, or <code>1</code>) or <code>false</code>
          (the attribute has any other value).</li>
       <li>If the bean has a method <code>setProperty(char)</code>,
         or <code>setProperty(Character)</code>, the method will be
         invoked with the first character of the value specified in
         the XML file. If the value contains zero or multiple characters,
         an IllegalArgumentException is thrown.</li>
       <li>If the bean has either of the following methods, in that order:
         <ul>
           <li><code>setProperty(long)</code></li>
           <li><code>setProperty(int)</code></li>
           <li><code>setProperty(short)</code></li>
           <li><code>setProperty(byte)</code></li>
           <li><code>setProperty(double)</code></li>
           <li><code>setProperty(float)</code></li>
         </ul>
         then the attribute value is converted into the respective type
         and the method is invoked. An IllegalArgumentException
         is thrown, if the conversion fails.</li>
       <li>If the bean has a method <code>java.lang.Class</code>, the
         <code>XsSAXParser</code> will interpret the value given in the
         XML file as a Java class name and load the named class from its
         class loader. If the class cannot be loaded, it will also try
         to use the current threads context class loader. An
         exception is thrown, if neither of the class loaders can
         load the class.</li>
      </ol>
    </section>

    <anchor id="TextSetter"/>
    <section><title>The TextSetter interface</title>
      <p>The <link href="../apidocs/org/apache/ws/jaxme/xs/parser/TextSetter.html">TextSetter</link>
        interface is invoked from within the SAX ContentHandlers method
        <code>characters(char[] pBuffer, int pOffset, int pLen)</code>.
        It's task is to fill the bean with character data. Note, that the latter
        method may very well be called multiple times, even for a single
        character sequence in the XML file. For example, if the XML reader
        loads the XML file in blocks of 1024 characters and a block stops
        right within an elements character data, then it is valid behaviour
        to call the <code>character(char[], int, int)</code> method twice:
        Once for the first part, which sits at the end of the 1024 characters
        and once for the remaining part. The same holds for the <code>addText()</code>
        method:</p>
      <source>
  public void addText(String pValue) throws SAXException;
      </source>
      <p>The default implementation is
        <link href="../apidocs/org/apache/ws/jaxme/xs/parser/impl/TextSetterImpl.html">
          TextSetterImpl</link>, which behaves as follows:</p>
      <ol>
        <li>If the bean has a method with the same signature
          <code>public void addText(String)</code>, then the method is invoked.</li>
        <li>If the bean doesn't have such a method and the supplied text is
          all whitespace, then the text is ignored. Otherwise an exception
          is thrown.</li>
      </ol>
    </section>

    <anchor id="ChildSetter"/>
    <section><title>Handling child elements</title>
      <p>Embedded child elements are handled by the interface
        <link href="../apidocs/org/apache/ws/jaxme/xs/parser/ChildSetter.html">ChildSetter</link> and
        its default implementation
        <link href="../apidocs/org/apache/ws/jaxme/xs/parser/impl/ChildSetterImpl.html">ChildSetterImpl</link>.
        The interface exposes a single method:</p>
      <source>
  public ContentHandler getChildHandler(String pQName, String pNamespaceURI,
                                        String pLocalName) throws SAXException;
        </source>
      <p>The purpose of the method is to create a SAX handler for this element.
        If such a handler is returned, then it receives the SAX events generated
        for the element. The default implementation works as follows:</p>
      <ol>
        <li>If the bean has a method with the same signature
          <code>public ContentHandler getChildHandler(String, String, String, String)</code>,
          then this method is invoked. A non-null result will be used as a ContentHandler
          for the child element.</li>
        <li>If the bean doesn't have such a method or if the method returned null,
          and the local name is <code>foo</code>, then a method
          <code>public T createFoo()</code> is searched, with an arbitrary result type T.
          If there is such a method it is invoked and a new instance of
          <link href="../apidocs/org/apache/ws/jaxme/xs/parser/impl/XsSAXParserImpl.html">XsSAXParserImpl</link>
          is created to configure the bean.</li>
        <li>An exception is thrown otherwise.</li>
      </ol>
    </section>
  </body>
</document>
