001/* UnitAttribute used to specify either a Unit Expression or Unit Equations. 002 003 Copyright (c) 2003-2014 The Regents of the University of California. 004 All rights reserved. 005 Permission is hereby granted, without written agreement and without 006 license or royalty fees, to use, copy, modify, and distribute this 007 software and its documentation for any purpose, provided that the above 008 copyright notice and the following two paragraphs appear in all copies 009 of this software. 010 011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 015 SUCH DAMAGE. 016 017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 022 ENHANCEMENTS, OR MODIFICATIONS. 023 024 PT_COPYRIGHT_VERSION_3 025 COPYRIGHTENDKEY 026 */ 027package ptolemy.moml.unit; 028 029import java.io.IOException; 030import java.io.Writer; 031import java.util.Collection; 032import java.util.LinkedList; 033import java.util.List; 034import java.util.Vector; 035 036import ptolemy.kernel.util.AbstractSettableAttribute; 037import ptolemy.kernel.util.IllegalActionException; 038import ptolemy.kernel.util.NameDuplicationException; 039import ptolemy.kernel.util.NamedObj; 040import ptolemy.kernel.util.Settable; 041import ptolemy.kernel.util.ValueListener; 042import ptolemy.util.StringUtilities; 043 044/////////////////////////////////////////////////////////////////// 045//// UnitAttribute 046 047/** 048 This class is used to implement the Unit Attribute. A 049 UnitsAttribute is either a UnitExpr, or a vector of 050 UnitConstraints. 051 052 @author Rowland R Johnson 053 @version $Id$ 054 @since Ptolemy II 8.0 055 @Pt.ProposedRating Red (rowland) 056 @Pt.AcceptedRating Red (rowland) 057 */ 058public class UnitAttribute extends AbstractSettableAttribute { 059 /** Construct a UnitsAttribute with no specific name, or container. 060 * @exception IllegalActionException If the attribute is not of an 061 * acceptable class for the container, or if the name contains a period. 062 * @exception NameDuplicationException If the name coincides with 063 * an attribute already in the container. 064 */ 065 public UnitAttribute() 066 throws IllegalActionException, NameDuplicationException { 067 super(); 068 } 069 070 /** Construct a UnitsAttribute with the specified name, and container. 071 * @param container Container 072 * @param name Name 073 * @exception IllegalActionException If the attribute is not of an 074 * acceptable class for the container, or if the name contains a period. 075 * @exception NameDuplicationException If the name coincides with 076 * an attribute already in the container. 077 */ 078 public UnitAttribute(NamedObj container, String name) 079 throws IllegalActionException, NameDuplicationException { 080 super(container, name); 081 } 082 083 /////////////////////////////////////////////////////////////////// 084 //// public methods //// 085 086 /** Add a listener to be notified when the value of this attribute changes. 087 * If the listener is already on the list of listeners, then do nothing. 088 * @param listener The listener to add. 089 */ 090 @Override 091 public void addValueListener(ValueListener listener) { 092 if (_valueListeners == null) { 093 _valueListeners = new LinkedList(); 094 } 095 096 if (!_valueListeners.contains(listener)) { 097 _valueListeners.add(listener); 098 } 099 } 100 101 /** Write a MoML description of the UnitsAttribute. Nothing is 102 * written if the value is null or "". 103 * @param output The output stream to write to. 104 * @param depth The depth in the hierarchy, to determine indenting. 105 * @param name The name to use instead of the current name. 106 * @exception IOException If an I/O error occurs. 107 * @see ptolemy.kernel.util.NamedObj#exportMoML(Writer, int, String) 108 */ 109 @Override 110 public void exportMoML(Writer output, int depth, String name) 111 throws IOException { 112 String value = getExpression(); 113 String valueTerm = ""; 114 115 if (value != null && !value.equals("")) { 116 valueTerm = " value=\"" + StringUtilities.escapeForXML(value) 117 + "\""; 118 119 output.write(_getIndentPrefix(depth) + "<" + _elementName 120 + " name=\"" + name + "\" class=\"" + getClassName() + "\"" 121 + valueTerm + ">\n"); 122 _exportMoMLContents(output, depth + 1); 123 output.write(_getIndentPrefix(depth) + "</" + _elementName + ">\n"); 124 } 125 } 126 127 /** Get the descriptive form of this attribute. 128 * @return a String that represents the descriptive form. 129 * @see ptolemy.kernel.util.Settable#getExpression() 130 */ 131 @Override 132 public String getExpression() { 133 switch (_type) { 134 case _EXPRESSION: { 135 if (_unitExpr == null) { 136 return ""; 137 } 138 139 return _unitExpr.descriptiveForm(); 140 } 141 142 case _CONSTRAINTS: { 143 if (_unitConstraints == null) { 144 return ""; 145 } 146 147 return getUnitConstraints().descriptiveForm(); 148 } 149 } 150 151 return null; 152 } 153 154 /** Get the UnitConstraints. 155 * @return The UnitConstraints. 156 */ 157 public UnitConstraints getUnitConstraints() { 158 return _unitConstraints; 159 } 160 161 /** Get the Unit Expression. 162 * @return The UnitExpr. 163 */ 164 public UnitExpr getUnitExpr() { 165 return _unitExpr; 166 } 167 168 /** Get the visibility of this attribute, as set by setVisibility(). 169 * The visibility is set by default to NONE. 170 * @return The visibility of this attribute. 171 * @see ptolemy.kernel.util.Settable#getVisibility() 172 */ 173 @Override 174 public Visibility getVisibility() { 175 return _visibility; 176 } 177 178 /** Remove a listener from the list of listeners that is 179 * notified when the value of this attribute changes. If no such listener 180 * exists, do nothing. 181 * @param listener The listener to remove. 182 */ 183 @Override 184 public void removeValueListener(ValueListener listener) { 185 if (_valueListeners != null) { 186 _valueListeners.remove(listener); 187 } 188 } 189 190 /** Set the expression. This method takes the descriptive form and 191 * determines the internal form (by parsing the descriptive form) and stores 192 * it. 193 * @param expression A String that is the descriptive form of either a Unit 194 * or a UnitEquation. 195 * @see ptolemy.kernel.util.Settable#setExpression(java.lang.String) 196 */ 197 @Override 198 public void setExpression(String expression) throws IllegalActionException { 199 super.setExpression(expression); 200 201 try { 202 if (getName().equals("_unitConstraints")) { 203 Vector uEquations = UnitLibrary.getParser() 204 .parseEquations(expression); 205 // Coverity: UParser.parseEquations() could return null. 206 if (uEquations != null) { 207 UnitConstraints uConstraints = new UnitConstraints(); 208 209 for (int i = 0; i < uEquations.size(); i++) { 210 uConstraints.addConstraint( 211 (UnitEquation) uEquations.elementAt(i)); 212 } 213 setUnitConstraints(uConstraints); 214 } 215 } 216 217 if (getName().equals("_units")) { 218 UnitExpr uExpr; 219 uExpr = UnitLibrary.getParser().parseUnitExpr(expression); 220 setUnitExpr(uExpr); 221 } 222 } catch (ParseException ex) { 223 throw new IllegalActionException(this, ex, 224 "Can't parse the expression " + expression); 225 } 226 } 227 228 /** Set the UnitConstraints. 229 * @param constraints The UnitConstraints. 230 */ 231 public void setUnitConstraints(UnitConstraints constraints) { 232 _unitConstraints = constraints; 233 _type = _CONSTRAINTS; 234 } 235 236 /** Set the Unit Expression. 237 * @param expr A UnitExpr. 238 */ 239 public void setUnitExpr(UnitExpr expr) { 240 _unitExpr = expr; 241 _type = _EXPRESSION; 242 } 243 244 /** Set the visibility of this attribute. The argument should be one 245 * of the public static instances in Settable. 246 * @param visibility The visibility of this attribute. 247 * @see ptolemy.kernel.util.Settable#setVisibility(Settable.Visibility) 248 */ 249 @Override 250 public void setVisibility(Visibility visibility) { 251 _visibility = visibility; 252 } 253 254 /* Not really relevant to current capability. 255 * But has to be included this class implements the Settable interface. 256 * @return Null, indicating that no other instances of Settable are 257 * validated. 258 * @see ptolemy.kernel.util.Settable#validate() 259 */ 260 @Override 261 public Collection validate() throws IllegalActionException { 262 return null; 263 } 264 265 /////////////////////////////////////////////////////////////////// 266 //// protected methods //// 267 268 /** Propagate the value of this object to the 269 * specified object. The specified object is required 270 * to be an instance of the same class as this one, or 271 * a ClassCastException will be thrown. 272 * @param destination Object to which to propagate the 273 * value. 274 * @exception IllegalActionException If the value cannot 275 * be propagated. 276 */ 277 @Override 278 protected void _propagateValue(NamedObj destination) 279 throws IllegalActionException { 280 ((Settable) destination).setExpression(getExpression()); 281 } 282 283 /////////////////////////////////////////////////////////////////// 284 //// private variables //// 285 Visibility _visibility = Settable.NONE; 286 287 // Listeners for changes in value. 288 private List _valueListeners; 289 290 private UnitExpr _unitExpr = null; 291 292 private UnitConstraints _unitConstraints = null; 293 294 private int _type = -1; 295 296 private static final int _EXPRESSION = 0; 297 298 private static final int _CONSTRAINTS = 1; 299}