weka.core.xml.XMLOptions Maven / Gradle / Ivy
Show all versions of weka-dev Show documentation
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
/*
* XMLOptions.java
* Copyright (C) 2004-2012 University of Waikato, Hamilton, New Zealand
*
*/
package weka.core.xml;
import java.io.File;
import java.io.InputStream;
import java.io.Reader;
import java.util.Vector;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import weka.core.RevisionHandler;
import weka.core.RevisionUtils;
import weka.core.Utils;
/**
* A class for transforming options listed in XML to a regular WEKA command line
* string.
*
*
* @author FracPete (fracpete at waikato dot ac dot nz)
* @version $Revision: 10203 $
*/
public class XMLOptions implements RevisionHandler {
/** tag for a single option. */
public final static String TAG_OPTION = "option";
/** tag for a list of options. */
public final static String TAG_OPTIONS = "options";
/** the name attribute. */
public final static String ATT_NAME = "name";
/** the type attribute. */
public final static String ATT_TYPE = "type";
/** the value attribute. */
public final static String ATT_VALUE = "value";
/** a value of the type attribute. */
public final static String VAL_TYPE_FLAG = "flag";
/** a value of the type attribute. */
public final static String VAL_TYPE_SINGLE = "single";
/** a value of the type attribute. */
public final static String VAL_TYPE_HYPHENS = "hyphens";
/** a value of the type attribute. */
public final static String VAL_TYPE_QUOTES = "quotes";
/** a value of the type attribute. */
public final static String VAL_TYPE_CLASSIFIER = "classifier";
/** a value of the type attribute. */
public final static String VAL_TYPE_OPTIONHANDLER = "optionhandler";
/** the root node. */
public final static String ROOT_NODE = TAG_OPTIONS;
/** the DTD for the XML file. */
public final static String DOCTYPE = "\n"
+ " \n" + " \n" + " \n" + " \n" + " \n" + "]\n" + ">";
/** the XML document. */
protected XMLDocument m_XMLDocument = null;
/**
* Creates a new instance of XMLOptions.
*
* @throws Exception if the construction of the DocumentBuilder fails
* @see #setValidating(boolean)
*/
public XMLOptions() throws Exception {
m_XMLDocument = new XMLDocument();
m_XMLDocument.setRootNode(ROOT_NODE);
m_XMLDocument.setDocType(DOCTYPE);
setValidating(true);
}
/**
* Creates a new instance of XMLOptions.
*
* @param xml the xml to parse (if "
* Note: this does clear the current DOM document!
*
* @param validating whether to use a validating parser
* @throws Exception if the instantiating of the DocumentBuilder fails
*/
public void setValidating(boolean validating) throws Exception {
m_XMLDocument.setValidating(validating);
}
/**
* returns the parsed DOM document.
*
* @return the parsed DOM document
*/
public Document getDocument() {
fixHyphens();
return m_XMLDocument.getDocument();
}
/**
* returns the handler of the XML document. the internal DOM document can be
* accessed via the getDocument()
method.
*
* @return the object handling the XML document
* @see #getDocument()
*/
public XMLDocument getXMLDocument() {
fixHyphens();
return m_XMLDocument;
}
/**
* pushes any options with type VAL_TYPE_HYPHENS to the end, i.e., the "--"
* are really added at the end.
*
* @see #VAL_TYPE_HYPHENS
*/
protected void fixHyphens() {
NodeList list;
Vector hyphens;
int i;
Node node;
Node tmpNode;
boolean isLast;
// get all option tags
list = m_XMLDocument.findNodes("//" + TAG_OPTION);
// get all hyphen tags
hyphens = new Vector();
for (i = 0; i < list.getLength(); i++) {
if (((Element) list.item(i)).getAttribute(ATT_TYPE).equals(
VAL_TYPE_HYPHENS)) {
hyphens.add((Element) list.item(i));
}
}
// check all hyphen tags whether they are at the end, if not fix it
for (i = 0; i < hyphens.size(); i++) {
node = hyphens.get(i);
// at the end?
isLast = true;
tmpNode = node;
while (tmpNode.getNextSibling() != null) {
// normal tag?
if (tmpNode.getNextSibling().getNodeType() == Node.ELEMENT_NODE) {
isLast = false;
break;
}
tmpNode = tmpNode.getNextSibling();
}
// move
if (!isLast) {
tmpNode = node.getParentNode();
tmpNode.removeChild(node);
tmpNode.appendChild(node);
}
}
}
/**
* converts the given node into a command line representation and returns it.
*
* @param parent the node to convert to command line
* @return the new command line
*/
protected String toCommandLine(Element parent) {
Vector result;
Vector list;
Vector subList;
NodeList subNodeList;
String[] params;
int i;
int n;
String tmpStr;
result = new Vector();
// "options" tag
if (parent.getNodeName().equals(TAG_OPTIONS)) {
// children
list = XMLDocument.getChildTags(parent);
if (parent.getAttribute(ATT_TYPE).equals(VAL_TYPE_CLASSIFIER)) {
System.err.println("Type '" + VAL_TYPE_CLASSIFIER + "' is deprecated, "
+ "use '" + VAL_TYPE_OPTIONHANDLER + "' instead!");
parent.setAttribute(ATT_TYPE, VAL_TYPE_OPTIONHANDLER);
}
if (parent.getAttribute(ATT_TYPE).equals(VAL_TYPE_OPTIONHANDLER)) {
result.add(parent.getAttribute(ATT_VALUE));
// hyphens?
if ((list.size() > 0)
&& (parent.getParentNode() != null)
&& (parent.getParentNode() instanceof Element)
&& (((Element) parent.getParentNode()).getNodeName()
.equals(TAG_OPTION))
&& (((Element) parent.getParentNode()).getAttribute(ATT_TYPE)
.equals(VAL_TYPE_HYPHENS))) {
result.add("--");
}
}
// process children
for (i = 0; i < list.size(); i++) {
tmpStr = toCommandLine(list.get(i));
try {
params = Utils.splitOptions(tmpStr);
for (n = 0; n < params.length; n++) {
result.add(params[n]);
}
} catch (Exception e) {
System.err.println("Error splitting: " + tmpStr);
e.printStackTrace();
}
}
}
// "option" tag
else if (parent.getNodeName().equals(TAG_OPTION)) {
subList = XMLDocument.getChildTags(parent);
subNodeList = parent.getChildNodes();
result.add("-" + parent.getAttribute(ATT_NAME));
// single argument
if (parent.getAttribute(ATT_TYPE).equals(VAL_TYPE_SINGLE)) {
if ((subNodeList.getLength() > 0)
&& (subNodeList.item(0).getNodeValue().trim().length() > 0)) {
result.add(subNodeList.item(0).getNodeValue());
}
}
// compound argument surrounded by quotes
else if (parent.getAttribute(ATT_TYPE).equals(VAL_TYPE_QUOTES)) {
result.add(toCommandLine(subList.get(0)));
}
// classname + further options after "--"
else if (parent.getAttribute(ATT_TYPE).equals(VAL_TYPE_HYPHENS)) {
tmpStr = toCommandLine(subList.get(0));
try {
params = Utils.splitOptions(tmpStr);
for (n = 0; n < params.length; n++) {
result.add(params[n]);
}
} catch (Exception e) {
System.err.println("Error splitting: " + tmpStr);
e.printStackTrace();
}
}
}
// other tag
else {
System.err.println("Unsupported tag '" + parent.getNodeName()
+ "' - skipped!");
}
return Utils.joinOptions(result.toArray(new String[result.size()]));
}
/**
* returns the given DOM document as command line.
*
* @return the document as command line
* @throws Exception if anything goes wrong initializing the parsing
*/
public String toCommandLine() throws Exception {
return toCommandLine(getDocument().getDocumentElement());
}
/**
* returns the current DOM document as string array.
*
* @return the document as string array
* @throws Exception if anything goes wrong initializing the parsing
*/
public String[] toArray() throws Exception {
return Utils.splitOptions(toCommandLine());
}
/**
* returns the object in a string representation (as indented XML output).
*
* @return the object in a string representation
*/
@Override
public String toString() {
return getXMLDocument().toString();
}
/**
* Returns the revision string.
*
* @return the revision
*/
@Override
public String getRevision() {
return RevisionUtils.extract("$Revision: 10203 $");
}
/**
* for testing only. prints the given XML file, the resulting commandline and
* the string array.
*
* @param args the commandline options.
* @throws Exception if something goes wrong
*/
public static void main(String[] args) throws Exception {
if (args.length > 0) {
System.out.println("\nXML:\n\n" + new XMLOptions(args[0]).toString());
System.out.println("\nCommandline:\n\n"
+ new XMLOptions(args[0]).toCommandLine());
System.out.println("\nString array:\n");
String[] options = new XMLOptions(args[0]).toArray();
for (String option : options) {
System.out.println(option);
}
}
}
}