001/* 002 * Copyright (c) 2005-2010 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: welker $' 006 * '$Date: 2010-05-06 05:21:26 +0000 (Thu, 06 May 2010) $' 007 * '$Revision: 24234 $' 008 * 009 * Permission is hereby granted, without written agreement and without 010 * license or royalty fees, to use, copy, modify, and distribute this 011 * software and its documentation for any purpose, provided that the above 012 * copyright notice and the following two paragraphs appear in all copies 013 * of this software. 014 * 015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 019 * SUCH DAMAGE. 020 * 021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 026 * ENHANCEMENTS, OR MODIFICATIONS. 027 * 028 */ 029 030package org.kepler.sms; 031 032import java.util.Iterator; 033import java.util.Vector; 034 035import ptolemy.actor.IOPort; 036import ptolemy.kernel.util.Attribute; 037import ptolemy.kernel.util.IllegalActionException; 038import ptolemy.kernel.util.NameDuplicationException; 039import ptolemy.kernel.util.NamedObj; 040import ptolemy.moml.MoMLChangeRequest; 041 042/** 043 * FIXME: Documentation ... A port generalization is a virtual port that 044 * encapsulates a set of underlying ports (both ptolemy ports and other virtual 045 * ports). A port generalization (and virtual ports in general) can be annotated 046 * using semantic types. For example, given an actor with a 'lat' and 'lon' 047 * port, a port generalization 'pg' can be constructed that encapsulates both 048 * 'lat' and 'lon'; and a semantic type such as "Location" can be assigned to 049 * 'pg', stating that 'lat' and 'lon' values combined form a location value. 050 * <p> 051 * A port generalization may <b>only</b> be contained within an entity (e.g., an 052 * actor). A virtual port must have a name. 053 * 054 * @author Shawn Bowers 055 * @created June 20, 2005 056 */ 057 058public class KeplerIOPortSemanticLink extends Attribute { 059 060 /** 061 * Constructor 062 * 063 * @param container 064 * Description of the Parameter 065 * @param name 066 * The value of the property 067 * @exception IllegalActionException 068 * Description of the Exception 069 * @exception NameDuplicationException 070 * Description of the Exception 071 */ 072 public KeplerIOPortSemanticLink(NamedObj container, String name) 073 throws IllegalActionException, NameDuplicationException { 074 super(container, name); 075 } 076 077 /** 078 * FIXME: This should be "external" to the port ... Set the container of the 079 * link to the given container. This method fails, in addition to the normal 080 * ptolemy constraints for setting containers, if the given container is not 081 * a org.kepler.sms.KeplerVirtualIOPort or ptolemy IOPort object. 082 * 083 * @param container 084 * The container for this virtual port. 085 */ 086 public void setContainer(NamedObj container) throws IllegalActionException, 087 NameDuplicationException { 088 if (!(container instanceof IOPort || container instanceof KeplerVirtualIOPort)) { 089 String msg = "Container not an IOPort or Kepler virtual IO port '" 090 + getName() + "'"; 091 throw new IllegalActionException(this, msg); 092 } 093 super.setContainer(container); 094 } 095 096 /** 097 * @return The domain of the link, which is an IOPort or 098 * KeplerVirtualIOPort. 099 */ 100 public Object getDomain() { 101 return getContainer(); 102 } 103 104 /** 105 * Assigns the domain of this link. As a side effect, makes the domain the 106 * container for this object. 107 */ 108 public void setDomain(IOPort domain) throws IllegalActionException, 109 NameDuplicationException { 110 setContainer(domain); 111 } 112 113 /** 114 * Assigns the domain of this link. As a side effect, makes the domain the 115 * container for this object. 116 */ 117 public void setDomain(KeplerVirtualIOPort domain) 118 throws IllegalActionException, NameDuplicationException { 119 if (!_validateDomain(domain)) { 120 String msg = "Domain port '" + domain.getName() 121 + "' does not match range" + " direction for link '" 122 + getName() + "'"; 123 throw new IllegalActionException(this, msg); 124 } 125 setContainer(domain); 126 } 127 128 /** 129 * @return The range of the link, which is an IOPort or KeplerVirtualIOPort 130 */ 131 public Object getRange() { 132 KeplerIOPortReference ref = _getRangeRef(); 133 if (ref != null) 134 return ref.getPort(); 135 return null; 136 } 137 138 /** 139 * @return The range as an IOPort reference. Null if there is no range. 140 */ 141 private KeplerIOPortReference _getRangeRef() { 142 for (Iterator iter = attributeList().iterator(); iter.hasNext();) { 143 Object obj = iter.next(); 144 if (obj instanceof KeplerIOPortReference) 145 return (KeplerIOPortReference) obj; 146 } 147 return null; 148 } 149 150 /** 151 * Assigns the IOPort as the range of the link. Removes the current range if 152 * one exists. 153 */ 154 public void setRange(IOPort range) throws IllegalActionException, 155 NameDuplicationException { 156 if (range == null) 157 return; 158 if (!_validateRange(range)) { 159 String msg = "Range port '" + range.getName() 160 + "' does not match domain" + " direction for link '" 161 + getName() + "'"; 162 throw new IllegalActionException(this, msg); 163 } 164 KeplerIOPortReference ref = _getRangeRef(); 165 if (ref != null) { 166 MoMLChangeRequest request = new MoMLChangeRequest(this, 167 getContainer(), _swapRange(range)); 168 requestChange(request); 169 System.out.println("HERE ... " + ref); 170 System.out.println(exportMoML()); 171 } else { 172 ref = new KeplerIOPortReference(this, "_range"); 173 ((KeplerIOPortReference) ref).setPort(range); 174 } 175 } 176 177 /** 178 * Assigns the Virtual IOPort as the range of the link. Removes the current 179 * range if one exists. 180 */ 181 public void setRange(KeplerVirtualIOPort range) 182 throws IllegalActionException, NameDuplicationException { 183 if (range == null) 184 return; 185 if (!_validateRange(range)) { 186 String msg = "Range port '" + range.getName() 187 + "' does not match domain" + " direction for link '" 188 + getName() + "'"; 189 throw new IllegalActionException(this, msg); 190 } 191 KeplerIOPortReference ref = _getRangeRef(); 192 if (ref != null) { 193 MoMLChangeRequest request = new MoMLChangeRequest(this, 194 getContainer(), _swapRange(range)); 195 requestChange(request); 196 System.out.println("HERE ... " + ref); 197 System.out.println(exportMoML()); 198 } else { 199 ref = new KeplerVirtualIOPortReference(this, "_range"); 200 ((KeplerVirtualIOPortReference) ref).setPort(range); 201 } 202 } 203 204 /** 205 * Helper function to remove an attribute from an a link. 206 */ 207 private String _swapRange(KeplerVirtualIOPort range) { 208 String linkStr = ""; 209 if (getName() != null) 210 linkStr += "<property name=\"" + getName() + "\" "; 211 else 212 linkStr += "<property "; 213 linkStr += "class=\"" + this.getClass().getName() + "\">\n"; 214 linkStr += " <property name=\"_range\" "; 215 linkStr += "class=\"" + KeplerVirtualIOPortReference.class.getName() 216 + "\" "; 217 linkStr += "value=\"" + range.getName() + "\""; 218 linkStr += "/>\n"; 219 220 for (Iterator<SemanticProperty> iter = getSemanticProperties().iterator(); iter.hasNext();) { 221 SemanticProperty p = iter.next(); 222 linkStr += " " + p.exportMoML() + "\n"; 223 } 224 return linkStr + "</property>"; 225 } 226 227 /** 228 * Helper function to remove an attribute from an a link. 229 */ 230 private String _swapRange(IOPort range) { 231 String linkStr = ""; 232 if (getName() != null) 233 linkStr += "<property name=\"" + getName() + "\" "; 234 else 235 linkStr += "<property "; 236 linkStr += "class=\"" + this.getClass().getName() + "\">\n"; 237 linkStr += " <property name=\"_range\" "; 238 linkStr += "class=\"" + KeplerIOPortReference.class.getName() + "\" "; 239 linkStr += "value=\"" + range.getName() + "\""; 240 linkStr += "/>\n"; 241 242 for (Iterator<SemanticProperty> iter = getSemanticProperties().iterator(); iter.hasNext();) { 243 SemanticProperty p = iter.next(); 244 linkStr += " " + p.exportMoML() + "\n"; 245 } 246 return linkStr + "</property>"; 247 } 248 249 /** 250 * 251 */ 252 public Vector<SemanticProperty> getSemanticProperties() { 253 Vector<SemanticProperty> result = new Vector<SemanticProperty>(); 254 for (Iterator<SemanticProperty> iter = attributeList(SemanticProperty.class).iterator(); iter 255 .hasNext();) 256 result.add(iter.next()); 257 return result; 258 } 259 260 /** 261 * 262 */ 263 public void addSemanticProperty(SemanticProperty property) 264 throws IllegalActionException, NameDuplicationException { 265 property.setContainer(this); 266 } 267 268 /** 269 * @return True if the given domain direction matches existing range 270 * direction. 271 */ 272 private boolean _validateDomain(IOPort domain) { 273 if (getRange() != null) { 274 Object obj = getRange(); 275 if (obj instanceof IOPort) 276 return ((IOPort) obj).isOutput() == domain.isOutput(); 277 else if (obj instanceof KeplerVirtualIOPort) 278 return ((KeplerVirtualIOPort) obj).isOutput() == domain 279 .isOutput(); 280 } 281 return true; 282 } 283 284 /** 285 * @return True if the given domain direction matches existing range 286 * direction. 287 */ 288 private boolean _validateDomain(KeplerVirtualIOPort domain) { 289 if (getRange() != null) { 290 Object obj = getRange(); 291 if (obj instanceof IOPort) 292 return ((IOPort) obj).isOutput() == domain.isOutput(); 293 else if (obj instanceof KeplerVirtualIOPort) 294 return ((KeplerVirtualIOPort) obj).isOutput() == domain 295 .isOutput(); 296 } 297 return true; 298 } 299 300 /** 301 * @return True if the given range direction matches existing domain 302 * direction. 303 */ 304 private boolean _validateRange(IOPort range) { 305 if (getDomain() != null) { 306 Object obj = getDomain(); 307 if (obj instanceof IOPort) 308 return ((IOPort) obj).isOutput() == range.isOutput(); 309 else if (obj instanceof KeplerVirtualIOPort) 310 return ((KeplerVirtualIOPort) obj).isOutput() == range 311 .isOutput(); 312 } 313 return true; 314 } 315 316 /** 317 * @return True if the given range direction matches existing domain 318 * direction. 319 */ 320 private boolean _validateRange(KeplerVirtualIOPort range) { 321 if (getDomain() != null) { 322 Object obj = getDomain(); 323 if (obj instanceof IOPort) 324 return ((IOPort) obj).isOutput() == range.isOutput(); 325 else if (obj instanceof KeplerVirtualIOPort) 326 return ((KeplerVirtualIOPort) obj).isOutput() == range 327 .isOutput(); 328 } 329 return true; 330 } 331 332} // KeplerIOPortSemanticLink