~ubuntu-branches/ubuntu/precise/weka/precise

« back to all changes in this revision

Viewing changes to weka/core/xml/XMLOptions.java

  • Committer: Bazaar Package Importer
  • Author(s): Soeren Sonnenburg
  • Date: 2008-02-24 09:18:45 UTC
  • Revision ID: james.westby@ubuntu.com-20080224091845-1l8zy6fm6xipbzsr
Tags: upstream-3.5.7+tut1
ImportĀ upstreamĀ versionĀ 3.5.7+tut1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *    This program is free software; you can redistribute it and/or modify
 
3
 *    it under the terms of the GNU General Public License as published by
 
4
 *    the Free Software Foundation; either version 2 of the License, or
 
5
 *    (at your option) any later version.
 
6
 *
 
7
 *    This program is distributed in the hope that it will be useful,
 
8
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
 *    GNU General Public License for more details.
 
11
 *
 
12
 *    You should have received a copy of the GNU General Public License
 
13
 *    along with this program; if not, write to the Free Software
 
14
 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
15
 */
 
16
 
 
17
/*
 
18
 * XMLOptions.java
 
19
 * Copyright (C) 2004 University of Waikato, Hamilton, New Zealand
 
20
 *
 
21
 */
 
22
 
 
23
package weka.core.xml;
 
24
 
 
25
import java.io.File;
 
26
import java.io.InputStream;
 
27
import java.io.Reader;
 
28
import java.util.Vector;
 
29
import org.w3c.dom.Document;
 
30
import org.w3c.dom.Element;
 
31
import org.w3c.dom.Node;
 
32
import org.w3c.dom.NodeList;
 
33
 
 
34
/**
 
35
 * A class for transforming options listed in XML to a regular WEKA command
 
36
 * line string.<p>
 
37
 *
 
38
 * @author FracPete (fracpete at waikato dot ac dot nz)
 
39
 * @version $Revision: 1.2 $
 
40
 */
 
41
public class XMLOptions {
 
42
   /** tag for a single option */
 
43
   public final static String TAG_OPTION = "option";
 
44
 
 
45
   /** tag for a list of options */
 
46
   public final static String TAG_OPTIONS = "options";
 
47
   
 
48
   /** the name attribute */
 
49
   public final static String ATT_NAME = "name";
 
50
   
 
51
   /** the type attribute */
 
52
   public final static String ATT_TYPE = "type";
 
53
   
 
54
   /** the value attribute */
 
55
   public final static String ATT_VALUE = "value";
 
56
   
 
57
   /** a value of the type attribute */
 
58
   public final static String VAL_TYPE_FLAG = "flag";
 
59
   
 
60
   /** a value of the type attribute */
 
61
   public final static String VAL_TYPE_SINGLE = "single";
 
62
   
 
63
   /** a value of the type attribute */
 
64
   public final static String VAL_TYPE_HYPHENS = "hyphens";
 
65
   
 
66
   /** a value of the type attribute */
 
67
   public final static String VAL_TYPE_QUOTES = "quotes";
 
68
   
 
69
   /** a value of the type attribute */
 
70
   public final static String VAL_TYPE_CLASSIFIER = "classifier";
 
71
 
 
72
   /** the root node */
 
73
   public final static String ROOT_NODE = TAG_OPTIONS;
 
74
   
 
75
   /** the DTD for the XML file */
 
76
   public final static String DOCTYPE = 
 
77
        "<!DOCTYPE " + ROOT_NODE + "\n"
 
78
      + "[\n"
 
79
      + "   <!ELEMENT " + TAG_OPTIONS + " (" + TAG_OPTION + ")*>\n"
 
80
      + "   <!ATTLIST " + TAG_OPTIONS + " " + ATT_TYPE + " CDATA \"classifier\">\n"
 
81
      + "   <!ATTLIST " + TAG_OPTIONS + " " + ATT_VALUE + " CDATA \"\">\n"
 
82
      + "   <!ELEMENT " + TAG_OPTION + " (#PCDATA | " + TAG_OPTIONS + ")*>\n"
 
83
      + "   <!ATTLIST " + TAG_OPTION + " " + ATT_NAME + " CDATA #REQUIRED>\n"
 
84
      + "   <!ATTLIST " + TAG_OPTION + " " + ATT_TYPE + " (flag | single | hyphens | quotes) \"single\">\n"
 
85
      + "]\n"
 
86
      + ">";
 
87
 
 
88
   /** the XML document */
 
89
   protected XMLDocument m_XMLDocument = null;
 
90
   
 
91
   /** 
 
92
    * Creates a new instance of XMLOptions 
 
93
    * @throws Exception if the construction of the DocumentBuilder fails
 
94
    * @see #setValidating(boolean)
 
95
    */
 
96
   public XMLOptions() throws Exception {
 
97
      m_XMLDocument = new XMLDocument(); 
 
98
      m_XMLDocument.setRootNode(ROOT_NODE);
 
99
      m_XMLDocument.setDocType(DOCTYPE);
 
100
      setValidating(true);
 
101
   }
 
102
   
 
103
   /** 
 
104
    * Creates a new instance of XMLOptions 
 
105
    * @param xml the xml to parse (if "<?xml" is not found then it is considered a file)
 
106
    * @throws Exception if the construction of the DocumentBuilder fails
 
107
    * @see #setValidating(boolean)
 
108
    */
 
109
   public XMLOptions(String xml) throws Exception {
 
110
      this();
 
111
      getXMLDocument().read(xml);
 
112
   }
 
113
   
 
114
   /** 
 
115
    * Creates a new instance of XMLOptions 
 
116
    * @param file the XML file to parse
 
117
    * @throws Exception if the construction of the DocumentBuilder fails
 
118
    * @see #setValidating(boolean)
 
119
    */
 
120
   public XMLOptions(File file) throws Exception {
 
121
      this();
 
122
      getXMLDocument().read(file);
 
123
   }
 
124
   
 
125
   /** 
 
126
    * Creates a new instance of XMLOptions 
 
127
    * @param stream the XML stream to parse
 
128
    * @throws Exception if the construction of the DocumentBuilder fails
 
129
    * @see #setValidating(boolean)
 
130
    */
 
131
   public XMLOptions(InputStream stream) throws Exception {
 
132
      this();
 
133
      getXMLDocument().read(stream);
 
134
   }
 
135
   
 
136
   /** 
 
137
    * Creates a new instance of XMLOptions 
 
138
    * @param reader the XML reader to parse
 
139
    * @throws Exception if the construction of the DocumentBuilder fails
 
140
    * @see #setValidating(boolean)
 
141
    */
 
142
   public XMLOptions(Reader reader) throws Exception {
 
143
      this();
 
144
      getXMLDocument().read(reader);
 
145
   }
 
146
   
 
147
   /**
 
148
    * returns whether a validating parser is used
 
149
    * @return whether a validating parser is used
 
150
    */
 
151
   public boolean getValidating() {
 
152
      return m_XMLDocument.getValidating();
 
153
   }
 
154
   
 
155
   /**
 
156
    * sets whether to use a validating parser or not. <br>
 
157
    * Note: this does clear the current DOM document! 
 
158
    * @param validating whether to use a validating parser
 
159
    * @throws Exception if the instantiating of the DocumentBuilder fails
 
160
    */
 
161
   public void setValidating(boolean validating) throws Exception {
 
162
       m_XMLDocument.setValidating(validating);
 
163
   }
 
164
   
 
165
   /**
 
166
    * returns the parsed DOM document
 
167
    * @return the parsed DOM document
 
168
    */
 
169
   public Document getDocument() {
 
170
      return fixHyphens(m_XMLDocument.getDocument());
 
171
   }
 
172
   
 
173
   /**
 
174
    * returns the handler of the XML document. the internal DOM document can 
 
175
    * be accessed via the <code>getDocument()</code> method.
 
176
    * @return the object handling the XML document
 
177
    * @see #getDocument()
 
178
    */
 
179
   public XMLDocument getXMLDocument() {
 
180
       return m_XMLDocument;
 
181
   }
 
182
   
 
183
   /**
 
184
    * pushes any options with type ATT_HYPHENS to the end, s.t. the "--" are
 
185
    * really added at the end
 
186
    * @param document the DOM document to work on
 
187
    * @return the fixed DOM document
 
188
    */
 
189
   protected Document fixHyphens(Document document) {
 
190
      NodeList          list;
 
191
      Vector            hyphens;
 
192
      int               i;
 
193
      Node              node;
 
194
      Node              tmpNode;
 
195
      boolean           isLast;
 
196
      
 
197
      // get all option tags
 
198
      list = document.getDocumentElement().getElementsByTagName(TAG_OPTION);
 
199
      
 
200
      // get all hyphen tags
 
201
      hyphens = new Vector();
 
202
      for (i = 0; i < list.getLength(); i++) {
 
203
         if (((Element) list.item(i)).getAttribute(ATT_TYPE).equals(VAL_TYPE_HYPHENS))
 
204
            hyphens.add(list.item(i));
 
205
      }
 
206
      
 
207
      // check all hyphen tags whether they are the end, if not fix it
 
208
      for (i = 0; i < hyphens.size(); i++) {
 
209
         node = (Node) hyphens.get(i);
 
210
         
 
211
         // at the end?
 
212
         isLast  = true;
 
213
         tmpNode = node;
 
214
         while (tmpNode.getNextSibling() != null) {
 
215
            // normal tag?
 
216
            if (tmpNode.getNextSibling().getNodeType() == Node.ELEMENT_NODE) {
 
217
               isLast = false;
 
218
               break;
 
219
            }
 
220
            tmpNode = tmpNode.getNextSibling();
 
221
         }
 
222
         
 
223
         // move
 
224
         if (!isLast) {
 
225
            tmpNode = node.getParentNode();
 
226
            tmpNode.removeChild(node);
 
227
            tmpNode.appendChild(node);
 
228
         }
 
229
      }
 
230
      
 
231
      return document;
 
232
   }
 
233
   
 
234
   /**
 
235
    * returns the quotes level for the given node, i.e. it returns the number 
 
236
    * of option's of the type "quotes" are in the path
 
237
    */
 
238
   protected int getQuotesLevel(Node node) {
 
239
      int         result;
 
240
      
 
241
      result = 0;
 
242
      while (node.getParentNode() != null) {
 
243
         if (!(node instanceof Element))
 
244
            continue;
 
245
         
 
246
         // option-tag?
 
247
         if (node.getNodeName().equals(TAG_OPTION)) {
 
248
            // types = quotes?
 
249
            if (((Element) node).getAttribute(ATT_TYPE).equals(VAL_TYPE_QUOTES))
 
250
               result++;
 
251
         }
 
252
 
 
253
         node = node.getParentNode();
 
254
      }
 
255
      
 
256
      return result;
 
257
   }
 
258
   
 
259
   /**
 
260
    * converts the given node into a command line representation and adds it
 
261
    * to the existing command line
 
262
    * @param cl the command line so far
 
263
    * @param parent the node to convert to command line
 
264
    * @param depth the current depth
 
265
    * @return the new command line
 
266
    */
 
267
   protected String toCommandLine(String cl, Element parent, int depth) {
 
268
      String            newCl;
 
269
      String            tmpCl;
 
270
      int               i;
 
271
      Vector            list;
 
272
      Vector            subList;
 
273
      NodeList          subNodeList;
 
274
      Element           node;
 
275
      
 
276
      newCl = "";
 
277
 
 
278
      // options
 
279
      if (parent.getNodeName().equals(TAG_OPTIONS)) {
 
280
         // classifier? -> add
 
281
         if (parent.getAttribute(ATT_TYPE).equals(VAL_TYPE_CLASSIFIER)) {
 
282
            newCl += parent.getAttribute(ATT_VALUE);
 
283
         }
 
284
         
 
285
         // process children
 
286
         list = XMLDocument.getChildTags(parent);
 
287
         for (i = 0; i < list.size(); i++)
 
288
            newCl = toCommandLine(newCl, (Element) list.get(i), depth + 1);
 
289
      }
 
290
      else
 
291
      // option
 
292
      if (parent.getNodeName().equals(TAG_OPTION)) {
 
293
         newCl       += " -" +  parent.getAttribute(ATT_NAME);
 
294
         subList      = XMLDocument.getChildTags(parent);
 
295
         subNodeList  = parent.getChildNodes();
 
296
 
 
297
         if (parent.getAttribute(ATT_TYPE).equals(VAL_TYPE_SINGLE)) {
 
298
            if ( (subNodeList.getLength() > 0) && (!subNodeList.item(0).getNodeValue().trim().equals("")) )
 
299
               newCl += " " + subNodeList.item(0).getNodeValue().trim();
 
300
         }
 
301
         else
 
302
         if (parent.getAttribute(ATT_TYPE).equals(VAL_TYPE_HYPHENS)) {
 
303
            newCl   += " " + ((Element) subList.get(0)).getAttribute(ATT_VALUE);  // expects classifier
 
304
            // get single options in this node
 
305
            subList  = XMLDocument.getChildTags((Element) subList.get(0));
 
306
            // get options after --
 
307
            tmpCl  = "";
 
308
            for (i = 0; i < subList.size(); i++)
 
309
               tmpCl = toCommandLine(tmpCl, (Element) subList.get(i), depth + 1);
 
310
            // add options
 
311
            tmpCl = tmpCl.trim();
 
312
            if (!tmpCl.equals(""))
 
313
               newCl += " -- " + tmpCl;
 
314
         }
 
315
         else
 
316
         if (parent.getAttribute(ATT_TYPE).equals(VAL_TYPE_QUOTES)) {
 
317
            newCl += " ";
 
318
            // opening quote
 
319
            for (i = 1; i < getQuotesLevel(parent); i++)
 
320
               newCl += "\\";
 
321
            newCl += "\"";
 
322
            // options
 
323
            tmpCl = "";
 
324
            for (i = 0; i < subList.size(); i++)
 
325
               tmpCl = toCommandLine(tmpCl, (Element) subList.get(i), depth + 1);
 
326
            newCl += tmpCl.trim();
 
327
            // closing quote
 
328
            for (i = 1; i < getQuotesLevel(parent); i++)
 
329
               newCl += "\\";
 
330
            newCl += "\"";
 
331
         }
 
332
      }
 
333
      
 
334
      // add to existing command line
 
335
      cl += " " + newCl.trim();
 
336
      
 
337
      return cl.trim();
 
338
   }
 
339
   
 
340
   /**
 
341
    * returns the given DOM document as command line
 
342
    * @return the document as command line
 
343
    * @throws Exception if anything goes wrong initializing the parsing
 
344
    */
 
345
   public String toCommandLine() throws Exception {
 
346
      return toCommandLine(new String(), getDocument().getDocumentElement(), 0);
 
347
   }
 
348
   
 
349
   /**
 
350
    * returns the current DOM document as string array (takes care of quotes!)
 
351
    * @return the document as string array
 
352
    * @throws Exception if anything goes wrong initializing the parsing
 
353
    */
 
354
   public String[] toArray() throws Exception {
 
355
       String         cl;
 
356
       Vector         result;
 
357
       boolean        quotes;
 
358
       boolean        backslash;
 
359
       boolean        add;
 
360
       int            i;
 
361
       String         tmpStr;
 
362
       
 
363
       cl     = toCommandLine();
 
364
       result = new Vector();
 
365
       
 
366
       // break up string
 
367
       quotes    = false;
 
368
       backslash = false;
 
369
       tmpStr    = "";
 
370
       for (i = 0; i < cl.length(); i++) {
 
371
          add = true;
 
372
          
 
373
          switch (cl.charAt(i)) {
 
374
             case '\\' :
 
375
                backslash = true;
 
376
                break;
 
377
                
 
378
             case '"' :
 
379
                // can we toggle quotes? (ignore nested quotes)
 
380
                if (!backslash) {
 
381
                   quotes = !quotes;
 
382
                   add    = false;
 
383
                }
 
384
                backslash = false;
 
385
                break;
 
386
               
 
387
             case ' ' :
 
388
                // if not quoted then break!
 
389
                if (!quotes) {
 
390
                   result.add(tmpStr.replaceAll("\\\\\"", "\""));
 
391
                   add    = false;
 
392
                   tmpStr = "";
 
393
                }
 
394
                break;
 
395
          }
 
396
 
 
397
          if (add)
 
398
             tmpStr += "" + cl.charAt(i);
 
399
       }
 
400
       
 
401
       // add last part
 
402
       if (!tmpStr.equals(""))
 
403
          result.add(tmpStr);
 
404
       
 
405
       return (String[]) result.toArray(new String[1]);
 
406
   }
 
407
   
 
408
   /**
 
409
    * returns the object in a string representation (as indented XML output)
 
410
    * 
 
411
    * @return the object in a string representation
 
412
    */
 
413
   public String toString() {
 
414
      return getXMLDocument().toString();
 
415
   }
 
416
   
 
417
   /**
 
418
    * for testing only. prints the given XML, the resulting commandline and
 
419
    * the string array.
 
420
    */
 
421
   public static void main(String[] args) throws Exception {
 
422
      if (args.length > 0) {
 
423
         System.out.println("\nXML:\n\n" + new XMLOptions(args[0]).toString()); 
 
424
          
 
425
         System.out.println("\nCommandline:\n\n" + new XMLOptions(args[0]).toCommandLine());
 
426
         
 
427
         System.out.println("\nString array:\n");
 
428
         String[] options = new XMLOptions(args[0]).toArray();
 
429
         for (int i = 0; i < options.length; i++)
 
430
            System.out.println(options[i]);
 
431
      }
 
432
   }
 
433
}