/**
* The base class for a an element in a property lattice.
*
* Copyright (c) 2007-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.
*
* PT_COPYRIGHT_VERSION_2 COPYRIGHTENDKEY
*
*
*/
package ptolemy.data.properties.lattice;
import ptolemy.data.properties.Property;
import ptolemy.graph.CPO;
import ptolemy.graph.InequalityTerm;
import ptolemy.kernel.util.IllegalActionException;
//////////////////////////////////////////////////////////////////////////
//// LatticeProperty
/**
* A base class representing a lattice property. A lattice property is a element
* in a property lattice. The user should create new sub-classes to represent
* different elements in a property lattice, see
* {@link ptolemy.data.properties.lattice.PropertyLattice}.
*
* @author Thomas Mandl, Man-Kit Leung, Edward A. Lee
* @version $Id$
* @since Ptolemy II 7.1
* @Pt.ProposedRating Red (mankit)
* @Pt.AcceptedRating Red (mankit)
*/
public class LatticeProperty extends Property implements PropertyTerm, Cloneable {
// FIXME: There is no reason that for this to have to be
// subclassed at all to create a lattice. Instead, we should have
// either constructor arguments or getter and setter methods for
// the key fields (depending on whether we want these fields to be
// immutable).
/**
* Create a new lattice property associated with the given lattice.
* @param lattice The given lattice.
*/
public LatticeProperty(PropertyLattice lattice) {
// FIXME: This constructors does not specify a name, which causes
// toString() to use the classname as the name. This seems wrong.
// For one thing, if you use this constructor, equals() will
// throw a null-pointer exception!
_lattice = lattice;
}
/**
* Create a new lattice property with the specified name and the specified
* lattice.
* @param lattice The specified lattice where this property resides.
* @param name The specified name for the property.
*/
public LatticeProperty(PropertyLattice lattice, String name) {
super(name);
_lattice = lattice;
}
/**
* Return this LatticeProperty.
* @return The clone.
* @exception CloneNotSupportedException Not thrown in this base class.
*/
public Object clone() throws CloneNotSupportedException {
// FIXME: The clone() method returns this. This is only
// correct if the object and all instances of subclasses are
// immutable. This seems extremely unlikely in a class that
// has an isConstant() method.
//
// cloning was an issue when we combined the property system
// with model transformation. We got it to run somehow,
// but unfortunately I don't remember the details. It's
// definitely something we did not understand in full detail,
// so some refactoring may be good. In my opinion the
// refactored code needs to be tested along with the model
// transformation.
return this;
}
/**
* Return true if the given object is equal to this lattice property. Two
* lattice properties are considered equal if they have the same name and
* are from the same lattice.
*
* Any instantiated LatticeProperty objects should use the
* LatticeProperty(Lattice lattice, String name) constructor so that
* the LatticeProperty's _name member is set to a value.
* Any subclasses of LatticeProperty should call this constructor in their
* constructor so that the property's _name is set correctly.
* If this is not done, then _name will be set to the empty string and
* will not have the correct value needed when the equals() method tests for
* equality between two LatticeProperty objects.
*/
public boolean equals(Object object) {
// FIXME: The equals() method compares names (which seems questionable,
// why is this right?). Even if this this is right,
// there is no corresponding hashcode() method, so if instances
// are put into hashed data structures, we will get chaos.
//
// The equals() implementation probably has to do with the
// reset mechanism. Every time we start the solver, new
// instances of the classes are created. Hence, comparison on
// the id's does not match.
if (object != null) {
if (object instanceof LatticeProperty) {
if (_name.equals(((LatticeProperty) object)._name)) {
return _lattice.getName().equals(
((LatticeProperty) object)._lattice.getName());
}
}
}
return false;
}
/**
* Return the associated object of this property term. By default, a lattice
* property is a constant property term. It has no associated object. This
* method returns null.
* @return Null.
*/
public Object getAssociatedObject() {
return null;
}
/**
* Return an array of constants contained in this term. By default, a
* lattice property is a constant property term. Return a size-1 array which
* contains this property.
*/
public InequalityTerm[] getConstants() {
return new InequalityTerm[] {
this
};
}
/**
* Get the property lattice associated with this property.
* @return The associated property lattice.
*/
public PropertyLattice getPropertyLattice() {
return _lattice;
}
/**
* Return the value of the property term. Return this property.
* @return This property.
*/
public Object getValue() {
return this;
}
/**
* Return an array of constants contained in this term. Return an array of
* zero length.
* @return An empty array.
*/
public InequalityTerm[] getVariables() {
return new InequalityTerm[0];
}
// FIXME: Having a hashCode method() causes lots of tests to fail?
// why?
// /** Return a hash code value for this LatticeProperty.
// * This method returns the hashCode of the {@link #_lattice}.
// * @return A hash code value for this LatticeProperty.
// */
// public int hashCode() {
// return _lattice.hashCode();
// }
/**
* Initialize the property term. Since LatticeProperty is a constant term,
* this base class does nothing.
* @exception IllegalActionException Not thrown in this base class.
*/
public void initialize(Object object) throws IllegalActionException {
// do nothing
}
/**
* Return true if this property does not correspond to a single property
* class. This occurs if the type is not instantiable, or it represents
* either an abstract base class or an interface. Return false in this base
* class by default.
* @return False.
*/
public boolean isAbstract() {
return false;
}
/**
* Test if the argument property is compatible with this property.
* @param property An instance of Property.
* @return True if the argument is compatible with this property.
*/
public boolean isCompatible(Property property) {
int propertyInfo = _lattice.compare(this, property);
return propertyInfo == CPO.SAME || propertyInfo == CPO.HIGHER;
}
/**
* Test if this property is a constant. Subclass should overrides this to
* return false if the property is the bottom of the lattice. This base
* class returns true by default.
* @return True in this base class.
*/
public boolean isConstant() {
return true;
}
/**
* Return true if this property term is effective.
*
* <p>This method is used to mark constraints that are due to
* unreachable parts of the model as not effective (i.e.
* isEffective() would return false), so that they would be
* excluded from the list passed to the constraint solver.</p>
*
* <p>isEffecitive() is ony used when we know for sure that parts
* of a model are unreachable. An example is a FSM with a guard
* like TRUE == FALSE. If we know that the guard transition can
* never happen (and therefore we use the static/dynamic solver
* with some basic partial evaluation) we reduce the model. In
* order the avoid the effort of recollecting the effecitve
* constraints the constraints are collected only once and then
* marked as effective (default) or not effective.
*
* <p>Note that reachability analysis is undecidable and partial
* reachability analysis has not yet been fully implemented.
* Also, it's helpful to know the values of
* parameters/outputs/transition guards for doing the analysis,
* but there are still some fundamental issues with calculating
* the values.</p>
*
* @return Always return true in this base class.
* @see #setEffective(boolean)
*/
public boolean isEffective() {
return true;
}
/**
* Determine if this Type corresponds to an instantiable token class.
* @return True if this type corresponds to an instantiable token class.
*/
public boolean isInstantiable() {
return true;
}
/**
* Return true if this property term is a settable (variable) term.
* Otherwise, return false. Return false in this base class by default.
* @return False.
*/
public boolean isSettable() {
return false;
}
/**
* Return true if the specified property is a substitution instance of this
* property. For the argument to be a substitution instance, it must be
* either the same as this property, or it must be a property that can be
* obtained by replacing the Baseproperty.UNKNOWN component of this property
* by another property.
* @param property A property.
* @return True if the argument is a substitution instance of this property.
*/
public boolean isSubstitutionInstance(Property property) {
return //(this == UNKNOWN) ||
this == _lattice.bottom() || this == property;
}
/**
* Return true if this property is a valid property value. Otherwise, return
* false. Return true in this base class by default.
* @return True.
*/
public boolean isValueAcceptable() {
return true;
}
/**
* Set the effectiveness of this property term to the specified value. Do
* nothing in this base by default.
* @param isEffective The specified effective value, ignored by this method
* @see #isEffective()
*/
public void setEffective(boolean isEffective) {
// do nothing
}
/**
* Set the value of this property term. Do nothing in this base by default.
* @param value The specified value.
*/
public void setValue(Object value) throws IllegalActionException {
// do nothing
}
/**
* Return the string that represents this lattice property. This base class
* returns the simple class name of the lattice property.
*/
public String toString() {
if (_name.length() > 0) {
return _name;
}
// FIXME: this seems wrong. Why return the class name?
return getClass().getSimpleName();
}
///////////////////////////////////////////////////////////////////
//// protected variables ////
/**
* The property lattice containing this lattice property.
*/
protected PropertyLattice _lattice;
}