com.tangosol.dev.component.Implementation 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 java.beans.PropertyVetoException;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.PrintWriter;
import com.tangosol.util.ClassHelper;
import com.tangosol.util.ErrorList;
import com.tangosol.run.xml.XmlElement;
/**
* This class represents the implementation (e.g. scripting) of a behavior.
*
* An Implementation trait is not subject to derivation/modification in the
* manner that other traits are. Implementations are additive within a
* Component such that, given a Component Modification M which applies to a
* Component Derivation D which derives from a base Component B, the resolved
* Component D would have the Implementations of M plus the Implementations
* of D. (The Implementations of the base Component are not carried to the
* derived Component. This reflects .class generation in which each Component
* results in a .class and each reachable Implementation becomes a Java method
* within the .class that results from the Component which contains the
* Implementation.)
*
* @version 0.50, 12/16/97
* @version 1.00, 08/13/98
* @author Cameron Purdy
*/
public class Implementation
extends Trait
{
// ----- construction ---------------------------------------------------
/**
* Construct an Implementation. This is the "default" constructor.
*
* @param behavior the behavior that has this implementation
* @param sLang the script language identifier
* @param sScript the unicode script
*/
protected Implementation(Behavior behavior, String sLang, String sScript)
{
super(behavior, RESOLVED);
if (behavior == null)
{
throw new IllegalArgumentException(CLASS +
": Containing behavior required.");
}
if (sLang == null || sLang.length() == 0)
{
throw new IllegalArgumentException(CLASS +
": Language identifier required.");
}
if (sScript == null || sScript.length() == 0)
{
sScript = BLANK;
}
m_sLang = sLang;
m_sScript = sScript;
// origin is manual
setFromManual();
}
/**
* Construct a blank Implementation Trait. Implementations are never
* derived.
*
* @param base the base Implementation to derive from
* @param behavior the containing behavior
* @param nMode one of RESOLVED, MODIFICATION
*
* @see #getBlankDerivedTrait(Trait, int)
*/
protected Implementation(Implementation base, Behavior behavior, int nMode)
{
super(base, behavior, nMode);
// assertion: (remove after testing) mode is not derived
if (nMode == DERIVATION)
{
throw new IllegalArgumentException(CLASS +
": Invalid mode for blank Implementation construction (" + nMode + ")");
}
this.m_sLang = base.m_sLang;
this.m_sScript = base.m_sScript;
}
/**
* Copy constructor.
*
* @param behavior the Behavior containing the new Implementation
* @param that the Implementation to copy from
*/
protected Implementation(Behavior behavior, Implementation that)
{
super(behavior, that);
this.m_sLang = that.m_sLang;
this.m_sScript = that.m_sScript;
}
/**
* Construct an Implementation from a stream.
*
* This is a custom serialization implementation that is unrelated to the
* Serializable interface and the Java implementation of persistence.
*
* @param behavior the containing behavior
* @param stream the stream to read this Implementation from
* @param nVersion version of the data structure in the stream
*
* @exception IOException An IOException is thrown if an error occurs
* reading the Implementation from the stream or if the
* stream does not contain a valid Implementation
*/
protected Implementation(Behavior behavior, DataInput stream, int nVersion)
throws IOException
{
super(behavior, stream, nVersion);
m_sLang = readString(stream);
m_sScript = readString(stream);
}
/**
* 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 Implementation(Trait parent, XmlElement xml, int nVersion)
throws IOException
{
super(parent, xml, nVersion);
String sLang = readString(xml.getElement("language"));
if (sLang.length() == 0)
{
sLang = "java";
}
String sScript = readString(xml.getElement("script"));
m_sLang = sLang;
m_sScript = sScript;
}
// ----- persistence ----------------------------------------------------
/**
* Save the Implementation 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 Implementation to
*
* @exception IOException An IOException is thrown if an error occurs
* writing the Implementation to the stream
*/
protected synchronized void save(DataOutput stream)
throws IOException
{
super.save(stream);
stream.writeUTF(m_sLang );
stream.writeUTF(m_sScript);
}
/**
* 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
{
super.save(xml);
if (!equals(m_sLang, "java"))
{
xml.addElement("language").setString(m_sLang);
}
XmlElement xmlScript = xml.addElement("script");
// add a human-readable description attribute
Behavior bhvr = getBehavior();
Component cd = bhvr.getComponent();
String sDesc = cd.isGlobal() ? bhvr.getName() :
'$' + cd.getName() + '.' + bhvr.getName();
xmlScript.addAttribute("desc").setString(sDesc);
xmlScript.setString(m_sScript);
}
// ----- derivation/modification ----------------------------------------
/**
* Construct a blank Implementation from this base.
*
* @param parent the containing behavior
* @param nMode either RESOLVED or MODIFICATION
*
* @return a new blank derived trait of this trait's class with the
* specified parent and mode
*/
protected Trait getBlankDerivedTrait(Trait parent, int nMode)
{
return new Implementation(this, (Behavior) 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 Trait resolve(Trait traitDelta, Trait parent, Loader loader, ErrorList errlist)
throws ComponentException
{
Implementation base = this;
Implementation delta = (Implementation) resolveDelta(traitDelta, loader, errlist);
Implementation derived = (Implementation) super.resolve(delta, parent, loader, errlist);
// ignore the delta; implementations can be modified on at their
// declaration level
derived.m_sLang = base.m_sLang;
derived.m_sScript = base.m_sScript;
return derived;
}
/**
* Implementations are never asked to extract.
*/
protected int getExtractMode(Trait base)
{
throw new UnsupportedOperationException(CLASS + ".getExtractMode: "
+ "Implementations do not extract!");
}
/**
* Implementations are never asked to extract.
*/
protected Trait extract(Trait base, Trait parent, Loader loader, ErrorList errlist)
throws ComponentException
{
throw new UnsupportedOperationException(CLASS + ".extract: "
+ "Implementations do not extract!");
}
// ----- miscellaneous Trait methods ------------------------------------
/**
* Reset state, discarding all information. An implementation is invalid
* after being reset.
*/
protected synchronized void invalidate()
{
super.invalidate();
m_sLang = null;
m_sScript = 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()
{
// unfortunately there is no other unique identifier
// (implementations are identified by position, which can change)
return String.valueOf(getUID());
}
/**
* Determine the unique description for this trait.
*
* 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 + "[" + getPosition() + "] " + getUniqueName();
}
// ----- accessors ------------------------------------------------------
/**
* Determine the behavior which contains this Implementation.
*
* @return the behavior trait that contains this Implementation
*/
public Behavior getBehavior()
{
return (Behavior) getParentTrait();
}
/**
* Determine if the Implementation is modifiable in any way. An
* implementation is not modifiable if it is not from this modification
* level.
*
* @return true if the Implementation is modifiable, false otherwise
*/
public boolean isModifiable()
{
return isDeclaredAtThisLevel() && super.isModifiable();
}
/**
* Get position for this implementation.
*
* @return the implementation position, zero based.
*/
public int getPosition()
{
Behavior bhvr = getBehavior();
return bhvr == null ? -1 : bhvr.getImplementationPosition(this);
}
// ----- language
/**
* Access the implementation language identifier.
*
* @return the language identifier for the script
*/
public String getLanguage()
{
return m_sLang;
}
/**
* Determine if the implementation language can be set.
*
* @return true if the language identifier can be set
*/
public boolean isLanguageSettable()
{
return isModifiable();
}
/**
* Determine if the specified language is a legal implementation language
* identifier.
*
* @return true if the specified language identifier is legal
*/
public static boolean isLanguageLegal(String sLang)
{
return ClassHelper.isPartialNameLegal(sLang);
}
/**
* Set the implementation language.
*
* @param sLang the new language for the implementation
*/
public void setLanguage(String sLang)
throws PropertyVetoException
{
setLanguage(sLang, true);
}
/**
* Set the implementation language.
*
* @param sLang the new language for the implementation
* @param fVetoable true if the setter can veto the value
*/
protected synchronized void setLanguage(String sLang, boolean fVetoable)
throws PropertyVetoException
{
String sPrev = m_sLang;
if (sLang.equals(sPrev))
{
return;
}
if (fVetoable)
{
if (!isLanguageSettable())
{
readOnlyAttribute(ATTR_LANG, sPrev, sLang);
}
if (!isLanguageLegal(sLang))
{
illegalAttributeValue(ATTR_LANG, sPrev, sLang);
}
fireVetoableChange(ATTR_LANG, sPrev, sLang);
}
m_sLang = sLang;
firePropertyChange(ATTR_LANG, sPrev, sLang);
}
// ----- script
/**
* Access the implementation script.
*
* @return the script
*/
public String getScript()
{
return m_sScript;
}
/**
* Determine if the implementation script can be set.
*
* @return true if the script can be set
*/
public boolean isScriptSettable()
{
return isModifiable();
}
/**
* Determine if the specified script is a legal script. This does not
* check syntax. Currently, all scripts are considered legal.
*
* @return true if the script is legal
*/
public static boolean isScriptLegal(String sScript)
{
return sScript != null;
}
/**
* Set the implementation script.
*
* @param sScript the new script for the implementation
*/
public void setScript(String sScript)
throws PropertyVetoException
{
setScript(sScript, true);
}
/**
* Set the implementation script.
*
* @param sScript the new script for the implementation
* @param fVetoable true if the setter can veto the value
*/
protected synchronized void setScript(String sScript, boolean fVetoable)
throws PropertyVetoException
{
String sPrev = m_sScript;
if (sScript.equals(sPrev))
{
return;
}
if (fVetoable)
{
if (!isScriptSettable())
{
readOnlyAttribute(ATTR_SCRIPT, sPrev, sScript);
}
if (!isScriptLegal(sScript))
{
illegalAttributeValue(ATTR_SCRIPT, sPrev, sScript);
}
fireVetoableChange(ATTR_SCRIPT, sPrev, sScript);
}
m_sScript = sScript;
firePropertyChange(ATTR_SCRIPT, sPrev, sScript);
}
// ----- Object methods -------------------------------------------------
/**
* Compare this Implementation to another Object for equality.
*
* @param obj the other Object to compare to this
*
* @return true if this Implementation equals that Object
*/
public boolean equals(Object obj)
{
if (obj instanceof Implementation)
{
Implementation that = (Implementation) obj;
return this == that
|| this.m_sLang .equals(that.m_sLang )
&& this.m_sScript.equals(that.m_sScript)
&& super.equals(that);
}
return false;
}
/**
* Provide a human-readable description of the Implementation.
*
* @return a string describing the Implementation
*/
public String toString()
{
return getUniqueDescription() + " (" + m_sLang + ")";
}
// ----- debugging ------------------------------------------------------
/**
* Provide the entire set of trait 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)
{
out.print(sIndent + "Implementation language=" + m_sLang + ", script=");
if (m_sScript == null)
{
out.println("");
}
else if (m_sScript == BLANK)
{
out.println("");
}
else
{
String sIndentScript = nextIndent(sIndent);
out.println();
out.println(sIndentScript + "{");
out.println(indentString(m_sScript, sIndentScript));
out.println(sIndentScript + "}");
}
super.dump(out, sIndent);
}
// ----- public constants ----------------------------------------------
/**
* The Language attribute.
*/
public static final String ATTR_LANG = "Language";
/**
* The Script attribute.
*/
public static final String ATTR_SCRIPT = "Script";
// ----- data members ---------------------------------------------------
/**
* The name of this class.
*/
private static final String CLASS = "Implementation";
/**
* The Implementation's descriptor string.
*/
protected static final String DESCRIPTOR = "Script";
/**
* The Implementation's scripting language identifier.
*/
private String m_sLang;
/**
* The Implementation's script.
*/
private String m_sScript;
}