Package org.jbpm.wire.binding

Source Code of org.jbpm.wire.binding.ObjectBinding

/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jbpm.wire.binding;

import java.util.ArrayList;
import java.util.List;

import org.jbpm.wire.Descriptor;
import org.jbpm.wire.descriptor.ArgDescriptor;
import org.jbpm.wire.descriptor.ObjectDescriptor;
import org.jbpm.wire.operation.Operation;
import org.jbpm.wire.xml.WireParser;
import org.jbpm.xml.Binding;
import org.jbpm.xml.Parse;
import org.jbpm.xml.Parser;
import org.jbpm.xml.XmlUtil;
import org.w3c.dom.Element;

/**
* <p>This {@link Binding} specifies a {@link ObjectDescriptor} (to create an object).</p>
* <p> Objects can be instantiated from a constructor or from a method invocation.</p>
*
* <p>An object descriptor is defined by a <b><code>{@literal <object>}</code></b> element.</p>
*
* <p>This element can have an attribute "name", which specifies the name of the created object in the WireContext.</p>
* <p>This element can have an attribute "auto-wire", which specifies if auto-wire is enabled (see <a href='#autowire'>Auto Wiring</a>)</p>
*
* <p>The method to create the object is specified with one of these methods (see <a href='#create'>creating objects</a>):
* <ul>
* <li>attribute "class" in the xml element</li>
* <li>attribute "factory" in the xml element</li>
* <li>element "factory" as a child of the xml element</li>
* </ul>
* Only one of these methods can be used.
* </p>
*
* <p>The method attribute specifies a method to call on the object.
* If the method is called on a previously created object,
* the access to this object is specified by the "factory" element or attribute.
* If the method is static, the class is specified by the "class" attribute.
* The arguments are taken from the {@literal <arg>} children elements.</p>
*
* <h3 id='create'>Creating objects</h3>
* <h4>Creating object from a constructor</h4>
*
* <p>This method uses the "class" attribute.</p>
*
* <p>The constructor is specified by the {@literal <constructor>} element.
* It contains a list of {@literal <arg>} elements, which are the arguments to give to the constructor.
* </p>
*
* <p><i>the method attribute must not be used if the {@literal <constructor>} element is specified.</i></p>
*
* <h5>Example</h5>
* Consider the following class:
* <pre> public class Foo {
*   String bar;
*   public Foo(String text) {
*     bar = text;
*   }
* }</pre>
*
* The following Xml declaration will create an object 'o' of class 'Foo'.
* The object will be constructed by calling <code>new Foo("hello")</code>.
*
* <pre>{@literal <objects>
*   <object name='o' class='Foo'>
*     <constructor>
*       <arg>
*        <string value='hello' />
*       </arg>
*     </constructor>
*   </object>
* </objects>}</pre>
*
* <h4>Creating an object from a method invocation</h4>
*
* <p>The name of the method to call is specified by the method attribute.</p>
* <ul>
* <li>If the method is <i>static</i>, the related class is declared by the "class" attribute.</li>
* <li>If the method is an object method, to object to which the method will be applied is defined by the 'factory' element or attribute.
* The object will be fetched from the context ('factory' attribute) or created from a descriptor (contained in the 'factory' element).</li>
* </ul>
* <p>The object constructed by the resulting {@link ObjectDescriptor} is the object returned by the call to the specified method.</p>
*
*
* <h3>Initializing Objects</h3>
* <h4 id='autowire'>Auto Wiring</h4>
* <p>If the auto wiring is enabled for the object (the attribute "auto-wire" is set to "true", "enabled" or "on"),
* the WireContext will try to look for objects with the same name as the fields in the class.
* If it finds an object with that name, and if it is assignable to the field's type, it is automatically injected,
* without the need for explicit &lt;field&gt; tag that specifies the injection in the wiring xml.</p>
* <p>If the auto wiring is enabled and the WireContext finds an object with the name of a field, but not assignable to this field,
* a warning message is generated.</p>
* <p>Auto-wiring is disabled by default (if no auto-wire attribute is found, a default value "auto-wire=disabled" is used).</p>
*
* <h4>Operations</h4>
* <p>Field injection or property injection are done after the auto-wiring. For more information, see {@link Operation}.</p>
*
* <p>If a field was injected by auto-wiring, its value can be overridden by specifying a &lt;field&gt; or &lt;property&gt; operation.</p>
*
* <p>Known Xml tags to specify an {@link Operation}:
* <ul>
* <li><b><code>{@literal <property .../>}</code></b>: see {@link PropertyBinding}</li>
* <li><b><code>{@literal <field .../>}</code></b>: see {@link FieldBinding}</li>
* <li><b><code>{@literal <invoke .../>}</code></b>: see {@link InvokeBinding}</li>
* <li><b><code>{@literal <subscribe .../>}</code></b>: see {@link SubscribeBinding}</li>
* <li><b><code>{@literal <enlist .../>}</code></b>: see {@link EnlistBinding}</li>
* </ul>
* </p>
* @author Tom Baeyens
* @author Guillaume Porcher (documentation)
*
* @see WireParser
*/
public class ObjectBinding implements Binding {

  public Object parse(Element element, Parse parse, Parser parser) {
    ObjectDescriptor descriptor = new ObjectDescriptor();

    WireParser wireParser = (WireParser) parser;
    String className = XmlUtil.attribute(element, "class");
    String factoryObjectName = XmlUtil.attribute(element, "factory");
    Element factoryElement = XmlUtil.element(element, "factory");

    if (className!=null) {
      descriptor.setClassName(className);
      if (factoryObjectName!=null) {
        parse.addProblem("attribute factory is specified together with attribute class in element object: "+XmlUtil.toString(element));
      }
      if (factoryElement!=null) {
        parse.addProblem("element factory is specified together with attribute class in element object: "+XmlUtil.toString(element));
      }

      Element constructorElement = XmlUtil.element(element, "constructor");
      if (constructorElement!=null) {
        List<Element> argElements = XmlUtil.elements(constructorElement, "arg");
        List<ArgDescriptor> argDescriptors = wireParser.parseArgs(argElements, parse);
        descriptor.setArgDescriptors(argDescriptors);

        if (element.hasAttribute("method")) {
          parse.addProblem("attributes class and method indicate static method and also a constructor element is specified for element object: "+XmlUtil.toString(element));
        }
      }

    } else if (factoryObjectName!=null) {
      descriptor.setFactoryObjectName(factoryObjectName);
      if (factoryElement!=null) {
        parse.addProblem("element factory is specified together with attribute factory in element object: "+XmlUtil.toString(element));
      }

    } else if (factoryElement!=null) {
      Element factoryDescriptorElement = XmlUtil.element(factoryElement);
      Descriptor factoryDescriptor = (Descriptor) parser.parseElement(factoryDescriptorElement, parse, WireParser.CATEGORY_DESCRIPTOR);
      descriptor.setFactoryDescriptor(factoryDescriptor);

    } else {
      parse.addProblem("element object must have one of {attribute class, attribute factory or element factory}: "+XmlUtil.toString(element));
    }

    // method
    if (element.hasAttribute("method")) {
      descriptor.setMethodName(element.getAttribute("method"));

      List<Element> argElements = XmlUtil.elements(element, "arg");
      List<ArgDescriptor> argDescriptors = wireParser.parseArgs(argElements, parse);
      descriptor.setArgDescriptors(argDescriptors);
    } else if (className == null) {
      parse.addProblem("element object with a element factory or a attribute factory must have a attribute method: "+XmlUtil.toString(element));
    }

    if( (className == null) && (XmlUtil.element(element, "constructor") != null)){
      parse.addProblem("element object with a element factory or a attribute factory can't have a constructor element: "+XmlUtil.toString(element));
    }

    // read the operations elements
    List<Operation> operations = null;
    List<Element> elements = XmlUtil.elements(element);
    if (elements!=null) {
      for (Element childElement: elements) {
        if(!childElement.getTagName().equals("constructor")
            && !childElement.getTagName().equals("factory")
            && !childElement.getTagName().equals("arg")){
          Operation operation = (Operation) parser.parseElement(childElement, parse, WireParser.CATEGORY_OPERATION);
          if (operation!=null) {
            if (operations==null) {
              operations = new ArrayList<Operation>();
            }
            operations.add(operation);
          }else{
            parse.addProblem("element object can only have factory, arg, constructor elements or " +
                "an operation element ("+ parser.getBindings().getTagNames(WireParser.CATEGORY_OPERATION) +")." +
                " Invalid element '"+childElement.getTagName()+"' in: "+XmlUtil.toString(element));
          }
        }
      }
    }
    descriptor.setOperations(operations);

    // autowiring
    String autoWireText = XmlUtil.attribute(element, "auto-wire");
    Boolean isAutoWireEnabled = XmlUtil.booleanEquals(autoWireText, Boolean.FALSE);
    if (isAutoWireEnabled==null) {
      parse.addProblem("invalid auto-wire value: '"+autoWireText+"' in "+XmlUtil.toString(element));
    } else if (isAutoWireEnabled) {
      descriptor.setAutoWireEnabled(true);
    }
    return descriptor;
  }
}
TOP

Related Classes of org.jbpm.wire.binding.ObjectBinding

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.