001/* A BoundaryDetector determines the topological relationship of a Receiver 002 with respect to boundary ports. 003 004 Copyright (c) 1997-2014 The Regents of the University of California. 005 All rights reserved. 006 Permission is hereby granted, without written agreement and without 007 license or royalty fees, to use, copy, modify, and distribute this 008 software and its documentation for any purpose, provided that the above 009 copyright notice and the following two paragraphs appear in all copies 010 of this software. 011 012 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 013 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 014 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 015 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 016 SUCH DAMAGE. 017 018 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 019 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 020 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 021 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 022 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 023 ENHANCEMENTS, OR MODIFICATIONS. 024 025 PT_COPYRIGHT_VERSION_2 026 COPYRIGHTENDKEY 027 028 029 */ 030package ptolemy.actor.process; 031 032import java.util.Iterator; 033 034import ptolemy.actor.IOPort; 035import ptolemy.actor.Receiver; 036import ptolemy.kernel.ComponentEntity; 037import ptolemy.kernel.util.IllegalActionException; 038import ptolemy.kernel.util.InvalidStateException; 039 040/////////////////////////////////////////////////////////////////// 041//// BoundaryDetector 042 043/** 044 A BoundaryDetector determines the topological relationship of a Receiver 045 with respect to boundary ports. 046 047 @author John S. Davis II 048 @version $Id$ 049 @since Ptolemy II 1.0 050 @Pt.ProposedRating Red (davisj) 051 @Pt.AcceptedRating Red (davisj) 052 053 */ 054public class BoundaryDetector { 055 /** Construct a BoundaryDetector with the specified containing 056 * receiver. 057 * @param receiver The receiver containing this BoundaryDetector. 058 */ 059 public BoundaryDetector(Receiver receiver) { 060 _receiver = receiver; 061 } 062 063 /////////////////////////////////////////////////////////////////// 064 //// public methods //// 065 066 /** Return true if the receiver containing this boundary detector 067 * is connected to a boundary port. A boundary port is an opaque 068 * port that is contained by a composite actor. If the containing 069 * receiver is connected to a boundary port, then return true; 070 * otherwise return false. 071 * This method is not synchronized so the caller should be. 072 * @return True if the containing receiver is connected to 073 * boundary port; return false otherwise. 074 * @exception IllegalActionException 075 */ 076 public boolean isConnectedToBoundary() throws IllegalActionException { 077 if (_connectedBoundaryCacheIsOn) { 078 return _isConnectedBoundaryValue; 079 } else { 080 IOPort contPort = _receiver.getContainer(); 081 082 if (contPort == null) { 083 _connectedBoundaryCacheIsOn = false; 084 _isConnectedBoundaryValue = false; 085 return _isConnectedBoundaryValue; 086 } 087 088 ComponentEntity contEntity = (ComponentEntity) contPort 089 .getContainer(); 090 IOPort connectedPort = null; 091 ComponentEntity connectedEntity = null; 092 093 Iterator ports = contPort.connectedPortList().iterator(); 094 095 while (ports.hasNext()) { 096 connectedPort = (IOPort) ports.next(); 097 connectedEntity = (ComponentEntity) connectedPort 098 .getContainer(); 099 100 if (connectedEntity == contEntity.getContainer() 101 && connectedPort.isInput() 102 && connectedPort.isOpaque()) { 103 // The port container of this receiver is 104 // connected to the inside of a boundary port. 105 // Now determine if this receiver's channel is 106 // connected to the boundary port. 107 Receiver[][] receivers = connectedPort.deepGetReceivers(); 108 109 for (Receiver[] receiver : receivers) { 110 for (int j = 0; j < receiver.length; j++) { 111 if (_receiver == receiver[j]) { 112 _connectedBoundaryCacheIsOn = true; 113 _isConnectedBoundaryValue = true; 114 return true; 115 } 116 } 117 } 118 } else if (connectedPort.isOpaque() 119 && !connectedEntity.isAtomic() 120 && connectedPort.isOutput()) { 121 // The port container of this receiver is 122 // connected to the outside of a boundary port. 123 // Now determine if this receiver's channel is 124 // connected to the boundary port. 125 Receiver[][] receivers = connectedPort.getRemoteReceivers(); 126 127 for (Receiver[] receiver : receivers) { 128 for (int j = 0; j < receiver.length; j++) { 129 if (_receiver == receiver[j]) { 130 _connectedBoundaryCacheIsOn = true; 131 _isConnectedBoundaryValue = true; 132 return true; 133 } 134 } 135 } 136 } 137 } 138 139 _connectedBoundaryCacheIsOn = true; 140 _isConnectedBoundaryValue = false; 141 return _isConnectedBoundaryValue; 142 } 143 } 144 145 /** Return true if the receiver containing this boundary detector 146 * is connected to the inside of an input boundary port; return 147 * false otherwise. A boundary port is an opaque port that is 148 * contained by a composite actor. 149 * This method is not synchronized so the caller should be. 150 * @return True if the containing receiver is connected to the 151 * inside of a boundary port; return false otherwise. 152 * @exception IllegalActionException 153 * @exception InvalidStateException 154 */ 155 public boolean isConnectedToBoundaryInside() 156 throws InvalidStateException, IllegalActionException { 157 if (_connectedInsideOfBoundaryCacheIsOn) { 158 return _isConnectedInsideOfBoundaryValue; 159 } else { 160 IOPort contPort = _receiver.getContainer(); 161 162 if (contPort == null) { 163 _connectedInsideOfBoundaryCacheIsOn = false; 164 _isConnectedInsideOfBoundaryValue = false; 165 return _isConnectedInsideOfBoundaryValue; 166 } 167 168 ComponentEntity contEntity = (ComponentEntity) contPort 169 .getContainer(); 170 IOPort connectedPort = null; 171 ComponentEntity connectedEntity = null; 172 173 Iterator ports = contPort.connectedPortList().iterator(); 174 175 while (ports.hasNext()) { 176 connectedPort = (IOPort) ports.next(); 177 connectedEntity = (ComponentEntity) connectedPort 178 .getContainer(); 179 180 if (connectedEntity == contEntity.getContainer() 181 && connectedPort.isInput() 182 && connectedPort.isOpaque()) { 183 // The port container of this receiver is 184 // connected to the inside of a boundary port. 185 // Now determine if this receiver's channel is 186 // connected to the boundary port. 187 Receiver[][] receivers = connectedPort.deepGetReceivers(); 188 189 for (Receiver[] receiver : receivers) { 190 for (int j = 0; j < receiver.length; j++) { 191 if (_receiver == receiver[j]) { 192 _connectedInsideOfBoundaryCacheIsOn = true; 193 _isConnectedInsideOfBoundaryValue = true; 194 return true; 195 } 196 } 197 } 198 } 199 } 200 201 _connectedInsideOfBoundaryCacheIsOn = true; 202 _isConnectedInsideOfBoundaryValue = false; 203 return _isConnectedInsideOfBoundaryValue; 204 } 205 } 206 207 /** Return true if the receiver containing this boundary detector 208 * is connected to the outside of an output boundary port; return 209 * false otherwise. A boundary port is an opaque port that is 210 * contained by a composite actor. If the receiver containing 211 * this boundary detector is contained on the inside of a boundary 212 * port, then return false. 213 * This method is not synchronized so the caller should be. 214 * @return True if the containing receiver is connected to the 215 * outside of a boundary port; return false otherwise. 216 * @exception IllegalActionException 217 */ 218 public boolean isConnectedToBoundaryOutside() 219 throws IllegalActionException { 220 if (_connectedOutsideOfBoundaryCacheIsOn) { 221 return _isConnectedOutsideOfBoundaryValue; 222 } else { 223 IOPort contPort = _receiver.getContainer(); 224 225 if (contPort == null) { 226 _connectedOutsideOfBoundaryCacheIsOn = false; 227 _isConnectedOutsideOfBoundaryValue = false; 228 return _isConnectedOutsideOfBoundaryValue; 229 } 230 231 Iterator ports = contPort.connectedPortList().iterator(); 232 233 while (ports.hasNext()) { 234 IOPort connectedPort = (IOPort) ports.next(); 235 ComponentEntity connectedEntity = (ComponentEntity) connectedPort 236 .getContainer(); 237 238 if (connectedPort.isOpaque() && !connectedEntity.isAtomic() 239 && connectedPort.isOutput()) { 240 // The port container of this receiver is 241 // connected to the outside of a boundary port. 242 // Now determine if this receiver's channel is 243 // connected to the boundary port. 244 Receiver[][] receivers = connectedPort.getRemoteReceivers(); 245 246 for (Receiver[] receiver : receivers) { 247 for (int j = 0; j < receiver.length; j++) { 248 if (_receiver == receiver[j]) { 249 _connectedOutsideOfBoundaryCacheIsOn = true; 250 _isConnectedOutsideOfBoundaryValue = true; 251 return true; 252 } 253 } 254 } 255 } 256 } 257 258 _connectedOutsideOfBoundaryCacheIsOn = true; 259 _isConnectedOutsideOfBoundaryValue = false; 260 return _isConnectedOutsideOfBoundaryValue; 261 } 262 } 263 264 /** Return true if the receiver containing this boundary detector 265 * is contained on the inside of a boundary port. A boundary port 266 * is an opaque port that is contained by a composite actor. If 267 * the containing receiver is contained on the inside of a 268 * boundary port then return true; otherwise return false. This 269 * method is not synchronized so the caller should be. 270 * @return True if the containing receiver is contained on the 271 * inside of a boundary port; return false otherwise. 272 */ 273 public boolean isInsideBoundary() { 274 if (_insideBoundaryCacheIsOn) { 275 return _isInsideBoundaryValue; 276 } else { 277 IOPort innerPort = _receiver.getContainer(); 278 279 if (innerPort == null) { 280 _insideBoundaryCacheIsOn = false; 281 _isInsideBoundaryValue = false; 282 return _isInsideBoundaryValue; 283 } 284 285 ComponentEntity innerEntity = (ComponentEntity) innerPort 286 .getContainer(); 287 288 if (innerEntity != null && !innerEntity.isAtomic() 289 && innerPort.isOpaque()) { 290 // The containing receiver is contained by the port 291 // of a composite actor. 292 if (innerPort.isOutput() && !innerPort.isInput()) { 293 _isInsideBoundaryValue = true; 294 } else if (!innerPort.isOutput() && innerPort.isInput()) { 295 _isInsideBoundaryValue = false; 296 } else if (!innerPort.isOutput() && !innerPort.isInput()) { 297 _isInsideBoundaryValue = false; 298 } else { 299 // CONCERN: The following only works if the port 300 // is not both an input and output. 301 throw new IllegalArgumentException("A port that " 302 + "is both an input and output can not be " 303 + "properly dealt with by " 304 + "PNQueueReceiver.isInsideBoundary"); 305 } 306 307 _insideBoundaryCacheIsOn = true; 308 return _isInsideBoundaryValue; 309 } 310 311 _insideBoundaryCacheIsOn = true; 312 _isInsideBoundaryValue = false; 313 return _isInsideBoundaryValue; 314 } 315 } 316 317 /** Return true if the receiver containing this boundary detector 318 * is contained on the outside of a boundary port. A boundary 319 * port is an opaque port that is contained by a composite actor. 320 * If the containing receiver is contained on the outside of a 321 * boundary port then return true; otherwise return false. This 322 * method is not synchronized so the caller should be. 323 * @return True if the containing receiver is contained on the 324 * outside of a boundary port; return false otherwise. 325 */ 326 public boolean isOutsideBoundary() { 327 if (_outsideBoundaryCacheIsOn) { 328 return _isInsideBoundaryValue; 329 } else { 330 IOPort innerPort = _receiver.getContainer(); 331 332 if (innerPort == null) { 333 _outsideBoundaryCacheIsOn = false; 334 _isOutsideBoundaryValue = false; 335 return _isOutsideBoundaryValue; 336 } 337 338 ComponentEntity innerEntity = (ComponentEntity) innerPort 339 .getContainer(); 340 341 if (innerEntity != null && !innerEntity.isAtomic() 342 && innerPort.isOpaque()) { 343 // The containing receiver is contained by the port 344 // of a composite actor. 345 if (innerPort.isOutput() && !innerPort.isInput()) { 346 _isOutsideBoundaryValue = false; 347 } else if (!innerPort.isOutput() && innerPort.isInput()) { 348 _isOutsideBoundaryValue = true; 349 } else if (!innerPort.isOutput() && !innerPort.isInput()) { 350 _isOutsideBoundaryValue = false; 351 } else { 352 // CONCERN: The following only works if the port 353 // is not both an input and output. 354 throw new IllegalArgumentException("A port that " 355 + "is both an input and output can not be " 356 + "properly dealt with by " 357 + "PNQueueReceiver.isInsideBoundary"); 358 } 359 360 _outsideBoundaryCacheIsOn = true; 361 return _isOutsideBoundaryValue; 362 } 363 364 _outsideBoundaryCacheIsOn = true; 365 _isOutsideBoundaryValue = false; 366 return _isOutsideBoundaryValue; 367 } 368 } 369 370 /** Reset the cache variables in boundary detector. 371 */ 372 public void reset() { 373 _insideBoundaryCacheIsOn = false; 374 _isInsideBoundaryValue = false; 375 _outsideBoundaryCacheIsOn = false; 376 _isOutsideBoundaryValue = false; 377 _connectedBoundaryCacheIsOn = false; 378 _isConnectedBoundaryValue = false; 379 } 380 381 /////////////////////////////////////////////////////////////////// 382 //// private methods //// 383 private Receiver _receiver; 384 385 private boolean _insideBoundaryCacheIsOn = false; 386 387 private boolean _isInsideBoundaryValue = false; 388 389 private boolean _outsideBoundaryCacheIsOn = false; 390 391 private boolean _isOutsideBoundaryValue = false; 392 393 private boolean _connectedBoundaryCacheIsOn = false; 394 395 private boolean _isConnectedBoundaryValue = false; 396 397 private boolean _connectedInsideOfBoundaryCacheIsOn = false; 398 399 private boolean _isConnectedInsideOfBoundaryValue = false; 400 401 private boolean _connectedOutsideOfBoundaryCacheIsOn = false; 402 403 private boolean _isConnectedOutsideOfBoundaryValue = false; 404}