/*
* A property adapter that is used by the PropertyTokenSolver.
*
* Below is the copyright agreement for the Ptolemy II system.
*
* 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.ArrayList;
import java.util.Iterator;
import java.util.List;
import ptolemy.actor.IOPort;
import ptolemy.actor.Receiver;
import ptolemy.actor.parameters.PortParameter;
import ptolemy.data.properties.ParseTreeAnnotationEvaluator;
import ptolemy.data.properties.PropertyHelper;
import ptolemy.kernel.CompositeEntity;
import ptolemy.kernel.Entity;
import ptolemy.kernel.Port;
import ptolemy.kernel.util.Attribute;
import ptolemy.kernel.util.IllegalActionException;
import ptolemy.kernel.util.InvalidStateException;
import ptolemy.kernel.util.KernelException;
/**
* A property adapter that is used by the PropertyTokenSolver.
*
* @author Man-Kit Leung
* @version $Id$
* @since Ptolemy II 7.1
* @Pt.ProposedRating Red (mankit)
* @Pt.AcceptedRating Red (mankit)
*/
public class PropertyTokenHelper extends PropertyHelper {
public PropertyTokenHelper(PropertyTokenSolver solver, Object component) {
setComponent(component);
_solver = solver;
}
public PropertyTokenSolver getSolver() {
return (PropertyTokenSolver) _solver;
}
public void addListener(boolean listenInputs, boolean listenOutputs)
throws IllegalActionException {
Iterator propertyables = getPropertyables().iterator();
while (propertyables.hasNext()) {
Object propertyable = propertyables.next();
if (propertyable instanceof IOPort) {
IOPort port = (IOPort) propertyable;
if (listenOutputs && port.isOutput()) {
port.addIOPortEventListener(getSolver().getSentListener());
}
if (listenInputs && port.isInput()) {
port.addIOPortEventListener(getSolver().getGotListener());
}
}
}
}
public void removeListener(boolean listenInputs, boolean listenOutputs)
throws IllegalActionException {
Iterator propertyables = getPropertyables().iterator();
while (propertyables.hasNext()) {
Object propertyable = propertyables.next();
if (propertyable instanceof IOPort) {
IOPort port = (IOPort) propertyable;
if (listenOutputs && port.isOutput()) {
port.removeIOPortEventListener(getSolver()
.getSentListener());
}
if (listenInputs && port.isInput()) {
port
.removeIOPortEventListener(getSolver()
.getGotListener());
}
}
}
}
public void determineProperty() throws IllegalActionException,
KernelException {
// determine ASTNodeHelpers
List<IOPort> inputPortList = new ArrayList<IOPort>();
List<IOPort> outputPortList = new ArrayList<IOPort>();
List<Attribute> attributeList = new ArrayList<Attribute>();
// separate propertyables
Iterator propertyableIterator = getPropertyables().iterator();
while (propertyableIterator.hasNext()) {
Object propertyable = propertyableIterator.next();
if (propertyable instanceof IOPort) {
IOPort port = (IOPort) propertyable;
// treat InOut ports as Out ports
if (port.isInput() && !port.isOutput()) {
inputPortList.add(port);
} else {
outputPortList.add(port);
}
// } else if ((propertyable instanceof Attribute) && (!((propertyable instanceof StringAttribute)))) {
} else if (propertyable instanceof Attribute
|| propertyable instanceof PortParameter) {
attributeList.add((Attribute) propertyable);
} else {
//FIXME: throw exception?
}
}
// extract ASTHelpers from adapterlist
List<PropertyTokenASTNodeHelper> ASTHelperList = new ArrayList<PropertyTokenASTNodeHelper>();
List<PropertyHelper> adapterList = new ArrayList<PropertyHelper>();
adapterList.addAll(_getSubHelpers());
Iterator adapters = adapterList.iterator();
while (adapters.hasNext()) {
PropertyHelper adapter = (PropertyHelper) adapters.next();
if (adapter instanceof PropertyTokenASTNodeHelper) {
ASTHelperList.add((PropertyTokenASTNodeHelper) adapter);
}
}
// determine inputPorts first, ASTNodes may depend on it
_determineInputPorts(inputPortList);
// determine Attributes
_determineAttributes(attributeList, ASTHelperList);
_determineRefinement();
// determine all subadapters except attribute adapters
adapters = adapterList.iterator();
while (adapters.hasNext()) {
PropertyTokenHelper adapter = (PropertyTokenHelper) adapters.next();
if (!ASTHelperList.contains(adapter)) {
adapter.determineProperty();
}
}
// determine outputPorts last, may depend on inports and outports
_determineOutputPorts(outputPortList);
}
public void setEquals(Object object, PropertyToken property) {
if (!_solver.isSettable(object)) {
return;
}
super.setEquals(object, property);
if (property != null) {
getSolver().putToken(object, property.getToken());
}
}
private boolean useChannel = false;
/**
* Return a list of property-able NamedObj contained by the component. All
* ports and parameters are considered property-able.
* @return The list of property-able named object.
* @exception IllegalActionException
*/
public List<Object> getPropertyables() throws IllegalActionException {
List<Object> list = new ArrayList<Object>();
// Add all channels.
if (!useChannel) {
list.addAll(((Entity) getComponent()).portList());
} else {
for (IOPort port : (List<IOPort>) ((Entity) getComponent())
.portList()) {
for (int i = 0; i < port.getWidth(); i++) {
list.add(new Channel(port, i));
}
}
}
// Add attributes.
// if (!getSolver().isListening()) {
list.addAll(_getPropertyableAttributes());
// }
return list;
}
protected ParseTreeAnnotationEvaluator _annotationEvaluator() {
return new ParseTreeTokenAnnotationEvaluator();
}
protected List<PropertyHelper> _getSubHelpers()
throws IllegalActionException {
// if (!getSolver().isListening()) {
return _getASTNodeHelpers();
// } else {
// return new LinkedList<PropertyHelper>();
// }
}
protected List<IOPort> _getInnerSourcePortList(IOPort port) {
List<IOPort> result = new ArrayList<IOPort>();
Iterator iterator = port.deepInsidePortList().iterator();
while (iterator.hasNext()) {
IOPort connectedPort = (IOPort) iterator.next();
boolean isInput = connectedPort.isInput();
boolean isCompositeInput = connectedPort.getContainer() instanceof CompositeEntity
&& isInput
&& port.depthInHierarchy() > connectedPort
.depthInHierarchy();
if (isInput && !isCompositeInput) {
result.add(connectedPort);
}
}
return result;
}
// FIXME: RENAME? get ports from inside the actors connected to outPort
// move to use case?
protected List<IOPort> _getInnerSinkPortList(IOPort port) {
List<IOPort> result = new ArrayList<IOPort>();
Iterator iterator = port.deepInsidePortList().iterator();
while (iterator.hasNext()) {
IOPort connectedPort = (IOPort) iterator.next();
boolean isInput = connectedPort.isInput();
boolean isCompositeOutput = connectedPort.getContainer() instanceof CompositeEntity
&& isInput
&& port.depthInHierarchy() > connectedPort
.depthInHierarchy();
if (!isInput && !isCompositeOutput) {
result.add(connectedPort);
}
}
return result;
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
protected List<Channel> _getInnerSourceChannelList(IOPort port) {
List<Channel> result = new ArrayList<Channel>();
return result;
}
protected List<Channel> _getInnerSinkChannelList(IOPort port)
throws InvalidStateException, IllegalActionException {
List<Channel> result = new ArrayList<Channel>();
Receiver[][] receivers = port.deepGetReceivers();
for (Receiver[] element : receivers) {
for (Receiver element2 : element) {
IOPort sinkPort = element2.getContainer();
result.add(new Channel(sinkPort, _getChannelNumber(element2,
sinkPort)));
}
}
return result;
}
private int _getChannelNumber(Receiver receiver, IOPort port) {
Receiver[][] receivers = port.getReceivers();
for (int i = 0; i < receivers.length; i++) {
assert receivers[i].length != 1;
if (receiver == receivers[i][0]) {
return i;
}
}
return -1;
}
protected List<Channel> _getSinkChannelList(IOPort port) {
List<Channel> result = new ArrayList<Channel>();
Receiver[][] receivers = port.getReceivers();
for (Receiver[] element : receivers) {
for (Receiver element2 : element) {
IOPort sinkPort = element2.getContainer();
result.add(new Channel(sinkPort, _getChannelNumber(element2,
sinkPort)));
}
}
return result;
}
///////////////////////////////////////////////////////////////////////////
protected List<Port> _getDeepSinkPortList(IOPort port) {
List<Port> result = new ArrayList<Port>();
Iterator iterator = port.deepConnectedPortList().iterator();
while (iterator.hasNext()) {
IOPort connectedPort = (IOPort) iterator.next();
boolean isInput = connectedPort.isInput();
boolean isCompositeOutput = connectedPort.getContainer() instanceof CompositeEntity
&& !isInput
&& port.depthInHierarchy() > connectedPort
.depthInHierarchy();
if (isInput || isCompositeOutput) {
result.add(connectedPort);
}
}
return result;
}
protected List<Port> _getDeepSourcePortList(IOPort port) {
List<Port> result = new ArrayList<Port>();
Iterator iterator = port.deepConnectedPortList().iterator();
while (iterator.hasNext()) {
IOPort connectedPort = (IOPort) iterator.next();
boolean isInput = connectedPort.isInput();
boolean isCompositeInput = connectedPort.getContainer() instanceof CompositeEntity
&& isInput
&& port.depthInHierarchy() > connectedPort
.depthInHierarchy();
if (!isInput || isCompositeInput) {
result.add(connectedPort);
}
}
return result;
}
protected void _determineInputPorts(List<IOPort> inputPortList)
throws IllegalActionException {
// do nothing in base class
}
protected void _determineOutputPorts(List<IOPort> outputPortList)
throws IllegalActionException {
// do nothing in base class
}
protected void _determineAttributes(List<Attribute> attributeList,
List<PropertyTokenASTNodeHelper> ASTNodeHelperList)
throws KernelException {
Iterator ASTNodeHelperIterator = ASTNodeHelperList.iterator();
while (ASTNodeHelperIterator.hasNext()) {
PropertyTokenASTNodeHelper ASTNodeHelper = (PropertyTokenASTNodeHelper) ASTNodeHelperIterator
.next();
ASTNodeHelper.determineProperty();
ASTNodeHelper.determineProperty(attributeList);
}
}
protected void _determineRefinement() throws IllegalActionException,
KernelException {
// do nothing in base class
}
}