001/**
002 A filter for backward compatibility with 7.2.devel or earlier models for width inference.
003
004 Copyright (c) 2008-2015 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.moml.filter;
030
031import java.io.File;
032import java.io.FileWriter;
033import java.io.InputStream;
034import java.net.URL;
035import java.util.Locale;
036
037import ptolemy.actor.IORelation;
038import ptolemy.data.IntToken;
039import ptolemy.kernel.util.NamedObj;
040import ptolemy.moml.MoMLParser;
041
042///////////////////////////////////////////////////////////////////
043//// ChangeFixedWidth1ToAuto
044
045/** When this class is registered with the MoMLParser.setMoMLFilter()
046 method, it will cause MoMLParser to filter so that models from
047 earlier releases will run in the current release.
048 This class will filter for relations that have a fixed width of 1.
049 The width value will be changed to AUto, which is the new default
050 for width inference.
051
052 @author Bert Rodiers
053 @version $Id$
054 @since Ptolemy II 8.0
055 @Pt.ProposedRating Red (rodiers)
056 @Pt.AcceptedRating Red (rodiers)
057 */
058public class ChangeFixedWidth1ToAuto extends MoMLFilterSimple {
059
060    ///////////////////////////////////////////////////////////////////
061    ////                         public methods                    ////
062
063    /** This method doesn't do anything.
064     *  @param container  The container for XML element.
065     *  @param element The XML element name.
066     *  @param attributeName The name of the attribute.
067     *  @param attributeValue The value of the attribute.
068     *  @param xmlFile The file currently being parsed.
069     *  @return A new value for the attribute, or the same value
070     *   to leave it unchanged, or null to cause the current element
071     *   to be ignored (unless the attributeValue argument is null).
072     */
073    @Override
074    public String filterAttributeValue(NamedObj container, String element,
075            String attributeName, String attributeValue, String xmlFile) {
076        return attributeValue;
077    }
078
079    /** Filter relations widths and change 1 to "Auto" and make sure still value
080     * is not not stored (if not changed).
081     *
082     *  @param container The object defined by the element that this
083     *   is the end of.
084     *  @param elementName The element name.
085     *  @param currentCharData The character data, which appears
086     *   only in the doc and configure elements
087     *  @param xmlFile The file currently being parsed.
088     *  @exception Exception If there is a problem modifying the
089     *  specified container.
090     */
091    @Override
092    public void filterEndElement(NamedObj container, String elementName,
093            StringBuffer currentCharData, String xmlFile) throws Exception {
094        if (container instanceof IORelation) {
095            IORelation relation = (IORelation) container;
096            IntToken t = (IntToken) relation.width.getToken();
097
098            if (t != null) {
099                int width = t.intValue();
100
101                if (width == 1) {
102                    madeModification = true;
103                    relation.width.setToken("Auto");
104                    relation.width.setDerivedLevel(1);
105                    // Make it derived to make sure it is not
106                    // saved if not changed.
107                }
108            }
109        }
110    }
111
112    /** Main function. Changes fixed relation width equal to 1 to "Auto" and save the model. The resulting width
113     * won't be saved in practice.
114     * @param args The arguments of the main function.
115     * @exception Exception If the model can't be converted.
116     */
117    public static void main(String[] args) throws Exception {
118        String errorMessage = "Usage: \n\tConvert one model:\n\t\tjava -classpath $PTII "
119                + "ptolemy.moml.filter.ChangeFixedWidth1ToAuto model.xml\n\tConvert all models in a folder:\n\t"
120                + "\tjava -classpath $PTII "
121                + "ptolemy.moml.filter.ChangeFixedWidth1ToAuto -all path\n\tConvert all models in a demo folder:\n\t\tjava -classpath $PTII "
122                + "ptolemy.moml.filter.ChangeFixedWidth1ToAuto -demo path";
123        if (args.length != 1 && args.length != 2) {
124            System.err.println(errorMessage);
125            return;
126        }
127
128        if (args.length == 1) {
129            _updateFile(args[0]);
130        }
131
132        if (args.length == 2) {
133            if (!args[0].equals("-all") && !args[0].equals("-demo")) {
134                System.err.println(errorMessage);
135                return;
136            }
137            _updateXMLFiles(new File(args[1]),
138                    args[0].equals("-demo") ? "demo" : null);
139        }
140    }
141
142    /** Return a string that describes what the filter does.
143     *  @return A description of the filter (ending with a newline).
144     */
145    @Override
146    public String toString() {
147        return Integer.toHexString(hashCode());
148    }
149
150    ///////////////////////////////////////////////////////////////////
151    ////                         private methods                   ////
152
153    /** Convert the models in the folder.
154     * @param folder The folder in which models need to be converted.
155     * @param filter If null, no filter will be applied. On models for which
156     * the path contains "/" + filter + "/" are converted.
157     */
158    private static void _updateXMLFiles(File folder, String filter) {
159        File[] files = folder.listFiles();
160
161        if (files != null) {
162            for (File file : files) {
163                if (file.isFile()) {
164                    String filename = file.getName();
165                    int length = filename.length();
166                    if (length > 3 && filename.substring(length - 4, length)
167                            .toLowerCase(Locale.getDefault()).equals(".xml")) {
168                        try {
169                            if (filter == null || file.toURI().toString()
170                                    .toLowerCase(Locale.getDefault())
171                                    .contains("/" + filter + "/")) {
172                                _updateFile(file.toString());
173                            }
174                        } catch (Exception e) {
175                            continue;
176                        }
177                    }
178                } else if (file.isDirectory()) {
179                    _updateXMLFiles(file, filter);
180                }
181            }
182        } else {
183            throw new NullPointerException(
184                    "Getting the files of \"" + folder + "\" returned null?");
185        }
186    }
187
188    /** Convert the model with name fileName.
189     * @param fileName The name (and path) of the model
190     * @exception Exception If the model can't be converted
191     */
192    private static void _updateFile(String fileName) throws Exception {
193        MoMLParser parser = new MoMLParser();
194        MoMLParser.setMoMLFilters(null);
195        MoMLParser.addMoMLFilters(BackwardCompatibility.allFilters());
196        ChangeFixedWidth1ToAuto filter = new ChangeFixedWidth1ToAuto();
197        MoMLParser.addMoMLFilter(filter);
198
199        URL xmlFile = ChangeFixedWidth1ToAuto.class.getClassLoader()
200                .getResource(fileName);
201
202        if (xmlFile != null) {
203            InputStream input = xmlFile.openStream();
204            NamedObj model = parser.parse(null, fileName, input);
205            input.close();
206            if (model != null && filter.madeModification) {
207                System.out.println("Start updating " + fileName);
208                FileWriter file = null;
209                try {
210                    file = new FileWriter(fileName);
211                    model.exportMoML(file, 0);
212                } finally {
213                    if (file != null) {
214                        file.close();
215                    }
216                }
217                System.out.println("End updating " + fileName);
218            }
219        }
220    }
221
222    ///////////////////////////////////////////////////////////////////
223    ////                         private variables                 ////
224
225    /** Keep track of modifications.*/
226    private boolean madeModification = false;
227
228}