
com.tangosol.dev.component.Integration Maven / Gradle / Ivy
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates.
*
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
package com.tangosol.dev.component;
import com.tangosol.util.ClassHelper;
import com.tangosol.util.ErrorList;
import com.tangosol.util.StringMap;
import com.tangosol.util.IllegalStringException;
import com.tangosol.util.WrapperException;
import com.tangosol.util.StringTable;
import com.tangosol.util.NullImplementation;
import com.tangosol.util.ChainedEnumerator;
import com.tangosol.util.SimpleEnumerator;
import com.tangosol.run.xml.XmlElement;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.PrintWriter;
import java.beans.PropertyVetoException;
import java.util.Enumeration;
import java.util.NoSuchElementException;
/**
* An Integration Map provides a mapping of the methods and constants (final
* fields) of a Java Class Signature into a Component Definition.
*
* @version 1.00, 12/03/97
* @author Cameron Purdy
* @version 2.00, 10/18/99
* @author Patrick J. McNerthney
*/
public class Integration
extends Trait
implements Constants
{
// ----- construction ---------------------------------------------------
/**
* Construct an Integration Map to provide a method/behavior and
* field/property mapping between a Java Class Signature and a
* Component Definition.
*
* @param parent the parent component that this integration belongs to
* @param sSignature the name of the Java Class Signature this is mapping against
*/
public Integration(Component parent, String sSignature)
{
super(parent, RESOLVED);
if (sSignature == null || sSignature.length() == 0)
{
sSignature = BLANK;
}
m_sPrevSignature = BLANK;
m_sSignature = sSignature;
m_sPrevModel = BLANK;
m_sModel = BLANK;
m_sPrevMisc = BLANK;
m_sMisc = BLANK;
m_mapPrevMethod = new StringMap();
m_mapMethod = new StringMap();
m_mapPrevField = new StringMap();
m_mapField = new StringMap();
m_jcs = null;
}
/**
* Copy constructor.
*
* @param parent the Component containing this Integration
* @param that the Integration object to copy from
*/
public Integration(Component parent, Integration that)
{
super(parent, that);
this.m_sPrevSignature = that.m_sPrevSignature;
this.m_sSignature = that.m_sSignature;
this.m_sPrevModel = that.m_sPrevModel;
this.m_sModel = that.m_sModel;
this.m_sPrevMisc = that.m_sPrevMisc;
this.m_sMisc = that.m_sMisc;
this.m_mapPrevMethod = that.m_mapPrevMethod; // immutable
this.m_mapMethod = (StringMap) that.m_mapMethod.clone();
this.m_mapPrevField = that.m_mapPrevField; // immutable
this.m_mapField = (StringMap) that.m_mapField .clone();
this.m_jcs = that.m_jcs;
}
/**
* Construct the integration from a stream.
*
* This is a custom serialization implementation that is unrelated to the
* Serializable interface and the Java implementation of persistence.
*
* @param cd the containing Component Definition
* @param stream the stream to read this Integration Definition from
* @param nVersion version of the data structure in the stream
*
* @exception IOException An IOException is thrown if an error occurs
* reading the Integration Definition from the stream or if the
* stream does not contain a valid Integration Definition.
*/
protected Integration(Component cd, DataInput stream, int nVersion)
throws IOException
{
super(cd, stream, nVersion);
m_sSignature = stream.readUTF();
if (m_sSignature.length() == 0)
{
m_sSignature = BLANK;
}
m_sModel = stream.readUTF();
if (m_sModel.length() == 0)
{
m_sModel = BLANK;
}
m_sMisc = stream.readUTF();
if (m_sMisc.length() == 0)
{
m_sMisc = BLANK;
}
m_sPrevSignature = BLANK;
m_sPrevModel = BLANK;
m_sPrevMisc = BLANK;
m_mapPrevMethod = new StringMap();
m_mapMethod = new StringMap(stream);
m_mapPrevField = new StringMap();
m_mapField = new StringMap(stream);
m_jcs = null;
}
/**
* Construct a Trait object from persistent data. All traits implement
* implement a constructor from persistent data.
*
* @param parent the trait that contains this trait
* @param xml the XmlElement to read the persistent information from
* @param nVersion version of the data structure in the stream
*
* @throws IOException if an exception occurs reading the trait data
*/
protected Integration(Trait parent, XmlElement xml, int nVersion)
throws IOException
{
super(parent, xml, nVersion);
m_sSignature = readString(xml.getElement("signature"));
m_sModel = readString(xml.getElement("model"));
m_sMisc = readString(xml.getElement("misc"));
m_sPrevSignature = BLANK;
m_sPrevModel = BLANK;
m_sPrevMisc = BLANK;
m_mapPrevMethod = new StringMap();
m_mapMethod = readStringMap(xml, "methods", "method");
m_mapPrevField = new StringMap();
m_mapField = readStringMap(xml, "fields", "field");
m_jcs = null;
}
/**
* Construct a blank Integration Trait.
*
* @param base the base Integration to derive from
* @param parent the Component containing this Integration
* @param nMode one of RESOLVED, DERIVATION, MODIFICATION
*
* @see Trait#getBlankDerivedTrait
*/
protected Integration(Integration base, Component parent, int nMode)
{
super(base, parent, nMode);
m_sPrevSignature = BLANK;
m_sSignature = BLANK;
m_sPrevModel = BLANK;
m_sModel = BLANK;
m_sPrevMisc = BLANK;
m_sMisc = BLANK;
m_mapPrevMethod = new StringMap();
m_mapMethod = new StringMap();
m_mapPrevField = new StringMap();
m_mapField = new StringMap();
m_jcs = null;
}
// ----- persistence ----------------------------------------------------
/**
* Save the Interface Map to a stream.
*
* This is a custom serialization implementation that is unrelated to the
* Serializable interface and the Java implementation of persistence.
*
* @param stream the stream to write this Interface Map to
*
* @exception IOException An IOException is thrown if an error occurs
* writing the Interface Map to the stream
*/
public synchronized void save(DataOutput stream)
throws IOException
{
// save the trait information
super.save(stream);
stream.writeUTF(m_sSignature);
stream.writeUTF(m_sModel);
stream.writeUTF(m_sMisc);
m_mapMethod.save(stream);
m_mapField .save(stream);
}
/**
* Save the Trait information to XML. If derived traits have any
* data of their own, then they must implement (i.e. supplement) this
* method.
*
* This is a custom serialization implementation that is unrelated to the
* Serializable interface and the Java implementation of persistence.
*
* @param xml an XmlElement to write the persistent information to
*
* @throws IOException if an exception occurs saving the trait data
*/
protected synchronized void save(XmlElement xml)
throws IOException
{
xml.addElement("signature").setString(m_sSignature);
xml.addElement("model").setString(m_sModel);
xml.addElement("misc").setString(m_sMisc);
super.save(xml);
saveStringMap(xml, "methods", "method", m_mapMethod);
saveStringMap(xml, "fields", "field", m_mapField);
}
// ----- derivation/modification ----------------------------------------
/**
* Construct a blank Trait. All traits implement this method.
*
* A blank derived trait is an "l-value" for resolve and extract
* processing. In other words, when resolve and extract create a result
* trait (either a resolved or delta trait) it is this method which is
* responsible for creating that trait in its initial state ("blank").
*
* The resolve and extract methods implemented by this class (Trait) are
* responsible for instantiating a resulting derived trait, either a
* RESOLVED, DERIVATION, or MODIFICATION trait, depending on which method
* (resolve or extract) was called and the parameters that were passed.
*
* This virtual method (getBlankDerivedTrait) is a "virtual constructor".
* In other words, it is responsible for instantiating the correct class,
* which is the same class as the "this" parameter (the base trait).
*
* @param parent the containing trait or null if the blank trait is
* not going to be contained by another trait
* @param nMode one of RESOLVED, DERIVATION, MODIFICATION
*
* @return a new blank derived trait of this trait's class with the
* specified parent and mode
*
* @see #resolve
* @see #extract
*/
protected Trait getBlankDerivedTrait(Trait parent, int nMode)
{
return new Integration(this, (Component) parent, nMode);
}
/**
* Create a derived/modified Trait by combining the information from this
* Trait with the super or base level's Trait information. Neither the
* base ("this") nor the delta may be modified in any way.
*
* @param traitDelta the Trait derivation or modification
* @param parent the Trait which will contain the resulting Trait or
* null if the resulting Trait will not be contained
* @param loader the Loader object for JCS, CIM, and CD dependencies
* @param errlist the error list object to log error information to
*
* @return the result of applying the specified delta Trait to this Trait
*
* @exception ComponentException thrown only if a fatal error occurs
*/
protected Integration resolve(Integration traitDelta, Component parent,
StringTable tblBehavior, StringTable tblProperty,
StringTable tblDeferBehavior, StringTable tblDeferProperty,
Loader loader, ErrorList errlist)
throws ComponentException
{
Integration base = this;
Integration delta = (Integration) resolveDelta(traitDelta, loader, errlist);
Integration derived = (Integration) super.resolve(delta, parent, loader, errlist);
// resolve class signature
String signatureBase = base.m_sSignature;
String signatureDelta = delta.m_sSignature;
String signatureDerived = signatureBase;
if (signatureDelta != BLANK && !signatureDelta.equals(signatureBase))
{
// TODO: Use loader to verify that this class is a sub-class
// of the previous class. Actually, this should be part of
// the isSignatureLegal call ???
if (derived.isSignatureLegal(signatureDelta))
{
signatureDerived = signatureDelta;
}
else
{
out("TODO: log error -- Illegal signature " + signatureDelta);
}
}
derived.m_sPrevSignature = signatureBase;
derived.m_sSignature = signatureDerived;
if (signatureDerived == BLANK)
{
return derived;
}
// resolve model and misc
String modelBase = base.m_sModel;
String miscBase = base.m_sMisc;
String modelDelta = delta.m_sModel;
String miscDelta = delta.m_sMisc;
String modelDerived = modelBase;
String miscDerived = miscBase;
if (modelDelta != BLANK || miscDelta != BLANK)
{
if (!modelDelta.equals(modelBase) || !miscDelta.equals(miscBase))
{
// TODO: We could verify that this model/misc can in fact
// override the previous model/misc. This should probably
// be a static call into the model class themselves. Actually,
// this should be part of the isValid call ???
if (isModelLegal(modelDelta, miscDelta))
{
modelDerived = modelDelta;
miscDerived = miscDelta;
}
else
{
out("TODO: log error -- Illegal model " + modelDelta + " " + miscDelta);
}
}
}
derived.m_sPrevModel = modelBase;
derived.m_sModel = modelDerived;
derived.m_sPrevMisc = miscBase;
derived.m_sMisc = miscDerived;
// Copy the base mapped methods to the derived's previous mapped methods.
StringMap mapPrev = (StringMap) base.m_mapPrevMethod.clone();
StringMap mapNew = base.m_mapMethod;
for (Enumeration enmr = mapNew.primaryStrings(); enmr.hasMoreElements();)
{
String sPrimary = (String) enmr.nextElement();
try
{
mapPrev.put(sPrimary, mapNew.get(sPrimary));
}
catch (IllegalStringException e)
{
throw new WrapperException(e);
}
}
derived.m_mapPrevMethod = mapPrev;
derived.m_mapMethod = new StringMap();
// Copy the base mapped fields to the derived's previous mapped fields.
mapPrev = (StringMap) base.m_mapPrevField.clone();
mapNew = base.m_mapField;
for (Enumeration enmr = mapNew.primaryStrings(); enmr.hasMoreElements();)
{
String sPrimary = (String) enmr.nextElement();
try
{
mapPrev.put(sPrimary, mapNew.get(sPrimary));
}
catch (IllegalStringException e)
{
throw new WrapperException(e);
}
}
derived.m_mapPrevField = mapPrev;
derived.m_mapField = new StringMap();
String sDerivedName = parent.getQualifiedName();
// load the JCS referenced by the integration map
Component jcsDerived = loader.loadSignature(signatureDerived);
if (jcsDerived == null)
{
// TODO: this should not be reported as a problem
// when a modification is loaded...
// unable to load Java Class Signature of integratee
logError(RESOLVE_LOADINTERFACE, ERROR, new Object[]
{signatureDerived, ATTR_INTEGRATION_SIGNATURE,
sDerivedName}, errlist);
return derived;
}
// resolve mapped methods
for (Enumeration enmr = delta.getMethods(); enmr.hasMoreElements();)
{
boolean fAddable = true;
// verify the "from" method name exists in the jcs (if we have one)
String sMethod = (String) enmr.nextElement();
Behavior method = null;
method = jcsDerived.getBehavior(sMethod);
if (method == null)
{
fAddable = false;
logError(MAP_MISSINGMETHOD, WARNING, new Object[]
{signatureDerived, sDerivedName, sMethod, jcsDerived.getName()}, errlist);
}
else
{
// verify that method is accessible
int nAccess = method.getAccess();
if (nAccess != ACCESS_PUBLIC && nAccess != ACCESS_PROTECTED)
{
fAddable = false;
logError(MAP_INVALIDMETHOD, WARNING, new Object[]
{signatureDerived, sDerivedName, sMethod, jcsDerived.getName()}, errlist);
}
}
// verify the "to" behavior name is valid for this component
String sBehavior = delta.getBehavior(sMethod);
Behavior behavior = parent.getBehavior(sBehavior);
if (behavior == null)
{
// verify that the signature is not reserved
if (parent.isBehaviorReserved(sBehavior))
{
fAddable = false;
logError(MAP_RESERVEDBEHAVIOR, WARNING, new Object[]
{signatureDerived, sDerivedName, sBehavior}, errlist);
}
// verify that the signature is not an accessor for an
// integrated field (property)
// TODO
}
else
{
if (method != null)
{
// certain behavior attributes that must match cannot be
// modified (fixed) if the behavior has non-manual origin
boolean fFixable = !behavior.isFromNonManual();
int nSeverity = (fFixable ? INFO : WARNING);
// verify that the static attribute matches
if (method.isStatic() != behavior.isStatic())
{
fAddable = fAddable && fFixable;
logError(MAP_SCOPEMISMATCH, nSeverity, new Object[]
{signatureDerived, sDerivedName, sBehavior, sMethod}, errlist);
}
// verify that the return value type matches
if (method .getReturnValue().getDataType() !=
behavior.getReturnValue().getDataType())
{
fAddable = fAddable && fFixable;
logError(MAP_RETURNMISMATCH, nSeverity, new Object[]
{signatureDerived, sDerivedName,
sBehavior, behavior.getReturnValue().getDataType().toString(),
sMethod, method.getReturnValue().getDataType().toString()}, errlist);
}
// verify that the parameter directions match
if (!method.getParameterDirections().equals(behavior.getParameterDirections()))
{
fAddable = fAddable && fFixable;
logError(MAP_DIRECTIONMISMATCH, nSeverity, new Object[]
{signatureDerived, sDerivedName, sBehavior, sMethod}, errlist);
}
}
}
if (!fAddable)
{
continue;
}
// add the entry to the integration method map
try
{
derived.m_mapMethod.put(sMethod, sBehavior);
}
catch (IllegalStringException e)
{
throw new WrapperException(e);
}
// search for a Behavior in the "defer" list and use it
// if possible instead of creating a Behavior from scratch
// (note - changes made here need to be made below too)
if (behavior == null && tblDeferBehavior != null)
{
behavior = (Behavior) tblDeferBehavior.get(sBehavior);
if (behavior != null)
{
// un-defer it
tblDeferBehavior.remove(sBehavior);
// copy the behavior to this component
behavior = new Behavior(parent, behavior);
// the Behavior is new at this level
behavior.setExists(EXISTS_INSERT);
// add it to this level
tblBehavior.put(sBehavior, behavior);
}
}
if (method != null)
{
if (behavior == null)
{
// if no such Behavior signature already exists, create
// one based on the method
String sName = sBehavior.substring(0, sBehavior.indexOf('('));
behavior = new Behavior(parent, this, sName, method);
try
{
parent.addBehavior(behavior, false);
}
catch (PropertyVetoException e)
{
throw new WrapperException(e);
}
}
else
{
// resolve any differences between the existing Behavior
// and the integrated method
behavior.setDeclaredByIntegration(this, method);
}
}
}
// resolve mapped fields
for (Enumeration enmr = delta.getFields(); enmr.hasMoreElements();)
{
boolean fAddable = true;
// verify the "from" field name exists in the jcs (if we have one)
String sField = (String) enmr.nextElement();
Property field = jcsDerived.getProperty(sField);
if (field == null)
{
fAddable = false;
logError(MAP_MISSINGFIELD, WARNING, new Object[]
{signatureDerived, sDerivedName, sField, jcsDerived.getName()}, errlist);
}
// verify the "to" property name is valid for this component
String sProperty = delta.getProperty(sField);
Property property = parent.getProperty(sProperty);
if (field != null)
{
if (property == null)
{
DataType dt = field.getDataType();
boolean fStatic = field.isStatic();
int nAccess = field.getAccess();
boolean fAccess = (nAccess == ACCESS_PUBLIC || nAccess == ACCESS_PROTECTED);
if (fAccess && field.isJavaConstant())
{
if (!Property.isJavaConstantCreatable(parent, dt, sProperty,
PROP_SINGLE, fStatic, field.getAccess()))
{
fAddable = false;
logError(MAP_PROPNOTCREATABLE, WARNING, new Object[]
{signatureDerived, sDerivedName, sProperty,
dt.toString()}, errlist);
}
}
else if (fAccess && field.isStandardProperty())
{
if (!Property.isPropertyCreatable(parent, dt, sProperty,
PROP_SINGLE, fStatic, false))
{
fAddable = false;
logError(MAP_PROPNOTCREATABLE, WARNING, new Object[]
{signatureDerived, sDerivedName, sProperty,
dt.toString()}, errlist);
}
}
else
{
fAddable = false;
logError(MAP_INVALIDFIELD, WARNING, new Object[]
{signatureDerived, sDerivedName, sField,
jcsDerived.getName()}, errlist);
}
}
else
{
// certain Property attributes that must match cannot be
// modified (fixed) if the Property has non-manual origin
boolean fFixable = !property.isFromNonManual();
int nSeverity = (fFixable ? INFO : WARNING);
// determine if the Property can be modified to match the
// integrated field
int nAccess = (field.isJavaConstant() ? field.getAccess() : ACCESS_PRIVATE);
if (property.getAccess() != nAccess)
{
fAddable = fAddable && fFixable;
logError(MAP_PROPFIELDMISMATCH, WARNING, new Object[]
{signatureDerived, sDerivedName, Property.ATTR_ACCESS,
sProperty, sField}, errlist);
}
if (field.isStandardProperty())
{
// ! TODO accessors must be available
}
if (property.isStatic() != field.isStatic())
{
fAddable = fAddable && fFixable;
logError(MAP_PROPFIELDMISMATCH, WARNING, new Object[]
{signatureDerived, sDerivedName, Property.ATTR_STATIC,
sProperty, sField}, errlist);
}
if (property.isFinal() != field.isFinal())
{
fAddable = fAddable && fFixable;
logError(MAP_PROPFIELDMISMATCH, WARNING, new Object[]
{signatureDerived, sDerivedName, Property.ATTR_FINAL,
sProperty, sField}, errlist);
}
if (property.isPersistent() != field.isPersistent())
{
fAddable = fAddable && fFixable;
logError(MAP_PROPFIELDMISMATCH, WARNING, new Object[]
{signatureDerived, sDerivedName, Property.ATTR_PERSISTENT,
sProperty, sField}, errlist);
}
if (property.getDirection() != field.getDirection())
{
fAddable = fAddable && fFixable;
logError(MAP_PROPFIELDMISMATCH, WARNING, new Object[]
{signatureDerived, sDerivedName, Property.ATTR_DIRECTION,
sProperty, sField}, errlist);
}
if (property.getDataType() != field.getDataType())
{
fAddable = fAddable && fFixable;
logError(MAP_PROPFIELDMISMATCH, WARNING, new Object[]
{signatureDerived, sDerivedName, Property.ATTR_DATATYPE,
sProperty, sField}, errlist);
}
if (property.getIndexed() != PROP_SINGLE)
{
fAddable = fAddable && fFixable;
logError(MAP_PROPFIELDMISMATCH, WARNING, new Object[]
{signatureDerived, sDerivedName, Property.ATTR_INDEXED,
sProperty, sField}, errlist);
}
// value must be NO_VALUE (or NO_DELTA)
if (!(property.isNoValue() || property.isNoDelta()))
{
fAddable = fAddable && fFixable;
logError(MAP_PROPVALUE, WARNING, new Object[]
{signatureDerived, sDerivedName, sProperty}, errlist);
}
}
}
if (!fAddable)
{
continue;
}
// add the entry to the integration field map and interface
try
{
derived.m_mapField.put(sField, sProperty);
}
catch (IllegalStringException e)
{
throw new WrapperException(e);
}
// search for a Property in the "defer" list and use it
// if possible instead of creating a Property from scratch
if (property == null && tblDeferProperty != null)
{
property = (Property) tblDeferProperty.get(sProperty);
if (property != null)
{
// un-defer it
tblDeferProperty.remove(sProperty);
// copy the property to this component
property = new Property(parent, property);
// the Property is new at this level
property.setExists(EXISTS_INSERT);
// add it to this level
tblProperty.put(sProperty, property);
}
}
if (field != null)
{
if (property == null)
{
// if no such Property already exists, create one based
// on the field
DataType dt = field.getDataType();
boolean fStatic = field.isStatic();
if (field.isJavaConstant())
{
property = Property.createJavaConstant(
parent, dt, sProperty, PROP_SINGLE, fStatic, field.getAccess());
}
else
{
property = Property.createProperty(
parent, dt, sProperty, PROP_SINGLE, fStatic, false);
}
try
{
parent.addProperty(property, false);
}
catch (PropertyVetoException e)
{
throw new WrapperException(e);
}
}
// resolve any differences between the existing Property
// and the integrated field
property.setFromIntegration(this, field);
// make sure accessors are available
if (!property.isConstant())
{
if (tblDeferBehavior != null)
{
for (int i = Property.PA_FIRST; i <= Property.PA_LAST; ++i)
{
if (property.isAccessorApplicable(i) && property.getAccessor(i) == null)
{
// search for a Behavior in the "defer" list and
// use it if possible instead of creating one
// (note - cut&paste from above)
String sBehavior = property.getAccessorSignature(i);
Behavior behavior = (Behavior) tblDeferBehavior.get(sBehavior);
if (behavior != null)
{
// un-defer it
tblDeferBehavior.remove(sBehavior);
// copy the behavior to this component
behavior = new Behavior(parent, behavior);
// the Behavior is new at this level
behavior.setExists(EXISTS_INSERT);
// add it to this level
tblBehavior.put(sBehavior, behavior);
}
}
}
}
// now that we've supplied as many accessors as we can
// find, let the property create the rest and synch the
// ones that already exist
property.addAccessors();
}
}
}
return derived;
}
/*
* Create a derivation/modification Trait by determining the differences
* between the derived Trait ("this") and the passed base Trait. Neither
* the derived Trait ("this") nor the base may be modified in any way.
*
* @param base the base Trait to extract
* @param parent the Trait which will contain the resulting Trait or
* null if the resulting Trait will not be contained
* @param loader the Loader object for JCS, CIM, and CD dependencies
* @param errlist the error list object to log error information to
*
* @return the delta between this derived Trait and the base Trait
*
* @exception ComponentException thrown only if a fatal error occurs
*/
protected Trait extract(Trait traitBase, Trait parent, Loader loader, ErrorList errlist)
throws ComponentException
{
Integration derived = this;
Integration base = (Integration) traitBase;
Integration delta = (Integration) super.extract(base, parent, loader, errlist);
// We only derive.
if (delta.getMode() != DERIVATION)
{
throw new IllegalArgumentException(
CLASS + ".extract: "
+ "Only Integration derivations can be extracted!");
}
// extract signature
String signatureBase = base.m_sSignature;
String signatureDerived = derived.m_sSignature;
String signatureDelta = BLANK;
if (!signatureDerived.equals(signatureBase))
{
signatureDelta = signatureDerived;
}
delta.m_sSignature = signatureDelta;
// extract model/misc
String modelBase = base.m_sModel;
String modelDerived = derived.m_sModel;
String modelDelta = BLANK;
String miscBase = base.m_sMisc;
String miscDerived = derived.m_sMisc;
String miscDelta = BLANK;
if (!modelDerived.equals(modelBase)
|| !miscDerived.equals(miscBase))
{
modelDelta = modelDerived;
miscDelta = miscDerived;
}
delta.m_sModel = modelDelta;
delta.m_sMisc = miscDelta;
// ----- Methods
extractMap(base.m_mapPrevMethod,
base.m_mapMethod,
derived.m_mapPrevMethod,
derived.m_mapMethod,
delta.m_mapMethod,
errlist);
// ----- Fields
extractMap(base.m_mapPrevField,
base.m_mapField,
derived.m_mapPrevField,
derived.m_mapField,
delta.m_mapField,
errlist);
delta.m_jcs = derived.m_jcs;
return delta;
}
private void extractMap(StringMap mapPrevBase,
StringMap mapBase,
StringMap mapPrevDerived,
StringMap mapDerived,
StringMap mapDelta,
ErrorList errlist)
{
// copy to the delta ALL map entries with reside in the
// derived, but do not reside in the base
for (Enumeration enmr = mapPrevDerived.primaryStrings(); enmr.hasMoreElements(); )
{
String sName = (String) enmr.nextElement();
if (!mapPrevBase.contains(sName) && !mapBase.contains(sName))
{
// copy it to the delta component
try
{
mapDelta.put(sName, mapPrevDerived.get(sName));
}
catch (IllegalStringException e)
{
throw new WrapperException(e);
}
}
}
for (Enumeration enmr = mapDerived.primaryStrings(); enmr.hasMoreElements(); )
{
String sName = (String) enmr.nextElement();
if (!mapPrevBase.contains(sName) && !mapBase.contains(sName))
{
// copy it to the delta component
try
{
mapDelta.put(sName, mapDerived.get(sName));
}
catch (IllegalStringException e)
{
throw new WrapperException(e);
}
}
}
}
/**
* Finalize the extract process. This means that this trait will not
* be asked to extract again. A trait is considered persistable after
* it has finalized the extract process.
*
* @exception ComponentException thrown only if a fatal error occurs
*/
public synchronized void finalizeExtract()
throws ComponentException
{
super.finalizeExtract(null, null);
try
{
// Discard non-mapped methods
for (Enumeration enmrMethods = m_mapMethod.primaryStrings(); enmrMethods.hasMoreElements();)
{
String method = (String) enmrMethods.nextElement();
String behavior = m_mapMethod.get( method );
if ( behavior == null )
{
m_mapMethod.remove( method );
}
}
// Discard non-mapped fields
for (Enumeration enmrFields = m_mapField.primaryStrings(); enmrFields.hasMoreElements(); )
{
String field = (String) enmrFields.nextElement();
String property = m_mapField.get( field );
if ( property == null )
{
m_mapField.remove( field );
}
}
}
catch (IllegalStringException e)
{
throw new WrapperException(e);
}
}
// ----- accessors ------------------------------------------------------
/**
* Determine the Component which contains this Integration.
*
* @return the Component trait that contains this Integration
*/
public Component getComponent()
{
return (Component) getParentTrait();
}
/**
* Determine if this Integration is different from integration
* on the super component.
*/
public boolean isNewIntegration()
{
return (!m_sPrevSignature.equals(m_sSignature)
|| !m_sPrevModel.equals(m_sModel)
|| !m_sPrevMisc.equals(m_sMisc)
|| !m_mapMethod.isEmpty()
|| !m_mapField.isEmpty()
);
}
/**
* Determine if the integration is modifiable.
*
* @return true if changes are permitted to the integration
*/
public boolean isModifiable()
{
return (super.isModifiable()
&& ((Component) getParentTrait()).isIntegrationSettable()
&& m_jcs != null);
}
/**
* Determine the unique name for this trait.
*
* A sub-trait that exists within a collection of sub-traits must have
* two ways of being identified:
*
* 1) A unique name, which is a string identifier
* 2) A UID as a secondary identifier (dog tag)
*
* @return the primary string identifier of the trait
*/
protected String getUniqueName()
{
return getSignature();
}
/**
* Determine the unique description for this trait. The unique
* description is in the format:
*
* + ' ' +
*
* All traits must be uniquely identifiable by a "description string".
* This enables the origin implementation built into Trait to use the
* description string to differentiate between Trait origins.
*
* @return the description string for the trait
*/
protected String getUniqueDescription()
{
return DESCRIPTOR + ' ' + getUniqueName();
}
/**
* Determines if this Integration exists for any reason at all.
*
* @return true if the Behavior is discardable
*/
protected boolean isDiscardable()
{
int nMode = getMode();
if (nMode == DERIVATION || nMode == MODIFICATION)
{
// check for delta information
if (isNewIntegration())
{
return false;
}
}
return super.isDiscardable();
}
/**
* Get the name of the Java Class Signature that the previous
* Integration Map maps from. This property is read-only.
*
* @return the name of the Java Class Signature
*/
public String getPreviousSignature()
{
return m_sPrevSignature;
}
/**
* Get the name of the Java Class Signature that this Integration Map maps
* from
*
* @return the name of the Java Class Signature
*/
public String getSignature()
{
return m_sSignature;
}
/**
* Determine if the name of the map can be changed.
*
* @return true if okay to change
*/
public boolean isSignatureSettable()
{
return super.isModifiable();
}
/**
* Determine if the specified map name is legal.
*
* @return true if the specified name is legal
*/
public boolean isSignatureLegal(String sName)
{
return ClassHelper.isQualifiedNameLegal(sName);
}
/**
* Set the name of the Integration Map.
*
* @param sSignature the name of the Integration Map
*/
public void setSignature(String sSignature)
throws PropertyVetoException
{
setSignature(sSignature, true);
}
/**
* Set the name of the Integration Map.
*
* @param sSignature the new name for the Component
* @param fVetoable true if the setter can veto the value
*
* @exception PropertyVetoException if the new attribute value is not
* accepted
*/
protected synchronized void setSignature(String sSignature, boolean fVetoable)
throws PropertyVetoException
{
if (sSignature == null || sSignature.length() == 0)
{
sSignature = BLANK;
}
String sPrev = m_sSignature;
if (sSignature.equals(sPrev))
{
return;
}
if (fVetoable)
{
if (!isSignatureSettable())
{
readOnlyAttribute(ATTR_INTEGRATION_SIGNATURE, sPrev, sSignature);
}
if (!isSignatureLegal(sSignature))
{
illegalAttributeValue(ATTR_INTEGRATION_SIGNATURE, sPrev, sSignature);
}
fireVetoableChange(ATTR_INTEGRATION_SIGNATURE, sPrev, sSignature);
}
m_sSignature = sSignature;
m_sModel = m_sPrevModel;
m_sMisc = m_sPrevMisc;
m_mapMethod = new StringMap();
m_mapField = new StringMap();
clearJcs();
firePropertyChange(ATTR_INTEGRATION_SIGNATURE, sPrev, sSignature);
}
/**
* Get the name of the Integration Model.
*
* @return the name of the Integration Model
*/
public String getModel()
{
return m_sModel;
}
/**
* Get the miscellaneous model information. This information is stored
* in the Integration Map by a tool to provide model-specific build
* instructions to the Integration Model.
*
* @return the the miscellaneous model information
*/
public String getMisc()
{
return m_sMisc;
}
/**
* Determine if the name of the Integration model can be changed.
*
* @return true if okay to change
*/
public boolean isModelSettable()
{
return isModifiable();
}
/**
* Determine whether the passed Integration Model name is legal.
*
* @param sModel the name of the Integration Model
*
* @return true if the specified value is a legal Integration Model name
*
* @see com.tangosol.util.ClassHelper#getDerivedName
*/
public boolean isModelLegal(String sModel, String sMisc)
{
if (sModel == null || sModel.length() == 0)
{
sModel = BLANK;
}
if (sMisc == null || sMisc.length() == 0)
{
sMisc = BLANK;
}
if (sModel == BLANK)
{
return sMisc == BLANK;
}
return ClassHelper.isPartialNameLegal(sModel);
}
/**
* Set the name and misc of the Integration Model.
*
* @param sModel the name of the Integration Model
* @param sMisc the misc of the Integration Model
*/
public void setModel(String sModel, String sMisc)
throws PropertyVetoException
{
setModel(sModel, sMisc, true);
}
/**
* Set the name and misc of the Integration Model.
*
* @param sModel the name of the Integration Model
* @param sMisc TODO
* @param fVetoable true if the setter can veto the value
*/
protected synchronized void setModel(String sModel, String sMisc, boolean fVetoable)
throws PropertyVetoException
{
if (sModel == null || sModel.length() == 0)
{
sModel = BLANK;
}
if (sMisc == null || sMisc.length() == 0)
{
sMisc = BLANK;
}
String[] asPrev = new String[]
{
m_sModel, m_sMisc
};
String[] asNew = new String[]
{
sModel, sMisc
};
if (asNew[0].equals(asPrev[0])
&& asNew[1].equals(asPrev[1]))
{
return;
}
if (fVetoable)
{
if (!isModelSettable())
{
readOnlyAttribute(ATTR_INTEGRATION_MODEL, asPrev, asNew);
}
if (!isModelLegal(asNew[0], asNew[1]))
{
illegalAttributeValue(ATTR_INTEGRATION_MODEL, asPrev, asNew);
}
fireVetoableChange(ATTR_INTEGRATION_MODEL, asPrev, asNew);
}
m_sModel = asNew[0];
m_sMisc = asNew[1];
firePropertyChange(ATTR_INTEGRATION_MODEL, asPrev, asNew);
}
// ----- methods/behaviors
/**
* Get all Java Class Signature method signatures. Some of the methods
* may have been removed from the map; if so, the getBehavior method will
* return null for the method.
*
* @return an enumeration of strings specifying each Java Class Signature
* method signature
*/
public Enumeration getMethods()
{
return new ChainedEnumerator(m_mapPrevMethod.primaryStrings(), m_mapMethod.primaryStrings());
}
/**
* Get all Component Definition behavior signatures corresponding to
* the Java Class Signature method signatures. Some of the behavior
* signatures may be null meaning that the corresponding method was
* removed.
*
* @return an enumeration of strings specifying each Component Definition
* behavior signature with an order corresponding to the
* enumeration returned from getMethods
*/
public Enumeration getBehaviors()
{
return new ChainedEnumerator(m_mapPrevMethod.secondaryStrings(), m_mapMethod.secondaryStrings());
}
/**
* Determine the behavior signature that corresponds to the specified
* method signature.
*
* @param sMethodSignature the signature of the Java Class Signature
* method to look up
*
* @return a string specifying the corresponding behavior signature or null if
* the method signature does not exist or has been removed from the map
*/
public String getBehavior(String sMethodSignature)
{
String sBehavior = m_mapPrevMethod.get(sMethodSignature);
if (sBehavior == null)
{
sBehavior = m_mapMethod.get(sMethodSignature);
}
return sBehavior;
}
public String getBehavior(Behavior method)
{
return getBehavior(method.getSignature());
}
public String getSuggestedBehavior(Behavior method)
{
String sBehavior = getBehavior(method);
if (sBehavior != null)
{
return sBehavior;
}
Property field = getFieldFromAccessor(method);
if (field == null)
{
return null;
}
String sProperty = getSuggestedProperty(field);
if (sProperty == null)
{
return null;
}
sBehavior = method.getSignature();
return sBehavior.substring(0, sBehavior.charAt(0) == 'i' ? 2 : 3)
+ sProperty + sBehavior.substring(sBehavior.indexOf('('));
}
/**
* Determine if the method signature exists in the integration map
*
* @param sMethodSignature the signature of the Java Class Signature
* method to look up
*
* @return true if the signature is in the map, false otherwise
*/
public boolean containsMethod(String sMethodSignature)
{
//return m_mapMethod.contains(sMethodSignature);
boolean fContains = m_mapPrevMethod.contains(sMethodSignature);
if (!fContains)
{
fContains = m_mapMethod.contains(sMethodSignature);
}
return fContains;
}
/**
* Determine the method signature that corresponds to the specified
* Component Definition behavior signature.
*
* @param sBehaviorSignature the signature of the Component Definition
* behavior to look up
*
* @return a string specifying the corresponding method signature or
* null if the behavior signature was not found
*/
public String getMethod(String sBehaviorSignature)
{
String sMethod = m_mapPrevMethod.getPrimary(sBehaviorSignature);
if (sMethod == null)
{
sMethod = m_mapMethod.getPrimary(sBehaviorSignature);
}
return sMethod;
}
/**
* Determine if the method was inherited from the super-class.
*
* @return true if it was inherited
*/
public boolean isMethodInherited(Behavior method)
{
return method.getExists() != EXISTS_INSERT;
}
/**
* Determine if the behavior was inherited from our super-map
*
* @return true if it was inherited
*/
public boolean isMethodBehaviorInherited(Behavior method)
{
return m_mapPrevMethod.contains(method.getSignature());
}
/**
* Determine if it is okay to add or remove mappped methods.
*
* @return true if okay to add mapped methods
*/
public boolean isMethodSettable(Behavior method)
{
if (!isModifiable() || method == null)
{
return false;
}
String sMethodSignature = method.getSignature();
if (m_mapPrevMethod.contains(sMethodSignature)
|| m_jcs.getBehavior(sMethodSignature) != method)
{
return false;
}
return true;
}
/**
* Determine if it is okay to rename mappped methods.
*
* @return true if okay to rename mapped methods
*/
public boolean isMethodRenamable(Behavior method)
{
Property field = getFieldFromAccessor(method);
if (field != null)
{
// We are a property accessor, check if the property
// is currently mapped.
String sProperty = getProperty(field);
if (sProperty != null)
{
// We claim the property is already mapped, this will be the case as long
// as one of it's accessors are mapped. Only allow renaming of this
// accessor if the property is not defined in the parent component.
if (isPropertyFromIntegration(sProperty))
{
return false;
}
}
}
return true;
}
private Property getFieldFromAccessor(Behavior method)
{
// Check if we are the accessor of any of the properties.
String [] asProperties = m_tblProperties.strings();
for (int i = 0; i < asProperties.length; ++i)
{
Property field = (Property) m_tblProperties.get(asProperties[i]);
if (field != null)
{
Behavior[] accessors = field.getAccessors();
for (int ii = 0; ii < accessors.length; ++ii)
{
if (accessors[ii] == method)
{
return field;
}
}
}
}
return null;
}
/**
* Determine whether the passed method and behavior names are legal.
*
* @param method the method to check
* @param sBehaviorSignature the behavior to check
*
* @return true if the specified values are okay
*
*/
public boolean isBehaviorLegal(Behavior method, String sBehaviorSignature)
{
if (method == null)
{
return false;
}
String sMethodSignature = method.getSignature();
Component parent = (Component) getParentTrait();
if (m_jcs == null)
{
return false;
}
if (m_jcs.getBehavior(sMethodSignature) != method)
{
return false;
}
// verify that method is accessible
int nAccess = method.getAccess();
if (nAccess != ACCESS_PUBLIC && nAccess != ACCESS_PROTECTED)
{
return false;
}
String sMethodParms = sMethodSignature.substring(sMethodSignature.indexOf('('));
// if method is being mapped to
if (sBehaviorSignature == null || sBehaviorSignature.length() == 0)
{
return true;
}
String sPrevBehaviorSignature = getBehavior(sMethodSignature);
if (sPrevBehaviorSignature != null && sPrevBehaviorSignature.length() == 0)
{
sPrevBehaviorSignature = null;
}
if (sBehaviorSignature.equals(sPrevBehaviorSignature))
{
return true;
}
int of = sBehaviorSignature.indexOf('(');
if (of < 0)
{
return false;
}
String sBehaviorName = sBehaviorSignature.substring(0, of);
String sBehaviorParms = sBehaviorSignature.substring(of);
// Behavior name must be a legal simple Java identifier
// and parameters must match
if (!ClassHelper.isSimpleNameLegal(sBehaviorName)
|| !sBehaviorParms.equals(sMethodParms))
{
return false;
}
// Make sure the behavior is already not mapped to a different method
String sBehaviorMethod = getMethod(sBehaviorSignature);
if (sBehaviorMethod != null)
{
return false;
}
// Get the current behavior if it exists
Behavior behavior = null;
if (sPrevBehaviorSignature != null)
{
behavior = parent.getBehavior(sPrevBehaviorSignature);
}
if (behavior != null)
{
return behavior.isNameLegal(sBehaviorName);
}
// Check if we are mapping to an existing behavior
behavior = parent.getBehavior(sBehaviorSignature);
if (behavior == null)
{
// verify that the new signature is not reserved
if (parent.isBehaviorReserved(sBehaviorSignature))
{
return false;
}
// verify that the signature is not an accessor for an
// integrated field (property)
// TODO - also in Component.java
return true;
}
// We are mapping to an existing behavior.
// certain behavior attributes that must match cannot be
// modified (fixed) if the behavior has non-manual origin
if (!behavior.isFromNonManual())
{
return true;
}
// verify that the static attribute matches
if (method.isStatic() != behavior.isStatic())
{
return false;
}
// verify that the return value type matches
if (method.getReturnValue().getDataType()
!= behavior.getReturnValue().getDataType())
{
return false;
}
// verify that the parameter directions match
if (!method.getParameterDirections()
.equals(behavior.getParameterDirections()))
{
return false;
}
return true;
}
/**
* Modify the behavior signature that maps to a particular method.
*
* @param method the method
* @param sBehaviorSignature the (new) signature of the behavior
* (may be null)
*
* @exception PropertyVetoException if the behavior name
* already maps to a different method
*/
public void setBehavior(Behavior method, String sBehaviorSignature)
throws PropertyVetoException
{
setBehavior(method, sBehaviorSignature, true);
}
/**
* Modify the behavior signature that maps to a particular method.
*
* @param method TODO
* @param sBehaviorSignature the (new) signature of the behavior
* (may be null)
* @param fVetoable TODO
*
* @exception PropertyVetoException if the behavior name
* already maps to a different method
*/
protected synchronized void setBehavior(Behavior method, String sBehaviorSignature, boolean fVetoable)
throws PropertyVetoException
{
if (method == null)
{
return;
}
String sMethodSignature = method.getSignature();
if (sBehaviorSignature != null && sBehaviorSignature.length() == 0)
{
sBehaviorSignature = null;
}
// get the current mapping, if any
String sPrevBehaviorSignature = getBehavior(sMethodSignature);
if (sPrevBehaviorSignature != null && sPrevBehaviorSignature.length() == 0)
{
sPrevBehaviorSignature = null;
}
// don't proceed if there is no change
if (sPrevBehaviorSignature == null)
{
if (sBehaviorSignature == null)
{
return;
}
}
else
{
if (sPrevBehaviorSignature.equals(sBehaviorSignature))
{
return;
}
}
// used for property change events
Object[] asPrev = new Object[]
{
method, sPrevBehaviorSignature
};
// verify the validitiy of the change
if (fVetoable)
{
if (!isMethodSettable(method))
{
readOnlyAttribute(ATTR_INTEGRATION_METHOD, asPrev, sBehaviorSignature);
}
// check if a method and behavior can be added
if (!isBehaviorLegal(method, sBehaviorSignature))
{
illegalAttributeValue(ATTR_INTEGRATION_METHOD, asPrev, sBehaviorSignature);
}
// notify veto listeners
fireVetoableChange(ATTR_INTEGRATION_METHOD, asPrev, sBehaviorSignature);
}
// Check if this is the last mapped accessor of
// a "manufactured" field to be removed.
boolean fLastAccessor = false;
Property field = getFieldFromAccessor(method);
if (sBehaviorSignature == null && field != null)
{
fLastAccessor = true;
Behavior[] accessors = field.getAccessors();
for (int i = 0; i < accessors.length; ++i)
{
// It is the last mapped accessor, remove
// any mapping against the field also.
Behavior accessor = accessors[i];
if (accessor != null && accessor != method)
{
if (getBehavior(accessor) != null)
{
fLastAccessor = false;
}
}
}
}
// add/remove the method from the map.
try
{
if (sBehaviorSignature == null)
{
if (fLastAccessor)
{
setProperty(field, null, false);
if (m_mapMethod.contains(sMethodSignature))
{
m_mapMethod.remove(sMethodSignature);
}
}
else
{
m_mapMethod.remove(sMethodSignature);
}
}
else
{
m_mapMethod.put(sMethodSignature, sBehaviorSignature);
}
}
catch (IllegalStringException e)
{
throw new WrapperException(e);
}
// Update the parent component to reflect the new behavior
Component parent = (Component) getParentTrait();
// Get the existing behavior that this method maps to (if any)
Behavior behavior = null;
if (sPrevBehaviorSignature != null)
{
behavior = parent.getBehavior(sPrevBehaviorSignature);
}
// Check if removing mapping
if (sBehaviorSignature == null)
{
// Remove the current behavior if it exists
if (behavior != null)
{
if (behavior.isFromIntegration())
{
behavior.removeOriginTrait(this);
if (behavior.isDiscardable())
{
parent.removeBehavior(behavior, false);
}
}
}
}
else
{
String sBehaviorName = sBehaviorSignature.substring(0, sBehaviorSignature.indexOf('('));
// Check if rename or adding the behavior
if (behavior == null)
{
// Check if a behavior already exists under that name
behavior = parent.getBehavior(sBehaviorSignature);
if (behavior == null)
{
// if no such Behavior signature already exists, create
// one based on the method
behavior = new Behavior(parent, this, sBehaviorName, method);
parent.addBehavior(behavior, false);
}
else
{
// resolve any differences between the existing Behavior
// and the integrated method
behavior.setDeclaredByIntegration(this, method);
}
}
else
{
// We checked if we are renaming an existing behavior
// that the new one does not exist.
behavior.setName(sBehaviorName, false);
}
}
// notify listeners
firePropertyChange(ATTR_INTEGRATION_METHOD, asPrev, sBehaviorSignature);
}
// ----- fields/properties
/**
* Get all Java Class Signature final field names. Some of the fields
* may have been removed from the map; if so, the getProperty method
* will return null for the field name.
*
* @return an enumeration of strings specifying each Java Class Signature
* final field name
*/
public Enumeration getFields()
{
return new ChainedEnumerator(m_mapPrevField.primaryStrings(), m_mapField.primaryStrings());
}
/**
* Get all Component Definition constant property names corresponding to
* the Java Class Signature final field names. Some of the property
* names may be null meaning that the corresponding field was removed.
*
* @return an enumeration of strings specifying each Component Definition
* constant property name with an order corresponding to the
* enumeration returned from getFields
*/
public Enumeration getProperties()
{
return new ChainedEnumerator(m_mapPrevField.secondaryStrings(), m_mapField.secondaryStrings());
}
/**
* Determine the constant property name that corresponds to the specified
* final field name.
*
* @param sField the name of the Java Class Signature final field
* to look up
*
* @return a string specifying the corresponding constant property name or
* null if the specified field doesn't exists or has been removed
*/
public String getProperty(String sField)
{
String sProperty = m_mapPrevField.get(sField);
if (sProperty == null)
{
sProperty = m_mapField.get(sField);
}
return sProperty;
}
public String getProperty(Property field)
{
String sFieldSignature = getFieldSignature(field);
// Check if an integrated Java Constant.
Property property = (Property) m_tblProperties.get(sFieldSignature);
if (property == null)
{
return getProperty(field.getName());
}
String sProperty = getSuggestedProperty(field);
if (sProperty != null)
{
if (!isPropertyFromIntegration(sProperty))
{
sProperty = null;
}
}
return sProperty;
}
public String getSuggestedProperty(Property field)
{
String sFieldSignature = getFieldSignature(field);
// Check if an integrated Java Constant.
Property property = (Property) m_tblProperties.get(sFieldSignature);
if (property == null)
{
return getProperty(field.getName());
}
String sProperty = null;
Behavior[] accessors = field.getAccessors();
for (int i = 0; i < accessors.length; ++i)
{
Behavior accessor = accessors[i];
if (accessor != null)
{
String sBehavior = getBehavior(accessor.getSignature());
if (sBehavior != null)
{
sBehavior = sBehavior.substring(sBehavior.charAt(0) == 'i' ? 2 : 3,
sBehavior.indexOf('('));
if (sProperty == null)
{
sProperty = sBehavior;
}
else
{
if (!sBehavior.equals(sProperty))
{
return field.getName();
}
}
}
}
}
return sProperty;
}
/**
* Determine if the field exists in the integration map
*
* @param sField the name of the Java Class Signature final field
* to look up
*
* @return true if the property is in the map, false otherwise
*/
public boolean containsField(String sField)
{
boolean fContains = m_mapPrevField.contains(sField);
if (!fContains)
{
fContains = m_mapField.contains(sField);
}
return fContains;
}
/**
* Determine the field name that corresponds to the specified Component
* Definition property.
*
* @param sProperty the name of the Component Definition constant property
* to look up
*
* @return a string specifying the corresponding field name or
* null if the property name was not found
*/
public String getField(String sProperty)
{
String sField = m_mapPrevField.getPrimary(sProperty);
if (sField == null)
{
sField = m_mapField.getPrimary(sProperty);
}
return sField;
}
/**
* Determine if the method was inherited from the super-class.
*
* @return true if it was inherited
*/
public boolean isFieldInherited(Property field)
{
if (field.getExists() != EXISTS_INSERT)
{
return true;
}
Behavior[] accessors = field.getAccessors();
for (int i = 0; i < accessors.length; ++i)
{
Behavior accessor = accessors[i];
if (accessor != null)
{
if (accessor.getExists() != EXISTS_INSERT)
{
return true;
}
}
}
return false;
}
/**
* Determine if the field was inherited from our super-map
*
* @return true if it was inherited
*/
public boolean isFieldPropertyInherited(Property field)
{
Property property = (Property) m_tblProperties.get(getFieldSignature(field));
if (property == null)
{
return m_mapPrevField.contains(field.getName());
}
Behavior[] accessors = property.getAccessors();
for (int i = 0; i < accessors.length; ++i)
{
Behavior accessor = accessors[i];
if (accessor != null)
{
if (m_mapPrevMethod.contains(accessor.getSignature()))
{
return true;
}
}
}
return false;
}
/**
* Determine if it is okay to add mappped fields.
*
* @return true if okay to add mapped fields
*/
public boolean isFieldSettable(Property field)
{
if (!isModifiable() || field == null)
{
return false;
}
// Make sure that this field looks like it belongs to us.
String sFieldSignature = getFieldSignature(field);
if (!m_tblProperties.contains(sFieldSignature))
{
return false;
}
// Check if this property was defined by the "super-map".
if (isFieldPropertyInherited(field))
{
return false;
}
// Check if a "real" field in the JCS.
if (m_tblProperties.get(sFieldSignature) == null)
{
// Make sure this field is really from the JCS.
return m_jcs.getProperty(field.getName()) == field;
}
String sProperty = getProperty(field);
if (sProperty == null)
{
// We are not already mapped, also check that all of
// the accessors are settable and of a consistent mapping.
Behavior[] accessors = field.getAccessors();
for (int i = 0; i < accessors.length; ++i)
{
Behavior accessor = accessors[i];
if (accessor != null)
{
if (!isMethodSettable(accessor))
{
return false;
}
// Check if the method a currently mapped.
String sBehavior = getBehavior(accessor.getSignature());
if (sBehavior != null)
{
// Generate the property name.
sBehavior = sBehavior.substring(sBehavior.charAt(0) == 'i' ? 2 : 3,
sBehavior.indexOf('('));
// Ensure that the mapped names are consistent.
if (sProperty == null)
{
sProperty = sBehavior;
}
else
{
if (!sBehavior.equals(sProperty))
{
return false;
}
}
}
}
}
}
else
{
// We claim to be already mapped, this can also be the case as long
// as one of our accessors are mapped. Only allow unmapping if
// we are defined as a property in the parent component.
if (!isPropertyFromIntegration(sProperty))
{
return false;
}
}
return true;
}
/**
* Determine if it is okay to add mappped fields.
*
* @return true if okay to add mapped fields
*/
public boolean isFieldRenamable(Property field)
{
return true;
}
/**
* Determine whether the passed field and property names are legal.
*
* @param field the field name to check
* @param sProperty the property name to check
*
* @return true if the specified values are okay
*
*/
public boolean isPropertyLegal(Property field, String sProperty)
{
if (field == null)
{
return false;
}
Component parent = (Component) getParentTrait();
if (m_jcs == null)
{
return false;
}
String sFieldSignature = getFieldSignature(field);
if (!m_tblProperties.contains(sFieldSignature))
{
return false;
}
// if a property is not being mapped to
if (sProperty == null || sProperty.length() == 0)
{
// Verify that the properties' accessors don't
// mind being unmapped.
Behavior[] accessors = field.getAccessors();
for (int i = 0; i < accessors.length; ++i)
{
Behavior accessor = accessors[i];
if (accessor != null)
{
if (!isBehaviorLegal(accessors[i], null))
{
return false;
}
}
}
return true;
}
String sPrevProperty = getProperty(field);
if (sPrevProperty != null && sPrevProperty.length() == 0)
{
sPrevProperty = null;
}
if (sProperty.equals(sPrevProperty))
{
return true;
}
// Property name must be a legal simple Java identifier
if (!ClassHelper.isSimpleNameLegal(sProperty))
{
return false;
}
// Make sure the property is not already mapped to a different field
String sPropertyField = getField(sProperty);
if (sPropertyField != null)
{
return false;
}
// Get the current property if it exists
Property property = null;
if (sPrevProperty != null)
{
property = parent.getProperty(sPrevProperty);
}
// check if the field is already mapped to a property
if (property != null)
{
// we are mapping an existing mapped property, first we
// check if the name change is legal.
if (!property.isNameLegal(sProperty))
{
return false;
}
}
else
{
// Check if we are mapping to an existing property in the
// parent component.
property = parent.getProperty(sProperty);
if (property == null)
{
// We are creating a brand new property in the parent component.
DataType dt = field.getDataType();
boolean fStatic = field.isStatic();
int nIndexed = field.getIndexed();
if (field.isJavaConstant())
{
int nAccess = field.getAccess();
if (nAccess != ACCESS_PUBLIC && nAccess != ACCESS_PROTECTED)
{
return false;
}
if (!Property.isJavaConstantCreatable(
parent, dt, sProperty, nIndexed, fStatic, nAccess))
{
return false;
}
}
else if (field.isCalculatedProperty())
{
if (!Property.isCalculatedPropertyCreatable(
parent, dt, sProperty, nIndexed, fStatic))
{
return false;
}
}
else if (field.isFunctionalProperty())
{
if (!Property.isFunctionalPropertyCreatable(
parent, dt, sProperty, nIndexed, fStatic))
{
return false;
}
}
else if (field.isStandardProperty())
{
if (!Property.isPropertyCreatable(
parent, dt, sProperty, nIndexed, fStatic, false))
{
return false;
}
}
else
{
return false;
}
}
else
{
// We are mapping to an existing property in the parent component.
// Certain Property attributes that must match cannot be
// modified (fixed) if the Property has non-manual origin
if (property.isFromNonManual())
{
// determine if the Property can be modified to match the
// integrated field
int nAccess = (field.isJavaConstant() ? field.getAccess() : ACCESS_PRIVATE);
if (property.getAccess() != nAccess)
{
return false;
}
if (property.isStatic() != field.isStatic())
{
return false;
}
if (property.isFinal() != field.isFinal())
{
return false;
}
if (property.isPersistent() != field.isPersistent())
{
return false;
}
if (property.getDirection() != field.getDirection())
{
return false;
}
if (property.getDataType() != field.getDataType())
{
return false;
}
if (property.getIndexed() != field.getIndexed())
{
return false;
}
// value must be NO_VALUE (or NO_DELTA)
if (!(property.isNoValue() || property.isNoDelta()))
{
return false;
}
}
}
// Verify that the properties' accessors also pass all of
// our checks.
Behavior[] accessors = field.getAccessors();
String[] behaviors = getAccessorsBehaviors(accessors, sProperty, field.isBooleanGet());
for (int i = 0; i < behaviors.length; ++i)
{
String behavior = behaviors[i];
if (behavior != null)
{
if (!isBehaviorLegal(accessors[i], behavior))
{
return false;
}
}
}
}
return true;
}
/**
* Modify the property that maps to a particular field.
*
* @param field the field being mapped
* @param sProperty the property to map the field to,
* null unmapped the field
*
*/
public void setProperty(Property field, String sProperty)
throws PropertyVetoException
{
setProperty(field, sProperty, true);
}
/**
* Modify the property that maps to a particular field.
*
* @param field the field being mapped
* @param sProperty the property to map the field to,
* null unmapped the field
* @param fVetoable TODO
*
*/
protected synchronized void setProperty(Property field, String sProperty, boolean fVetoable)
throws PropertyVetoException
{
if (sProperty != null && sProperty.length() == 0)
{
sProperty = null;
}
String sPrevProperty = getProperty(field);
if (sPrevProperty != null && sPrevProperty.length() == 0)
{
sPrevProperty = null;
}
if (sPrevProperty == null)
{
if (sProperty == null)
{
return;
}
}
else
{
if (sPrevProperty.equals(sProperty))
{
return;
}
}
Object [] asPrev = new Object[]
{
field, sPrevProperty
};
if (fVetoable)
{
if (!isFieldSettable(field))
{
readOnlyAttribute(ATTR_INTEGRATION_FIELD, asPrev, sProperty);
}
// check if a field and property is legit
if (!isPropertyLegal(field, sProperty))
{
illegalAttributeValue(ATTR_INTEGRATION_FIELD, asPrev, sProperty);
}
// notify veto listeners
fireVetoableChange(ATTR_INTEGRATION_FIELD, asPrev, sProperty);
}
// add the property to the map if it is defined by the integrated
// component as a field.
try
{
// check if this is a "real" field being integrated
if (m_tblProperties.get(getFieldSignature(field)) == null)
{
if (sProperty == null)
{
m_mapField.remove(field.getName());
}
else
{
m_mapField.put(field.getName(), sProperty);
}
}
}
catch (IllegalStringException e)
{
throw new WrapperException(e);
}
// Update the parent component to reflect the new property
Component parent = (Component) getParentTrait();
// Get the existing property that this field maps to (if any)
Property property = null;
if (sPrevProperty != null)
{
property = parent.getProperty(sPrevProperty);
}
// Check if removing mapping
if (sProperty == null)
{
// Remove the current property if it exists
if (property != null)
{
if (isPropertyFromIntegration(property))
{
property.removeOriginTrait(this);
parent.removeProperty(property, false);
}
}
// Remove all mapped accessors.
Behavior[] accessors = field.getAccessors();
for (int i = 0; i < accessors.length; ++i)
{
Behavior accessor = accessors[i];
if (accessor != null)
{
setBehavior(accessor, null, false);
}
}
}
else
{
// Check if rename or adding the property
if (property == null)
{
// Check if a behavior already exists under that name
property = parent.getProperty(sProperty);
if (property == null)
{
// if no such Property already exists, create one based
// on the field
DataType dt = field.getDataType();
int nIndexed = field.getIndexed();
boolean fStatic = field.isStatic();
if (field.isJavaConstant())
{
property = Property.createJavaConstant(
parent, dt, sProperty, nIndexed, fStatic, field.getAccess());
}
else if (field.isCalculatedProperty())
{
property = Property.createCalculatedProperty(
parent, dt, sProperty, nIndexed, fStatic);
}
else if (field.isFunctionalProperty())
{
property = Property.createFunctionalProperty(
parent, dt, sProperty, nIndexed, fStatic);
}
else
{
property = Property.createProperty(
parent, dt, sProperty, nIndexed, fStatic, false);
}
parent.addProperty(property, false);
}
// resolve any differences between the existing Property
// and the integrated field
property.setFromIntegration(this, field);
// make sure accessors are available
// let the property create the accessors and synch the
// ones that already exist
property.addAccessors();
// TODO add "setFromIntegration" to Component.expandIntegrates
// As a work around don't let extraction to remove the property
property.setFromManual();
}
else
{
// We checked if we are renaming an existing behavior
// that the new one does not exist.
property.setName(sProperty, false);
}
// Now, deal with all of this properties' accessors
Behavior[] accessors = field.getAccessors();
String[] behaviors = getAccessorsBehaviors(accessors, sProperty, field.isBooleanGet());
for (int i = 0; i < behaviors.length; ++i)
{
String behavior = behaviors[i];
if (behavior != null)
{
setBehavior(accessors[i], behavior, false);
}
}
}
// notify listeners
firePropertyChange(ATTR_INTEGRATION_FIELD, asPrev, sProperty);
}
// ----- helpers --------------------------------------------------------
/**
* Get the current Java Class Signature associated with this Integration Map
*
* @return The Java Class Signature
*/
public String[] getImplements()
{
return m_tblImplements.strings();
}
public Interface getImplements(String sInterface)
{
if (!m_tblImplements.contains(sInterface))
{
return null;
}
return m_jcs.getImplements(sInterface);
}
public String[] getDispatches()
{
return m_tblDispatches.strings();
}
public Interface getDispatches(String sInterface)
{
if (!m_tblDispatches.contains(sInterface))
{
return null;
}
Interface iface = (Interface) m_tblDispatches.get(sInterface);
if (iface == null)
{
iface = m_jcs.getImplements(sInterface);
}
return iface;
}
public String[] getMethodBehavior()
{
return m_tblBehaviors.strings();
}
public Behavior getMethodBehavior(String sMethod)
{
return m_jcs.getBehavior(sMethod);
}
public String[] getFieldProperty()
{
return m_tblProperties.strings();
}
public Property getFieldProperty(String sField)
{
if (!m_tblProperties.contains(sField))
{
return null;
}
Property property = (Property) m_tblProperties.get(sField);
if (property == null)
{
property = m_jcs.getProperty(sField.substring(0,sField.indexOf('.')));
}
return property;
}
/**
* TODO
*/
public void clearJcs()
{
m_jcs = null;
m_tblImplements = null;
m_tblDispatches = null;
m_tblBehaviors = null;
m_tblProperties = null;
}
/**
* TODO
*/
public void loadJcs(Loader loader)
throws ComponentException
{
clearJcs();
// gg: 2005.01.26 when super component removes Integration
// resolve does not remove it causing NPE; working around
// by making an empty Integration valid
m_tblImplements = new StringTable();
m_tblDispatches = new StringTable();
m_tblBehaviors = new StringTable();
m_tblProperties = new StringTable();
if (m_sSignature == BLANK)
{
return;
}
m_jcs = loader.loadSignature(m_sSignature);
if (m_jcs == null)
{
return;
}
// Put all of the methods in the behaviors table for now, we
// will later remove those that correspond to properties and
// dispatches.
String[] as = m_jcs.getBehavior();
for (int i = 0; i < as.length; ++i)
{
String sMethod = as[i];
if (!sMethod.startsWith(""))
{
m_tblBehaviors.add(as[i]);
}
}
// First go through the jcs's interfaces and organize between dispatches and
// interfaces.
//as = m_jcs.getImplements();
//for (int i = 0; i < as.length; ++i)
// {
// String sImplements = as[i];
// if (isEventListener(sImplements, loader))
// {
// m_tblDispatches.add(sImplements);
// }
// else
// {
// m_tblImplements.add(sImplements);
// }
// for (Enumeration enmr = m_jcs.getImplements(sImplements).getBehaviors();
// enmr.hasMoreElements();)
// {
// m_tblBehaviors.remove((String) enmr.nextElement());
// }
// }
// Next set up all the fields as properties.
as = m_jcs.getProperty();
for (int i = 0; i < as.length; ++i)
{
m_tblProperties.add(getFieldSignature(m_jcs.getProperty(as[i])));
}
// Now, sort the methods into appropriate categories.
as = m_jcs.getBehavior();
for (int i = 0; i < as.length; ++i)
{
Behavior method = m_jcs.getBehavior(as[i]);
// parse a verb and noun from the method name
String sVerb = method.getName();
String sNoun = null;
for (int ii = 0; ii < sVerb.length(); ++ii)
{
if (!Character.isLowerCase(sVerb.charAt(ii)))
{
sNoun = sVerb.substring(ii);
sVerb = sVerb.substring(0,ii);
break;
}
}
if (sNoun == null)
{
continue;
}
DataType dataType = method.getReturnValue().getDataType();
if (sVerb.equals("is") || sVerb.equals("get"))
{
switch (method.getParameterCount())
{
case 0:
setupProperty(sNoun, dataType);
break;
case 1:
if (method.getParameter(0).getDataType() == DataType.INT)
{
setupProperty(sNoun, dataType.getArrayType());
}
break;
}
}
else if (dataType == DataType.VOID && sVerb.equals("set"))
{
switch (method.getParameterCount())
{
case 1:
setupProperty(sNoun, method.getParameter(0).getDataType());
break;
case 2:
if (method.getParameter(0).getDataType() == DataType.INT)
{
setupProperty(sNoun, method.getParameter(1).getDataType().getArrayType());
}
break;
}
}
else if (dataType == DataType.VOID
&& (sVerb.equals("add") || sVerb.equals("remove"))
&& sNoun.endsWith("Listener")
&& method.getParameterCount() == 1)
{
dataType = method.getParameter(0).getDataType();
if (dataType.isClass()
&& isEventListener(dataType.getClassName(), loader))
{
setupDispatches(dataType);
}
}
}
}
private boolean isEventListener(String sClass, Loader loader)
{
if (sClass.equals("java.util.EventListener"))
{
return true;
}
try
{
Component component = loader.loadSignature(sClass);
if (component != null)
{
String[] asImplements = component.getImplements();
for (int i = 0; i < asImplements.length; ++i)
{
if (isEventListener(asImplements[i], loader))
{
return true;
}
}
}
}
catch (ComponentException ce)
{
}
return false;
}
private String getFieldSignature(Property field)
{
DataType dataType = field.getDataType();
if (!field.isSingle())
{
dataType = dataType.getArrayType();
}
return field.getName() + '.' + dataType.getTypeString();
}
private String[] getAccessorsBehaviors(Behavior[] accessors, String sProperty, boolean fBooleanGet)
{
// First determine if we are dealing with all of
// the accessors, or a sub-set.
boolean fAllSet = true;
boolean fAllClear = true;
if (sProperty != null)
{
for (int i = 0; i < accessors.length; ++i)
{
Behavior accessor = accessors[i];
if (accessor != null)
{
if (getBehavior(accessor.getSignature()) == null)
{
fAllSet = false;
}
else
{
fAllClear = false;
}
}
}
}
String[] behaviors = new String[accessors.length];
for (int i = 0; i < accessors.length; ++i)
{
behaviors[i] = null;
Behavior accessor = accessors[i];
if (accessor != null)
{
String sMethod = accessor.getSignature();
if (fAllClear || fAllSet || getBehavior(sMethod) != null)
{
String sPrefix;
switch (sMethod.charAt(0))
{
case 'g':
if (!fBooleanGet)
{
sPrefix = "get";
break;
}
// drop into 'i'
case 'i':
sPrefix = "is";
break;
default:
sPrefix = "set";
break;
}
behaviors[i] = sPrefix + sProperty + sMethod.substring(sMethod.indexOf('('));
}
}
}
return behaviors;
}
private void setupProperty(String sProperty, DataType dataType)
{
String sPropertySignature = sProperty + '.' + dataType.getTypeString();
// Check if this property has already been setup.
if (m_tblProperties.contains(sPropertySignature))
{
return;
}
boolean fArray = dataType.isArray();
DataType elementType = (fArray ? dataType.getElementType() : dataType);
boolean fBoolean = ((dataType.isArray()
? dataType.getElementType()
: dataType) == DataType.BOOLEAN);
String sOut = fBoolean ? "is" : "get";
String sSingleOut = sOut + sProperty + "()";
Behavior method = m_jcs.getBehavior(sSingleOut);
if (method == null || method.getReturnValue().getDataType() != dataType)
{
if (fBoolean)
{
sOut = "get";
sSingleOut = sOut + sProperty + "()";
method = m_jcs.getBehavior(sSingleOut);
if (method == null || method.getReturnValue().getDataType() != dataType)
{
sOut = "is";
sSingleOut = null;
}
}
else
{
sSingleOut = null;
}
}
String sSingleIn = "set" + sProperty + '(' + dataType.getTypeString() + ')';
method = m_jcs.getBehavior(sSingleIn);
if (method == null || method.getReturnValue().getDataType() != DataType.VOID)
{
sSingleIn = null;
}
String sIndexedOut = null;
String sIndexedIn = null;
if (fArray)
{
sIndexedOut = sOut + sProperty + "(I)";
method = m_jcs.getBehavior(sIndexedOut);
if (method == null || method.getReturnValue().getDataType() != elementType)
{
if (fBoolean && sSingleOut == null)
{
sOut = "get";
sIndexedOut = sOut + sProperty + "(I)";
method = m_jcs.getBehavior(sIndexedOut);
if (method == null || method.getReturnValue().getDataType() != elementType)
{
sOut = "is";
sIndexedOut = null;
}
}
}
sIndexedIn = "set" + sProperty + "(I" + elementType.getTypeString() + ')';
method = m_jcs.getBehavior(sIndexedIn);
if (method == null || method.getReturnValue().getDataType() != DataType.VOID)
{
sIndexedIn = null;
}
}
int iType = 0;
int nProp = 0;
if (sSingleOut != null && sSingleIn != null)
{
iType = 1; // standard property
if (sIndexedOut == null || sIndexedIn == null)
{
nProp = PROP_SINGLE;
sIndexedOut = null;
sIndexedIn = null;
}
else
{
nProp = PROP_INDEXED;
}
}
else if (sIndexedOut != null && sIndexedIn != null)
{
iType = 1; // standard property
nProp = PROP_INDEXEDONLY;
sSingleOut = null;
sSingleIn = null;
}
else if (sSingleOut != null)
{
if (sIndexedIn == null)
{
iType = 2; // calculated property
if (sIndexedOut == null)
{
nProp = PROP_SINGLE;
}
else
{
nProp = PROP_INDEXED;
}
}
}
else if (sSingleIn != null)
{
if (sIndexedOut == null)
{
iType = 3; // functional property
if (sIndexedIn == null)
{
nProp = PROP_SINGLE;
}
else
{
nProp = PROP_INDEXED;
}
}
}
else if (sIndexedOut != null)
{
iType = 2; // calculated property
nProp = PROP_INDEXEDONLY;
}
else if (sIndexedIn != null)
{
iType = 3; // functional property
nProp = PROP_INDEXEDONLY;
}
if (nProp == PROP_SINGLE && fArray)
{
elementType = dataType;
}
Property property = null;
switch (iType)
{
case 1:
property = Property.createProperty(m_jcs, elementType, sProperty, nProp, false, false);
break;
case 2:
property = Property.createCalculatedProperty(m_jcs, elementType, sProperty, nProp, false);
break;
case 3:
property = Property.createFunctionalProperty(m_jcs, elementType, sProperty, nProp, false);
break;
}
if (property != null)
{
if (fBoolean && sOut.equals("get"))
{
property.setBooleanGet(true);
}
m_tblProperties.put(sPropertySignature, property);
if (sSingleOut != null)
{
m_tblBehaviors.remove(sSingleOut);
}
if (sSingleIn != null)
{
m_tblBehaviors.remove(sSingleIn);
}
if (sIndexedOut != null)
{
m_tblBehaviors.remove(sIndexedOut);
}
if (sIndexedIn != null)
{
m_tblBehaviors.remove(sIndexedIn);
}
}
}
private boolean isPropertyFromIntegration(String sProperty)
{
Property property = ((Component) getParentTrait()).getProperty(sProperty);
if (property == null)
{
return false;
}
return isPropertyFromIntegration(property);
}
private boolean isPropertyFromIntegration(Property property)
{
if (property.isFromIntegration())
{
return true;
}
Behavior[] accessors = property.getAccessors();
for (int i = 0; i < accessors.length; ++i)
{
Behavior accessor = accessors[i];
if (accessor != null && accessor.isFromIntegration())
{
return true;
}
}
return false;
}
private void setupDispatches(DataType dataType)
{
String className = dataType.getClassName();
// Check if already setup.
if (m_tblDispatches.get(className) != null)
{
return;
}
String name = className.substring(className.lastIndexOf('.') + 1) + "(L" + className + ";)";
String sAdd = "add" + name;
Behavior method = m_jcs.getBehavior(sAdd);
if (method == null
|| method.getReturnValue().getDataType() != DataType.VOID
|| method.getParameterCount() != 1
|| method.getParameter(0).getDataType() != dataType)
{
return;
}
String sRemove = "remove" + name;
method = m_jcs.getBehavior(sRemove);
if (method == null
|| method.getReturnValue().getDataType() != DataType.VOID
|| method.getParameterCount() != 1
|| method.getParameter(0).getDataType() != dataType)
{
return;
}
Enumeration enmrBehaviors;
Enumeration enmrProperties;
Interface iface = m_jcs.getImplements(className);
if (iface != null)
{
enmrBehaviors = iface.getBehaviors();
enmrProperties = iface.getProperties();
}
else
{
enmrBehaviors = NullImplementation.getEnumeration();
enmrProperties = NullImplementation.getEnumeration();
}
iface = new Interface(m_jcs,
className,
Interface.DISPATCHES,
new ChainedEnumerator(enmrBehaviors,
new SimpleEnumerator(new Object[] {sAdd, sRemove})),
enmrProperties);
m_tblDispatches.put(className, iface);
m_tblBehaviors.remove(sAdd);
m_tblBehaviors.remove(sRemove);
}
// ----- Object methods -------------------------------------------------
/**
* Compares this Integration map to another Object for equality.
*
* @param obj the other Object to compare to this
*
* @return true if this Component equals that Object
*/
public boolean equals(Object obj)
{
if (!(obj instanceof Integration))
{
return false;
}
Integration that = (Integration) obj;
if (this == that)
{
return true;
}
return super.equals(that)
&& this.m_sPrevSignature.equals(that.m_sPrevSignature)
&& this.m_sSignature.equals(that.m_sSignature)
&& this.m_sPrevModel.equals(that.m_sPrevModel)
&& this.m_sModel.equals(that.m_sModel)
&& this.m_sPrevMisc.equals(that.m_sPrevMisc)
&& this.m_sMisc.equals(that.m_sMisc)
&& this.m_mapMethod.equals(that.m_mapMethod)
&& this.m_mapField.equals(that.m_mapField)
;
}
/**
* Reset state, discarding all information.
*/
protected synchronized void invalidate()
{
super.invalidate();
m_sPrevSignature = null;
m_sSignature = null;
m_sPrevModel = null;
m_sModel = null;
m_sPrevMisc = null;
m_sMisc = null;
m_mapPrevMethod = null;
m_mapMethod = null;
m_mapPrevField = null;
m_mapField = null;
m_jcs = null;
}
// ----- debug methods --------------------------------------------------
/**
* Provide the entire set of Integration information in a printed format.
*/
public void dump()
{
dump(getOut(), BLANK);
}
/**
* Provide the entire set of Integration information in a printed format.
*
* @param out PrintWriter object to dump the information to
* @param sIndent a string used to indent each line of dumped information
*/
public void dump(PrintWriter out, String sIndent)
{
dump(out, sIndent, true);
}
/**
* Provide the entire set of Integration information in a printed format.
*
* @param out PrintWriter object to dump the information to
* @param sIndent a string used to indent each line of dumped information
* @param fIndentFirstLine false to suppress first line indention
*/
public void dump(PrintWriter out, String sIndent, boolean fIndentFirstLine)
{
if (fIndentFirstLine)
{
out.print(sIndent);
}
out.println("PrevSignature=" + m_sPrevSignature );
out.println(sIndent + "Signature=" + m_sSignature );
out.println(sIndent + "PrevModel=" + m_sPrevModel);
out.println(sIndent + "Model=" + m_sModel);
out.println(sIndent + "PrevMisc=" + m_sPrevMisc);
out.println(sIndent + "Misc=" + m_sMisc);
// trait attributes
super.dump(out, sIndent);
out();
dump(out, sIndent + " ", m_mapPrevMethod, m_mapMethod, "Java Method", "Behavior");
out();
dump(out, sIndent + " ", m_mapPrevField , m_mapField, "Java Field", "Property");
}
/**
* Provide the entire set of Integration information in a printed format.
*
* @param out PrintWriter object to dump the information to
* @param sIndent a string used to indent each line of dumped information
* @param map the StringMap
* @param sCol1 heading for primary strings
* @param sCol2 heading for secondary strings
*/
private void dump(PrintWriter out, String sIndent, StringMap mapPrev, StringMap map, String sCol1, String sCol2)
{
// determine longest string in each column
Enumeration enmr1 = new ChainedEnumerator(mapPrev.primaryStrings(), map.primaryStrings());
Enumeration enmr2 = new ChainedEnumerator(mapPrev.secondaryStrings(), map.secondaryStrings());
int cch1 = sCol1.length();
int cch2 = sCol2.length();
try
{
while (true)
{
String s1 = (String) enmr1.nextElement();
if (s1.length() > cch1)
{
cch1 = s1.length();
}
String s2 = (String) enmr2.nextElement();
if (s2 == null)
{
s2 = NULL_STRING;
}
else if (s2 == s1)
{
s2 = EQUAL_STRING;
}
if (s2.length() > cch2)
{
cch2 = s2.length();
}
}
}
catch (NoSuchElementException e)
{
}
// build dividers to place below headers
int cchMax = (cch1 > cch2 ? cch1 : cch2);
char[] achSpc = new char[cchMax];
char[] achDiv = new char[cchMax];
for (int i = 0; i < cchMax; ++i)
{
achSpc[i] = ' ';
achDiv[i] = '-';
}
String sSpc = new String(achSpc);
String sDiv = new String(achDiv);
String sDiv1 = sDiv.substring(0, cch1);
String sDiv2 = sDiv.substring(0, cch2);
// dump strings
out.println(sIndent + (sCol1 + sSpc).substring(0, cch1)
+ " " + (sCol2 + sSpc).substring(0, cch2)
+ " Type");
out.println(sIndent + sDiv1 + " " + sDiv2 + " ---------");
enmr1 = new ChainedEnumerator(mapPrev.primaryStrings(), map.primaryStrings());
enmr2 = new ChainedEnumerator(mapPrev.secondaryStrings(), map.secondaryStrings());
try
{
while (true)
{
String s1 = (String) enmr1.nextElement();
String s2 = (String) enmr2.nextElement();
if (s2 == null)
{
s2 = NULL_STRING;
}
else if (s2 == s1)
{
s2 = EQUAL_STRING;
}
out.println(sIndent + (s1 + sSpc).substring(0, cch1)
+ " " + (s2 + sSpc).substring(0, cch2)
+ " " + (mapPrev.contains(s1) ? "Inherited" : "Local"));
}
}
catch (NoSuchElementException e)
{
}
}
// ----- data members ---------------------------------------------------
/**
* The map name.
*/
public static final String ATTR_INTEGRATION_SIGNATURE = "IntegrationSignature";
/**
* The Model attribute.
*/
public static final String ATTR_INTEGRATION_MODEL = "IntegrationModel";
/**
* The Behavior attribute.
*/
public static final String ATTR_INTEGRATION_METHOD = "IntegrationMethod";
/**
* The Property attribute.
*/
public static final String ATTR_INTEGRATION_FIELD = "IntegrationField";
/**
* The name of this class.
*/
private static final String CLASS = "Integration";
/**
* The Parameter's descriptor string.
*/
protected static final String DESCRIPTOR = CLASS;
/**
* The printed representation of a null string.
*/
private static final String NULL_STRING = "";
/**
* The printed representation of an equal string.
*/
private static final String EQUAL_STRING = "";
/**
* The name of the Java Class Signature being integrated.
*/
private String m_sPrevSignature;
private String m_sSignature;
/**
* The name of the Integration Model. This name is used during Component
* Compilation to determine the class responsible for building the
* integration interfaces and classes.
*/
private String m_sPrevModel;
private String m_sModel;
/**
* Model-defined miscellaneous information used in the build process.
*/
private String m_sPrevMisc;
private String m_sMisc;
/**
* A map between the signatures of Java Class Signature methods and
* Component Definition behaviors.
*/
private StringMap m_mapPrevMethod;
private StringMap m_mapMethod;
/**
* A map between the names of Java Class Signature final fields and
* Component Definition constant properties.
*/
private StringMap m_mapPrevField;
private StringMap m_mapField;
/**
* The Java Class Signature that this maps against. This field is
* set by the UI tool during modification and is only used to very
* the validity of methods and fields being mapped.
*/
private Component m_jcs;
private StringTable m_tblImplements;
private StringTable m_tblDispatches;
private StringTable m_tblBehaviors;
private StringTable m_tblProperties;
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy