+/* $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();
+}