001/* An attribute that contains documentation for the container.
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.Iterator;
033import java.util.List;
034
035import ptolemy.kernel.util.ChangeRequest;
036import ptolemy.kernel.util.IllegalActionException;
037import ptolemy.kernel.util.InternalErrorException;
038import ptolemy.kernel.util.NameDuplicationException;
039import ptolemy.kernel.util.NamedObj;
040import ptolemy.kernel.util.Settable;
041import ptolemy.kernel.util.StringAttribute;
042import ptolemy.util.StringUtilities;
043
044///////////////////////////////////////////////////////////////////
045//// Documentation
046
047/**
048 An attribute that contains documentation for the container.
049 <p>
050 The name of a documentation object can often be meaningful.  Many times
051 the name can be used to specify important information about the type of
052 documentation.  Unfortunately, all documentation objects are currently
053 treated the same.
054
055 @author  Edward A. Lee
056 @version $Id$
057 @since Ptolemy II 0.4
058 @Pt.ProposedRating Yellow (eal)
059 @Pt.AcceptedRating Yellow (neuendor)
060 */
061public class Documentation extends StringAttribute {
062    /** Construct an attribute with the specified container and name.
063     *  The documentation contained by the attribute is initially empty,
064     *  but can be set using the setValue() method.
065     *  @param container The container.
066     *  @param name The name of the attribute.
067     *  @exception IllegalActionException If the attribute is not of an
068     *   acceptable class for the container.
069     *  @exception NameDuplicationException If the name coincides with
070     *   an attribute already in the container.
071     */
072    public Documentation(NamedObj container, String name)
073            throws IllegalActionException, NameDuplicationException {
074        super(container, name);
075        setVisibility(Settable.EXPERT);
076    }
077
078    ///////////////////////////////////////////////////////////////////
079    ////                         public methods                    ////
080
081    /** Return as a single string all the documentation associated with
082     *  the specified object.  Each attribute of type of class Documentation
083     *  that the object contains contributes to the documentation.
084     *  The text contributed by each such attribute starts on a new line.
085     *  If there are no such attributes, then null is returned.
086     *  @param object The object to document.
087     *  @return The documentation for the object.
088     */
089    public static String consolidate(NamedObj object) {
090        List docList = object.attributeList(Documentation.class);
091
092        if (docList.size() > 0) {
093            StringBuffer doc = new StringBuffer();
094            Iterator segments = docList.iterator();
095
096            while (segments.hasNext()) {
097                Documentation segment = (Documentation) segments.next();
098                doc.append(segment.getValueAsString());
099
100                if (segments.hasNext()) {
101                    doc.append("\n");
102                }
103            }
104
105            return doc.toString();
106        } else {
107            return null;
108        }
109    }
110
111    /** Write a MoML description of this object with the specified
112     *  indentation depth.  This class is directly supported by the MoML
113     *  "doc" element, so we generate MoML of the form
114     *  "&lt;doc&gt;<i>documentation</i>&lt;/doc&gt;", where
115     *  <i>documentation</i> is replaced by the string value of this
116     *  attribute. If this object is not persistent, then write nothing.
117     *  @param output The output stream to write to.
118     *  @param depth The depth in the hierarchy, to determine indenting.
119     *  @param name The name to use instead of the current name.
120     *  @exception IOException If an I/O error occurs.
121     *  @see NamedObj#_exportMoMLContents
122     *  @see #isPersistent()
123     */
124    @Override
125    public void exportMoML(Writer output, int depth, String name)
126            throws IOException {
127        if (_isMoMLSuppressed(depth)) {
128            return;
129        }
130
131        if (name.equals("_doc")) {
132            // Name is the default name.  Omit.
133            output.write(_getIndentPrefix(depth) + "<doc>"
134                    + StringUtilities.escapeForXML(getExpression())
135                    + "</doc>\n");
136        } else {
137            // Name is not the default name.
138            output.write(_getIndentPrefix(depth) + "<doc name=\"" + name + "\">"
139                    + StringUtilities.escapeForXML(getExpression())
140                    + "</doc>\n");
141        }
142    }
143
144    /** Override the base class to remove this instance from
145     *  its container if the argument is an empty string.
146     *  The removal is done in a change request, so it may
147     *  not take effect immediately.
148     *  @param expression The value of the string attribute.
149     *  @exception IllegalActionException If the change is not acceptable
150     *   to the container.
151     */
152    @Override
153    public void setExpression(String expression) throws IllegalActionException {
154        if (expression.equals("")) {
155            ChangeRequest request = new ChangeRequest(this,
156                    "Delete empty doc tag.") {
157                @Override
158                protected void _execute() throws Exception {
159                    setContainer(null);
160                }
161            };
162
163            requestChange(request);
164        } else {
165            super.setExpression(expression);
166        }
167    }
168
169    /** Set the documentation string.
170     *  @param value The documentation.
171     *  @see #getValueAsString()
172     */
173    public void setValue(String value) {
174        try {
175            setExpression(value);
176        } catch (IllegalActionException e) {
177            throw new InternalErrorException(e);
178        }
179    }
180
181    /** Get the documentation as a string, with the class name prepended.
182     *  @return A string describing the object.
183     */
184    @Override
185    public String toString() {
186        return "(" + getClass().getName() + ", " + getExpression() + ")";
187    }
188}