blob: 73b9e8526857ccd84877e707097ff819bdf22d09 [file] [log] [blame]
/**
*
* Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable.
*
* 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.apache.xbean.spring.generator;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;
import java.util.Collections;
/**
* @author Dain Sundstrom
* @version $Id$
* @since 1.0
*/
public class XsdGenerator implements GeneratorPlugin {
private final File destFile;
private final LogFacade log;
public XsdGenerator(LogFacade log, File destFile) {
this.destFile = destFile;
this.log = log;
}
public void generate(NamespaceMapping namespaceMapping) throws IOException {
// TODO can only handle 1 schema document so far...
File file = destFile;
log.log("Generating XSD file: " + file + " for namespace: " + namespaceMapping.getNamespace());
PrintWriter out = new PrintWriter(new FileWriter(file));
try {
generateSchema(out, namespaceMapping);
} finally {
out.close();
}
}
private void generateSchema(PrintWriter out, NamespaceMapping namespaceMapping) {
out.println("<?xml version='1.0'?>");
out.println("<!-- NOTE: this file is autogenerated by XBeans -->");
out.println();
out.println("<xs:schema elementFormDefault='qualified'");
out.println(" targetNamespace='" + namespaceMapping.getNamespace() + "'");
out.println(" xmlns:xs='http://www.w3.org/2001/XMLSchema'");
out.println(" xmlns:tns='" + namespaceMapping.getNamespace() + "'>");
for (Iterator iter = namespaceMapping.getElements().iterator(); iter.hasNext();) {
ElementMapping element = (ElementMapping) iter.next();
generateElementMapping(out, namespaceMapping, element);
}
out.println();
out.println("</xs:schema>");
}
private void generateElementMapping(PrintWriter out, NamespaceMapping namespaceMapping, ElementMapping element) {
out.println();
out.println(" <!-- element for type: " + element.getClassName() + " -->");
String localName = element.getElementName();
out.println(" <xs:element name='" + localName + "'>");
out.println(" <xs:complexType>");
int complexCount = 0;
for (Iterator iterator = element.getAttributes().iterator(); iterator.hasNext();) {
AttributeMapping attributeMapping = (AttributeMapping) iterator.next();
if (!Utils.isSimpleType(attributeMapping.getType())) {
complexCount++;
}
}
if (complexCount > 0) {
out.println(" <xs:sequence>");
for (Iterator iterator = element.getAttributes().iterator(); iterator.hasNext();) {
AttributeMapping attributeMapping = (AttributeMapping) iterator.next();
if (!Utils.isSimpleType(attributeMapping.getType())) {
generateElementMappingComplexProperty(out, namespaceMapping, attributeMapping);
}
}
out.println(" </xs:sequence>");
}
for (Iterator iterator = element.getAttributes().iterator(); iterator.hasNext();) {
AttributeMapping attributeMapping = (AttributeMapping) iterator.next();
if (Utils.isSimpleType(attributeMapping.getType())) {
generateElementMappingSimpleProperty(out, attributeMapping);
} else if (!attributeMapping.getType().isCollection()) {
generateElementMappingComplexPropertyAsRef(out, attributeMapping);
}
}
out.println(" <xs:anyAttribute namespace='##other' processContents='lax'/>");
out.println(" </xs:complexType>");
out.println(" </xs:element>");
out.println();
}
private void generateElementMappingSimpleProperty(PrintWriter out, AttributeMapping attributeMapping) {
out.println(" <xs:attribute name='" + attributeMapping.getAttributeName() + "' type='" + Utils.getXsdType(attributeMapping.getType()) + "'/>");
}
private void generateElementMappingComplexPropertyAsRef(PrintWriter out, AttributeMapping attributeMapping) {
out.println(" <xs:attribute name='" + attributeMapping.getAttributeName() + "' type='xs:string'/>");
}
private void generateElementMappingComplexProperty(PrintWriter out, NamespaceMapping namespaceMapping, AttributeMapping attributeMapping) {
Type type = attributeMapping.getType();
List types;
if (type.isCollection()) {
types = Utils.findImplementationsOf(namespaceMapping, type.getNestedType());
} else {
types = Utils.findImplementationsOf(namespaceMapping, type);
}
types = Collections.EMPTY_LIST;
String maxOccurs = type.isCollection() ? "unbounded" : "1";
out.println(" <xs:element name='" + attributeMapping.getAttributeName() + "' minOccurs='0' maxOccurs='1'>");
out.println(" <xs:complexType>");
if (types.isEmpty()) {
out.println(" <xs:sequence minOccurs='0' maxOccurs='" + maxOccurs + "'><xs:any/></xs:sequence>");
} else {
out.println(" <xs:choice minOccurs='0' maxOccurs='" + maxOccurs + "'>");
for (Iterator iterator = types.iterator(); iterator.hasNext();) {
ElementMapping element = (ElementMapping) iterator.next();
out.println(" <xs:element ref='tns:" + element.getElementName() + "'/>");
}
out.println(" </xs:choice>");
}
out.println(" </xs:complexType>");
out.println(" </xs:element>");
}
}