/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* Copy of SchemaTypeSystemCompiler.
* The only purpose of this is to compile a schema AND javaize everyType in order
* to get the exact generated Java Names for every xml Type as if the java files were
* really generated with xmlbeans compiler.
*
* BRUTAL: we could maybe just have re-written our own "java namer module"
*/
package org.apache.xmlbeans.impl.schema;
import java.io.File;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.xmlbeans.BindingConfig;
import org.apache.xmlbeans.Filer;
import org.apache.xmlbeans.SchemaTypeLoader;
import org.apache.xmlbeans.SchemaTypeSystem;
import org.apache.xmlbeans.XmlBeans;
import org.apache.xmlbeans.XmlErrorCodes;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.apache.xmlbeans.impl.common.XmlErrorWatcher;
import org.apache.xmlbeans.impl.xb.xsdschema.SchemaDocument;
import org.apache.xmlbeans.impl.xb.xsdschema.SchemaDocument.Schema;
public class MySchemaTypeSystemCompiler {
public static SchemaTypeSystem compile2(String name, SchemaTypeSystem existingSTS, XmlObject[] schemas, BindingConfig config,
SchemaTypeLoader linkTo, Filer filer, XmlOptions options) {
try {
SchemaTypeSystem sys = XmlBeans.compileXmlBeans(name, existingSTS, schemas, config, linkTo, filer, options);
return sys;
} catch (XmlException e) {
e.printStackTrace();
return null;
}
}
/*
SchemaTypeSystem sts = XmlBeans.compileXsd(new XmlObject[]
{ XmlObject.Factory.parse(myXSDFile) },
XmlBeans.getBuiltinTypeSystem(),
null);
SchemaTypeLoader stl = XmlBeans.typeLoaderUnion(new SchemaTypeLoader[]
{ sts, XmlBeans.getBuiltinTypeSystem() });
XmlObject mydoc = stl.parse(instanceFile, null, null);
System.out.println("Document valid: " + mydoc.validate());
*/
/**
* Please do not invoke this method directly as the signature could change unexpectedly. Use one of
* {@link XmlBeans#loadXsd(XmlObject[])}, {@link XmlBeans#compileXsd(XmlObject[], SchemaTypeLoader, XmlOptions)}, or
* {@link XmlBeans#compileXmlBeans(String, SchemaTypeSystem, XmlObject[], BindingConfig, SchemaTypeLoader, Filer, XmlOptions)}
*/
public static SchemaTypeSystemImpl compile(String name, SchemaTypeSystem existingSTS, XmlObject[] input, BindingConfig config,
SchemaTypeLoader linkTo, Filer filer, XmlOptions options) throws XmlException {
options = XmlOptions.maskNull(options);
ArrayList schemas = new ArrayList();
if (input != null) {
for (int i = 0; i < input.length; i++) {
if (input[i] instanceof Schema) {
schemas.add(input[i]);
} else if (input[i] instanceof SchemaDocument && ((SchemaDocument) input[i]).getSchema() != null) {
schemas.add(((SchemaDocument) input[i]).getSchema());
} else {
throw new XmlException("Thread " + Thread.currentThread().getName() + ": The " + i
+ "th supplied input is not a schema document: its type is " + input[i].schemaType());
}
}
}
Collection userErrors = (Collection) options.get(XmlOptions.ERROR_LISTENER);
XmlErrorWatcher errorWatcher = new XmlErrorWatcher(userErrors);
/**
* MODIF FROM ORIGINAL: javaize set to TRUE SchemaTypeSystemImpl stsi = compileImpl(existingSTS, name, (Schema[])schemas.toArray(new
* Schema[schemas.size()]), config, linkTo, options, errorWatcher, filer!=null, null, null, null);
*/
SchemaTypeSystemImpl stsi = compileImpl(existingSTS, name, (Schema[]) schemas.toArray(new Schema[schemas.size()]), config, linkTo,
options, errorWatcher, true, null, null, null);
// if there is an error and compile didn't recover (stsi==null), throw exception
if (errorWatcher.hasError() && stsi == null) {
throw new XmlException(errorWatcher.firstError());
}
/**
* MODIF FROM ORIGINAL: DO NOT WRITE FILES if (stsi != null && !stsi.isIncomplete() && filer != null) { stsi.save(filer);
* generateTypes(stsi, filer, options); }
*/
return stsi;
}
//
// Compiles a SchemaTypeSystem
//
public static SchemaTypeSystemImpl compileImpl(SchemaTypeSystem system, String name, Schema[] schemas, BindingConfig config,
SchemaTypeLoader linkTo, XmlOptions options, Collection outsideErrors, boolean javaize, URI baseURI, Map sourcesToCopyMap,
File schemasDir) {
if (linkTo == null) {
throw new IllegalArgumentException("Must supply linkTo");
}
XmlErrorWatcher errorWatcher = new XmlErrorWatcher(outsideErrors);
boolean incremental = system != null;
// construct the state
StscState state = StscState.start();
boolean validate = options == null || !options.hasOption(XmlOptions.COMPILE_NO_VALIDATION);
try {
state.setErrorListener(errorWatcher);
state.setBindingConfig(config);
state.setOptions(options);
state.setGivenTypeSystemName(name);
state.setSchemasDir(schemasDir);
if (baseURI != null) {
state.setBaseUri(baseURI);
}
// construct the classpath (you always get the builtin types)
linkTo = SchemaTypeLoaderImpl.build(new SchemaTypeLoader[] { BuiltinSchemaTypeSystem.get(), linkTo }, null, null);
state.setImportingTypeLoader(linkTo);
List validSchemas = new ArrayList(schemas.length);
// load all the xsd files into it
if (validate) {
XmlOptions validateOptions = new XmlOptions().setErrorListener(errorWatcher);
if (options.hasOption(XmlOptions.VALIDATE_TREAT_LAX_AS_SKIP)) {
validateOptions.setValidateTreatLaxAsSkip();
}
for (int i = 0; i < schemas.length; i++) {
if (schemas[i].validate(validateOptions)) {
validSchemas.add(schemas[i]);
}
}
} else {
validSchemas.addAll(Arrays.asList(schemas));
}
Schema[] startWith = (Schema[]) validSchemas.toArray(new Schema[validSchemas.size()]);
if (incremental) {
Set namespaces = new HashSet();
startWith = getSchemasToRecompile((SchemaTypeSystemImpl) system, startWith, namespaces);
state.initFromTypeSystem((SchemaTypeSystemImpl) system, namespaces);
} else {
state.setDependencies(new SchemaDependencies());
}
// deal with imports and includes
StscImporter.SchemaToProcess[] schemasAndChameleons = StscImporter.resolveImportsAndIncludes(startWith);
// call the translator so that it may also perform magic
StscTranslator.addAllDefinitions(schemasAndChameleons);
// call the resolver to do its magic
StscResolver.resolveAll();
// call the checker to check both restrictions and defaults
StscChecker.checkAll();
// call the javaizer to do its magic
StscJavaizer.javaizeAllTypes(javaize);
// construct the loader out of the state
StscState.get().sts().loadFromStscState(state);
// fill in the source-copy map
if (sourcesToCopyMap != null) {
sourcesToCopyMap.putAll(state.sourceCopyMap());
}
if (errorWatcher.hasError()) {
// EXPERIMENTAL: recovery from compilation errors and partial type system
if (state.allowPartial() && state.getRecovered() == errorWatcher.size()) {
// if partial type system allowed and all errors were recovered
StscState.get().sts().setIncomplete(true);
} else {
// if any non-recoverable errors, return null
return null;
}
}
if (system != null) {
((SchemaTypeSystemImpl) system).setIncomplete(true);
}
return StscState.get().sts();
} finally {
StscState.end();
}
}
/**
* Get the list of Schemas to be recompiled, based on the list of Schemas that were modified. We make use of the depencency information
* that we stored in the typesystem and of the entity resolvers that have been set up
*/
private static Schema[] getSchemasToRecompile(SchemaTypeSystemImpl system, Schema[] modified, Set namespaces) {
Set modifiedFiles = new HashSet();
Map haveFile = new HashMap();
List result = new ArrayList();
for (int i = 0; i < modified.length; i++) {
String fileURL = modified[i].documentProperties().getSourceName();
if (fileURL == null) {
throw new IllegalArgumentException("One of the Schema files passed in"
+ " doesn't have the source set, which prevents it to be incrementally" + " compiled");
}
modifiedFiles.add(fileURL);
haveFile.put(fileURL, modified[i]);
result.add(modified[i]);
}
SchemaDependencies dep = system.getDependencies();
List nss = dep.getNamespacesTouched(modifiedFiles);
namespaces.addAll(dep.computeTransitiveClosure(nss));
List needRecompilation = dep.getFilesTouched(namespaces);
StscState.get().setDependencies(new SchemaDependencies(dep, namespaces));
for (int i = 0; i < needRecompilation.size(); i++) {
String url = (String) needRecompilation.get(i);
Schema have = (Schema) haveFile.get(url);
if (have == null) {
// We have to load the file from the entity resolver
try {
XmlObject xdoc = StscImporter.DownloadTable.downloadDocument(StscState.get().getS4SLoader(), null, url);
XmlOptions voptions = new XmlOptions();
voptions.setErrorListener(StscState.get().getErrorListener());
if (!(xdoc instanceof SchemaDocument) || !xdoc.validate(voptions)) {
StscState.get().error("Referenced document is not a valid schema, URL = " + url,
XmlErrorCodes.CANNOT_FIND_RESOURCE, null);
continue;
}
SchemaDocument sDoc = (SchemaDocument) xdoc;
result.add(sDoc.getSchema());
} catch (java.net.MalformedURLException mfe) {
StscState.get().error(XmlErrorCodes.EXCEPTION_LOADING_URL,
new Object[] { "MalformedURLException", url, mfe.getMessage() }, null);
continue;
} catch (java.io.IOException ioe) {
StscState.get().error(XmlErrorCodes.EXCEPTION_LOADING_URL, new Object[] { "IOException", url, ioe.getMessage() }, null);
continue;
} catch (XmlException xmle) {
StscState.get().error(XmlErrorCodes.EXCEPTION_LOADING_URL, new Object[] { "XmlException", url, xmle.getMessage() },
null);
continue;
}
}
}
return (Schema[]) result.toArray(new Schema[result.size()]);
}
}