001/* A port for use in component domains. 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_2 025 COPYRIGHTENDKEY 026 027 */ 028package ptolemy.component; 029 030import java.util.Iterator; 031 032import ptolemy.data.TupleToken; 033import ptolemy.kernel.ComponentEntity; 034import ptolemy.kernel.ComponentPort; 035import ptolemy.kernel.util.CrossRefList; 036import ptolemy.kernel.util.IllegalActionException; 037import ptolemy.kernel.util.NameDuplicationException; 038import ptolemy.kernel.util.Workspace; 039 040/////////////////////////////////////////////////////////////////// 041//// MethodCallPort 042 043/** 044 A port for use in the component domain. 045 046 @author Yang Zhao 047 @version $Id$ 048 @since Ptolemy II 11.0 049 @Pt.ProposedRating yellow(cxh) 050 @Pt.AcceptedRating red(cxh) 051 */ 052public class MethodCallPort extends ComponentPort { 053 /** Construct a port in the default workspace with an empty string 054 * as its name. Increment the version number of the workspace. 055 * The object is added to the workspace directory. 056 */ 057 public MethodCallPort() { 058 super(); 059 } 060 061 /** Construct a port in the specified workspace with an empty 062 * string as a name. You can then change the name with setName(). 063 * If the workspace argument is null, then use the default workspace. 064 * The object is added to the workspace directory. 065 * Increment the version number of the workspace. 066 * @param workspace The workspace that will list the port. 067 */ 068 public MethodCallPort(Workspace workspace) { 069 super(workspace); 070 } 071 072 /** Construct a port with the given name contained by the specified 073 * entity. The container argument must not be null, or a 074 * NullPointerException will be thrown. This port will use the 075 * workspace of the container for synchronization and version counts. 076 * If the name argument is null, then the name is set to the empty 077 * string. Increment the version of the workspace. 078 * @param container The container entity. 079 * @param name The name of the port. 080 * @exception IllegalActionException If the port is not of an acceptable 081 * class for the container. 082 * @exception NameDuplicationException If the name coincides with 083 * a port already in the container. 084 */ 085 public MethodCallPort(ComponentEntity container, String name) 086 throws IllegalActionException, NameDuplicationException { 087 super(container, name); 088 } 089 090 /** Construct an IOPort with a container and a name that is 091 * either an input, an output, or both, depending on the third 092 * and fourth arguments. The specified container must implement 093 * the Actor interface or an exception will be thrown. 094 * 095 * @param container The container actor. 096 * @param name The name of the port. 097 * @param isProvidedPort True if this port provides the method. 098 * @exception IllegalActionException If the port is not of an acceptable 099 * class for the container, or if the container does not implement the 100 * Actor interface. 101 * @exception NameDuplicationException If the name coincides with 102 * a port already in the container. 103 */ 104 public MethodCallPort(ComponentEntity container, String name, 105 boolean isProvidedPort) 106 throws IllegalActionException, NameDuplicationException { 107 this(container, name); 108 _isProvider = isProvidedPort; 109 } 110 111 /////////////////////////////////////////////////////////////////// 112 //// public methods //// 113 114 /** Clone the object into the specified workspace. The new object is 115 * <i>not</i> added to the directory of that workspace (you must do this 116 * yourself if you want it there). 117 * The result is a new port with no connections and no container. 118 * @param workspace The workspace for the cloned object. 119 * @exception CloneNotSupportedException If one or more of the 120 * attributes cannot be cloned. 121 * @return A new ComponentPort. 122 */ 123 @Override 124 public Object clone(Workspace workspace) throws CloneNotSupportedException { 125 MethodCallPort newObject = (MethodCallPort) super.clone(workspace); 126 newObject._insideLinks = new CrossRefList(newObject); 127 return newObject; 128 } 129 130 /////////////////////////////////////////////////////////////////// 131 //// public methods //// 132 133 /** Call the method associated with this port with the specified 134 * arguments. 135 * <p> 136 * If this port is a provider, as indicated by @link{#isProvider()}, 137 * then this method returns TupleToken.VOID, an empty tuple token. 138 * Subclasses should override this method to perform whatever 139 * functionality is associated with this method. 140 * <p> 141 * If this port is not a provider of this method, then this method 142 * delegates the call to all ports to which this port is 143 * deeply connected that are providers. The order in which those 144 * calls are performed is determined by the order in which connections 145 * are made. The returned token is a concatenation of the returned 146 * values of all the called methods. If there is nothing connected, 147 * then this method will return TupleToken.VOID. 148 * @param arguments The arguments to the method. 149 * @see #isProvider() 150 * @see ptolemy.data.TupleToken#VOID 151 */ 152 public synchronized TupleToken call(TupleToken arguments) { 153 if (!isProvider()) { 154 Iterator ports = this.deepConnectedPortList().iterator(); 155 TupleToken result = TupleToken.VOID; 156 157 while (ports.hasNext()) { 158 MethodCallPort port = (MethodCallPort) ports.next(); 159 160 if (port.isProvider()) { 161 result = TupleToken.merge(result, port.call(arguments)); 162 } 163 } 164 165 return result; 166 } 167 168 // The port provided should over write this method. 169 return TupleToken.VOID; 170 } 171 172 /** Return true if this port provides the method, 173 * vs. requires the method. By default, this method returns 174 * false, meaning that the port requires rather than provides 175 * the method. 176 * @see #setProvider(boolean) 177 * @see #MethodCallPort(ComponentEntity, String, boolean) 178 * @see #call(TupleToken) 179 * @return True if this port provides the method. 180 */ 181 public boolean isProvider() { 182 return _isProvider; 183 } 184 185 /** Call with argument true to specify that this port provides the method, 186 * and call with argument false to specify that it requires the method. 187 * @see #isProvider() 188 * @see #MethodCallPort(ComponentEntity, String, boolean) 189 * @see #call(TupleToken) 190 */ 191 public void setProvider(boolean isProvider) { 192 _isProvider = isProvider; 193 } 194 195 /////////////////////////////////////////////////////////////////// 196 //// private variables //// 197 198 /** Indicator of whether this port provides the method. */ 199 private boolean _isProvider = false; 200}