com.tangosol.dev.component.Integration Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of coherence Show documentation
Show all versions of coherence Show documentation
Oracle Coherence Community Edition
/*
* 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;
}