001/* An attribute that represents a waypoint in a relation.
002
003 Copyright (c) 1998-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.moml;
029
030import java.io.IOException;
031import java.io.Writer;
032import java.util.LinkedList;
033import java.util.List;
034
035import ptolemy.kernel.Port;
036import ptolemy.kernel.Relation;
037import ptolemy.kernel.util.IllegalActionException;
038import ptolemy.kernel.util.Location;
039import ptolemy.kernel.util.NameDuplicationException;
040import ptolemy.kernel.util.Workspace;
041import ptolemy.util.StringUtilities;
042
043///////////////////////////////////////////////////////////////////
044//// Vertex
045
046/**
047 This attribute represents a waypoint in a relation. It extends
048 Location, meaning that can be associated with a physical location
049 in a visual rendition.  It can optionally be associated with another
050 instance of Vertex to indicate that there is a path from this
051 one to the other one. Cyclic paths are not permitted, although
052 currently that is not enforced by this class.
053
054 @author Steve Neuendorffer and Edward A. Lee
055 @version $Id$
056 @since Ptolemy II 0.4
057 @Pt.ProposedRating Red (eal)
058 @Pt.AcceptedRating Red (reviewmoderator)
059 */
060public class Vertex extends Location {
061    /** Construct an attribute 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
064     *  is null, then use the default workspace.
065     *  The object is added to the directory of the workspace.
066     *  Increment the version number of the workspace.
067     *  @param workspace The workspace that will list the attribute.
068     */
069    public Vertex(Workspace workspace) {
070        super(workspace);
071        _elementName = "vertex";
072    }
073
074    /** Construct an attribute with the given name and position.
075     *  @param container The container.
076     *  @param name The name of the vertex.
077     *  @exception IllegalActionException If the attribute is not of an
078     *   acceptable class for the container.
079     *  @exception NameDuplicationException If the name coincides with
080     *   an attribute already in the container.
081     */
082    public Vertex(Relation container, String name)
083            throws IllegalActionException, NameDuplicationException {
084        super(container, name);
085        _elementName = "vertex";
086    }
087
088    ///////////////////////////////////////////////////////////////////
089    ////                         public methods                    ////
090
091    /** Add the specified port to the list of ports linked to this vertex.
092     *  @param port The port to link.
093     */
094    public void addLinkedPort(Port port) {
095        if (_ports == null) {
096            _ports = new LinkedList<Port>();
097        }
098
099        _ports.add(port);
100    }
101
102    /** Write a MoML description of this object.
103     *  MoML is an XML modeling markup language.
104     *  In this class, the object is identified by the "property"
105     *  element, with "name", "class", and "value" (XML) attributes.
106     *  The body of the element, between the "&lt;property&gt;"
107     *  and "&lt;/property&gt;", is written using
108     *  the _exportMoMLContents() protected method, so that derived classes
109     *  can override that method alone to alter only how the contents
110     *  of this object are described.
111     *  The text that is written is indented according to the specified
112     *  depth, with each line (including the last one)
113     *  terminated with a newline. If the object is non-persistent, then
114     *  write nothing.
115     *  @param output The output stream to write to.
116     *  @param depth The depth in the hierarchy, to determine indenting.
117     *  @param name The name to use instead of the current name.
118     *  @exception IOException If an I/O error occurs.
119     */
120    @Override
121    public void exportMoML(Writer output, int depth, String name)
122            throws IOException {
123        if (_isMoMLSuppressed(depth)) {
124            return;
125        }
126
127        // This method is very similar to the superclass
128        // Location.exportMoML() except that this method does not
129        // include the 'class='.
130        String value = getExpression();
131        String valueTerm = "";
132
133        if (value != null && !value.equals("")) {
134            valueTerm = " value=\"" + StringUtilities.escapeForXML(value)
135                    + "\"";
136        }
137
138        output.write(
139                _getIndentPrefix(depth) + "<" + _elementName + " name=\"" + name // + "\" class=\""
140                // + getClassName()
141                        + "\"" + valueTerm + ">\n");
142        _exportMoMLContents(output, depth + 1);
143        output.write(_getIndentPrefix(depth) + "</" + _elementName + ">\n");
144    }
145
146    /** Return the other vertex to which there is a path from this vertex, or
147     *  null if there is none.  Note that the paths are one directional,
148     *  so this vertex might return null even though there is another vertex
149     *  with a path to it.
150     *  @return The other vertex or null.
151     *  @see #setLinkedVertex(Vertex)
152     */
153    public Vertex getLinkedVertex() {
154        return _linked;
155    }
156
157    /** Get the list of ports linked to this vertex.
158     *  @return A list of ports connected to this vertex.
159     */
160    public List linkedPorts() {
161        // FIXME: Perhaps this should return an unmodifiable version?
162        return _ports;
163    }
164
165    /** Remove the specified port from the list of ports linked to this vertex.
166     *  If the port is not linked, do nothing.
167     *  @param port The port to remove.
168     */
169    public void removeLinkedPort(Port port) {
170        if (_ports != null) {
171            _ports.remove(port);
172        }
173    }
174
175    /** Set the other vertex to which there is a path from this vertex.
176     *  If the argument is null, remove the path.
177     *  @param vertex The vertex to link to this one.
178     *  @see #getLinkedVertex()
179     */
180    public void setLinkedVertex(Vertex vertex) {
181        _linked = vertex;
182    }
183
184    /** Get a description of the class, which is the class name and
185     *  the location in parentheses.
186     *  @return A string describing the object.
187     */
188    @Override
189    public String toString() {
190        // FIXME add linked ports.
191        return super.toString();
192    }
193
194    ///////////////////////////////////////////////////////////////////
195    ////                         protected methods                 ////
196
197    /** Write a MoML description of the contents of this object, which
198     *  in this base class is the attributes.  This method is called
199     *  by _exportMoML().  If there are attributes, then
200     *  each attribute description is indented according to the specified
201     *  depth and terminated with a newline character.
202     *  @param output The output stream to write to.
203     *  @param depth The depth in the hierarchy, to determine indenting.
204     *  @exception IOException If an I/O error occurs.
205     *  @see ptolemy.kernel.util.NamedObj#_exportMoMLContents
206     */
207    @Override
208    protected void _exportMoMLContents(Writer output, int depth)
209            throws IOException {
210        super._exportMoMLContents(output, depth);
211
212        if (_linked != null) {
213            output.write(_getIndentPrefix(depth));
214            output.write("<pathTo=\"" + _linked.getName() + "\"/>\n");
215        }
216    }
217
218    ///////////////////////////////////////////////////////////////////
219    ////                         private variables                 ////
220    // The vertex that this attribute is connected to.
221    private Vertex _linked;
222
223    // The list of linked ports.
224    private LinkedList<Port> _ports;
225}