/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2002-2008, Open Source Geospatial Foundation (OSGeo)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotools.maven.xmlcodegen;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.eclipse.xsd.XSDAttributeDeclaration;
import org.eclipse.xsd.XSDComplexTypeContent;
import org.eclipse.xsd.XSDComplexTypeDefinition;
import org.eclipse.xsd.XSDElementDeclaration;
import org.eclipse.xsd.XSDInclude;
import org.eclipse.xsd.XSDNamedComponent;
import org.eclipse.xsd.XSDSchema;
import org.eclipse.xsd.XSDTypeDefinition;
import org.geotools.xml.Schemas;
/**
* Generates bindings for types, elements, and attributes declared in an xml
* schema.
* <p>
* Usage Example:
* <pre>
* <code>
* XSDSchem schema = ...
* BindingGenerator g = new BindingGenerator();
* g.setPackageBase( "org.geotools.xml.xs" );
* g.setLocation( "/home/user" );
* g.generate( schema );
* </code>
* </pre>
* </p>
*
* @author Justin Deoliveira, The Open Planning Project, jdeolive@openplans.org
*
*/
public class BindingGenerator extends AbstractGenerator {
static Logger logger = org.geotools.util.logging.Logging.getLogger("org.geotools.xml");
boolean generateXsd = true;
boolean generateAttributes = true;
boolean generateElements = true;
boolean generateTypes = true;
boolean generateConfiguration = true;
boolean generateTests = false;
Class complexBindingBaseClass;
Class simpleBindingBaseClass;
BindingConstructorArgument[] bindingConstructorArguments;
public void setBindingConstructorArguments(
BindingConstructorArgument[] bindingConstructorArguments ) {
this.bindingConstructorArguments = bindingConstructorArguments;
}
public void setGenerateXsd(
boolean generateXsd) {
this.generateXsd = generateXsd;
}
public void setGenerateAttributes(boolean generateAttributes) {
this.generateAttributes = generateAttributes;
}
public void setGenerateElements(boolean generateElements) {
this.generateElements = generateElements;
}
public void setGenerateTypes(boolean generateTypes) {
this.generateTypes = generateTypes;
}
public void setGenerateConfiguration(boolean generateConfiguration) {
this.generateConfiguration = generateConfiguration;
}
public void setGenerateTests(boolean generateTests) {
this.generateTests = generateTests;
}
public void setComplexBindingBaseClass(Class complexBindingBaseClass) {
this.complexBindingBaseClass = complexBindingBaseClass;
}
public void setSimpleBindingBaseClass(Class simpleBindingBaseClass) {
this.simpleBindingBaseClass = simpleBindingBaseClass;
}
public void generate(XSDSchema schema) {
List components = new ArrayList();
if (generateElements) {
List elements = schema.getElementDeclarations();
for (Iterator e = elements.iterator(); e.hasNext();) {
XSDElementDeclaration element = (XSDElementDeclaration) e.next();
generate(element, schema);
if (target(element, schema)) {
components.add(element);
}
}
}
if (generateTypes) {
List types = GeneratorUtils.allTypes( schema );
for (Iterator t = types.iterator(); t.hasNext();) {
XSDTypeDefinition type = (XSDTypeDefinition) t.next();
generate( type, schema );
if (target(type, schema)) {
components.add(type);
}
}
}
if (generateAttributes) {
List attributes = schema.getAttributeDeclarations();
for (Iterator a = attributes.iterator(); a.hasNext();) {
XSDAttributeDeclaration attribute = (XSDAttributeDeclaration) a
.next();
generate(attribute, schema);
if (target(attribute, schema)) {
components.add(attribute);
}
}
}
if (generateXsd) {
try {
String result = execute("XSDTemplate", schema);
write(result, prefix(schema).toUpperCase(), sourceLocation);
} catch (Exception e) {
String msg = "Error generating binding interface";
logger.log(Level.WARNING, msg, e);
}
}
if (generateConfiguration) {
try {
String result = execute("ConfigurationTemplate", new Object[]{schema,components} );
String prefix = Schemas.getTargetPrefix(schema).toUpperCase();
write(result, prefix + "Configuration",sourceLocation);
}
catch( Exception e ) {
logger.log( Level.SEVERE, "Error generating resolver", e );
}
//copy over all included schemas
ArrayList includes = new ArrayList();
File file = null;
try {
file = findSchemaFile( schema.getSchemaLocation() );
}
catch (IOException e) {
logger.log(Level.SEVERE, "", e );
}
if ( file != null ) {
includes.add( file );
}
else {
logger.log( Level.SEVERE, "Could not find: " + schema.getSchemaLocation() + " to copy." );
}
for (Iterator i = Schemas.getIncludes(schema).iterator(); i.hasNext();) {
XSDInclude include = (XSDInclude) i.next();
file = null;
try {
file = findSchemaFile( include.getSchemaLocation() );
}
catch (IOException e) {
logger.log(Level.SEVERE, "", e );
}
if ( file != null ) {
includes.add( file );
}
else {
logger.log( Level.SEVERE, "Could not find: " + include.getSchemaLocation() + " to copy." );
}
}
for (Iterator i = includes.iterator(); i.hasNext();) {
File include = (File) i.next();
try {
copy(include,resourceLocation);
}
catch (IOException e) {
logger.log( Level.WARNING, "Could not copy file " + include , e );
}
}
}
if (generateTests) {
try {
String result = execute("BindingTestSupportClass", new Object[]{schema} );
String prefix = Schemas.getTargetPrefix(schema).toUpperCase();
write(result, prefix + "TestSupport", testLocation);
}
catch( Exception e ) {
logger.log( Level.SEVERE, "Error generating test support class", e );
}
}
}
boolean target(XSDNamedComponent c, XSDSchema schema) {
return c.getTargetNamespace().equals(schema.getTargetNamespace());
}
void generate(XSDNamedComponent c, XSDSchema schema) {
if (!target(c, schema)) {
return;
}
if ( !included( c ) ) {
return;
}
Class bindingBaseClass = simpleBindingBaseClass;
if ( c instanceof XSDComplexTypeDefinition ) {
bindingBaseClass = complexBindingBaseClass;
}
logger.info( "Generating binding for " + c.getName() );
try {
String result = execute("CLASS",
new Object[] { c, bindingConstructorArguments, bindingBaseClass });
write(result, name(c), sourceLocation);
} catch (Exception ioe) {
String msg = "Unable to generate binding for " + c;
logger.log(Level.WARNING, msg, ioe);
}
if ( generateTests ) {
logger.info( "Generating binding test for " + c.getName() );
try {
String result = execute("BindingTestClass",
new Object[] { c } );
write(result, testName(c), testLocation);
} catch (Exception ioe) {
String msg = "Unable to generate binding test for " + c;
logger.log(Level.WARNING, msg, ioe);
}
}
}
String name(XSDNamedComponent c) {
return c.getName().substring(0, 1).toUpperCase()
+ c.getName().substring(1) + "Binding";
}
String testName(XSDNamedComponent c) {
return c.getName().substring(0, 1).toUpperCase()
+ c.getName().substring(1) + "BindingTest";
}
public static void main(String[] args) throws Exception {
XSDSchema schema = Schemas.parse("/home/jdeolive/devel/geotools/trunk/demo/xml-po/src/main/xsd/po.xsd");
System.out.println( schema.getQNamePrefixToNamespaceMap() );
// ArrayList cargList = new ArrayList();
// HashSet includedTypes = new HashSet();
// BindingGenerator g = new BindingGenerator();
//
// if (args.length == 0) {
// usage();
// System.exit(0);
// }
//
// for (int i = 0; i < args.length; i++) {
// String arg = args[i];
//
// if ("--help".equals(arg)) {
// usage();
// System.exit(0);
// }
//
// if ("--schema".equals(arg)) {
// schema = Schemas.parse(args[++i]);
// } else if ("--output".equals(arg)) {
// g.setLocation(args[++i]);
// } else if ("--package".equals(arg)) {
// g.setPackageBase(args[++i]);
// } else if ("--include-type".equals(arg)) {
// includedTypes.add(args[++i]);
// } else if ("--carg".equals(arg)) {
// try {
// cargList.add(Class.forName(args[++i]));
// } catch (ClassNotFoundException e) {
// String msg = "Could not load class: " + args[i];
// throw (IllegalArgumentException) new IllegalArgumentException(msg)
// .initCause(e);
// }
// } else if ("--noelements".equals(arg)) {
// g.setGenerateElements(false);
// } else if ("--noattributes".equals(arg)) {
// g.setGenerateAttributes(false);
// } else if ("--notypes".equals(arg)) {
// g.setGenerateTypes(false);
// } else if ("--no-binding-interface".equals(arg)) {
// g.setGeneratingBindingInterface( false );
// } else if ("--no-binding-configuration".equals(arg)) {
// g.setGeneratingBindingConfiguration( false );
// }
//
// }
//
// Class[] cargs = null;
//
// if (!cargList.isEmpty()) {
// cargs = (Class[]) cargList.toArray(new Class[cargList.size()]);
// }
//
// if (schema == null) {
// String msg = "ERROR: schema not specified";
// usage();
//
// throw new IllegalArgumentException(msg);
// }
//
// if (g.getLocation() == null) {
// g.setLocation(System.getProperty("user.dir"));
// }
//
// g.setIncludedTypes(includedTypes);
// //g.setBindingConstructorArguments(cargs);
// g.generate(schema);
}
public static void usage() {
System.out.println("Options");
System.out.println("\t\t--help: Print this message");
System.out.println("\t\t--schema <path>: Path to schema file");
System.out.println("\t\t--output <path>: Path to output directory");
System.out.println("\t\t--package <package>: Package out writen files");
System.out.println("\t\t--include-type <type>: Include a single type" );
System.out.println(
"\t\t--carg <class>: Qualified class name of binding constructor argument");
System.out.println(
"\t\t--noelements: Turn off element binding generation");
System.out.println(
"\t\t--noattributes: Turn off attribute binding generation");
System.out.println("\t\t--notypes: Turn off type binding generation");
System.out.println("\t\t--no-binding-interface: Turn off binding interface generation");
System.out.println("\t\t--no-binding-configuration: Turn off binding configuration generation");
}
}