/*
* Copyright 2014 JBoss Inc
*
* 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 org.artificer.integration.artifactbuilder;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.AttributeDeclaration;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BaseArtifactEnum;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BaseArtifactType;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ComplexTypeDeclaration;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.ElementDeclaration;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.SimpleTypeDeclaration;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.XsdDocument;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.XsdDocumentEnum;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.XsdDocumentTarget;
import org.artificer.common.ArtifactTypeEnum;
import org.artificer.common.query.xpath.StaticNamespaceContext;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
* @author Brett Meyer
*/
public class XsdDocumentArtifactBuilder extends XmlArtifactBuilder {
protected IndexedArtifactCollection derivedArtifacts = new IndexedArtifactCollection();
@Override
protected void configureNamespaceMappings(StaticNamespaceContext namespaceContext) {
super.configureNamespaceMappings(namespaceContext);
namespaceContext.addMapping("xs", "http://www.w3.org/2001/XMLSchema");
namespaceContext.addMapping("xsd", "http://www.w3.org/2001/XMLSchema");
}
@Override
protected void derive() throws IOException {
try {
String targetNS = rootElement.getAttribute("targetNamespace");
if (getPrimaryArtifact() instanceof XsdDocument) {
((XsdDocument) getPrimaryArtifact()).setTargetNamespace(targetNS);
}
deriveXsd(rootElement);
processImportedXsds(rootElement, targetNS);
processIncludedXsds(rootElement, targetNS);
processRedefinedXsds(rootElement, targetNS);
} catch (Exception e) {
throw new IOException(e);
}
}
protected void deriveXsd(Element schema) throws XPathExpressionException {
String targetNS = schema.getAttribute("targetNamespace");
processElementDeclarations(schema, targetNS);
processAttributeDeclarations(schema, targetNS);
processSimpleTypeDeclarations(schema, targetNS);
processComplexTypeDeclarations(schema, targetNS);
}
private void processElementDeclarations(Element schema, String targetNS) throws XPathExpressionException {
// xpath expression to find all global element decls
NodeList nodes = (NodeList) query(schema, "./xsd:element", XPathConstants.NODESET);
for (int idx = 0; idx < nodes.getLength(); idx++) {
Element node = (Element) nodes.item(idx);
if (node.hasAttribute("name")) {
String nsName = node.getAttribute("name");
ElementDeclaration elementDecl = new ElementDeclaration();
elementDecl.setArtifactType(BaseArtifactEnum.ELEMENT_DECLARATION);
elementDecl.setName(nsName);
elementDecl.setNamespace(targetNS);
elementDecl.setNCName(nsName);
derivedArtifacts.add(elementDecl);
}
}
}
private void processAttributeDeclarations(Element schema, String targetNS) throws XPathExpressionException {
// xpath expression to find all global attribute decls
NodeList nodes = (NodeList) query(schema, "./xsd:attribute", XPathConstants.NODESET);
for (int idx = 0; idx < nodes.getLength(); idx++) {
Element node = (Element) nodes.item(idx);
if (node.hasAttribute("name")) {
String nsName = node.getAttribute("name");
AttributeDeclaration attributeDecl = new AttributeDeclaration();
attributeDecl.setArtifactType(BaseArtifactEnum.ATTRIBUTE_DECLARATION);
attributeDecl.setName(nsName);
attributeDecl.setNamespace(targetNS);
attributeDecl.setNCName(nsName);
derivedArtifacts.add(attributeDecl);
}
}
}
private void processSimpleTypeDeclarations(Element schema, String targetNS) throws XPathExpressionException {
// xpath expression to find all global simple type decls
NodeList nodes = (NodeList) query(schema, "./xsd:simpleType", XPathConstants.NODESET);
for (int idx = 0; idx < nodes.getLength(); idx++) {
Element node = (Element) nodes.item(idx);
if (node.hasAttribute("name")) {
String nsName = node.getAttribute("name");
SimpleTypeDeclaration simpleTypeDecl = new SimpleTypeDeclaration();
simpleTypeDecl.setArtifactType(BaseArtifactEnum.SIMPLE_TYPE_DECLARATION);
simpleTypeDecl.setName(nsName);
simpleTypeDecl.setNamespace(targetNS);
simpleTypeDecl.setNCName(nsName);
derivedArtifacts.add(simpleTypeDecl);
}
}
}
private void processComplexTypeDeclarations(Element schema, String targetNS) throws XPathExpressionException {
// xpath expression to find all global complex type decls
NodeList nodes = (NodeList) query(schema, "./xsd:complexType", XPathConstants.NODESET);
for (int idx = 0; idx < nodes.getLength(); idx++) {
Element node = (Element) nodes.item(idx);
if (node.hasAttribute("name")) {
String nsName = node.getAttribute("name");
ComplexTypeDeclaration complexTypeDecl = new ComplexTypeDeclaration();
complexTypeDecl.setArtifactType(BaseArtifactEnum.COMPLEX_TYPE_DECLARATION);
complexTypeDecl.setName(nsName);
complexTypeDecl.setNamespace(targetNS);
complexTypeDecl.setNCName(nsName);
derivedArtifacts.add(complexTypeDecl);
}
}
}
private void processImportedXsds(Element schema, String targetNS) throws XPathExpressionException {
if (getPrimaryArtifact() instanceof XsdDocument) {
processImportedXsds(((XsdDocument) getPrimaryArtifact()).getImportedXsds(), schema, targetNS);
}
}
protected void processImportedXsds(List<XsdDocumentTarget> targetCollection, Element schema, String targetNS) throws XPathExpressionException {
NodeList nodes = (NodeList) query(schema, "./xsd:import", XPathConstants.NODESET);
for (int idx = 0; idx < nodes.getLength(); idx++) {
Element node = (Element) nodes.item(idx);
if (node.hasAttribute("namespace") && node.hasAttribute("schemaLocation")) {
String namespace = node.getAttribute("namespace");
String schemaLocation = node.getAttribute("schemaLocation");
stripPath(schemaLocation);
XsdDocument xsdDocumentRef = derivedArtifacts.lookupXsdDocument(namespace, schemaLocation);
XsdDocumentTarget xsdDocumentTarget = new XsdDocumentTarget();
xsdDocumentTarget.setArtifactType(XsdDocumentEnum.XSD_DOCUMENT);
if (xsdDocumentRef != null) {
xsdDocumentTarget.setValue(xsdDocumentRef.getUuid());
} else {
relationshipSources.add(new NamespaceRelationshipSource(namespace, schemaLocation,
xsdDocumentTarget, targetCollection, ArtifactTypeEnum.XsdDocument.getModel(),
ArtifactTypeEnum.XsdDocument.getType()));
}
targetCollection.add(xsdDocumentTarget);
}
}
}
private void processIncludedXsds(Element schema, String targetNS) throws XPathExpressionException {
if (getPrimaryArtifact() instanceof XsdDocument) {
processIncludedXsds(((XsdDocument) getPrimaryArtifact()).getIncludedXsds(), schema, targetNS);
}
}
protected void processIncludedXsds(List<XsdDocumentTarget> targetCollection, Element schema, String targetNS) throws XPathExpressionException {
NodeList nodes = (NodeList) query(schema, "./xsd:include", XPathConstants.NODESET);
for (int idx = 0; idx < nodes.getLength(); idx++) {
Element node = (Element) nodes.item(idx);
if (node.hasAttribute("schemaLocation")) {
String schemaLocation = node.getAttribute("schemaLocation");
stripPath(schemaLocation);
XsdDocument xsdDocumentRef = derivedArtifacts.lookupXsdDocument(targetNS, schemaLocation);
XsdDocumentTarget xsdDocumentTarget = new XsdDocumentTarget();
xsdDocumentTarget.setArtifactType(XsdDocumentEnum.XSD_DOCUMENT);
if (xsdDocumentRef != null) {
xsdDocumentTarget.setValue(xsdDocumentRef.getUuid());
} else {
relationshipSources.add(new NamespaceRelationshipSource(targetNS, schemaLocation, xsdDocumentTarget, targetCollection,
ArtifactTypeEnum.XsdDocument.getModel(), ArtifactTypeEnum.XsdDocument.getType()));
}
targetCollection.add(xsdDocumentTarget);
}
}
}
private void processRedefinedXsds(Element schema, String targetNS) throws XPathExpressionException {
if (getPrimaryArtifact() instanceof XsdDocument) {
processRedefinedXsds(((XsdDocument) getPrimaryArtifact()).getRedefinedXsds(), schema, targetNS);
}
}
protected void processRedefinedXsds(List<XsdDocumentTarget> targetCollection, Element schema, String targetNS) throws XPathExpressionException {
NodeList nodes = (NodeList) query(schema, "./xsd:redefine", XPathConstants.NODESET);
for (int idx = 0; idx < nodes.getLength(); idx++) {
Element node = (Element) nodes.item(idx);
if (node.hasAttribute("schemaLocation")) {
String schemaLocation = node.getAttribute("schemaLocation");
stripPath(schemaLocation);
XsdDocument xsdDocumentRef = derivedArtifacts.lookupXsdDocument(targetNS, schemaLocation);
XsdDocumentTarget xsdDocumentTarget = new XsdDocumentTarget();
xsdDocumentTarget.setArtifactType(XsdDocumentEnum.XSD_DOCUMENT);
if (xsdDocumentRef != null) {
xsdDocumentTarget.setValue(xsdDocumentRef.getUuid());
} else {
relationshipSources.add(new NamespaceRelationshipSource(targetNS, schemaLocation, xsdDocumentTarget, targetCollection,
ArtifactTypeEnum.XsdDocument.getModel(), ArtifactTypeEnum.XsdDocument.getType()));
}
targetCollection.add(xsdDocumentTarget);
}
}
}
// TODO: Move to a util?
protected void stripPath(String s) {
// If it's an absolute path, strip it down.
if (s.lastIndexOf("/") > -1) {
s = s.substring(s.lastIndexOf("/"));
}
if (s.lastIndexOf("\\") > -1) {
s = s.substring(s.lastIndexOf("\\")); // Shame on you for using Windows...
}
}
@Override
public Collection<BaseArtifactType> getDerivedArtifacts() {
return derivedArtifacts;
}
}