
redora.generator.XMLUtil Maven / Gradle / Ivy
/*
* Copyright 2009-2010 Nanjing RedOrange ltd (http://www.red-orange.cn)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package redora.generator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Writer;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import static javax.xml.xpath.XPathConstants.NODESET;
/**
* XML utilities in specific use for handling the model files.
*
* @author Nanjing RedOrange (http://www.red-orange.cn)
*/
public class XMLUtil {
/**
* Transform xml Node with xslt template file to stream
*/
public static void xsltTransform(@NotNull Node xml, @NotNull InputStream xslt, @NotNull Writer out
, @NotNull Map param) throws TransformerException {
Source xmlSource = new DOMSource(xml);
Source xsltSource = new StreamSource(xslt);
Transformer transformer = TransformerFactory.newInstance().newTransformer(xsltSource);
for (String key : param.keySet()) {
transformer.setParameter(key, param.get(key));
}
transformer.transform(xmlSource, new StreamResult(out));
}
/**
* Retrieves the distinct values of all 'language' attributes in given
* document.
*
* @param doc (Mandatory) The AllModels document
* @return Empty or filled set.
* @throws ModelGenerationException Wrapper on XPath exceptions
*/
@NotNull
public static Set definedLanguages(@NotNull Document doc) throws ModelGenerationException {
Set retVal = new HashSet();
XPath xpath = XPathFactory.newInstance().newXPath();
NodeList langNodes;
try {
langNodes = (NodeList) xpath.evaluate("//@language", doc, NODESET);
} catch (XPathExpressionException e) {
throw new ModelGenerationException("Filter on language failed", e);
}
if (langNodes != null) {
for (int i = 0; i < langNodes.getLength(); i++) {
retVal.add(langNodes.item(i).getNodeValue());
}
System.out.println("Found " + retVal.size()
+ " different languages.");
} else {
System.out.println("No captions found, the client will be using the model attribute names for caption.");
}
return retVal;
}
/**
* Looks if this model document has the sorted = true tag.
* @param doc (Mandatory) A model document
* @return True if yes
* @throws XPathExpressionException Just passing on
*/
public static boolean isSortable(@NotNull Document doc) throws XPathExpressionException {
XPath xpath = XPathFactory.newInstance().newXPath();
NodeList sorted = (NodeList)xpath.evaluate("/object/sorted", doc, NODESET);
return (sorted.getLength() == 1 && sorted.item(0).getFirstChild().getNodeValue().equals("true"));
}
/**
* Return a nodelist with all the /object/attributes, or filtered as you xpath wished.
*
* @param doc (Mandatory) A model document
* @param filter (Optional) XPathish filter. Default it is '*' (all).
* @return A list of attributes
* @throws XPathExpressionException Just passing on
*/
@NotNull
public static NodeList attributes(@NotNull Document doc, @Nullable String filter) throws XPathExpressionException {
XPath xpath = XPathFactory.newInstance().newXPath();
if (filter == null) {
filter = "*";
}
return (NodeList)xpath.evaluate("/object/attributes/" + filter, doc, NODESET);
}
public static NodeList queries(@NotNull Document doc) throws XPathExpressionException {
XPath xpath = XPathFactory.newInstance().newXPath();
return (NodeList)xpath.evaluate("/object/queries/query", doc, NODESET);
}
/**
* Insert attribute in given node. If this attribute already exists, the new attribute will not be inserted
*
* @param node (Mandatory) Node in need of attribute
* @param name (Mandatory) Attribute name
* @param value (Mandatory) It's value
*/
public static void attribute(@NotNull Node node, @NotNull String name, @NotNull String value) {
if (node.getAttributes().getNamedItem(name) == null) {
Attr att = node.getOwnerDocument().createAttribute(name);
att.setNodeValue(value);
node.getAttributes().setNamedItem(att);
}
}
@Nullable
public static Node finder(@NotNull Node parent, @Nullable String name) {
NodeList finders = parent.getChildNodes();
for (int f = 0; f < finders.getLength(); f++)
if ("finder".equals(finders.item(f).getNodeName()) &&
(name == null || name.equals(finders.item(f).getAttributes().getNamedItem("name").getNodeValue())))
return finders.item(f);
return null;
}
@NotNull
public static Node addFinder(@NotNull Document doc, @NotNull Node parent, String jsonValue, boolean forceCreate) {
Node retVal = finder(parent, null);
if (forceCreate || retVal == null) {
retVal = doc.createElement("finder");
parent.appendChild(retVal);
}
attribute(retVal, "json", jsonValue);
return retVal;
}
@NotNull
public static Node addFinder(@NotNull Document doc, @NotNull Node parent, String name, String jsonValue) {
Node retVal = finder(parent, name);
if (retVal == null) {
retVal = doc.createElement("finder");
parent.appendChild(retVal);
}
attribute(retVal, "json", jsonValue);
attribute(retVal, "name", name);
return retVal;
}
/**
* Adds an child element to the document's root element. Only adds the tag
* if it not yet already exists.
*
* @param doc (Mandatory) The XML document
* @param tag (Mandatory) The element's name
* @param value (Optional) It's value, when null, the tag will be empty
*/
public static void addChildElement(@NotNull Document doc, @NotNull String tag, @Nullable String value) {
if (doc.getElementsByTagName(tag).getLength() == 0) {
Node tagNode = doc.createElement(tag);
if (value != null) {
tagNode.setTextContent(value);
}
doc.getFirstChild().appendChild(tagNode);
}
}
/**
* Retrieves all enum from model doc.
*
* @param allModels (Mandatory) The allModels document
* @param basePackage (Mandatory)
* @return Empty or filled set.
* @throws ModelGenerationException Wrapper on XPath exceptions
*/
@NotNull
public static Map enumerations(@NotNull Document allModels, @NotNull String basePackage)
throws ModelGenerationException {
Map retVal = new HashMap();
NodeList enumNodes;
try {
enumNodes = (NodeList) XPathFactory.newInstance().newXPath().evaluate("//enum[@scope='global']"
, allModels, NODESET);
} catch (XPathExpressionException e) {
throw new ModelGenerationException("The search on global scoped enums failed", e);
}
if (enumNodes != null) {
for (int i = 0; i < enumNodes.getLength(); i++) {
String name = enumNodes.item(i).getAttributes().getNamedItem("class").getNodeValue();
Document enumDoc = newDocument(basePackage, "enums");
addChildElement(enumDoc, "name", name);
addChildElement(enumDoc, "fieldName", enumNodes.item(i).getAttributes().getNamedItem("fieldName").getNodeValue());
enumDoc.getFirstChild().appendChild(enumDoc.importNode(enumNodes.item(i), true));
retVal.put(name, enumDoc);
}
} else {
System.out.println("No captions found, the client will be using the model attribute names for caption.");
}
return retVal;
}
/**
* Create the model XML document and adds the root element and optional a
* package element. This method is simple and created for your convenience.
*
* @param basePackage (Optional) Adds a 'package' element, it will the the root's
* first child
* @param root (Mandatory) root element name
* @return Document The Model document
* @throws ModelGenerationException Wrapper on ParserConfigurationException: should not happen
*/
@NotNull
public static Document newDocument(@Nullable String basePackage, @NotNull String root)
throws ModelGenerationException {
Document doc;
try {
doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
} catch (ParserConfigurationException e) {
throw new ModelGenerationException(
"Strange, the DOM is not configured right, it worked before! Maybe you have some system properties set that interfere with me",
e);
}
Node insertNode = doc.createElement(root);
doc.appendChild(doc.importNode(insertNode, true));
if (basePackage != null) {
addChildElement(doc, "package", basePackage);
}
return doc;
}
/**
* Dumps Document to String. Any exceptions are ignored
*
* @param doc (Mandatory)
* @return String of given doc.
*/
@NotNull
public static String asString(@NotNull Document doc) {
Source source = new DOMSource(doc);
OutputStream out = new ByteArrayOutputStream();
Result result = new StreamResult(out);
try {
TransformerFactory.newInstance().newTransformer().transform(source, result);
} catch (TransformerException e) {
//Ignoring error, this is in error handling already
e.printStackTrace();
}
return out.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy