]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.data/src/org/simantics/scl/data/xml/JDomHelper.java
78a54410c65a0c5aec6d289912f99bc2c5b8a9b9
[simantics/platform.git] / bundles / org.simantics.scl.data / src / org / simantics / scl / data / xml / JDomHelper.java
1 package org.simantics.scl.data.xml;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.io.StringReader;
6 import java.io.StringWriter;
7 import java.net.URL;
8 import java.util.ArrayList;
9 import java.util.Collections;
10 import java.util.Comparator;
11 import java.util.LinkedHashMap;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.concurrent.ArrayBlockingQueue;
15
16 import org.jdom2.CDATA;
17 import org.jdom2.Content;
18 import org.jdom2.Content.CType;
19 import org.jdom2.Document;
20 import org.jdom2.Element;
21 import org.jdom2.IllegalAddException;
22 import org.jdom2.JDOMException;
23 import org.jdom2.Namespace;
24 import org.jdom2.filter.Filters;
25 import org.jdom2.input.SAXBuilder;
26 import org.jdom2.input.sax.XMLReaderJDOMFactory;
27 import org.jdom2.input.sax.XMLReaderXSDFactory;
28 import org.jdom2.output.Format;
29 import org.jdom2.output.XMLOutputter;
30 import org.jdom2.xpath.XPathExpression;
31 import org.jdom2.xpath.XPathFactory;
32 import org.simantics.scl.runtime.function.Function;
33 import org.simantics.scl.runtime.function.FunctionImpl1;
34 import org.simantics.scl.runtime.reporting.SCLReporting;
35
36 public class JDomHelper {
37     private static final SAXBuilder BUILDER = new SAXBuilder();
38     private static final XMLOutputter OUTPUTTER = new XMLOutputter(Format.getPrettyFormat());
39     private static final XPathFactory XPATH_FACTORY = XPathFactory.instance(); 
40     
41     private static final int XPATH_CACHE_MAX = 50;
42     
43     private static final Map<String,XPathExpression<Element>> XPATH_CACHE = Collections.synchronizedMap(
44             new LinkedHashMap<String,XPathExpression<Element>>(XPATH_CACHE_MAX) {
45                 private static final long serialVersionUID = 2546245625L;
46      
47                 @Override
48                 protected boolean removeEldestEntry(Map.Entry<String,XPathExpression<Element>> eldest) {
49                     return size() > XPATH_CACHE_MAX;
50                 }
51             });
52
53     public static Document parseString(String xmlDocument) throws JDOMException, IOException {
54         return BUILDER.build(new StringReader(xmlDocument));
55     }
56     
57     public static Document parseFile(String xmlFileName) throws JDOMException, IOException {
58         return BUILDER.build(new File(xmlFileName));
59     }
60     
61     public static String outputString(Document document) throws IOException {
62         StringWriter writer = new StringWriter();
63         OUTPUTTER.output(document, writer);
64         return writer.toString();
65     }
66     
67     private static XPathExpression<Element> getXPathExpression(String xPathText) {
68         XPathExpression<Element> expression = XPATH_CACHE.get(xPathText);
69         if(expression == null) {
70             expression = XPATH_FACTORY.compile(xPathText, Filters.element());
71             XPATH_CACHE.put(xPathText, expression);
72         }
73         return expression;
74     }
75     
76     public static List<Element> elementsByXPath(Element element, String xPathText) {
77         XPathExpression<Element> expr = getXPathExpression(xPathText);
78         return expr.evaluate(element);
79     }
80     
81     public static void addNamedChild(Element parent, String name, Element child) {
82         child.setName(name);
83         try {
84             parent.addContent(child);
85         } catch(IllegalAddException e) {
86             SCLReporting.printError("Failed to set the parent of an element " + name + ":");
87             SCLReporting.printError("    " + e.getMessage());
88         }
89     }
90     
91     public static void setNamespace(Document document, String namespace) {
92         setElementNamespace(document.getRootElement(), namespace);
93     }
94     
95     public static void setElementNamespace(Element element, String namespace) {
96         Namespace ns = Namespace.getNamespace(namespace);
97         setNamespaceRecursively(element, ns);
98     }   
99
100         private static void setNamespaceRecursively(Element element, Namespace ns) {
101                 element.setNamespace(ns);
102                 for(Element child : element.getChildren())
103                         if(child.getNamespace() == Namespace.NO_NAMESPACE)
104                                 setNamespaceRecursively(child, ns);
105         }
106         
107         public static void clearNamespace(Document document) {
108                 clearElementNamespace(document.getRootElement());
109         }
110         
111         public static void clearElementNamespace(Element element) {
112                 element.setNamespace(null);
113                 for (Element child : element.getChildren())
114                         clearElementNamespace(child);
115         }
116         
117         public static Function parseStringWithSchemaFile(String xsdFile) throws JDOMException {
118                 XMLReaderJDOMFactory factory = new XMLReaderXSDFactory(new File(xsdFile));
119                 SAXBuilder builder = new SAXBuilder(factory);
120                 return parseStringWithBuilder(builder);
121         }
122         
123         public static Function parseStringWithSchemaURL(URL xsd) throws JDOMException {
124                 XMLReaderJDOMFactory factory = new XMLReaderXSDFactory(xsd);
125                 SAXBuilder builder = new SAXBuilder(factory);
126                 return parseStringWithBuilder(builder);
127         }
128         
129         public static Function parseFileWithSchemaFile(String xsdFile) throws JDOMException {
130                 XMLReaderJDOMFactory factory = new XMLReaderXSDFactory(new File(xsdFile));
131                 SAXBuilder builder = new SAXBuilder(factory);
132                 return parseFileWithBuilder(builder);
133         }
134         
135         public static Function parseFileWithSchemaURL(URL xsd) throws JDOMException {
136                 XMLReaderJDOMFactory factory = new XMLReaderXSDFactory(xsd);
137                 SAXBuilder builder = new SAXBuilder(factory);
138                 return parseFileWithBuilder(builder);
139         }
140         
141         private static Function parseStringWithBuilder(final SAXBuilder builder) {
142                 return new FunctionImpl1<String, Document>() {
143                         @Override
144                         public Document apply(String xml) {
145                                 try {
146                                         return builder.build(new StringReader(xml));
147                                 }
148                                 catch (JDOMException | IOException e) {
149                                         throw new RuntimeException(e);
150                                 }
151                         };
152                 };
153         }
154         
155         private static Function parseFileWithBuilder(final SAXBuilder builder) {
156                 return new FunctionImpl1<String, Document>() {
157                         @Override
158                         public Document apply(String xml) {
159                                 try {
160                                         return builder.build(new File(xml));
161                                 }
162                                 catch (JDOMException | IOException e) {
163                                         throw new RuntimeException(e);
164                                 }
165                         };
166                 };
167         }
168         
169         public static void sortChildrenWith(final Function comparator, Element element) {
170             element.sortChildren(new Comparator() {
171             @Override
172             public int compare(Object o1, Object o2) {
173                 return (Integer)comparator.apply(o1, o2);
174             }
175             });
176         }
177         
178         public static void addCDATA(Element element, String cdata) {
179                 element.addContent(new CDATA(cdata));
180         }
181         
182         public static List<String> getCDATAs(Element element) {
183                 ArrayList<String> result = new ArrayList<>();
184                 for(Content c : element.getContent()) {
185                         if(CType.CDATA.equals(c.getCType())) result.add(c.getValue());
186                 }
187                 return result;
188         }
189         
190 }