/*******************************************************************************
$Source: /cvs/repositories/openii3/project/java/source/org/openeai/moa/XmlEnterpriseObjectImpl.java,v $
$Revision: 1.39 $
*******************************************************************************/
/**********************************************************************
This file is part of the OpenEAI Application Foundation or
OpenEAI Message Object API created by Tod Jackson
(tod@openeai.org) and Steve Wheat (steve@openeai.org) at
the University of Illinois Urbana-Champaign.
Copyright (C) 2002 The OpenEAI Software Foundation
This library 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 library 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 library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
For specific licensing details and examples of how this software
can be used to build commercial integration software or to implement
integrations for your enterprise, visit http://www.OpenEai.org/licensing.
*/
package org.openeai.moa;
import java.io.ByteArrayInputStream;
import java.lang.reflect.*;
import java.util.HashMap;
import java.util.Properties;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import org.openeai.xml.*;
import org.openeai.config.*;
import org.openeai.layouts.*;
import org.openeai.moa.objects.testsuite.TestId;
/**
* This is the ancestor class of our "xml aware" objects inclued in the
* Message Object API (MOA). This includes both "message/jms aware" objects like
* BasicPerson and child objects that are "xml aware" but not "message/jms aware"
* like the Address object which is a child object of BasicPerson.
* <P>
* @author Tod Jackson (tod@openeai.org)
* @author Steve Wheat (steve@openeai.org)
* @version 3.0 - 28 January 2003
*/
public class XmlEnterpriseObjectImpl
extends EnterpriseObjectBase implements XmlEnterpriseObject, org.openeai.PubliclyCloneable {
private EnterpriseLayoutManager m_saveInputLManager = null;
private EnterpriseLayoutManager m_saveOutputLManager = null;
private boolean m_validate = false;
private boolean m_deferInitialization = false;
private Document m_provideDoc=null;
private Document m_responseDoc=null;
private Document m_createDoc=null;
private Document m_updateDoc=null;
private Document m_deleteDoc=null;
private Document m_queryDoc=null;
private Document m_generateDoc=null;
private Document m_createSyncDoc=null;
private Document m_deleteSyncDoc=null;
private Document m_updateSyncDoc=null;
private Document m_generateSyncDoc=null;
private String m_provideDocUri=null;
private String m_responseDocUri=null;
private String m_createDocUri=null;
private String m_updateDocUri=null;
private String m_deleteDocUri=null;
private String m_queryDocUri=null;
private String m_generateDocUri=null;
private String m_createSyncDocUri=null;
private String m_deleteSyncDocUri=null;
private String m_updateSyncDocUri=null;
private String m_generateSyncDocUri=null;
// Move the following to EnterpriseObject...
// private MessageSeries m_messageSeries = null;
// private Predecessor m_predecessor = null;
private EnterpriseFields m_fields = null;
public static EnterpriseFields ENTERPRISE_FIELDS = null;
private HashMap m_inputLayoutManagers = new HashMap();
private HashMap m_outputLayoutManagers = new HashMap();
private final static String LIST = "java.util.List";
public static EnterpriseLayoutManager XML_LAYOUT_MANAGER = null;
private EnterpriseLayoutManager m_inputLayoutManager = null;
private EnterpriseLayoutManager m_outputLayoutManager = null;
private TestId m_testId = null;
private XmlEnterpriseObject m_baseline = null;
/**
*
**/
private void setDeferInitialization(boolean defer) {
m_deferInitialization = defer;
}
/**
*
**/
public final boolean deferInitialization() {
return m_deferInitialization;
}
/**
* Sets the baseline object associated to this object. The baseline object
* is populated by all objects when that object performs a Query action
* via the JmsEnterpriseObject.query method. Then,
* when updates are performed on the object and an Update-Request/Sync is made on behalf
* of the object (via the JmsEnterpriseObject.update/updateSync method, it uses the baseline
* object to populate the DataArea/BaselineData element in the update document.
* The baseline object remains untouched during the processing on the main object.
*<P>
* @param baseline XmlEnterpriseObject the baseline object (e.g. - BasicPerson) that is an
* image of the object at the time the Query action was performed.
*/
public final void setBaseline(XmlEnterpriseObject baseline) {
m_baseline = baseline;
}
/**
* Returns the baseline object associated to this object. The baseline object
* is populated by all objects when that object performs a Query action
* via the JmsEnterpriseObject.query method. Then,
* when updates are performed on the object and an Update-Request/Sync is made on behalf
* of the object (via the JmsEnterpriseObject.update/updateSync method, it uses the baseline
* object to populate the DataArea/BaselineData element in the update document.
* The baseline object remains untouched during the processing on the main object.
*<P>
* @return XmlEnterpriseObject the baseline object (e.g. - BasicPerson) that is an
* image of the object at the time of the Query.
*/
public final XmlEnterpriseObject getBaseline() {
return m_baseline;
}
/**
* Sets the test id associated to this object. This is used during testing to correlate
* a message sent by a particular object to a message consumed by a gateway. This is
* related to the OpenEAI Test Suite foundation.
*<P>
* @param tId TestId the test id object associated to this object.
*/
public void setTestId(TestId tId) {
m_testId = tId;
}
/**
* Returns the test id associated to this object. This is used during testing to correlate
* a message sent by a particular object to a message consumed by a gateway. This is
* related to the OpenEAI Test Suite foundation.
*<P>
* @return TestId the test id object associated to this object.
*/
public TestId getTestId() {
return m_testId;
}
/**
* Constructor
*/
public XmlEnterpriseObjectImpl() {
}
// Move the following to EnterpriseObject...
/*
public void setMessageSeries(MessageSeries series) {
m_messageSeries = series;
}
public MessageSeries getMessageSeries() {
return m_messageSeries;
}
public void initializeMessageSeries(String uuidUri) throws XmlEnterpriseObjectException {
try {
GenericUuid guuid = new GenericUuid(uuidUri);
String uuid = guuid.getId();
MessageSeries mSeries = new MessageSeries();
mSeries.setMessageSeriesId(uuid);
mSeries.setMessageSeriesSequence("1");
setMessageSeries(mSeries);
}
catch (Exception e) {
String errMessage = "Error initializing MessageSeries. Exception: " + e.getMessage();
logger.fatal(errMessage);
throw new XmlEnterpriseObjectException(errMessage, e);
}
}
public void setPredecessor(Predecessor predecessor) {
m_predecessor = predecessor;
}
public Predecessor getPredecessor() {
return m_predecessor;
}
*/
/**
* Object initialization. This method initializes the current object with information
* contained in the MessageObjectConfig passed in. All XmlEnterpriseObjectImpls
* inherit this functionality and the init method is called when the AppConfig object
* is being built for a particular application. This method will never be called
* directly from an application. The call is "behind the scenes". The values stored in the config
* object passed in are retreived from the Application Deployment and EnterpriseObjects
* documents. This includes configuration information for things like: Primed Documents,
* Xml Validation, Enterprise field rules (translation, formats, scrubbing etc.) and
* Layout management. See the documentation for the Application Deployment and
* EnterpriseObjects Xml documents for more information on these items. More information
* can also be found in the JavaDoc for the org.openeai.config package.
*<P>
* @param mConfig MessageObjectConfig object loaded with all configuration information
* relative to this object built from the configuration document.
*<P>
* @throws EnterpriseObjectException if errors occur initializing the current MessageObject.
* @see org.openeai.config.MessageObjectConfig
* @see org.openeai.config.EnterpriseFields
*/
public void init(MessageObjectConfig mConfig) throws EnterpriseObjectException {
Properties props = mConfig.getProperties();
XmlDocumentReader xmlReader = new XmlDocumentReader();
setDeferInitialization(new Boolean(props.getProperty("deferInitialization","false")).booleanValue());
try {
setCreateDocUri(props.getProperty("create-PrimedXmlDocument",null));
setCreateSyncDocUri(props.getProperty("createSync-PrimedXmlDocument",null));
setDeleteDocUri(props.getProperty("delete-PrimedXmlDocument",null));
setDeleteSyncDocUri(props.getProperty("deleteSync-PrimedXmlDocument",null));
setGenerateDocUri(props.getProperty("generate-PrimedXmlDocument",null));
setGenerateSyncDocUri(props.getProperty("generate-PrimedXmlDocument",null));
setUpdateDocUri(props.getProperty("update-PrimedXmlDocument",null));
setUpdateSyncDocUri(props.getProperty("updateSync-PrimedXmlDocument",null));
setQueryDocUri(props.getProperty("query-PrimedXmlDocument",null));
setProvideDocUri(props.getProperty("provide-PrimedXmlDocument",null));
setResponseDocUri(props.getProperty("response-PrimedXmlDocument",null));
// if initialization is deferred, we'll wait until the user makes their
// first request of a particular document to initialize it.
if (deferInitialization() == false) {
setCreateDoc(xmlReader.initializeDocument(getCreateDocUri(), getValidation()));
setCreateSyncDoc(xmlReader.initializeDocument(getCreateSyncDocUri(), getValidation()));
setDeleteDoc(xmlReader.initializeDocument(getDeleteDocUri(), getValidation()));
setDeleteSyncDoc(xmlReader.initializeDocument(getDeleteSyncDocUri(), getValidation()));
setGenerateDoc(xmlReader.initializeDocument(getGenerateDocUri(), getValidation()));
setGenerateSyncDoc(xmlReader.initializeDocument(getGenerateSyncDocUri(), getValidation()));
setUpdateDoc(xmlReader.initializeDocument(getUpdateDocUri(), getValidation()));
setUpdateSyncDoc(xmlReader.initializeDocument(getUpdateSyncDocUri(), getValidation()));
setQueryDoc(xmlReader.initializeDocument(getQueryDocUri(), getValidation()));
setProvideDoc(xmlReader.initializeDocument(getProvideDocUri(), getValidation()));
setResponseDoc(xmlReader.initializeDocument(getResponseDocUri(), getValidation()));
}
}
catch (XmlDocumentReaderException e) {
logger.fatal(e.getMessage(), e);
throw new EnterpriseObjectException(e.getMessage(), e);
}
try {
setValidation(new Boolean(props.getProperty("xmlDocumentValidation","false")).booleanValue());
setEnterpriseFields((EnterpriseFields)mConfig.getEnterpriseFields().clone());
// Set a Static Enterprise fields object here as well for use by objects that
// aren't configured via a config doc?
// note, the following inclusion of JmsEnterpriseObject is only for backward compatibility
if ((this instanceof org.openeai.moa.jmsobjects.JmsEnterpriseObject) ||
(this instanceof org.openeai.moa.ActionableEnterpriseObject)) {
if (XmlEnterpriseObjectImpl.ENTERPRISE_FIELDS == null) {
logger.debug("Setting static EnterpriseFields object to be that of " + getClass().getName());
XmlEnterpriseObjectImpl.ENTERPRISE_FIELDS = (EnterpriseFields)mConfig.getEnterpriseFields().clone();
}
}
setInputLayoutManagers(mConfig.getInputLayoutManagers());
setInputLayoutManager(mConfig.getInputLayoutManager()); // The default one (first in list).
setOutputLayoutManagers(mConfig.getOutputLayoutManagers());
setOutputLayoutManager(mConfig.getOutputLayoutManager()); // The default one (first in list).
// Set a static Xml Layout manager (input and output) for objects that aren't configured
// via a config doc.
// note, the following inclusion of JmsEnterpriseObject is only for backward compatibility
if ((this instanceof org.openeai.moa.jmsobjects.JmsEnterpriseObject) ||
(this instanceof org.openeai.moa.ActionableEnterpriseObject)) {
if (XmlEnterpriseObjectImpl.XML_LAYOUT_MANAGER == null) {
logger.debug("Setting static XmlLayoutManager object to be that of " + getClass().getName());
XmlEnterpriseObjectImpl.XML_LAYOUT_MANAGER = getInputLayoutManager("xml");
}
}
}
catch (Exception e) {
throw new EnterpriseObjectException(e.getMessage(), e);
}
}
/**
* This method sets the EnterpriseFields and XML layout manager information on the child object
* passed in to be that of the current object. This is a convenience method that can
* be used by Parent objects when returning a child object from a "getter" method. Since
* the child objects will not be initialized with this information at start up, this
* eliminates the need to application developers to do this programmatically since
* it can be done automatically in the getter methods.
*<P>
* Example: The BasicPerson object has a child object in it called Name. The
* name object is another XmlEnterpriseObjectImpl. When the getName() method is
* called on BasicPerson, this method is called to "give" the Name object being returned
* the EnterpriseFields and XmlLayout manager associated to the BasicPerson. Since
* the BasicPerson's EnterpriseObjects XML document will also have to include the Name
* object's definition, the Name object returned by the BasicPerson.getName() method will
* have what it needs to function properly and no action will be required by the developers.
*<P>
* @param childXeo XmlEnterpriseObjectImpl the child object being initialized.
*/
public final void initializeChild(XmlEnterpriseObject childXeo) {
// set the enterprsiefields and xmllayout manager on the object
// we're returning to that of this parent object. This way,
// the object returned will be all set up for buildObjectFromInput etc.
if (childXeo.getEnterpriseFields() != null) {
try {
// childXeo.setEnterpriseFields((EnterpriseFields)getEnterpriseFields().clone());
childXeo.setEnterpriseFields(getEnterpriseFields());
}
catch (Exception e) {
childXeo.setEnterpriseFields(getEnterpriseFields());
}
}
// this way only initialized the child with the current XML Layout Manager.
// this may not be enough in some cases (where there are is more than one layout
// manager in use).
/*
XmlLayout inXmlLayout = (XmlLayout)getInputLayoutManager("xml");
XmlLayout outXmlLayout = (XmlLayout)getOutputLayoutManager("xml");
childXeo.getInputLayoutManagers().put("xml",inXmlLayout);
childXeo.setInputLayoutManager(inXmlLayout);
childXeo.getOutputLayoutManagers().put("xml",outXmlLayout);
childXeo.setOutputLayoutManager(outXmlLayout);
*/
// this is the way it should be, so we'll be sure to pass along
// ALL layout managers and not just the XML one.
childXeo.setInputLayoutManager(getInputLayoutManager());
childXeo.setInputLayoutManagers(getInputLayoutManagers());
childXeo.setOutputLayoutManager(getOutputLayoutManager());
childXeo.setOutputLayoutManagers(getOutputLayoutManagers());
}
/**
* Recursively checks the contents of the object and true if it contains any data. Otherwise,
* it returns false. For example, if the BasicPerson/Name/FirstName variable
* has data in it, this method will return true. If no instance variables, or child
* objects have data in them, it returns false.
*<P>
* @return boolean an indicator specifying whether or not the object is empty.
*<P>
* @throws XmlEnterpriseObjectException if any errors occur when determining
* if the object empty.
*/
public boolean isEmpty() throws XmlEnterpriseObjectException {
boolean isDate = isDate();
Method[] methods = getClass().getDeclaredMethods();
java.util.ArrayList m = new java.util.ArrayList();
for (int i=0; i<methods.length; i++) {
m.add(methods[i]);
}
if (isDate) {
Class superClass = getClass().getSuperclass();
String superClassName = superClass.getName();
String superObjectName = superClassName.substring(superClassName.lastIndexOf('.') + 1);
if (superObjectName.equals("Date") || superObjectName.equals("Datetime")) {
// it extends the OpenEAI Date/Datetime object.
Method[] superClassMethods = superClass.getDeclaredMethods();
for (int i=0; i<superClassMethods.length; i++) {
m.add(superClassMethods[i]);
}
}
}
for (int i=0; i<m.size(); i++) {
Method getter = (Method)m.get(i);
String methodName = getter.getName();
// Ignore the getType method on Date objects only.
if (methodName.equals("getType") && isDate) {
continue;
}
// Ignore getter methods that take parms.
if (getter.getParameterTypes().length > 0) {
continue;
}
if (methodName.indexOf("get") == 0) {
// If we find a getter method, we need to call it. If it's a String
// we need to check to see if it's length is greater than zero, if
// if is, return true.
// If it's an XmlEnterpriseObjectImpl, we need to return the isEmpty
// method on it.
// If it's a List, we need to check its length and if it's greater
// than zero return true;
String fieldName = methodName.substring(methodName.indexOf("get")+3);
logger.debug("[isEmpty] Calling getter method for " + fieldName);
try {
Object obj = getter.invoke(this, new Object[] {});
if (obj instanceof String) {
String retVal = (String)obj;
if (retVal != null) {
if (retVal.length() > 0) {
logger.debug("[isEmpty-String] Found data in " + fieldName);
return false;
}
}
}
else if (obj instanceof XmlEnterpriseObject) {
XmlEnterpriseObject xeo = (XmlEnterpriseObject)obj;
boolean xeoIsEmpty = xeo.isEmpty();
if (xeoIsEmpty == false) {
logger.debug("[isEmpty-XmlEnterpriseObjectImpl] Found data in " + fieldName);
return false;
}
}
else if (obj instanceof java.util.List) {
java.util.List v = (java.util.List)obj;
if (v.size() > 0) {
logger.debug("[isEmpty-List] Found data in " + fieldName);
return false;
}
}
}
catch (InvocationTargetException e) {
String errMessage = "Couldn't invoke method: get" + fieldName + " on object " +
getClass().getName() + " Exception: " + e.getMessage();
throw new XmlEnterpriseObjectException(errMessage, e);
}
catch (IllegalAccessException e1) {
String errMessage = "Couldn't access method: get" + fieldName + " on object " +
getClass().getName() + " Exception: " + e1.getMessage();
throw new XmlEnterpriseObjectException(errMessage, e1);
}
}
}
return true;
}
/**
* Checks to see if this object is a "Date/Datetime" object. This is because Dates and Datetimes
* contain special constructors that indicate the type of Date/Datetime being built and
* several other foundation components need to determine if an object being dealt with
* is one of those Date/Datetime objects.
*
* @return boolean
*
*/
public final boolean isDate() {
String className = getClass().getName();
String objectName = className.substring(className.lastIndexOf('.') + 1);
if (objectName.equals("Date") || objectName.equals("Datetime")) {
return true;
}
return false;
}
private boolean isDate(String className) {
String objectName = className.substring(className.lastIndexOf('.') + 1);
if (objectName.equals("Date") || objectName.equals("Datetime")) {
return true;
}
return false;
}
public Object clone() throws CloneNotSupportedException {
try {
return deepCopy();
}
catch (Exception e) {
throw new CloneNotSupportedException(e.getMessage());
}
}
/**
* Performs a recursive field for field copy of the current Object and returns the result.
* Any object found that supports the "clone" method is cloned. Since all simple fields within
* an XmlEnterpriseObjectImpl are ultimately Strings, the resulting object is in fact a new object
* because the copy is recursive.
*
* @return XmlEnterpriseObject a "deep" copy of the object.
*
*/
private XmlEnterpriseObject deepCopy() throws EnterpriseObjectException {
// Create a new XmlEnterpriseObjectImpl,
// Go through all getter methods of the current object, and call the setter
// methods on the new object...
// Save this value because we're going to have to potentially set initial values to null or blank
// on fields that aren't allowed to be null or blank when the message is produced. Therefore,
// we'll set this value to false while we do the copy and then set it back to whatever the value
// was initially when we're done.
String className = this.getClass().getName();
EnterpriseFields xeoFields = null;
boolean existingIgnoreValidation = getEnterpriseFields().ignoreValidation();
XmlEnterpriseObject newXeo = null;
try {
xeoFields = (EnterpriseFields)getEnterpriseFields().clone();
if (xeoFields == null) {
throw new EnterpriseObjectException("No EnterpriseFields object found in this " + className + ". Cannot continue!");
}
java.lang.Class obj = java.lang.Class.forName(className);
newXeo = (XmlEnterpriseObject)obj.newInstance();
newXeo.setEnterpriseFields((EnterpriseFields)getEnterpriseFields().clone());
newXeo.getEnterpriseFields().setIgnoreValidation(true);
logger.debug("[deepCopy] Instantiated a " + newXeo.getClass().getName());
}
catch (Exception e) {
throw new EnterpriseObjectException("Error instantiating a " + className + " Exception: " + e.getMessage(), e);
}
Method[] methods = newXeo.getClass().getMethods();
for (int i=0; i<methods.length; i++) {
Method setter = methods[i];
String methodName = setter.getName();
Class[] parmTypes = setter.getParameterTypes();
if (parmTypes.length == 1) {
if (methodName.indexOf("set") == 0) {
// If we find a setter method, we need to call the corresponding getter
// method on the new XmlEnterpriseObject we created passing the value
// returned from the getter method from the current object.
String fieldName = methodName.substring(methodName.indexOf("set")+3);
Method getter = null;
logger.debug("[deepCopy] Calling setter method for " + fieldName);
try {
getter = newXeo.getClass().getMethod("get" + fieldName, new Class[] {});
Class c = getter.getReturnType();
// Have to create a new List if the return type is List, cloning isn't enough
// So, we'll create a new list to be used in the call to the setter method
// We'll populate that list with values from the getter method (one at a time).
// If the objects stored in the list are of type XmlEnterpriseObjectImpl
// we'll call the deepCopy method on each one of those objects before adding
// them to the new list.
if (c == java.util.List.class) {
java.util.List getterList = (java.util.List)getter.invoke(this, new Object[] {});
if (getterList != null) {
java.util.List setterList = java.util.Collections.synchronizedList(new java.util.ArrayList());
for (int j=0; j<getterList.size(); j++) {
Object vObj = getterList.get(j);
if (vObj instanceof XmlEnterpriseObject) {
XmlEnterpriseObject vXeo = (XmlEnterpriseObject)vObj;
setterList.add((XmlEnterpriseObject)vXeo.clone());
}
else {
// The only other type of objects that should exist in our lists (for now anyway)
// besides XmlEnterpriseObjectImpls are Strings, therefore, we'll just cast it
// here to a String to create another "copy" of the string contained in the list
// we're copying.
// New - 4/4/2002 to determine "growing" problem
String vStringObj = (String)vObj;
setterList.add(vStringObj);
// End New - 4/4/2002
}
}
setter.invoke(newXeo, new Object[] {setterList});
}
}
else {
// Either do a clone or just call the getter method.
Method cloneMethod = null;
try {
cloneMethod = c.getMethod("clone", new Class[] {});
newXeo.getEnterpriseFields().setIgnoreValidation(true);
if (isDate(c.getName())) {
org.openeai.PubliclyCloneable gObj = (org.openeai.PubliclyCloneable)getter.invoke(this, new Object[] {});
if (gObj != null) {
Object cObj = gObj.clone();
setter.invoke(newXeo, new Object[] {cObj});
}
}
else {
setter.invoke(newXeo, new Object[] {cloneMethod.invoke(getter.invoke(this, new Object[] {}), new Object[] {})});
}
logger.debug("Called the clone method for " + c.getName() + " on field: " + fieldName);
}
catch (Exception e) {
logger.debug("No clone method found for " + c.getName());
}
if (cloneMethod == null) {
if (getter.invoke(this, new Object[] {}) != null) {
newXeo.getEnterpriseFields().setIgnoreValidation(true);
setter.invoke(newXeo, new Object[] {getter.invoke(this, new Object[] {})});
}
else {
logger.debug("get" + fieldName + " method returned a null.");
}
}
}
}
catch (NoSuchMethodException exc) {
logger.debug("Couldn't find method: get" + fieldName + " on object " +
className + " ignoring..." );
}
catch (InvocationTargetException e) {
throw new EnterpriseObjectException("Error invoking method: get" + fieldName +
" on object " + className + " Exception: " + e.getMessage(), e);
}
catch (IllegalAccessException e1) {
throw new EnterpriseObjectException("Error invoking method: get" + fieldName +
" on object " + className + " Exception: " + e1.getMessage(), e1);
}
catch (Exception e2) {
throw new EnterpriseObjectException("Error cloning object " +
className + " Exception: " + e2.getMessage(), e2);
}
}
}
}
// before we return the deep copy, re-set the enterprise fields object back
// to its original setting so translation/validation will be turned back on or off...
newXeo.getEnterpriseFields().setIgnoreValidation(existingIgnoreValidation);
return newXeo;
}
// Move the following to EnterpriseObject...
/**
* Sets the EnterpriseFields object associated with this object.
* For information on the EnterpriseFields object, refer to the JavaDoc
* for the org.openeai.config package. This is called
* when the object is initialized. The EnterpriseFields object is built
* based on information found in the EnterpriseObjects document.
*<P>
* This information is specified in the MessageObjectConfig XML Element in the deployment
* documents and is passed to this object during initialization by the MessageObjectConfig
* Java object.
*<P>
* @param fields EnterpriseFields the EnterpriseFields object that will be used by this
* object to validate/format data passed to setter methods on this object.
* @see org.openeai.config.EnterpriseFields
*/
public final void setEnterpriseFields(EnterpriseFields fields) {
m_fields = fields;
}
/**
* Returns the EnterpriseFields object associated with this object.
* For information on the EnterpriseFields object, refer to the JavaDoc
* for the org.openeai.config package.
*<P>
* @return EnterpriseFields the EnterpriseFields object that will be used by this
* object to validate/format data passed to setter methods on this object.
* @see org.openeai.config.EnterpriseFields
*
*/
public final EnterpriseFields getEnterpriseFields() {
/*
return m_fields;
*/
if (m_fields != null) {
logger.debug("Using NORMAL enterprise fields object for " + getClass().getName().substring(getClass().getName().lastIndexOf('.') + 1));
if (m_fields.getEODocRoot() == null) {
// the EnterpriseFields object hasn't been initialized,
// it was deferred when the object was initialized.
// we need to:
// - parse the EO document
// - initialize the m_fields object
logger.debug("EnterpriseFields object is not initialized for the " +
getClass().getName().substring(getClass().getName().lastIndexOf('.') + 1) +
" object. Initializing it for it's first use.");
try {
XmlDocumentReader xmlReader = new XmlDocumentReader();
m_fields.init(xmlReader.initializeDocument(m_fields.getEnterpriseObjectsUri(),getValidation()));
}
catch (Exception e) {
logger.fatal(e.getMessage(), e);
}
return m_fields;
}
else {
return m_fields;
}
}
// return m_fields;
else {
// return static enterprise fields object?
// EVENTUALLY, this needs to go away.
logger.debug("Using STATIC enterprise fields object for " + getClass().getName().substring(getClass().getName().lastIndexOf('.') + 1));
try {
if (ENTERPRISE_FIELDS.getEODocRoot() == null) {
// the static EnterpriseFields object hasn't been initialized,
// it was deferred when the object was initialized.
// we need to:
// - parse the EO document
// - initialize the m_fields object
logger.debug("STATIC EnterpriseFields object is not initialized for the " +
getClass().getName().substring(getClass().getName().lastIndexOf('.') + 1) +
" object. Initializing it for it's first use.");
try {
XmlDocumentReader xmlReader = new XmlDocumentReader();
ENTERPRISE_FIELDS.init(xmlReader.initializeDocument(ENTERPRISE_FIELDS.getEnterpriseObjectsUri(),getValidation()));
}
catch (Exception e) {
logger.fatal(e.getMessage(), e);
}
}
m_fields = (EnterpriseFields)ENTERPRISE_FIELDS.clone();
}
catch (Exception e) {
logger.warn("Error cloning static enterprise fields object. Returning reference to static EnterpriseFields object. Exception: " + e.getMessage());
m_fields = ENTERPRISE_FIELDS;
}
return m_fields;
}
}
/**
* Uses the EnterpriseFields object associated to this object to convert the application
* value passed in to the enterprise value.
*<P>
* @return String the enterprise value that corresponds to the rules for the field
* @param fieldName String the name of the field for which the conversion is being performed
* @param appValue String the value being converted.
* @see org.openeai.config.EnterpriseFields
*/
protected String getEnterpriseValue(String fieldName, String appValue)
throws EnterpriseFieldException {
String className = getClass().getName();
String objectName = "";
if (isDate()) {
try {
Method getter = getClass().getMethod("getType", new Class[] {});
objectName = (String)getter.invoke(this, new Object[] {});
}
catch (Exception e) {
String errMessage = "Couldn't invoke method: getType() on object " +
getClass().getName() + " Exception: " + e.getMessage();
throw new EnterpriseFieldException(errMessage, e);
}
}
else {
objectName = className.substring(className.lastIndexOf('.') + 1);
}
EnterpriseFields fields = getEnterpriseFields();
if (fields == null || fields.getFieldsForObject(objectName).size() == 0) {
// this means this object doesn't have an EnterpriseFields object
// associated with it yet. This is okay because the only time it really
// matters is when an EnterpriseMessage is built. At that time,
// this object will have one associated with it because it will get
// set by the "message action" methods in JmsEnterpriseObject and
// in any build...Message methods...
logger.debug("No fields found for object: " + objectName);
return appValue;
}
String retValue = "";
retValue = fields.getEnterpriseValue(objectName, fieldName, appValue);
logger.debug("[XmlEnterpriseObjectImpl] Enterprise value for " +
objectName + "/" + fieldName + " is " + retValue);
return retValue;
}
/**
* Uses the EnterpriseFields object associated to this object to convert the enterprise
* value passed in to the application specific value based on rules found in the EnterpriseObjects XML
* document associated to the object for the application name passed in.
*<P>
* @return String the applicaiton specific value that corresponds to the rules for the field
* @param appName String the name of the applicatoin for which the conversion is being performed
* @param fieldName String the name of the field for which the conversion is being performed
* @param enterpriseValue String the value being converted.
* @see org.openeai.config.EnterpriseFields
*/
protected String getApplicationValue(String appName, String fieldName, String enterpriseValue)
throws EnterpriseFieldException {
if (enterpriseValue == null) { enterpriseValue = ""; }
String className = getClass().getName();
String objectName = "";
if (isDate()) {
try {
Method getter = getClass().getMethod("getType", new Class[] {});
objectName = (String)getter.invoke(this, new Object[] {});
}
catch (Exception e) {
String errMessage = "Couldn't invoke method: getType() on object " +
getClass().getName() + " Exception: " + e.getMessage();
throw new EnterpriseFieldException(errMessage, e);
}
}
else {
objectName = className.substring(className.lastIndexOf('.') + 1);
}
EnterpriseFields fields = getEnterpriseFields();
if (fields == null || fields.getFieldsForObject(objectName).size() == 0) {
// this means this object doesn't have an EnterpriseFields object
// associated with it yet. This is okay because the only time it really
// matters is when an EnterpriseMessage is built. At that time,
// this object will have one associated with it because it will get
// set by the "message action" methods in JmsEnterpriseObject and
// in any build...Message methods...
logger.debug("No fields found for object: " + objectName);
return enterpriseValue;
}
String retValue = "";
retValue = fields.getApplicationValue(objectName, appName, fieldName, enterpriseValue);
logger.debug("[XmlEnterpriseObjectImpl] Application value for " +
objectName + "/" + fieldName + " is " + retValue + " for application " + appName);
return retValue;
}
// Move the following to EnterpriseObject...
// EnterpriseLayoutManager methods
private void initializeLayoutManager(EnterpriseLayoutManager elm) {
try {
XmlDocumentReader xmlReader = new XmlDocumentReader();
elm.init(elm.getLayoutManagerName(),
xmlReader.initializeDocument(elm.getEnterpriseObjectsUri(),getValidation()));
}
catch (Exception e) {
logger.fatal(e.getMessage(), e);
}
}
/**
* Returns a HashMap containing all Input Layout managers associated to
* this object. These are all the input layout managers that may be used by
* this object. Since objects may support several different layout managers
* that are used to build themselves, this is necessary.
*<P>
* @return HashMap the list of Input Layout managers that may be used by this
* object.
*/
public final HashMap getInputLayoutManagers() {
return m_inputLayoutManagers;
}
public final void setInputLayoutManagers(HashMap iManagers) {
m_inputLayoutManagers = iManagers;
}
public final void addInputLayoutManager(String type, EnterpriseLayoutManager iLayout) {
m_inputLayoutManagers.put(type, iLayout);
}
public final void setInputLayoutManager(EnterpriseLayoutManager elm) {
m_inputLayoutManager = elm;
}
/**
* Returns this object's currently assigned Input Layout manager. If no
* current input layout manager exists, it returns the XmlLayout manager that all
* objects must have.
*<P>
* @return EnterpriseLayoutManager the currently assigned input layout manager.
* if no input layout manager has been assigned, it returns the XmlLayout manager.
*/
public final EnterpriseLayoutManager getInputLayoutManager() {
if (m_inputLayoutManager == null) {
// check to make sure the static XML Layout manager has been initialized
// if not, initialize it.
if (XML_LAYOUT_MANAGER.getLayoutRoot() == null) {
logger.debug("STATIC XML_LAYOUT_MANAGER object is not initialized for the " +
getClass().getName().substring(getClass().getName().lastIndexOf('.') + 1) +
" object. Initializing it for it's first use (input).");
initializeLayoutManager(XML_LAYOUT_MANAGER);
}
return XML_LAYOUT_MANAGER;
}
// check to make sure the Layout manager has been initialized
// if not, initialize it.
if (m_inputLayoutManager.getLayoutRoot() == null) {
logger.debug("Input LayoutManager object is not initialized for the " +
getClass().getName().substring(getClass().getName().lastIndexOf('.') + 1) +
" object. Initializing it for it's first use.");
initializeLayoutManager(m_inputLayoutManager);
}
return m_inputLayoutManager;
}
/**
* Returns an Input Layout manager for this object of a specified type. (e.g. - "xml", "extract").
* If no layout manager of the specified type exists, it returns null.
*<P>
* @param type String the type of input layout manager ("xml", "extract" etc.).
*<P>
* @return EnterpriseLayoutManager the input layout manager that is the type
* specified as a parm.
*/
public final EnterpriseLayoutManager getInputLayoutManager(String type) {
if (m_inputLayoutManagers.containsKey(type)) {
// check to make sure the Layout manager has been initialized
// if not, initialize it before returning.
EnterpriseLayoutManager elm = (EnterpriseLayoutManager)m_inputLayoutManagers.get(type);
if (elm.getLayoutRoot() == null) {
logger.debug("Input LayoutManager object of type '" + type + "' is not initialized for the " +
getClass().getName().substring(getClass().getName().lastIndexOf('.') + 1) +
" object. Initializing it for it's first use.");
initializeLayoutManager(elm);
}
return elm;
}
if (type.equalsIgnoreCase("xml")) {
logger.debug("No Input XmlLayout manager found for object, " + getClass().getName() + " using static XmlLayout manager.");
if (XML_LAYOUT_MANAGER != null) {
// check to make sure the Layout manager has been initialized
// if not, initialize it before returning.
if (XML_LAYOUT_MANAGER.getLayoutRoot() == null) {
logger.debug("STATIC Input LayoutManager object of type '" + type + "' is not initialized for the " +
getClass().getName().substring(getClass().getName().lastIndexOf('.') + 1) +
" object. Initializing it for it's first use.");
initializeLayoutManager(XML_LAYOUT_MANAGER);
}
return XML_LAYOUT_MANAGER;
}
}
logger.fatal("Couldn't find an Input Layout Manager of type " + type + " for " + getClass().getName());
return null;
}
/**
* Returns a HashMap containing all Output Layout managers associated to
* this object. These are all the output layout managers that may be used by
* this object. Since objects may support several different layout managers
* that are used to serialize themselves, this is necessary.
*<P>
* @return HashMap the list of Output Layout managers that may be used by this
* object.
*/
public final HashMap getOutputLayoutManagers() {
return m_outputLayoutManagers;
}
public final void setOutputLayoutManagers(HashMap oManagers) {
m_outputLayoutManagers = oManagers;
}
public final void addOutputLayoutManager(String type, EnterpriseLayoutManager oLayout) {
m_outputLayoutManagers.put(type, oLayout);
}
public final void setOutputLayoutManager(EnterpriseLayoutManager elm) {
m_outputLayoutManager = elm;
}
/**
* Returns this object's currently assigned Output Layout manager. If no
* current output layout manager exists, it returns the XmlLayout manager that all
* objects must have.
*<P>
* @return EnterpriseLayoutManager the currently assigned output layout manager.
* if no output layout manager has been assigned, it returns the XmlLayout manager.
*/
public final EnterpriseLayoutManager getOutputLayoutManager() {
if (m_outputLayoutManager == null) {
// check to make sure the Layout manager has been initialized
// if not, initialize it before returning.
if (XML_LAYOUT_MANAGER.getLayoutRoot() == null) {
logger.debug("STATIC OutputLayoutManager object is not initialized for the " +
getClass().getName().substring(getClass().getName().lastIndexOf('.') + 1) +
" object. Initializing it for it's first use.");
initializeLayoutManager(XML_LAYOUT_MANAGER);
}
return XML_LAYOUT_MANAGER;
}
// check to make sure the Layout manager has been initialized
// if not, initialize it before returning.
if (m_outputLayoutManager.getLayoutRoot() == null) {
logger.debug("Output LayoutManager object is not initialized for the " +
getClass().getName().substring(getClass().getName().lastIndexOf('.') + 1) +
" object. Initializing it for it's first use.");
initializeLayoutManager(m_outputLayoutManager);
}
return m_outputLayoutManager;
}
/**
* Returns an Output Layout manager for this object of a specified type. (e.g. - "xml", "extract").
* If no layout manager of the specified type exists, it returns null.
*<P>
* @param type String the type of output layout manager ("xml", "extract" etc.).
*<P>
* @return EnterpriseLayoutManager the output layout manager that is the type
* specified as a parm.
*/
public final EnterpriseLayoutManager getOutputLayoutManager(String type) {
if (m_outputLayoutManagers.containsKey(type)) {
// check to make sure the Layout manager has been initialized
// if not, initialize it before returning.
EnterpriseLayoutManager elm = (EnterpriseLayoutManager)m_outputLayoutManagers.get(type);
if (elm.getLayoutRoot() == null) {
logger.debug("Output LayoutManager object of type '" + type + "' is not initialized for the " +
getClass().getName().substring(getClass().getName().lastIndexOf('.') + 1) +
" object. Initializing it for it's first use.");
initializeLayoutManager(elm);
}
return elm;
}
if (type.equalsIgnoreCase("xml")) {
logger.debug("No Output XmlLayout manager found for object, " + getClass().getName() + " using static XmlLayout manager.");
if (XML_LAYOUT_MANAGER != null) {
// check to make sure the Layout manager has been initialized
// if not, initialize it before returning.
if (XML_LAYOUT_MANAGER.getLayoutRoot() == null) {
logger.debug("STATIC Output LayoutManager object of type '" + type + "' is not initialized for the " +
getClass().getName().substring(getClass().getName().lastIndexOf('.') + 1) +
" object. Initializing it for it's first use.");
initializeLayoutManager(XML_LAYOUT_MANAGER);
}
return XML_LAYOUT_MANAGER;
}
}
logger.fatal("Couldn't find an Output Layout Manager of type " + type + " for " + getClass().getName());
return null;
}
/**
* Using the currently assigned input layout manager, this method
* takes the input passed in and builds the object from that input.
* For example, if the data passed in is a BasicPerson XML Element, and
* the current inputLayoutManager is the XmlLayout manager, it will ask
* the layout manager to build the BasicPerson object from that element.
* The layout manager will then take the data in the element and put it into
* the appropriate instance variables (via object getter/setter methods). While
* it's doing that, the input data will be validated based on business rules
* found in the EnterpriseFields object (built from EnterpriseObjects.xml)
* <P>
* Additionally, if the data passed in is "application specific" data (like codes)
* this data will be converted to Enterprise Values based on Translation information
* also obtained from the EnterpriseObjects.xml document.
*<P>
* This method (along with buildOutputFromObject and the Layout Manager infrastructure)
* allows us to generalize the building our message objects so we don't have to
* put all of that logic in the objects themselves. We just implement new Layout Managers
* and associate those layouts to the objects. All objects have an Xml Layout Manager
* associated to them that is derived from the EnterpriseObjects.xml document.
*<P>
* @param input Object the data that will be used to build the object.
* e.g. - Element, String etc.
*<P>
* @throws EnterpriseLayoutException. If an error occurs building the object
* from the data passed in.
*/
public final void buildObjectFromInput(Object input) throws EnterpriseLayoutException {
if (getInputLayoutManager() == null) {
throw new EnterpriseLayoutException("INPUT LAYOUT MANAGER IS NULL for object " + getClass().getName());
}
getInputLayoutManager().buildObjectFromInput(input, this);
}
/**
* Using the currently assigned output layout manager, this method
* uses the current contents of the object and builds an output object as
* implemented by the layout manager.
* For example, if the object is a BasicPerson, and
* the current outputLayoutManager is the XmlLayout manager, it will ask
* the layout manager to build the BasicPerson XML Element from BasicPerson object.
* The layout manager will then retrieve the data from the BasicPerson object
* via object getter methods and build an Element from the data. While
* it's doing that, the object will be validated based on business rules
* found in the EnterpriseFields object (built from EnterpriseObjects.xml)
*<P>
* This method (along with buildInputFromObject and the Layout Manager infrastructure)
* allows us to generalize the serialization our message objects so we don't have to
* put all of that logic in the objects themselves. We just implement new Layout Managers
* and associate those layouts to the objects. All objects have an Xml Layout Manager
* associated to them that is derived from the EnterpriseObjects.xml document.
*<P>
* @return Object the data that will be built from the object. The calling applicatons
* will cast this object to the appropriate thing. e.g. - Element, String etc.
*<P>
* @throws EnterpriseLayoutException. If an error occurs building the output
* from the object.
*/
public final Object buildOutputFromObject() throws EnterpriseLayoutException {
if (getOutputLayoutManager() == null) {
throw new EnterpriseLayoutException("OUTPUT LAYOUT MANAGER IS NULL for object " + getClass().getName());
}
return getOutputLayoutManager().buildOutputFromObject(this);
}
/**
* Using the currently assigned output layout manager, this method
* uses the current contents of the object and builds an output object as
* implemented by the layout manager for the specified application name.
* For example, if the object is a BasicPerson, and
* the current outputLayoutManager is the ExtractLayout manager, it will ask
* the layout manager to build an extract line with application specific values
* using the contents of the BasicPerson object. This allows us to "reverse translate"
* our enterprise values to application specific values (like codes etc.)
* The information related to these translations can be found in the EnterpriseObjects.xml document.
*<P>
* This method (along with buildInputFromObject and the Layout Manager infrastructure)
* allows us to generalize the serialization our message objects so we don't have to
* put all of that logic in the objects themselves. We just implement new Layout Managers
* and associate those layouts to the objects. All objects have an Xml Layout Manager
* associated to them that is derived from the EnterpriseObjects.xml document.
*<P>
* @return Object the data that will be built from the object. The calling applicatons
* will cast this object to the appropriate thing. e.g. - Element, String etc.
*<P>
* @throws EnterpriseLayoutException. If an error occurs building the output
* from the object.
*/
public final Object buildOutputFromObject(String appName) throws EnterpriseLayoutException {
if (getOutputLayoutManager() == null) {
throw new EnterpriseLayoutException("OUTPUT LAYOUT MANAGER IS NULL for object " + getClass().getName());
}
return getOutputLayoutManager().buildOutputFromObject(this, appName);
}
/**
* This method allows application developers to build an object from
* a XML String representation of an object that was previously converted
* to an XML String via the toXmlString() method. This method basically
* uses the "xml" inputLayoutManager to build the object from an Element that
* gets created out of the String passed in. This is so developers don't have to
* convert the String to an element themselves (as a convenience). They just
* have to pass the String and this method takes care of converting it to an Element
* and asking the layout manager to build the object from that element.
*<P>
* @param theString String the XML String that will be used to build the object.
*<P>
* @throws XmlEnterpriseObjectException. If an error occurs building the object
* from the data passed in.
*/
public final void buildObjectFromXmlString(String theString) throws XmlEnterpriseObjectException {
if (theString == null || theString.length() == 0) {
logger.warn("Can't build the object from the blank or null string passed in.");
return;
}
try {
XmlDocumentReader xmlReader = new XmlDocumentReader();
Document objectDoc = xmlReader.initializeDocument(new ByteArrayInputStream(theString.getBytes()), false);
Element eObject = objectDoc.getRootElement();
EnterpriseLayoutManager saveInputLManager = null;
saveInputLManager = getInputLayoutManager();
EnterpriseLayoutManager xmlInputLayoutManager = getInputLayoutManager("xml");
if (xmlInputLayoutManager == null) {
throw new XmlEnterpriseObjectException("Could not find an XML Input Layout Manager for object " + getClass().getName());
}
setInputLayoutManager(xmlInputLayoutManager);
buildObjectFromInput(eObject);
setInputLayoutManager(saveInputLManager);
}
catch (Exception e) {
String errMessage = "Unknown exception occurred building object " +
getClass().getName() + " from an XML String. String is: \n" + theString + "\n\n" +
"Exception: " + e.getMessage();
throw new XmlEnterpriseObjectException(errMessage, e);
}
}
// document methods
public final Document getCreateDoc() {
if (m_createDoc != null) {
return(Document)m_createDoc.clone();
}
else {
if (getCreateDocUri() != null) {
try {
XmlDocumentReader xmlReader = new XmlDocumentReader();
logger.debug("Primed 'Create' document initialization was deferred. Initializing for first use.");
setCreateDoc(xmlReader.initializeDocument(getCreateDocUri(), getValidation()));
return(Document)m_createDoc.clone();
}
catch (Exception e) {
logger.fatal(e.getMessage(), e);
}
}
return null;
}
}
/**
* Returns the primed create XML document URI. This URI corresponds to the
* PrimedXmlDocument elements listed in the MessageObjectConfig portion of the deployment
* descriptor. The method is called when the object is initialized by AppConfig to
* create the Create-Request primed document using the URI specified in the deployment
* descriptor.
* <P>
* @return String the Create-Request primed document URI as listed in the MessageObjectConfig
* Element associate to this object.
**/
public final String getCreateDocUri() {
return m_createDocUri;
}
/**
* Sets the primed create XML document URI. This URI corresponds to the
* PrimedXmlDocument elements listed in the MessageObjectConfig portion of the deployment
* descriptor. The method is called when the object is initialized by AppConfig to
* create the Create-Request primed document using the URI specified in the deployment
* descriptor.
* <P>
* @param uri String the Create-Request primed document URI as listed in the MessageObjectConfig
* Element associate to this object.
**/
public final void setCreateDocUri(String uri) {
m_createDocUri = uri;
}
public Document getProvideDoc() {
if (m_provideDoc != null) {
return(Document)m_provideDoc.clone();
}
else {
if (getProvideDocUri() != null) {
try {
XmlDocumentReader xmlReader = new XmlDocumentReader();
logger.debug("Primed 'Provide' document initialization was deferred. Initializing for first use.");
setProvideDoc(xmlReader.initializeDocument(getProvideDocUri(), getValidation()));
return(Document)m_provideDoc.clone();
}
catch (Exception e) {
logger.fatal(e.getMessage(), e);
}
}
return null;
}
}
/**
* Returns the primed Provide-Reply XML document URI. This URI corresponds to the
* PrimedXmlDocument elements listed in the MessageObjectConfig portion of the deployment
* descriptor. The method is called when the object is initialized by AppConfig to
* create the Provide-Reply primed document using the URI specified in the deployment
* descriptor.
* <P>
* @return String the Provide-Reply primed document URI as listed in the MessageObjectConfig
* Element associate to this object.
**/
public final String getProvideDocUri() {
return m_provideDocUri;
}
/**
* Sets the primed Provide-Reply XML document URI. This URI corresponds to the
* PrimedXmlDocument elements listed in the MessageObjectConfig portion of the deployment
* descriptor. The method is called when the object is initialized by AppConfig to
* create the Provide-Reply primed document using the URI specified in the deployment
* descriptor.
* <P>
* @param uri String the Provide-Reply primed document URI as listed in the MessageObjectConfig
* Element associate to this object.
**/
public final void setProvideDocUri(String uri) {
m_provideDocUri = uri;
}
public Document getResponseDoc() {
if (m_responseDoc != null) {
return(Document)m_responseDoc.clone();
}
else {
if (getResponseDocUri() != null) {
try {
XmlDocumentReader xmlReader = new XmlDocumentReader();
logger.debug("Primed 'Response' document initialization was deferred. Initializing for first use.");
setResponseDoc(xmlReader.initializeDocument(getResponseDocUri(), getValidation()));
return(Document)m_responseDoc.clone();
}
catch (Exception e) {
logger.fatal(e.getMessage(), e);
}
}
return null;
}
}
/**
* Returns the primed Response-Reply XML document URI. This URI corresponds to the
* PrimedXmlDocument elements listed in the MessageObjectConfig portion of the deployment
* descriptor. The method is called when the object is initialized by AppConfig to
* create the Response-Reply primed document using the URI specified in the deployment
* descriptor.
* <P>
* @return String the Response-Reply primed document URI as listed in the MessageObjectConfig
* Element associate to this object.
**/
public final String getResponseDocUri() {
return m_responseDocUri;
}
/**
* Sets the primed Response-Reply XML document URI. This URI corresponds to the
* PrimedXmlDocument elements listed in the MessageObjectConfig portion of the deployment
* descriptor. The method is called when the object is initialized by AppConfig to
* create the Response-Reply primed document using the URI specified in the deployment
* descriptor.
* <P>
* @param uri String the Response-Reply primed document URI as listed in the MessageObjectConfig
* Element associate to this object.
**/
public final void setResponseDocUri(String uri) {
m_responseDocUri = uri;
}
public final Document getDeleteDoc() {
if (m_deleteDoc != null) {
return(Document)m_deleteDoc.clone();
}
else {
if (getDeleteDocUri() != null) {
try {
XmlDocumentReader xmlReader = new XmlDocumentReader();
logger.debug("Primed 'Delete' document initialization was deferred. Initializing for first use.");
setDeleteDoc(xmlReader.initializeDocument(getDeleteDocUri(), getValidation()));
return(Document)m_deleteDoc.clone();
}
catch (Exception e) {
logger.fatal(e.getMessage(), e);
}
}
return null;
}
}
/**
* Returns the primed Delete-Request XML document URI. This URI corresponds to the
* PrimedXmlDocument elements listed in the MessageObjectConfig portion of the deployment
* descriptor. The method is called when the object is initialized by AppConfig to
* create the Delete-Request primed document using the URI specified in the deployment
* descriptor.
* <P>
* @return String the Response-Reply primed document URI as listed in the MessageObjectConfig
* Element associate to this object.
**/
public final String getDeleteDocUri() {
return m_deleteDocUri;
}
/**
* Sets the primed Delete-Request XML document URI. This URI corresponds to the
* PrimedXmlDocument elements listed in the MessageObjectConfig portion of the deployment
* descriptor. The method is called when the object is initialized by AppConfig to
* create the Delete-Request primed document using the URI specified in the deployment
* descriptor.
* <P>
* @param uri String the Response-Reply primed document URI as listed in the MessageObjectConfig
* Element associate to this object.
**/
public final void setDeleteDocUri(String uri) {
m_deleteDocUri = uri;
}
public final Document getUpdateDoc() {
if (m_updateDoc != null) {
return(Document)m_updateDoc.clone();
}
else {
if (getUpdateDocUri() != null) {
try {
XmlDocumentReader xmlReader = new XmlDocumentReader();
logger.debug("Primed 'Update' document initialization was deferred. Initializing for first use.");
setUpdateDoc(xmlReader.initializeDocument(getUpdateDocUri(), getValidation()));
return(Document)m_updateDoc.clone();
}
catch (Exception e) {
logger.fatal(e.getMessage(), e);
}
}
return null;
}
}
/**
* Returns the primed Update-Request XML document URI. This URI corresponds to the
* PrimedXmlDocument elements listed in the MessageObjectConfig portion of the deployment
* descriptor. The method is called when the object is initialized by AppConfig to
* create the Update-Request primed document using the URI specified in the deployment
* descriptor.
* <P>
* @return String the Response-Reply primed document URI as listed in the MessageObjectConfig
* Element associate to this object.
**/
public final String getUpdateDocUri() {
return m_updateDocUri;
}
/**
* Sets the primed Update-Request XML document URI. This URI corresponds to the
* PrimedXmlDocument elements listed in the MessageObjectConfig portion of the deployment
* descriptor. The method is called when the object is initialized by AppConfig to
* create the Update-Request primed document using the URI specified in the deployment
* descriptor.
* <P>
* @param uri String the Response-Reply primed document URI as listed in the MessageObjectConfig
* Element associate to this object.
**/
public final void setUpdateDocUri(String uri) {
m_updateDocUri = uri;
}
public final Document getGenerateDoc() {
if (m_generateDoc != null) {
return(Document)m_generateDoc.clone();
}
else {
if (getGenerateDocUri() != null) {
try {
XmlDocumentReader xmlReader = new XmlDocumentReader();
logger.debug("Primed 'Generate' document initialization was deferred. Initializing for first use.");
setGenerateDoc(xmlReader.initializeDocument(getGenerateDocUri(), getValidation()));
return(Document)m_generateDoc.clone();
}
catch (Exception e) {
logger.fatal(e.getMessage(), e);
}
}
return null;
}
}
/**
* Returns the primed Generate-Request XML document URI. This URI corresponds to the
* PrimedXmlDocument elements listed in the MessageObjectConfig portion of the deployment
* descriptor. The method is called when the object is initialized by AppConfig to
* create the Generate-Request primed document using the URI specified in the deployment
* descriptor.
* <P>
* @return String the Generate-Reply primed document URI as listed in the MessageObjectConfig
* Element associate to this object.
**/
public final String getGenerateDocUri() {
return m_generateDocUri;
}
/**
* Sets the primed Generate-Request XML document URI. This URI corresponds to the
* PrimedXmlDocument elements listed in the MessageObjectConfig portion of the deployment
* descriptor. The method is called when the object is initialized by AppConfig to
* create the Generate-Request primed document using the URI specified in the deployment
* descriptor.
* <P>
* @param uri String the Generate-Reply primed document URI as listed in the MessageObjectConfig
* Element associate to this object.
**/
public final void setGenerateDocUri(String uri) {
m_generateDocUri = uri;
}
public final Document getCreateSyncDoc() {
if (m_createSyncDoc != null) {
return(Document)m_createSyncDoc.clone();
}
else {
if (getCreateSyncDocUri() != null) {
try {
XmlDocumentReader xmlReader = new XmlDocumentReader();
logger.debug("Primed 'CreateSync' document initialization was deferred. Initializing for first use.");
setCreateSyncDoc(xmlReader.initializeDocument(getCreateSyncDocUri(), getValidation()));
return(Document)m_createSyncDoc.clone();
}
catch (Exception e) {
logger.fatal(e.getMessage(), e);
}
}
return null;
}
}
/**
* Returns the primed Create-Sync XML document URI. This URI corresponds to the
* PrimedXmlDocument elements listed in the MessageObjectConfig portion of the deployment
* descriptor. The method is called when the object is initialized by AppConfig to
* create the Create-Sync primed document using the URI specified in the deployment
* descriptor.
* <P>
* @return String the Create-Sync primed document URI as listed in the MessageObjectConfig
* Element associate to this object.
**/
public final String getCreateSyncDocUri() {
return m_createSyncDocUri;
}
/**
* Sets the primed Create-Sync XML document URI. This URI corresponds to the
* PrimedXmlDocument elements listed in the MessageObjectConfig portion of the deployment
* descriptor. The method is called when the object is initialized by AppConfig to
* create the Create-Sync primed document using the URI specified in the deployment
* descriptor.
* <P>
* @param uri String the Create-Sync primed document URI as listed in the MessageObjectConfig
* Element associate to this object.
**/
public final void setCreateSyncDocUri(String uri) {
m_createSyncDocUri = uri;
}
public final Document getDeleteSyncDoc() {
if (m_deleteSyncDoc != null) {
return(Document)m_deleteSyncDoc.clone();
}
else {
if (getDeleteSyncDocUri() != null) {
try {
XmlDocumentReader xmlReader = new XmlDocumentReader();
logger.debug("Primed 'DeleteSync' document initialization was deferred. Initializing for first use.");
setDeleteSyncDoc(xmlReader.initializeDocument(getDeleteSyncDocUri(), getValidation()));
return(Document)m_deleteSyncDoc.clone();
}
catch (Exception e) {
logger.fatal(e.getMessage(), e);
}
}
return null;
}
}
/**
* Returns the primed Delete-Sync XML document URI. This URI corresponds to the
* PrimedXmlDocument elements listed in the MessageObjectConfig portion of the deployment
* descriptor. The method is called when the object is initialized by AppConfig to
* create the Delete-Sync primed document using the URI specified in the deployment
* descriptor.
* <P>
* @return String the Delete-Sync primed document URI as listed in the MessageObjectConfig
* Element associate to this object.
**/
public final String getDeleteSyncDocUri() {
return m_deleteSyncDocUri;
}
/**
* Sets the primed Delete-Sync XML document URI. This URI corresponds to the
* PrimedXmlDocument elements listed in the MessageObjectConfig portion of the deployment
* descriptor. The method is called when the object is initialized by AppConfig to
* create the Delete-Sync primed document using the URI specified in the deployment
* descriptor.
* <P>
* @return String the Delete-Sync primed document URI as listed in the MessageObjectConfig
* Element associate to this object.
**/
public final void setDeleteSyncDocUri(String uri) {
m_deleteSyncDocUri = uri;
}
public final Document getUpdateSyncDoc() {
if (m_updateSyncDoc != null) {
return(Document)m_updateSyncDoc.clone();
}
else {
if (getUpdateSyncDocUri() != null) {
try {
XmlDocumentReader xmlReader = new XmlDocumentReader();
logger.debug("Primed 'UpdateSync' document initialization was deferred. Initializing for first use.");
setUpdateSyncDoc(xmlReader.initializeDocument(getUpdateSyncDocUri(), getValidation()));
return(Document)m_updateSyncDoc.clone();
}
catch (Exception e) {
logger.fatal(e.getMessage(), e);
}
}
return null;
}
}
/**
* Returns the primed Update-Sync XML document URI. This URI corresponds to the
* PrimedXmlDocument elements listed in the MessageObjectConfig portion of the deployment
* descriptor. The method is called when the object is initialized by AppConfig to
* create the Update-Sync primed document using the URI specified in the deployment
* descriptor.
* <P>
* @return String the Update-Sync primed document URI as listed in the MessageObjectConfig
* Element associate to this object.
**/
public final String getUpdateSyncDocUri() {
return m_updateSyncDocUri;
}
/**
* Sets the primed Update-Sync XML document URI. This URI corresponds to the
* PrimedXmlDocument elements listed in the MessageObjectConfig portion of the deployment
* descriptor. The method is called when the object is initialized by AppConfig to
* create the Update-Sync primed document using the URI specified in the deployment
* descriptor.
* <P>
* @param uri String the Update-Sync primed document URI as listed in the MessageObjectConfig
* Element associate to this object.
**/
public final void setUpdateSyncDocUri(String uri) {
m_updateSyncDocUri = uri;
}
public final Document getGenerateSyncDoc() {
if (m_generateSyncDoc != null) {
return(Document)m_generateSyncDoc.clone();
}
else {
if (getGenerateSyncDocUri() != null) {
try {
XmlDocumentReader xmlReader = new XmlDocumentReader();
logger.debug("Primed 'GenerateSync' document initialization was deferred. Initializing for first use.");
setGenerateSyncDoc(xmlReader.initializeDocument(getGenerateSyncDocUri(), getValidation()));
return(Document)m_generateSyncDoc.clone();
}
catch (Exception e) {
logger.fatal(e.getMessage(), e);
}
}
return null;
}
}
/**
* Returns the primed Generate-Sync XML document URI. This URI corresponds to the
* PrimedXmlDocument elements listed in the MessageObjectConfig portion of the deployment
* descriptor. The method is called when the object is initialized by AppConfig to
* create the Generate-Sync primed document using the URI specified in the deployment
* descriptor.
* <P>
* @return String the Generate-Sync primed document URI as listed in the MessageObjectConfig
* Element associate to this object.
**/
public final String getGenerateSyncDocUri() {
return m_generateSyncDocUri;
}
/**
* Sets the primed Generate-Sync XML document URI. This URI corresponds to the
* PrimedXmlDocument elements listed in the MessageObjectConfig portion of the deployment
* descriptor. The method is called when the object is initialized by AppConfig to
* create the Generate-Sync primed document using the URI specified in the deployment
* descriptor.
* <P>
* @param uri String the Generate-Sync primed document URI as listed in the MessageObjectConfig
* Element associate to this object.
**/
public final void setGenerateSyncDocUri(String uri) {
m_generateSyncDocUri = uri;
}
public final Document getQueryDoc() {
if (m_queryDoc != null) {
return(Document)m_queryDoc.clone();
}
else {
if (getQueryDocUri() != null) {
try {
XmlDocumentReader xmlReader = new XmlDocumentReader();
setQueryDoc(xmlReader.initializeDocument(getQueryDocUri(), getValidation()));
return(Document)m_queryDoc.clone();
}
catch (Exception e) {
logger.fatal(e.getMessage(), e);
}
}
return null;
}
}
/**
* Returns the primed Query-Request XML document URI. This URI corresponds to the
* PrimedXmlDocument elements listed in the MessageObjectConfig portion of the deployment
* descriptor. The method is called when the object is initialized by AppConfig to
* create the Query-Request primed document using the URI specified in the deployment
* descriptor.
* <P>
* @return String the Query-Request primed document URI as listed in the MessageObjectConfig
* Element associate to this object.
**/
public final String getQueryDocUri() {
return m_queryDocUri;
}
/**
* Sets the primed Query-Request XML document URI. This URI corresponds to the
* PrimedXmlDocument elements listed in the MessageObjectConfig portion of the deployment
* descriptor. The method is called when the object is initialized by AppConfig to
* create the Query-Request primed document using the URI specified in the deployment
* descriptor.
* <P>
* @param uri String the Query-Request primed document URI as listed in the MessageObjectConfig
* Element associate to this object.
**/
public final void setQueryDocUri(String uri) {
m_queryDocUri = uri;
}
protected String getRootElementName(Element e) {
while (e.isRootElement() == false) {
logger.debug("Element name: " + e.getName());
e = (Element) e.getParent();
logger.debug("Element name: " + e.getName());
}
return e.getName();
}
/**
* This method looks at the document and returns the appropriate ControlArea.
* Since there can be three different control areas based on the message
* (ControlAreaRequest, ControlAreaReply and ControlAreaSync) we need to have
* some intelligence built in when retrieving the element from the document.
* Clients should never need to call this method directly.
*
* @param root org.jdom.Element the root element of the document
*
* @return Element the ControlArea element (may be ControlAreaRequest,
* ControlAreaReply or ControlAreaSync depending on the doc)
*/
protected Element getControlArea(Element root) {
java.util.List cList = root.getChildren();
Element retElem = null;
for (int i=0; i<cList.size(); i++) {
Element current = (Element)cList.get(i);
if (current.getName().indexOf("ControlArea") != -1) {
retElem = current;
}
}
return retElem;
}
/**
* Sets a boolean flag indicating whether or not XML validation will be used when messages
* are produced/published by this object. If XML validation is turned on, the resulting
* XML document that gets generated from the contents of this object will be validated
* from an XML perspective prior to producing/publishing any messages.
*<P>
* This information is specified in the MessageObjectConfig XML Element in the deployment
* documents and is passed to this object during initialization by the MessageObjectConfig
* Java object.
*<P>
* @param validate boolean true=XML validation will be on, false=XML validation will be off.
*/
public final void setValidation(boolean validate) {
m_validate = validate;
}
/**
* Returns a boolean flag indicating whether or not XML validation will be used when messages
* are produced/published by this object. If XML validation is turned on, the resulting
* XML document that gets generated from the contents of this object will be validated
* from an XML perspective prior to producing/publishing any messages.
*<P>
* This information is specified in the MessageObjectConfig XML Element in the deployment
* documents and is passed to this object during initialization by the MessageObjectConfig
* Java object.
*<P>
* @return boolean true=XML validation will be on, false=XML validation will be off.
*/
public final boolean getValidation() {
return m_validate;
}
public final void setCreateDoc(Document doc) {
m_createDoc = doc;
}
public final void setDeleteDoc(Document doc) {
m_deleteDoc = doc;
}
/**
* Sets the "primed" update document associated with this object. This is called
* during object initialization and is set based on information in the MessagingEnterprise
* document. Clients should never need to call this method directly.
*<P>
* This information is specified in the MessageObjectConfig XML Element in the deployment
* documents and is passed to this object during initialization by the MessageObjectConfig
* Java object.
*<P>
* @param doc org.jdom.Document the "primed" update Document
*
*/
public final void setUpdateDoc(Document doc) {
m_updateDoc = doc;
}
/**
* Sets the "primed" generate document associated with this object. This is called
* during object initialization and is set based on information in the MessagingEnterprise
* document. Clients should never need to call this method directly.
*<P>
* This information is specified in the MessageObjectConfig XML Element in the deployment
* documents and is passed to this object during initialization by the MessageObjectConfig
* Java object.
*<P>
* @param doc org.jdom.Document the "primed" generate Document
*
*/
public final void setGenerateDoc(Document doc) {
m_generateDoc = doc;
}
public final void setCreateSyncDoc(Document doc) {
m_createSyncDoc = doc;
}
public final void setDeleteSyncDoc(Document doc) {
m_deleteSyncDoc = doc;
}
public final void setUpdateSyncDoc(Document doc) {
m_updateSyncDoc = doc;
}
public void setResponseDoc(Document doc) {
m_responseDoc = doc;
}
public void setProvideDoc(Document doc) {
m_provideDoc = doc;
}
public final void setGenerateSyncDoc(Document doc) {
m_generateSyncDoc = doc;
}
public final void setQueryDoc(Document doc) {
m_queryDoc = doc;
}
public final void dumpData() {
try {
EnterpriseLayoutManager elm = getOutputLayoutManager("xml");
if (elm != null) {
Object obj = elm.buildOutputFromObject(this);
if (obj instanceof Element) {
XMLOutputter fmt = new XMLOutputter(Format.getPrettyFormat());
logger.info(fmt.outputString((Element)obj));
}
}
}
catch (Exception exc) {
logger.fatal("dumpData: Exception caught: " + exc.getMessage());
//exc.printStackTrace();
}
}
/**
* A convenience method that can be used to compare two Xml aware objects (XmlEnterpriseObjectImpl).
* This method converts the current object and the object passed in to an XML String
* via the toXmlString() method. Then it does a String comparison on those two strings.
* Note, this method IS case sensitive.
*<P>
* @return boolean
*<P>
* @throws XmlEnterpriseObjectException. If an error occurs serializing the
* object to a String. This is usually due to invalid data (formats etc.) determined
* from the object's current rules as specified in EnterpriseFields.
*/
public final boolean equals(XmlEnterpriseObject xeo) throws XmlEnterpriseObjectException {
if (isEmpty() && xeo.isEmpty() == false) {
return false;
}
else if (isEmpty() == false && xeo.isEmpty()) {
return false;
}
else if (isEmpty() && xeo.isEmpty()) {
return true;
}
if (this.toXmlString().equals(xeo.toXmlString())) {
return true;
}
else {
return false;
}
}
/**
* Returns a comma separated String containing all the data currently stored in this object.
*<P>
* Format for returned data:
* <P>
* FieldName1=some value, FieldName2=field2 data etc.
* <P>
* @return String
*/
public String toString() {
StringBuffer sBuf = new StringBuffer();
String className = this.getClass().getName();
Method[] methods = getClass().getDeclaredMethods();
for (int i=0; i<methods.length; i++) {
Method getter = methods[i];
String methodName = getter.getName();
Class c = getter.getReturnType();
Class[] parms = getter.getParameterTypes();
if (methodName.indexOf("get") == 0 && parms.length == 0) {
String fieldName = methodName.substring(methodName.indexOf("get")+3);
try {
if (c == String.class) {
// just call the getter method.
String sObj = (String)getter.invoke(this, new Object[] {});
if (sObj != null) {
sBuf.append(fieldName + "=" + sObj + ", ");
}
}
else {
Object xObj = getter.invoke(this, new Object[] {});
if (xObj != null) {
sBuf.append(fieldName + "=" + xObj.toString() + ", ");
}
}
}
catch (InvocationTargetException e) {
logger.fatal("Error invoking method: get" + fieldName +
" on object " + className + " Exception: " + e.getMessage());
logger.fatal(e.getMessage(), e);
}
catch (IllegalAccessException e1) {
logger.fatal("Error invoking method: get" + fieldName +
" on object " + className + " Exception: " + e1.getMessage());
logger.fatal(e1.getMessage(), e1);
}
}
}
// need to check the length of sBuf here before attempting to trim it.
if (sBuf.length() > 2) {
sBuf.delete(sBuf.length() - 2, sBuf.length());
}
return sBuf.toString();
}
/**
* A convenience method that can be used simply by application developers
* to retreive the contents of the object as an XML String. Basically,
* this is a fully valid XML Element just represented as a String. This
* data can then be used to persist the entire object, and/or build an
* Element from that String which can be used to build the object from an
* input (an XML Element).
*<P>
* @return String the XML representation of the object as a String.
*<P>
* @throws XmlEnterpriseObjectException. If an error occurs serializing the
* object to a String. This is usually due to invalid data (formats etc.) determined
* from the object's current rules as specified in EnterpriseFields.
*/
public final String toXmlString() throws XmlEnterpriseObjectException {
/*
if (isEmpty()) {
return null;
}
*/
try {
EnterpriseLayoutManager saveOutElm = getOutputLayoutManager();
EnterpriseLayoutManager outElm = getOutputLayoutManager("xml");
EnterpriseLayoutManager inElm = getInputLayoutManager("xml");
if (outElm == null) {
throw new XmlEnterpriseObjectException("Couldn't find an XML " +
"Output Layout Manager for " + getClass().getName());
}
if (inElm == null) {
throw new XmlEnterpriseObjectException("Couldn't find an XML " +
"Input Layout Manager for " + getClass().getName());
}
setOutputLayoutManager(outElm);
Element eOutput = (Element)buildOutputFromObject();
setOutputLayoutManager(saveOutElm);
XmlEnterpriseObject xeo = null;
String className = this.getClass().getName();
java.lang.Class obj = java.lang.Class.forName(className);
if (isDate()) {
try {
Method getter = getClass().getMethod("getType", new Class[] {});
String dateType = (String)getter.invoke(this, new Object[] {});
Class[] parms = {String.class};
Constructor c = obj.getConstructor(parms);
Object[] o = {dateType};
xeo = (XmlEnterpriseObject)c.newInstance(o);
}
catch (Exception e) {
String errMessage = "Couldn't invoke method: getType() on object " +
getClass().getName() + " Exception: " + e.getMessage();
throw new EnterpriseFieldException(errMessage, e);
}
}
else {
// default
xeo = (XmlEnterpriseObject)obj.newInstance();
}
xeo.setEnterpriseFields((EnterpriseFields)getEnterpriseFields().clone());
xeo.setOutputLayoutManager(outElm);
xeo.setInputLayoutManager(inElm);
logger.debug("re-building object from input...");
xeo.buildObjectFromInput(eOutput);
XMLOutputter xmlOut = new XMLOutputter();
String objAsXmlString = xmlOut.outputString((Element)xeo.buildOutputFromObject());
logger.debug("[toXmlString] " + className + " as an XML String: \n" + objAsXmlString);
// To test to make sure it doesn't have any goofy characters in it...
// If it does, an exception will be thrown here.
XmlDocumentReader xmlReader = new XmlDocumentReader();
Document objectDoc = xmlReader.initializeDocument(new ByteArrayInputStream(objAsXmlString.getBytes()), false);
return objAsXmlString;
}
catch (Exception exc) {
logger.fatal(exc.getMessage(), exc);
String errMessage = "Error in toXmlString: " + exc.getMessage() + " on object " +
getClass().getName() + " Exception: " + exc.getMessage();
throw new XmlEnterpriseObjectException(errMessage, exc);
}
}
/**
* goes through all the key fields on the xeo passed in and creates a string containing all the
* values from those key fields. This string is used by other methods to determine if there are
* matching new/baseline xeos with the same key information. That allows us to determine
* if a transaction should be an insert, update, delete or ignored.
* <P>
* @return String the combined key value
* <P>
* @throws XmlEnterpriseObjectException
**/
public final String getCombinedKeyValue()
throws XmlEnterpriseObjectException {
// goes through all the key fields on the xeo passed in and creates a string containing all the
// values from those key fields. This string is used by other methods to determine if there are
// matching new/baseline xeos with the same key information. That allows us to determine
// if a transaction should be an insert, update, delete or ignored.
String className = getClass().getName();
String objectName = className.substring(className.lastIndexOf('.') + 1); // Our based element in the XML passed in
if (isDate()) {
try {
Method getter = getClass().getMethod("getType", new Class[] {});
objectName = (String)getter.invoke(this, new Object[] {});
}
catch (Exception e) {
String errMessage = "Couldn't invoke method: getType() on object " +
getClass().getName() + " Exception: " + e.getMessage();
throw new XmlEnterpriseObjectException(errMessage, e);
}
}
java.util.List keys = getEnterpriseFields().getKeyNamesForField( objectName );
StringBuffer combinedKeyValue = new StringBuffer();
for (int i=0; i<keys.size(); i++) {
String keyName = (String)keys.get(i);
Object obj = getValueFromObject(keyName);
String keyValue = "";
if (obj instanceof XmlEnterpriseObject) {
XmlEnterpriseObject x = (XmlEnterpriseObject)obj;
String xClassName = x.getClass().getName();
String xObjectName = xClassName.substring(xClassName.lastIndexOf('.') + 1);
java.util.List xKeys = x.getEnterpriseFields().getKeyNamesForField( xObjectName );
if (xKeys != null && xKeys.size() > 0) {
keyValue = x.getCombinedKeyValue();
}
else {
keyValue = x.toString();
}
}
else if (isRepeating(keyName)) {
// it's a list, we need to go through each object and get the combined
// key value from each item in the list.
// int numObjects = getLength(keyName);
// StringBuffer repeatingKeyValue = new StringBuffer();
// for (int j=0; j<numObjects; j++) {
// Integer iParm = new Integer(j);
// Object repeatingObj = null;
// repeatingObj = getValueFromObject(keyName, new Object[] {iParm}, new Class[] {Integer.TYPE});
// if (repeatingObj instanceof XmlEnterpriseObject) {
// XmlEnterpriseObject x = (XmlEnterpriseObject)repeatingObj;
// String xClassName = x.getClass().getName();
// String xObjectName = xClassName.substring(xClassName.lastIndexOf('.') + 1);
// java.util.List xKeys = x.getEnterpriseFields().getKeyNamesForField( xObjectName );
// if (xKeys != null && xKeys.size() > 0) {
// repeatingKeyValue.append(x.getCombinedKeyValue());
// }
// else {
// repeatingKeyValue.append(x.toString());
// }
// }
// else {
// repeatingKeyValue.append((String)repeatingObj);
// }
// }
// keyValue = repeatingKeyValue.toString();
// actually, if it's a repeating field and it's required, it CAN'T be part of the key
// so, we'll just ignore it....
}
else {
keyValue = (String)obj;
}
if (keyValue != null && keyValue.length() > 0) {
combinedKeyValue.append(keyValue);
}
}
return combinedKeyValue.toString();
}
/**
* Convenience method that tells the layout manager implementation how many instances
* of a given repeatable field exist on the parent object. This is useful in determining
* how many child objects need to be serialized when building an output from an object.
*<P>
* If a child object is a repeating object within a parent object, the "getter"
* method for that child object will return a java.util.List. This method invokes
* the getter method for the child object and returns the size of that List. If the
* List returned is null, zero will be returned.
* <P>
* For example, the Address child object in the BasicPerson object is repeating. Therefore,
* the BasicPerson object has a "getAddress" method that returns a java.util.List of Address
* objects that exist in that BasicPerson. This method invokes that method and
* returns the size of the returned object.
* <P>
* @return int the number of child objects
* @param xeo XmlEnterpriseObject the parent object being queried
* @param fieldName String the name of the child object being tested
* @throws EnterpriseLayoutException if an error occurs executing the getter method for the particular
* field on the parent object passed in. An exception will also be thrown if the
* object being checked is not a repeating field (the object returned by the getter method
* is not a java.util.List.
*/
protected int getLength(String fieldName) throws XmlEnterpriseObjectException {
int numObjects = 0;
String className = this.getClass().getName();
String objectName = className.substring(className.lastIndexOf('.') + 1); // Our based element in the XML passed in
try {
Method getter = null;
logger.debug("Seeing if " + fieldName + " is a repeating object on " + objectName + " passed in.");
getter = this.getClass().getMethod("get" + fieldName, new Class[] {});
String returnType = getter.getReturnType().getName();
logger.debug("get" + fieldName + " return type: " + returnType);
if (returnType.equals(LIST)) {
Object obj = getter.invoke(this, new Object[] {});
if (obj != null) {
java.util.List aList = (java.util.List)obj;
numObjects = aList.size();
}
else {
numObjects = 0;
}
}
else {
throw new EnterpriseLayoutException("The field '" + fieldName +
"' is NOT a repeating child field in the '" + objectName + "' object.");
}
}
catch (Exception e) {
throw new XmlEnterpriseObjectException("Unexpected Error attempting to invoke the 'get" +
fieldName + "' method on the '" + objectName + "' object. Exception: " + e.getMessage(), e);
}
return numObjects;
}
/**
* Convenience method that indicates if the field specified
* is a repeating field this object.
*<P>
* If a child object is a repeating object within a parent object, the "getter"
* method for that child object will return a java.util.List. This method inspects the
* return type of that getter method and checks to see if it's a java.util.List.
* <P>
* For example, the Address child object in the BasicPerson object is repeating. Therefore,
* the BasicPerson object has a "getAddress" method that returns a java.util.List of Address
* objects that exist in that BasicPerson. This method invokes that method and
* checks the class type (instanceof) the returned object. If it's a java.util.List
* it knows the Address is a repeating child on the BasicPerson. This will work for any
* XmlEnterpriseObject.
* <P>
* @return boolean true if the field is a repeating field, false if not.
* @param fieldName String the name of the field being tested.
* @throws XmlEnterpriseObjectException if an error occurs executing the child object's getter method.
*/
public boolean isRepeating(String fieldName) throws XmlEnterpriseObjectException {
boolean isRepeating = false;
String className = this.getClass().getName();
String objectName = className.substring(className.lastIndexOf('.') + 1); // Our based element in the XML passed in
try {
Method getter = null;
logger.debug("Seeing if " + fieldName + " is a repeating object on " + objectName + " passed in.");
getter = this.getClass().getMethod("get" + fieldName, new Class[] {});
String returnType = getter.getReturnType().getName();
logger.debug("get" + fieldName + " return type: " + returnType);
if (returnType.equals(LIST)) {
logger.debug(fieldName + " is a repeating object in " + objectName + " passed in.");
isRepeating = true;
}
else {
logger.debug(fieldName + " is NOT a repeating object in " + objectName + " passed in.");
}
}
catch (Exception e) {
logger.fatal(e.getMessage(), e);
throw new XmlEnterpriseObjectException("Unexpected Error attempting to invoke the 'get" +
fieldName + "' method on the '" + objectName + "' object. Exception: " + e.getMessage(), e);
}
return isRepeating;
}
/**
* Returns the current value from the field name passed in. Convenience
* method to allow "reflective" use of XmlEnterpriseObjects. Allows for
* parameters. This is especially neccessary when retrieving an individual
* object from a list of objects contained within the parent object.
*<P>
* @return Object the value from the field
* @param fieldName String the name of the field from which to retrieve data
* @param parms Object[] any parameters that need to be passed to the getter method being called.
* @param parmTypes Class[] the paramater types associated to any parameters.
* @throws XmlEnterpriseObjectException if the field name passed in does not exist
* or if any other errors occur calling the getter method associated to the field.
*/
public final Object getValueFromObject(String fieldName, Object[] parms, Class[] parmTypes)
throws XmlEnterpriseObjectException {
String className = getClass().getName();
String objectName = className.substring(className.lastIndexOf('.') + 1); // Our based element in the XML passed in
try {
Method getter = null;
logger.debug("Calling getter method for " + fieldName);
getter = getClass().getMethod("get" + fieldName, parmTypes);
Class c = getter.getReturnType();
Object obj = getter.invoke(this, parms);
return obj;
}
catch (Exception e) {
String errMessage = "Error calling getter method for " +
objectName + "/" + fieldName + " Exception: " + e.getMessage();
throw new XmlEnterpriseObjectException(errMessage, e);
}
}
/**
* Returns the current value from the field name passed in. Convenience
* method to allow "reflective" use of XmlEnterpriseObjects. Assumes
* the getter method being called does not take any parameters.
*<P>
* @return Object the value from the field
* @param fieldName String the name of the field from which to retrieve data
* @throws XmlEnterpriseObjectException if the field name passed in does not exist
* or if any other errors occur calling the getter method associated to the field.
*/
public final Object getValueFromObject(String fieldName)
throws XmlEnterpriseObjectException {
String className = getClass().getName();
String objectName = className.substring(className.lastIndexOf('.') + 1); // Our based element in the XML passed in
try {
Method getter = null;
logger.debug("Calling getter method for " + fieldName);
getter = getClass().getMethod("get" + fieldName, new Class[] {});
Class c = getter.getReturnType();
Object obj = getter.invoke(this, new Object[] {});
return obj;
}
catch (Exception e) {
String errMessage = "Error calling getter method for " +
objectName + "/" + fieldName + ". Exception: " + e.getMessage();
throw new XmlEnterpriseObjectException(errMessage, e);
}
}
/**
* Sets the current value the field name passed in to the value passed in. Convenience
* method to allow "reflective" use of XmlEnterpriseObjects. Assumes
* the setter method being called takes one String parameter.
*<P>
* @param fieldName String the name of the field from which to retrieve data
* @param value String the value to set on the field
* @throws XmlEnterpriseObjectException if the field name passed in does not exist
* or if any other errors occur calling the setter method associated to the field.
*/
public final void setValue(String fieldName, String value)
throws XmlEnterpriseObjectException {
String className = getClass().getName();
String objectName = className.substring(className.lastIndexOf('.') + 1);
try {
Method setter = null;
Object[] parms = new Object[] {};
parms[0] = value;
Class[] parmTypes = new Class[] {};
parmTypes[0] = value.getClass();
logger.debug("Calling setter method for " + fieldName);
setter = getClass().getMethod("set" + fieldName, parmTypes);
setter.invoke(this, parms);
}
catch (Exception e) {
String errMessage = "Error calling setter method for " +
objectName + "/" + fieldName + " Exception: " + e.getMessage();
throw new XmlEnterpriseObjectException(errMessage, e);
}
}
protected void saveLayoutManagers() {
// Since ever object performing these actions are going to be using an XML
// Layout Manager for querying, updating, deleting ect. we need to save the
// layout manager the object is currently using, then change the manager
// to be the XML layout manager (which all objects should have by default)
// After all of this is done, we'll set the layout manager back to what it
// was when this method was called...
// Save layout manager
EnterpriseLayoutManager tmpInput = getInputLayoutManager("xml");
if (tmpInput != null) {
m_saveInputLManager = getInputLayoutManager();
setInputLayoutManager(tmpInput);
logger.debug("[saveLayoutManagers] Input layout manager for " + getClass().getName() + " is " + getInputLayoutManager().getClass().getName());
}
EnterpriseLayoutManager tmpOutput = getOutputLayoutManager("xml");
if (tmpOutput != null) {
m_saveOutputLManager = getOutputLayoutManager();
setOutputLayoutManager(tmpOutput);
logger.debug("[saveLayoutManagers] Output layout manager for " + getClass().getName() + " is " + getOutputLayoutManager().getClass().getName());
}
}
protected void restoreLayoutManagers() {
setInputLayoutManager(m_saveInputLManager);
setOutputLayoutManager(m_saveOutputLManager);
}
}