/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The name "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
package org.apache.ws.jaxme.generator.sg.impl;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.ws.jaxme.XMLWriter;
import org.apache.ws.jaxme.generator.sg.Context;
import org.apache.ws.jaxme.generator.sg.GroupSG;
import org.apache.ws.jaxme.generator.sg.ObjectSG;
import org.apache.ws.jaxme.generator.sg.SGFactory;
import org.apache.ws.jaxme.generator.sg.SchemaSG;
import org.apache.ws.jaxme.generator.sg.SchemaSGChain;
import org.apache.ws.jaxme.generator.sg.TypeSG;
import org.apache.ws.jaxme.impl.JAXBContextImpl;
import org.apache.ws.jaxme.impl.XMLWriterImpl;
import org.apache.ws.jaxme.js.JavaConstructor;
import org.apache.ws.jaxme.js.JavaField;
import org.apache.ws.jaxme.js.JavaMethod;
import org.apache.ws.jaxme.js.JavaQName;
import org.apache.ws.jaxme.js.JavaQNameImpl;
import org.apache.ws.jaxme.js.JavaSource;
import org.apache.ws.jaxme.js.JavaSourceFactory;
import org.apache.ws.jaxme.js.Parameter;
import org.apache.ws.jaxme.js.TextFile;
import org.apache.ws.jaxme.logging.Logger;
import org.apache.ws.jaxme.logging.LoggerAccess;
import org.apache.ws.jaxme.util.DOMSerializer;
import org.apache.ws.jaxme.xs.XSElement;
import org.apache.ws.jaxme.xs.XSGroup;
import org.apache.ws.jaxme.xs.XSSchema;
import org.apache.ws.jaxme.xs.XSType;
import org.apache.ws.jaxme.xs.jaxb.JAXBGlobalBindings;
import org.apache.ws.jaxme.xs.jaxb.JAXBJavaType;
import org.apache.ws.jaxme.xs.jaxb.JAXBSchema;
import org.apache.ws.jaxme.xs.types.XSNCName;
import org.apache.ws.jaxme.xs.xml.XsQName;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
/**
* @author <a href="mailto:joe@ispsoft.de">Jochen Wiedmann</a>
*/
public class JAXBSchemaSG implements SchemaSGChain {
private final static Logger log = LoggerAccess.getLogger(JAXBSchemaSG.class);
private final Map elementsByName = new HashMap();
private final Map groupsByName = new HashMap();
private final Map typesByName = new HashMap();
private final SGFactory factory;
private final XSSchema xsSchema;
private final JavaSourceFactory javaSourceFactory = new JavaSourceFactory();
private TypeSG[] typesByOrder;
private ObjectSG[] elementsByOrder;
private ObjectSG[] objectsByOrder;
private GroupSG[] groupsByOrder;
/** <p>Creates a new instance of JAXBSchemaSG.</p>
*/
public JAXBSchemaSG(SGFactory pFactory, XSSchema pSchema) {
factory = pFactory;
xsSchema = pSchema;
javaSourceFactory.setOverwriteForced(pFactory.getGenerator().isForcingOverwrite());
javaSourceFactory.setSettingReadOnly(pFactory.getGenerator().isSettingReadOnly());
}
public SchemaSG getSchema(SchemaSG pController) { return pController; }
public Locator getLocator(SchemaSG pController) { return xsSchema.getLocator(); }
public SGFactory getFactory(SchemaSG pController) { return factory; }
protected XSSchema getXSSchema() { return xsSchema; }
public void init(SchemaSG pController) throws SAXException {
final String mName = "init";
log.finest(mName, "->");
Object[] childs = getXSSchema().getChilds();
List elements = new ArrayList();
List types = new ArrayList();
List groups = new ArrayList();
List objects = new ArrayList();
for (int i = 0; i < childs.length; i++) {
Object o = childs[i];
log.finest(mName, "Child" + o);
if (o instanceof XSType) {
TypeSG typeSG = pController.getType(((XSType) o).getName());
if (typeSG == null) {
throw new IllegalStateException("TypeSG not created");
}
types.add(typeSG);
} else if (o instanceof XSGroup) {
GroupSG groupSG = pController.getGroup(((XSGroup) o).getName());
if (groupSG == null) {
throw new IllegalStateException("GroupSG not created");
}
groups.add(groupSG);
} else if (o instanceof XSElement) {
ObjectSG objectSG = pController.getElement(((XSElement) o).getName());
if (objectSG == null) {
throw new IllegalStateException("ObjectSG not created");
}
objects.add(objectSG);
elements.add(objectSG);
}
}
elementsByOrder = (ObjectSG[]) elements.toArray(new ObjectSG[elements.size()]);
typesByOrder = (TypeSG[]) types.toArray(new TypeSG[types.size()]);
groupsByOrder = (GroupSG[]) groups.toArray(new GroupSG[groups.size()]);
objectsByOrder = (ObjectSG[]) objects.toArray(new ObjectSG[objects.size()]);
log.finest(mName, "<-");
}
public TypeSG getType(SchemaSG pController, XsQName pName) throws SAXException {
TypeSG typeSG = (TypeSG) typesByName.get(pName);
if (typeSG != null) {
return typeSG;
}
XSType type = getXSSchema().getType(pName);
if (type == null) {
return null;
}
typeSG = pController.getFactory().getTypeSG(type);
typesByName.put(pName, typeSG);
return typeSG;
}
public GroupSG[] getGroups(SchemaSG pController) throws SAXException {
return groupsByOrder;
}
public GroupSG getGroup(SchemaSG pController, XsQName pName) throws SAXException {
GroupSG groupSG = (GroupSG) groupsByName.get(pName);
if (groupSG != null) {
return groupSG;
}
XSGroup group = getXSSchema().getGroup(pName);
if (group == null) {
return null;
}
groupSG = pController.getFactory().getGroupSG(group);
groupsByName.put(pName, groupSG);
return groupSG;
}
public TypeSG[] getTypes(SchemaSG pController) throws SAXException {
return typesByOrder;
}
public ObjectSG[] getObjects(SchemaSG pController) throws SAXException {
return objectsByOrder;
}
public ObjectSG getElement(SchemaSG pController, XsQName pName) throws SAXException {
ObjectSG objectSG = (ObjectSG) elementsByName.get(pName);
if (objectSG != null) {
return objectSG;
}
XSElement element = getXSSchema().getElement(pName);
if (element == null) {
return null;
}
objectSG = pController.getFactory().getObjectSG(element);
elementsByName.put(pName, objectSG);
return objectSG;
}
public String getCollectionType(SchemaSG pController) {
XSSchema schema = getXSSchema();
if (schema instanceof JAXBSchema) {
JAXBSchema jaxbSchema = (JAXBSchema) schema;
JAXBGlobalBindings globalBindings = jaxbSchema.getJAXBGlobalBindings();
if (globalBindings != null) {
String result = globalBindings.getCollectionType();
if (result != null) {
return result;
}
}
}
return ArrayList.class.getName();
}
public JavaSourceFactory getJavaSourceFactory(SchemaSG pController) {
return javaSourceFactory;
}
public void generate(SchemaSG pController) throws SAXException {
GroupSG[] groups = pController.getGroups();
for (int i = 0; i < groups.length; i++) {
groups[i].generate();
}
TypeSG[] types = pController.getTypes();
for (int i = 0; i < types.length; i++) {
types[i].generate();
}
ObjectSG[] objects = pController.getObjects();
for (int i = 0; i < objects.length; i++) {
objects[i].generate();
}
pController.generateJaxbProperties();
}
public ObjectSG[] getElements(SchemaSG pController) throws SAXException {
return elementsByOrder;
}
public boolean isBindingStyleModelGroup(SchemaSG pController) {
XSSchema schema = getXSSchema();
if (schema instanceof JAXBSchema) {
JAXBSchema jaxbSchema = (JAXBSchema) schema;
JAXBGlobalBindings globalBindings = jaxbSchema.getJAXBGlobalBindings();
if (globalBindings != null) {
return globalBindings.isBindingStyleModelGroup();
}
}
return false;
}
public boolean isChoiceContentProperty(SchemaSG pController) {
XSSchema schema = getXSSchema();
if (schema instanceof JAXBSchema) {
JAXBSchema jaxbSchema = (JAXBSchema) schema;
JAXBGlobalBindings globalBindings = jaxbSchema.getJAXBGlobalBindings();
if (globalBindings != null) {
return globalBindings.isChoiceContentProperty();
}
}
return false;
}
public boolean isFailFastCheckEnabled(SchemaSG pController) {
XSSchema schema = getXSSchema();
if (schema instanceof JAXBSchema) {
JAXBSchema jaxbSchema = (JAXBSchema) schema;
JAXBGlobalBindings globalBindings = jaxbSchema.getJAXBGlobalBindings();
if (globalBindings != null) {
return globalBindings.isEnableFailFastCheck();
}
}
return false;
}
public boolean isJavaNamingConventionsEnabled(SchemaSG pController) {
XSSchema schema = getXSSchema();
if (schema instanceof JAXBSchema) {
JAXBSchema jaxbSchema = (JAXBSchema) schema;
JAXBGlobalBindings globalBindings = jaxbSchema.getJAXBGlobalBindings();
if (globalBindings != null) {
return globalBindings.isEnableJavaNamingConventions();
}
}
return true;
}
public boolean isFixedAttributeConstantProperty(SchemaSG pController) {
XSSchema schema = getXSSchema();
if (schema instanceof JAXBSchema) {
JAXBSchema jaxbSchema = (JAXBSchema) schema;
JAXBGlobalBindings globalBindings = jaxbSchema.getJAXBGlobalBindings();
if (globalBindings != null) {
return globalBindings.isFixedAttributeAsConstantProperty();
}
}
return false;
}
public boolean isGeneratingIsSetMethod(SchemaSG pController) {
XSSchema schema = getXSSchema();
if (schema instanceof JAXBSchema) {
JAXBSchema jaxbSchema = (JAXBSchema) schema;
JAXBGlobalBindings globalBindings = jaxbSchema.getJAXBGlobalBindings();
if (globalBindings != null) {
return globalBindings.isGenerateIsSetMethod();
}
}
return false;
}
public boolean isUnderscoreWordSeparator(SchemaSG pController) {
XSSchema schema = getXSSchema();
if (schema instanceof JAXBSchema) {
JAXBSchema jaxbSchema = (JAXBSchema) schema;
JAXBGlobalBindings globalBindings = jaxbSchema.getJAXBGlobalBindings();
if (globalBindings != null) {
return JAXBGlobalBindings.UnderscoreBinding.AS_WORD_SEPARATOR.equals(globalBindings.getUnderscoreBinding());
}
}
return true;
}
public JAXBJavaType[] getJAXBJavaTypes(SchemaSG pController) {
XSSchema schema = getXSSchema();
if (schema instanceof JAXBSchema) {
JAXBSchema jaxbSchema = (JAXBSchema) schema;
JAXBGlobalBindings globalBindings = jaxbSchema.getJAXBGlobalBindings();
if (globalBindings != null) {
return globalBindings.getJavaType();
}
}
return new JAXBJavaType[0];
}
public XsQName[] getTypesafeEnumBase(SchemaSG pController) {
XSSchema schema = getXSSchema();
if (schema instanceof JAXBSchema) {
JAXBSchema jaxbSchema = (JAXBSchema) schema;
JAXBGlobalBindings globalBindings = jaxbSchema.getJAXBGlobalBindings();
if (globalBindings != null) {
return globalBindings.getTypesafeEnumBase();
}
}
return new XsQName[]{XSNCName.getInstance().getName()};
}
public Document getConfigFile(SchemaSG pController, String pPackageName, List pContextList)
throws SAXException {
final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
dbf.setValidating(false);
final DocumentBuilder db;
try {
db = dbf.newDocumentBuilder();
} catch (ParserConfigurationException e) {
throw new SAXException("Failed to create a DocumentBuilder: " + e.getMessage(), e);
}
final Document doc = db.newDocument();
final String uri = JAXBContextImpl.CONFIGURATION_URI;
final Element root = doc.createElementNS(uri, "Configuration");
root.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns", uri);
doc.appendChild(root);
for (Iterator iter = pContextList.iterator(); iter.hasNext(); ) {
Object o = iter.next();
Context ctx;
if (o instanceof ObjectSG) {
ctx = ((ObjectSG) o).getClassContext();
} else {
ctx = ((TypeSG) o).getComplexTypeSG().getClassContext();
}
String packageName = ctx.getXMLInterfaceName().getPackageName();
if (packageName == null) {
packageName = "";
}
if (!packageName.equals(pPackageName)) {
continue;
}
Element manager = doc.createElementNS(uri, "Manager");
root.appendChild(manager);
manager.setAttributeNS(null, "elementInterface", ctx.getXMLInterfaceName().toString());
manager.setAttributeNS(null, "elementClass", ctx.getXMLImplementationName().toString());
manager.setAttributeNS(null, "handlerClass", ctx.getXMLHandlerName().toString());
manager.setAttributeNS(null, "marshallerClass", ctx.getXMLSerializerName().toString());
manager.setAttributeNS(null, "validatorClass", ctx.getXMLValidatorName().toString());
if (o instanceof ObjectSG) {
manager.setAttributeNS(null, "qName", ((ObjectSG) o).getName().toString());
}
}
return doc;
}
protected String generateConfigFile(SchemaSG pController, String pPackageName, List pContextList) throws SAXException {
Document doc = pController.getConfigFile(pPackageName, pContextList);
StringWriter sw = new StringWriter();
XMLWriter xw = new XMLWriterImpl();
try {
xw.setWriter(sw);
} catch (JAXBException e) {
throw new SAXException(e);
}
DOMSerializer ds = new DOMSerializer();
ds.serialize(doc, xw);
return sw.toString();
}
public void generateJaxbProperties(SchemaSG pController) throws SAXException {
List contextList = new ArrayList();
ObjectSG[] elements = pController.getElements();
for (int i = 0; i < elements.length; i++) {
contextList.add(elements[i]);
}
TypeSG[] types = pController.getTypes();
for (int i = 0; i < types.length; i++) {
if (types[i].isComplex()) {
contextList.add(types[i]);
}
}
Map packages = new HashMap();
for (Iterator iter = contextList.iterator(); iter.hasNext(); ) {
Object o = iter.next();
Context ctx;
if (o instanceof ObjectSG) {
ctx = ((ObjectSG) o).getClassContext();
} else {
ctx = ((TypeSG) o).getComplexTypeSG().getClassContext();
}
String packageName = ctx.getXMLInterfaceName().getPackageName();
if (packages.containsKey(packageName)) {
continue;
}
TextFile textFile = pController.getJavaSourceFactory().newTextFile(packageName, "jaxb.properties");
textFile.addLine(JAXBContext.JAXB_CONTEXT_FACTORY + "=" + JAXBContextImpl.class.getName());
packages.put(packageName, textFile);
String configFile = generateConfigFile(pController, packageName, contextList);
TextFile confFile = pController.getJavaSourceFactory().newTextFile(packageName, "Configuration.xml");
confFile.setContents(configFile);
getObjectFactory(pController, packageName, contextList);
}
}
protected JavaSource getObjectFactory(SchemaSG pController, String pPackageName, List pContextList) {
JavaQName qName = JavaQNameImpl.getInstance(pPackageName, "ObjectFactory");
JavaSource js = pController.getJavaSourceFactory().newJavaSource(qName, "public");
JavaField jf = js.newJavaField("jaxbContext", JAXBContextImpl.class, "private");
JavaField properties = js.newJavaField("properties", Map.class, "private");
JavaConstructor jcon = js.newJavaConstructor("public");
jcon.addThrows(JAXBException.class);
jcon.addLine(jf, " = (", JAXBContextImpl.class, ") ",
JAXBContext.class, ".newInstance(",
JavaSource.getQuoted(pPackageName), ");");
JavaMethod newInstanceMethod = js.newJavaMethod("newInstance", Object.class, "public");
newInstanceMethod.addThrows(JAXBException.class);
Parameter pElementInterface = newInstanceMethod.addParam(Class.class, "pElementInterface");
newInstanceMethod.addLine("return ", jf, ".getElement(", pElementInterface, ");");
{
JavaMethod getPropertyMethod = js.newJavaMethod("getProperty", Object.class, "public");
Parameter pName = getPropertyMethod.addParam(String.class, "pName");
getPropertyMethod.addIf(properties, " == null");
getPropertyMethod.addLine("return null;");
getPropertyMethod.addEndIf();
getPropertyMethod.addLine("return ", properties, ".get(", pName, ");");
}
{
JavaMethod setPropertyMethod = js.newJavaMethod("setProperty", void.class, "public");
Parameter pName = setPropertyMethod.addParam(String.class, "pName");
Parameter pValue = setPropertyMethod.addParam(Object.class, "pValue");
setPropertyMethod.addIf(properties, " == null");
setPropertyMethod.addLine(properties, " = new ", HashMap.class, "();");
setPropertyMethod.addEndIf();
setPropertyMethod.addLine(properties, ".put(", pName, ", ", pValue, ");");
}
for (Iterator iter = pContextList.iterator(); iter.hasNext(); ) {
Object o = iter.next();
if (!(o instanceof ObjectSG)) {
continue;
}
ObjectSG objectSG = (ObjectSG) o;
TypeSG typeSG = objectSG.getTypeSG();
if (!typeSG.isComplex()) {
continue;
}
JavaQName resultName = objectSG.getClassContext().getXMLInterfaceName();
String className = resultName.getClassName();
String methodName = "create" + Character.toUpperCase(className.charAt(0)) + className.substring(1);
JavaMethod createMethod = js.newJavaMethod(methodName, resultName, "public");
createMethod.addThrows(JAXBException.class);
createMethod.addLine("return (", resultName, ") newInstance(", resultName, ".class);");
}
return js;
}
}