001/*  A composite that contain one actor and mirror the ports and parameters of that actor.
002
003 Copyright (c) 2007-2015 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.actor.lib.hoc;
029
030import ptolemy.actor.parameters.ParameterMirrorPort;
031import ptolemy.actor.parameters.ParameterPort;
032import ptolemy.kernel.ComponentPort;
033import ptolemy.kernel.CompositeEntity;
034import ptolemy.kernel.Port;
035import ptolemy.kernel.util.IllegalActionException;
036import ptolemy.kernel.util.NameDuplicationException;
037import ptolemy.kernel.util.Workspace;
038
039///////////////////////////////////////////////////////////////////
040//// MirrorComposite
041
042/**
043 A composite that contains one actor and mirrors the ports and
044 parameters of that actor. This is identical to the base class
045 except that it requires its ports to be of type MirrorPort or
046 ParameterMirrorPort. That is, every port of this composite is
047 mirrored in the inside model, whereas the base class tolerates ports
048 that are not mirrored (typically instances of TypedIOPort).
049
050 @author Ilge Akkaya, Edward A. Lee
051 @version $Id$
052 @since Ptolemy II 6.1
053 @Pt.ProposedRating Yellow (eal)
054 @Pt.AcceptedRating Red (neuendor)
055 */
056public class MirrorComposite extends ReflectComposite {
057
058    /** Create an actor with a name and a container.
059     *  The container argument must not be null, or a
060     *  NullPointerException will be thrown.  This actor will use the
061     *  workspace of the container for synchronization and version counts.
062     *  If the name argument is null, then the name is set to the empty string.
063     *  Increment the version of the workspace.
064     *  @param container The container actor.
065     *  @param name The name of this actor.
066     *  @exception IllegalActionException If the container is incompatible
067     *   with this actor.
068     *  @exception NameDuplicationException If the name coincides with
069     *   an actor already in the container.
070     */
071    public MirrorComposite(CompositeEntity container, String name)
072            throws IllegalActionException, NameDuplicationException {
073        super(container, name);
074        _init();
075    }
076
077    /** Construct a MirrorComposite in the specified workspace with
078     *  no container and an empty string as a name. You can then change
079     *  the name with setName(). If the workspace argument is null, then
080     *  use the default workspace.  You should set the local director or
081     *  executive director before attempting to send data to the actor
082     *  or to execute it. Add the actor to the workspace directory.
083     *  Increment the version number of the workspace.
084     *  @param workspace The workspace that will list the actor.
085     */
086    public MirrorComposite(Workspace workspace) {
087        super(workspace);
088        _init();
089    }
090
091    /** Create an actor with a name and a container that optionally
092     *  mirrors the ports that are instances of ParameterPort.
093     *  The container argument must not be null, or a
094     *  NullPointerException will be thrown.  This actor will use the
095     *  workspace of the container for synchronization and version counts.
096     *  If the name argument is null, then the name is set to the empty string.
097     *  Increment the version of the workspace.
098     *  @param container The container actor.
099     *  @param name The name of this actor.
100     *  @param mirrorParameterPorts If false, then ports that are instances of
101     *   ParameterPort are not mirrored.
102     *  @exception IllegalActionException If the container is incompatible
103     *   with this actor.
104     *  @exception NameDuplicationException If the name coincides with
105     *   an actor already in the container.
106     */
107    public MirrorComposite(CompositeEntity container, String name,
108            boolean mirrorParameterPorts)
109            throws IllegalActionException, NameDuplicationException {
110        super(container, name, mirrorParameterPorts);
111        _init();
112    }
113
114    ///////////////////////////////////////////////////////////////////
115    ////                         protected methods                 ////
116
117    /** Add a port to this actor. This overrides the base class to
118     *  throw an exception if the port is not an instance of MirrorPort
119     *  or ParameterMirrorPort.
120     *  @param port The TypedIOPort to add to this actor.
121     *  @exception IllegalActionException If the port is not an instance
122     *   of IteratePort, or the port has no name.
123     *  @exception NameDuplicationException If the port name collides with a
124     *   name already in the actor.
125     */
126    @Override
127    protected void _addPort(Port port)
128            throws IllegalActionException, NameDuplicationException {
129
130        if (!(port instanceof MirrorPort
131                || port instanceof ParameterMirrorPort)) {
132            throw new IllegalActionException(this,
133                    "MirrorComposite ports are required to be "
134                            + "instances of MirrorPort");
135        }
136
137        super._addPort(port);
138    }
139
140    private void _init() {
141        setClassName("ptolemy.actor.lib.hoc.MirrorComposite");
142    }
143
144    /** Return true if the specified inside port should be mirrored.
145     *  This overrides the base class to return true for all ports
146     *  unless the port is an instance of ParameterPort and the
147     *  constructor specified that parameter ports should not be mirrored.
148     *  @param insidePort The port that may be mirrored.
149     *  @return True if the inside port should be mirrored.
150     */
151    @Override
152    protected boolean _mirrorPort(ComponentPort insidePort) {
153        // do not mirror ports that are not instances of MirrorPort
154        if (!_mirrorParameterPorts && insidePort instanceof ParameterPort) {
155            return false;
156        }
157        return true;
158    }
159
160    ///////////////////////////////////////////////////////////////////
161    ////                         inner classes                     ////
162
163    ///////////////////////////////////////////////////////////////////
164    //// MirrorCompositeContents
165
166    /** This is a specialized composite actor for use in MirrorComposite.
167     *  In particular, it ensures that if ports are added or deleted
168     *  locally, then corresponding ports will be added or deleted
169     *  in the container.  That addition will result in appropriate
170     *  connections being made.
171     */
172    public static class MirrorCompositeContents
173            extends ReflectCompositeContents {
174        // NOTE: This has to be a static class so that MoML can
175        // instantiate it.
176
177        /** Construct an actor with a name and a container.
178         *  @param container The container.
179         *  @param name The name of this actor.
180         *  @exception IllegalActionException If the container is incompatible
181         *   with this actor.
182         *  @exception NameDuplicationException If the name coincides with
183         *   an actor already in the container.
184         */
185        public MirrorCompositeContents(CompositeEntity container, String name)
186                throws IllegalActionException, NameDuplicationException {
187            super(container, name);
188        }
189
190        /** Add a port to this actor. This overrides the base class to
191         *  add a corresponding port to the container using a change
192         *  request, if that port does not already exist.
193         *  @param port The TypedIOPort to add to this actor.
194         *  @exception IllegalActionException If the port is not an instance of
195         *   MirrorPort, or the port has no name.
196         *  @exception NameDuplicationException If the port name
197         *  collides with a name already in the actor.
198         */
199        @Override
200        protected void _addPort(final Port port)
201                throws IllegalActionException, NameDuplicationException {
202
203            if (!(port instanceof MirrorPort
204                    || port instanceof ParameterMirrorPort)) {
205                throw new IllegalActionException(this,
206                        "Ports in MirrorComposiMirrorCompositeContentsite must be MirrorPort.");
207            }
208
209            super._addPort(port);
210        }
211    }
212}