dol: initial dol commit
[jump.git] / dol / src / dol / helper / flattener / FlattenerHelper.java
1 /* $Id: FlattenerHelper.java 1 2010-02-24 13:03:05Z haidw $ */
2 package dol.helper.flattener;
3
4 import java.util.List;
5
6 import org.jdom.Document;
7 import org.jdom.Element;
8
9 import dol.datamodel.XmlTag;
10
11 /**
12  * Helper class to generate the source code of a class for writing
13  * an XML file based on an XML file with iterators. For details, refer
14  * to removeIterators().
15  *
16  * @see #removeIterators(org.jdom.Document doc)
17  */
18 public class FlattenerHelper {
19
20     protected String _preamble = "public class Generator {\n\n  public "
21         + "Generator() {\n    //nothing to be done here\n  }\n"
22         + "\n  public static void main(String[] args) {\n";
23
24
25     //true, when an element is generated. places a restriction on the append
26     //element, namely that it must be a single variable, no function of a
27     //variable
28     protected boolean _generateElement = false;
29
30     protected String _indent = ""; //indentation of lines in Generator class
31
32     //code for obtaining range of iterator variables. is updated in each
33     //call of generateAppend
34     protected String _iteratorRangeCode = "";
35
36     //indentation of XML elements (use increaseXmlIndent() and
37     //decreaseXmlIndent() to change the indentation)
38     protected String _xmlIndent = "";
39
40     /**
41      * Default constructor. The generated class will have the name
42      * "Generator".
43      */
44     public FlattenerHelper() {
45     }
46
47     /**
48      * Constructor.
49      *
50      * @param classname class name of the generated class
51      */
52     public FlattenerHelper(String classname) {
53         _preamble = _preamble.replace("Generator", classname);
54     }
55
56     public String processElement(Element element) {
57         return "";
58     }
59
60     /**
61      * Generate source code for println statement that prints out an XML
62      * element.
63      * @param element    the XML element itself
64      * @param attributes attributes to include in the XML element
65      * @param standalone true, when element shall be closed. false, otherwise
66      * @return println statement which prints out the XML element
67      */
68     protected String generateElement(Element element,
69                                      String[] attributes, boolean standalone)
70     {
71         String sourceCode = _indent + "System.out.println(\"";
72         sourceCode += _xmlIndent + "<" + element.getName();
73         for (int i = 0; i < attributes.length; i++) {
74
75             if (attributes[i].equals("basename")) {
76                 sourceCode += " " + attributes[i] + "=\\\"";
77                 sourceCode += element.getAttributeValue("name");
78                 
79                 if (!generateAppend(element).equals("")) {
80                     sourceCode += "\\\"";
81                     sourceCode += " range=\\\"" + _iteratorRangeCode;
82                 }
83                 sourceCode += "\\\"";
84             } else if (attributes[i].equals("name")) {
85                 sourceCode += " " + attributes[i] + "=\\\"";
86                 sourceCode += element.getAttributeValue("name");
87                 sourceCode += generateAppend(element);
88                 sourceCode += "\\\"";
89             } else if (attributes[i].equals("size")
90                        && element.getName().equals(_xt.getSWChannelTag())) {
91                 sourceCode += " " + attributes[i] + "=\\\"";
92                 sourceCode += "\" + ";
93                 sourceCode += element.getAttributeValue("size");
94                 sourceCode += "+ \"";
95                 sourceCode += "\\\"";
96             } else if (attributes[i].equals("tokensize")
97                        && element.getName().equals(_xt.getSWChannelTag())) {
98                 if (element.getAttributeValue("tokensize") != null) {
99                     sourceCode += " " + attributes[i] + "=\\\"";
100                     sourceCode += "\"";
101                     sourceCode += " + ";
102                     sourceCode += element.getAttributeValue("tokensize");
103                     sourceCode += "+ \"";
104                     sourceCode += "\\\"";
105                 }
106             } else {
107                 sourceCode += " " + attributes[i] + "=\\\"";
108                 sourceCode += element.getAttributeValue(attributes[i]);
109                 sourceCode += "\\\"";
110             }
111
112         }
113
114         if (standalone)
115             sourceCode += "/";
116         sourceCode +=">\");\n";
117
118         return sourceCode;
119     }
120
121     /**
122      * 
123      */
124     @SuppressWarnings("unchecked")
125     public String removeIterators(Document doc)
126         throws RuntimeException {
127         String sourceCode = _preamble;
128         String functionString = "";
129         String rootName = "";
130         _indent = "    ";
131
132         Element root = doc.getRootElement();
133         String xmlns = root.getNamespaceURI();
134         String xsiLocation = "";
135         for (org.jdom.Attribute attr :
136                  (List<org.jdom.Attribute>)root.getAttributes()) { 
137             //System.out.println(attr.getName() + ": ");
138             //System.out.println(attr.getValue());
139             if (attr.getName().equals("schemaLocation"))
140                 xsiLocation = attr.getValue();
141         }
142
143         if (!root.getChildren().isEmpty()) {
144             //if there are any elements in the document, create a new header
145             //for the xml document
146             rootName = root.getName();
147
148             sourceCode += _indent
149                 + "java.util.Hashtable<String, Integer> table = "
150                 + "new java.util.Hashtable<String, Integer>();\n";
151
152             sourceCode += _indent + "System.out.println(\""
153                 + "<?xml version=\\\"1.0\\\" "
154                 + "encoding=\\\"UTF-8\\\"?>\");\n";
155             sourceCode += _indent + "System.out.println(\"<"
156                 + rootName + " xmlns=\\\"" + xmlns
157                 + "\\\" xmlns:xsi=\\\"http://www.w3.org/2001/"
158                 + "XMLSchema-instance\\\" \\n  xsi:schemaLocation=\\\""
159                 + xsiLocation + "\\\" name=\\\""
160                 + root.getAttributeValue("name") + "_flattened"
161                 + "\\\">\\n \");\n";
162         }
163
164
165         for (Element elmt : (List<Element>)root.getChildren()) {
166             try {
167                 if (elmt.getName().equalsIgnoreCase(_xt.getIteratorTag())) {
168                     sourceCode += generateIterator(elmt);
169                 }
170                 else if (elmt.getName().equalsIgnoreCase(_xt.getVariableTag())) {
171                     sourceCode += generateVariable(elmt);
172                 }
173                 else if (elmt.getName().equalsIgnoreCase(_xt.getFunctionTag())) {
174                     functionString += generateFunction(elmt);
175                 }
176                 else {
177                     sourceCode += processElement(elmt);
178                 }
179             }
180             catch (RuntimeException e) {
181                 String elementName = "";
182                 System.out.println(e.getMessage());
183                 if (!elmt.getName().equalsIgnoreCase(_xt.getIteratorTag()) &&
184                     !elmt.getName().equalsIgnoreCase(_xt.getVariableTag())) {
185                     elementName = elmt.getAttributeValue("name");
186                 }
187                 throw new RuntimeException(
188                     "Error: An error occurred while parsing the <"
189                     + elmt.getName() + "> element \""
190                     + elementName + "\".");
191             }
192         }
193
194         sourceCode += _indent + "System.out.println(\"</"
195             + rootName +">\");\n  }\n";
196         _indent = "  ";
197         sourceCode += functionString;
198         sourceCode += "\n}";
199
200         return sourceCode;
201     }
202
203
204     /**
205      * 
206      */
207     @SuppressWarnings("unchecked")
208     protected String generateIterator(Element element) {
209         String variableName = element.getAttributeValue("variable");
210         /*
211         //extract the upper iteration boundary and construct the for loop
212         String forLoop = element.getAttributeValue("range");
213         String boundary = forLoop.replaceAll(
214         "for.*;[ ]*\\w*[ ]*[<>=]* *(.*);.*", "$1");
215         */
216         String forLoop = "for (int " + variableName + " = 0; " + variableName
217             + " < " + element.getAttributeValue("range") + "; "
218             + variableName + "++)";
219
220         String sourceCode = _indent + "table.put(\"" + variableName
221             + "\", " + element.getAttributeValue("range") + ");\n";
222
223         sourceCode += _indent + forLoop + " {\n";
224         _indent += "  ";
225
226         for (Element el : (List<Element>)element.getChildren()) {
227             try {
228                 if (el.getName().equalsIgnoreCase(_xt.getIteratorTag())) {
229                     sourceCode += generateIterator(el);
230                 }
231                 else {
232                     sourceCode += processElement(el);
233                 }
234             }
235             catch (RuntimeException e) {
236                 System.out.println(e.getMessage());
237                 throw new RuntimeException(
238                     "Error: An error occurred while parsing the <"
239                     + el.getName() + "> element \""
240                     + el.getAttributeValue("name") + "\".");
241             }
242         }
243         _indent = _indent.substring(0, _indent.length() - 2);
244         sourceCode += _indent + "}\n";
245         sourceCode += _indent + "table.remove(\"" + variableName + "\");\n";
246
247         return sourceCode;
248     }
249
250     /**
251      * 
252      */
253     @SuppressWarnings("unchecked")
254     protected String generateAppend(Element element)
255         throws RuntimeException {
256         String sourceCode = "";
257         
258         _iteratorRangeCode = "";
259         for (Element childElement : (List<Element>)element.getChildren()) {
260             if (childElement.getName().equalsIgnoreCase("append")) {
261                 if (_generateElement &&
262                     !childElement.getAttributeValue(_xt.getFunctionTag()).replaceAll(
263                         "\\w", "").equals("")) {
264                     throw new RuntimeException("Error: Found \""
265                                                + childElement.getAttributeValue("function")
266                                                + "\" in <append>. When constructing elements with an "
267                                                + "iterator using <append function=\"xxx\">, xxx must "
268                                                + "be a single variable. No mathematical operations "
269                                                + "are permitted.");
270                 }
271                 sourceCode += "\" + \"_\" + ("
272                     + childElement.getAttributeValue(_xt.getFunctionTag())
273                     + ") + \"";
274
275                 if (!_iteratorRangeCode.equals(""))
276                     _iteratorRangeCode += ";";
277
278                 _iteratorRangeCode += "\" + table.get(\""
279                     + childElement.getAttributeValue(_xt.getFunctionTag())
280                     + "\") + \"";
281             }
282         }
283         return sourceCode;
284     }
285
286     protected String generateVariable(Element element) {
287         String sourceCode = _indent + "int ";
288         sourceCode += element.getAttributeValue("name");
289         sourceCode += " = ";
290         sourceCode += element.getAttributeValue("value");
291         sourceCode += ";\n";
292         return sourceCode;
293     }
294
295     protected String generateFunction(Element element) {
296         return element.getText();
297     }
298
299     /**
300      * Increase the XML indentation.
301      **/
302     protected void increaseXmlIndent() {
303         _xmlIndent += "  ";
304     }
305
306     /**
307      * Decrease the XML indentation.
308      */
309     protected void decreaseXmlIndent() {
310         _xmlIndent = _xmlIndent.substring(0, _xmlIndent.length() - 2);
311     }
312
313     protected XmlTag _xt = XmlTag.getInstance();
314 }