001/* UnitExpr that will contain UnitTerms. 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.util.Iterator; 030import java.util.Vector; 031 032import ptolemy.actor.IOPort; 033 034/////////////////////////////////////////////////////////////////// 035//// UnitExpr 036 037/** A UnitExpr contains UnitTerms. 038 @author Rowland R Johnson 039 @version $Id$ 040 @since Ptolemy II 8.0 041 @Pt.ProposedRating Red (rowland) 042 @Pt.AcceptedRating Red (rowland) 043 */ 044public class UnitExpr implements UnitPresentation { 045 /** Construct an empty (i.e. no UnitTerms) UnitExpr. 046 * 047 */ 048 public UnitExpr() { 049 } 050 051 /** Construct a UnitTerm from an IOPort. 052 * The constructed UnitExpr will have one UnitTerm and it will be 053 * a variable with the name being that of the port. 054 * @param ioPort The IOPort. 055 */ 056 public UnitExpr(IOPort ioPort) { 057 UnitTerm uTerm = new UnitTerm(); 058 uTerm.setVariable( 059 ioPort.getContainer().getName() + "." + ioPort.getName()); 060 _uTerms.add(uTerm); 061 } 062 063 /////////////////////////////////////////////////////////////////// 064 //// public methods //// 065 066 /** Add a UnitTerm to the expression. 067 * @param uTerm The UnitTerm. 068 */ 069 public void addUnitTerm(UnitTerm uTerm) { 070 _uTerms.add(uTerm); 071 } 072 073 /** Create a copy of this UnitExpr. 074 * @return The new UnitExpr. 075 */ 076 public UnitExpr copy() { 077 UnitExpr retv = new UnitExpr(); 078 Vector newUTerms = new Vector(); 079 080 for (int i = 0; i < _uTerms.size(); i++) { 081 UnitTerm term = (UnitTerm) _uTerms.elementAt(i); 082 newUTerms.add(term.copy()); 083 } 084 085 retv._setUTerms(newUTerms); 086 return retv; 087 } 088 089 /** The expression of the UnitExpr that is commonly used by humans. 090 * @see ptolemy.moml.unit.UnitPresentation#descriptiveForm() 091 */ 092 @Override 093 public String descriptiveForm() { 094 Iterator iter = _uTerms.iterator(); 095 StringBuffer retv = new StringBuffer(); 096 if (iter.hasNext()) { 097 String descriptiveForm = ((UnitTerm) iter.next()).descriptiveForm(); 098 // Coverity: UnitTerm.descriptiveForm() could return null. 099 if (descriptiveForm != null) { 100 retv.append(descriptiveForm); 101 } 102 } 103 104 while (iter.hasNext()) { 105 retv.append(" " + ((UnitTerm) iter.next()).descriptiveForm()); 106 } 107 108 return retv.toString(); 109 } 110 111 /** If this UnitExpr has one term and it is a Unit then return that Unit. 112 * @return The Unit if there is a single UnitTerm, and it is a Unit, null 113 * otherwise. 114 */ 115 public Unit getSingleUnit() { 116 if (_uTerms.size() == 1 && ((UnitTerm) _uTerms.elementAt(0)).isUnit()) { 117 return ((UnitTerm) _uTerms.elementAt(0)).getUnit(); 118 } 119 120 return null; 121 } 122 123 /** Get the UnitTerms in this UnitExpr. 124 * @return The UnitTerms. 125 */ 126 public Vector getUTerms() { 127 return _uTerms; 128 } 129 130 /** Create a new UnitExpr that is the inverse of this UnitExpr. 131 * @return The inverse of this UnitExpr. 132 */ 133 public UnitExpr invert() { 134 UnitExpr retv = new UnitExpr(); 135 Vector myUTerms = new Vector(); 136 137 for (int i = 0; i < _uTerms.size(); i++) { 138 myUTerms.add(((UnitTerm) _uTerms.elementAt(i)).invert()); 139 } 140 141 retv._setUTerms(myUTerms); 142 return retv; 143 } 144 145 /** 146 * Reduce a UnitExpr to produce a UnitExpr that has at most one Unit. Any 147 * embedded UnitExpr is first transformed so that all embedded UnitExprs 148 * are replaced with Units. This intermediate result is a mixture of Units 149 * and variables. The Units are then replaced with their product. The 150 * result is a single Unit and all of the original variables. 151 * @return The reduced UnitExpr. 152 */ 153 public UnitExpr reduce() { 154 _flatten(); 155 156 Unit reductionUnit = UnitLibrary.Identity.copy(); 157 Vector newUTerms = new Vector(); 158 159 for (int i = 0; i < _uTerms.size(); i++) { 160 UnitTerm unitTerm = (UnitTerm) _uTerms.elementAt(i); 161 162 if (unitTerm.isUnit()) { 163 reductionUnit = reductionUnit.multiplyBy( 164 unitTerm.getUnit().pow(unitTerm.getExponent())); 165 } else { 166 newUTerms.add(unitTerm); 167 } 168 } 169 170 newUTerms.add(new UnitTerm(reductionUnit)); 171 172 UnitExpr retv = new UnitExpr(); 173 retv._setUTerms(newUTerms); 174 return retv; 175 } 176 177 @Override 178 public String toString() { 179 StringBuffer retv = new StringBuffer("UnitExpr:["); 180 181 if (_uTerms.size() > 0) { 182 retv.append(((UnitTerm) _uTerms.elementAt(0)).toString()); 183 184 for (int i = 1; i < _uTerms.size(); i++) { 185 retv.append(" " + ((UnitTerm) _uTerms.elementAt(i)).toString()); 186 } 187 } 188 189 retv.append("]"); 190 return retv.toString(); 191 } 192 193 /////////////////////////////////////////////////////////////////// 194 //// protected methods //// 195 protected void _setUTerms(Vector uTerms) { 196 _uTerms = uTerms; 197 } 198 199 /////////////////////////////////////////////////////////////////// 200 //// private methods //// 201 private void _flatten() { 202 if (_isFlat) { 203 return; 204 } 205 206 Vector newUTerms = new Vector(); 207 208 for (int i = 0; i < _uTerms.size(); i++) { 209 UnitTerm unitTerm = (UnitTerm) _uTerms.elementAt(i); 210 211 if (unitTerm.isUnitExpr()) { 212 UnitExpr uExpr = unitTerm.getUnitExpr(); 213 214 if (uExpr != null) { 215 uExpr._flatten(); 216 newUTerms.addAll(uExpr.getUTerms()); 217 } 218 } else { 219 newUTerms.add(unitTerm); 220 } 221 } 222 223 _isFlat = true; 224 _setUTerms(newUTerms); 225 } 226 227 /////////////////////////////////////////////////////////////////// 228 //// private variables //// 229 boolean _isFlat = false; 230 231 Vector _uTerms = new Vector(); 232}