Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.openxma.hbmfilemerge.HbmFileMerge Maven / Gradle / Ivy
package org.openxma.hbmfilemerge;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
public class HbmFileMerge {
private static final String HIBERNATE_DOCTYPE_SYSTEM = "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd";
private static final String HIBERNATE_DOCTYPE_PUBLIC = "-//Hibernate/Hibernate Mapping DTD//EN";
private static final DocumentBuilderFactory DOC_BUILDER_FACTORY = DocumentBuilderFactory.newInstance();
private DocumentBuilder _builder;
private HbmFileMergeInput _input;
private HbmFileMerge(HbmFileMergeInput input) {
if (null == input)
throw new IllegalArgumentException("missing input");
_input = input;
initDocumentBuilder();
}
public static HbmFileMerge getInstance(File resourcesFolder, File resourcesGenFolder) {
return new HbmFileMerge(HbmFileMergeInput.getInstance(resourcesFolder, resourcesGenFolder));
}
/**
* @param fragmentHbm
* the custom hbm.xml to be merged with the generated hbm.xml
* @throws SAXException
* @throws IOException
* @throws XPathExpressionException
* @throws TransformerException
*/
public String mergeGenHbmWith(File fragmentHbm) throws SAXException, IOException, XPathExpressionException,
TransformerException {
return merge(_input.getMergeInputByFragmentHbm(fragmentHbm));
}
/**
* @param genHbm
* the generated hbm.xml to be merged with the fragment hbm xml
* @throws SAXException
* @throws IOException
* @throws XPathExpressionException
* @throws TransformerException
*/
public String mergeFragmentHbmWith(File genHbm) throws SAXException, IOException, XPathExpressionException,
TransformerException {
return merge(_input.getMergeInputByGenHbm(genHbm));
}
private void initDocumentBuilder() {
try {
_builder = DOC_BUILDER_FACTORY.newDocumentBuilder();
// skip resolving (external) DTDs
_builder.setEntityResolver(new EntityResolver() {
public InputSource resolveEntity(java.lang.String publicId, java.lang.String systemId)
throws SAXException, java.io.IOException {
if (systemId.endsWith(".dtd"))
// this deactivates all DTDs by giving empty XML docs
return new InputSource(new ByteArrayInputStream(""
.getBytes()));
else
return null;
}
});
} catch (ParserConfigurationException e) {
throw new IllegalStateException("could not create DocumentBuilder", e);
}
}
private String merge(HbmFilePair genFragmentPair) throws SAXException, IOException, XPathExpressionException,
TransformerException {
if (null == genFragmentPair)
return null;
Document mergedDoc = merge(genFragmentPair.getGenHbm(), genFragmentPair.getFragmentHbm());
// then nothing was merged, because the fragment did not contain any
// nodes
if (null == mergedDoc)
return createMergedHbmFileName(genFragmentPair.getGenHbm());
return saveStateToHbmFile(genFragmentPair.getGenHbm(), mergedDoc);
}
private String saveStateToHbmFile(File genHbm, Document doc) throws IOException, TransformerException {
String pathToHbmXml = createMergedHbmFileName(genHbm);
createTransformer().transform(new DOMSource(doc),
new StreamResult(new FileOutputStream(new File(pathToHbmXml))));
return pathToHbmXml;
}
private Transformer createTransformer() throws TransformerConfigurationException {
TransformerFactory transFactory = TransformerFactory.newInstance();
Transformer transformer = transFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, HIBERNATE_DOCTYPE_PUBLIC);
transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, HIBERNATE_DOCTYPE_SYSTEM);
return transformer;
}
private String createMergedHbmFileName(File genHbm) throws IOException {
String path = genHbm.getCanonicalPath();
return path.replace(new StringBuffer().append(HbmFileNameSuffix.GEN).append("."), "");
}
private Document merge(File genHbm, File fragment) throws SAXException, IOException, XPathExpressionException,
TransformerException {
if (null == fragment || null == genHbm)
return null;
Map fragmentNodeList = new HashMap();
for (XmlElement xmlElement : XmlElement.values()) {
NodeList nodes = getFragmentNodeListByXmlElement(fragment, xmlElement);
if (nodes.getLength() > 0)
fragmentNodeList.put(xmlElement, nodes);
}
return mergeFragmentIntoGenHbm(parseFile(genHbm), fragmentNodeList);
}
private Document mergeFragmentIntoGenHbm(Document genHbm, Map fragmentNodeList)
throws XPathExpressionException, SAXException, IOException, TransformerException {
if (fragmentNodeList.isEmpty())
return null;
for (Entry entry : fragmentNodeList.entrySet())
replaceWithFragments(entry.getKey(), entry.getValue(), genHbm);
return genHbm;
}
private void replaceWithFragments(XmlElement xmlElement, NodeList fragmentNodeList, Document genHbm)
throws XPathExpressionException, SAXException, IOException, TransformerException {
for (int i = 0; i < fragmentNodeList.getLength(); i++) {
replaceWithFragment(xmlElement, fragmentNodeList.item(i), genHbm);
}
}
private void replaceWithFragment(XmlElement xmlElement, Node fragmentNode, Document genHbm)
throws XPathExpressionException, DOMException, SAXException, IOException, TransformerException {
Node relevantGenHbmNode = getRelevantGenHbmNode(xmlElement, fragmentNode, genHbm);
if (null == relevantGenHbmNode) {
//add this element
xmlElement.getParentNode(genHbm).appendChild(genHbm.importNode(fragmentNode, true));
} else if (XmlElement.CLASS.equals(xmlElement)) {
//special merge mode for class element: only attributes will be merged
mergeClassXmlElementAttributes(relevantGenHbmNode, fragmentNode, genHbm);
} else {
//merge this element
xmlElement.getParentNode(genHbm).replaceChild(genHbm.importNode(fragmentNode, true), relevantGenHbmNode);
}
}
private void mergeClassXmlElementAttributes(Node relevantGenHbmNode, Node fragmentNode, Document genHbm)
throws XPathExpressionException, DOMException, SAXException, IOException, TransformerException {
NamedNodeMap fragmentNodeAttrs = fragmentNode.getAttributes();
for (int i = 0; i < fragmentNodeAttrs.getLength(); i++) {
Node next = fragmentNodeAttrs.item(i);
Node relAttr = relevantGenHbmNode.getAttributes().getNamedItem(next.getNodeName());
if (null == relAttr) {
((Element) relevantGenHbmNode).setAttribute(next.getNodeName(), next.getNodeValue());
} else {
relAttr.setNodeValue(next.getNodeValue());
}
}
}
private Node getRelevantGenHbmNode(XmlElement xmlElement, Node fragmentNode, Document genHbm)
throws XPathExpressionException, SAXException, IOException {
if (xmlElement.isSelfIdentified()) {
return (Node) xmlElement.getXpathExpr().evaluate(genHbm, XPathConstants.NODE);
} else {
XmlElementAttributeDto props = xmlElement.getIdAttrValueFromFragmentIdAttrNode(fragmentNode);
return (Node) xmlElement.getRelevantGenHbmNodeXPathExpression(props).evaluate(genHbm, XPathConstants.NODE);
}
}
private NodeList getFragmentNodeListByXmlElement(File fragment, XmlElement xmlElement) throws SAXException,
IOException, XPathExpressionException {
return (NodeList) xmlElement.getXpathExpr().evaluate(parseFile(fragment), XPathConstants.NODESET);
}
private Document parseFile(File toParse) throws SAXException, IOException {
if (null == toParse || !toParse.isFile())
throw new IllegalArgumentException("missing file or is no file");
try {
// we do this extensive error logging, in order localise encoding
// problems in hbm xml files
return _builder.parse(toParse);
} catch (SAXParseException spe) {
String err = spe.toString() + "\n Line number: " + spe.getLineNumber() + "\nColumn number: "
+ spe.getColumnNumber() + "\n Public ID: " + spe.getPublicId() + "\n System ID: "
+ spe.getSystemId();
System.out.println(err);
throw new RuntimeException(err);
}
}
}