/*
* Copyright 2007 - 2017 the original author or authors.
*
* 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 net.sf.jailer.ui;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import net.sf.jailer.datamodel.AggregationSchema;
import net.sf.jailer.datamodel.Association;
import net.sf.jailer.datamodel.Cardinality;
import net.sf.jailer.datamodel.Table;
import net.sf.jailer.xml.XmlUtil;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
* Builds XML sketches.
*
* @author Ralf Wisser
*/
public class XmlSketchBuilder {
/**
* Builds XML sketches for given table.
*
* @param table the table
* @return xml sketch for table
*/
public static String buildSketch(Table table, int depth) throws Exception {
if (table == null) {
return "";
}
Document sketch = table.getXmlTemplateAsDocument(null);
if (sketch.getChildNodes().getLength() > 0 && sketch.getChildNodes().item(0) instanceof Element) {
insertAssociationSketch((Element) sketch.getChildNodes().item(0), table, sketch, depth);
}
return XmlUtil.buildOmitDeclaration(sketch);
}
private static void insertAssociationSketch(Element element, Table table, Document doc, int depth) throws DOMException, ParserConfigurationException, SAXException, IOException {
NodeList children = element.getChildNodes();
int i = 0;
while (i < children.getLength()) {
if (children.item(i) instanceof Element) {
Element e = (Element) children.item(i);
if (XmlUtil.NS_URI.equals(e.getNamespaceURI()) && XmlUtil.ASSOCIATION_TAG.equals(e.getLocalName()) && e.getTextContent() != null) {
Association association = null;
for (Association a: table.associations) {
if (a.getAggregationSchema() != AggregationSchema.NONE) {
if (a.getName().equals(e.getTextContent().trim())) {
association = a;
break;
}
}
}
if (association != null && depth < 3) {
Node[] ae = insertAssociationSketch(association, doc, depth + 1);
if (ae != null) {
for (Node n: ae) {
element.insertBefore(doc.importNode(n, true), e);
++i;
}
}
}
element.removeChild(e);
} else {
++i;
}
} else {
++i;
}
}
}
private static Node[] insertAssociationSketch(Association association, Document doc, int depth) throws ParserConfigurationException, SAXException, IOException {
if (association.getAggregationSchema() == AggregationSchema.EXPLICIT_LIST) {
Element e1 = doc.createElement(association.getAggregationTagName());
Element e2 = doc.createElement(association.destination.getUnqualifiedName().toLowerCase());
e1.appendChild(e2);
if (association.getCardinality() != Cardinality.MANY_TO_ONE && association.getCardinality() != Cardinality.ONE_TO_ONE) {
e1.appendChild(doc.createComment("..."));
}
return new Node[] { e1 };
}
else if (association.getAggregationSchema() == AggregationSchema.IMPLICIT_LIST) {
Element e1 = doc.createElement(association.getAggregationTagName());
if (association.getCardinality() != Cardinality.MANY_TO_ONE && association.getCardinality() != Cardinality.ONE_TO_ONE) {
Node c = doc.createComment("...");
return new Node[] { e1, c };
}
return new Node[] { e1 };
} else if (association.getAggregationSchema() == AggregationSchema.FLAT) {
Document sketch = association.destination.getXmlTemplateAsDocument(null);
List<Node> nodes = new ArrayList<Node>();
if (sketch.getChildNodes().getLength() > 0 && sketch.getChildNodes().item(0) instanceof Element) {
insertAssociationSketch((Element) sketch.getChildNodes().item(0), association.destination, sketch, depth + 1);
}
NodeList children = sketch.getChildNodes().item(0).getChildNodes();
for (int i = 0; i < children.getLength(); ++i) {
nodes.add(children.item(i));
}
if (association.getCardinality() != Cardinality.MANY_TO_ONE && association.getCardinality() != Cardinality.ONE_TO_ONE) {
nodes.add(sketch.createComment("..."));
}
return nodes.toArray(new Node[nodes.size()]);
}
return null;
}
/**
* Builds XML sketches for given table.
*
* @param table the table
* @return xml sketch for table
*/
public static String buildSketch2(Table table, int depth) {
StringBuilder sb = new StringBuilder();
if (table != null && depth < 2) {
List<Association> sortedSourceAssociations = new ArrayList<Association>(table.associations);
Collections.sort(sortedSourceAssociations, new Comparator<Association>() {
public int compare(Association o1, Association o2) {
return o1.destination.getName().compareTo(o2.destination.getName());
}
});
if (depth == 0) {
sb.append("<" + table.getUnqualifiedName().toLowerCase() + ">\n");
sb.append(" -- elements of " + table.getUnqualifiedName() + " --\n");
}
String indent = " ";
for (Association a: sortedSourceAssociations) {
if (a.getAggregationSchema() == AggregationSchema.EXPLICIT_LIST) {
sb.append(indent + "<" + a.getAggregationTagName() + ">\n");
sb.append(indent + " <" + a.destination.getUnqualifiedName().toLowerCase() + "/>\n");
if (a.getCardinality() != Cardinality.MANY_TO_ONE && a.getCardinality() != Cardinality.ONE_TO_ONE) {
sb.append(indent + " <" + a.destination.getUnqualifiedName().toLowerCase() + "/>\n");
sb.append(indent + " ...\n");
}
sb.append(indent + "</" + a.getAggregationTagName() + ">\n");
} else if (a.getAggregationSchema() == AggregationSchema.IMPLICIT_LIST) {
sb.append(indent + "<" + a.getAggregationTagName() + "/>\n");
if (a.getCardinality() != Cardinality.MANY_TO_ONE && a.getCardinality() != Cardinality.ONE_TO_ONE) {
sb.append(indent + "<" + a.getAggregationTagName() + "/>\n");
sb.append(indent + " ...\n");
}
} else if (a.getAggregationSchema() == AggregationSchema.FLAT) {
sb.append(indent + "-- elements of " + a.destination.getUnqualifiedName() + "(flattened " + a.getName() + ") --\n");
sb.append(buildSketch2(a.destination, depth + 1));
if (a.getCardinality() != Cardinality.MANY_TO_ONE && a.getCardinality() != Cardinality.ONE_TO_ONE) {
sb.append(indent + "-- elements of " + a.destination.getUnqualifiedName() + "(flattened " + a.getName() + ") --\n");
sb.append(indent + " ...\n");
}
}
}
if (depth == 0) {
sb.append("</" + table.getUnqualifiedName().toLowerCase() + ">\n");
}
}
return sb.toString();
}
}