/* The base abstract class for an ontology solver.
Copyright (c) 2008-2014 The Regents of the University of California.
All rights reserved.
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the above
copyright notice and the following two paragraphs appear in all copies
of this software.
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.
PT_COPYRIGHT_VERSION_2
COPYRIGHTENDKEY
*/
package ptolemy.data.ontologies;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import ptolemy.actor.IOPort;
import ptolemy.actor.parameters.SharedParameter;
import ptolemy.data.ObjectToken;
import ptolemy.data.RecordToken;
import ptolemy.data.Token;
import ptolemy.data.expr.ASTPtRootNode;
import ptolemy.data.expr.Constants;
import ptolemy.data.expr.Node;
import ptolemy.data.expr.PtParser;
import ptolemy.data.expr.Variable;
import ptolemy.domains.modal.kernel.Configurer;
import ptolemy.kernel.CompositeEntity;
import ptolemy.kernel.util.Attribute;
import ptolemy.kernel.util.IllegalActionException;
import ptolemy.kernel.util.NameDuplicationException;
import ptolemy.kernel.util.NamedObj;
import ptolemy.kernel.util.Settable;
import ptolemy.kernel.util.Workspace;
import ptolemy.moml.MoMLModelAttribute;
///////////////////////////////////////////////////////////////////
////OntologySolverBase
/**
The base abstract class for an ontology solver.
The base class provides the core functionality for ontology
solver resolution. It provides a method to create an OntologyAdapter for any
given model component. The model component can be an object of any
Ptolemy class (e.g. ASTPtRootNode, Sink, Entity, and FSMActor). A
model component, in turn, may have one or multiple objects to which
ontology concepts can be attached.
Subclasses needs to implement {@link #resolveConcepts()}
to specify exactly how to perform the ontology concept resolution. For example,
one may gather all the constraints from the OntologyAdapters and feed them
into a constraint solver.
Every OntologySolver is linked together by the SharedParameter called
"ontologySolverUtilitiesWrapper", which contains the shared utility object.
This allows every OntologySolver to find other solvers in the model.
@author Man-Kit Leung
@version $Id: OntologySolverBase.java 70402 2014-10-23 00:52:20Z cxh $
@since Ptolemy II 10.0
@Pt.ProposedRating Red (mankit)
@Pt.AcceptedRating Red (mankit)
*/
public abstract class OntologySolverBase extends MoMLModelAttribute {
/**
* Construct an OntologySolverBase with the specified container and
* name. If this is the first OntologySolver created in the model,
* the shared utility object will also be created.
*
* @param container The specified container.
* @param name The specified name.
* @exception IllegalActionException If the OntologySolverBase is
* not of an acceptable attribute for the container.
* @exception NameDuplicationException If the name coincides with an
* attribute already in the container.
*/
public OntologySolverBase(NamedObj container, String name)
throws IllegalActionException, NameDuplicationException {
super(container, name);
ontologySolverUtilitiesWrapper = new SharedParameter(this,
"ontologySolverUtilitiesWrapper", OntologySolver.class);
ontologySolverUtilitiesWrapper.setPersistent(false);
ontologySolverUtilitiesWrapper.setVisibility(Settable.NONE);
// **We can only create a new shared utilities object
// only once per model.
if (ontologySolverUtilitiesWrapper.getExpression().length() == 0) {
ontologySolverUtilitiesWrapper.setToken(new ObjectToken(
new OntologySolverUtilities()));
}
Collection parameters = ontologySolverUtilitiesWrapper
.sharedParameterSet();
for (SharedParameter parameter : parameters) {
parameters = parameter.sharedParameterSet();
}
_ontologySolverUtilities = (OntologySolverUtilities) ((ObjectToken) ontologySolverUtilitiesWrapper
.getToken()).getValue();
}
///////////////////////////////////////////////////////////////////
//// ports and parameters ////
/**
* The shared parameter that links together every solver in the
* same model.
*/
public SharedParameter ontologySolverUtilitiesWrapper;
///////////////////////////////////////////////////////////////////
//// public methods ////
/**
* Clear the resolved property for the specified object. The
* object is assumed to be property-able; otherwise, nothing
* happens.
*
* @param object The specified object.
*/
public void clearResolvedConcept(Object object) {
_resolvedProperties.remove(object);
}
/** Traverse the list of constants and remove any ConceptTokens
* that may have been added by MonotonicyConceptFunction.
* @see ptolemy.data.ontologies.lattice.adapters.monotonicityAnalysis.MonotonicityConceptFunction
*/
public static void cleanConstants() {
RecordToken constants = Constants.constants();
//System.out.println("OntologySolverBase: Constants: " + constants);
Set labels = constants.labelSet();
for (String label : labels) {
Token token = constants.get(label);
if (token instanceof ConceptToken) {
//System.out.println("Found " + token + " Removing " + label);
Constants.remove(label);
}
}
//System.out.println("OntologySolverBase: Constants after cleaning: " + Constants.constants());
}
/** Clone the object into the specified workspace.
* @param workspace The workspace for the new object.
* @return A new NamedObj.
* @exception CloneNotSupportedException If any of the attributes
* cannot be cloned.
*/
@Override
public Object clone(Workspace workspace) throws CloneNotSupportedException {
OntologySolverBase newObject = (OntologySolverBase) super
.clone(workspace);
newObject._ontologySolverUtilities = null;
newObject.reset();
return newObject;
}
/**
* Return the list of all PropertyAdapters associated with this
* ontology solver.
*
* @return The list of PropertyAdapters.
* @exception IllegalActionException If there is an exception from getting
* all the subAdapters.
*/
public List getAllAdapters() throws IllegalActionException {
NamedObj topLevel = _toplevel();
List result = new LinkedList();
List subAdapters = new LinkedList();
result.add(getAdapter(topLevel));
subAdapters.add(getAdapter(topLevel));
while (!subAdapters.isEmpty()) {
OntologyAdapter adapter = subAdapters.remove(0);
subAdapters.addAll(adapter._getSubAdapters());
result.add(adapter);
}
return result;
}
/** Return the subset of all concept-able objects that are NamedObjs.
*
* @return The set of all concept-able NamedObjs.
* @exception IllegalActionException Thrown if
* an error occurs when getting the adapters or the concept-able
* objects from them.
*/
public Set getAllConceptableNamedObjs()
throws IllegalActionException {
Set result = new HashSet();
for (Object conceptable : getAllPropertyables()) {
if (conceptable instanceof NamedObj) {
result.add((NamedObj) conceptable);
}
}
return result;
}
/**
* Return the set of all property-able objects obtained from
* all PropertyAdapter.
*
* @return The set of all property-able objects.
* @exception IllegalActionException Thrown if
* an error occurs when getting the adapters or the property-able
* objects from them.
*/
public Set getAllPropertyables() throws IllegalActionException {
HashSet result = new HashSet();
for (OntologyAdapter adapter : getAllAdapters()) {
result.addAll(adapter.getPropertyables());
}
return result;
}
/**
* Return the list of all solvers that are in the same model. They
* are linked by the specified SharedParameter.
*
* @param sharedParameter The specified SharedParameter links
* together the solvers.
* @return A list of PropertySolvers.
*/
public static List getAllSolvers(
SharedParameter sharedParameter) {
List parameters = new ArrayList(
sharedParameter.sharedParameterSet());
List solvers = new LinkedList();
for (NamedObj parameter : parameters) {
Object container = parameter.getContainer();
if (container instanceof OntologySolver) {
solvers.add((OntologySolver) container);
}
}
return solvers;
}
/**
* Get the attribute that corresponds to the specified
* ASTPtRootNode. This assumes that the correspondence is recorded
* previously through calling
* {@link ptolemy.data.ontologies.OntologySolverUtilities#putAttribute(ASTPtRootNode, Attribute)}.
*
* @param node The specified ASTPtRootNode.
* @return The attribute associated with the specified ASTPtRootNode.
* @exception AssertionError Thrown if the specified node does not
* have a corresponding attribute.
*/
public Attribute getAttribute(ASTPtRootNode node) {
Node root = node;
Map attributes = getOntologySolverUtilities()
.getAttributes();
while (root.jjtGetParent() != null) {
if (attributes.containsKey(root)) {
return attributes.get(root);
}
root = root.jjtGetParent();
}
if (!attributes.containsKey(root)) {
throw new AssertionError(node.toString()
+ " does not have a corresponding attribute.");
}
return attributes.get(root);
}
/**
* Return the property adapter for the specified component.
*
* @param object The specified component.
* @return The property adapter for the component.
* @exception IllegalActionException Thrown if the adapter cannot
* be found or instantiated.
*/
public OntologyAdapter getAdapter(Object object)
throws IllegalActionException {
return _getAdapter(object, this);
}
/** Return a list of all the ontologies contained in this solver.
* If it contains no ontologies, then return an empty list.
* @return A list containing all ontologies in this solver.
*/
public List getAllContainedOntologies() {
NamedObj containedModel = getContainedModel();
if (containedModel instanceof CompositeEntity) {
return ((CompositeEntity) containedModel)
.entityList(Ontology.class);
}
return new LinkedList();
}
/** Return the ontology for this constraint solver.
* If this solver contains more than one ontology, then return the
* last one added. If it contains no ontologies, then return null.
* @return The ontology for this constraint solver.
* @exception IllegalActionException If the structure is not a lattice.
*/
public Ontology getOntology() throws IllegalActionException {
List ontologies = getAllContainedOntologies();
if (ontologies.size() > 0) {
return ontologies.get(ontologies.size() - 1);
}
return null;
}
/**
* Return the expression parser.
*
* @return The expression parser.
*/
public PtParser getParser() {
if (_parser == null) {
OntologySolverBase.cleanConstants();
_parser = new PtParser();
}
return _parser;
}
/** Return the root ASTPtRootNode associated with the specified
* attribute.
*
* @param attribute The specified attribute.
* @return The root ASTPtRootNode associated with the specified
* attribute.
* @exception IllegalActionException Thrown if there is a problem getting
* the parse tree.
*/
// FIXME: Why is this here? It does not seem to belong...
public ASTPtRootNode getParseTree(Attribute attribute)
throws IllegalActionException {
Map parseTrees = getOntologySolverUtilities()
.getParseTrees();
if (!parseTrees.containsKey(attribute)) {
String expression = null;
if (attribute instanceof Settable) {
expression = ((Settable) attribute).getExpression().trim();
}
if (expression == null || expression.length() == 0) {
return null;
}
ASTPtRootNode parseTree;
// if ((attribute instanceof StringAttribute) ||
// ((attribute instanceof Variable
// && ((Variable) attribute).isStringMode()))) {
if (attribute instanceof Variable
&& ((Variable) attribute).isStringMode()) {
parseTree = getParser().generateStringParseTree(expression);
} else {
parseTree = getParser().generateParseTree(expression);
}
parseTrees.put(attribute, parseTree);
getOntologySolverUtilities().putAttribute(parseTree, attribute);
}
return parseTrees.get(attribute);
}
/** Return the concept value associated with the specified object.
* @param object The specified object.
* @return The property of the specified object.
* @see #setConcept(Object, Concept)
*/
public Concept getConcept(Object object) {
return _resolvedProperties.get(object);
}
/** Return the shared utility object.
* @return The shared utility object.
* @see #setOntologySolverUtilities
*/
public OntologySolverUtilities getOntologySolverUtilities() {
return _ontologySolverUtilities;
}
/**
* Initialize the solver. In the base class, only calls reset().
* Subclasses can add functionality.
* @exception IllegalActionException Thrown if there is a problem
* initializing the solver.
*/
public void initialize() throws IllegalActionException {
reset();
}
/**
* Mark the property of the specified object as non-settable. The
* specified object has a fixed assigned property.
* @param object The specified object.
*/
public void markAsNonSettable(Object object) {
_nonSettables.add(object);
}
/**
* Reset the solver.
*/
public void reset() {
_resolvedProperties = new HashMap