View Javadoc

1   /*
2    * Copyright 2007 - 2008 JEuclid, http://jeuclid.sf.net
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  /* $Id: Mml2xxx.java,v 06749543c58f 2008/08/22 13:26:52 maxberger $ */
18  
19  package net.sourceforge.jeuclid.app;
20  
21  import java.io.File;
22  import java.io.IOException;
23  import java.util.ArrayList;
24  import java.util.Arrays;
25  import java.util.List;
26  import java.util.Locale;
27  
28  import net.sourceforge.jeuclid.LayoutContext;
29  import net.sourceforge.jeuclid.MutableLayoutContext;
30  import net.sourceforge.jeuclid.context.LayoutContextImpl;
31  import net.sourceforge.jeuclid.context.Parameter;
32  import net.sourceforge.jeuclid.context.typewrapper.EnumTypeWrapper;
33  import net.sourceforge.jeuclid.context.typewrapper.TypeWrapper;
34  import net.sourceforge.jeuclid.converter.Converter;
35  import net.sourceforge.jeuclid.converter.ConverterRegistry;
36  
37  import org.apache.commons.cli.CommandLine;
38  import org.apache.commons.cli.GnuParser;
39  import org.apache.commons.cli.HelpFormatter;
40  import org.apache.commons.cli.Option;
41  import org.apache.commons.cli.Options;
42  import org.apache.commons.cli.ParseException;
43  import org.apache.commons.lang.StringUtils;
44  
45  /**
46   * Utility class to be used from the command line to call the converters.
47   * 
48   * @version $Revision: 06749543c58f $
49   */
50  // CHECKSTYLE:OFF
51  // Data abstraction coupling is too high. But it makes no sense to split up
52  // this class.
53  public final class Mml2xxx {
54      // CHECKSTYLE:ON
55  
56      private static final String OUT_FILE_TYPE = "outFileType";
57  
58      private static final String DEFAULT_TYPE = "image/png";
59  
60      private Mml2xxx() {
61          // Empty on purpose
62      }
63  
64      private static Options createOptions() {
65          final Options options = new Options();
66          final Option oft = new Option(Mml2xxx.OUT_FILE_TYPE, true,
67                  "output file mime type [default: derived from the target file's extention]"
68                          + "; available values are: "
69                          + StringUtils.join(ConverterRegistry.getInstance()
70                                  .getAvailableOutfileTypes().iterator(), ' '));
71          options.addOption(oft);
72          final LayoutContext defaultCtx = LayoutContextImpl
73                  .getDefaultLayoutContext();
74          for (final Parameter param : Parameter.values()) {
75              final TypeWrapper typeWrapper = param.getTypeWrapper();
76              final StringBuilder desc = new StringBuilder(param
77                      .getOptionDesc());
78              final String defValue = param.toString(defaultCtx
79                      .getParameter(param));
80              if (defValue != null) {
81                  desc.append(" [default: ").append(defValue).append("]");
82              }
83              final Option o = new Option(param.getOptionName(), true, desc
84                      .toString());
85              String argName = param.getTypeWrapper().getValueType()
86                      .getSimpleName().toLowerCase(Locale.ENGLISH);
87              if (typeWrapper instanceof EnumTypeWrapper) {
88                  argName = StringUtils.join(((EnumTypeWrapper) typeWrapper)
89                          .values(), '|');
90              }
91              o.setArgName(argName);
92              options.addOption(o);
93          }
94          return options;
95      }
96  
97      /**
98       * Main function for use from scripts.
99       * 
100      * @param args
101      *            command line arguments.
102      */
103     public static void main(final String[] args) {
104         final Options options = Mml2xxx.createOptions();
105         CommandLine cmdLine = null;
106         try {
107             cmdLine = new GnuParser().parse(options, args);
108 
109             final List<String> files = Arrays.asList(cmdLine.getArgs());
110             if (files.size() < 2) {
111                 throw new ParseException("Not enough arguments!");
112             }
113             final int sourceCount = files.size() - 1;
114             final File lastFile = new File(files.get(sourceCount));
115             final boolean multi = lastFile.isDirectory();
116             final List<File> sources = Mml2xxx.createListOfSourceFiles(files,
117                     sourceCount);
118 
119             final MutableLayoutContext ctx = Mml2xxx
120                     .createLayoutContext(cmdLine);
121             if (multi) {
122                 Mml2xxx.convertMultipleFiles(cmdLine, lastFile, sources, ctx);
123             } else {
124                 if (sources.size() != 1) {
125                     throw new ParseException(
126                             "Too many file arguments. Did you want to add a target directory?");
127                 }
128                 final String outFileType = Mml2xxx.findOutfileType(cmdLine,
129                         lastFile.getName());
130                 Converter.getInstance().convert(sources.get(0), lastFile,
131                         outFileType, ctx);
132             }
133         } catch (final ParseException pe) {
134             System.err.println(pe);
135             Mml2xxx.showUsage(options);
136             System.exit(1);
137         } catch (final IOException ioe) {
138             System.err.println("Error encountered during converion process");
139             ioe.printStackTrace(System.err);
140             System.exit(2);
141         } catch (final IllegalArgumentException iae) {
142             System.err.println(iae);
143             Mml2xxx.showUsage(options);
144             System.exit(1);
145         }
146     }
147 
148     private static void convertMultipleFiles(final CommandLine cmdLine,
149             final File lastFile, final List<File> sources,
150             final MutableLayoutContext layoutContext) throws ParseException,
151             IOException {
152         final String outFileType = Mml2xxx.findOutfileType(cmdLine, null);
153         for (final File source : sources) {
154             final String fileName = source.getName();
155             final int dotpos = fileName.lastIndexOf('.');
156             final String baseName;
157             if (dotpos >= 0) {
158                 baseName = fileName.substring(0, dotpos);
159             } else {
160                 baseName = fileName;
161             }
162             final File target = new File(lastFile, baseName
163                     + '.'
164                     + ConverterRegistry.getInstance().getSuffixForMimeType(
165                             outFileType));
166             Converter.getInstance().convert(source, target, outFileType,
167                     layoutContext);
168         }
169     }
170 
171     private static List<File> createListOfSourceFiles(
172             final List<String> files, final int count) throws ParseException {
173         final List<File> sources = new ArrayList<File>(count);
174         for (int i = 0; i < count; i++) {
175             final String current = files.get(i);
176             final File source = new File(current);
177             if (!source.isFile() || !source.canRead()) {
178                 throw new ParseException(current
179                         + " is not a file or not readable");
180             }
181             sources.add(source);
182         }
183         return sources;
184     }
185 
186     private static String findOutfileType(final CommandLine cmdLine,
187             final String fileName) throws ParseException {
188         String outFileType = cmdLine.getOptionValue(Mml2xxx.OUT_FILE_TYPE);
189         final String isNotSupported = " is not supported";
190         if ((outFileType == null) && (fileName != null)) {
191             final int dot = fileName.lastIndexOf('.');
192             if (dot != -1 && dot != fileName.length() - 1) {
193                 final String extension = fileName.substring(dot + 1);
194                 outFileType = ConverterRegistry.getInstance()
195                         .getMimeTypeForSuffix(extension);
196             }
197         }
198         if (outFileType == null) {
199             System.out.println("No ouput type could be detected, assuming "
200                     + Mml2xxx.DEFAULT_TYPE);
201             outFileType = Mml2xxx.DEFAULT_TYPE;
202         } else {
203             if (!ConverterRegistry.getInstance().getAvailableOutfileTypes()
204                     .contains(outFileType)) {
205                 throw new IllegalArgumentException("Output type "
206                         + outFileType + isNotSupported);
207             }
208         }
209         return outFileType;
210     }
211 
212     private static MutableLayoutContext createLayoutContext(
213             final CommandLine cmdLine) {
214         final MutableLayoutContext ctx = new LayoutContextImpl(
215                 LayoutContextImpl.getDefaultLayoutContext());
216         for (final Parameter param : Parameter.values()) {
217             final String value = cmdLine
218                     .getOptionValue(param.getOptionName());
219             if (value != null) {
220                 ctx.setParameter(param, param.fromString(value));
221             }
222         }
223         return ctx;
224     }
225 
226     private static void showUsage(final Options options) {
227         final HelpFormatter hf = new HelpFormatter();
228         final String lineSep = hf.getNewLine();
229         hf
230                 .printHelp(
231                         "mml2xxx <source file(s)> <target file/directory> [options]",
232                         "source is the path to the source file (MathML or ODF format)"
233                                 + lineSep
234                                 + "target is the path to the target file / directory"
235                                 + lineSep
236                                 + "If multiple source files are given, target must be a directory",
237                         options,
238                         "Example: mml2xxx a.mml a.png -backgroundColor white");
239     }
240 
241 }