/*
* A property solver that annotates the model with data tokens.
*
* Copyright (c) 2008-2009 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.
*/
package ptolemy.data.properties.token;
import java.util.HashMap;
import java.util.Map;
import ptolemy.actor.Actor;
import ptolemy.actor.Manager;
import ptolemy.actor.TypedCompositeActor;
import ptolemy.data.IntToken;
import ptolemy.data.Token;
import ptolemy.data.expr.Parameter;
import ptolemy.data.expr.StringParameter;
import ptolemy.data.properties.Property;
import ptolemy.data.properties.PropertyHelper;
import ptolemy.data.properties.PropertySolver;
import ptolemy.data.properties.gui.PropertySolverGUIFactory;
import ptolemy.data.properties.token.firstValueToken.FirstTokenGotListener;
import ptolemy.data.properties.token.firstValueToken.FirstTokenSentListener;
import ptolemy.domains.fsm.kernel.FSMActor;
import ptolemy.domains.fsm.kernel.FSMDirector;
import ptolemy.kernel.util.IllegalActionException;
import ptolemy.kernel.util.KernelException;
import ptolemy.kernel.util.NameDuplicationException;
import ptolemy.kernel.util.NamedObj;
/**
* A property solver that annotates the model with data tokens.
*
* @author Man-Kit Leung
* @version $Id$
* @since Ptolemy II 7.1
* @Pt.ProposedRating Red (mankit)
* @Pt.AcceptedRating Red (mankit)
*/
public class PropertyTokenSolver extends PropertySolver {
/**
* Construct a PropertySolver with the specified container and name.
* @param container The specified container.
* @param name The specified name.
* @exception IllegalActionException If the PropertySolver is not of an
* acceptable attribute for the container.
* @exception NameDuplicationException If the name coincides with an
* attribute already in the container.
*/
public PropertyTokenSolver(NamedObj container, String name)
throws IllegalActionException, NameDuplicationException {
super(container, name);
useCase = new StringParameter(this, "portValue");
useCase.setExpression("firstValueToken");
listeningMethod = new StringParameter(this, "listeningMethod");
listeningMethod.setExpression("Input & Output Ports");
numberIterations = new Parameter(this, "numberIterations");
numberIterations.setExpression("1");
_attachText("_iconDescription", "<svg>\n"
+ "<rect x=\"-50\" y=\"-20\" width=\"115\" height=\"40\" "
+ "style=\"fill:yellow\"/>" + "<text x=\"-40\" y=\"-5\" "
+ "style=\"font-size:12; font-family:SansSerif; fill:black\">"
+ "Double click to\nResolve Property.</text></svg>");
new PropertySolverGUIFactory(this, "_portValueSolverGUIFactory");
_addChoices();
}
///////////////////////////////////////////////////////////////////
//// public variables ////
/** The name of the use case. This default value is the string
* "portValue".
*/
public StringParameter useCase;
/** The listening method. The default value is the string
* "Input & Output Ports".
*/
public StringParameter listeningMethod;
/** The number of interations. The default value is an integer
* with value 1.
*/
public Parameter numberIterations;
///////////////////////////////////////////////////////////////////
//// public methods ////
/** Return the extended use case name.
* @return the string "token::" followed by the value of the useCase
* parameter.
*/
public String getExtendedUseCaseName() {
return "token::" + getUseCaseName();
}
/** Return the got token listener.
* @return the got token listener.
*/
public FirstTokenGotListener getGotListener() {
return _gotListener;
}
/**
* Return the adapter that contains property information for the given
* object.
* @param object The given object.
* @return The associated property constraint adapter.
*/
public PropertyHelper getHelper(Object object)
throws IllegalActionException {
return _getHelper(object);
}
/** Return the value of the listeningMethod expression.
* @return the value of the listeningMethod expression.
*/
public String getListening() {
// FIXME: this should be called getListeningMethod
return listeningMethod.getExpression();
}
/**
* Return the property value associated with the specified object.
* @param object The specified object.
* @return The property of the specified object.
*/
public Property getProperty(Object object) {
Property result;
// if (object instanceof PortParameter) {
// result = getProperty(((PortParameter)object).getPort());
// } else {
result = super.getProperty(object);
// }
return result == null ? new PropertyToken(Token.NIL) : result;
}
/** Return the got token listener.
* @return the got token listener.
*/
public FirstTokenSentListener getSentListener() {
return _sentListener;
}
/** Return the token that corresponds with the object.
* @param object The object.
* @return the token.
* @see #putToken(Object, Token)
*/
public Token getToken(Object object) {
return _tokenMap.get(object);
}
/**
* Return the name of the use case.
* @return The name of the use case.
*/
public String getUseCaseName() {
return useCase.getExpression();
}
/**
* Return true if this solver is listening.
* @return true if the value of listeningMessage is
* not equal to "NONE".
*/
public Boolean isListening() {
return !getListening().equalsIgnoreCase("NONE");
}
/**
* Put a token and object pair into the token map.
* @param object The object key.
* @param token The token value.
* @see #getToken(Object)
*/
public void putToken(Object object, Token token) {
// FIXME: this should be called setToken()
_tokenMap.put(object, token);
}
/** Reset the solver and clear the token map.
*/
public void reset() {
super.reset();
_clearTokenMap();
}
///////////////////////////////////////////////////////////////////
//// protected methods ////
/*
* Resolve the property values for the specified top-level entity by
* running the model.
* @param analyzer The specified model analyzer.
* @exception IllegalActionException Not thrown in this base class.
*/
protected void _resolveProperties(NamedObj analyzer) throws KernelException {
NamedObj toplevel = _toplevel();
PropertyTokenCompositeHelper topLevelHelper = (PropertyTokenCompositeHelper) _getHelper(toplevel);
super._resolveProperties(analyzer);
topLevelHelper.reinitialize();
// run model
if (!getListening().equals("NONE")) {
topLevelHelper.addListener(getListening().contains("Input"),
getListening().contains("Output"));
// run simulation
Manager manager = new Manager(toplevel.workspace(),
"PortValueManager");
if (toplevel instanceof TypedCompositeActor) {
((TypedCompositeActor) toplevel).setManager(manager);
} else if (toplevel instanceof FSMActor) {
TypedCompositeActor compositeActor = new TypedCompositeActor(
workspace());
FSMDirector fsmDirector = new FSMDirector(workspace());
compositeActor.setDirector(fsmDirector);
((FSMActor) toplevel).setContainer(compositeActor);
compositeActor.setManager(manager);
((FSMActor) toplevel).setContainer(null);
} else {
throw new IllegalActionException(
"Not able to fire this type of toplevel actor ("
+ toplevel + ").");
}
manager.preinitializeAndResolveTypes();
((Actor) toplevel).initialize();
((Actor) toplevel).iterate(((IntToken) numberIterations.getToken())
.intValue());
((Actor) toplevel).wrapup();
//FIXME: stoping the manager conflicts with extendedFirstListener. No iterations can be done there.
// ((Actor) topLevel).stop();
manager.wrapup();
manager.finish();
manager.stop();
topLevelHelper.removeListener(getListening().contains("Input"),
getListening().contains("Output"));
}
topLevelHelper.determineProperty();
}
/**
* Add choices to the parameters.
* @exception IllegalActionException If there is a problem accessing files
* or parameters.
*/
private void _addChoices() throws IllegalActionException {
// Add all the subdirectories in token/ directory as
// choices. Directories named "CVS" and ".svn" are skipped.
_addChoices(useCase, "$CLASSPATH/ptolemy/data/properties/token");
listeningMethod.addChoice("NONE");
listeningMethod.addChoice("Input & Output Ports");
listeningMethod.addChoice("Input Ports");
listeningMethod.addChoice("Output Ports");
}
///////////////////////////////////////////////////////////////////
//// private methods ////
/** Clear the token map. */
private void _clearTokenMap() {
_tokenMap.clear();
}
///////////////////////////////////////////////////////////////////
//// private variables ////
private final FirstTokenSentListener _sentListener = new FirstTokenSentListener(
this);
private final FirstTokenGotListener _gotListener = new FirstTokenGotListener(
this);
private final Map<Object, Token> _tokenMap = new HashMap<Object, Token>();
}