001/* An action that generates the Moml for a group of states to be used as a
002 design pattern.
003
004 Copyright (c) 2008-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 */
029package ptolemy.actor;
030
031import java.io.StringWriter;
032import java.util.HashMap;
033import java.util.HashSet;
034import java.util.List;
035
036import ptolemy.data.BooleanToken;
037import ptolemy.data.expr.Parameter;
038import ptolemy.data.expr.StringParameter;
039import ptolemy.kernel.ComponentEntity;
040import ptolemy.kernel.ComponentRelation;
041import ptolemy.kernel.CompositeEntity;
042import ptolemy.kernel.Port;
043import ptolemy.kernel.util.Attribute;
044import ptolemy.kernel.util.InternalErrorException;
045import ptolemy.kernel.util.NamedObj;
046import ptolemy.util.StringUtilities;
047
048/**
049  An action that generates the Moml for a group of states to be used as a
050  design pattern.
051
052  @author Thomas Huining Feng
053  @version $Id$
054  @since Ptolemy II 8.0
055  @Pt.ProposedRating Red (tfeng)
056  @Pt.AcceptedRating Red (tfeng)
057 */
058public class DesignPatternGetMoMLAction {
059
060    /** Generate the Moml string for the given object. If the object is a group
061     *  of states, then the contents of the group are generated; otherwise, the
062     *  Moml of the object itself is generated with {@link
063     *  NamedObj#exportMoML(String)}.
064     *
065     *  @param object The object.
066     *  @param name The name to be used for the object in the generated Moml.
067     *  @return The Moml string.
068     */
069    public String getMoml(NamedObj object, String name) {
070        CompositeEntity group = (CompositeEntity) object;
071        Attribute before = object.getAttribute("Before");
072        Attribute after = object.getAttribute("After");
073        StringWriter buffer = new StringWriter();
074        int extraIndent = 0;
075        try {
076            buffer.write("<group>\n");
077
078            if (before != null) {
079                String oldType = null;
080                StringParameter typeParameter = (StringParameter) before
081                        .getAttribute("_type");
082                if (typeParameter == null) {
083                    typeParameter = new StringParameter(before, "_type");
084                } else {
085                    oldType = typeParameter.getExpression();
086                }
087                typeParameter.setExpression("immediate");
088                try {
089                    buffer.write(
090                            StringUtilities.getIndentPrefix(1) + "<group>\n");
091                    before.exportMoML(buffer, 2);
092                    buffer.write(
093                            StringUtilities.getIndentPrefix(1) + "</group>\n");
094                } finally {
095                    if (oldType == null) {
096                        typeParameter.setContainer(null);
097                    } else {
098                        typeParameter.setExpression(oldType);
099                    }
100                }
101            }
102
103            if (after != null || before != null) {
104                extraIndent++;
105                buffer.write(StringUtilities.getIndentPrefix(extraIndent)
106                        + "<group>\n");
107            }
108
109            List<Attribute> attributes = group.attributeList();
110            for (Attribute attribute : attributes) {
111                if (!_IGNORED_ATTRIBUTES.contains(attribute.getName())
112                        && (after == null || attribute != after)
113                        && (before == null || attribute != before)) {
114                    attribute.exportMoML(buffer, extraIndent + 1);
115                    if (attribute instanceof Parameter) {
116                        String parameterName = attribute.getName();
117                        String expression = _overriddenParameters
118                                .get(parameterName);
119                        if (expression != null) {
120                            buffer.write(StringUtilities
121                                    .getIndentPrefix(extraIndent + 1)
122                                    + "<property name=\"" + parameterName
123                                    + "\" value=\"" + expression + "\">\n");
124                            buffer.write(StringUtilities.getIndentPrefix(
125                                    extraIndent + 1) + "</property>\n");
126                        }
127                    }
128                }
129            }
130
131            List<Port> ports = group.portList();
132            for (Port port : ports) {
133                buffer.write(StringUtilities.getIndentPrefix(extraIndent + 1)
134                        + "<port name=\"" + port.getName() + "\">\n");
135                if (port instanceof IOPort) {
136                    IOPort ioPort = (IOPort) port;
137                    boolean isInput = ioPort.isInput();
138                    boolean isOutput = ioPort.isOutput();
139                    if (isInput) {
140                        buffer.write(
141                                StringUtilities.getIndentPrefix(extraIndent + 2)
142                                        + "<property name=\"input\"/>\n");
143                    }
144                    if (isOutput) {
145                        buffer.write(
146                                StringUtilities.getIndentPrefix(extraIndent + 2)
147                                        + "<property name=\"output\"/>\n");
148                    }
149                    if (ioPort.isMultiport()) {
150                        buffer.write(
151                                StringUtilities.getIndentPrefix(extraIndent + 2)
152                                        + "<property name=\"multiport\"/>\n");
153                    }
154                }
155                attributes = port.attributeList();
156                for (Attribute attribute : attributes) {
157                    if (!_IGNORED_ATTRIBUTES.contains(attribute.getName())) {
158                        attribute.exportMoML(buffer, extraIndent + 2);
159                    }
160                }
161                buffer.write(StringUtilities.getIndentPrefix(extraIndent + 1)
162                        + "</port>\n");
163            }
164
165            List<ComponentEntity> classes = group.classDefinitionList();
166            for (ComponentEntity entity : classes) {
167                Attribute attribute = entity.getAttribute("_noAutonaming");
168                if (attribute != null
169                        && ((BooleanToken) ((Parameter) attribute).getToken())
170                                .booleanValue()) {
171                    entity.exportMoML(buffer, extraIndent + 2);
172                }
173            }
174
175            List<ComponentEntity> entities = group.entityList();
176            for (ComponentEntity entity : entities) {
177                Attribute attribute = entity.getAttribute("_noAutonaming");
178                if (attribute != null
179                        && ((BooleanToken) ((Parameter) attribute).getToken())
180                                .booleanValue()) {
181                    entity.exportMoML(buffer, extraIndent + 2);
182                }
183            }
184
185            buffer.write(StringUtilities.getIndentPrefix(extraIndent + 1)
186                    + "<group name=\"auto\">\n");
187
188            classes = group.classDefinitionList();
189            for (ComponentEntity entity : classes) {
190                Attribute attribute = entity.getAttribute("_noAutonaming");
191                if (attribute == null
192                        || !((BooleanToken) ((Parameter) attribute).getToken())
193                                .booleanValue()) {
194                    entity.exportMoML(buffer, extraIndent + 2);
195                }
196            }
197
198            entities = group.entityList();
199            for (ComponentEntity entity : entities) {
200                Attribute attribute = entity.getAttribute("_noAutonaming");
201                if (attribute == null
202                        || !((BooleanToken) ((Parameter) attribute).getToken())
203                                .booleanValue()) {
204                    entity.exportMoML(buffer, extraIndent + 2);
205                }
206            }
207
208            List<ComponentRelation> relations = group.relationList();
209            for (ComponentRelation relation : relations) {
210                relation.exportMoML(buffer, extraIndent + 2);
211            }
212
213            buffer.write(group.exportLinks(extraIndent + 2, null));
214            buffer.write(StringUtilities.getIndentPrefix(extraIndent + 1)
215                    + "</group>\n");
216            if (after != null || before != null) {
217                buffer.write(StringUtilities.getIndentPrefix(extraIndent)
218                        + "</group>\n");
219            }
220
221            if (after != null) {
222                String oldType = null;
223                StringParameter typeParameter = (StringParameter) after
224                        .getAttribute("_type");
225                if (typeParameter == null) {
226                    typeParameter = new StringParameter(after, "_type");
227                } else {
228                    oldType = typeParameter.getExpression();
229                }
230                typeParameter.setExpression("delayed");
231                try {
232                    buffer.write(
233                            StringUtilities.getIndentPrefix(1) + "<group>\n");
234                    after.exportMoML(buffer, 2);
235                    buffer.write(
236                            StringUtilities.getIndentPrefix(1) + "</group>\n");
237                } finally {
238                    if (oldType == null) {
239                        typeParameter.setContainer(null);
240                    } else {
241                        typeParameter.setExpression(oldType);
242                    }
243                }
244            }
245
246            buffer.write("</group>\n");
247
248            return buffer.toString();
249        } catch (Throwable throwable) {
250            // This should not occur.
251            throw new InternalErrorException(null, throwable,
252                    "Unable to get the " + "Moml content for group "
253                            + group.getName() + ".");
254        }
255    }
256
257    /** Add a parameter and expression to the map of parameters
258     *  to override.
259     *  @param name The name of the parameter.
260     *  @param expression The expression of the parameter.
261     */
262    public void overrideParameter(String name, String expression) {
263        _overriddenParameters.put(name, expression);
264    }
265
266    /** The set of attribute names that need to be ignored while generating
267     *  the Moml.
268     */
269    private static final HashSet<String> _IGNORED_ATTRIBUTES = new HashSet<String>();
270
271    private HashMap<String, String> _overriddenParameters = new HashMap<String, String>();
272
273    static {
274        _IGNORED_ATTRIBUTES.add("GroupIcon");
275        _IGNORED_ATTRIBUTES.add("_alternateGetMomlAction");
276        _IGNORED_ATTRIBUTES.add("_createdBy");
277        _IGNORED_ATTRIBUTES.add("_designPatternIcon");
278        _IGNORED_ATTRIBUTES.add("_hideName");
279        _IGNORED_ATTRIBUTES.add("_vergilSize");
280        _IGNORED_ATTRIBUTES.add("_vergilZoomFactor");
281        _IGNORED_ATTRIBUTES.add("_vergilCenter");
282        _IGNORED_ATTRIBUTES.add("_windowProperties");
283    }
284}