dol: initial dol commit
[jump.git] / dol / src / dol / helper / flattener / FlattenerHelper.java
diff --git a/dol/src/dol/helper/flattener/FlattenerHelper.java b/dol/src/dol/helper/flattener/FlattenerHelper.java
new file mode 100644 (file)
index 0000000..b11d977
--- /dev/null
@@ -0,0 +1,314 @@
+/* $Id: FlattenerHelper.java 1 2010-02-24 13:03:05Z haidw $ */
+package dol.helper.flattener;
+
+import java.util.List;
+
+import org.jdom.Document;
+import org.jdom.Element;
+
+import dol.datamodel.XmlTag;
+
+/**
+ * Helper class to generate the source code of a class for writing
+ * an XML file based on an XML file with iterators. For details, refer
+ * to removeIterators().
+ *
+ * @see #removeIterators(org.jdom.Document doc)
+ */
+public class FlattenerHelper {
+
+    protected String _preamble = "public class Generator {\n\n  public "
+        + "Generator() {\n    //nothing to be done here\n  }\n"
+        + "\n  public static void main(String[] args) {\n";
+
+
+    //true, when an element is generated. places a restriction on the append
+    //element, namely that it must be a single variable, no function of a
+    //variable
+    protected boolean _generateElement = false;
+
+    protected String _indent = ""; //indentation of lines in Generator class
+
+    //code for obtaining range of iterator variables. is updated in each
+    //call of generateAppend
+    protected String _iteratorRangeCode = "";
+
+    //indentation of XML elements (use increaseXmlIndent() and
+    //decreaseXmlIndent() to change the indentation)
+    protected String _xmlIndent = "";
+
+    /**
+     * Default constructor. The generated class will have the name
+     * "Generator".
+     */
+    public FlattenerHelper() {
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param classname class name of the generated class
+     */
+    public FlattenerHelper(String classname) {
+        _preamble = _preamble.replace("Generator", classname);
+    }
+
+    public String processElement(Element element) {
+        return "";
+    }
+
+    /**
+     * Generate source code for println statement that prints out an XML
+     * element.
+     * @param element    the XML element itself
+     * @param attributes attributes to include in the XML element
+     * @param standalone true, when element shall be closed. false, otherwise
+     * @return println statement which prints out the XML element
+     */
+    protected String generateElement(Element element,
+                                     String[] attributes, boolean standalone)
+    {
+        String sourceCode = _indent + "System.out.println(\"";
+        sourceCode += _xmlIndent + "<" + element.getName();
+        for (int i = 0; i < attributes.length; i++) {
+
+            if (attributes[i].equals("basename")) {
+                sourceCode += " " + attributes[i] + "=\\\"";
+                sourceCode += element.getAttributeValue("name");
+                
+                if (!generateAppend(element).equals("")) {
+                    sourceCode += "\\\"";
+                    sourceCode += " range=\\\"" + _iteratorRangeCode;
+                }
+                sourceCode += "\\\"";
+            } else if (attributes[i].equals("name")) {
+                sourceCode += " " + attributes[i] + "=\\\"";
+                sourceCode += element.getAttributeValue("name");
+                sourceCode += generateAppend(element);
+                sourceCode += "\\\"";
+            } else if (attributes[i].equals("size")
+                       && element.getName().equals(_xt.getSWChannelTag())) {
+                sourceCode += " " + attributes[i] + "=\\\"";
+                sourceCode += "\" + ";
+                sourceCode += element.getAttributeValue("size");
+                sourceCode += "+ \"";
+                sourceCode += "\\\"";
+            } else if (attributes[i].equals("tokensize")
+                       && element.getName().equals(_xt.getSWChannelTag())) {
+                if (element.getAttributeValue("tokensize") != null) {
+                    sourceCode += " " + attributes[i] + "=\\\"";
+                    sourceCode += "\"";
+                    sourceCode += " + ";
+                    sourceCode += element.getAttributeValue("tokensize");
+                    sourceCode += "+ \"";
+                    sourceCode += "\\\"";
+                }
+            } else {
+                sourceCode += " " + attributes[i] + "=\\\"";
+                sourceCode += element.getAttributeValue(attributes[i]);
+                sourceCode += "\\\"";
+            }
+
+        }
+
+        if (standalone)
+            sourceCode += "/";
+        sourceCode +=">\");\n";
+
+        return sourceCode;
+    }
+
+    /**
+     * 
+     */
+    @SuppressWarnings("unchecked")
+    public String removeIterators(Document doc)
+        throws RuntimeException {
+        String sourceCode = _preamble;
+        String functionString = "";
+        String rootName = "";
+        _indent = "    ";
+
+        Element root = doc.getRootElement();
+        String xmlns = root.getNamespaceURI();
+        String xsiLocation = "";
+        for (org.jdom.Attribute attr :
+                 (List<org.jdom.Attribute>)root.getAttributes()) { 
+            //System.out.println(attr.getName() + ": ");
+            //System.out.println(attr.getValue());
+            if (attr.getName().equals("schemaLocation"))
+                xsiLocation = attr.getValue();
+        }
+
+        if (!root.getChildren().isEmpty()) {
+            //if there are any elements in the document, create a new header
+            //for the xml document
+            rootName = root.getName();
+
+            sourceCode += _indent
+                + "java.util.Hashtable<String, Integer> table = "
+                + "new java.util.Hashtable<String, Integer>();\n";
+
+            sourceCode += _indent + "System.out.println(\""
+                + "<?xml version=\\\"1.0\\\" "
+                + "encoding=\\\"UTF-8\\\"?>\");\n";
+            sourceCode += _indent + "System.out.println(\"<"
+                + rootName + " xmlns=\\\"" + xmlns
+                + "\\\" xmlns:xsi=\\\"http://www.w3.org/2001/"
+                + "XMLSchema-instance\\\" \\n  xsi:schemaLocation=\\\""
+                + xsiLocation + "\\\" name=\\\""
+                + root.getAttributeValue("name") + "_flattened"
+                + "\\\">\\n \");\n";
+        }
+
+
+        for (Element elmt : (List<Element>)root.getChildren()) {
+            try {
+                if (elmt.getName().equalsIgnoreCase(_xt.getIteratorTag())) {
+                    sourceCode += generateIterator(elmt);
+                }
+                else if (elmt.getName().equalsIgnoreCase(_xt.getVariableTag())) {
+                    sourceCode += generateVariable(elmt);
+                }
+                else if (elmt.getName().equalsIgnoreCase(_xt.getFunctionTag())) {
+                    functionString += generateFunction(elmt);
+                }
+                else {
+                    sourceCode += processElement(elmt);
+                }
+            }
+            catch (RuntimeException e) {
+                String elementName = "";
+                System.out.println(e.getMessage());
+                if (!elmt.getName().equalsIgnoreCase(_xt.getIteratorTag()) &&
+                    !elmt.getName().equalsIgnoreCase(_xt.getVariableTag())) {
+                    elementName = elmt.getAttributeValue("name");
+                }
+                throw new RuntimeException(
+                    "Error: An error occurred while parsing the <"
+                    + elmt.getName() + "> element \""
+                    + elementName + "\".");
+            }
+        }
+
+        sourceCode += _indent + "System.out.println(\"</"
+            + rootName +">\");\n  }\n";
+        _indent = "  ";
+        sourceCode += functionString;
+        sourceCode += "\n}";
+
+        return sourceCode;
+    }
+
+
+    /**
+     * 
+     */
+    @SuppressWarnings("unchecked")
+    protected String generateIterator(Element element) {
+        String variableName = element.getAttributeValue("variable");
+        /*
+        //extract the upper iteration boundary and construct the for loop
+        String forLoop = element.getAttributeValue("range");
+        String boundary = forLoop.replaceAll(
+        "for.*;[ ]*\\w*[ ]*[<>=]* *(.*);.*", "$1");
+        */
+        String forLoop = "for (int " + variableName + " = 0; " + variableName
+            + " < " + element.getAttributeValue("range") + "; "
+            + variableName + "++)";
+
+        String sourceCode = _indent + "table.put(\"" + variableName
+            + "\", " + element.getAttributeValue("range") + ");\n";
+
+        sourceCode += _indent + forLoop + " {\n";
+        _indent += "  ";
+
+        for (Element el : (List<Element>)element.getChildren()) {
+            try {
+                if (el.getName().equalsIgnoreCase(_xt.getIteratorTag())) {
+                    sourceCode += generateIterator(el);
+                }
+                else {
+                    sourceCode += processElement(el);
+                }
+            }
+            catch (RuntimeException e) {
+                System.out.println(e.getMessage());
+                throw new RuntimeException(
+                    "Error: An error occurred while parsing the <"
+                    + el.getName() + "> element \""
+                    + el.getAttributeValue("name") + "\".");
+            }
+        }
+        _indent = _indent.substring(0, _indent.length() - 2);
+        sourceCode += _indent + "}\n";
+        sourceCode += _indent + "table.remove(\"" + variableName + "\");\n";
+
+        return sourceCode;
+    }
+
+    /**
+     * 
+     */
+    @SuppressWarnings("unchecked")
+    protected String generateAppend(Element element)
+        throws RuntimeException {
+        String sourceCode = "";
+        
+        _iteratorRangeCode = "";
+        for (Element childElement : (List<Element>)element.getChildren()) {
+            if (childElement.getName().equalsIgnoreCase("append")) {
+                if (_generateElement &&
+                    !childElement.getAttributeValue(_xt.getFunctionTag()).replaceAll(
+                        "\\w", "").equals("")) {
+                    throw new RuntimeException("Error: Found \""
+                                               + childElement.getAttributeValue("function")
+                                               + "\" in <append>. When constructing elements with an "
+                                               + "iterator using <append function=\"xxx\">, xxx must "
+                                               + "be a single variable. No mathematical operations "
+                                               + "are permitted.");
+                }
+                sourceCode += "\" + \"_\" + ("
+                    + childElement.getAttributeValue(_xt.getFunctionTag())
+                    + ") + \"";
+
+                if (!_iteratorRangeCode.equals(""))
+                    _iteratorRangeCode += ";";
+
+                _iteratorRangeCode += "\" + table.get(\""
+                    + childElement.getAttributeValue(_xt.getFunctionTag())
+                    + "\") + \"";
+            }
+        }
+        return sourceCode;
+    }
+
+    protected String generateVariable(Element element) {
+        String sourceCode = _indent + "int ";
+        sourceCode += element.getAttributeValue("name");
+        sourceCode += " = ";
+        sourceCode += element.getAttributeValue("value");
+        sourceCode += ";\n";
+        return sourceCode;
+    }
+
+    protected String generateFunction(Element element) {
+        return element.getText();
+    }
+
+    /**
+     * Increase the XML indentation.
+     **/
+    protected void increaseXmlIndent() {
+        _xmlIndent += "  ";
+    }
+
+    /**
+     * Decrease the XML indentation.
+     */
+    protected void decreaseXmlIndent() {
+        _xmlIndent = _xmlIndent.substring(0, _xmlIndent.length() - 2);
+    }
+
+    protected XmlTag _xt = XmlTag.getInstance();
+}