feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.sun.tools.internal.xjc.util.SubtreeCutter;
|
||||
import com.sun.tools.internal.xjc.Options;
|
||||
import com.sun.tools.internal.xjc.Plugin;
|
||||
import com.sun.xml.internal.bind.v2.util.EditDistance;
|
||||
|
||||
import org.xml.sax.helpers.NamespaceSupport;
|
||||
import org.xml.sax.Locator;
|
||||
import org.xml.sax.ErrorHandler;
|
||||
import org.xml.sax.SAXParseException;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.WellKnownNamespace;
|
||||
|
||||
/**
|
||||
* Common code between {@code DTDExtensionBindingChecker} and {@link ExtensionBindingChecker}.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public abstract class AbstractExtensionBindingChecker extends SubtreeCutter {
|
||||
/** Remembers in-scope namespace bindings. */
|
||||
protected final NamespaceSupport nsSupport = new NamespaceSupport();
|
||||
|
||||
/**
|
||||
* Set of namespace URIs that designates enabled extensions.
|
||||
*/
|
||||
protected final Set<String> enabledExtensions = new HashSet<String>();
|
||||
|
||||
private final Set<String> recognizableExtensions = new HashSet<String>();
|
||||
|
||||
private Locator locator;
|
||||
|
||||
/**
|
||||
* Namespace URI of the target schema language. Elements in this
|
||||
* namespace are always allowed.
|
||||
*/
|
||||
protected final String schemaLanguage;
|
||||
|
||||
/**
|
||||
* If false, any use of extensions is reported as an error.
|
||||
*/
|
||||
protected final boolean allowExtensions;
|
||||
|
||||
private final Options options;
|
||||
|
||||
/**
|
||||
* @param handler
|
||||
* This error handler will receive detected errors.
|
||||
*/
|
||||
public AbstractExtensionBindingChecker( String schemaLanguage, Options options, ErrorHandler handler ) {
|
||||
this.schemaLanguage = schemaLanguage;
|
||||
this.allowExtensions = options.compatibilityMode!=Options.STRICT;
|
||||
this.options = options;
|
||||
setErrorHandler(handler);
|
||||
|
||||
for (Plugin plugin : options.getAllPlugins())
|
||||
recognizableExtensions.addAll(plugin.getCustomizationURIs());
|
||||
recognizableExtensions.add(Const.XJC_EXTENSION_URI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the given URI is indeed a valid extension namespace URI,
|
||||
* and if so enable it.
|
||||
* <p>
|
||||
* This method does all the error handling.
|
||||
*/
|
||||
protected final void checkAndEnable(String uri) throws SAXException {
|
||||
if( !isRecognizableExtension(uri) ) {
|
||||
String nearest = EditDistance.findNearest(uri, recognizableExtensions);
|
||||
// not the namespace URI we know of
|
||||
error( Messages.ERR_UNSUPPORTED_EXTENSION.format(uri,nearest) );
|
||||
} else
|
||||
if( !isSupportedExtension(uri) ) {
|
||||
// recognizable but not not supported, meaning
|
||||
// the plug-in isn't enabled
|
||||
|
||||
// look for plug-in that handles this URI
|
||||
Plugin owner = null;
|
||||
for( Plugin p : options.getAllPlugins() ) {
|
||||
if(p.getCustomizationURIs().contains(uri)) {
|
||||
owner = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(owner!=null)
|
||||
// we know the plug-in that supports this namespace, but it's not enabled
|
||||
error( Messages.ERR_PLUGIN_NOT_ENABLED.format(owner.getOptionName(),uri));
|
||||
else {
|
||||
// this shouldn't happen, but be defensive...
|
||||
error( Messages.ERR_UNSUPPORTED_EXTENSION.format(uri) );
|
||||
}
|
||||
}
|
||||
|
||||
// as an error recovery enable this namespace URI anyway.
|
||||
enabledExtensions.add(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the tag name belongs to a plugin namespace-wise, check its local name
|
||||
* to make sure it's correct.
|
||||
*/
|
||||
protected final void verifyTagName(String namespaceURI, String localName, String qName) throws SAXException {
|
||||
if(options.pluginURIs.contains(namespaceURI)) {
|
||||
// make sure that this is a valid tag name
|
||||
boolean correct = false;
|
||||
for( Plugin p : options.activePlugins ) {
|
||||
if(p.isCustomizationTagName(namespaceURI,localName)) {
|
||||
correct = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!correct) {
|
||||
error( Messages.ERR_ILLEGAL_CUSTOMIZATION_TAGNAME.format(qName) );
|
||||
startCutting();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given namespace URI is supported as the extension
|
||||
* bindings.
|
||||
*/
|
||||
protected final boolean isSupportedExtension( String namespaceUri ) {
|
||||
return namespaceUri.equals(Const.XJC_EXTENSION_URI) || options.pluginURIs.contains(namespaceUri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given namespace URI can be potentially recognized
|
||||
* by this XJC.
|
||||
*/
|
||||
protected final boolean isRecognizableExtension( String namespaceUri ) {
|
||||
return recognizableExtensions.contains(namespaceUri);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDocumentLocator(Locator locator) {
|
||||
super.setDocumentLocator(locator);
|
||||
this.locator = locator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startDocument() throws SAXException {
|
||||
super.startDocument();
|
||||
|
||||
nsSupport.reset();
|
||||
enabledExtensions.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startPrefixMapping(String prefix, String uri) throws SAXException {
|
||||
if (WellKnownNamespace.XML_NAMESPACE_URI.equals(uri)) return;
|
||||
super.startPrefixMapping(prefix, uri); //xml prefix shall not be declared based on jdk api javado
|
||||
nsSupport.pushContext();
|
||||
nsSupport.declarePrefix(prefix,uri);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endPrefixMapping(String prefix) throws SAXException {
|
||||
if ("xml".equals(prefix)) return; //xml prefix shall not be declared based on jdk api javadoc
|
||||
super.endPrefixMapping(prefix);
|
||||
nsSupport.popContext();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reports an error and returns the created SAXParseException
|
||||
*/
|
||||
protected final SAXParseException error( String msg ) throws SAXException {
|
||||
SAXParseException spe = new SAXParseException( msg, locator );
|
||||
getErrorHandler().error(spe);
|
||||
return spe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports a warning.
|
||||
*/
|
||||
protected final void warning( String msg ) throws SAXException {
|
||||
SAXParseException spe = new SAXParseException( msg, locator );
|
||||
getErrorHandler().warning(spe);
|
||||
}
|
||||
}
|
||||
65
jdkSrc/jdk8/com/sun/tools/internal/xjc/reader/Const.java
Normal file
65
jdkSrc/jdk8/com/sun/tools/internal/xjc/reader/Const.java
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.WellKnownNamespace;
|
||||
|
||||
|
||||
/**
|
||||
* Useful constant values.
|
||||
*
|
||||
* @author
|
||||
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
public class Const {
|
||||
|
||||
/** XML namespace URI. */
|
||||
public final static String XMLNS_URI =
|
||||
"http://www.w3.org/2000/xmlns/";
|
||||
|
||||
/** JAXB customization URI. */
|
||||
public final static String JAXB_NSURI =
|
||||
"http://java.sun.com/xml/ns/jaxb";
|
||||
|
||||
/** XJC vendor extension namespace URI. */
|
||||
public final static String XJC_EXTENSION_URI =
|
||||
"http://java.sun.com/xml/ns/jaxb/xjc";
|
||||
|
||||
/** RELAX NG namespace URI. */
|
||||
public static final String RELAXNG_URI =
|
||||
"http://relaxng.org/ns/structure/1.0";
|
||||
|
||||
/** URI to represent DTD. */
|
||||
public static final String DTD = "DTD";
|
||||
|
||||
/**
|
||||
* Attribute name of the expected media type.
|
||||
*
|
||||
* @see WellKnownNamespace#XML_MIME_URI
|
||||
* @see http://www.w3.org/TR/xml-media-types/
|
||||
*/
|
||||
public static final String EXPECTED_CONTENT_TYPES = "expectedContentTypes";
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader;
|
||||
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import com.sun.tools.internal.xjc.Options;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.ErrorHandler;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* This filter checks jaxb:extensionBindingPrefix and
|
||||
* pass/filter extension bindings.
|
||||
*
|
||||
* <p>
|
||||
* This filter also remembers enabled extension namespaces
|
||||
* and filters out any extension namespaces that doesn't belong
|
||||
* to those. The net effect is that disabled customizations
|
||||
* will never pass through this filter.
|
||||
*
|
||||
* <p>
|
||||
* Note that we can't just filter out all foreign namespaces,
|
||||
* as we need to use user-defined tags in documentations to generate javadoc.
|
||||
*
|
||||
* <p>
|
||||
* The class needs to know the list of extension binding namespaces
|
||||
* that the RI recognizes.
|
||||
* To add new URI, modify the isSupportedExtension method.
|
||||
*
|
||||
* @author
|
||||
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
public final class ExtensionBindingChecker extends AbstractExtensionBindingChecker {
|
||||
|
||||
/**
|
||||
* Number of the elements encountered. Used to detect the root element.
|
||||
*/
|
||||
private int count=0;
|
||||
|
||||
public ExtensionBindingChecker(String schemaLanguage, Options options, ErrorHandler handler) {
|
||||
super(schemaLanguage, options, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the elements with the given namespace URI
|
||||
* should be blocked by this filter.
|
||||
*/
|
||||
private boolean needsToBePruned( String uri ) {
|
||||
if( uri.equals(schemaLanguage) )
|
||||
return false;
|
||||
if( uri.equals(Const.JAXB_NSURI) )
|
||||
return false;
|
||||
if( enabledExtensions.contains(uri) )
|
||||
return false;
|
||||
|
||||
// we don't need to prune something unless
|
||||
// the rest of the processor recognizes it as something special.
|
||||
// this allows us to send the documentation and other harmless
|
||||
// foreign XML fragments, which may be picked up as documents.
|
||||
return isRecognizableExtension(uri);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void startDocument() throws SAXException {
|
||||
super.startDocument();
|
||||
count=0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement(String namespaceURI, String localName, String qName, Attributes atts)
|
||||
throws SAXException {
|
||||
|
||||
if(!isCutting()) {
|
||||
String v = atts.getValue(Const.JAXB_NSURI,"extensionBindingPrefixes");
|
||||
if(v!=null) {
|
||||
if(count!=0)
|
||||
// the binding attribute is allowed only at the root level.
|
||||
error( Messages.ERR_UNEXPECTED_EXTENSION_BINDING_PREFIXES.format() );
|
||||
|
||||
if(!allowExtensions)
|
||||
error( Messages.ERR_VENDOR_EXTENSION_DISALLOWED_IN_STRICT_MODE.format() );
|
||||
|
||||
// then remember the associated namespace URIs.
|
||||
StringTokenizer tokens = new StringTokenizer(v);
|
||||
while(tokens.hasMoreTokens()) {
|
||||
String prefix = tokens.nextToken();
|
||||
String uri = nsSupport.getURI(prefix);
|
||||
if( uri==null )
|
||||
// undeclared prefix
|
||||
error( Messages.ERR_UNDECLARED_PREFIX.format(prefix) );
|
||||
else
|
||||
checkAndEnable(uri);
|
||||
}
|
||||
}
|
||||
|
||||
if( needsToBePruned(namespaceURI) ) {
|
||||
// start pruning the tree. Call the super class method directly.
|
||||
if( isRecognizableExtension(namespaceURI) ) {
|
||||
// but this is a supported customization.
|
||||
// isn't the user forgetting @jaxb:extensionBindingPrefixes?
|
||||
warning( Messages.ERR_SUPPORTED_EXTENSION_IGNORED.format(namespaceURI) );
|
||||
}
|
||||
startCutting();
|
||||
} else
|
||||
verifyTagName(namespaceURI, localName, qName);
|
||||
}
|
||||
|
||||
count++;
|
||||
super.startElement(namespaceURI, localName, qName, atts);
|
||||
}
|
||||
}
|
||||
59
jdkSrc/jdk8/com/sun/tools/internal/xjc/reader/Messages.java
Normal file
59
jdkSrc/jdk8/com/sun/tools/internal/xjc/reader/Messages.java
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
/**
|
||||
* Formats error messages.
|
||||
*/
|
||||
public enum Messages {
|
||||
DUPLICATE_PROPERTY, // 1 arg
|
||||
DUPLICATE_ELEMENT, // 1 arg
|
||||
|
||||
ERR_UNDECLARED_PREFIX,
|
||||
ERR_UNEXPECTED_EXTENSION_BINDING_PREFIXES,
|
||||
ERR_UNSUPPORTED_EXTENSION,
|
||||
ERR_SUPPORTED_EXTENSION_IGNORED,
|
||||
ERR_RELEVANT_LOCATION,
|
||||
ERR_CLASS_NOT_FOUND,
|
||||
PROPERTY_CLASS_IS_RESERVED,
|
||||
ERR_VENDOR_EXTENSION_DISALLOWED_IN_STRICT_MODE,
|
||||
ERR_ILLEGAL_CUSTOMIZATION_TAGNAME, // 1 arg
|
||||
ERR_PLUGIN_NOT_ENABLED, // 2 args
|
||||
;
|
||||
|
||||
private static final ResourceBundle rb = ResourceBundle.getBundle(Messages.class.getPackage().getName() +".MessageBundle");
|
||||
|
||||
public String toString() {
|
||||
return format();
|
||||
}
|
||||
|
||||
public String format( Object... args ) {
|
||||
return MessageFormat.format( rb.getString(name()), args );
|
||||
}
|
||||
}
|
||||
101
jdkSrc/jdk8/com/sun/tools/internal/xjc/reader/ModelChecker.java
Normal file
101
jdkSrc/jdk8/com/sun/tools/internal/xjc/reader/ModelChecker.java
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import com.sun.tools.internal.xjc.ErrorReceiver;
|
||||
import com.sun.tools.internal.xjc.model.CClassInfo;
|
||||
import com.sun.tools.internal.xjc.model.CPropertyInfo;
|
||||
import com.sun.tools.internal.xjc.model.Model;
|
||||
|
||||
/**
|
||||
* Checks errors on model classes.
|
||||
*
|
||||
* <p>
|
||||
* This should be used as a {@link Ring} component.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class ModelChecker {
|
||||
private final Model model = Ring.get(Model.class);
|
||||
private final ErrorReceiver errorReceiver = Ring.get(ErrorReceiver.class);
|
||||
|
||||
public ModelChecker() {
|
||||
}
|
||||
|
||||
public void check() {
|
||||
for( CClassInfo ci : model.beans().values() )
|
||||
check(ci);
|
||||
}
|
||||
|
||||
private void check( CClassInfo ci ) {
|
||||
List<CPropertyInfo> props = ci.getProperties();
|
||||
Map<QName,CPropertyInfo> collisionTable = new HashMap<QName,CPropertyInfo>();
|
||||
|
||||
OUTER:
|
||||
for( int i=0; i<props.size(); i++ ) {
|
||||
CPropertyInfo p1 = props.get(i);
|
||||
|
||||
if(p1.getName(true).equals("Class")) {
|
||||
errorReceiver.error(p1.locator,Messages.PROPERTY_CLASS_IS_RESERVED.format());
|
||||
continue;
|
||||
}
|
||||
|
||||
QName n = p1.collectElementNames(collisionTable);
|
||||
if(n!=null) {
|
||||
CPropertyInfo p2 = collisionTable.get(n);
|
||||
|
||||
if (p2.getName(true).equals(n.toString()) || p2.getName(false).equals(n.toString())) {
|
||||
errorReceiver.error(p1.locator, Messages.DUPLICATE_ELEMENT.format(n));
|
||||
errorReceiver.error(p2.locator, Messages.ERR_RELEVANT_LOCATION.format());
|
||||
}
|
||||
}
|
||||
|
||||
for( int j=i+1; j<props.size(); j++ ) {
|
||||
if(checkPropertyCollision(p1,props.get(j)))
|
||||
continue OUTER;
|
||||
}
|
||||
for( CClassInfo c=ci.getBaseClass(); c!=null; c=c.getBaseClass() ) {
|
||||
for( CPropertyInfo p2 : c.getProperties() )
|
||||
if(checkPropertyCollision(p1,p2))
|
||||
continue OUTER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkPropertyCollision(CPropertyInfo p1, CPropertyInfo p2) {
|
||||
if(!p1.getName(true).equals(p2.getName(true)))
|
||||
return false;
|
||||
errorReceiver.error(p1.locator,Messages.DUPLICATE_PROPERTY.format(p1.getName(true)));
|
||||
errorReceiver.error(p2.locator,Messages.ERR_RELEVANT_LOCATION.format());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
227
jdkSrc/jdk8/com/sun/tools/internal/xjc/reader/RawTypeSet.java
Normal file
227
jdkSrc/jdk8/com/sun/tools/internal/xjc/reader/RawTypeSet.java
Normal file
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.activation.MimeType;
|
||||
|
||||
import com.sun.tools.internal.xjc.model.CElementPropertyInfo;
|
||||
import static com.sun.tools.internal.xjc.model.CElementPropertyInfo.CollectionMode.*;
|
||||
import com.sun.tools.internal.xjc.model.CReferencePropertyInfo;
|
||||
import com.sun.tools.internal.xjc.model.CTypeRef;
|
||||
import com.sun.tools.internal.xjc.model.Multiplicity;
|
||||
import com.sun.tools.internal.xjc.model.nav.NType;
|
||||
import com.sun.xml.internal.bind.v2.model.core.Element;
|
||||
import com.sun.xml.internal.bind.v2.model.core.ID;
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* Set of {@link Ref}.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class RawTypeSet {
|
||||
|
||||
|
||||
public final Set<Ref> refs;
|
||||
|
||||
/**
|
||||
* True if this type set can form references to types.
|
||||
*/
|
||||
public final Mode canBeTypeRefs;
|
||||
|
||||
/**
|
||||
* The occurence of the whole references.
|
||||
*/
|
||||
public final Multiplicity mul;
|
||||
|
||||
// computed inside canBeTypeRefs()
|
||||
private CElementPropertyInfo.CollectionMode collectionMode;
|
||||
|
||||
/**
|
||||
* Should be called from one of the raw type set builders.
|
||||
*/
|
||||
public RawTypeSet( Set<Ref> refs, Multiplicity m ) {
|
||||
this.refs = refs;
|
||||
mul = m;
|
||||
canBeTypeRefs = canBeTypeRefs();
|
||||
}
|
||||
|
||||
public CElementPropertyInfo.CollectionMode getCollectionMode() {
|
||||
return collectionMode;
|
||||
}
|
||||
|
||||
public boolean isRequired() {
|
||||
return mul.min.compareTo(BigInteger.ZERO) == 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Represents the possible binding option for this {@link RawTypeSet}.
|
||||
*/
|
||||
public enum Mode {
|
||||
/**
|
||||
* This {@link RawTypeSet} can be either an reference property or
|
||||
* an element property, and XJC recommends element property.
|
||||
*/
|
||||
SHOULD_BE_TYPEREF(0),
|
||||
/**
|
||||
* This {@link RawTypeSet} can be either an reference property or
|
||||
* an element property, and XJC recommends reference property.
|
||||
*/
|
||||
CAN_BE_TYPEREF(1),
|
||||
/**
|
||||
* This {@link RawTypeSet} can be only bound to a reference property.
|
||||
*/
|
||||
MUST_BE_REFERENCE(2);
|
||||
|
||||
private final int rank;
|
||||
|
||||
Mode(int rank) {
|
||||
this.rank = rank;
|
||||
}
|
||||
|
||||
Mode or(Mode that) {
|
||||
switch(Math.max(this.rank,that.rank)) {
|
||||
case 0: return SHOULD_BE_TYPEREF;
|
||||
case 1: return CAN_BE_TYPEREF;
|
||||
case 2: return MUST_BE_REFERENCE;
|
||||
}
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if {@link #refs} can form refs of types.
|
||||
*
|
||||
* If there are multiple {@link Ref}s with the same type,
|
||||
* we cannot make them into type refs. Or if any of the {@link Ref}
|
||||
* says they cannot be in type refs, we cannot do that either.
|
||||
*
|
||||
* TODO: just checking if the refs are the same is not suffice.
|
||||
* If two refs derive from each other, they cannot form a list of refs
|
||||
* (because of a possible ambiguity).
|
||||
*/
|
||||
private Mode canBeTypeRefs() {
|
||||
Set<NType> types = new HashSet<NType>();
|
||||
|
||||
collectionMode = mul.isAtMostOnce()?NOT_REPEATED:REPEATED_ELEMENT;
|
||||
|
||||
// the way we compute this is that we start from the most optimistic value,
|
||||
// and then gradually degrade as we find something problematic.
|
||||
Mode mode = Mode.SHOULD_BE_TYPEREF;
|
||||
|
||||
for( Ref r : refs ) {
|
||||
mode = mode.or(r.canBeType(this));
|
||||
if(mode== Mode.MUST_BE_REFERENCE)
|
||||
return mode; // no need to continue the processing
|
||||
|
||||
if(!types.add(r.toTypeRef(null).getTarget().getType()))
|
||||
return Mode.MUST_BE_REFERENCE; // collision
|
||||
if(r.isListOfValues()) {
|
||||
if(refs.size()>1 || !mul.isAtMostOnce())
|
||||
return Mode.MUST_BE_REFERENCE; // restriction on @XmlList
|
||||
collectionMode = REPEATED_VALUE;
|
||||
}
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void addTo(CElementPropertyInfo prop) {
|
||||
assert canBeTypeRefs!= Mode.MUST_BE_REFERENCE;
|
||||
if(mul.isZero())
|
||||
return; // the property can't have any value
|
||||
|
||||
List<CTypeRef> dst = prop.getTypes();
|
||||
for( Ref t : refs )
|
||||
dst.add(t.toTypeRef(prop));
|
||||
}
|
||||
|
||||
public void addTo(CReferencePropertyInfo prop) {
|
||||
if(mul.isZero())
|
||||
return; // the property can't have any value
|
||||
for( Ref t : refs )
|
||||
t.toElementRef(prop);
|
||||
}
|
||||
|
||||
public ID id() {
|
||||
for( Ref t : refs ) {
|
||||
ID id = t.id();
|
||||
if(id!=ID.NONE) return id;
|
||||
}
|
||||
return ID.NONE;
|
||||
}
|
||||
|
||||
public MimeType getExpectedMimeType() {
|
||||
for( Ref t : refs ) {
|
||||
MimeType mt = t.getExpectedMimeType();
|
||||
if(mt!=null) return mt;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A reference to something.
|
||||
*
|
||||
* <p>
|
||||
* A {@link Ref} can be either turned into {@link CTypeRef} to form
|
||||
* an element property, or {@link Element} to form a reference property.
|
||||
*/
|
||||
public static abstract class Ref {
|
||||
/**
|
||||
* @param ep
|
||||
* the property to which the returned {@link CTypeRef} will be
|
||||
* added to.
|
||||
*/
|
||||
protected abstract CTypeRef toTypeRef(CElementPropertyInfo ep);
|
||||
protected abstract void toElementRef(CReferencePropertyInfo prop);
|
||||
/**
|
||||
* Can this {@link Ref} be a type ref?
|
||||
* @return false to veto.
|
||||
* @param parent
|
||||
*/
|
||||
protected abstract Mode canBeType(RawTypeSet parent);
|
||||
protected abstract boolean isListOfValues();
|
||||
/**
|
||||
* When this {@link RawTypeSet} binds to a {@link CElementPropertyInfo},
|
||||
* this method is used to determine if the property is ID or not.
|
||||
*/
|
||||
protected abstract ID id();
|
||||
|
||||
/**
|
||||
* When this {@link RawTypeSet} binds to a {@link CElementPropertyInfo},
|
||||
* this method is used to determine if the property has an associated expected MIME type or not.
|
||||
*/
|
||||
protected MimeType getExpectedMimeType() { return null; }
|
||||
}
|
||||
}
|
||||
134
jdkSrc/jdk8/com/sun/tools/internal/xjc/reader/Ring.java
Normal file
134
jdkSrc/jdk8/com/sun/tools/internal/xjc/reader/Ring.java
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.sun.tools.internal.xjc.ErrorReceiver;
|
||||
import com.sun.tools.internal.xjc.model.Model;
|
||||
|
||||
/**
|
||||
* Holds all the binding related singleton components in a "ring",
|
||||
* and let you access those components, creating them as necessary.
|
||||
*
|
||||
* <p>
|
||||
* A {@link Ring} is local to a thread,
|
||||
* and only one instanceof {@link Ring} can be active at any given time.
|
||||
*
|
||||
* Use {@link #begin()} and {@link #end(Ring)} to start/end a ring scope.
|
||||
* Inside a scope, use {@link #get()} to obtain the instance.
|
||||
*
|
||||
* <p>
|
||||
* When a {@link Model} is built by the reader, an active {@link Ring} scope
|
||||
* is assumed.
|
||||
*
|
||||
*
|
||||
* <h2>Components in Ring</h2>
|
||||
* <p>
|
||||
* Depending on the schema language we are dealing with, different
|
||||
* components are in the model. But at least the following components
|
||||
* are in the ring.
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link ErrorReceiver}
|
||||
* </ul>
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class Ring {
|
||||
|
||||
private final Map<Class,Object> components = new HashMap<Class,Object>();
|
||||
|
||||
private static final ThreadLocal<Ring> instances = new ThreadLocal<Ring>();
|
||||
|
||||
private Ring() {}
|
||||
|
||||
public static <T> void add( Class<T> clazz, T instance ) {
|
||||
assert !get().components.containsKey(clazz);
|
||||
get().components.put(clazz,instance);
|
||||
}
|
||||
|
||||
public static <T> void add( T o ) {
|
||||
add((Class<T>)o.getClass(),o);
|
||||
}
|
||||
|
||||
public static <T> T get( Class<T> key ) {
|
||||
T t = (T)get().components.get(key);
|
||||
if(t==null) {
|
||||
try {
|
||||
Constructor<T> c = key.getDeclaredConstructor();
|
||||
c.setAccessible(true);
|
||||
t = c.newInstance();
|
||||
if(!get().components.containsKey(key))
|
||||
// many components register themselves.
|
||||
add(key,t);
|
||||
} catch (InstantiationException e) {
|
||||
throw new Error(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new Error(e);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new Error(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
assert t!=null;
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link Ring} instance is associated with a thread.
|
||||
*/
|
||||
public static Ring get() {
|
||||
return instances.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a new scope.
|
||||
*/
|
||||
public static Ring begin() {
|
||||
Ring r = null;
|
||||
synchronized (instances) {
|
||||
r = instances.get();
|
||||
instances.set(new Ring());
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends a scope.
|
||||
*/
|
||||
public static void end(Ring old) {
|
||||
synchronized (instances) {
|
||||
instances.remove();
|
||||
instances.set(old);
|
||||
}
|
||||
}
|
||||
}
|
||||
266
jdkSrc/jdk8/com/sun/tools/internal/xjc/reader/TypeUtil.java
Normal file
266
jdkSrc/jdk8/com/sun/tools/internal/xjc/reader/TypeUtil.java
Normal file
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import com.sun.codemodel.internal.JClass;
|
||||
import com.sun.codemodel.internal.JCodeModel;
|
||||
import com.sun.codemodel.internal.JDefinedClass;
|
||||
import com.sun.codemodel.internal.JType;
|
||||
import com.sun.tools.internal.xjc.ErrorReceiver;
|
||||
|
||||
import org.xml.sax.Locator;
|
||||
import org.xml.sax.SAXParseException;
|
||||
|
||||
/**
|
||||
* Type-related utility methods.
|
||||
*
|
||||
* @author
|
||||
* <a href="mailto:kohsuke.kawaguchi@sun.com">Kohsuke KAWAGUCHI</a>
|
||||
*/
|
||||
public class TypeUtil {
|
||||
|
||||
|
||||
/**
|
||||
* Computes the common base type of two types.
|
||||
*
|
||||
* @param types
|
||||
* set of {@link JType} objects.
|
||||
*/
|
||||
public static JType getCommonBaseType( JCodeModel codeModel, Collection<? extends JType> types ) {
|
||||
return getCommonBaseType( codeModel, types.toArray(new JType[types.size()]) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the common base type of types.
|
||||
*
|
||||
* TODO: this is a very interesting problem. Since one type has possibly
|
||||
* multiple base types, it's not an easy problem.
|
||||
* The current implementation is very naive.
|
||||
*
|
||||
* To make the result deterministic across differente JVMs, we have to
|
||||
* use a Set whose ordering is deterministic.
|
||||
*/
|
||||
public static JType getCommonBaseType(JCodeModel codeModel, JType... t) {
|
||||
// first, eliminate duplicates.
|
||||
Set<JType> uniqueTypes = new TreeSet<JType>(typeComparator);
|
||||
for (JType type : t)
|
||||
uniqueTypes.add(type);
|
||||
|
||||
// if this yields only one type. return now.
|
||||
// this is the only case where we can return a primitive type
|
||||
// from this method
|
||||
if (uniqueTypes.size() == 1)
|
||||
return uniqueTypes.iterator().next();
|
||||
|
||||
// assertion failed. nullType can be used only under a very special circumstance
|
||||
assert !uniqueTypes.isEmpty();
|
||||
|
||||
// the null type doesn't need to be taken into account.
|
||||
uniqueTypes.remove(codeModel.NULL);
|
||||
|
||||
// box all the types and compute the intersection of all types
|
||||
Set<JClass> s = null;
|
||||
|
||||
for (JType type : uniqueTypes) {
|
||||
JClass cls = type.boxify();
|
||||
|
||||
if (s == null)
|
||||
s = getAssignableTypes(cls);
|
||||
else
|
||||
s.retainAll(getAssignableTypes(cls));
|
||||
}
|
||||
|
||||
// any JClass can be casted to Object, so make sure it's always there
|
||||
s.add( codeModel.ref(Object.class));
|
||||
|
||||
// refine 's' by removing "lower" types.
|
||||
// for example, if we have both java.lang.Object and
|
||||
// java.io.InputStream, then we don't want to use java.lang.Object.
|
||||
|
||||
JClass[] raw = s.toArray(new JClass[s.size()]);
|
||||
s.clear();
|
||||
|
||||
for (int i = 0; i < raw.length; i++) { // for each raw[i]
|
||||
int j;
|
||||
for (j = 0; j < raw.length; j++) { // see if raw[j] "includes" raw[i]
|
||||
if (i == j)
|
||||
continue;
|
||||
|
||||
if (raw[i].isAssignableFrom(raw[j]))
|
||||
break; // raw[j] is derived from raw[i], hence j includes i.
|
||||
}
|
||||
|
||||
if (j == raw.length)
|
||||
// no other type inclueds raw[i]. remember this value.
|
||||
s.add(raw[i]);
|
||||
}
|
||||
|
||||
assert !s.isEmpty(); // since at least java.lang.Object has to be there
|
||||
|
||||
// we now pick the candidate for the return type
|
||||
JClass result = pickOne(s);
|
||||
|
||||
// finally, sometimes this method is used to compute the base type of types like
|
||||
// JAXBElement<A>, JAXBElement<B>, and JAXBElement<C>.
|
||||
// for those inputs, at this point result=JAXBElement.
|
||||
//
|
||||
// here, we'll try to figure out the parameterization
|
||||
// so that we can return JAXBElement<? extends D> instead of just "JAXBElement".
|
||||
if(result.isParameterized())
|
||||
return result;
|
||||
|
||||
// for each uniqueType we store the list of base type parameterization
|
||||
List<List<JClass>> parameters = new ArrayList<List<JClass>>(uniqueTypes.size());
|
||||
int paramLen = -1;
|
||||
|
||||
for (JType type : uniqueTypes) {
|
||||
JClass cls = type.boxify();
|
||||
JClass bp = cls.getBaseClass(result);
|
||||
// if there's no parameterization in the base type,
|
||||
// we won't do any better than <?>. Thus no point in trying to figure out the parameterization.
|
||||
// just return the base type.
|
||||
if(bp.equals(result))
|
||||
return result;
|
||||
|
||||
assert bp.isParameterized();
|
||||
List<JClass> tp = bp.getTypeParameters();
|
||||
parameters.add(tp);
|
||||
|
||||
assert paramLen==-1 || paramLen==tp.size();
|
||||
// since 'bp' always is a parameterized version of 'result', it should always
|
||||
// have the same number of parameters.
|
||||
paramLen = tp.size();
|
||||
}
|
||||
|
||||
List<JClass> paramResult = new ArrayList<JClass>();
|
||||
List<JClass> argList = new ArrayList<JClass>(parameters.size());
|
||||
// for each type parameter compute the common base type
|
||||
for( int i=0; i<paramLen; i++ ) {
|
||||
argList.clear();
|
||||
for (List<JClass> list : parameters)
|
||||
argList.add(list.get(i));
|
||||
|
||||
// compute the lower bound.
|
||||
JClass bound = (JClass)getCommonBaseType(codeModel,argList);
|
||||
boolean allSame = true;
|
||||
for (JClass a : argList)
|
||||
allSame &= a.equals(bound);
|
||||
if(!allSame)
|
||||
bound = bound.wildcard();
|
||||
|
||||
paramResult.add(bound);
|
||||
}
|
||||
|
||||
return result.narrow(paramResult);
|
||||
}
|
||||
|
||||
private static JClass pickOne(Set<JClass> s) {
|
||||
// we may have more than one candidates at this point.
|
||||
// any user-defined generated types should have
|
||||
// precedence over system-defined existing types.
|
||||
//
|
||||
// so try to return such a type if any.
|
||||
for (JClass c : s)
|
||||
if (c instanceof JDefinedClass)
|
||||
return c;
|
||||
|
||||
// we can do more if we like. for example,
|
||||
// we can avoid types in the RI runtime.
|
||||
// but for now, just return the first one.
|
||||
return s.iterator().next();
|
||||
}
|
||||
|
||||
private static Set<JClass> getAssignableTypes( JClass t ) {
|
||||
Set<JClass> r = new TreeSet<JClass>(typeComparator);
|
||||
getAssignableTypes(t,r);
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of all classes/interfaces that a given type
|
||||
* implements/extends, including itself.
|
||||
*
|
||||
* For example, if you pass java.io.FilterInputStream, then the returned
|
||||
* set will contain java.lang.Object, java.lang.InputStream, and
|
||||
* java.lang.FilterInputStream.
|
||||
*/
|
||||
private static void getAssignableTypes( JClass t, Set<JClass> s ) {
|
||||
if(!s.add(t))
|
||||
return;
|
||||
|
||||
// add its raw type
|
||||
s.add(t.erasure());
|
||||
|
||||
// if this type is added for the first time,
|
||||
// recursively process the super class.
|
||||
JClass _super = t._extends();
|
||||
if(_super!=null)
|
||||
getAssignableTypes(_super,s);
|
||||
|
||||
// recursively process all implemented interfaces
|
||||
Iterator<JClass> itr = t._implements();
|
||||
while(itr.hasNext())
|
||||
getAssignableTypes(itr.next(),s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a {@link JType} object for the string representation
|
||||
* of a type.
|
||||
*/
|
||||
public static JType getType( JCodeModel codeModel,
|
||||
String typeName, ErrorReceiver errorHandler, Locator errorSource ) {
|
||||
|
||||
try {
|
||||
return codeModel.parseType(typeName);
|
||||
} catch( ClassNotFoundException ee ) {
|
||||
|
||||
// make it a warning
|
||||
errorHandler.warning( new SAXParseException(
|
||||
Messages.ERR_CLASS_NOT_FOUND.format(typeName)
|
||||
,errorSource));
|
||||
|
||||
// recover by assuming that it's a class that derives from Object
|
||||
return codeModel.directClass(typeName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares {@link JType} objects by their names.
|
||||
*/
|
||||
private static final Comparator<JType> typeComparator = new Comparator<JType>() {
|
||||
public int compare(JType t1, JType t2) {
|
||||
return t1.fullName().compareTo(t2.fullName());
|
||||
}
|
||||
};
|
||||
}
|
||||
80
jdkSrc/jdk8/com/sun/tools/internal/xjc/reader/Util.java
Normal file
80
jdkSrc/jdk8/com/sun/tools/internal/xjc/reader/Util.java
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
public class Util
|
||||
{
|
||||
/**
|
||||
* Parses the specified string either as an {@link URL} or as a {@link File}.
|
||||
*
|
||||
* @throws IOException
|
||||
* if the parameter is neither.
|
||||
*/
|
||||
public static Object getFileOrURL(String fileOrURL) throws IOException {
|
||||
try {
|
||||
return new URL(fileOrURL);
|
||||
} catch (MalformedURLException e) {
|
||||
return new File(fileOrURL).getCanonicalFile();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Gets an InputSource from a string, which contains either
|
||||
* a file name or an URL.
|
||||
*/
|
||||
public static InputSource getInputSource(String fileOrURL) {
|
||||
try {
|
||||
Object o = getFileOrURL(fileOrURL);
|
||||
if(o instanceof URL) {
|
||||
return new InputSource(escapeSpace(((URL)o).toExternalForm()));
|
||||
} else {
|
||||
String url = ((File)o).toURL().toExternalForm();
|
||||
return new InputSource(escapeSpace(url));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
return new InputSource(fileOrURL);
|
||||
}
|
||||
}
|
||||
|
||||
public static String escapeSpace( String url ) {
|
||||
// URLEncoder didn't work.
|
||||
StringBuffer buf = new StringBuffer();
|
||||
for (int i = 0; i < url.length(); i++) {
|
||||
// TODO: not sure if this is the only character that needs to be escaped.
|
||||
if (url.charAt(i) == ' ')
|
||||
buf.append("%20");
|
||||
else
|
||||
buf.append(url.charAt(i));
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
50
jdkSrc/jdk8/com/sun/tools/internal/xjc/reader/dtd/Block.java
Normal file
50
jdkSrc/jdk8/com/sun/tools/internal/xjc/reader/dtd/Block.java
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.dtd;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class Block {
|
||||
final boolean isOptional;
|
||||
final boolean isRepeated;
|
||||
|
||||
/**
|
||||
* {@link Element}s that belong to this block.
|
||||
* <p>
|
||||
* We want to preserve the order they are added, but we don't want
|
||||
* dupliates.
|
||||
*/
|
||||
final Set<Element> elements = new LinkedHashSet<Element>();
|
||||
|
||||
Block(boolean optional, boolean repeated) {
|
||||
isOptional = optional;
|
||||
isRepeated = repeated;
|
||||
}
|
||||
}
|
||||
314
jdkSrc/jdk8/com/sun/tools/internal/xjc/reader/dtd/Element.java
Normal file
314
jdkSrc/jdk8/com/sun/tools/internal/xjc/reader/dtd/Element.java
Normal file
@@ -0,0 +1,314 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.dtd;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import com.sun.tools.internal.xjc.model.CBuiltinLeafInfo;
|
||||
import com.sun.tools.internal.xjc.model.CClassInfo;
|
||||
import com.sun.tools.internal.xjc.model.CElementPropertyInfo;
|
||||
import static com.sun.tools.internal.xjc.model.CElementPropertyInfo.CollectionMode.*;
|
||||
import com.sun.tools.internal.xjc.model.CPropertyInfo;
|
||||
import com.sun.tools.internal.xjc.model.CReferencePropertyInfo;
|
||||
import com.sun.tools.internal.xjc.model.CTypeRef;
|
||||
import com.sun.tools.internal.xjc.model.CValuePropertyInfo;
|
||||
import com.sun.tools.internal.xjc.model.TypeUse;
|
||||
import com.sun.tools.internal.xjc.reader.dtd.bindinfo.BIConversion;
|
||||
import com.sun.tools.internal.xjc.reader.dtd.bindinfo.BIElement;
|
||||
import com.sun.xml.internal.bind.v2.model.core.ID;
|
||||
import com.sun.xml.internal.bind.v2.model.core.WildcardMode;
|
||||
import com.sun.xml.internal.dtdparser.DTDEventListener;
|
||||
|
||||
import org.xml.sax.Locator;
|
||||
|
||||
/**
|
||||
* DTD Element.
|
||||
*
|
||||
* <p>
|
||||
* This class extends {@link Term} to participate in the content model tree.
|
||||
*
|
||||
* <p>
|
||||
* This class is repsonsible for binding the element.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class Element extends Term implements Comparable<Element> {
|
||||
|
||||
/**
|
||||
* Name of the element.
|
||||
*/
|
||||
final String name;
|
||||
|
||||
private final TDTDReader owner;
|
||||
|
||||
/**
|
||||
* @see DTDEventListener#endContentModel(String, short)
|
||||
*/
|
||||
private short contentModelType;
|
||||
|
||||
private Term contentModel;
|
||||
|
||||
/**
|
||||
* True if this element is referenced from another element.
|
||||
*/
|
||||
boolean isReferenced;
|
||||
|
||||
/**
|
||||
* If this element maps to a class, that class representation.
|
||||
* Otherwise null.
|
||||
*/
|
||||
private CClassInfo classInfo;
|
||||
|
||||
/**
|
||||
* True if {@link #classInfo} field is computed.
|
||||
*/
|
||||
private boolean classInfoComputed;
|
||||
|
||||
/**
|
||||
* List of attribute properties on this element
|
||||
*/
|
||||
final List<CPropertyInfo> attributes = new ArrayList<CPropertyInfo>();
|
||||
|
||||
/**
|
||||
* Normalized blocks of the content model.
|
||||
*/
|
||||
private final List<Block> normalizedBlocks = new ArrayList<Block>();
|
||||
|
||||
/**
|
||||
* True if this element needs to be a class.
|
||||
*
|
||||
* Currently, if an element is referenced from a construct like (A|B|C),
|
||||
* we require those A,B, and C to be a class.
|
||||
*/
|
||||
private boolean mustBeClass;
|
||||
|
||||
/**
|
||||
* The source location where this element is defined.
|
||||
*/
|
||||
private Locator locator;
|
||||
|
||||
public Element(TDTDReader owner,String name) {
|
||||
this.owner = owner;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
void normalize(List<Block> r, boolean optional) {
|
||||
Block o = new Block(optional,false);
|
||||
o.elements.add(this);
|
||||
r.add(o);
|
||||
}
|
||||
|
||||
void addAllElements(Block b) {
|
||||
b.elements.add(this);
|
||||
}
|
||||
|
||||
boolean isOptional() {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean isRepeated() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Define its content model.
|
||||
*/
|
||||
void define(short contentModelType, Term contentModel, Locator locator) {
|
||||
assert this.contentModel==null; // may not be called twice
|
||||
this.contentModelType = contentModelType;
|
||||
this.contentModel = contentModel;
|
||||
this.locator = locator;
|
||||
contentModel.normalize(normalizedBlocks,false);
|
||||
|
||||
for( Block b : normalizedBlocks ) {
|
||||
if(b.isRepeated || b.elements.size()>1) {
|
||||
for( Element e : b.elements ) {
|
||||
owner.getOrCreateElement(e.name).mustBeClass = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When this element is an PCDATA-only content model,
|
||||
* returns the conversion for it. Otherwise the behavior is undefined.
|
||||
*/
|
||||
private TypeUse getConversion() {
|
||||
assert contentModel == Term.EMPTY; // this is PCDATA-only element
|
||||
|
||||
BIElement e = owner.bindInfo.element(name);
|
||||
if(e!=null) {
|
||||
BIConversion conv = e.getConversion();
|
||||
if(conv!=null)
|
||||
return conv.getTransducer();
|
||||
}
|
||||
return CBuiltinLeafInfo.STRING;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return null if this class is not bound to a class.
|
||||
*/
|
||||
CClassInfo getClassInfo() {
|
||||
if(!classInfoComputed) {
|
||||
classInfoComputed = true;
|
||||
classInfo = calcClass();
|
||||
}
|
||||
return classInfo;
|
||||
}
|
||||
|
||||
private CClassInfo calcClass() {
|
||||
BIElement e = owner.bindInfo.element(name);
|
||||
if(e==null) {
|
||||
if(contentModelType!=DTDEventListener.CONTENT_MODEL_MIXED
|
||||
|| !attributes.isEmpty()
|
||||
|| mustBeClass)
|
||||
return createDefaultClass();
|
||||
if(contentModel!=Term.EMPTY) {
|
||||
throw new UnsupportedOperationException("mixed content model not supported");
|
||||
} else {
|
||||
// just #PCDATA
|
||||
if(isReferenced)
|
||||
return null;
|
||||
else
|
||||
// if no one else is referencing, assumed to be the root.
|
||||
return createDefaultClass();
|
||||
}
|
||||
} else {
|
||||
return e.clazz;
|
||||
}
|
||||
}
|
||||
|
||||
private CClassInfo createDefaultClass() {
|
||||
String className = owner.model.getNameConverter().toClassName(name);
|
||||
QName tagName = new QName("",name);
|
||||
|
||||
return new CClassInfo(owner.model,owner.getTargetPackage(),className,locator,null,tagName,null,null/*TODO*/);
|
||||
}
|
||||
|
||||
void bind() {
|
||||
CClassInfo ci = getClassInfo();
|
||||
assert ci!=null || attributes.isEmpty();
|
||||
for( CPropertyInfo p : attributes )
|
||||
ci.addProperty(p);
|
||||
|
||||
switch(contentModelType) {
|
||||
case DTDEventListener.CONTENT_MODEL_ANY:
|
||||
CReferencePropertyInfo rp = new CReferencePropertyInfo("Content",true,false,true,null,null/*TODO*/,locator, false, false, false);
|
||||
rp.setWildcard(WildcardMode.SKIP);
|
||||
ci.addProperty(rp);
|
||||
return;
|
||||
case DTDEventListener.CONTENT_MODEL_CHILDREN:
|
||||
break; // handling follows
|
||||
case DTDEventListener.CONTENT_MODEL_MIXED:
|
||||
if(contentModel!=Term.EMPTY)
|
||||
throw new UnsupportedOperationException("mixed content model unsupported yet");
|
||||
|
||||
if(ci!=null) {
|
||||
// if this element is mapped to a class, just put one property
|
||||
CValuePropertyInfo p = new CValuePropertyInfo("value", null,null/*TODO*/,locator,getConversion(),null);
|
||||
ci.addProperty(p);
|
||||
}
|
||||
return;
|
||||
case DTDEventListener.CONTENT_MODEL_EMPTY:
|
||||
// no content model
|
||||
assert ci!=null;
|
||||
return;
|
||||
}
|
||||
|
||||
// normalize
|
||||
List<Block> n = new ArrayList<Block>();
|
||||
contentModel.normalize(n,false);
|
||||
|
||||
{// check collision among Blocks
|
||||
Set<String> names = new HashSet<String>();
|
||||
boolean collision = false;
|
||||
|
||||
OUTER:
|
||||
for( Block b : n )
|
||||
for( Element e : b.elements )
|
||||
if(!names.add(e.name)) {
|
||||
collision = true;
|
||||
break OUTER;
|
||||
}
|
||||
|
||||
if(collision) {
|
||||
// collapse all blocks into one
|
||||
Block all = new Block(true,true);
|
||||
for( Block b : n )
|
||||
all.elements.addAll(b.elements);
|
||||
n.clear();
|
||||
n.add(all);
|
||||
}
|
||||
}
|
||||
|
||||
for( Block b : n ) {
|
||||
CElementPropertyInfo p;
|
||||
if(b.isRepeated || b.elements.size()>1) {
|
||||
// collection
|
||||
StringBuilder name = new StringBuilder();
|
||||
for( Element e : b.elements ) {
|
||||
if(name.length()>0)
|
||||
name.append("Or");
|
||||
name.append(owner.model.getNameConverter().toPropertyName(e.name));
|
||||
}
|
||||
p = new CElementPropertyInfo(name.toString(), REPEATED_ELEMENT, ID.NONE, null, null,null/*TODO*/, locator, !b.isOptional );
|
||||
for( Element e : b.elements ) {
|
||||
CClassInfo child = owner.getOrCreateElement(e.name).getClassInfo();
|
||||
assert child!=null; // we are requiring them to be classes.
|
||||
p.getTypes().add(new CTypeRef(child,new QName("",e.name),null,false,null));
|
||||
}
|
||||
} else {
|
||||
// single property
|
||||
String name = b.elements.iterator().next().name;
|
||||
String propName = owner.model.getNameConverter().toPropertyName(name);
|
||||
|
||||
TypeUse refType;
|
||||
Element ref = owner.getOrCreateElement(name);
|
||||
if(ref.getClassInfo()!=null)
|
||||
refType = ref.getClassInfo();
|
||||
else {
|
||||
refType = ref.getConversion().getInfo();
|
||||
}
|
||||
|
||||
p = new CElementPropertyInfo(propName,
|
||||
refType.isCollection()?REPEATED_VALUE:NOT_REPEATED, ID.NONE, null, null,null/*TODO*/, locator, !b.isOptional );
|
||||
|
||||
p.getTypes().add(new CTypeRef(refType.getInfo(),new QName("",name),null,false,null));
|
||||
}
|
||||
ci.addProperty(p);
|
||||
}
|
||||
}
|
||||
|
||||
public int compareTo(Element that) {
|
||||
return this.name.compareTo(that.name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.dtd;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
/**
|
||||
* Formats error messages.
|
||||
*/
|
||||
class Messages
|
||||
{
|
||||
/** Loads a string resource and formats it with specified arguments. */
|
||||
static String format( String property, Object... args ) {
|
||||
String text = ResourceBundle.getBundle(Messages.class.getPackage().getName() + ".MessageBundle").getString(property);
|
||||
return MessageFormat.format(text,args);
|
||||
}
|
||||
|
||||
|
||||
public static final String ERR_NO_ROOT_ELEMENT = // arg:0
|
||||
"TDTDReader.NoRootElement";
|
||||
|
||||
public static final String ERR_UNDEFINED_ELEMENT_IN_BINDINFO = // arg:1
|
||||
"TDTDReader.UndefinedElementInBindInfo";
|
||||
|
||||
public static final String ERR_CONVERSION_FOR_NON_VALUE_ELEMENT = // arg:1
|
||||
"TDTDReader.ConversionForNonValueElement";
|
||||
|
||||
public static final String ERR_CONTENT_PROPERTY_PARTICLE_MISMATCH = // arg:1
|
||||
"TDTDReader.ContentProperty.ParticleMismatch";
|
||||
|
||||
public static final String ERR_CONTENT_PROPERTY_DECLARATION_TOO_SHORT = // arg:1
|
||||
"TDTDReader.ContentProperty.DeclarationTooShort";
|
||||
|
||||
public static final String ERR_BINDINFO_NON_EXISTENT_ELEMENT_DECLARATION = // arg:1
|
||||
"TDTDReader.BindInfo.NonExistentElementDeclaration";
|
||||
|
||||
public static final String ERR_BINDINFO_NON_EXISTENT_INTERFACE_MEMBER = // arg:1
|
||||
"TDTDReader.BindInfo.NonExistentInterfaceMember";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.dtd;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.sun.xml.internal.dtdparser.DTDEventListener;
|
||||
|
||||
|
||||
/**
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class ModelGroup extends Term {
|
||||
enum Kind {
|
||||
CHOICE, SEQUENCE
|
||||
}
|
||||
|
||||
Kind kind;
|
||||
|
||||
private final List<Term> terms = new ArrayList<Term>();
|
||||
|
||||
void normalize(List<Block> r, boolean optional) {
|
||||
switch(kind) {
|
||||
case SEQUENCE:
|
||||
for( Term t : terms )
|
||||
t.normalize(r,optional);
|
||||
return;
|
||||
case CHOICE:
|
||||
Block b = new Block(isOptional()||optional,isRepeated());
|
||||
addAllElements(b);
|
||||
r.add(b);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void addAllElements(Block b) {
|
||||
for( Term t : terms )
|
||||
t.addAllElements(b);
|
||||
}
|
||||
|
||||
boolean isOptional() {
|
||||
switch(kind) {
|
||||
case SEQUENCE:
|
||||
for( Term t : terms )
|
||||
if(!t.isOptional())
|
||||
return false;
|
||||
return true;
|
||||
case CHOICE:
|
||||
for( Term t : terms )
|
||||
if(t.isOptional())
|
||||
return true;
|
||||
return false;
|
||||
default:
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
boolean isRepeated() {
|
||||
switch(kind) {
|
||||
case SEQUENCE:
|
||||
return true;
|
||||
case CHOICE:
|
||||
for( Term t : terms )
|
||||
if(t.isRepeated())
|
||||
return true;
|
||||
return false;
|
||||
default:
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
void setKind(short connectorType) {
|
||||
Kind k;
|
||||
switch(connectorType) {
|
||||
case DTDEventListener.SEQUENCE:
|
||||
k = Kind.SEQUENCE;
|
||||
break;
|
||||
case DTDEventListener.CHOICE:
|
||||
k = Kind.CHOICE;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
assert kind==null || k==kind;
|
||||
kind = k;
|
||||
}
|
||||
|
||||
void addTerm(Term t) {
|
||||
if (t instanceof ModelGroup) {
|
||||
ModelGroup mg = (ModelGroup) t;
|
||||
if(mg.kind==this.kind) {
|
||||
terms.addAll(mg.terms);
|
||||
return;
|
||||
}
|
||||
}
|
||||
terms.add(t);
|
||||
}
|
||||
|
||||
|
||||
Term wrapUp() {
|
||||
switch(terms.size()) {
|
||||
case 0:
|
||||
return EMPTY;
|
||||
case 1:
|
||||
assert kind==null;
|
||||
return terms.get(0);
|
||||
default:
|
||||
assert kind!=null;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.dtd;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.sun.xml.internal.dtdparser.DTDEventListener;
|
||||
|
||||
|
||||
/**
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class Occurence extends Term {
|
||||
final Term term;
|
||||
final boolean isOptional;
|
||||
final boolean isRepeated;
|
||||
|
||||
Occurence(Term term, boolean optional, boolean repeated) {
|
||||
this.term = term;
|
||||
isOptional = optional;
|
||||
isRepeated = repeated;
|
||||
}
|
||||
|
||||
static Term wrap( Term t, int occurence ) {
|
||||
switch(occurence) {
|
||||
case DTDEventListener.OCCURENCE_ONCE:
|
||||
return t;
|
||||
case DTDEventListener.OCCURENCE_ONE_OR_MORE:
|
||||
return new Occurence(t,false,true);
|
||||
case DTDEventListener.OCCURENCE_ZERO_OR_MORE:
|
||||
return new Occurence(t,true,true);
|
||||
case DTDEventListener.OCCURENCE_ZERO_OR_ONE:
|
||||
return new Occurence(t,true,false);
|
||||
default:
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
void normalize(List<Block> r, boolean optional) {
|
||||
if(isRepeated) {
|
||||
Block b = new Block(isOptional||optional,true);
|
||||
addAllElements(b);
|
||||
r.add(b);
|
||||
} else {
|
||||
term.normalize(r,optional||isOptional);
|
||||
}
|
||||
}
|
||||
|
||||
void addAllElements(Block b) {
|
||||
term.addAllElements(b);
|
||||
}
|
||||
|
||||
boolean isOptional() {
|
||||
return isOptional||term.isOptional();
|
||||
}
|
||||
|
||||
boolean isRepeated() {
|
||||
return isRepeated||term.isRepeated();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,463 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.dtd;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import com.sun.codemodel.internal.JClass;
|
||||
import com.sun.codemodel.internal.JCodeModel;
|
||||
import com.sun.codemodel.internal.JDefinedClass;
|
||||
import com.sun.codemodel.internal.JPackage;
|
||||
import com.sun.tools.internal.xjc.AbortException;
|
||||
import com.sun.tools.internal.xjc.ErrorReceiver;
|
||||
import com.sun.tools.internal.xjc.Options;
|
||||
import com.sun.tools.internal.xjc.model.CAttributePropertyInfo;
|
||||
import com.sun.tools.internal.xjc.model.CBuiltinLeafInfo;
|
||||
import com.sun.tools.internal.xjc.model.CClassInfo;
|
||||
import com.sun.tools.internal.xjc.model.CPropertyInfo;
|
||||
import com.sun.tools.internal.xjc.model.Model;
|
||||
import com.sun.tools.internal.xjc.model.TypeUse;
|
||||
import com.sun.tools.internal.xjc.model.TypeUseFactory;
|
||||
import com.sun.tools.internal.xjc.model.CDefaultValue;
|
||||
import com.sun.tools.internal.xjc.reader.ModelChecker;
|
||||
import com.sun.tools.internal.xjc.reader.Ring;
|
||||
import com.sun.tools.internal.xjc.reader.dtd.bindinfo.BIAttribute;
|
||||
import com.sun.tools.internal.xjc.reader.dtd.bindinfo.BIElement;
|
||||
import com.sun.tools.internal.xjc.reader.dtd.bindinfo.BIInterface;
|
||||
import com.sun.tools.internal.xjc.reader.dtd.bindinfo.BindInfo;
|
||||
import com.sun.tools.internal.xjc.util.CodeModelClassFactory;
|
||||
import com.sun.tools.internal.xjc.util.ErrorReceiverFilter;
|
||||
import com.sun.xml.internal.bind.api.impl.NameConverter;
|
||||
import com.sun.xml.internal.dtdparser.DTDHandlerBase;
|
||||
import com.sun.xml.internal.dtdparser.DTDParser;
|
||||
import com.sun.xml.internal.dtdparser.InputEntity;
|
||||
import com.sun.xml.internal.xsom.XmlString;
|
||||
import com.sun.istack.internal.SAXParseException2;
|
||||
|
||||
import org.xml.sax.EntityResolver;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.Locator;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXParseException;
|
||||
import org.xml.sax.helpers.LocatorImpl;
|
||||
|
||||
/**
|
||||
* Parses DTD grammar along with binding information into BGM.
|
||||
*
|
||||
* @author
|
||||
* <a href="mailto:kohsuke.kawaguchi@sun.com">Kohsuke KAWAGUCHI</a>
|
||||
*/
|
||||
public class TDTDReader extends DTDHandlerBase
|
||||
{
|
||||
/**
|
||||
* Parses DTD grammar and a binding information into BGM.
|
||||
*
|
||||
* <p>
|
||||
* This method is just a utility method that covers 80% of the use
|
||||
* cases.
|
||||
*
|
||||
* @param bindingInfo
|
||||
* binding information file, if any. Can be null.
|
||||
*/
|
||||
public static Model parse(
|
||||
InputSource dtd,
|
||||
InputSource bindingInfo,
|
||||
ErrorReceiver errorReceiver,
|
||||
Options opts) {
|
||||
|
||||
try {
|
||||
// set up a ring
|
||||
final Ring old = Ring.begin();
|
||||
try {
|
||||
ErrorReceiverFilter ef = new ErrorReceiverFilter(errorReceiver);
|
||||
|
||||
JCodeModel cm = new JCodeModel();
|
||||
Model model = new Model(opts,cm,NameConverter.standard,opts.classNameAllocator,null);
|
||||
|
||||
Ring.add(cm);
|
||||
Ring.add(model);
|
||||
Ring.add(ErrorReceiver.class,ef);
|
||||
|
||||
TDTDReader reader = new TDTDReader( ef, opts, bindingInfo);
|
||||
|
||||
DTDParser parser = new DTDParser();
|
||||
parser.setDtdHandler(reader);
|
||||
if( opts.entityResolver!=null )
|
||||
parser.setEntityResolver(opts.entityResolver);
|
||||
|
||||
try {
|
||||
parser.parse(dtd);
|
||||
} catch (SAXParseException e) {
|
||||
return null; // this error was already handled by GrammarReaderController
|
||||
}
|
||||
|
||||
Ring.get(ModelChecker.class).check();
|
||||
|
||||
if(ef.hadError()) return null;
|
||||
else return model;
|
||||
} finally {
|
||||
Ring.end(old);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
errorReceiver.error(new SAXParseException2(e.getMessage(),null,e));
|
||||
return null;
|
||||
} catch (SAXException e) {
|
||||
errorReceiver.error(new SAXParseException2(e.getMessage(),null,e));
|
||||
return null;
|
||||
} catch (AbortException e) {
|
||||
// parsing was aborted but the error was already reported
|
||||
return null;
|
||||
}
|
||||
}
|
||||
protected TDTDReader(ErrorReceiver errorReceiver, Options opts, InputSource _bindInfo)
|
||||
throws AbortException {
|
||||
this.entityResolver = opts.entityResolver;
|
||||
this.errorReceiver = new ErrorReceiverFilter(errorReceiver);
|
||||
bindInfo = new BindInfo(model,_bindInfo, this.errorReceiver);
|
||||
classFactory = new CodeModelClassFactory(errorReceiver);
|
||||
}
|
||||
|
||||
private final EntityResolver entityResolver;
|
||||
|
||||
/**
|
||||
* binding information.
|
||||
*
|
||||
* <p>
|
||||
* This is always non-null even if no binding information was specified.
|
||||
* (In that case, a dummy object will be provided.)
|
||||
*/
|
||||
final BindInfo bindInfo;
|
||||
|
||||
final Model model = Ring.get(Model.class);
|
||||
|
||||
private final CodeModelClassFactory classFactory;
|
||||
|
||||
private final ErrorReceiverFilter errorReceiver;
|
||||
|
||||
/**
|
||||
* Element name to its content model definition.
|
||||
*/
|
||||
private final Map<String,Element> elements = new HashMap<String,Element>();
|
||||
|
||||
|
||||
public void startDTD(InputEntity entity) throws SAXException {
|
||||
}
|
||||
|
||||
public void endDTD() throws SAXException {
|
||||
|
||||
// bind them all.
|
||||
// we need to know how elements are referencing each other before we do this,
|
||||
// so this can be only done at the endDTD method
|
||||
for( Element e : elements.values() )
|
||||
e.bind();
|
||||
|
||||
// if there was an error by now, just abort.
|
||||
if (errorReceiver.hadError())
|
||||
return;
|
||||
|
||||
processInterfaceDeclarations();
|
||||
|
||||
// check XJC extensions and realize them
|
||||
model.serialVersionUID = bindInfo.getSerialVersionUID();
|
||||
if(model.serialVersionUID!=null)
|
||||
model.serializable=true;
|
||||
model.rootClass = bindInfo.getSuperClass();
|
||||
model.rootInterface = bindInfo.getSuperInterface();
|
||||
|
||||
// TODO: do we need to reimplement them?
|
||||
// // performs annotation
|
||||
// Annotator.annotate(model, this);
|
||||
// FieldCollisionChecker.check( model, this );
|
||||
|
||||
|
||||
processConstructorDeclarations();
|
||||
}
|
||||
|
||||
/** Processes interface declarations. */
|
||||
private void processInterfaceDeclarations() {
|
||||
|
||||
|
||||
Map<String,InterfaceAcceptor> fromName = new HashMap<String,InterfaceAcceptor>();
|
||||
|
||||
// first, create empty InterfaceItem declaration for all interfaces
|
||||
Map<BIInterface,JClass> decls = new HashMap<BIInterface,JClass>();
|
||||
|
||||
for( BIInterface decl : bindInfo.interfaces() ) {
|
||||
final JDefinedClass intf = classFactory.createInterface(
|
||||
bindInfo.getTargetPackage(), decl.name(), copyLocator() );
|
||||
decls.put(decl,intf);
|
||||
fromName.put(decl.name(),new InterfaceAcceptor() {
|
||||
public void implement(JClass c) {
|
||||
intf._implements(c);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for( final CClassInfo ci : model.beans().values() ) {
|
||||
fromName.put(ci.getName(),new InterfaceAcceptor() {
|
||||
public void implement(JClass c) {
|
||||
ci._implements(c);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// traverse the interface declarations again
|
||||
// and populate its expression according to the members attribute.
|
||||
for( Map.Entry<BIInterface,JClass> e : decls.entrySet() ) {
|
||||
BIInterface decl = e.getKey();
|
||||
JClass c = e.getValue();
|
||||
|
||||
for (String member : decl.members()) {
|
||||
InterfaceAcceptor acc = fromName.get(member);
|
||||
if (acc == null) {
|
||||
// there is no such class/interface
|
||||
// TODO: error location
|
||||
error(decl.getSourceLocation(),
|
||||
Messages.ERR_BINDINFO_NON_EXISTENT_INTERFACE_MEMBER,
|
||||
member);
|
||||
continue;
|
||||
}
|
||||
|
||||
acc.implement(c);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: check the cyclic interface definition
|
||||
}
|
||||
|
||||
private static interface InterfaceAcceptor {
|
||||
void implement( JClass c );
|
||||
}
|
||||
|
||||
|
||||
JPackage getTargetPackage() {
|
||||
return bindInfo.getTargetPackage();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates constructor declarations as specified in the
|
||||
* binding information.
|
||||
*
|
||||
* <p>
|
||||
* Also checks that the binding file does not contain
|
||||
* declarations for non-existent elements.
|
||||
*/
|
||||
private void processConstructorDeclarations() {
|
||||
for( BIElement decl: bindInfo.elements() ) {
|
||||
Element e = elements.get(decl.name());
|
||||
if(e==null) {
|
||||
error(decl.getSourceLocation(),
|
||||
Messages.ERR_BINDINFO_NON_EXISTENT_ELEMENT_DECLARATION,decl.name());
|
||||
continue; // continue to process next declaration
|
||||
}
|
||||
|
||||
if(!decl.isClass())
|
||||
// only element-class declaration has constructor definitions
|
||||
continue;
|
||||
|
||||
decl.declareConstructors(e.getClassInfo());
|
||||
}
|
||||
}
|
||||
|
||||
public void attributeDecl(String elementName, String attributeName, String attributeType, String[] enumeration, short attributeUse, String defaultValue) throws SAXException {
|
||||
getOrCreateElement(elementName).attributes.add(
|
||||
createAttribute(elementName, attributeName, attributeType, enumeration, attributeUse, defaultValue)
|
||||
);
|
||||
}
|
||||
|
||||
protected CPropertyInfo createAttribute(
|
||||
String elementName, String attributeName, String attributeType,
|
||||
String[] enums, short attributeUse, String defaultValue )
|
||||
throws SAXException {
|
||||
|
||||
boolean required = attributeUse==USE_REQUIRED;
|
||||
|
||||
// get the attribute-property declaration
|
||||
BIElement edecl = bindInfo.element(elementName);
|
||||
BIAttribute decl=null;
|
||||
if(edecl!=null) decl=edecl.attribute(attributeName);
|
||||
|
||||
String propName;
|
||||
if(decl==null) propName = model.getNameConverter().toPropertyName(attributeName);
|
||||
else propName = decl.getPropertyName();
|
||||
|
||||
QName qname = new QName("",attributeName);
|
||||
|
||||
// if no declaration is specified, just wrap it by
|
||||
// a FieldItem and let the normalizer handle its content.
|
||||
TypeUse use;
|
||||
|
||||
if(decl!=null && decl.getConversion()!=null)
|
||||
use = decl.getConversion().getTransducer();
|
||||
else
|
||||
use = builtinConversions.get(attributeType);
|
||||
|
||||
CPropertyInfo r = new CAttributePropertyInfo(
|
||||
propName, null,null/*TODO*/, copyLocator(), qname, use, null, required );
|
||||
|
||||
if(defaultValue!=null)
|
||||
r.defaultValue = CDefaultValue.create( use, new XmlString(defaultValue) );
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Element getOrCreateElement( String elementName ) {
|
||||
Element r = elements.get(elementName);
|
||||
if(r==null) {
|
||||
r = new Element(this,elementName);
|
||||
elements.put(elementName,r);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
public void startContentModel(String elementName, short contentModelType) throws SAXException {
|
||||
assert modelGroups.isEmpty();
|
||||
modelGroups.push(new ModelGroup());
|
||||
}
|
||||
|
||||
public void endContentModel(String elementName, short contentModelType) throws SAXException {
|
||||
assert modelGroups.size()==1;
|
||||
Term term = modelGroups.pop().wrapUp();
|
||||
|
||||
Element e = getOrCreateElement(elementName);
|
||||
e.define( contentModelType, term, copyLocator() );
|
||||
}
|
||||
|
||||
|
||||
private final Stack<ModelGroup> modelGroups = new Stack<ModelGroup>();
|
||||
|
||||
public void startModelGroup() throws SAXException {
|
||||
modelGroups.push(new ModelGroup());
|
||||
}
|
||||
|
||||
public void endModelGroup(short occurence) throws SAXException {
|
||||
Term t = Occurence.wrap( modelGroups.pop().wrapUp(), occurence );
|
||||
modelGroups.peek().addTerm(t);
|
||||
}
|
||||
|
||||
public void connector(short connectorType) throws SAXException {
|
||||
modelGroups.peek().setKind(connectorType);
|
||||
}
|
||||
|
||||
// TODO: for now, we just ignore all the content model specification
|
||||
// and treat it as (A,B,C,....)
|
||||
|
||||
public void childElement(String elementName, short occurence) throws SAXException {
|
||||
Element child = getOrCreateElement(elementName);
|
||||
modelGroups.peek().addTerm( Occurence.wrap( child, occurence ) );
|
||||
child.isReferenced = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Mutable {@link Locator} instance that points to
|
||||
* the current source line.
|
||||
* <p>
|
||||
* Use {@link #copyLocator()} to get a immutable clone.
|
||||
*/
|
||||
private Locator locator;
|
||||
|
||||
public void setDocumentLocator(Locator loc) {
|
||||
this.locator = loc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a snapshot of the current {@link #locator} values.
|
||||
*/
|
||||
private Locator copyLocator(){
|
||||
return new LocatorImpl(locator);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
// builtin datatype handling
|
||||
//
|
||||
//
|
||||
|
||||
/** Transducers for the built-in types. Read-only. */
|
||||
private static final Map<String,TypeUse> builtinConversions;
|
||||
|
||||
|
||||
static {
|
||||
// list of datatypes which have built-in conversions.
|
||||
// note that although xs:token and xs:normalizedString are not
|
||||
// specified in the spec, they need to be here because they
|
||||
// have different whitespace normalization semantics.
|
||||
Map<String,TypeUse> m = new HashMap<String,TypeUse>();
|
||||
|
||||
m.put("CDATA", CBuiltinLeafInfo.NORMALIZED_STRING);
|
||||
m.put("ENTITY", CBuiltinLeafInfo.TOKEN);
|
||||
m.put("ENTITIES", CBuiltinLeafInfo.STRING.makeCollection());
|
||||
m.put("NMTOKEN", CBuiltinLeafInfo.TOKEN);
|
||||
m.put("NMTOKENS", CBuiltinLeafInfo.STRING.makeCollection());
|
||||
m.put("ID", CBuiltinLeafInfo.ID);
|
||||
m.put("IDREF", CBuiltinLeafInfo.IDREF);
|
||||
m.put("IDREFS", TypeUseFactory.makeCollection(CBuiltinLeafInfo.IDREF));
|
||||
m.put("ENUMERATION",CBuiltinLeafInfo.TOKEN);
|
||||
|
||||
builtinConversions = Collections.unmodifiableMap(m);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
// error related utility methods
|
||||
//
|
||||
//
|
||||
public void error(SAXParseException e) throws SAXException {
|
||||
errorReceiver.error(e);
|
||||
}
|
||||
|
||||
public void fatalError(SAXParseException e) throws SAXException {
|
||||
errorReceiver.fatalError(e);
|
||||
}
|
||||
|
||||
public void warning(SAXParseException e) throws SAXException {
|
||||
errorReceiver.warning(e);
|
||||
}
|
||||
|
||||
protected final void error( Locator loc, String prop, Object... args ) {
|
||||
errorReceiver.error(loc,Messages.format(prop,args));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
62
jdkSrc/jdk8/com/sun/tools/internal/xjc/reader/dtd/Term.java
Normal file
62
jdkSrc/jdk8/com/sun/tools/internal/xjc/reader/dtd/Term.java
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.dtd;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
abstract class Term {
|
||||
abstract void normalize( List<Block> r, boolean optional );
|
||||
|
||||
abstract void addAllElements(Block b);
|
||||
|
||||
abstract boolean isOptional();
|
||||
|
||||
abstract boolean isRepeated();
|
||||
|
||||
/**
|
||||
* Represents empty term.
|
||||
* <p>
|
||||
* This special term is only used to represent #PCDATA-only content model.
|
||||
*/
|
||||
static final Term EMPTY = new Term() {
|
||||
void normalize(List<Block> r, boolean optional) {
|
||||
}
|
||||
|
||||
void addAllElements(Block b) {
|
||||
}
|
||||
|
||||
boolean isOptional() {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean isRepeated() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.dtd.bindinfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.sun.tools.internal.xjc.generator.bean.field.FieldRenderer;
|
||||
import com.sun.tools.internal.xjc.generator.bean.field.FieldRendererFactory;
|
||||
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/** <attribute> declaration in the binding file. */
|
||||
public class BIAttribute
|
||||
{
|
||||
/**
|
||||
* Wraps a given <attribute> element.
|
||||
* <p>
|
||||
* Should be created only from {@link BIElement}.
|
||||
*/
|
||||
BIAttribute( BIElement _parent, Element _e ) {
|
||||
this.parent = _parent;
|
||||
this.element = _e;
|
||||
}
|
||||
|
||||
private final BIElement parent;
|
||||
private final Element element;
|
||||
|
||||
/** Gets the name of this attribute-property declaration. */
|
||||
public final String name() {
|
||||
return element.getAttribute("name");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the conversion method for this attribute, if any.
|
||||
*
|
||||
* @return
|
||||
* If the convert attribute is not specified, this
|
||||
* method returns null.
|
||||
*/
|
||||
public BIConversion getConversion() {
|
||||
if (element.getAttributeNode("convert") == null)
|
||||
return null;
|
||||
|
||||
String cnv = element.getAttribute("convert");
|
||||
return parent.conversion(cnv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the realization of this particle, if any.
|
||||
*
|
||||
* @return
|
||||
* null if the "collection" attribute was not specified.
|
||||
*/
|
||||
public final FieldRenderer getRealization() {
|
||||
Attr a = element.getAttributeNode("collection");
|
||||
if(a==null) return null;
|
||||
|
||||
String v = element.getAttribute("collection").trim();
|
||||
|
||||
FieldRendererFactory frf = parent.parent.model.options.getFieldRendererFactory();
|
||||
if(v.equals("array")) return frf.getArray();
|
||||
if(v.equals("list"))
|
||||
return frf.getList(
|
||||
parent.parent.codeModel.ref(ArrayList.class));
|
||||
|
||||
// the correctness of the attribute value must be
|
||||
// checked by the validator.
|
||||
throw new InternalError("unexpected collection value: "+v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the property name for this attribute.
|
||||
*
|
||||
* @return
|
||||
* always a non-null, valid string.
|
||||
*/
|
||||
public final String getPropertyName() {
|
||||
String r = DOMUtil.getAttribute(element,"property");
|
||||
if(r!=null) return r;
|
||||
else return name();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.dtd.bindinfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import com.sun.tools.internal.xjc.model.CClassInfo;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.xml.sax.Locator;
|
||||
|
||||
/**
|
||||
* <constructor> declaration in the binding file.
|
||||
*
|
||||
* <p>
|
||||
* Since JAXB will generate both interfaces and implementations,
|
||||
* A constructor declaration will create:
|
||||
*
|
||||
* <ul>
|
||||
* <li> a method declaration in the factory interface
|
||||
* <li> a method implementation in the factory implementation class
|
||||
* <li> a constructor implementation in the actual implementation class
|
||||
* </ul>
|
||||
*/
|
||||
public class BIConstructor
|
||||
{
|
||||
BIConstructor( Element _node ) {
|
||||
this.dom = _node;
|
||||
|
||||
StringTokenizer tokens = new StringTokenizer(
|
||||
DOMUtil.getAttribute(_node,"properties"));
|
||||
|
||||
List<String> vec = new ArrayList<String>();
|
||||
while(tokens.hasMoreTokens())
|
||||
vec.add(tokens.nextToken());
|
||||
properties = vec.toArray(new String[0]);
|
||||
|
||||
if( properties.length==0 )
|
||||
throw new AssertionError("this error should be catched by the validator");
|
||||
}
|
||||
|
||||
/** <constructor> element in the source binding file. */
|
||||
private final Element dom;
|
||||
|
||||
/** properties specified by @properties. */
|
||||
private final String[] properties;
|
||||
|
||||
/**
|
||||
* Creates a constructor declaration into the ClassItem.
|
||||
*
|
||||
* @param cls
|
||||
* ClassItem object that corresponds to the
|
||||
* element declaration that contains this declaration.
|
||||
*/
|
||||
public void createDeclaration( CClassInfo cls ) {
|
||||
cls.addConstructor(properties);
|
||||
}
|
||||
|
||||
/** Gets the location where this declaration is declared. */
|
||||
public Locator getSourceLocation() {
|
||||
return DOMLocator.getLocationInfo(dom);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.dtd.bindinfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.sun.codemodel.internal.JClass;
|
||||
import com.sun.tools.internal.xjc.Options;
|
||||
import com.sun.tools.internal.xjc.generator.bean.field.FieldRenderer;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Particles in the <content> declaration in the binding file.
|
||||
*
|
||||
*/
|
||||
public class BIContent
|
||||
{
|
||||
/**
|
||||
* Wraps a given particle.
|
||||
*
|
||||
* <p>
|
||||
* This object should be created through
|
||||
* the {@link #create(Element, BIElement)} method.
|
||||
*/
|
||||
private BIContent( Element e, BIElement _parent ) {
|
||||
this.element = e;
|
||||
this.parent = _parent;
|
||||
this.opts = parent.parent.model.options;
|
||||
}
|
||||
|
||||
/** The particle element which this object is wrapping. */
|
||||
protected final Element element;
|
||||
|
||||
/** The parent object.*/
|
||||
protected final BIElement parent;
|
||||
|
||||
private final Options opts;
|
||||
|
||||
/**
|
||||
* Gets the realization of this particle, if any.
|
||||
*
|
||||
* @return
|
||||
* null if the "collection" attribute was not specified.
|
||||
*/
|
||||
public final FieldRenderer getRealization() {
|
||||
String v = DOMUtil.getAttribute(element,"collection");
|
||||
if(v==null) return null;
|
||||
|
||||
v = v.trim();
|
||||
if(v.equals("array")) return opts.getFieldRendererFactory().getArray();
|
||||
if(v.equals("list"))
|
||||
return opts.getFieldRendererFactory().getList(
|
||||
parent.parent.codeModel.ref(ArrayList.class));
|
||||
|
||||
// the correctness of the attribute value must be
|
||||
// checked by the validator.
|
||||
throw new InternalError("unexpected collection value: "+v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the property name of this particle.
|
||||
*
|
||||
* @return
|
||||
* always a non-null, valid string.
|
||||
*/
|
||||
public final String getPropertyName() {
|
||||
String r = DOMUtil.getAttribute(element,"property");
|
||||
|
||||
// in case of <element-ref>, @property is optional and
|
||||
// defaults to @name.
|
||||
// in all other cases, @property is mandatory.
|
||||
if(r!=null) return r;
|
||||
return DOMUtil.getAttribute(element,"name");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of this property, if any.
|
||||
* <p>
|
||||
* <element-ref> particle doesn't have the type.
|
||||
*
|
||||
* @return
|
||||
* null if none is specified.
|
||||
*/
|
||||
public final JClass getType() {
|
||||
try {
|
||||
String type = DOMUtil.getAttribute(element,"supertype");
|
||||
if(type==null) return null;
|
||||
|
||||
// TODO: does this attribute defaults to the current package?
|
||||
int idx = type.lastIndexOf('.');
|
||||
if(idx<0) return parent.parent.codeModel.ref(type);
|
||||
else return parent.parent.getTargetPackage().ref(type);
|
||||
} catch( ClassNotFoundException e ) {
|
||||
// TODO: better error handling
|
||||
throw new NoClassDefFoundError(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates an appropriate subclass of BIContent
|
||||
* by sniffing the tag name.
|
||||
* <p>
|
||||
* This method should be only called by the BIElement class.
|
||||
*/
|
||||
static BIContent create( Element e, BIElement _parent ) {
|
||||
return new BIContent(e,_parent);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.dtd.bindinfo;
|
||||
|
||||
import com.sun.tools.internal.xjc.model.TypeUse;
|
||||
|
||||
/**
|
||||
* conversion declaration (<conversion> and <enumeration>).
|
||||
*/
|
||||
public interface BIConversion
|
||||
{
|
||||
/** Gets the conversion name. */
|
||||
String name();
|
||||
|
||||
/** Gets a transducer for this conversion. */
|
||||
TypeUse getTransducer();
|
||||
}
|
||||
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.dtd.bindinfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import com.sun.tools.internal.xjc.model.CClassInfo;
|
||||
import com.sun.xml.internal.bind.api.impl.NameConverter;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.xml.sax.Locator;
|
||||
|
||||
|
||||
/**
|
||||
* <element> declaration in the binding file.
|
||||
*/
|
||||
public final class BIElement
|
||||
{
|
||||
/**
|
||||
* Wraps a given <element> element in the binding file.
|
||||
*
|
||||
* <p>
|
||||
* Should be created only from {@link BindInfo}.
|
||||
*/
|
||||
BIElement( BindInfo bi, Element _e ) {
|
||||
this.parent = bi;
|
||||
this.e = _e;
|
||||
|
||||
{
|
||||
Element c = DOMUtil.getElement(e,"content");
|
||||
if(c!=null) {
|
||||
if(DOMUtil.getAttribute(c,"property")!=null) {
|
||||
// if @property is there, this is a general declaration
|
||||
this.rest = BIContent.create(c,this);
|
||||
} else {
|
||||
// this must be a model-based declaration
|
||||
for( Element p : DOMUtil.getChildElements(c) ) {
|
||||
if(p.getLocalName().equals("rest"))
|
||||
this.rest = BIContent.create(p,this);
|
||||
else
|
||||
this.contents.add(BIContent.create(p,this));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// parse <attribute>s
|
||||
for( Element atr : DOMUtil.getChildElements(e,"attribute") ) {
|
||||
BIAttribute a = new BIAttribute( this, atr );
|
||||
attributes.put(a.name(),a);
|
||||
}
|
||||
|
||||
if(isClass()) {
|
||||
// if this is a class-declaration, create JClass object now
|
||||
String className = DOMUtil.getAttribute(e,"class");
|
||||
if(className==null)
|
||||
// none was specified. infer the name.
|
||||
className = NameConverter.standard.toClassName(name());
|
||||
this.className = className;
|
||||
} else {
|
||||
// this is not an element-class declaration
|
||||
className = null;
|
||||
}
|
||||
|
||||
// process conversion declarations
|
||||
for( Element conv : DOMUtil.getChildElements(e,"conversion") ) {
|
||||
BIConversion c = new BIUserConversion(bi,conv);
|
||||
conversions.put(c.name(),c);
|
||||
}
|
||||
for( Element en : DOMUtil.getChildElements(e,"enumeration") ) {
|
||||
BIConversion c = BIEnumeration.create(en,this);
|
||||
conversions.put(c.name(),c);
|
||||
}
|
||||
|
||||
// parse <constructor>s
|
||||
for( Element c : DOMUtil.getChildElements(e,"constructor") ) {
|
||||
constructors.add( new BIConstructor(c) );
|
||||
}
|
||||
|
||||
String name = name();
|
||||
QName tagName = new QName("",name);
|
||||
|
||||
this.clazz = new CClassInfo(parent.model,parent.getTargetPackage(),className,getLocation(),null,tagName,null,null/*TODO*/);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source location where this element is declared.
|
||||
*/
|
||||
public Locator getLocation() {
|
||||
return DOMLocator.getLocationInfo(e);
|
||||
}
|
||||
|
||||
|
||||
/** The parent {@link BindInfo} object to which this object belongs. */
|
||||
final BindInfo parent;
|
||||
|
||||
/** <element> element which this object is wrapping. */
|
||||
private final Element e;
|
||||
|
||||
/**
|
||||
* The bean representation for this element.
|
||||
*/
|
||||
public final CClassInfo clazz;
|
||||
|
||||
/**
|
||||
* Content-property declarations.
|
||||
* <p>
|
||||
* This vector will be empty if no content-property declaration is made.
|
||||
*/
|
||||
private final List<BIContent> contents = new ArrayList<BIContent>();
|
||||
|
||||
/** Conversion declarations. */
|
||||
private final Map<String,BIConversion> conversions = new HashMap<String,BIConversion>();
|
||||
|
||||
/**
|
||||
* The "rest" content-property declaration.
|
||||
* <p>
|
||||
* This field is null when there was no "rest" declaration.
|
||||
*/
|
||||
private BIContent rest;
|
||||
|
||||
/** Attribute-property declarations. */
|
||||
private final Map<String,BIAttribute> attributes = new HashMap<String,BIAttribute>();
|
||||
|
||||
/** Constructor declarations. */
|
||||
private final List<BIConstructor> constructors = new ArrayList<BIConstructor>();
|
||||
|
||||
/**
|
||||
* the class which is generated by this declaration.
|
||||
* This field will be null if this declaration is an element-property
|
||||
* declaration.
|
||||
*/
|
||||
private final String className;
|
||||
|
||||
|
||||
|
||||
/** Gets the element name. */
|
||||
public String name() { return DOMUtil.getAttribute(e,"name"); }
|
||||
|
||||
/**
|
||||
* Checks if the element type is "class".
|
||||
* If false, that means this element will be a value.
|
||||
*/
|
||||
public boolean isClass() {
|
||||
return "class".equals(e.getAttribute("type"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this element is designated as a root element.
|
||||
*/
|
||||
public boolean isRoot() {
|
||||
return "true".equals(e.getAttribute("root"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the JClass object that represents this declaration.
|
||||
*
|
||||
* <p>
|
||||
* This method returns null if this declaration
|
||||
* is an element-property declaration.
|
||||
*/
|
||||
public String getClassName() {
|
||||
return className;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates constructor declarations for this element.
|
||||
*
|
||||
* <p>
|
||||
* This method should only be called by DTDReader <b>after</b>
|
||||
* the normalization has completed.
|
||||
*
|
||||
* @param src
|
||||
* The ClassItem object that corresponds to this declaration
|
||||
*/
|
||||
public void declareConstructors( CClassInfo src ) {
|
||||
for( BIConstructor c : constructors )
|
||||
c.createDeclaration(src);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the conversion method for this element.
|
||||
*
|
||||
* <p>
|
||||
* This method can be called only when this element
|
||||
* declaration is designated as element-value.
|
||||
*
|
||||
* @return
|
||||
* If the convert attribute is not specified, this
|
||||
* method returns null.
|
||||
*/
|
||||
public BIConversion getConversion() {
|
||||
String cnv = DOMUtil.getAttribute(e,"convert");
|
||||
if(cnv==null) return null;
|
||||
|
||||
return conversion(cnv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the conversion name to the conversion declaration.
|
||||
*
|
||||
* <p>
|
||||
* Element-local declarations are checked first.
|
||||
*
|
||||
* @return
|
||||
* A non-null valid BIConversion object.
|
||||
*/
|
||||
public BIConversion conversion( String name ) {
|
||||
BIConversion r = conversions.get(name);
|
||||
if(r!=null) return r;
|
||||
|
||||
// check the global conversion declarations
|
||||
return parent.conversion(name);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Iterates all content-property declarations (except 'rest').
|
||||
*/
|
||||
public List<BIContent> getContents() {
|
||||
return contents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the attribute-property declaration, if any.
|
||||
*
|
||||
* @return
|
||||
* null if attribute declaration was not given by that name.
|
||||
*/
|
||||
public BIAttribute attribute( String name ) {
|
||||
return attributes.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the 'rest' content-property declaration, if any.
|
||||
* @return
|
||||
* if there is no 'rest' declaration, return null.
|
||||
*/
|
||||
public BIContent getRest() { return this.rest; }
|
||||
|
||||
/** Gets the location where this declaration is declared. */
|
||||
public Locator getSourceLocation() {
|
||||
return DOMLocator.getLocationInfo(e);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.dtd.bindinfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import com.sun.tools.internal.xjc.model.CBuiltinLeafInfo;
|
||||
import com.sun.tools.internal.xjc.model.CClassInfoParent;
|
||||
import com.sun.tools.internal.xjc.model.CEnumConstant;
|
||||
import com.sun.tools.internal.xjc.model.CEnumLeafInfo;
|
||||
import com.sun.tools.internal.xjc.model.Model;
|
||||
import com.sun.tools.internal.xjc.model.TypeUse;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* <enumeration> declaration in the binding file.
|
||||
*/
|
||||
public final class BIEnumeration implements BIConversion
|
||||
{
|
||||
/** Creates an object from <enumeration> declaration. */
|
||||
private BIEnumeration( Element _e, TypeUse _xducer ) {
|
||||
this.e = _e;
|
||||
this.xducer = _xducer;
|
||||
}
|
||||
|
||||
/** <enumeration> element in DOM. */
|
||||
private final Element e;
|
||||
|
||||
private final TypeUse xducer;
|
||||
|
||||
public String name() { return DOMUtil.getAttribute(e,"name"); }
|
||||
|
||||
/** Returns a transducer for this enumeration declaration. */
|
||||
public TypeUse getTransducer() { return xducer; }
|
||||
|
||||
|
||||
|
||||
|
||||
/** Creates a global enumeration declaration. */
|
||||
static BIEnumeration create( Element dom, BindInfo parent ) {
|
||||
// create a class in the target package.
|
||||
return new BIEnumeration(
|
||||
dom,
|
||||
new CEnumLeafInfo(
|
||||
parent.model,
|
||||
null,
|
||||
new CClassInfoParent.Package(parent.getTargetPackage()),
|
||||
DOMUtil.getAttribute(dom,"name"),
|
||||
CBuiltinLeafInfo.STRING,
|
||||
buildMemberList(parent.model,dom),
|
||||
null, null/*TODO*/,
|
||||
DOMLocator.getLocationInfo(dom)));
|
||||
}
|
||||
|
||||
/** Creates an element-local enumeration declaration. */
|
||||
static BIEnumeration create( Element dom, BIElement parent ) {
|
||||
// create a class as a nested class
|
||||
return new BIEnumeration(
|
||||
dom,
|
||||
new CEnumLeafInfo(
|
||||
parent.parent.model,
|
||||
null,
|
||||
parent.clazz,
|
||||
DOMUtil.getAttribute(dom,"name"),
|
||||
CBuiltinLeafInfo.STRING,
|
||||
buildMemberList(parent.parent.model,dom),
|
||||
null, null/*TODO*/,
|
||||
DOMLocator.getLocationInfo(dom) ));
|
||||
}
|
||||
|
||||
private static List<CEnumConstant> buildMemberList( Model model, Element dom ) {
|
||||
List<CEnumConstant> r = new ArrayList<CEnumConstant>();
|
||||
|
||||
String members = DOMUtil.getAttribute(dom,"members");
|
||||
if(members==null) members=""; // TODO: error handling
|
||||
|
||||
StringTokenizer tokens = new StringTokenizer(members);
|
||||
while(tokens.hasMoreTokens()) {
|
||||
String token = tokens.nextToken();
|
||||
r.add(new CEnumConstant(model.getNameConverter().toConstantName(token),
|
||||
null,token,null/*TODO*/,null,null));
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.dtd.bindinfo;
|
||||
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.xml.sax.Locator;
|
||||
|
||||
/**
|
||||
* <interface> declaration in the binding file.
|
||||
*/
|
||||
public final class BIInterface
|
||||
{
|
||||
BIInterface( Element e ) {
|
||||
this.dom = e;
|
||||
name = DOMUtil.getAttribute(e,"name");
|
||||
members = parseTokens(DOMUtil.getAttribute(e,"members"));
|
||||
|
||||
if(DOMUtil.getAttribute(e,"properties")!=null) {
|
||||
fields = parseTokens(DOMUtil.getAttribute(e,"properties"));
|
||||
throw new AssertionError("//interface/@properties is not supported");
|
||||
} else // no property was specified
|
||||
fields = new String[0];
|
||||
}
|
||||
|
||||
/** <interface> element in the binding file. */
|
||||
private final Element dom;
|
||||
|
||||
/** Name of the generated Java interface. */
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* Gets the name of this interface.
|
||||
* This name should also used as the class name.
|
||||
*/
|
||||
public String name() { return name; }
|
||||
|
||||
|
||||
private final String[] members;
|
||||
|
||||
/**
|
||||
* Gets the names of interfaces/classes that implement
|
||||
* this interface.
|
||||
*/
|
||||
public String[] members() { return members; }
|
||||
|
||||
|
||||
private final String[] fields;
|
||||
|
||||
/** Gets the names of fields in this interface. */
|
||||
public String[] fields() { return fields; }
|
||||
|
||||
|
||||
/** Gets the location where this declaration is declared. */
|
||||
public Locator getSourceLocation() {
|
||||
return DOMLocator.getLocationInfo(dom);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** splits a list into an array of strings. */
|
||||
private static String[] parseTokens( String value ) {
|
||||
StringTokenizer tokens = new StringTokenizer(value);
|
||||
|
||||
String[] r = new String[tokens.countTokens()];
|
||||
int i=0;
|
||||
while(tokens.hasMoreTokens())
|
||||
r[i++] = tokens.nextToken();
|
||||
|
||||
return r;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.dtd.bindinfo;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.bind.annotation.adapters.XmlAdapter;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import com.sun.codemodel.internal.JClass;
|
||||
import com.sun.codemodel.internal.JClassAlreadyExistsException;
|
||||
import com.sun.codemodel.internal.JCodeModel;
|
||||
import com.sun.codemodel.internal.JDefinedClass;
|
||||
import com.sun.codemodel.internal.JExpr;
|
||||
import com.sun.codemodel.internal.JExpression;
|
||||
import com.sun.codemodel.internal.JMethod;
|
||||
import com.sun.codemodel.internal.JMod;
|
||||
import com.sun.codemodel.internal.JPackage;
|
||||
import com.sun.codemodel.internal.JPrimitiveType;
|
||||
import com.sun.codemodel.internal.JType;
|
||||
import com.sun.codemodel.internal.JVar;
|
||||
import com.sun.tools.internal.xjc.model.CAdapter;
|
||||
import com.sun.tools.internal.xjc.model.CBuiltinLeafInfo;
|
||||
import com.sun.tools.internal.xjc.model.TypeUse;
|
||||
import com.sun.tools.internal.xjc.model.TypeUseFactory;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.util.XmlFactory;
|
||||
import org.w3c.dom.Element;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.Locator;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* <conversion> declaration in the binding file.
|
||||
* This declaration declares a conversion by user-specified methods.
|
||||
*/
|
||||
public class BIUserConversion implements BIConversion
|
||||
{
|
||||
/**
|
||||
* Wraps a given <conversion> element in the binding file.
|
||||
*/
|
||||
BIUserConversion( BindInfo bi, Element _e ) {
|
||||
this.owner = bi;
|
||||
this.e = _e;
|
||||
}
|
||||
|
||||
private static void add( Map<String,BIConversion> m, BIConversion c ) {
|
||||
m.put( c.name(), c );
|
||||
}
|
||||
|
||||
/** Adds all built-in conversions into the given map. */
|
||||
static void addBuiltinConversions( BindInfo bi, Map<String,BIConversion> m ) {
|
||||
add( m, new BIUserConversion( bi, parse("<conversion name='boolean' type='java.lang.Boolean' parse='getBoolean' />")));
|
||||
add( m, new BIUserConversion( bi, parse("<conversion name='byte' type='java.lang.Byte' parse='parseByte' />")));
|
||||
add( m, new BIUserConversion( bi, parse("<conversion name='short' type='java.lang.Short' parse='parseShort' />")));
|
||||
add( m, new BIUserConversion( bi, parse("<conversion name='int' type='java.lang.Integer' parse='parseInt' />")));
|
||||
add( m, new BIUserConversion( bi, parse("<conversion name='long' type='java.lang.Long' parse='parseLong' />")));
|
||||
add( m, new BIUserConversion( bi, parse("<conversion name='float' type='java.lang.Float' parse='parseFloat' />")));
|
||||
add( m, new BIUserConversion( bi, parse("<conversion name='double' type='java.lang.Double' parse='parseDouble' />")));
|
||||
}
|
||||
|
||||
private static Element parse(String text) {
|
||||
try {
|
||||
//this is parsing well known schemas, do not configure secure processing - always true
|
||||
DocumentBuilderFactory dbf = XmlFactory.createDocumentBuilderFactory(false);
|
||||
InputSource is = new InputSource(new StringReader(text));
|
||||
return dbf.newDocumentBuilder().parse(is).getDocumentElement();
|
||||
} catch (SAXException x) {
|
||||
throw new Error(x);
|
||||
} catch (IOException x) {
|
||||
throw new Error(x);
|
||||
} catch (ParserConfigurationException x) {
|
||||
throw new Error(x);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** The owner {@link BindInfo} object to which this object belongs. */
|
||||
private final BindInfo owner;
|
||||
|
||||
/** <conversion> element which this object is wrapping. */
|
||||
private final Element e;
|
||||
|
||||
|
||||
|
||||
/** Gets the location where this declaration is declared. */
|
||||
public Locator getSourceLocation() {
|
||||
return DOMLocator.getLocationInfo(e);
|
||||
}
|
||||
|
||||
/** Gets the conversion name. */
|
||||
public String name() { return DOMUtil.getAttribute(e,"name"); }
|
||||
|
||||
/** Gets a transducer for this conversion. */
|
||||
public TypeUse getTransducer() {
|
||||
|
||||
String ws = DOMUtil.getAttribute(e,"whitespace");
|
||||
if(ws==null) ws = "collapse";
|
||||
|
||||
String type = DOMUtil.getAttribute(e,"type");
|
||||
if(type==null) type=name();
|
||||
JType t=null;
|
||||
|
||||
int idx = type.lastIndexOf('.');
|
||||
if(idx<0) {
|
||||
// no package name is specified.
|
||||
try {
|
||||
t = JPrimitiveType.parse(owner.codeModel,type);
|
||||
} catch( IllegalArgumentException ex ) {
|
||||
// otherwise treat it as a class name in the current package
|
||||
type = owner.getTargetPackage().name()+'.'+type;
|
||||
}
|
||||
}
|
||||
if(t==null) {
|
||||
try {
|
||||
// TODO: revisit this later
|
||||
JDefinedClass cls = owner.codeModel._class(type);
|
||||
cls.hide();
|
||||
t = cls;
|
||||
} catch( JClassAlreadyExistsException ex ) {
|
||||
t = ex.getExistingClass();
|
||||
}
|
||||
}
|
||||
|
||||
String parse = DOMUtil.getAttribute(e,"parse");
|
||||
if(parse==null) parse="new";
|
||||
|
||||
String print = DOMUtil.getAttribute(e,"print");
|
||||
if(print==null) print="toString";
|
||||
|
||||
JDefinedClass adapter = generateAdapter(owner.codeModel, parse, print, t.boxify());
|
||||
|
||||
// XmlJavaType customization always converts between string and an user-defined type.
|
||||
return TypeUseFactory.adapt(CBuiltinLeafInfo.STRING,new CAdapter(adapter));
|
||||
}
|
||||
|
||||
// TODO: anyway to reuse this code between XML Schema compiler?
|
||||
private JDefinedClass generateAdapter(JCodeModel cm, String parseMethod, String printMethod, JClass inMemoryType) {
|
||||
JDefinedClass adapter = null;
|
||||
|
||||
int id = 1;
|
||||
while(adapter==null) {
|
||||
try {
|
||||
JPackage pkg = owner.getTargetPackage();
|
||||
adapter = pkg._class("Adapter"+id);
|
||||
} catch (JClassAlreadyExistsException ex) {
|
||||
// try another name in search for an unique name.
|
||||
// this isn't too efficient, but we expect people to usually use
|
||||
// a very small number of adapters.
|
||||
id++;
|
||||
}
|
||||
}
|
||||
|
||||
adapter._extends(cm.ref(XmlAdapter.class).narrow(String.class).narrow(inMemoryType));
|
||||
|
||||
JMethod unmarshal = adapter.method(JMod.PUBLIC, inMemoryType, "unmarshal");
|
||||
JVar $value = unmarshal.param(String.class, "value");
|
||||
|
||||
JExpression inv;
|
||||
|
||||
if( parseMethod.equals("new") ) {
|
||||
// "new" indicates that the constructor of the target type
|
||||
// will do the unmarshalling.
|
||||
|
||||
// RESULT: new <type>()
|
||||
inv = JExpr._new(inMemoryType).arg($value);
|
||||
} else {
|
||||
int idx = parseMethod.lastIndexOf('.');
|
||||
if(idx<0) {
|
||||
// parseMethod specifies the static method of the target type
|
||||
// which will do the unmarshalling.
|
||||
|
||||
// because of an error check at the constructor,
|
||||
// we can safely assume that this cast works.
|
||||
inv = inMemoryType.staticInvoke(parseMethod).arg($value);
|
||||
} else {
|
||||
inv = JExpr.direct(parseMethod+"(value)");
|
||||
}
|
||||
}
|
||||
unmarshal.body()._return(inv);
|
||||
|
||||
|
||||
JMethod marshal = adapter.method(JMod.PUBLIC, String.class, "marshal");
|
||||
$value = marshal.param(inMemoryType,"value");
|
||||
|
||||
int idx = printMethod.lastIndexOf('.');
|
||||
if(idx<0) {
|
||||
// printMethod specifies a method in the target type
|
||||
// which performs the serialization.
|
||||
|
||||
// RESULT: <value>.<method>()
|
||||
inv = $value.invoke(printMethod);
|
||||
} else {
|
||||
// RESULT: <className>.<method>(<value>)
|
||||
inv = JExpr.direct(printMethod+"(value)");
|
||||
}
|
||||
marshal.body()._return(inv);
|
||||
|
||||
return adapter;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,334 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.dtd.bindinfo;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
import javax.xml.validation.ValidatorHandler;
|
||||
|
||||
import com.sun.codemodel.internal.ClassType;
|
||||
import com.sun.codemodel.internal.JClass;
|
||||
import com.sun.codemodel.internal.JClassAlreadyExistsException;
|
||||
import com.sun.codemodel.internal.JCodeModel;
|
||||
import com.sun.codemodel.internal.JDefinedClass;
|
||||
import com.sun.codemodel.internal.JPackage;
|
||||
import com.sun.istack.internal.SAXParseException2;
|
||||
import com.sun.tools.internal.xjc.AbortException;
|
||||
import com.sun.tools.internal.xjc.ErrorReceiver;
|
||||
import com.sun.tools.internal.xjc.SchemaCache;
|
||||
import com.sun.tools.internal.xjc.model.CCustomizations;
|
||||
import com.sun.tools.internal.xjc.model.CPluginCustomization;
|
||||
import com.sun.tools.internal.xjc.model.Model;
|
||||
import com.sun.tools.internal.xjc.reader.Const;
|
||||
import com.sun.tools.internal.xjc.util.CodeModelClassFactory;
|
||||
import com.sun.tools.internal.xjc.util.ErrorReceiverFilter;
|
||||
import com.sun.tools.internal.xjc.util.ForkContentHandler;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.util.XmlFactory;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
|
||||
/**
|
||||
* Root of the binding information.
|
||||
*/
|
||||
public class BindInfo
|
||||
{
|
||||
/** Controller object that can be used to report errors. */
|
||||
protected final ErrorReceiver errorReceiver;
|
||||
|
||||
/*package*/ final Model model;
|
||||
|
||||
/**
|
||||
* The -p option that should control the default Java package that
|
||||
* will contain the generated code. Null if unspecified. This takes
|
||||
* precedence over the value specified in the binding file.
|
||||
*/
|
||||
private final String defaultPackage;
|
||||
|
||||
public BindInfo(Model model, InputSource source, ErrorReceiver _errorReceiver) throws AbortException {
|
||||
this( model, parse(model,source,_errorReceiver), _errorReceiver);
|
||||
}
|
||||
|
||||
public BindInfo(Model model, Document _dom, ErrorReceiver _errorReceiver) {
|
||||
this.model = model;
|
||||
this.dom = _dom.getDocumentElement();
|
||||
this.codeModel = model.codeModel;
|
||||
this.errorReceiver = _errorReceiver;
|
||||
this.classFactory = new CodeModelClassFactory(_errorReceiver);
|
||||
// TODO: decide name converter from the binding file
|
||||
|
||||
this.defaultPackage = model.options.defaultPackage;
|
||||
|
||||
// copy global customizations to the model
|
||||
model.getCustomizations().addAll(getGlobalCustomizations());
|
||||
|
||||
// process element declarations
|
||||
for( Element ele : DOMUtil.getChildElements(dom,"element")) {
|
||||
BIElement e = new BIElement(this,ele);
|
||||
elements.put(e.name(),e);
|
||||
}
|
||||
|
||||
// add built-in conversions
|
||||
BIUserConversion.addBuiltinConversions(this,conversions);
|
||||
|
||||
// process conversion declarations
|
||||
for( Element cnv : DOMUtil.getChildElements(dom,"conversion")) {
|
||||
BIConversion c = new BIUserConversion(this,cnv);
|
||||
conversions.put(c.name(),c);
|
||||
}
|
||||
for( Element en : DOMUtil.getChildElements(dom,"enumeration")) {
|
||||
BIConversion c = BIEnumeration.create( en, this );
|
||||
conversions.put(c.name(),c);
|
||||
}
|
||||
// TODO: check the uniquness of conversion name
|
||||
|
||||
|
||||
// process interface definitions
|
||||
for( Element itf : DOMUtil.getChildElements(dom,"interface")) {
|
||||
BIInterface c = new BIInterface(itf);
|
||||
interfaces.put(c.name(),c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** CodeModel object that is used by this binding file. */
|
||||
final JCodeModel codeModel;
|
||||
|
||||
/** Wrap the codeModel object and automate error reporting. */
|
||||
final CodeModelClassFactory classFactory;
|
||||
|
||||
/** DOM tree that represents binding info. */
|
||||
private final Element dom;
|
||||
|
||||
/** Conversion declarations. */
|
||||
private final Map<String,BIConversion> conversions = new HashMap<String,BIConversion>();
|
||||
|
||||
/** Element declarations keyed by names. */
|
||||
private final Map<String,BIElement> elements = new HashMap<String,BIElement>();
|
||||
|
||||
/** interface declarations keyed by names. */
|
||||
private final Map<String,BIInterface> interfaces = new HashMap<String,BIInterface>();
|
||||
|
||||
|
||||
/** XJC extension namespace. */
|
||||
private static final String XJC_NS = Const.XJC_EXTENSION_URI;
|
||||
|
||||
//
|
||||
//
|
||||
// Exposed public methods
|
||||
//
|
||||
//
|
||||
/** Gets the serialVersionUID if it's turned on. */
|
||||
public Long getSerialVersionUID() {
|
||||
Element serial = DOMUtil.getElement(dom,XJC_NS,"serializable");
|
||||
if(serial==null) return null;
|
||||
|
||||
String v = DOMUtil.getAttribute(serial,"uid");
|
||||
if(v==null) v="1";
|
||||
return new Long(v);
|
||||
}
|
||||
|
||||
/** Gets the xjc:superClass customization if it's turned on. */
|
||||
public JClass getSuperClass() {
|
||||
Element sc = DOMUtil.getElement(dom,XJC_NS,"superClass");
|
||||
if (sc == null) return null;
|
||||
|
||||
JDefinedClass c;
|
||||
|
||||
try {
|
||||
String v = DOMUtil.getAttribute(sc,"name");
|
||||
if(v==null) return null;
|
||||
c = codeModel._class(v);
|
||||
c.hide();
|
||||
} catch (JClassAlreadyExistsException e) {
|
||||
c = e.getExistingClass();
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/** Gets the xjc:superInterface customization if it's turned on. */
|
||||
public JClass getSuperInterface() {
|
||||
Element sc = DOMUtil.getElement(dom,XJC_NS,"superInterface");
|
||||
if (sc == null) return null;
|
||||
|
||||
String name = DOMUtil.getAttribute(sc,"name");
|
||||
if (name == null) return null;
|
||||
|
||||
JDefinedClass c;
|
||||
|
||||
try {
|
||||
c = codeModel._class(name, ClassType.INTERFACE);
|
||||
c.hide();
|
||||
} catch (JClassAlreadyExistsException e) {
|
||||
c = e.getExistingClass();
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the specified package name (options/@package).
|
||||
*/
|
||||
public JPackage getTargetPackage() {
|
||||
if(model.options.defaultPackage!=null)
|
||||
// "-p" takes precedence over everything else
|
||||
return codeModel._package(model.options.defaultPackage);
|
||||
|
||||
String p;
|
||||
if( defaultPackage!=null )
|
||||
p = defaultPackage;
|
||||
else
|
||||
p = getOption("package", "");
|
||||
return codeModel._package(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the conversion declaration from the binding info.
|
||||
*
|
||||
* @return
|
||||
* A non-null valid BIConversion object.
|
||||
*/
|
||||
public BIConversion conversion(String name) {
|
||||
BIConversion r = conversions.get(name);
|
||||
if (r == null)
|
||||
throw new AssertionError("undefined conversion name: this should be checked by the validator before we read it");
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the element declaration from the binding info.
|
||||
*
|
||||
* @return
|
||||
* If there is no declaration with a given name,
|
||||
* this method returns null.
|
||||
*/
|
||||
public BIElement element( String name ) {
|
||||
return elements.get(name);
|
||||
}
|
||||
/** Iterates all {@link BIElement}s in a read-only set. */
|
||||
public Collection<BIElement> elements() {
|
||||
return elements.values();
|
||||
}
|
||||
|
||||
/** Returns all {@link BIInterface}s in a read-only set. */
|
||||
public Collection<BIInterface> interfaces() {
|
||||
return interfaces.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of top-level {@link CPluginCustomization}s.
|
||||
*/
|
||||
private CCustomizations getGlobalCustomizations() {
|
||||
CCustomizations r=null;
|
||||
for( Element e : DOMUtil.getChildElements(dom) ) {
|
||||
if(!model.options.pluginURIs.contains(e.getNamespaceURI()))
|
||||
continue; // this isn't a plugin customization
|
||||
if(r==null)
|
||||
r = new CCustomizations();
|
||||
r.add(new CPluginCustomization(e, DOMLocator.getLocationInfo(e)));
|
||||
}
|
||||
|
||||
if(r==null) r = CCustomizations.EMPTY;
|
||||
return new CCustomizations(r);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
// Internal utility methods
|
||||
//
|
||||
//
|
||||
|
||||
|
||||
/** Gets the value from the option element. */
|
||||
private String getOption(String attName, String defaultValue) {
|
||||
Element opt = DOMUtil.getElement(dom,"options");
|
||||
if (opt != null) {
|
||||
String s = DOMUtil.getAttribute(opt,attName);
|
||||
if (s != null)
|
||||
return s;
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazily parsed schema for the binding file.
|
||||
*/
|
||||
private static SchemaCache bindingFileSchema = new SchemaCache(BindInfo.class.getResource("bindingfile.xsd"));
|
||||
|
||||
/**
|
||||
* Parses an InputSource into dom4j Document.
|
||||
* Returns null in case of an exception.
|
||||
*/
|
||||
private static Document parse( Model model, InputSource is, ErrorReceiver receiver ) throws AbortException {
|
||||
try {
|
||||
ValidatorHandler validator = bindingFileSchema.newValidator();
|
||||
|
||||
// set up the pipe line as :
|
||||
// /-> extensionChecker -> validator
|
||||
// parser-> -<
|
||||
// \-> DOM builder
|
||||
SAXParserFactory pf = XmlFactory.createParserFactory(model.options.disableXmlSecurity);
|
||||
DocumentBuilderFactory domFactory = XmlFactory.createDocumentBuilderFactory(model.options.disableXmlSecurity);
|
||||
DOMBuilder builder = new DOMBuilder(domFactory);
|
||||
|
||||
ErrorReceiverFilter controller = new ErrorReceiverFilter(receiver);
|
||||
validator.setErrorHandler(controller);
|
||||
XMLReader reader = pf.newSAXParser().getXMLReader();
|
||||
reader.setErrorHandler(controller);
|
||||
|
||||
DTDExtensionBindingChecker checker = new DTDExtensionBindingChecker("", model.options, controller);
|
||||
checker.setContentHandler(validator);
|
||||
|
||||
reader.setContentHandler(new ForkContentHandler(checker,builder));
|
||||
|
||||
reader.parse(is);
|
||||
|
||||
if(controller.hadError()) throw new AbortException();
|
||||
return (Document)builder.getDOM();
|
||||
} catch( IOException e ) {
|
||||
receiver.error( new SAXParseException2(e.getMessage(),null,e) );
|
||||
} catch( SAXException e ) {
|
||||
receiver.error( new SAXParseException2(e.getMessage(),null,e) );
|
||||
} catch( ParserConfigurationException e ) {
|
||||
receiver.error( new SAXParseException2(e.getMessage(),null,e) );
|
||||
}
|
||||
|
||||
throw new AbortException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.dtd.bindinfo;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import com.sun.xml.internal.bind.marshaller.SAX2DOMEx;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.Locator;
|
||||
|
||||
/**
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class DOMBuilder extends SAX2DOMEx {
|
||||
private Locator locator;
|
||||
|
||||
public DOMBuilder(DocumentBuilderFactory f) throws ParserConfigurationException {
|
||||
super(f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDocumentLocator(Locator locator) {
|
||||
super.setDocumentLocator(locator);
|
||||
this.locator = locator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement(String namespace, String localName, String qName, Attributes attrs) {
|
||||
super.startElement(namespace, localName, qName, attrs);
|
||||
DOMLocator.setLocationInfo(getCurrentElement(),locator);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.dtd.bindinfo;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.xml.sax.Locator;
|
||||
|
||||
class DOMLocator {
|
||||
private static final String locationNamespace =
|
||||
"http://www.sun.com/xmlns/jaxb/dom-location";
|
||||
private static final String systemId = "systemid";
|
||||
private static final String column = "column";
|
||||
private static final String line = "line";
|
||||
|
||||
/** Sets the location information to a specified element. */
|
||||
public static void setLocationInfo( Element e, Locator loc ) {
|
||||
e.setAttributeNS(locationNamespace,"loc:"+systemId,loc.getSystemId());
|
||||
e.setAttributeNS(locationNamespace,"loc:"+column,Integer.toString(loc.getLineNumber()));
|
||||
e.setAttributeNS(locationNamespace,"loc:"+line,Integer.toString(loc.getColumnNumber()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the location information from an element.
|
||||
*
|
||||
* <p>
|
||||
* For this method to work, the setLocationInfo method has to be
|
||||
* called before.
|
||||
*/
|
||||
public static Locator getLocationInfo( final Element e ) {
|
||||
if(DOMUtil.getAttribute(e,locationNamespace,systemId)==null)
|
||||
return null; // no location information
|
||||
|
||||
return new Locator(){
|
||||
public int getLineNumber() {
|
||||
return Integer.parseInt(DOMUtil.getAttribute(e,locationNamespace,line));
|
||||
}
|
||||
public int getColumnNumber() {
|
||||
return Integer.parseInt(DOMUtil.getAttribute(e,locationNamespace,column));
|
||||
}
|
||||
public String getSystemId() {
|
||||
return DOMUtil.getAttribute(e,locationNamespace,systemId);
|
||||
}
|
||||
// we are not interested in PUBLIC ID.
|
||||
public String getPublicId() { return null; }
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.dtd.bindinfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
/**
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class DOMUtil {
|
||||
final static String getAttribute(Element e,String attName) {
|
||||
if(e.getAttributeNode(attName)==null) return null;
|
||||
return e.getAttribute(attName);
|
||||
}
|
||||
|
||||
public static String getAttribute(Element e, String nsUri, String local) {
|
||||
if(e.getAttributeNodeNS(nsUri,local)==null) return null;
|
||||
return e.getAttributeNS(nsUri,local);
|
||||
}
|
||||
|
||||
public static Element getElement(Element e, String nsUri, String localName) {
|
||||
NodeList l = e.getChildNodes();
|
||||
for(int i=0;i<l.getLength();i++) {
|
||||
Node n = l.item(i);
|
||||
if(n.getNodeType()==Node.ELEMENT_NODE) {
|
||||
Element r = (Element)n;
|
||||
if(equals(r.getLocalName(),localName) && equals(fixNull(r.getNamespaceURI()),nsUri))
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for defensive string comparisons, as many DOM methods often return null
|
||||
* depending on how they are created.
|
||||
*/
|
||||
private static boolean equals(String a,String b) {
|
||||
if(a==b) return true;
|
||||
if(a==null || b==null) return false;
|
||||
return a.equals(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* DOM API returns null for the default namespace whereas it should return "".
|
||||
*/
|
||||
private static String fixNull(String s) {
|
||||
if(s==null) return "";
|
||||
else return s;
|
||||
}
|
||||
|
||||
public static Element getElement(Element e, String localName) {
|
||||
return getElement(e,"",localName);
|
||||
}
|
||||
|
||||
public static List<Element> getChildElements(Element e) {
|
||||
List<Element> r = new ArrayList<Element>();
|
||||
NodeList l = e.getChildNodes();
|
||||
for(int i=0;i<l.getLength();i++) {
|
||||
Node n = l.item(i);
|
||||
if(n.getNodeType()==Node.ELEMENT_NODE)
|
||||
r.add((Element)n);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
public static List<Element> getChildElements(Element e,String localName) {
|
||||
List<Element> r = new ArrayList<Element>();
|
||||
NodeList l = e.getChildNodes();
|
||||
for(int i=0;i<l.getLength();i++) {
|
||||
Node n = l.item(i);
|
||||
if(n.getNodeType()==Node.ELEMENT_NODE) {
|
||||
Element c = (Element)n;
|
||||
if(c.getLocalName().equals(localName))
|
||||
r.add(c);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.dtd.bindinfo;
|
||||
|
||||
import com.sun.tools.internal.xjc.Options;
|
||||
import com.sun.tools.internal.xjc.reader.AbstractExtensionBindingChecker;
|
||||
import com.sun.tools.internal.xjc.reader.Const;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.ErrorHandler;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLFilter;
|
||||
|
||||
/**
|
||||
* {@link XMLFilter} that checks the use of extension namespace URIs
|
||||
* (to see if they have corresponding plugins), and otherwise report an error.
|
||||
*
|
||||
* <p>
|
||||
* This code also masks the recognized extensions from the validator that
|
||||
* will be plugged as the next component to this.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class DTDExtensionBindingChecker extends AbstractExtensionBindingChecker {
|
||||
public DTDExtensionBindingChecker(String schemaLanguage, Options options, ErrorHandler handler) {
|
||||
super(schemaLanguage, options, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the elements with the given namespace URI
|
||||
* should be blocked by this filter.
|
||||
*/
|
||||
private boolean needsToBePruned( String uri ) {
|
||||
if( uri.equals(schemaLanguage) )
|
||||
return false;
|
||||
if( uri.equals(Const.JAXB_NSURI) )
|
||||
return false;
|
||||
if( uri.equals(Const.XJC_EXTENSION_URI) )
|
||||
return false;
|
||||
// we don't want validator to see extensions that we understand ,
|
||||
// because they will complain.
|
||||
// OTOH, if this is an extension that we didn't understand,
|
||||
// we want the validator to report an error
|
||||
return enabledExtensions.contains(uri);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void startElement(String uri, String localName, String qName, Attributes atts)
|
||||
throws SAXException {
|
||||
|
||||
if( !isCutting() ) {
|
||||
if(!uri.equals("")) {
|
||||
// "" is the standard namespace
|
||||
checkAndEnable(uri);
|
||||
|
||||
verifyTagName(uri, localName, qName);
|
||||
|
||||
if(needsToBePruned(uri))
|
||||
startCutting();
|
||||
}
|
||||
}
|
||||
|
||||
super.startElement(uri, localName, qName, atts);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.dtd.bindinfo;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
/**
|
||||
* Formats error messages.
|
||||
*/
|
||||
class Messages
|
||||
{
|
||||
/** Loads a string resource and formats it with specified arguments. */
|
||||
static String format( String property, Object... args ) {
|
||||
String text = ResourceBundle.getBundle(Messages.class.getPackage().getName() + ".MessageBundle").getString(property);
|
||||
return MessageFormat.format(text,args);
|
||||
}
|
||||
|
||||
|
||||
static final String ERR_UNDEFINED_FIELD = // arg:1
|
||||
"BIConstructor.UndefinedField";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.gbind;
|
||||
|
||||
/**
|
||||
* {@link Expression} that represents the union of two expressions "A|B".
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class Choice extends Expression {
|
||||
/**
|
||||
* "A" of "A|B".
|
||||
*/
|
||||
private final Expression lhs;
|
||||
/**
|
||||
* "B" of "A|B".
|
||||
*/
|
||||
private final Expression rhs;
|
||||
/**
|
||||
* Compute this value eagerly for better performance
|
||||
*/
|
||||
private final boolean isNullable;
|
||||
|
||||
public Choice(Expression lhs, Expression rhs) {
|
||||
this.lhs = lhs;
|
||||
this.rhs = rhs;
|
||||
this.isNullable = lhs.isNullable() || rhs.isNullable();
|
||||
}
|
||||
|
||||
boolean isNullable() {
|
||||
return isNullable;
|
||||
}
|
||||
|
||||
ElementSet lastSet() {
|
||||
return ElementSets.union(lhs.lastSet(),rhs.lastSet());
|
||||
}
|
||||
|
||||
void buildDAG(ElementSet incoming) {
|
||||
lhs.buildDAG(incoming);
|
||||
rhs.buildDAG(incoming);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return '('+lhs.toString()+'|'+rhs.toString()+')';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.gbind;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents one strongly-connected component
|
||||
* of the {@link Element} graph.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class ConnectedComponent implements Iterable<Element> {
|
||||
/**
|
||||
* {@link Element}s that belong to this component.
|
||||
*/
|
||||
private final List<Element> elements = new ArrayList<Element>();
|
||||
|
||||
/*package*/ boolean isRequired;
|
||||
|
||||
/**
|
||||
* Returns true iff this {@link ConnectedComponent}
|
||||
* can match a substring whose length is greater than 1.
|
||||
*
|
||||
* <p>
|
||||
* That means this property will become a collection property.
|
||||
*/
|
||||
public final boolean isCollection() {
|
||||
assert !elements.isEmpty();
|
||||
|
||||
// a strongly connected component by definition has a cycle,
|
||||
// so if its size is bigger than 1 there must be a cycle.
|
||||
if(elements.size()>1)
|
||||
return true;
|
||||
|
||||
// if size is 1, it might be still forming a self-cycle
|
||||
Element n = elements.get(0);
|
||||
return n.hasSelfLoop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true iff this {@link ConnectedComponent}
|
||||
* forms a cut set of a graph.
|
||||
*
|
||||
* <p>
|
||||
* That means any valid element sequence must have at least
|
||||
* one value for this property.
|
||||
*/
|
||||
public final boolean isRequired() {
|
||||
return isRequired;
|
||||
}
|
||||
|
||||
/*package*/void add(Element e) {
|
||||
assert !elements.contains(e);
|
||||
elements.add(e);
|
||||
}
|
||||
|
||||
public Iterator<Element> iterator() {
|
||||
return elements.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Just produces debug representation
|
||||
*/
|
||||
public String toString() {
|
||||
String s = elements.toString();
|
||||
if(isRequired())
|
||||
s += '!';
|
||||
if(isCollection())
|
||||
s += '*';
|
||||
return s;
|
||||
}
|
||||
}
|
||||
228
jdkSrc/jdk8/com/sun/tools/internal/xjc/reader/gbind/Element.java
Normal file
228
jdkSrc/jdk8/com/sun/tools/internal/xjc/reader/gbind/Element.java
Normal file
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.gbind;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* {@link Expression} that represents an alphabet of a regular language.
|
||||
*
|
||||
* <p>
|
||||
* Since this package is about a regular expression over element declarations,
|
||||
* this represents an XML element declaration (hence the name.)
|
||||
*
|
||||
* Element needs to be interned, meaning one {@link Element} per one tag name.
|
||||
*
|
||||
* <p>
|
||||
* Implements {@link ElementSet} to represent a self.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public abstract class Element extends Expression implements ElementSet {
|
||||
/**
|
||||
* Once we build a graph from {@link Expression},
|
||||
* we represent an edge e1 -> e2 by {@code e1.foreEdges.contains(e2)}
|
||||
* and {@code e2.backEdges.contains(e1)}.
|
||||
*/
|
||||
final Set<Element> foreEdges = new LinkedHashSet<Element>();
|
||||
final Set<Element> backEdges = new LinkedHashSet<Element>();
|
||||
|
||||
/**
|
||||
* Previous element in the DFS post-order traveral
|
||||
* of the element graph.
|
||||
*
|
||||
* <p>
|
||||
* We use {@code prevPostOrder==null} as a check if the element is visted in DFS,
|
||||
* so this chain terminates by a self-reference, not by having null.
|
||||
*
|
||||
* Set in {@link #assignDfsPostOrder(Element)}
|
||||
*/
|
||||
/*package*/ Element prevPostOrder;
|
||||
|
||||
/**
|
||||
* {@link ConnectedComponent} to which this element belongs.
|
||||
*
|
||||
* Set in {@link #buildStronglyConnectedComponents(List<ConnectedComponent>)}
|
||||
*/
|
||||
private ConnectedComponent cc;
|
||||
|
||||
protected Element() {
|
||||
}
|
||||
|
||||
ElementSet lastSet() {
|
||||
return this;
|
||||
}
|
||||
|
||||
boolean isNullable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* True if this {@link Element} is {@link SourceNode}.
|
||||
*/
|
||||
boolean isSource() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* True if this {@link Element} is {@link SinkNode}.
|
||||
*/
|
||||
boolean isSink() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void buildDAG(ElementSet incoming) {
|
||||
incoming.addNext(this);
|
||||
}
|
||||
|
||||
public void addNext(Element element) {
|
||||
foreEdges.add(element);
|
||||
element.backEdges.add(this);
|
||||
}
|
||||
|
||||
public boolean contains(ElementSet rhs) {
|
||||
return this==rhs || rhs==ElementSet.EMPTY_SET;
|
||||
}
|
||||
|
||||
/**
|
||||
* Just to satisfy the {@link ElementSet} contract.
|
||||
*
|
||||
* @deprecated
|
||||
* if you statically call this method, there's something wrong.
|
||||
*/
|
||||
public Iterator<Element> iterator() {
|
||||
return Collections.singleton(this).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverses the {@link Element} graph with DFS
|
||||
* and set {@link #prevPostOrder}.
|
||||
*
|
||||
* Should be first invoked on the source node of the graph.
|
||||
*/
|
||||
/*package*/ Element assignDfsPostOrder(Element prev) {
|
||||
if(prevPostOrder!=null)
|
||||
return prev; // already visited
|
||||
|
||||
prevPostOrder = this; // set a dummy value to prepare for cycles
|
||||
|
||||
for (Element next : foreEdges) {
|
||||
prev = next.assignDfsPostOrder(prev);
|
||||
}
|
||||
this.prevPostOrder = prev; // set to the real value
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a set of strongly connected components and puts them
|
||||
* all into the given set.
|
||||
*/
|
||||
public void buildStronglyConnectedComponents(List<ConnectedComponent> ccs) {
|
||||
|
||||
// store visited elements - loop detection
|
||||
List<Element> visitedElements = new ArrayList<Element>();
|
||||
|
||||
for(Element cur=this; cur!=cur.prevPostOrder; cur=cur.prevPostOrder) {
|
||||
|
||||
if(visitedElements.contains(cur)) {
|
||||
// if I've already processed cur element, I'm in a loop
|
||||
break;
|
||||
} else {
|
||||
visitedElements.add(cur);
|
||||
}
|
||||
|
||||
if(cur.belongsToSCC())
|
||||
continue;
|
||||
|
||||
// start a new component
|
||||
ConnectedComponent cc = new ConnectedComponent();
|
||||
ccs.add(cc);
|
||||
|
||||
cur.formConnectedComponent(cc);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean belongsToSCC() {
|
||||
return cc!=null || isSource() || isSink();
|
||||
}
|
||||
|
||||
/**
|
||||
* Forms a strongly connected component by doing a reverse DFS.
|
||||
*/
|
||||
private void formConnectedComponent(ConnectedComponent group) {
|
||||
if(belongsToSCC())
|
||||
return;
|
||||
|
||||
this.cc=group;
|
||||
group.add(this);
|
||||
for (Element prev : backEdges)
|
||||
prev.formConnectedComponent(group);
|
||||
}
|
||||
|
||||
public boolean hasSelfLoop() {
|
||||
// if foreEdges have a loop, backEdges must have one. Or vice versa
|
||||
assert foreEdges.contains(this)==backEdges.contains(this);
|
||||
|
||||
return foreEdges.contains(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given {@link ConnectedComponent} forms a cut-set
|
||||
* of a graph.
|
||||
*
|
||||
* @param visited
|
||||
* Used to keep track of visited nodes.
|
||||
* @return
|
||||
* true if it is indeed a cut-set. false if not.
|
||||
*/
|
||||
/*package*/ final boolean checkCutSet(ConnectedComponent cc, Set<Element> visited) {
|
||||
assert belongsToSCC(); // SCC discomposition must be done first
|
||||
|
||||
if(isSink())
|
||||
// the definition of the cut set is that without those nodes
|
||||
// you can't reach from soruce to sink
|
||||
return false;
|
||||
|
||||
if(!visited.add(this))
|
||||
return true;
|
||||
|
||||
if(this.cc==cc)
|
||||
return true;
|
||||
|
||||
for (Element next : foreEdges) {
|
||||
if(!next.checkCutSet(cc,visited))
|
||||
// we've found a path to the sink
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.gbind;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* A set over a list of {@link Element}.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
interface ElementSet extends Iterable<Element> {
|
||||
/**
|
||||
* For each element in this set, adds an edge to the given element.
|
||||
*/
|
||||
void addNext(Element element);
|
||||
|
||||
public static final ElementSet EMPTY_SET = new ElementSet() {
|
||||
public void addNext(Element element) {
|
||||
// noop
|
||||
}
|
||||
|
||||
public boolean contains(ElementSet element) {
|
||||
return this==element;
|
||||
}
|
||||
|
||||
public Iterator<Element> iterator() {
|
||||
return Collections.<Element>emptySet().iterator();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Doesn't have to be strict (it's OK for this method to return false
|
||||
* when it's actually true) since this is used just for optimization.
|
||||
*
|
||||
* (Erring on the other side is NG)
|
||||
*/
|
||||
boolean contains(ElementSet rhs);
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.gbind;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
|
||||
/**
|
||||
* Factory methods for {@link ElementSet}.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class ElementSets {
|
||||
/**
|
||||
* Returns an union of two {@link ElementSet}s.
|
||||
*
|
||||
* This method performs better if lhs is bigger than rhs
|
||||
*/
|
||||
public static ElementSet union(ElementSet lhs, ElementSet rhs) {
|
||||
if(lhs.contains(rhs))
|
||||
return lhs;
|
||||
if(lhs==ElementSet.EMPTY_SET)
|
||||
return rhs;
|
||||
if(rhs==ElementSet.EMPTY_SET)
|
||||
return lhs;
|
||||
return new MultiValueSet(lhs,rhs);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ElementSet} that has multiple {@link Element}s in it.
|
||||
*
|
||||
* This isn't particularly efficient or anything, but it will do for now.
|
||||
*/
|
||||
private static final class MultiValueSet extends LinkedHashSet<Element> implements ElementSet {
|
||||
public MultiValueSet(ElementSet lhs, ElementSet rhs) {
|
||||
addAll(lhs);
|
||||
addAll(rhs);
|
||||
// not that anything will break with size==1 MultiValueSet,
|
||||
// but it does suggest that we are missing an easy optimization
|
||||
assert size()>1;
|
||||
}
|
||||
|
||||
private void addAll(ElementSet lhs) {
|
||||
if(lhs instanceof MultiValueSet) {
|
||||
super.addAll((MultiValueSet)lhs);
|
||||
} else {
|
||||
for (Element e : lhs)
|
||||
add(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean contains(ElementSet rhs) {
|
||||
// this isn't complete but sound
|
||||
return super.contains(rhs) || rhs==ElementSet.EMPTY_SET;
|
||||
}
|
||||
|
||||
public void addNext(Element element) {
|
||||
for (Element e : this)
|
||||
e.addNext(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.gbind;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This builds content models.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public abstract class Expression {
|
||||
|
||||
/**
|
||||
* Computes <tt>LAST(exp)</tt>
|
||||
*/
|
||||
abstract ElementSet lastSet();
|
||||
|
||||
/**
|
||||
* True of <tt>\epsilon \in L(exp)</tt>
|
||||
*/
|
||||
abstract boolean isNullable();
|
||||
|
||||
/**
|
||||
* Builds up a DAG among {@link Element}s in this expression.
|
||||
*/
|
||||
abstract void buildDAG(ElementSet incoming);
|
||||
|
||||
/**
|
||||
* {@link Expression} that represents epsilon, the length-0 string.
|
||||
*/
|
||||
public static final Expression EPSILON = new Expression() {
|
||||
ElementSet lastSet() {
|
||||
return ElementSet.EMPTY_SET;
|
||||
}
|
||||
|
||||
boolean isNullable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void buildDAG(ElementSet incoming) {
|
||||
// noop
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "-";
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.gbind;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Graph of {@link Element}s.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class Graph implements Iterable<ConnectedComponent> {
|
||||
private final Element source = new SourceNode();
|
||||
private final Element sink = new SinkNode();
|
||||
|
||||
/**
|
||||
* Strongly connected components of this graph.
|
||||
*/
|
||||
private final List<ConnectedComponent> ccs = new ArrayList<ConnectedComponent>();
|
||||
|
||||
/**
|
||||
* Builds a {@link Graph} from an {@link Expression} tree.
|
||||
*
|
||||
* {@link Expression} given to the graph will be modified forever,
|
||||
* and it will not be able to create another {@link Graph}.
|
||||
*/
|
||||
public Graph(Expression body) {
|
||||
// attach source and sink
|
||||
Expression whole = new Sequence(new Sequence(source,body),sink);
|
||||
|
||||
// build up a graph
|
||||
whole.buildDAG(ElementSet.EMPTY_SET);
|
||||
|
||||
// decompose into strongly connected components.
|
||||
// the algorithm is standard DFS-based algorithm,
|
||||
// one illustration of this algorithm is available at
|
||||
// http://www.personal.kent.edu/~rmuhamma/Algorithms/MyAlgorithms/GraphAlgor/strongComponent.htm
|
||||
source.assignDfsPostOrder(sink);
|
||||
source.buildStronglyConnectedComponents(ccs);
|
||||
|
||||
// cut-set check
|
||||
Set<Element> visited = new HashSet<Element>();
|
||||
for (ConnectedComponent cc : ccs) {
|
||||
visited.clear();
|
||||
if(source.checkCutSet(cc,visited)) {
|
||||
cc.isRequired = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List up {@link ConnectedComponent}s of this graph in an order.
|
||||
*/
|
||||
public Iterator<ConnectedComponent> iterator() {
|
||||
return ccs.iterator();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return ccs.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.gbind;
|
||||
|
||||
/**
|
||||
* {@link Expression} that represents kleene-star operation (A+)
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class OneOrMore extends Expression {
|
||||
/**
|
||||
* 'A' of 'A+'.
|
||||
*/
|
||||
private final Expression child;
|
||||
|
||||
public OneOrMore(Expression child) {
|
||||
this.child = child;
|
||||
}
|
||||
|
||||
ElementSet lastSet() {
|
||||
return child.lastSet();
|
||||
}
|
||||
|
||||
boolean isNullable() {
|
||||
return child.isNullable();
|
||||
}
|
||||
|
||||
void buildDAG(ElementSet incoming) {
|
||||
child.buildDAG(ElementSets.union(incoming,child.lastSet()));
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return child.toString()+'+';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.gbind;
|
||||
|
||||
/**
|
||||
* {@link Expression} that represents a concatanation of two expressions
|
||||
* "A,B".
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class Sequence extends Expression {
|
||||
/**
|
||||
* 'A' of 'A,B'
|
||||
*/
|
||||
private final Expression lhs;
|
||||
/**
|
||||
* 'B' of 'A,B'
|
||||
*/
|
||||
private final Expression rhs;
|
||||
/**
|
||||
* Compute this value eagerly for better performance
|
||||
*/
|
||||
private final boolean isNullable;
|
||||
|
||||
/**
|
||||
* Cached value of {@link #lastSet()} for better performance.
|
||||
* Sequence tends to be where the recursive lastSet computation occurs.
|
||||
*/
|
||||
private ElementSet lastSet;
|
||||
|
||||
public Sequence(Expression lhs, Expression rhs) {
|
||||
this.lhs = lhs;
|
||||
this.rhs = rhs;
|
||||
isNullable = lhs.isNullable() && rhs.isNullable();
|
||||
}
|
||||
|
||||
ElementSet lastSet() {
|
||||
if(lastSet==null) {
|
||||
if(rhs.isNullable())
|
||||
lastSet = ElementSets.union(lhs.lastSet(),rhs.lastSet());
|
||||
else
|
||||
lastSet = rhs.lastSet();
|
||||
}
|
||||
return lastSet;
|
||||
}
|
||||
|
||||
boolean isNullable() {
|
||||
return isNullable;
|
||||
}
|
||||
|
||||
void buildDAG(ElementSet incoming) {
|
||||
lhs.buildDAG(incoming);
|
||||
if(lhs.isNullable())
|
||||
rhs.buildDAG(ElementSets.union(incoming,lhs.lastSet()));
|
||||
else
|
||||
rhs.buildDAG(lhs.lastSet());
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return '('+lhs.toString()+','+rhs.toString()+')';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.gbind;
|
||||
|
||||
/**
|
||||
* Sink node of a grpah.
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class SinkNode extends Element {
|
||||
public String toString() {
|
||||
return "#sink";
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isSink() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.gbind;
|
||||
|
||||
/**
|
||||
* Source node of a graph.
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class SourceNode extends Element {
|
||||
public String toString() {
|
||||
return "#source";
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isSource() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.internalizer;
|
||||
|
||||
import com.sun.istack.internal.SAXParseException2;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.Locator;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXParseException;
|
||||
import org.xml.sax.helpers.XMLFilterImpl;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
/**
|
||||
* XMLFilter that finds references to other schema files from
|
||||
* SAX events.
|
||||
* <p/>
|
||||
* This implementation is a base implementation for typical case
|
||||
* where we just need to look for a particular attribute which
|
||||
* contains an URL to another schema file.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
public abstract class AbstractReferenceFinderImpl extends XMLFilterImpl {
|
||||
|
||||
protected final DOMForest parent;
|
||||
|
||||
protected AbstractReferenceFinderImpl(DOMForest _parent) {
|
||||
this.parent = _parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* IF the given element contains a reference to an external resource,
|
||||
* return its URL.
|
||||
*
|
||||
* @param nsURI Namespace URI of the current element
|
||||
* @param localName Local name of the current element
|
||||
* @return It's OK to return a relative URL.
|
||||
*/
|
||||
protected abstract String findExternalResource(String nsURI, String localName, Attributes atts);
|
||||
|
||||
@Override
|
||||
public void startElement(String namespaceURI, String localName, String qName, Attributes atts)
|
||||
throws SAXException {
|
||||
super.startElement(namespaceURI, localName, qName, atts);
|
||||
|
||||
String relativeRef = findExternalResource(namespaceURI, localName, atts);
|
||||
if (relativeRef == null) {
|
||||
return; // not found
|
||||
}
|
||||
try {
|
||||
// absolutize URL.
|
||||
String lsi = locator.getSystemId();
|
||||
String ref;
|
||||
URI relRefURI = new URI(relativeRef);
|
||||
if (relRefURI.isAbsolute())
|
||||
ref = relativeRef;
|
||||
else {
|
||||
if (lsi.startsWith("jar:")) {
|
||||
int bangIdx = lsi.indexOf('!');
|
||||
if (bangIdx > 0) {
|
||||
ref = lsi.substring(0, bangIdx + 1)
|
||||
+ new URI(lsi.substring(bangIdx + 1)).resolve(new URI(relativeRef)).toString();
|
||||
} else {
|
||||
ref = relativeRef;
|
||||
}
|
||||
} else {
|
||||
ref = new URI(lsi).resolve(new URI(relativeRef)).toString();
|
||||
}
|
||||
}
|
||||
|
||||
// then parse this schema as well,
|
||||
// but don't mark this document as a root.
|
||||
if (parent != null) { // this is there to allow easier testing
|
||||
parent.parse(ref, false);
|
||||
}
|
||||
} catch (URISyntaxException e) {
|
||||
String msg = e.getMessage();
|
||||
if (new File(relativeRef).exists()) {
|
||||
msg = Messages.format(Messages.ERR_FILENAME_IS_NOT_URI) + ' ' + msg;
|
||||
}
|
||||
|
||||
SAXParseException spe = new SAXParseException2(
|
||||
Messages.format(Messages.ERR_UNABLE_TO_PARSE, relativeRef, msg),
|
||||
locator, e);
|
||||
|
||||
fatalError(spe);
|
||||
throw spe;
|
||||
} catch (IOException e) {
|
||||
SAXParseException spe = new SAXParseException2(
|
||||
Messages.format(Messages.ERR_UNABLE_TO_PARSE, relativeRef, e.getMessage()),
|
||||
locator, e);
|
||||
|
||||
fatalError(spe);
|
||||
throw spe;
|
||||
}
|
||||
}
|
||||
|
||||
private Locator locator;
|
||||
|
||||
@Override
|
||||
public void setDocumentLocator(Locator locator) {
|
||||
super.setDocumentLocator(locator);
|
||||
this.locator = locator;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.internalizer;
|
||||
|
||||
import javax.xml.XMLConstants;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXNotRecognizedException;
|
||||
import org.xml.sax.SAXNotSupportedException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.AttributesImpl;
|
||||
import org.xml.sax.helpers.XMLFilterImpl;
|
||||
|
||||
/**
|
||||
* {@link XMLReader} filter for supporting
|
||||
* <tt>http://xml.org/sax/features/namespace-prefixes</tt> feature.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class ContentHandlerNamespacePrefixAdapter extends XMLFilterImpl {
|
||||
/**
|
||||
* True if <tt>http://xml.org/sax/features/namespace-prefixes</tt> is set to true.
|
||||
*/
|
||||
private boolean namespacePrefixes = false;
|
||||
|
||||
private String[] nsBinding = new String[8];
|
||||
private int len;
|
||||
|
||||
public ContentHandlerNamespacePrefixAdapter() {
|
||||
}
|
||||
|
||||
public ContentHandlerNamespacePrefixAdapter(XMLReader parent) {
|
||||
setParent(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getFeature(String name) throws SAXNotRecognizedException, SAXNotSupportedException {
|
||||
if(name.equals(PREFIX_FEATURE))
|
||||
return namespacePrefixes;
|
||||
return super.getFeature(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFeature(String name, boolean value) throws SAXNotRecognizedException, SAXNotSupportedException {
|
||||
if(name.equals(PREFIX_FEATURE)) {
|
||||
this.namespacePrefixes = value;
|
||||
return;
|
||||
}
|
||||
if(name.equals(NAMESPACE_FEATURE) && value)
|
||||
return;
|
||||
super.setFeature(name, value);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void startPrefixMapping(String prefix, String uri) throws SAXException {
|
||||
if (XMLConstants.XML_NS_URI.equals(uri)) return; //xml prefix shall not be declared based on jdk api javadoc
|
||||
if(len==nsBinding.length) {
|
||||
// reallocate
|
||||
String[] buf = new String[nsBinding.length*2];
|
||||
System.arraycopy(nsBinding,0,buf,0,nsBinding.length);
|
||||
nsBinding = buf;
|
||||
}
|
||||
nsBinding[len++] = prefix;
|
||||
nsBinding[len++] = uri;
|
||||
super.startPrefixMapping(prefix,uri);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
|
||||
if(namespacePrefixes) {
|
||||
this.atts.setAttributes(atts);
|
||||
// add namespace bindings back as attributes
|
||||
for( int i=0; i<len; i+=2 ) {
|
||||
String prefix = nsBinding[i];
|
||||
if(prefix.length()==0)
|
||||
this.atts.addAttribute(XMLConstants.XML_NS_URI,"xmlns","xmlns","CDATA",nsBinding[i+1]);
|
||||
else
|
||||
this.atts.addAttribute(XMLConstants.XML_NS_URI,prefix,"xmlns:"+prefix,"CDATA",nsBinding[i+1]);
|
||||
}
|
||||
atts = this.atts;
|
||||
}
|
||||
len=0;
|
||||
super.startElement(uri, localName, qName, atts);
|
||||
}
|
||||
|
||||
private final AttributesImpl atts = new AttributesImpl();
|
||||
|
||||
private static final String PREFIX_FEATURE = "http://xml.org/sax/features/namespace-prefixes";
|
||||
private static final String NAMESPACE_FEATURE = "http://xml.org/sax/features/namespaces";
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.internalizer;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
/**
|
||||
* Simple utility ensuring that the value is cached only in case it is non-internal implementation
|
||||
*/
|
||||
abstract class ContextClassloaderLocal<V> {
|
||||
|
||||
private static final String FAILED_TO_CREATE_NEW_INSTANCE = "FAILED_TO_CREATE_NEW_INSTANCE";
|
||||
|
||||
private WeakHashMap<ClassLoader, V> CACHE = new WeakHashMap<ClassLoader, V>();
|
||||
|
||||
public V get() throws Error {
|
||||
ClassLoader tccl = getContextClassLoader();
|
||||
V instance = CACHE.get(tccl);
|
||||
if (instance == null) {
|
||||
instance = createNewInstance();
|
||||
CACHE.put(tccl, instance);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void set(V instance) {
|
||||
CACHE.put(getContextClassLoader(), instance);
|
||||
}
|
||||
|
||||
protected abstract V initialValue() throws Exception;
|
||||
|
||||
private V createNewInstance() {
|
||||
try {
|
||||
return initialValue();
|
||||
} catch (Exception e) {
|
||||
throw new Error(format(FAILED_TO_CREATE_NEW_INSTANCE, getClass().getName()), e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String format(String property, Object... args) {
|
||||
String text = ResourceBundle.getBundle(ContextClassloaderLocal.class.getName()).getString(property);
|
||||
return MessageFormat.format(text, args);
|
||||
}
|
||||
|
||||
private static ClassLoader getContextClassLoader() {
|
||||
return (ClassLoader)
|
||||
AccessController.doPrivileged(new PrivilegedAction() {
|
||||
public Object run() {
|
||||
ClassLoader cl = null;
|
||||
try {
|
||||
cl = Thread.currentThread().getContextClassLoader();
|
||||
} catch (SecurityException ex) {
|
||||
}
|
||||
return cl;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.internalizer;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import com.sun.tools.internal.xjc.reader.Const;
|
||||
import com.sun.xml.internal.bind.marshaller.SAX2DOMEx;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.Locator;
|
||||
|
||||
/**
|
||||
* Builds DOM while keeping the location information.
|
||||
*
|
||||
* <p>
|
||||
* This class also looks for outer most <jaxb:bindings>
|
||||
* customizations.
|
||||
*
|
||||
* @author
|
||||
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
class DOMBuilder extends SAX2DOMEx {
|
||||
/**
|
||||
* Grows a DOM tree under the given document, and
|
||||
* stores location information to the given table.
|
||||
*
|
||||
* @param outerMostBindings
|
||||
* This set will receive newly found outermost
|
||||
* jaxb:bindings customizations.
|
||||
*/
|
||||
public DOMBuilder( Document dom, LocatorTable ltable, Set outerMostBindings ) {
|
||||
super( dom );
|
||||
this.locatorTable = ltable;
|
||||
this.outerMostBindings = outerMostBindings;
|
||||
}
|
||||
|
||||
/** Location information will be stored into this object. */
|
||||
private final LocatorTable locatorTable;
|
||||
|
||||
private final Set outerMostBindings;
|
||||
|
||||
private Locator locator;
|
||||
|
||||
public void setDocumentLocator(Locator locator) {
|
||||
this.locator = locator;
|
||||
super.setDocumentLocator(locator);
|
||||
}
|
||||
|
||||
|
||||
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) {
|
||||
super.startElement(namespaceURI, localName, qName, atts);
|
||||
|
||||
Element e = getCurrentElement();
|
||||
locatorTable.storeStartLocation( e, locator );
|
||||
|
||||
// check if this element is an outer-most <jaxb:bindings>
|
||||
if( Const.JAXB_NSURI.equals(e.getNamespaceURI())
|
||||
&& "bindings".equals(e.getLocalName()) ) {
|
||||
|
||||
// if this is the root node (meaning that this file is an
|
||||
// external binding file) or if the parent is XML Schema element
|
||||
// (meaning that this is an "inlined" external binding)
|
||||
Node p = e.getParentNode();
|
||||
if( p instanceof Document
|
||||
||( p instanceof Element && !e.getNamespaceURI().equals(p.getNamespaceURI()))) {
|
||||
outerMostBindings.add(e); // remember this value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void endElement(String namespaceURI, String localName, String qName) {
|
||||
locatorTable.storeEndLocation( getCurrentElement(), locator );
|
||||
super.endElement(namespaceURI, localName, qName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,574 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.internalizer;
|
||||
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import com.sun.istack.internal.XMLStreamReaderToContentHandler;
|
||||
import com.sun.tools.internal.xjc.ErrorReceiver;
|
||||
import com.sun.tools.internal.xjc.Options;
|
||||
import com.sun.tools.internal.xjc.reader.Const;
|
||||
import com.sun.tools.internal.xjc.util.ErrorReceiverFilter;
|
||||
import com.sun.xml.internal.bind.marshaller.DataWriter;
|
||||
import com.sun.xml.internal.bind.v2.util.XmlFactory;
|
||||
import com.sun.xml.internal.xsom.parser.JAXPParser;
|
||||
import com.sun.xml.internal.xsom.parser.XMLParser;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.xml.sax.*;
|
||||
import org.xml.sax.helpers.XMLFilterImpl;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.sax.SAXResult;
|
||||
import javax.xml.transform.sax.SAXSource;
|
||||
import javax.xml.validation.SchemaFactory;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.util.*;
|
||||
|
||||
import static com.sun.xml.internal.bind.v2.util.XmlFactory.allowExternalAccess;
|
||||
import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI;
|
||||
|
||||
|
||||
/**
|
||||
* Builds a DOM forest and maintains association from
|
||||
* system IDs to DOM trees.
|
||||
*
|
||||
* <p>
|
||||
* A forest is a transitive reflexive closure of referenced documents.
|
||||
* IOW, if a document is in a forest, all the documents referenced from
|
||||
* it is in a forest, too. To support this semantics, {@link DOMForest}
|
||||
* uses {@link InternalizationLogic} to find referenced documents.
|
||||
*
|
||||
* <p>
|
||||
* Some documents are marked as "root"s, meaning those documents were
|
||||
* put into a forest explicitly, not because it is referenced from another
|
||||
* document. (However, a root document can be referenced from other
|
||||
* documents, too.)
|
||||
*
|
||||
* @author
|
||||
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
public final class DOMForest {
|
||||
/** actual data storage map<SystemId,Document>. */
|
||||
private final Map<String,Document> core = new HashMap<String,Document>();
|
||||
|
||||
/**
|
||||
* To correctly feed documents to a schema parser, we need to remember
|
||||
* which documents (of the forest) were given as the root
|
||||
* documents, and which of them are read as included/imported
|
||||
* documents.
|
||||
*
|
||||
* <p>
|
||||
* Set of system ids as strings.
|
||||
*/
|
||||
private final Set<String> rootDocuments = new HashSet<String>();
|
||||
|
||||
/** Stores location information for all the trees in this forest. */
|
||||
public final LocatorTable locatorTable = new LocatorTable();
|
||||
|
||||
/** Stores all the outer-most <jaxb:bindings> customizations. */
|
||||
public final Set<Element> outerMostBindings = new HashSet<Element>();
|
||||
|
||||
/** Used to resolve references to other schema documents. */
|
||||
private EntityResolver entityResolver = null;
|
||||
|
||||
/** Errors encountered during the parsing will be sent to this object. */
|
||||
private ErrorReceiver errorReceiver = null;
|
||||
|
||||
/** Schema language dependent part of the processing. */
|
||||
protected final InternalizationLogic logic;
|
||||
|
||||
private final SAXParserFactory parserFactory;
|
||||
private final DocumentBuilder documentBuilder;
|
||||
|
||||
private final Options options;
|
||||
|
||||
public DOMForest(
|
||||
SAXParserFactory parserFactory, DocumentBuilder documentBuilder,
|
||||
InternalizationLogic logic ) {
|
||||
|
||||
this.parserFactory = parserFactory;
|
||||
this.documentBuilder = documentBuilder;
|
||||
this.logic = logic;
|
||||
this.options = null;
|
||||
}
|
||||
|
||||
public DOMForest( InternalizationLogic logic, Options opt ) {
|
||||
|
||||
if (opt == null) throw new AssertionError("Options object null");
|
||||
this.options = opt;
|
||||
|
||||
try {
|
||||
DocumentBuilderFactory dbf = XmlFactory.createDocumentBuilderFactory(opt.disableXmlSecurity);
|
||||
this.documentBuilder = dbf.newDocumentBuilder();
|
||||
this.parserFactory = XmlFactory.createParserFactory(opt.disableXmlSecurity);
|
||||
} catch( ParserConfigurationException e ) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
this.logic = logic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the DOM tree associated with the specified system ID,
|
||||
* or null if none is found.
|
||||
*/
|
||||
public Document get( String systemId ) {
|
||||
Document doc = core.get(systemId);
|
||||
|
||||
if( doc==null && systemId.startsWith("file:/") && !systemId.startsWith("file://") ) {
|
||||
// As of JDK1.4, java.net.URL.toExternal method returns URLs like
|
||||
// "file:/abc/def/ghi" which is an incorrect file protocol URL according to RFC1738.
|
||||
// Some other correctly functioning parts return the correct URLs ("file:///abc/def/ghi"),
|
||||
// and this descripancy breaks DOM look up by system ID.
|
||||
|
||||
// this extra check solves this problem.
|
||||
doc = core.get( "file://"+systemId.substring(5) );
|
||||
}
|
||||
|
||||
if( doc==null && systemId.startsWith("file:") ) {
|
||||
// on Windows, filenames are case insensitive.
|
||||
// perform case-insensitive search for improved user experience
|
||||
String systemPath = getPath(systemId);
|
||||
for (String key : core.keySet()) {
|
||||
if(key.startsWith("file:") && getPath(key).equalsIgnoreCase(systemPath)) {
|
||||
doc = core.get(key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips off the leading 'file:///' portion from an URL.
|
||||
*/
|
||||
private String getPath(String key) {
|
||||
key = key.substring(5); // skip 'file:'
|
||||
while(key.length()>0 && key.charAt(0)=='/') {
|
||||
key = key.substring(1);
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a read-only set of root document system IDs.
|
||||
*/
|
||||
public Set<String> getRootDocuments() {
|
||||
return Collections.unmodifiableSet(rootDocuments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Picks one document at random and returns it.
|
||||
*/
|
||||
public Document getOneDocument() {
|
||||
for (Document dom : core.values()) {
|
||||
if (!dom.getDocumentElement().getNamespaceURI().equals(Const.JAXB_NSURI))
|
||||
return dom;
|
||||
}
|
||||
// we should have caught this error very early on
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the correctness of the XML Schema documents and return true
|
||||
* if it's OK.
|
||||
*
|
||||
* <p>
|
||||
* This method performs a weaker version of the tests where error messages
|
||||
* are provided without line number information. So whenever possible
|
||||
* use {@link SchemaConstraintChecker}.
|
||||
*
|
||||
* @see SchemaConstraintChecker
|
||||
*/
|
||||
public boolean checkSchemaCorrectness(ErrorReceiver errorHandler) {
|
||||
try {
|
||||
boolean disableXmlSecurity = false;
|
||||
if (options != null) {
|
||||
disableXmlSecurity = options.disableXmlSecurity;
|
||||
}
|
||||
SchemaFactory sf = XmlFactory.createSchemaFactory(W3C_XML_SCHEMA_NS_URI, disableXmlSecurity);
|
||||
ErrorReceiverFilter filter = new ErrorReceiverFilter(errorHandler);
|
||||
sf.setErrorHandler(filter);
|
||||
Set<String> roots = getRootDocuments();
|
||||
Source[] sources = new Source[roots.size()];
|
||||
int i=0;
|
||||
for (String root : roots) {
|
||||
sources[i++] = new DOMSource(get(root),root);
|
||||
}
|
||||
sf.newSchema(sources);
|
||||
return !filter.hadError();
|
||||
} catch (SAXException e) {
|
||||
// the errors should have been reported
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the system ID from which the given DOM is parsed.
|
||||
* <p>
|
||||
* Poor-man's base URI.
|
||||
*/
|
||||
public String getSystemId( Document dom ) {
|
||||
for (Map.Entry<String,Document> e : core.entrySet()) {
|
||||
if (e.getValue() == dom)
|
||||
return e.getKey();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Document parse( InputSource source, boolean root ) throws SAXException {
|
||||
if( source.getSystemId()==null )
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
return parse( source.getSystemId(), source, root );
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an XML at the given location (
|
||||
* and XMLs referenced by it) into DOM trees
|
||||
* and stores them to this forest.
|
||||
*
|
||||
* @return the parsed DOM document object.
|
||||
*/
|
||||
public Document parse( String systemId, boolean root ) throws SAXException, IOException {
|
||||
|
||||
systemId = Options.normalizeSystemId(systemId);
|
||||
|
||||
if( core.containsKey(systemId) )
|
||||
// this document has already been parsed. Just ignore.
|
||||
return core.get(systemId);
|
||||
|
||||
InputSource is=null;
|
||||
|
||||
// allow entity resolver to find the actual byte stream.
|
||||
if( entityResolver!=null )
|
||||
is = entityResolver.resolveEntity(null,systemId);
|
||||
if( is==null )
|
||||
is = new InputSource(systemId);
|
||||
|
||||
// but we still use the original system Id as the key.
|
||||
return parse( systemId, is, root );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link ContentHandler} to feed SAX events into.
|
||||
*
|
||||
* <p>
|
||||
* The client of this class can feed SAX events into the handler
|
||||
* to parse a document into this DOM forest.
|
||||
*
|
||||
* This version requires that the DOM object to be created and registered
|
||||
* to the map beforehand.
|
||||
*/
|
||||
private ContentHandler getParserHandler( Document dom ) {
|
||||
ContentHandler handler = new DOMBuilder(dom,locatorTable,outerMostBindings);
|
||||
handler = new WhitespaceStripper(handler,errorReceiver,entityResolver);
|
||||
handler = new VersionChecker(handler,errorReceiver,entityResolver);
|
||||
|
||||
// insert the reference finder so that
|
||||
// included/imported schemas will be also parsed
|
||||
XMLFilterImpl f = logic.createExternalReferenceFinder(this);
|
||||
f.setContentHandler(handler);
|
||||
|
||||
if(errorReceiver!=null)
|
||||
f.setErrorHandler(errorReceiver);
|
||||
if(entityResolver!=null)
|
||||
f.setEntityResolver(entityResolver);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
public interface Handler extends ContentHandler {
|
||||
/**
|
||||
* Gets the DOM that was built.
|
||||
*/
|
||||
public Document getDocument();
|
||||
}
|
||||
|
||||
private static abstract class HandlerImpl extends XMLFilterImpl implements Handler {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link ContentHandler} to feed SAX events into.
|
||||
*
|
||||
* <p>
|
||||
* The client of this class can feed SAX events into the handler
|
||||
* to parse a document into this DOM forest.
|
||||
*/
|
||||
public Handler getParserHandler( String systemId, boolean root ) {
|
||||
final Document dom = documentBuilder.newDocument();
|
||||
core.put( systemId, dom );
|
||||
if(root)
|
||||
rootDocuments.add(systemId);
|
||||
|
||||
ContentHandler handler = getParserHandler(dom);
|
||||
|
||||
// we will register the DOM to the map once the system ID becomes available.
|
||||
// but the SAX allows the event source to not to provide that information,
|
||||
// so be prepared for such case.
|
||||
HandlerImpl x = new HandlerImpl() {
|
||||
public Document getDocument() {
|
||||
return dom;
|
||||
}
|
||||
};
|
||||
x.setContentHandler(handler);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the given document and add it to the DOM forest.
|
||||
*
|
||||
* @return
|
||||
* null if there was a parse error. otherwise non-null.
|
||||
*/
|
||||
public Document parse( String systemId, InputSource inputSource, boolean root ) throws SAXException {
|
||||
Document dom = documentBuilder.newDocument();
|
||||
|
||||
systemId = Options.normalizeSystemId(systemId);
|
||||
|
||||
// put into the map before growing a tree, to
|
||||
// prevent recursive reference from causing infinite loop.
|
||||
core.put( systemId, dom );
|
||||
if(root)
|
||||
rootDocuments.add(systemId);
|
||||
|
||||
try {
|
||||
XMLReader reader = parserFactory.newSAXParser().getXMLReader();
|
||||
reader.setContentHandler(getParserHandler(dom));
|
||||
if(errorReceiver!=null)
|
||||
reader.setErrorHandler(errorReceiver);
|
||||
if(entityResolver!=null)
|
||||
reader.setEntityResolver(entityResolver);
|
||||
reader.parse(inputSource);
|
||||
} catch( ParserConfigurationException e ) {
|
||||
// in practice, this exception won't happen.
|
||||
errorReceiver.error(e.getMessage(),e);
|
||||
core.remove(systemId);
|
||||
rootDocuments.remove(systemId);
|
||||
return null;
|
||||
} catch( IOException e ) {
|
||||
errorReceiver.error(Messages.format(Messages.DOMFOREST_INPUTSOURCE_IOEXCEPTION, systemId, e.toString()),e);
|
||||
core.remove(systemId);
|
||||
rootDocuments.remove(systemId);
|
||||
return null;
|
||||
}
|
||||
|
||||
return dom;
|
||||
}
|
||||
|
||||
public Document parse( String systemId, XMLStreamReader parser, boolean root ) throws XMLStreamException {
|
||||
Document dom = documentBuilder.newDocument();
|
||||
|
||||
systemId = Options.normalizeSystemId(systemId);
|
||||
|
||||
if(root)
|
||||
rootDocuments.add(systemId);
|
||||
|
||||
if(systemId==null)
|
||||
throw new IllegalArgumentException("system id cannot be null");
|
||||
core.put( systemId, dom );
|
||||
|
||||
new XMLStreamReaderToContentHandler(parser,getParserHandler(dom),false,false).bridge();
|
||||
|
||||
return dom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs internalization.
|
||||
*
|
||||
* This method should be called only once, only after all the
|
||||
* schemas are parsed.
|
||||
*
|
||||
* @return
|
||||
* the returned bindings need to be applied after schema
|
||||
* components are built.
|
||||
*/
|
||||
public SCDBasedBindingSet transform(boolean enableSCD) {
|
||||
return Internalizer.transform(this, enableSCD, options.disableXmlSecurity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the schema correctness check by using JAXP 1.3.
|
||||
*
|
||||
* <p>
|
||||
* This is "weak", because {@link SchemaFactory#newSchema(Source[])}
|
||||
* doesn't handle inclusions very correctly (it ends up parsing it
|
||||
* from its original source, not in this tree), and because
|
||||
* it doesn't handle two documents for the same namespace very
|
||||
* well.
|
||||
*
|
||||
* <p>
|
||||
* We should eventually fix JAXP (and Xerces), but meanwhile
|
||||
* this weaker and potentially wrong correctness check is still
|
||||
* better than nothing when used inside JAX-WS (JAXB CLI and Ant
|
||||
* does a better job of checking this.)
|
||||
*
|
||||
* <p>
|
||||
* To receive errors, use {@link SchemaFactory#setErrorHandler(ErrorHandler)}.
|
||||
*/
|
||||
public void weakSchemaCorrectnessCheck(SchemaFactory sf) {
|
||||
List<SAXSource> sources = new ArrayList<SAXSource>();
|
||||
for( String systemId : getRootDocuments() ) {
|
||||
Document dom = get(systemId);
|
||||
if (dom.getDocumentElement().getNamespaceURI().equals(Const.JAXB_NSURI))
|
||||
continue; // this isn't a schema. we have to do a negative check because if we see completely unrelated ns, we want to report that as an error
|
||||
|
||||
SAXSource ss = createSAXSource(systemId);
|
||||
try {
|
||||
ss.getXMLReader().setFeature("http://xml.org/sax/features/namespace-prefixes",true);
|
||||
} catch (SAXException e) {
|
||||
throw new AssertionError(e); // Xerces wants this. See 6395322.
|
||||
}
|
||||
sources.add(ss);
|
||||
}
|
||||
|
||||
try {
|
||||
allowExternalAccess(sf, "file,http", options.disableXmlSecurity).newSchema(sources.toArray(new SAXSource[0]));
|
||||
} catch (SAXException e) {
|
||||
// error should have been reported.
|
||||
} catch (RuntimeException re) {
|
||||
// JAXP RI isn't very trustworthy when it comes to schema error check,
|
||||
// and we know some cases where it just dies with NPE. So handle it gracefully.
|
||||
// this masks a bug in the JAXP RI, but we need a release that we have to make.
|
||||
try {
|
||||
sf.getErrorHandler().warning(
|
||||
new SAXParseException(Messages.format(
|
||||
Messages.ERR_GENERAL_SCHEMA_CORRECTNESS_ERROR,re.getMessage()),
|
||||
null,null,-1,-1,re));
|
||||
} catch (SAXException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link SAXSource} that, when parsed, reads from this {@link DOMForest}
|
||||
* (instead of parsing the original source identified by the system ID.)
|
||||
*/
|
||||
public @NotNull SAXSource createSAXSource(String systemId) {
|
||||
ContentHandlerNamespacePrefixAdapter reader = new ContentHandlerNamespacePrefixAdapter(new XMLFilterImpl() {
|
||||
// XMLReader that uses XMLParser to parse. We need to use XMLFilter to indrect
|
||||
// handlers, since SAX allows handlers to be changed while parsing.
|
||||
@Override
|
||||
public void parse(InputSource input) throws SAXException, IOException {
|
||||
createParser().parse(input, this, this, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parse(String systemId) throws SAXException, IOException {
|
||||
parse(new InputSource(systemId));
|
||||
}
|
||||
});
|
||||
|
||||
return new SAXSource(reader,new InputSource(systemId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates {@link XMLParser} for XSOM which reads documents from
|
||||
* this DOMForest rather than doing a fresh parse.
|
||||
*
|
||||
* The net effect is that XSOM will read transformed XML Schemas
|
||||
* instead of the original documents.
|
||||
*/
|
||||
public XMLParser createParser() {
|
||||
return new DOMForestParser(this, new JAXPParser(XmlFactory.createParserFactory(options.disableXmlSecurity)));
|
||||
}
|
||||
|
||||
public EntityResolver getEntityResolver() {
|
||||
return entityResolver;
|
||||
}
|
||||
|
||||
public void setEntityResolver(EntityResolver entityResolver) {
|
||||
this.entityResolver = entityResolver;
|
||||
}
|
||||
|
||||
public ErrorReceiver getErrorHandler() {
|
||||
return errorReceiver;
|
||||
}
|
||||
|
||||
public void setErrorHandler(ErrorReceiver errorHandler) {
|
||||
this.errorReceiver = errorHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the parsed documents.
|
||||
*/
|
||||
public Document[] listDocuments() {
|
||||
return core.values().toArray(new Document[core.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the system IDs of the documents.
|
||||
*/
|
||||
public String[] listSystemIDs() {
|
||||
return core.keySet().toArray(new String[core.keySet().size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps the contents of the forest to the specified stream.
|
||||
*
|
||||
* This is a debug method. As such, error handling is sloppy.
|
||||
*/
|
||||
@SuppressWarnings("CallToThreadDumpStack")
|
||||
public void dump( OutputStream out ) throws IOException {
|
||||
try {
|
||||
// create identity transformer
|
||||
boolean disableXmlSecurity = false;
|
||||
if (options != null) {
|
||||
disableXmlSecurity = options.disableXmlSecurity;
|
||||
}
|
||||
TransformerFactory tf = XmlFactory.createTransformerFactory(disableXmlSecurity);
|
||||
Transformer it = tf.newTransformer();
|
||||
|
||||
for (Map.Entry<String, Document> e : core.entrySet()) {
|
||||
out.write( ("---<< "+e.getKey()+'\n').getBytes() );
|
||||
|
||||
DataWriter dw = new DataWriter(new OutputStreamWriter(out),null);
|
||||
dw.setIndentStep(" ");
|
||||
it.transform( new DOMSource(e.getValue()),
|
||||
new SAXResult(dw));
|
||||
|
||||
out.write( "\n\n\n".getBytes() );
|
||||
}
|
||||
} catch( TransformerException e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.internalizer;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.sun.xml.internal.xsom.parser.XMLParser;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.EntityResolver;
|
||||
import org.xml.sax.ErrorHandler;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
|
||||
/**
|
||||
* {@link XMLParser} implementation that
|
||||
* parses XML from a DOM forest instead of parsing it from
|
||||
* its original location.
|
||||
*
|
||||
* @author
|
||||
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
class DOMForestParser implements XMLParser {
|
||||
|
||||
/** DOM forest to be "parsed". */
|
||||
private final DOMForest forest;
|
||||
|
||||
/** Scanner object will do the actual SAX events generation. */
|
||||
private final DOMForestScanner scanner;
|
||||
|
||||
private final XMLParser fallbackParser;
|
||||
|
||||
/**
|
||||
* @param fallbackParser
|
||||
* This parser will be used when DOMForestParser needs to parse
|
||||
* documents that are not in the forest.
|
||||
*/
|
||||
DOMForestParser( DOMForest forest, XMLParser fallbackParser ) {
|
||||
this.forest = forest;
|
||||
this.scanner = new DOMForestScanner(forest);
|
||||
this.fallbackParser = fallbackParser;
|
||||
}
|
||||
|
||||
public void parse(
|
||||
InputSource source,
|
||||
ContentHandler contentHandler,
|
||||
ErrorHandler errorHandler,
|
||||
EntityResolver entityResolver )
|
||||
throws SAXException, IOException {
|
||||
|
||||
String systemId = source.getSystemId();
|
||||
Document dom = forest.get(systemId);
|
||||
|
||||
if(dom==null) {
|
||||
// if no DOM tree is built for it,
|
||||
// let the fall back parser parse the original document.
|
||||
//
|
||||
// for example, XSOM parses datatypes.xsd (XML Schema part 2)
|
||||
// but this will never be built into the forest.
|
||||
fallbackParser.parse( source, contentHandler, errorHandler, entityResolver );
|
||||
return;
|
||||
}
|
||||
|
||||
scanner.scan( dom, contentHandler );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.internalizer;
|
||||
|
||||
import com.sun.xml.internal.bind.unmarshaller.DOMScanner;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.Locator;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.XMLFilterImpl;
|
||||
|
||||
/**
|
||||
* Produces a complete series of SAX events from any DOM node
|
||||
* in the DOMForest.
|
||||
*
|
||||
* <p>
|
||||
* This class hides a logic of re-associating {@link Locator}
|
||||
* to the generated SAX event stream.
|
||||
*
|
||||
* @author
|
||||
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
public class DOMForestScanner {
|
||||
|
||||
private final DOMForest forest;
|
||||
|
||||
/**
|
||||
* Scans DOM nodes of the given forest.
|
||||
*
|
||||
* DOM node parameters to the scan method must be a part of
|
||||
* this forest.
|
||||
*/
|
||||
public DOMForestScanner( DOMForest _forest ) {
|
||||
this.forest = _forest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the whole set of SAX events by treating
|
||||
* element e as if it's a root element.
|
||||
*/
|
||||
public void scan( Element e, ContentHandler contentHandler ) throws SAXException {
|
||||
DOMScanner scanner = new DOMScanner();
|
||||
|
||||
// insert the location resolver into the pipe line
|
||||
LocationResolver resolver = new LocationResolver(scanner);
|
||||
resolver.setContentHandler(contentHandler);
|
||||
|
||||
// parse this DOM.
|
||||
scanner.setContentHandler(resolver);
|
||||
scanner.scan(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the whole set of SAX events from the given Document
|
||||
* in the DOMForest.
|
||||
*/
|
||||
public void scan( Document d, ContentHandler contentHandler ) throws SAXException {
|
||||
scan( d.getDocumentElement(), contentHandler );
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercepts the invocation of the setDocumentLocator method
|
||||
* and passes itself as the locator.
|
||||
*
|
||||
* If the client calls one of the methods on the Locator interface,
|
||||
* use the LocatorTable to resolve the source location.
|
||||
*/
|
||||
private class LocationResolver extends XMLFilterImpl implements Locator {
|
||||
LocationResolver( DOMScanner _parent ) {
|
||||
this.parent = _parent;
|
||||
}
|
||||
|
||||
private final DOMScanner parent;
|
||||
|
||||
/**
|
||||
* Flag that tells us whether we are processing a start element event
|
||||
* or an end element event.
|
||||
*
|
||||
* DOMScanner's getCurrentLocation method doesn't tell us which, but
|
||||
* this information is necessary to return the correct source line information.
|
||||
*
|
||||
* Thus we set this flag appropriately before we pass an event to
|
||||
* the next ContentHandler, thereby making it possible to figure
|
||||
* out which location to return.
|
||||
*/
|
||||
private boolean inStart = false;
|
||||
|
||||
@Override
|
||||
public void setDocumentLocator(Locator locator) {
|
||||
// ignore one set by the parent.
|
||||
|
||||
super.setDocumentLocator(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
|
||||
inStart = false;
|
||||
super.endElement(namespaceURI, localName, qName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement(String namespaceURI, String localName, String qName, Attributes atts)
|
||||
throws SAXException {
|
||||
inStart = true;
|
||||
super.startElement(namespaceURI, localName, qName, atts);
|
||||
}
|
||||
|
||||
private Locator findLocator() {
|
||||
Node n = parent.getCurrentLocation();
|
||||
if( n instanceof Element ) {
|
||||
Element e = (Element)n;
|
||||
if( inStart )
|
||||
return forest.locatorTable.getStartLocation( e );
|
||||
else
|
||||
return forest.locatorTable.getEndLocation( e );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// Locator methods
|
||||
//
|
||||
//
|
||||
public int getColumnNumber() {
|
||||
Locator l = findLocator();
|
||||
if(l!=null) return l.getColumnNumber();
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int getLineNumber() {
|
||||
Locator l = findLocator();
|
||||
if(l!=null) return l.getLineNumber();
|
||||
return -1;
|
||||
}
|
||||
|
||||
public String getPublicId() {
|
||||
Locator l = findLocator();
|
||||
if(l!=null) return l.getPublicId();
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getSystemId() {
|
||||
Locator l = findLocator();
|
||||
if(l!=null) return l.getSystemId();
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.internalizer;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.xml.sax.helpers.XMLFilterImpl;
|
||||
|
||||
/**
|
||||
* Encapsulates schema-language dependent internalization logic.
|
||||
*
|
||||
* {@link Internalizer} and {@link DOMForest} are responsible for
|
||||
* doing schema language independent part, and this object is responsible
|
||||
* for schema language dependent part.
|
||||
*
|
||||
* @author
|
||||
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
public interface InternalizationLogic {
|
||||
/**
|
||||
* Creates a new instance of XMLFilter that can be used to
|
||||
* find references to external schemas.
|
||||
*
|
||||
* <p>
|
||||
* Schemas that are included/imported need to be a part of
|
||||
* {@link DOMForest}, and this filter will be expected to
|
||||
* find such references.
|
||||
*
|
||||
* <p>
|
||||
* Once such a reference is found, the filter is expected to
|
||||
* call the parse method of DOMForest.
|
||||
*
|
||||
* <p>
|
||||
* {@link DOMForest} will register ErrorHandler to the returned
|
||||
* object, so any error should be sent to that error handler.
|
||||
*
|
||||
* @return
|
||||
* This method returns {@link XMLFilterImpl} because
|
||||
* the filter has to be usable for two directions
|
||||
* (wrapping a reader and wrapping a ContentHandler)
|
||||
*/
|
||||
XMLFilterImpl createExternalReferenceFinder( DOMForest parent );
|
||||
|
||||
/**
|
||||
* Checks if the specified element is a valid target node
|
||||
* to attach a customization.
|
||||
*
|
||||
* @param parent
|
||||
* The owner DOMForest object. Probably useful only
|
||||
* to obtain context information, such as error handler.
|
||||
* @param bindings
|
||||
* <jaxb:bindings> element or a customization element.
|
||||
* @return
|
||||
* true if it's OK, false if not.
|
||||
*/
|
||||
boolean checkIfValidTargetNode( DOMForest parent, Element bindings, Element target );
|
||||
|
||||
/**
|
||||
* Prepares an element that actually receives customizations.
|
||||
*
|
||||
* <p>
|
||||
* For example, in XML Schema, target nodes can be any schema
|
||||
* element but it is always the <xsd:appinfo> element that
|
||||
* receives customization.
|
||||
*
|
||||
* @param target
|
||||
* The target node designated by the customization.
|
||||
* @return
|
||||
* Always return non-null valid object
|
||||
*/
|
||||
Element refineTarget( Element target );
|
||||
}
|
||||
@@ -0,0 +1,615 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.internalizer;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.text.ParseException;
|
||||
|
||||
import javax.xml.xpath.XPath;
|
||||
import javax.xml.xpath.XPathConstants;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
|
||||
import com.sun.istack.internal.SAXParseException2;
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import com.sun.istack.internal.Nullable;
|
||||
import com.sun.tools.internal.xjc.ErrorReceiver;
|
||||
import com.sun.tools.internal.xjc.reader.Const;
|
||||
import com.sun.tools.internal.xjc.util.DOMUtils;
|
||||
import com.sun.xml.internal.bind.v2.util.EditDistance;
|
||||
import com.sun.xml.internal.bind.v2.util.XmlFactory;
|
||||
import com.sun.xml.internal.xsom.SCD;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.xml.XMLConstants;
|
||||
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.SAXParseException;
|
||||
|
||||
/**
|
||||
* Internalizes external binding declarations.
|
||||
*
|
||||
* <p>
|
||||
* The {@link #transform(DOMForest,boolean)} method is the entry point.
|
||||
*
|
||||
* @author
|
||||
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
class Internalizer {
|
||||
|
||||
private static final String WSDL_NS = "http://schemas.xmlsoap.org/wsdl/";
|
||||
|
||||
private final XPath xpath;
|
||||
|
||||
/**
|
||||
* Internalize all <jaxb:bindings> customizations in the given forest.
|
||||
*
|
||||
* @return
|
||||
* if the SCD support is enabled, the return bindings need to be applied
|
||||
* after schema components are parsed.
|
||||
* If disabled, the returned binding set will be empty.
|
||||
* SCDs are only for XML Schema, and doesn't make any sense for other
|
||||
* schema languages.
|
||||
*/
|
||||
static SCDBasedBindingSet transform( DOMForest forest, boolean enableSCD, boolean disableSecureProcessing ) {
|
||||
return new Internalizer(forest, enableSCD, disableSecureProcessing).transform();
|
||||
}
|
||||
|
||||
|
||||
private Internalizer(DOMForest forest, boolean enableSCD, boolean disableSecureProcessing) {
|
||||
this.errorHandler = forest.getErrorHandler();
|
||||
this.forest = forest;
|
||||
this.enableSCD = enableSCD;
|
||||
xpath = XmlFactory.createXPathFactory(disableSecureProcessing).newXPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* DOMForest object currently being processed.
|
||||
*/
|
||||
private final DOMForest forest;
|
||||
|
||||
/**
|
||||
* All errors found during the transformation is sent to this object.
|
||||
*/
|
||||
private ErrorReceiver errorHandler;
|
||||
|
||||
/**
|
||||
* If true, the SCD-based target selection is supported.
|
||||
*/
|
||||
private boolean enableSCD;
|
||||
|
||||
|
||||
private SCDBasedBindingSet transform() {
|
||||
|
||||
// either target nodes are conventional DOM nodes (as per spec),
|
||||
Map<Element,List<Node>> targetNodes = new HashMap<Element,List<Node>>();
|
||||
// ... or it will be schema components by means of SCD (RI extension)
|
||||
SCDBasedBindingSet scd = new SCDBasedBindingSet(forest);
|
||||
|
||||
//
|
||||
// identify target nodes for all <jaxb:bindings>
|
||||
//
|
||||
for (Element jaxbBindings : forest.outerMostBindings) {
|
||||
// initially, the inherited context is itself
|
||||
buildTargetNodeMap(jaxbBindings, jaxbBindings, null, targetNodes, scd);
|
||||
}
|
||||
|
||||
//
|
||||
// then move them to their respective positions.
|
||||
//
|
||||
for (Element jaxbBindings : forest.outerMostBindings) {
|
||||
move(jaxbBindings, targetNodes);
|
||||
}
|
||||
|
||||
return scd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates attributes of a <jaxb:bindings> element.
|
||||
*/
|
||||
private void validate( Element bindings ) {
|
||||
NamedNodeMap atts = bindings.getAttributes();
|
||||
for( int i=0; i<atts.getLength(); i++ ) {
|
||||
Attr a = (Attr)atts.item(i);
|
||||
if( a.getNamespaceURI()!=null )
|
||||
continue; // all foreign namespace OK.
|
||||
if( a.getLocalName().equals("node") )
|
||||
continue;
|
||||
if( a.getLocalName().equals("schemaLocation"))
|
||||
continue;
|
||||
if( a.getLocalName().equals("scd") )
|
||||
continue;
|
||||
|
||||
// enhancements
|
||||
if( a.getLocalName().equals("required") ) //
|
||||
continue;
|
||||
if( a.getLocalName().equals("multiple") ) //
|
||||
continue;
|
||||
|
||||
|
||||
// TODO: flag error for this undefined attribute
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the target node of the "bindings" element
|
||||
* by using the inherited target node, then put
|
||||
* the result into the "result" map and the "scd" map.
|
||||
*
|
||||
* @param inheritedTarget
|
||||
* The current target node. This always exists, even if
|
||||
* the user starts specifying targets via SCD (in that case
|
||||
* this inherited target is just not going to be used.)
|
||||
* @param inheritedSCD
|
||||
* If the ancestor <bindings> node specifies @scd to
|
||||
* specify the target via SCD, then this parameter represents that context.
|
||||
*/
|
||||
private void buildTargetNodeMap( Element bindings, @NotNull Node inheritedTarget,
|
||||
@Nullable SCDBasedBindingSet.Target inheritedSCD,
|
||||
Map<Element,List<Node>> result, SCDBasedBindingSet scdResult ) {
|
||||
// start by the inherited target
|
||||
Node target = inheritedTarget;
|
||||
ArrayList<Node> targetMultiple = null;
|
||||
|
||||
validate(bindings); // validate this node
|
||||
|
||||
boolean required = true;
|
||||
boolean multiple = false;
|
||||
|
||||
if(bindings.getAttribute("required") != null) {
|
||||
String requiredAttr = bindings.getAttribute("required");
|
||||
|
||||
if(requiredAttr.equals("no") || requiredAttr.equals("false") || requiredAttr.equals("0"))
|
||||
required = false;
|
||||
}
|
||||
|
||||
if(bindings.getAttribute("multiple") != null) {
|
||||
String requiredAttr = bindings.getAttribute("multiple");
|
||||
|
||||
if(requiredAttr.equals("yes") || requiredAttr.equals("true") || requiredAttr.equals("1"))
|
||||
multiple = true;
|
||||
}
|
||||
|
||||
|
||||
// look for @schemaLocation
|
||||
if( bindings.getAttributeNode("schemaLocation")!=null ) {
|
||||
String schemaLocation = bindings.getAttribute("schemaLocation");
|
||||
|
||||
// enhancement - schemaLocation="*" = bind to all schemas..
|
||||
if(schemaLocation.equals("*")) {
|
||||
for(String systemId : forest.listSystemIDs()) {
|
||||
if (result.get(bindings) == null)
|
||||
result.put(bindings, new ArrayList<Node>());
|
||||
result.get(bindings).add(forest.get(systemId).getDocumentElement());
|
||||
|
||||
Element[] children = DOMUtils.getChildElements(bindings, Const.JAXB_NSURI, "bindings");
|
||||
for (Element value : children)
|
||||
buildTargetNodeMap(value, forest.get(systemId).getDocumentElement(), inheritedSCD, result, scdResult);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
try {
|
||||
// TODO: use the URI class
|
||||
// TODO: honor xml:base
|
||||
URL loc = new URL(
|
||||
new URL(forest.getSystemId(bindings.getOwnerDocument())), schemaLocation
|
||||
);
|
||||
schemaLocation = loc.toExternalForm();
|
||||
target = forest.get(schemaLocation);
|
||||
if ((target == null) && (loc.getProtocol().startsWith("file"))) {
|
||||
File f = new File(loc.getFile());
|
||||
schemaLocation = new File(f.getCanonicalPath()).toURI().toString();
|
||||
}
|
||||
} catch( MalformedURLException e ) {
|
||||
} catch( IOException e ) {
|
||||
Logger.getLogger(Internalizer.class.getName()).log(Level.FINEST, e.getLocalizedMessage());
|
||||
}
|
||||
|
||||
target = forest.get(schemaLocation);
|
||||
if(target==null) {
|
||||
reportError( bindings,
|
||||
Messages.format(Messages.ERR_INCORRECT_SCHEMA_REFERENCE,
|
||||
schemaLocation,
|
||||
EditDistance.findNearest(schemaLocation,forest.listSystemIDs())));
|
||||
|
||||
return; // abort processing this <jaxb:bindings>
|
||||
}
|
||||
|
||||
target = ((Document)target).getDocumentElement();
|
||||
}
|
||||
}
|
||||
|
||||
// look for @node
|
||||
if( bindings.getAttributeNode("node")!=null ) {
|
||||
String nodeXPath = bindings.getAttribute("node");
|
||||
|
||||
// evaluate this XPath
|
||||
NodeList nlst;
|
||||
try {
|
||||
xpath.setNamespaceContext(new NamespaceContextImpl(bindings));
|
||||
nlst = (NodeList)xpath.evaluate(nodeXPath,target,XPathConstants.NODESET);
|
||||
} catch (XPathExpressionException e) {
|
||||
if(required) {
|
||||
reportError( bindings,
|
||||
Messages.format(Messages.ERR_XPATH_EVAL,e.getMessage()), e );
|
||||
return; // abort processing this <jaxb:bindings>
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if( nlst.getLength()==0 ) {
|
||||
if(required)
|
||||
reportError( bindings,
|
||||
Messages.format(Messages.NO_XPATH_EVAL_TO_NO_TARGET, nodeXPath) );
|
||||
return; // abort
|
||||
}
|
||||
|
||||
if( nlst.getLength()!=1 ) {
|
||||
if(!multiple) {
|
||||
reportError( bindings,
|
||||
Messages.format(Messages.NO_XPATH_EVAL_TOO_MANY_TARGETS, nodeXPath,nlst.getLength()) );
|
||||
|
||||
return; // abort
|
||||
} else {
|
||||
if(targetMultiple == null) targetMultiple = new ArrayList<Node>();
|
||||
for(int i = 0; i < nlst.getLength(); i++) {
|
||||
targetMultiple.add(nlst.item(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check
|
||||
if(!multiple || nlst.getLength() == 1) {
|
||||
Node rnode = nlst.item(0);
|
||||
if (!(rnode instanceof Element)) {
|
||||
reportError(bindings,
|
||||
Messages.format(Messages.NO_XPATH_EVAL_TO_NON_ELEMENT, nodeXPath));
|
||||
return; // abort
|
||||
}
|
||||
|
||||
if (!forest.logic.checkIfValidTargetNode(forest, bindings, (Element) rnode)) {
|
||||
reportError(bindings,
|
||||
Messages.format(Messages.XPATH_EVAL_TO_NON_SCHEMA_ELEMENT,
|
||||
nodeXPath, rnode.getNodeName()));
|
||||
return; // abort
|
||||
}
|
||||
|
||||
target = rnode;
|
||||
} else {
|
||||
for(Node rnode : targetMultiple) {
|
||||
if (!(rnode instanceof Element)) {
|
||||
reportError(bindings,
|
||||
Messages.format(Messages.NO_XPATH_EVAL_TO_NON_ELEMENT, nodeXPath));
|
||||
return; // abort
|
||||
}
|
||||
|
||||
if (!forest.logic.checkIfValidTargetNode(forest, bindings, (Element) rnode)) {
|
||||
reportError(bindings,
|
||||
Messages.format(Messages.XPATH_EVAL_TO_NON_SCHEMA_ELEMENT,
|
||||
nodeXPath, rnode.getNodeName()));
|
||||
return; // abort
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// look for @scd
|
||||
if( bindings.getAttributeNode("scd")!=null ) {
|
||||
String scdPath = bindings.getAttribute("scd");
|
||||
if(!enableSCD) {
|
||||
// SCD selector was found, but it's not activated. report an error
|
||||
// but recover by handling it anyway. this also avoids repeated error messages.
|
||||
reportError(bindings,
|
||||
Messages.format(Messages.SCD_NOT_ENABLED));
|
||||
enableSCD = true;
|
||||
}
|
||||
|
||||
try {
|
||||
inheritedSCD = scdResult.createNewTarget( inheritedSCD, bindings,
|
||||
SCD.create(scdPath, new NamespaceContextImpl(bindings)) );
|
||||
} catch (ParseException e) {
|
||||
reportError( bindings, Messages.format(Messages.ERR_SCD_EVAL,e.getMessage()),e );
|
||||
return; // abort processing this bindings
|
||||
}
|
||||
}
|
||||
|
||||
// update the result map
|
||||
if (inheritedSCD != null) {
|
||||
inheritedSCD.addBinidng(bindings);
|
||||
} else if (!multiple || targetMultiple == null) {
|
||||
if (result.get(bindings) == null)
|
||||
result.put(bindings, new ArrayList<Node>());
|
||||
result.get(bindings).add(target);
|
||||
} else {
|
||||
for (Node rnode : targetMultiple) {
|
||||
if (result.get(bindings) == null)
|
||||
result.put(bindings, new ArrayList<Node>());
|
||||
|
||||
result.get(bindings).add(rnode);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// look for child <jaxb:bindings> and process them recursively
|
||||
Element[] children = DOMUtils.getChildElements( bindings, Const.JAXB_NSURI, "bindings" );
|
||||
for (Element value : children)
|
||||
if(!multiple || targetMultiple == null)
|
||||
buildTargetNodeMap(value, target, inheritedSCD, result, scdResult);
|
||||
else {
|
||||
for(Node rnode : targetMultiple) {
|
||||
buildTargetNodeMap(value, rnode, inheritedSCD, result, scdResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves JAXB customizations under their respective target nodes.
|
||||
*/
|
||||
private void move(Element bindings, Map<Element, List<Node>> targetNodes) {
|
||||
List<Node> nodelist = targetNodes.get(bindings);
|
||||
|
||||
if(nodelist == null) {
|
||||
return; // abort
|
||||
}
|
||||
|
||||
for (Node target : nodelist) {
|
||||
if (target == null) // this must be the result of an error on the external binding.
|
||||
// recover from the error by ignoring this node
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (Element item : DOMUtils.getChildElements(bindings)) {
|
||||
String localName = item.getLocalName();
|
||||
|
||||
if ("bindings".equals(localName)) {
|
||||
// process child <jaxb:bindings> recursively
|
||||
move(item, targetNodes);
|
||||
} else if ("globalBindings".equals(localName)) {
|
||||
// <jaxb:globalBindings> always go to the root of document.
|
||||
Element root = forest.getOneDocument().getDocumentElement();
|
||||
if (root.getNamespaceURI().equals(WSDL_NS)) {
|
||||
NodeList elements = root.getElementsByTagNameNS(XMLConstants.W3C_XML_SCHEMA_NS_URI, "schema");
|
||||
if ((elements == null) || (elements.getLength() < 1)) {
|
||||
reportError(item, Messages.format(Messages.ORPHANED_CUSTOMIZATION, item.getNodeName()));
|
||||
return;
|
||||
} else {
|
||||
moveUnder(item, (Element)elements.item(0));
|
||||
}
|
||||
} else {
|
||||
moveUnder(item, root);
|
||||
}
|
||||
} else {
|
||||
if (!(target instanceof Element)) {
|
||||
reportError(item,
|
||||
Messages.format(Messages.CONTEXT_NODE_IS_NOT_ELEMENT));
|
||||
return; // abort
|
||||
}
|
||||
|
||||
if (!forest.logic.checkIfValidTargetNode(forest, item, (Element) target)) {
|
||||
reportError(item,
|
||||
Messages.format(Messages.ORPHANED_CUSTOMIZATION, item.getNodeName()));
|
||||
return; // abort
|
||||
}
|
||||
|
||||
// move this node under the target
|
||||
moveUnder(item, (Element) target);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the "decl" node under the "target" node.
|
||||
*
|
||||
* @param decl
|
||||
* A JAXB customization element (e.g., <jaxb:class>)
|
||||
*
|
||||
* @param target
|
||||
* XML Schema element under which the declaration should move.
|
||||
* For example, <xs:element>
|
||||
*/
|
||||
private void moveUnder( Element decl, Element target ) {
|
||||
Element realTarget = forest.logic.refineTarget(target);
|
||||
|
||||
declExtensionNamespace( decl, target );
|
||||
|
||||
// copy in-scope namespace declarations of the decl node
|
||||
// to the decl node itself so that this move won't change
|
||||
// the in-scope namespace bindings.
|
||||
Element p = decl;
|
||||
Set<String> inscopes = new HashSet<String>();
|
||||
while(true) {
|
||||
NamedNodeMap atts = p.getAttributes();
|
||||
for( int i=0; i<atts.getLength(); i++ ) {
|
||||
Attr a = (Attr)atts.item(i);
|
||||
if( Const.XMLNS_URI.equals(a.getNamespaceURI()) ) {
|
||||
String prefix;
|
||||
if( a.getName().indexOf(':')==-1 ) prefix = "";
|
||||
else prefix = a.getLocalName();
|
||||
|
||||
if( inscopes.add(prefix) && p!=decl ) {
|
||||
// if this is the first time we see this namespace bindings,
|
||||
// copy the declaration.
|
||||
// if p==decl, there's no need to. Note that
|
||||
// we want to add prefix to inscopes even if p==Decl
|
||||
|
||||
decl.setAttributeNodeNS( (Attr)a.cloneNode(true) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( p.getParentNode() instanceof Document )
|
||||
break;
|
||||
|
||||
p = (Element)p.getParentNode();
|
||||
}
|
||||
|
||||
if( !inscopes.contains("") ) {
|
||||
// if the default namespace was undeclared in the context of decl,
|
||||
// it must be explicitly set to "" since the new environment might
|
||||
// have a different default namespace URI.
|
||||
decl.setAttributeNS(Const.XMLNS_URI,"xmlns","");
|
||||
}
|
||||
|
||||
|
||||
// finally move the declaration to the target node.
|
||||
if( realTarget.getOwnerDocument()!=decl.getOwnerDocument() ) {
|
||||
// if they belong to different DOM documents, we need to clone them
|
||||
Element original = decl;
|
||||
decl = (Element)realTarget.getOwnerDocument().importNode(decl,true);
|
||||
|
||||
// this effectively clones a ndoe,, so we need to copy locators.
|
||||
copyLocators( original, decl );
|
||||
}
|
||||
|
||||
realTarget.appendChild( decl );
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively visits sub-elements and declare all used namespaces.
|
||||
* TODO: the fact that we recognize all namespaces in the extension
|
||||
* is a bad design.
|
||||
*/
|
||||
private void declExtensionNamespace(Element decl, Element target) {
|
||||
// if this comes from external namespaces, add the namespace to
|
||||
// @extensionBindingPrefixes.
|
||||
if( !Const.JAXB_NSURI.equals(decl.getNamespaceURI()) )
|
||||
declareExtensionNamespace( target, decl.getNamespaceURI() );
|
||||
|
||||
NodeList lst = decl.getChildNodes();
|
||||
for( int i=0; i<lst.getLength(); i++ ) {
|
||||
Node n = lst.item(i);
|
||||
if( n instanceof Element )
|
||||
declExtensionNamespace( (Element)n, target );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Attribute name. */
|
||||
private static final String EXTENSION_PREFIXES = "extensionBindingPrefixes";
|
||||
|
||||
/**
|
||||
* Adds the specified namespace URI to the jaxb:extensionBindingPrefixes
|
||||
* attribute of the target document.
|
||||
*/
|
||||
private void declareExtensionNamespace( Element target, String nsUri ) {
|
||||
// look for the attribute
|
||||
Element root = target.getOwnerDocument().getDocumentElement();
|
||||
Attr att = root.getAttributeNodeNS(Const.JAXB_NSURI,EXTENSION_PREFIXES);
|
||||
if( att==null ) {
|
||||
String jaxbPrefix = allocatePrefix(root,Const.JAXB_NSURI);
|
||||
// no such attribute. Create one.
|
||||
att = target.getOwnerDocument().createAttributeNS(
|
||||
Const.JAXB_NSURI,jaxbPrefix+':'+EXTENSION_PREFIXES);
|
||||
root.setAttributeNodeNS(att);
|
||||
}
|
||||
|
||||
String prefix = allocatePrefix(root,nsUri);
|
||||
if( att.getValue().indexOf(prefix)==-1 )
|
||||
// avoid redeclaring the same namespace twice.
|
||||
att.setValue( att.getValue()+' '+prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Declares a new prefix on the given element and associates it
|
||||
* with the specified namespace URI.
|
||||
* <p>
|
||||
* Note that this method doesn't use the default namespace
|
||||
* even if it can.
|
||||
*/
|
||||
private String allocatePrefix( Element e, String nsUri ) {
|
||||
// look for existing namespaces.
|
||||
NamedNodeMap atts = e.getAttributes();
|
||||
for( int i=0; i<atts.getLength(); i++ ) {
|
||||
Attr a = (Attr)atts.item(i);
|
||||
if( Const.XMLNS_URI.equals(a.getNamespaceURI()) ) {
|
||||
if( a.getName().indexOf(':')==-1 ) continue;
|
||||
|
||||
if( a.getValue().equals(nsUri) )
|
||||
return a.getLocalName(); // found one
|
||||
}
|
||||
}
|
||||
|
||||
// none found. allocate new.
|
||||
while(true) {
|
||||
String prefix = "p"+(int)(Math.random()*1000000)+'_';
|
||||
if(e.getAttributeNodeNS(Const.XMLNS_URI,prefix)!=null)
|
||||
continue; // this prefix is already allocated.
|
||||
|
||||
e.setAttributeNS(Const.XMLNS_URI,"xmlns:"+prefix,nsUri);
|
||||
return prefix;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copies location information attached to the "src" node to the "dst" node.
|
||||
*/
|
||||
private void copyLocators( Element src, Element dst ) {
|
||||
forest.locatorTable.storeStartLocation(
|
||||
dst, forest.locatorTable.getStartLocation(src) );
|
||||
forest.locatorTable.storeEndLocation(
|
||||
dst, forest.locatorTable.getEndLocation(src) );
|
||||
|
||||
// recursively process child elements
|
||||
Element[] srcChilds = DOMUtils.getChildElements(src);
|
||||
Element[] dstChilds = DOMUtils.getChildElements(dst);
|
||||
|
||||
for( int i=0; i<srcChilds.length; i++ )
|
||||
copyLocators( srcChilds[i], dstChilds[i] );
|
||||
}
|
||||
|
||||
|
||||
private void reportError( Element errorSource, String formattedMsg ) {
|
||||
reportError( errorSource, formattedMsg, null );
|
||||
}
|
||||
|
||||
private void reportError( Element errorSource,
|
||||
String formattedMsg, Exception nestedException ) {
|
||||
|
||||
SAXParseException e = new SAXParseException2( formattedMsg,
|
||||
forest.locatorTable.getStartLocation(errorSource),
|
||||
nestedException );
|
||||
errorHandler.error(e);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.internalizer;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.xml.sax.Locator;
|
||||
import org.xml.sax.helpers.LocatorImpl;
|
||||
|
||||
/**
|
||||
* Stores {@link Locator} objects for every {@link Element}.
|
||||
*
|
||||
* @author
|
||||
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
public final class LocatorTable {
|
||||
/** Locations of the start element. */
|
||||
private final Map startLocations = new HashMap();
|
||||
|
||||
/** Locations of the end element. */
|
||||
private final Map endLocations = new HashMap();
|
||||
|
||||
public void storeStartLocation( Element e, Locator loc ) {
|
||||
startLocations.put(e,new LocatorImpl(loc));
|
||||
}
|
||||
|
||||
public void storeEndLocation( Element e, Locator loc ) {
|
||||
endLocations.put(e,new LocatorImpl(loc));
|
||||
}
|
||||
|
||||
public Locator getStartLocation( Element e ) {
|
||||
return (Locator)startLocations.get(e);
|
||||
}
|
||||
|
||||
public Locator getEndLocation( Element e ) {
|
||||
return (Locator)endLocations.get(e);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.internalizer;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
/**
|
||||
* Formats error messages.
|
||||
*/
|
||||
class Messages
|
||||
{
|
||||
/** Loads a string resource and formats it with specified arguments. */
|
||||
static String format( String property, Object... args ) {
|
||||
String text = ResourceBundle.getBundle(Messages.class.getPackage().getName() +".MessageBundle").getString(property);
|
||||
return MessageFormat.format(text,args);
|
||||
}
|
||||
|
||||
static final String ERR_INCORRECT_SCHEMA_REFERENCE = // args:2
|
||||
"Internalizer.IncorrectSchemaReference";
|
||||
static final String ERR_XPATH_EVAL = // arg:1
|
||||
"Internalizer.XPathEvaluationError";
|
||||
static final String NO_XPATH_EVAL_TO_NO_TARGET = // arg:1
|
||||
"Internalizer.XPathEvaluatesToNoTarget";
|
||||
static final String NO_XPATH_EVAL_TOO_MANY_TARGETS = // arg:2
|
||||
"Internalizer.XPathEvaulatesToTooManyTargets";
|
||||
static final String NO_XPATH_EVAL_TO_NON_ELEMENT = // arg:1
|
||||
"Internalizer.XPathEvaluatesToNonElement";
|
||||
static final String XPATH_EVAL_TO_NON_SCHEMA_ELEMENT = // arg:2
|
||||
"Internalizer.XPathEvaluatesToNonSchemaElement";
|
||||
static final String SCD_NOT_ENABLED = // arg:0
|
||||
"SCD_NOT_ENABLED";
|
||||
static final String ERR_SCD_EVAL = // arg: 1
|
||||
"ERR_SCD_EVAL";
|
||||
static final String ERR_SCD_EVALUATED_EMPTY = // arg:1
|
||||
"ERR_SCD_EVALUATED_EMPTY";
|
||||
static final String ERR_SCD_MATCHED_MULTIPLE_NODES = // arg:2
|
||||
"ERR_SCD_MATCHED_MULTIPLE_NODES";
|
||||
static final String ERR_SCD_MATCHED_MULTIPLE_NODES_FIRST = // arg:1
|
||||
"ERR_SCD_MATCHED_MULTIPLE_NODES_FIRST";
|
||||
static final String ERR_SCD_MATCHED_MULTIPLE_NODES_SECOND = // arg:1
|
||||
"ERR_SCD_MATCHED_MULTIPLE_NODES_SECOND";
|
||||
static final String CONTEXT_NODE_IS_NOT_ELEMENT = // arg:0
|
||||
"Internalizer.ContextNodeIsNotElement";
|
||||
static final String ERR_INCORRECT_VERSION = // arg:0
|
||||
"Internalizer.IncorrectVersion";
|
||||
static final String ERR_VERSION_NOT_FOUND = // arg:0
|
||||
"Internalizer.VersionNotPresent";
|
||||
static final String TWO_VERSION_ATTRIBUTES = // arg:0
|
||||
"Internalizer.TwoVersionAttributes";
|
||||
static final String ORPHANED_CUSTOMIZATION = // arg:1
|
||||
"Internalizer.OrphanedCustomization";
|
||||
static final String ERR_UNABLE_TO_PARSE = // arg:2
|
||||
"AbstractReferenceFinderImpl.UnableToParse";
|
||||
static final String ERR_FILENAME_IS_NOT_URI = // arg:0
|
||||
"ERR_FILENAME_IS_NOT_URI";
|
||||
static final String ERR_GENERAL_SCHEMA_CORRECTNESS_ERROR = // arg:1
|
||||
"ERR_GENERAL_SCHEMA_CORRECTNESS_ERROR";
|
||||
static final String DOMFOREST_INPUTSOURCE_IOEXCEPTION = // arg:2
|
||||
"DOMFOREST_INPUTSOURCE_IOEXCEPTION";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
* THIS FILE WAS MODIFIED BY SUN MICROSYSTEMS, INC.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.internalizer;
|
||||
|
||||
import java.util.Iterator;
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.namespace.NamespaceContext;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* Implements {@link NamespaceContext} by looking at the in-scope
|
||||
* namespace binding of a DOM element.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class NamespaceContextImpl implements NamespaceContext {
|
||||
private final Element e;
|
||||
|
||||
public NamespaceContextImpl(Element e) {
|
||||
this.e = e;
|
||||
}
|
||||
|
||||
public String getNamespaceURI(String prefix) {
|
||||
Node parent = e;
|
||||
String namespace = null;
|
||||
final String prefixColon = prefix + ':';
|
||||
|
||||
if (prefix.equals("xml")) {
|
||||
namespace = XMLConstants.XML_NS_URI;
|
||||
} else {
|
||||
int type;
|
||||
|
||||
while ((null != parent) && (null == namespace)
|
||||
&& (((type = parent.getNodeType()) == Node.ELEMENT_NODE)
|
||||
|| (type == Node.ENTITY_REFERENCE_NODE))) {
|
||||
if (type == Node.ELEMENT_NODE) {
|
||||
if (parent.getNodeName().startsWith(prefixColon))
|
||||
return parent.getNamespaceURI();
|
||||
NamedNodeMap nnm = parent.getAttributes();
|
||||
|
||||
for (int i = 0; i < nnm.getLength(); i++) {
|
||||
Node attr = nnm.item(i);
|
||||
String aname = attr.getNodeName();
|
||||
boolean isPrefix = aname.startsWith("xmlns:");
|
||||
|
||||
if (isPrefix || aname.equals("xmlns")) {
|
||||
int index = aname.indexOf(':');
|
||||
String p = isPrefix ? aname.substring(index + 1) : "";
|
||||
|
||||
if (p.equals(prefix)) {
|
||||
namespace = attr.getNodeValue();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parent = parent.getParentNode();
|
||||
}
|
||||
}
|
||||
|
||||
if(prefix.equals(""))
|
||||
return ""; // default namespace
|
||||
return namespace;
|
||||
}
|
||||
|
||||
public String getPrefix(String namespaceURI) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Iterator getPrefixes(String namespaceURI) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.internalizer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import javax.xml.bind.UnmarshallerHandler;
|
||||
import javax.xml.validation.ValidatorHandler;
|
||||
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import com.sun.istack.internal.SAXParseException2;
|
||||
import com.sun.tools.internal.xjc.ErrorReceiver;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIDeclaration;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BindInfo;
|
||||
import com.sun.tools.internal.xjc.util.ForkContentHandler;
|
||||
import com.sun.tools.internal.xjc.util.DOMUtils;
|
||||
import com.sun.xml.internal.xsom.SCD;
|
||||
import com.sun.xml.internal.xsom.XSAnnotation;
|
||||
import com.sun.xml.internal.xsom.XSComponent;
|
||||
import com.sun.xml.internal.xsom.XSSchemaSet;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXParseException;
|
||||
|
||||
/**
|
||||
* Set of binding nodes that have target nodes specified via SCD.
|
||||
*
|
||||
* This is parsed during {@link Internalizer} works on the tree,
|
||||
* but applying this has to wait for {@link XSSchemaSet} to be parsed.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
* @see SCD
|
||||
*/
|
||||
public final class SCDBasedBindingSet {
|
||||
|
||||
/**
|
||||
* Represents the target schema component of the
|
||||
* customization identified by SCD.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class Target {
|
||||
/**
|
||||
* SCDs can be specified via multiple steps, like:
|
||||
*
|
||||
* <xmp>
|
||||
* <bindings scd="foo/bar">
|
||||
* <bindings scd="zot/xyz">
|
||||
* </xmp>
|
||||
*
|
||||
* This field and {@link #nextSibling} form a single-linked list that
|
||||
* represent the children that shall be evaluated within this target.
|
||||
* Think of it as {@code List<Target>}.
|
||||
*/
|
||||
private Target firstChild;
|
||||
private final Target nextSibling;
|
||||
|
||||
/**
|
||||
* Compiled SCD.
|
||||
*/
|
||||
private final @NotNull SCD scd;
|
||||
|
||||
/**
|
||||
* The element on which SCD was found.
|
||||
*/
|
||||
private final @NotNull Element src;
|
||||
|
||||
/**
|
||||
* Bindings that apply to this SCD.
|
||||
*/
|
||||
private final List<Element> bindings = new ArrayList<Element>();
|
||||
|
||||
private Target(Target parent, Element src, SCD scd) {
|
||||
if(parent==null) {
|
||||
this.nextSibling = topLevel;
|
||||
topLevel = this;
|
||||
} else {
|
||||
this.nextSibling = parent.firstChild;
|
||||
parent.firstChild = this;
|
||||
}
|
||||
this.src = src;
|
||||
this.scd = scd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new binding declaration to be associated to the schema component
|
||||
* identified by {@link #scd}.
|
||||
*/
|
||||
void addBinidng(Element binding) {
|
||||
bindings.add(binding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies bindings to the schema component for this and its siblings.
|
||||
*/
|
||||
private void applyAll(Collection<? extends XSComponent> contextNode) {
|
||||
for( Target self=this; self!=null; self=self.nextSibling )
|
||||
self.apply(contextNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies bindings to the schema component for just this node.
|
||||
*/
|
||||
private void apply(Collection<? extends XSComponent> contextNode) {
|
||||
// apply the SCD...
|
||||
Collection<XSComponent> childNodes = scd.select(contextNode);
|
||||
if(childNodes.isEmpty()) {
|
||||
// no node matched
|
||||
if(src.getAttributeNode("if-exists")!=null) {
|
||||
// if this attribute exists, it's not an error if SCD didn't match.
|
||||
return;
|
||||
}
|
||||
|
||||
reportError( src, Messages.format(Messages.ERR_SCD_EVALUATED_EMPTY,scd) );
|
||||
return;
|
||||
}
|
||||
|
||||
if(firstChild!=null)
|
||||
firstChild.applyAll(childNodes);
|
||||
|
||||
if(!bindings.isEmpty()) {
|
||||
// error to match more than one components
|
||||
Iterator<XSComponent> itr = childNodes.iterator();
|
||||
XSComponent target = itr.next();
|
||||
if(itr.hasNext()) {
|
||||
reportError( src, Messages.format(Messages.ERR_SCD_MATCHED_MULTIPLE_NODES,scd,childNodes.size()) );
|
||||
errorReceiver.error( target.getLocator(), Messages.format(Messages.ERR_SCD_MATCHED_MULTIPLE_NODES_FIRST) );
|
||||
errorReceiver.error( itr.next().getLocator(), Messages.format(Messages.ERR_SCD_MATCHED_MULTIPLE_NODES_SECOND) );
|
||||
}
|
||||
|
||||
// apply bindings to the target
|
||||
for (Element binding : bindings) {
|
||||
for (Element item : DOMUtils.getChildElements(binding)) {
|
||||
String localName = item.getLocalName();
|
||||
|
||||
if ("bindings".equals(localName))
|
||||
continue; // this should be already in Target.bindings of some SpecVersion.
|
||||
|
||||
try {
|
||||
new DOMForestScanner(forest).scan(item,loader);
|
||||
BIDeclaration decl = (BIDeclaration)unmarshaller.getResult();
|
||||
|
||||
// add this binding to the target
|
||||
XSAnnotation ann = target.getAnnotation(true);
|
||||
BindInfo bi = (BindInfo)ann.getAnnotation();
|
||||
if(bi==null) {
|
||||
bi = new BindInfo();
|
||||
ann.setAnnotation(bi);
|
||||
}
|
||||
bi.addDecl(decl);
|
||||
} catch (SAXException e) {
|
||||
// the error should have already been reported.
|
||||
} catch (JAXBException e) {
|
||||
// if validation didn't fail, then unmarshalling can't go wrong
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Target topLevel;
|
||||
|
||||
/**
|
||||
* The forest where binding elements came from. Needed to report line numbers for errors.
|
||||
*/
|
||||
private final DOMForest forest;
|
||||
|
||||
|
||||
// variables used only during the apply method
|
||||
//
|
||||
private ErrorReceiver errorReceiver;
|
||||
private UnmarshallerHandler unmarshaller;
|
||||
private ForkContentHandler loader; // unmarshaller+validator
|
||||
|
||||
SCDBasedBindingSet(DOMForest forest) {
|
||||
this.forest = forest;
|
||||
}
|
||||
|
||||
Target createNewTarget(Target parent, Element src, SCD scd) {
|
||||
return new Target(parent,src,scd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the additional binding customizations.
|
||||
*/
|
||||
public void apply(XSSchemaSet schema, ErrorReceiver errorReceiver) {
|
||||
if(topLevel!=null) {
|
||||
this.errorReceiver = errorReceiver;
|
||||
Unmarshaller u = BindInfo.getCustomizationUnmarshaller();
|
||||
this.unmarshaller = u.getUnmarshallerHandler();
|
||||
ValidatorHandler v = BindInfo.bindingFileSchema.newValidator();
|
||||
v.setErrorHandler(errorReceiver);
|
||||
loader = new ForkContentHandler(v,unmarshaller);
|
||||
|
||||
topLevel.applyAll(schema.getSchemas());
|
||||
|
||||
this.loader = null;
|
||||
this.unmarshaller = null;
|
||||
this.errorReceiver = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void reportError( Element errorSource, String formattedMsg ) {
|
||||
reportError( errorSource, formattedMsg, null );
|
||||
}
|
||||
|
||||
private void reportError( Element errorSource,
|
||||
String formattedMsg, Exception nestedException ) {
|
||||
|
||||
SAXParseException e = new SAXParseException2( formattedMsg,
|
||||
forest.locatorTable.getStartLocation(errorSource),
|
||||
nestedException );
|
||||
errorReceiver.error(e);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.internalizer;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.sun.tools.internal.xjc.reader.Const;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.EntityResolver;
|
||||
import org.xml.sax.ErrorHandler;
|
||||
import org.xml.sax.Locator;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXParseException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.LocatorImpl;
|
||||
import org.xml.sax.helpers.XMLFilterImpl;
|
||||
|
||||
/**
|
||||
* Checks the jaxb:version attribute on a XML Schema document.
|
||||
*
|
||||
* jaxb:version is optional if no binding customization is used,
|
||||
* but if present, its value must be "1.0".
|
||||
*
|
||||
* @author
|
||||
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
public class VersionChecker extends XMLFilterImpl {
|
||||
|
||||
/**
|
||||
* We store the value of the version attribute in this variable
|
||||
* when we hit the root element.
|
||||
*/
|
||||
private String version = null ;
|
||||
|
||||
/** Will be set to true once we hit the root element. */
|
||||
private boolean seenRoot = false;
|
||||
|
||||
/** Will be set to true once we hit a binding declaration. */
|
||||
private boolean seenBindings = false;
|
||||
|
||||
private Locator locator;
|
||||
|
||||
/**
|
||||
* Stores the location of the start tag of the root tag.
|
||||
*/
|
||||
private Locator rootTagStart;
|
||||
|
||||
public VersionChecker( XMLReader parent ) {
|
||||
setParent(parent);
|
||||
}
|
||||
|
||||
public VersionChecker( ContentHandler handler,ErrorHandler eh,EntityResolver er ) {
|
||||
setContentHandler(handler);
|
||||
if(eh!=null) setErrorHandler(eh);
|
||||
if(er!=null) setEntityResolver(er);
|
||||
}
|
||||
|
||||
public void startElement(String namespaceURI, String localName, String qName, Attributes atts)
|
||||
throws SAXException {
|
||||
|
||||
super.startElement(namespaceURI, localName, qName, atts);
|
||||
|
||||
if(!seenRoot) {
|
||||
// if this is the root element
|
||||
seenRoot = true;
|
||||
rootTagStart = new LocatorImpl(locator);
|
||||
|
||||
version = atts.getValue(Const.JAXB_NSURI,"version");
|
||||
if( namespaceURI.equals(Const.JAXB_NSURI) ) {
|
||||
String version2 = atts.getValue("","version");
|
||||
if( version!=null && version2!=null ) {
|
||||
// we have both @version and @jaxb:version. error.
|
||||
SAXParseException e = new SAXParseException(
|
||||
Messages.format( Messages.TWO_VERSION_ATTRIBUTES ), locator );
|
||||
getErrorHandler().error(e);
|
||||
}
|
||||
if( version==null )
|
||||
version = version2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( Const.JAXB_NSURI.equals(namespaceURI) )
|
||||
seenBindings = true;
|
||||
}
|
||||
|
||||
public void endDocument() throws SAXException {
|
||||
super.endDocument();
|
||||
|
||||
if( seenBindings && version==null ) {
|
||||
// if we see a binding declaration but not version attribute
|
||||
SAXParseException e = new SAXParseException(
|
||||
Messages.format(Messages.ERR_VERSION_NOT_FOUND),rootTagStart);
|
||||
getErrorHandler().error(e);
|
||||
}
|
||||
|
||||
// if present, the value must be either 1.0 or 2.0
|
||||
if( version!=null && !VERSIONS.contains(version) ) {
|
||||
SAXParseException e = new SAXParseException(
|
||||
Messages.format(Messages.ERR_INCORRECT_VERSION),rootTagStart);
|
||||
getErrorHandler().error(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setDocumentLocator(Locator locator) {
|
||||
super.setDocumentLocator(locator);
|
||||
this.locator = locator;
|
||||
}
|
||||
|
||||
private static final Set<String> VERSIONS = new HashSet<String>(Arrays.asList("1.0","2.0","2.1"));
|
||||
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.internalizer;
|
||||
|
||||
import com.sun.xml.internal.bind.WhiteSpaceProcessor;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.EntityResolver;
|
||||
import org.xml.sax.ErrorHandler;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.XMLFilterImpl;
|
||||
|
||||
/**
|
||||
* Strips ignorable whitespace from SAX event stream.
|
||||
*
|
||||
* <p>
|
||||
* This filter works only when the event stream doesn't
|
||||
* contain any mixed content.
|
||||
*
|
||||
* @author
|
||||
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
class WhitespaceStripper extends XMLFilterImpl {
|
||||
|
||||
private int state = 0;
|
||||
|
||||
private char[] buf = new char[1024];
|
||||
private int bufLen = 0;
|
||||
|
||||
private static final int AFTER_START_ELEMENT = 1;
|
||||
private static final int AFTER_END_ELEMENT = 2;
|
||||
|
||||
public WhitespaceStripper(XMLReader reader) {
|
||||
setParent(reader);
|
||||
}
|
||||
|
||||
public WhitespaceStripper(ContentHandler handler,ErrorHandler eh,EntityResolver er) {
|
||||
setContentHandler(handler);
|
||||
if(eh!=null) setErrorHandler(eh);
|
||||
if(er!=null) setEntityResolver(er);
|
||||
}
|
||||
|
||||
public void characters(char[] ch, int start, int length) throws SAXException {
|
||||
switch(state) {
|
||||
case AFTER_START_ELEMENT:
|
||||
// we have to store the characters here, even if it consists entirely
|
||||
// of whitespaces. This is because successive characters event might
|
||||
// include non-whitespace char, in which case all the whitespaces in
|
||||
// this event may suddenly become significant.
|
||||
if( bufLen+length>buf.length ) {
|
||||
// reallocate buffer
|
||||
char[] newBuf = new char[Math.max(bufLen+length,buf.length*2)];
|
||||
System.arraycopy(buf,0,newBuf,0,bufLen);
|
||||
buf = newBuf;
|
||||
}
|
||||
System.arraycopy(ch,start,buf,bufLen,length);
|
||||
bufLen += length;
|
||||
break;
|
||||
case AFTER_END_ELEMENT:
|
||||
// check if this is ignorable.
|
||||
int len = start+length;
|
||||
for( int i=start; i<len; i++ )
|
||||
if( !WhiteSpaceProcessor.isWhiteSpace(ch[i]) ) {
|
||||
super.characters(ch, start, length);
|
||||
return;
|
||||
}
|
||||
// if it's entirely whitespace, ignore it.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
|
||||
processPendingText();
|
||||
super.startElement(uri, localName, qName, atts);
|
||||
state = AFTER_START_ELEMENT;
|
||||
bufLen = 0;
|
||||
}
|
||||
|
||||
public void endElement(String uri, String localName, String qName) throws SAXException {
|
||||
processPendingText();
|
||||
super.endElement(uri, localName, qName);
|
||||
state = AFTER_END_ELEMENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwars the buffered characters if it contains any non-whitespace
|
||||
* character.
|
||||
*/
|
||||
private void processPendingText() throws SAXException {
|
||||
if(state==AFTER_START_ELEMENT) {
|
||||
for( int i=bufLen-1; i>=0; i-- )
|
||||
if( !WhiteSpaceProcessor.isWhiteSpace(buf[i]) ) {
|
||||
super.characters(buf, 0, bufLen);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
|
||||
// ignore completely.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.relaxng;
|
||||
|
||||
/**
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
enum BindStyle {
|
||||
TYPE, ELEMENT
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.relaxng;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import com.sun.tools.internal.xjc.model.CAttributePropertyInfo;
|
||||
import com.sun.tools.internal.xjc.model.CClassInfo;
|
||||
import com.sun.tools.internal.xjc.model.CElementPropertyInfo;
|
||||
import com.sun.tools.internal.xjc.model.CReferencePropertyInfo;
|
||||
import com.sun.tools.internal.xjc.model.Multiplicity;
|
||||
import com.sun.tools.internal.xjc.reader.RawTypeSet;
|
||||
import com.sun.xml.internal.bind.v2.model.core.ID;
|
||||
|
||||
import com.sun.xml.internal.rngom.digested.DAttributePattern;
|
||||
import com.sun.xml.internal.rngom.digested.DChoicePattern;
|
||||
import com.sun.xml.internal.rngom.digested.DMixedPattern;
|
||||
import com.sun.xml.internal.rngom.digested.DOneOrMorePattern;
|
||||
import com.sun.xml.internal.rngom.digested.DOptionalPattern;
|
||||
import com.sun.xml.internal.rngom.digested.DPattern;
|
||||
import com.sun.xml.internal.rngom.digested.DPatternWalker;
|
||||
import com.sun.xml.internal.rngom.digested.DZeroOrMorePattern;
|
||||
|
||||
import static com.sun.tools.internal.xjc.model.CElementPropertyInfo.CollectionMode.REPEATED_ELEMENT;
|
||||
|
||||
/**
|
||||
* Recursively visits {@link DPattern} and
|
||||
* decides which patterns to map to properties.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class ContentModelBinder extends DPatternWalker {
|
||||
private final RELAXNGCompiler compiler;
|
||||
private final CClassInfo clazz;
|
||||
|
||||
private boolean insideOptional = false;
|
||||
private int iota=1;
|
||||
|
||||
public ContentModelBinder(RELAXNGCompiler compiler,CClassInfo clazz) {
|
||||
this.compiler = compiler;
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
public Void onMixed(DMixedPattern p) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Void onChoice(DChoicePattern p) {
|
||||
boolean old = insideOptional;
|
||||
insideOptional = true;
|
||||
super.onChoice(p);
|
||||
insideOptional = old;
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void onOptional(DOptionalPattern p) {
|
||||
boolean old = insideOptional;
|
||||
insideOptional = true;
|
||||
super.onOptional(p);
|
||||
insideOptional = old;
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void onZeroOrMore(DZeroOrMorePattern p) {
|
||||
return onRepeated(p,true);
|
||||
}
|
||||
|
||||
public Void onOneOrMore(DOneOrMorePattern p) {
|
||||
return onRepeated(p,insideOptional);
|
||||
|
||||
}
|
||||
|
||||
private Void onRepeated(DPattern p,boolean optional) {
|
||||
RawTypeSet rts = RawTypeSetBuilder.build(compiler, p, optional? Multiplicity.STAR : Multiplicity.PLUS);
|
||||
if(rts.canBeTypeRefs==RawTypeSet.Mode.SHOULD_BE_TYPEREF) {
|
||||
CElementPropertyInfo prop = new CElementPropertyInfo(
|
||||
calcName(p),REPEATED_ELEMENT,ID.NONE,null,null,null,p.getLocation(),!optional);
|
||||
rts.addTo(prop);
|
||||
clazz.addProperty(prop);
|
||||
} else {
|
||||
CReferencePropertyInfo prop = new CReferencePropertyInfo(
|
||||
calcName(p),true,!optional,false/*TODO*/,null,null,p.getLocation(), false, false, false);
|
||||
rts.addTo(prop);
|
||||
clazz.addProperty(prop);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void onAttribute(DAttributePattern p) {
|
||||
// TODO: support multiple names
|
||||
QName name = p.getName().listNames().iterator().next();
|
||||
|
||||
CAttributePropertyInfo ap = new CAttributePropertyInfo(
|
||||
calcName(p), null,null/*TODO*/, p.getLocation(), name,
|
||||
p.getChild().accept(compiler.typeUseBinder), null,
|
||||
!insideOptional);
|
||||
clazz.addProperty(ap);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private String calcName(DPattern p) {
|
||||
// TODO
|
||||
return "field"+(iota++);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.relaxng;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.sun.tools.internal.xjc.model.CBuiltinLeafInfo;
|
||||
import com.sun.tools.internal.xjc.model.TypeUse;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.SimpleTypeBuilder;
|
||||
|
||||
import com.sun.xml.internal.rngom.xml.util.WellKnownNamespaces;
|
||||
|
||||
/**
|
||||
* Data-bindable datatype library.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class DatatypeLib {
|
||||
/**
|
||||
* Datatype library's namespace URI.
|
||||
*/
|
||||
public final String nsUri;
|
||||
|
||||
private final Map<String,TypeUse> types = new HashMap<String,TypeUse>();
|
||||
|
||||
public DatatypeLib(String nsUri) {
|
||||
this.nsUri = nsUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the type name to the information.
|
||||
*/
|
||||
TypeUse get(String name) {
|
||||
return types.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Datatype library for the built-in type.
|
||||
*/
|
||||
public static final DatatypeLib BUILTIN = new DatatypeLib("");
|
||||
|
||||
/**
|
||||
* Datatype library for XML Schema datatypes.
|
||||
*/
|
||||
public static final DatatypeLib XMLSCHEMA = new DatatypeLib(WellKnownNamespaces.XML_SCHEMA_DATATYPES);
|
||||
|
||||
static {
|
||||
BUILTIN.types.put("token",CBuiltinLeafInfo.TOKEN);
|
||||
BUILTIN.types.put("string",CBuiltinLeafInfo.STRING);
|
||||
XMLSCHEMA.types.putAll(SimpleTypeBuilder.builtinConversions);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.relaxng;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.sun.xml.internal.rngom.digested.DDefine;
|
||||
import com.sun.xml.internal.rngom.digested.DGrammarPattern;
|
||||
import com.sun.xml.internal.rngom.digested.DPatternWalker;
|
||||
import com.sun.xml.internal.rngom.digested.DRefPattern;
|
||||
|
||||
/**
|
||||
* Recursively find all {@link DDefine}s in the grammar.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class DefineFinder extends DPatternWalker {
|
||||
|
||||
public final Set<DDefine> defs = new HashSet<DDefine>();
|
||||
|
||||
public Void onGrammar(DGrammarPattern p) {
|
||||
for( DDefine def : p ) {
|
||||
defs.add(def);
|
||||
def.getPattern().accept(this);
|
||||
}
|
||||
|
||||
return p.getStart().accept(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* We visit all {@link DDefine}s from {@link DGrammarPattern},
|
||||
* so no point in resolving refs.
|
||||
*/
|
||||
public Void onRef(DRefPattern p) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.relaxng;
|
||||
|
||||
import com.sun.xml.internal.rngom.digested.DPatternWalker;
|
||||
|
||||
/**
|
||||
* Decides the name for a particle.
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
class NameCalculator extends DPatternWalker {
|
||||
}
|
||||
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.relaxng;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import com.sun.codemodel.internal.JCodeModel;
|
||||
import com.sun.codemodel.internal.JPackage;
|
||||
import com.sun.tools.internal.xjc.Options;
|
||||
import com.sun.tools.internal.xjc.model.CBuiltinLeafInfo;
|
||||
import com.sun.tools.internal.xjc.model.CClassInfo;
|
||||
import com.sun.tools.internal.xjc.model.CClassInfoParent;
|
||||
import com.sun.tools.internal.xjc.model.CEnumConstant;
|
||||
import com.sun.tools.internal.xjc.model.CEnumLeafInfo;
|
||||
import com.sun.tools.internal.xjc.model.CNonElement;
|
||||
import com.sun.tools.internal.xjc.model.CTypeInfo;
|
||||
import com.sun.tools.internal.xjc.model.Model;
|
||||
import com.sun.tools.internal.xjc.model.TypeUse;
|
||||
import com.sun.xml.internal.bind.api.impl.NameConverter;
|
||||
|
||||
import com.sun.xml.internal.rngom.digested.DChoicePattern;
|
||||
import com.sun.xml.internal.rngom.digested.DDefine;
|
||||
import com.sun.xml.internal.rngom.digested.DElementPattern;
|
||||
import com.sun.xml.internal.rngom.digested.DPattern;
|
||||
import com.sun.xml.internal.rngom.digested.DPatternWalker;
|
||||
import com.sun.xml.internal.rngom.digested.DRefPattern;
|
||||
import com.sun.xml.internal.rngom.digested.DValuePattern;
|
||||
import com.sun.xml.internal.rngom.nc.NameClass;
|
||||
import com.sun.xml.internal.rngom.xml.util.WellKnownNamespaces;
|
||||
|
||||
/**
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class RELAXNGCompiler {
|
||||
/**
|
||||
* Schema to compile.
|
||||
*/
|
||||
final DPattern grammar;
|
||||
|
||||
/**
|
||||
* All named patterns in this schema.
|
||||
*/
|
||||
final Set<DDefine> defs;
|
||||
|
||||
final Options opts;
|
||||
|
||||
final Model model;
|
||||
|
||||
/**
|
||||
* The package to which we generate the code into.
|
||||
*/
|
||||
final JPackage pkg;
|
||||
|
||||
final Map<String,DatatypeLib> datatypes = new HashMap<String, DatatypeLib>();
|
||||
|
||||
/**
|
||||
* Patterns that are mapped to Java concepts.
|
||||
*
|
||||
* <p>
|
||||
* The value is an array because we map elements with finite names
|
||||
* to multiple classes.
|
||||
*
|
||||
* TODO: depending on the type of the key, the type of the values can be further
|
||||
* restricted. Make this into its own class to represent those constraints better.
|
||||
*/
|
||||
final Map<DPattern,CTypeInfo[]> classes = new HashMap<DPattern,CTypeInfo[]>();
|
||||
|
||||
/**
|
||||
* Classes that need to be bound.
|
||||
*
|
||||
* The value is the content model to be bound.
|
||||
*/
|
||||
final Map<CClassInfo,DPattern> bindQueue = new HashMap<CClassInfo,DPattern>();
|
||||
|
||||
final TypeUseBinder typeUseBinder = new TypeUseBinder(this);
|
||||
|
||||
public static Model build(DPattern grammar, JCodeModel codeModel, Options opts ) {
|
||||
RELAXNGCompiler compiler = new RELAXNGCompiler(grammar, codeModel, opts);
|
||||
compiler.compile();
|
||||
return compiler.model;
|
||||
}
|
||||
|
||||
public RELAXNGCompiler(DPattern grammar, JCodeModel codeModel, Options opts) {
|
||||
this.grammar = grammar;
|
||||
this.opts = opts;
|
||||
this.model = new Model(opts,codeModel, NameConverter.smart,opts.classNameAllocator,null);
|
||||
|
||||
datatypes.put("",DatatypeLib.BUILTIN);
|
||||
datatypes.put(WellKnownNamespaces.XML_SCHEMA_DATATYPES,DatatypeLib.XMLSCHEMA);
|
||||
|
||||
// find all defines
|
||||
DefineFinder deff = new DefineFinder();
|
||||
grammar.accept(deff);
|
||||
this.defs = deff.defs;
|
||||
|
||||
if(opts.defaultPackage2!=null)
|
||||
pkg = codeModel._package(opts.defaultPackage2);
|
||||
else
|
||||
if(opts.defaultPackage!=null)
|
||||
pkg = codeModel._package(opts.defaultPackage);
|
||||
else
|
||||
pkg = codeModel.rootPackage();
|
||||
}
|
||||
|
||||
private void compile() {
|
||||
// decide which patterns to map to classes
|
||||
promoteElementDefsToClasses();
|
||||
promoteTypeSafeEnums();
|
||||
// TODO: promote patterns with <jaxb:class> to classes
|
||||
// TODO: promote 'type' patterns to classes
|
||||
promoteTypePatternsToClasses();
|
||||
|
||||
for (Map.Entry<CClassInfo,DPattern> e : bindQueue.entrySet())
|
||||
bindContentModel(e.getKey(),e.getValue());
|
||||
}
|
||||
|
||||
private void bindContentModel(CClassInfo clazz, DPattern pattern) {
|
||||
// first we decide which patterns in it map to properties
|
||||
// then we process each of them by using RawTypeSetBuilder.
|
||||
// much like DefaultParticleBinder in XSD
|
||||
pattern.accept(new ContentModelBinder(this,clazz));
|
||||
}
|
||||
|
||||
private void promoteTypeSafeEnums() {
|
||||
// we'll be trying a lot of choices,
|
||||
// and most of them will not be type-safe enum.
|
||||
// using the same list improves the memory efficiency.
|
||||
List<CEnumConstant> members = new ArrayList<CEnumConstant>();
|
||||
|
||||
OUTER:
|
||||
for( DDefine def : defs ) {
|
||||
DPattern p = def.getPattern();
|
||||
if (p instanceof DChoicePattern) {
|
||||
DChoicePattern cp = (DChoicePattern) p;
|
||||
|
||||
members.clear();
|
||||
|
||||
// check if the choice consists of all value patterns
|
||||
// and that they are of the same datatype
|
||||
DValuePattern vp = null;
|
||||
|
||||
for( DPattern child : cp ) {
|
||||
if(child instanceof DValuePattern) {
|
||||
DValuePattern c = (DValuePattern) child;
|
||||
if(vp==null)
|
||||
vp=c;
|
||||
else {
|
||||
if(!vp.getDatatypeLibrary().equals(c.getDatatypeLibrary())
|
||||
|| !vp.getType().equals(c.getType()) )
|
||||
continue OUTER; // different type name
|
||||
}
|
||||
|
||||
members.add(new CEnumConstant(
|
||||
model.getNameConverter().toConstantName(c.getValue()),
|
||||
null, c.getValue(), null, null/*TODO*/, c.getLocation()
|
||||
));
|
||||
} else
|
||||
continue OUTER; // not a value
|
||||
}
|
||||
|
||||
if(members.isEmpty())
|
||||
continue; // empty choice
|
||||
|
||||
CNonElement base = CBuiltinLeafInfo.STRING;
|
||||
|
||||
DatatypeLib lib = datatypes.get(vp.getNs());
|
||||
if(lib!=null) {
|
||||
TypeUse use = lib.get(vp.getType());
|
||||
if(use instanceof CNonElement)
|
||||
base = (CNonElement)use;
|
||||
}
|
||||
|
||||
CEnumLeafInfo xducer = new CEnumLeafInfo(model, null,
|
||||
new CClassInfoParent.Package(pkg), def.getName(), base,
|
||||
new ArrayList<CEnumConstant>(members),
|
||||
null, null/*TODO*/, cp.getLocation());
|
||||
|
||||
classes.put(cp,new CTypeInfo[]{xducer});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void promoteElementDefsToClasses() {
|
||||
// look for elements among named patterns
|
||||
for( DDefine def : defs ) {
|
||||
DPattern p = def.getPattern();
|
||||
if (p instanceof DElementPattern) {
|
||||
DElementPattern ep = (DElementPattern) p;
|
||||
|
||||
mapToClass(ep);
|
||||
}
|
||||
}
|
||||
|
||||
// also look for root elements
|
||||
grammar.accept(new DPatternWalker() {
|
||||
public Void onRef(DRefPattern p) {
|
||||
return null; // stop recursion
|
||||
}
|
||||
|
||||
public Void onElement(DElementPattern p) {
|
||||
mapToClass(p);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void mapToClass(DElementPattern p) {
|
||||
NameClass nc = p.getName();
|
||||
if(nc.isOpen())
|
||||
return; // infinite name. can't map to a class.
|
||||
|
||||
Set<QName> names = nc.listNames();
|
||||
|
||||
CClassInfo[] types = new CClassInfo[names.size()];
|
||||
int i=0;
|
||||
for( QName n : names ) {
|
||||
// TODO: read class names from customization
|
||||
String name = model.getNameConverter().toClassName(n.getLocalPart());
|
||||
|
||||
bindQueue.put(
|
||||
types[i++] = new CClassInfo(model,pkg,name,p.getLocation(),null,n,null,null/*TODO*/),
|
||||
p.getChild() );
|
||||
}
|
||||
|
||||
classes.put(p,types);
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks for named patterns that are not bound to classes so far,
|
||||
* but that can be bound to classes.
|
||||
*/
|
||||
private void promoteTypePatternsToClasses() {
|
||||
|
||||
// for( DDefine def : defs ) {
|
||||
// ;
|
||||
//
|
||||
// def.getPattern().accept(new InheritanceChecker());
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.relaxng;
|
||||
|
||||
import com.sun.tools.internal.xjc.reader.Const;
|
||||
import com.sun.tools.internal.xjc.reader.internalizer.AbstractReferenceFinderImpl;
|
||||
import com.sun.tools.internal.xjc.reader.internalizer.DOMForest;
|
||||
import com.sun.tools.internal.xjc.reader.internalizer.InternalizationLogic;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.helpers.XMLFilterImpl;
|
||||
|
||||
/**
|
||||
* RELAX NG specific internalization logic.
|
||||
*
|
||||
* @author
|
||||
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
public class RELAXNGInternalizationLogic implements InternalizationLogic {
|
||||
|
||||
/**
|
||||
* This filter looks for <xs:import> and <xs:include>
|
||||
* and parses those documents referenced by them.
|
||||
*/
|
||||
private static final class ReferenceFinder extends AbstractReferenceFinderImpl {
|
||||
ReferenceFinder( DOMForest parent ) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
protected String findExternalResource( String nsURI, String localName, Attributes atts) {
|
||||
if( Const.RELAXNG_URI.equals(nsURI)
|
||||
&& ("include".equals(localName) || "externalRef".equals(localName) ) )
|
||||
return atts.getValue("href");
|
||||
else
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
public XMLFilterImpl createExternalReferenceFinder(DOMForest parent) {
|
||||
return new ReferenceFinder(parent);
|
||||
}
|
||||
|
||||
public boolean checkIfValidTargetNode(DOMForest parent, Element bindings, Element target) {
|
||||
return Const.RELAXNG_URI.equals(target.getNamespaceURI());
|
||||
}
|
||||
|
||||
public Element refineTarget(Element target) {
|
||||
// no refinement necessary
|
||||
return target;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.relaxng;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.sun.tools.internal.xjc.model.CClassInfo;
|
||||
import com.sun.tools.internal.xjc.model.CElementPropertyInfo;
|
||||
import com.sun.tools.internal.xjc.model.CReferencePropertyInfo;
|
||||
import com.sun.tools.internal.xjc.model.CTypeInfo;
|
||||
import com.sun.tools.internal.xjc.model.CTypeRef;
|
||||
import com.sun.tools.internal.xjc.model.Multiplicity;
|
||||
import com.sun.tools.internal.xjc.reader.RawTypeSet;
|
||||
import com.sun.xml.internal.bind.v2.model.core.ID;
|
||||
|
||||
import com.sun.xml.internal.rngom.digested.DAttributePattern;
|
||||
import com.sun.xml.internal.rngom.digested.DElementPattern;
|
||||
import com.sun.xml.internal.rngom.digested.DOneOrMorePattern;
|
||||
import com.sun.xml.internal.rngom.digested.DPattern;
|
||||
import com.sun.xml.internal.rngom.digested.DPatternWalker;
|
||||
import com.sun.xml.internal.rngom.digested.DZeroOrMorePattern;
|
||||
|
||||
/**
|
||||
* Builds {@link RawTypeSet} for RELAX NG.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class RawTypeSetBuilder extends DPatternWalker {
|
||||
public static RawTypeSet build( RELAXNGCompiler compiler, DPattern contentModel, Multiplicity mul ) {
|
||||
RawTypeSetBuilder builder = new RawTypeSetBuilder(compiler,mul);
|
||||
contentModel.accept(builder);
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplicity of the property.
|
||||
*/
|
||||
private Multiplicity mul;
|
||||
|
||||
/**
|
||||
* Accumulates discovered {@link RawTypeSet.Ref}s.
|
||||
*/
|
||||
private final Set<RawTypeSet.Ref> refs = new HashSet<RawTypeSet.Ref>();
|
||||
|
||||
private final RELAXNGCompiler compiler;
|
||||
|
||||
public RawTypeSetBuilder(RELAXNGCompiler compiler,Multiplicity mul) {
|
||||
this.mul = mul;
|
||||
this.compiler = compiler;
|
||||
}
|
||||
|
||||
private RawTypeSet create() {
|
||||
return new RawTypeSet(refs,mul);
|
||||
}
|
||||
|
||||
public Void onAttribute(DAttributePattern p) {
|
||||
// attributes form their own properties
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void onElement(DElementPattern p) {
|
||||
CTypeInfo[] tis = compiler.classes.get(p);
|
||||
if(tis!=null) {
|
||||
for( CTypeInfo ti : tis )
|
||||
refs.add(new CClassInfoRef((CClassInfo)ti));
|
||||
} else {
|
||||
// TODO
|
||||
assert false;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void onZeroOrMore(DZeroOrMorePattern p) {
|
||||
mul = mul.makeRepeated();
|
||||
return super.onZeroOrMore(p);
|
||||
}
|
||||
|
||||
public Void onOneOrMore(DOneOrMorePattern p) {
|
||||
mul = mul.makeRepeated();
|
||||
return super.onOneOrMore(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* For {@link CClassInfo}s that map to elements.
|
||||
*/
|
||||
private static final class CClassInfoRef extends RawTypeSet.Ref {
|
||||
private final CClassInfo ci;
|
||||
CClassInfoRef(CClassInfo ci) {
|
||||
this.ci = ci;
|
||||
assert ci.isElement();
|
||||
}
|
||||
|
||||
protected ID id() {
|
||||
return ID.NONE;
|
||||
}
|
||||
|
||||
protected boolean isListOfValues() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected RawTypeSet.Mode canBeType(RawTypeSet parent) {
|
||||
return RawTypeSet.Mode.SHOULD_BE_TYPEREF;
|
||||
}
|
||||
|
||||
protected void toElementRef(CReferencePropertyInfo prop) {
|
||||
prop.getElements().add(ci);
|
||||
}
|
||||
|
||||
protected CTypeRef toTypeRef(CElementPropertyInfo ep) {
|
||||
return new CTypeRef(ci,ci.getElementName(),ci.getTypeName(),false,null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.relaxng;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
|
||||
import com.sun.xml.internal.rngom.digested.DAttributePattern;
|
||||
import com.sun.xml.internal.rngom.digested.DChoicePattern;
|
||||
import com.sun.xml.internal.rngom.digested.DDefine;
|
||||
import com.sun.xml.internal.rngom.digested.DListPattern;
|
||||
import com.sun.xml.internal.rngom.digested.DMixedPattern;
|
||||
import com.sun.xml.internal.rngom.digested.DOneOrMorePattern;
|
||||
import com.sun.xml.internal.rngom.digested.DOptionalPattern;
|
||||
import com.sun.xml.internal.rngom.digested.DPatternWalker;
|
||||
import com.sun.xml.internal.rngom.digested.DRefPattern;
|
||||
import com.sun.xml.internal.rngom.digested.DZeroOrMorePattern;
|
||||
|
||||
/**
|
||||
* Fumigate the named patterns that can be bound to inheritance.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class TypePatternBinder extends DPatternWalker {
|
||||
private boolean canInherit;
|
||||
private final Stack<Boolean> stack = new Stack<Boolean>();
|
||||
|
||||
/**
|
||||
* Patterns that are determined not to be bindable to inheritance.
|
||||
*/
|
||||
private final Set<DDefine> cannotBeInherited = new HashSet<DDefine>();
|
||||
|
||||
|
||||
void reset() {
|
||||
canInherit = true;
|
||||
stack.clear();
|
||||
}
|
||||
|
||||
public Void onRef(DRefPattern p) {
|
||||
if(!canInherit) {
|
||||
cannotBeInherited.add(p.getTarget());
|
||||
} else {
|
||||
// if the whole pattern is like "A,B", we can only inherit from
|
||||
// either A or B. For now, always derive from A.
|
||||
// it might be worthwhile to have a smarter binding logic where
|
||||
// we pick A and B based on their 'usefulness' --- by taking into
|
||||
// account how many other paterns are derived from those.
|
||||
canInherit = false;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
Set the flag to false if we hit a pattern that cannot include
|
||||
a <ref> to be bound as an inheritance.
|
||||
|
||||
All the following code are the same
|
||||
*/
|
||||
public Void onChoice(DChoicePattern p) {
|
||||
push(false);
|
||||
super.onChoice(p);
|
||||
pop();
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void onAttribute(DAttributePattern p) {
|
||||
push(false);
|
||||
super.onAttribute(p);
|
||||
pop();
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void onList(DListPattern p) {
|
||||
push(false);
|
||||
super.onList(p);
|
||||
pop();
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void onMixed(DMixedPattern p) {
|
||||
push(false);
|
||||
super.onMixed(p);
|
||||
pop();
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void onOneOrMore(DOneOrMorePattern p) {
|
||||
push(false);
|
||||
super.onOneOrMore(p);
|
||||
pop();
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void onZeroOrMore(DZeroOrMorePattern p) {
|
||||
push(false);
|
||||
super.onZeroOrMore(p);
|
||||
pop();
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void onOptional(DOptionalPattern p) {
|
||||
push(false);
|
||||
super.onOptional(p);
|
||||
pop();
|
||||
return null;
|
||||
}
|
||||
|
||||
private void push(boolean v) {
|
||||
stack.push(canInherit);
|
||||
canInherit = v;
|
||||
}
|
||||
|
||||
private void pop() {
|
||||
canInherit = stack.pop();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.relaxng;
|
||||
|
||||
import com.sun.tools.internal.xjc.model.CBuiltinLeafInfo;
|
||||
import com.sun.tools.internal.xjc.model.TypeUse;
|
||||
import com.sun.tools.internal.xjc.model.TypeUseFactory;
|
||||
|
||||
import com.sun.xml.internal.rngom.digested.DAttributePattern;
|
||||
import com.sun.xml.internal.rngom.digested.DChoicePattern;
|
||||
import com.sun.xml.internal.rngom.digested.DContainerPattern;
|
||||
import com.sun.xml.internal.rngom.digested.DDataPattern;
|
||||
import com.sun.xml.internal.rngom.digested.DElementPattern;
|
||||
import com.sun.xml.internal.rngom.digested.DEmptyPattern;
|
||||
import com.sun.xml.internal.rngom.digested.DGrammarPattern;
|
||||
import com.sun.xml.internal.rngom.digested.DGroupPattern;
|
||||
import com.sun.xml.internal.rngom.digested.DInterleavePattern;
|
||||
import com.sun.xml.internal.rngom.digested.DListPattern;
|
||||
import com.sun.xml.internal.rngom.digested.DMixedPattern;
|
||||
import com.sun.xml.internal.rngom.digested.DNotAllowedPattern;
|
||||
import com.sun.xml.internal.rngom.digested.DOneOrMorePattern;
|
||||
import com.sun.xml.internal.rngom.digested.DOptionalPattern;
|
||||
import com.sun.xml.internal.rngom.digested.DPattern;
|
||||
import com.sun.xml.internal.rngom.digested.DPatternVisitor;
|
||||
import com.sun.xml.internal.rngom.digested.DRefPattern;
|
||||
import com.sun.xml.internal.rngom.digested.DTextPattern;
|
||||
import com.sun.xml.internal.rngom.digested.DValuePattern;
|
||||
import com.sun.xml.internal.rngom.digested.DZeroOrMorePattern;
|
||||
|
||||
/**
|
||||
* Walks the pattern tree and binds it to a {@link TypeUse}.
|
||||
*
|
||||
* The singleton instance is kept in {@link RELAXNGCompiler}.
|
||||
*
|
||||
* TODO: I should really normalize before process.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class TypeUseBinder implements DPatternVisitor<TypeUse> {
|
||||
private final RELAXNGCompiler compiler;
|
||||
|
||||
public TypeUseBinder(RELAXNGCompiler compiler) {
|
||||
this.compiler = compiler;
|
||||
}
|
||||
|
||||
|
||||
public TypeUse onGrammar(DGrammarPattern p) {
|
||||
return CBuiltinLeafInfo.STRING;
|
||||
}
|
||||
|
||||
public TypeUse onChoice(DChoicePattern p) {
|
||||
// can't support unions
|
||||
return CBuiltinLeafInfo.STRING;
|
||||
}
|
||||
|
||||
public TypeUse onData(DDataPattern p) {
|
||||
return onDataType(p.getDatatypeLibrary(), p.getType());
|
||||
}
|
||||
|
||||
public TypeUse onValue(DValuePattern p) {
|
||||
return onDataType(p.getDatatypeLibrary(),p.getType());
|
||||
}
|
||||
|
||||
private TypeUse onDataType(String datatypeLibrary, String type) {
|
||||
DatatypeLib lib = compiler.datatypes.get(datatypeLibrary);
|
||||
if(lib!=null) {
|
||||
TypeUse use = lib.get(type);
|
||||
if(use!=null)
|
||||
return use;
|
||||
}
|
||||
|
||||
// unknown
|
||||
return CBuiltinLeafInfo.STRING;
|
||||
}
|
||||
|
||||
public TypeUse onInterleave(DInterleavePattern p) {
|
||||
return onContainer(p);
|
||||
}
|
||||
|
||||
public TypeUse onGroup(DGroupPattern p) {
|
||||
return onContainer(p);
|
||||
}
|
||||
|
||||
private TypeUse onContainer(DContainerPattern p) {
|
||||
TypeUse t=null;
|
||||
for( DPattern child : p ) {
|
||||
TypeUse s = child.accept(this);
|
||||
if(t!=null && t!=s)
|
||||
return CBuiltinLeafInfo.STRING; // heterogenous
|
||||
t = s;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
public TypeUse onNotAllowed(DNotAllowedPattern p) {
|
||||
// TODO
|
||||
return error();
|
||||
}
|
||||
|
||||
public TypeUse onEmpty(DEmptyPattern p) {
|
||||
return CBuiltinLeafInfo.STRING;
|
||||
}
|
||||
|
||||
public TypeUse onList(DListPattern p) {
|
||||
return p.getChild().accept(this);
|
||||
}
|
||||
|
||||
public TypeUse onOneOrMore(DOneOrMorePattern p) {
|
||||
return TypeUseFactory.makeCollection( p.getChild().accept(this) );
|
||||
}
|
||||
|
||||
public TypeUse onZeroOrMore(DZeroOrMorePattern p) {
|
||||
return TypeUseFactory.makeCollection( p.getChild().accept(this) );
|
||||
}
|
||||
|
||||
public TypeUse onOptional(DOptionalPattern p) {
|
||||
return CBuiltinLeafInfo.STRING;
|
||||
}
|
||||
|
||||
public TypeUse onRef(DRefPattern p) {
|
||||
// TODO: check for enums
|
||||
return p.getTarget().getPattern().accept(this);
|
||||
}
|
||||
|
||||
public TypeUse onText(DTextPattern p) {
|
||||
return CBuiltinLeafInfo.STRING;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// Not allowed in this context
|
||||
//
|
||||
//
|
||||
public TypeUse onAttribute(DAttributePattern p) {
|
||||
return error();
|
||||
}
|
||||
|
||||
public TypeUse onElement(DElementPattern p) {
|
||||
return error();
|
||||
}
|
||||
|
||||
public TypeUse onMixed(DMixedPattern p) {
|
||||
return error();
|
||||
}
|
||||
|
||||
private TypeUse error() {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema;
|
||||
|
||||
import com.sun.tools.internal.xjc.model.CElement;
|
||||
import com.sun.xml.internal.xsom.XSComplexType;
|
||||
import com.sun.xml.internal.xsom.XSElementDecl;
|
||||
|
||||
/**
|
||||
* {@link ClassBinder} that marks abstract components as abstract.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi (kk@kohsuke.org)
|
||||
*/
|
||||
class Abstractifier extends ClassBinderFilter {
|
||||
public Abstractifier(ClassBinder core) {
|
||||
super(core);
|
||||
}
|
||||
|
||||
public CElement complexType(XSComplexType xs) {
|
||||
CElement ci = super.complexType(xs);
|
||||
if(ci!=null && xs.isAbstract())
|
||||
ci.setAbstract();
|
||||
return ci;
|
||||
}
|
||||
|
||||
public CElement elementDecl(XSElementDecl xs) {
|
||||
CElement ci = super.elementDecl(xs);
|
||||
if(ci!=null && xs.isAbstract())
|
||||
ci.setAbstract();
|
||||
return ci;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,568 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
|
||||
import com.sun.codemodel.internal.JCodeModel;
|
||||
import com.sun.codemodel.internal.fmt.JTextFile;
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import com.sun.istack.internal.Nullable;
|
||||
import com.sun.tools.internal.xjc.ErrorReceiver;
|
||||
import com.sun.tools.internal.xjc.Options;
|
||||
import com.sun.tools.internal.xjc.Plugin;
|
||||
import com.sun.tools.internal.xjc.generator.bean.field.FieldRendererFactory;
|
||||
import com.sun.tools.internal.xjc.model.CClassInfoParent;
|
||||
import com.sun.tools.internal.xjc.model.Model;
|
||||
import com.sun.tools.internal.xjc.reader.ModelChecker;
|
||||
import com.sun.tools.internal.xjc.reader.Ring;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIDeclaration;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIDom;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIGlobalBinding;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BISchemaBinding;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BISerializable;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BindInfo;
|
||||
import com.sun.tools.internal.xjc.util.CodeModelClassFactory;
|
||||
import com.sun.tools.internal.xjc.util.ErrorReceiverFilter;
|
||||
import com.sun.xml.internal.bind.api.impl.NameConverter;
|
||||
import com.sun.xml.internal.bind.v2.util.XmlFactory;
|
||||
import com.sun.xml.internal.xsom.XSAnnotation;
|
||||
import com.sun.xml.internal.xsom.XSAttributeUse;
|
||||
import com.sun.xml.internal.xsom.XSComponent;
|
||||
import com.sun.xml.internal.xsom.XSDeclaration;
|
||||
import com.sun.xml.internal.xsom.XSParticle;
|
||||
import com.sun.xml.internal.xsom.XSSchema;
|
||||
import com.sun.xml.internal.xsom.XSSchemaSet;
|
||||
import com.sun.xml.internal.xsom.XSSimpleType;
|
||||
import com.sun.xml.internal.xsom.XSTerm;
|
||||
import com.sun.xml.internal.xsom.XSType;
|
||||
import com.sun.xml.internal.xsom.XSWildcard;
|
||||
import com.sun.xml.internal.xsom.util.XSFinder;
|
||||
|
||||
import org.xml.sax.Locator;
|
||||
|
||||
/**
|
||||
* Root of the XML Schema binder.
|
||||
*
|
||||
* <div><img src="doc-files/binding_chart.png"/></div>
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public class BGMBuilder extends BindingComponent {
|
||||
|
||||
/**
|
||||
* Entry point.
|
||||
*/
|
||||
public static Model build( XSSchemaSet _schemas, JCodeModel codeModel,
|
||||
ErrorReceiver _errorReceiver, Options opts ) {
|
||||
// set up a ring
|
||||
final Ring old = Ring.begin();
|
||||
try {
|
||||
ErrorReceiverFilter ef = new ErrorReceiverFilter(_errorReceiver);
|
||||
|
||||
Ring.add(XSSchemaSet.class,_schemas);
|
||||
Ring.add(codeModel);
|
||||
Model model = new Model(opts, codeModel, null/*set later*/, opts.classNameAllocator, _schemas);
|
||||
Ring.add(model);
|
||||
Ring.add(ErrorReceiver.class,ef);
|
||||
Ring.add(CodeModelClassFactory.class,new CodeModelClassFactory(ef));
|
||||
|
||||
BGMBuilder builder = new BGMBuilder(opts.defaultPackage,opts.defaultPackage2,
|
||||
opts.isExtensionMode(),opts.getFieldRendererFactory(), opts.activePlugins);
|
||||
builder._build();
|
||||
|
||||
if(ef.hadError()) return null;
|
||||
else return model;
|
||||
} finally {
|
||||
Ring.end(old);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* True if the compiler is running in the extension mode
|
||||
* (as opposed to the strict conformance mode.)
|
||||
*/
|
||||
public final boolean inExtensionMode;
|
||||
|
||||
/**
|
||||
* If this is non-null, this package name takes over
|
||||
* all the schema customizations.
|
||||
*/
|
||||
public final String defaultPackage1;
|
||||
|
||||
/**
|
||||
* If this is non-null, this package name will be
|
||||
* used when no customization is specified.
|
||||
*/
|
||||
public final String defaultPackage2;
|
||||
|
||||
private final BindGreen green = Ring.get(BindGreen.class);
|
||||
private final BindPurple purple = Ring.get(BindPurple.class);
|
||||
|
||||
public final Model model = Ring.get(Model.class);
|
||||
|
||||
public final FieldRendererFactory fieldRendererFactory;
|
||||
|
||||
/**
|
||||
* Lazily computed {@link RefererFinder}.
|
||||
*
|
||||
* @see #getReferer
|
||||
*/
|
||||
private RefererFinder refFinder;
|
||||
|
||||
private List<Plugin> activePlugins;
|
||||
|
||||
protected BGMBuilder(String defaultPackage1, String defaultPackage2,
|
||||
boolean _inExtensionMode, FieldRendererFactory fieldRendererFactory,
|
||||
List<Plugin> activePlugins) {
|
||||
this.inExtensionMode = _inExtensionMode;
|
||||
this.defaultPackage1 = defaultPackage1;
|
||||
this.defaultPackage2 = defaultPackage2;
|
||||
this.fieldRendererFactory = fieldRendererFactory;
|
||||
this.activePlugins = activePlugins;
|
||||
promoteGlobalBindings();
|
||||
}
|
||||
|
||||
private void _build() {
|
||||
// do the binding
|
||||
buildContents();
|
||||
getClassSelector().executeTasks();
|
||||
|
||||
// additional error check
|
||||
// Reports unused customizations to the user as errors.
|
||||
Ring.get(UnusedCustomizationChecker.class).run();
|
||||
|
||||
Ring.get(ModelChecker.class).check();
|
||||
|
||||
for( Plugin ma : activePlugins )
|
||||
ma.postProcessModel(model, Ring.get(ErrorReceiver.class));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/** List up all the global bindings. */
|
||||
private void promoteGlobalBindings() {
|
||||
// promote any global bindings in the schema
|
||||
XSSchemaSet schemas = Ring.get(XSSchemaSet.class);
|
||||
|
||||
for( XSSchema s : schemas.getSchemas() ) {
|
||||
BindInfo bi = getBindInfo(s);
|
||||
|
||||
// collect all global customizations
|
||||
model.getCustomizations().addAll(bi.toCustomizationList());
|
||||
|
||||
BIGlobalBinding gb = bi.get(BIGlobalBinding.class);
|
||||
if(gb==null)
|
||||
continue;
|
||||
|
||||
gb.markAsAcknowledged();
|
||||
|
||||
if(globalBinding==null) {
|
||||
globalBinding = gb;
|
||||
} else {
|
||||
if (!globalBinding.isEqual(gb)) { // see Issue 687 - this may happen with syntactically imported documents
|
||||
// acknowledge this customization and report an error
|
||||
// otherwise the user will see "customization is attached to a wrong place" error,
|
||||
// which is incorrect
|
||||
getErrorReporter().error( gb.getLocation(),
|
||||
Messages.ERR_MULTIPLE_GLOBAL_BINDINGS);
|
||||
getErrorReporter().error( globalBinding.getLocation(),
|
||||
Messages.ERR_MULTIPLE_GLOBAL_BINDINGS_OTHER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( globalBinding==null ) {
|
||||
// no global customization is present.
|
||||
// use the default one
|
||||
globalBinding = new BIGlobalBinding();
|
||||
BindInfo big = new BindInfo();
|
||||
big.addDecl(globalBinding);
|
||||
big.setOwner(this,null);
|
||||
}
|
||||
|
||||
// code generation mode
|
||||
model.strategy = globalBinding.getCodeGenerationStrategy();
|
||||
model.rootClass = globalBinding.getSuperClass();
|
||||
model.rootInterface = globalBinding.getSuperInterface();
|
||||
|
||||
particleBinder = globalBinding.isSimpleMode() ? new ExpressionParticleBinder() : new DefaultParticleBinder();
|
||||
|
||||
// check XJC extensions and realize them
|
||||
BISerializable serial = globalBinding.getSerializable();
|
||||
if(serial!=null) {
|
||||
model.serializable = true;
|
||||
model.serialVersionUID = serial.uid;
|
||||
}
|
||||
|
||||
// obtain the name conversion mode
|
||||
if (globalBinding.nameConverter!=null)
|
||||
model.setNameConverter(globalBinding.nameConverter);
|
||||
|
||||
// attach global conversions to the appropriate simple types
|
||||
globalBinding.dispatchGlobalConversions(schemas);
|
||||
|
||||
globalBinding.errorCheck();
|
||||
}
|
||||
|
||||
/**
|
||||
* Global bindings.
|
||||
*
|
||||
* The empty global binding is set as the default, so that
|
||||
* there will be no need to test if the value is null.
|
||||
*/
|
||||
private BIGlobalBinding globalBinding;
|
||||
|
||||
/**
|
||||
* Gets the global bindings.
|
||||
*/
|
||||
public @NotNull BIGlobalBinding getGlobalBinding() { return globalBinding; }
|
||||
|
||||
|
||||
private ParticleBinder particleBinder;
|
||||
|
||||
/**
|
||||
* Gets the particle binder for this binding.
|
||||
*/
|
||||
public @NotNull ParticleBinder getParticleBinder() { return particleBinder; }
|
||||
|
||||
|
||||
/**
|
||||
* Name converter that implements "XML->Java name conversion"
|
||||
* as specified in the spec.
|
||||
*
|
||||
* This object abstracts the detail that we use different name
|
||||
* conversion depending on the customization.
|
||||
*
|
||||
* <p>
|
||||
* This object should be used to perform any name conversion
|
||||
* needs, instead of the JJavaName class in CodeModel.
|
||||
*/
|
||||
public NameConverter getNameConverter() { return model.getNameConverter(); }
|
||||
|
||||
/** Fill-in the contents of each classes. */
|
||||
private void buildContents() {
|
||||
ClassSelector cs = getClassSelector();
|
||||
SimpleTypeBuilder stb = Ring.get(SimpleTypeBuilder.class);
|
||||
|
||||
for( XSSchema s : Ring.get(XSSchemaSet.class).getSchemas() ) {
|
||||
BISchemaBinding sb = getBindInfo(s).get(BISchemaBinding.class);
|
||||
|
||||
if(sb!=null && !sb.map) {
|
||||
sb.markAsAcknowledged();
|
||||
continue; // no mapping for this package
|
||||
}
|
||||
|
||||
getClassSelector().pushClassScope( new CClassInfoParent.Package(
|
||||
getClassSelector().getPackage(s.getTargetNamespace())) );
|
||||
|
||||
checkMultipleSchemaBindings(s);
|
||||
processPackageJavadoc(s);
|
||||
populate(s.getAttGroupDecls(),s);
|
||||
populate(s.getAttributeDecls(),s);
|
||||
populate(s.getElementDecls(),s);
|
||||
populate(s.getModelGroupDecls(),s);
|
||||
|
||||
// fill in typeUses
|
||||
for (XSType t : s.getTypes().values()) {
|
||||
stb.refererStack.push(t);
|
||||
model.typeUses().put( getName(t), cs.bindToType(t,s) );
|
||||
stb.refererStack.pop();
|
||||
}
|
||||
|
||||
getClassSelector().popClassScope();
|
||||
}
|
||||
}
|
||||
|
||||
/** Reports an error if there are more than one jaxb:schemaBindings customization. */
|
||||
private void checkMultipleSchemaBindings( XSSchema schema ) {
|
||||
ArrayList<Locator> locations = new ArrayList<Locator>();
|
||||
|
||||
BindInfo bi = getBindInfo(schema);
|
||||
for( BIDeclaration bid : bi ) {
|
||||
if( bid.getName()==BISchemaBinding.NAME )
|
||||
locations.add( bid.getLocation() );
|
||||
}
|
||||
if(locations.size()<=1) return; // OK
|
||||
|
||||
// error
|
||||
getErrorReporter().error( locations.get(0),
|
||||
Messages.ERR_MULTIPLE_SCHEMA_BINDINGS,
|
||||
schema.getTargetNamespace() );
|
||||
for( int i=1; i<locations.size(); i++ )
|
||||
getErrorReporter().error( (Locator)locations.get(i),
|
||||
Messages.ERR_MULTIPLE_SCHEMA_BINDINGS_LOCATION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls {@link ClassSelector} for each item in the iterator
|
||||
* to populate class items if there is any.
|
||||
*/
|
||||
private void populate( Map<String,? extends XSComponent> col, XSSchema schema ) {
|
||||
ClassSelector cs = getClassSelector();
|
||||
for( XSComponent sc : col.values() )
|
||||
cs.bindToType(sc,schema);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates <code>package.html</code> if the customization
|
||||
* says so.
|
||||
*/
|
||||
private void processPackageJavadoc( XSSchema s ) {
|
||||
// look for the schema-wide customization
|
||||
BISchemaBinding cust = getBindInfo(s).get(BISchemaBinding.class);
|
||||
if(cust==null) return; // not present
|
||||
|
||||
cust.markAsAcknowledged();
|
||||
if( cust.getJavadoc()==null ) return; // no javadoc customization
|
||||
|
||||
// produce a HTML file
|
||||
JTextFile html = new JTextFile("package.html");
|
||||
html.setContents(cust.getJavadoc());
|
||||
getClassSelector().getPackage(s.getTargetNamespace()).addResourceFile(html);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets or creates the BindInfo object associated to a schema component.
|
||||
*
|
||||
* @return
|
||||
* Always return a non-null valid BindInfo object.
|
||||
* Even if no declaration was specified, this method creates
|
||||
* a new BindInfo so that new decls can be added.
|
||||
*/
|
||||
public BindInfo getOrCreateBindInfo( XSComponent schemaComponent ) {
|
||||
|
||||
BindInfo bi = _getBindInfoReadOnly(schemaComponent);
|
||||
if(bi!=null) return bi;
|
||||
|
||||
// XSOM is read-only, so we cannot add new annotations.
|
||||
// for components that didn't have annotations,
|
||||
// we maintain an external map.
|
||||
bi = new BindInfo();
|
||||
bi.setOwner(this,schemaComponent);
|
||||
externalBindInfos.put(schemaComponent,bi);
|
||||
return bi;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Used as a constant instance to represent the empty {@link BindInfo}.
|
||||
*/
|
||||
private final BindInfo emptyBindInfo = new BindInfo();
|
||||
|
||||
/**
|
||||
* Gets the BindInfo object associated to a schema component.
|
||||
*
|
||||
* @return
|
||||
* always return a valid {@link BindInfo} object. If none
|
||||
* is specified for the given component, a dummy empty BindInfo
|
||||
* will be returned.
|
||||
*/
|
||||
public BindInfo getBindInfo( XSComponent schemaComponent ) {
|
||||
BindInfo bi = _getBindInfoReadOnly(schemaComponent);
|
||||
if(bi!=null) return bi;
|
||||
else return emptyBindInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the BindInfo object associated to a schema component.
|
||||
*
|
||||
* @return
|
||||
* null if no bind info is associated to this schema component.
|
||||
*/
|
||||
private BindInfo _getBindInfoReadOnly( XSComponent schemaComponent ) {
|
||||
|
||||
BindInfo bi = externalBindInfos.get(schemaComponent);
|
||||
if(bi!=null) return bi;
|
||||
|
||||
XSAnnotation annon = schemaComponent.getAnnotation();
|
||||
if(annon!=null) {
|
||||
bi = (BindInfo)annon.getAnnotation();
|
||||
if(bi!=null) {
|
||||
if(bi.getOwner()==null)
|
||||
bi.setOwner(this,schemaComponent);
|
||||
return bi;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A map that stores binding declarations augmented by XJC.
|
||||
*/
|
||||
private final Map<XSComponent,BindInfo> externalBindInfos = new HashMap<XSComponent,BindInfo>();
|
||||
|
||||
/**
|
||||
* Gets the {@link BIDom} object that applies to the given particle.
|
||||
*/
|
||||
protected final BIDom getLocalDomCustomization( XSParticle p ) {
|
||||
if (p == null) {
|
||||
return null;
|
||||
}
|
||||
BIDom dom = getBindInfo(p).get(BIDom.class);
|
||||
if(dom!=null) return dom;
|
||||
|
||||
// if not, the term might have one.
|
||||
dom = getBindInfo(p.getTerm()).get(BIDom.class);
|
||||
if(dom!=null) return dom;
|
||||
|
||||
XSTerm t = p.getTerm();
|
||||
// type could also have one, in case of the dom customization
|
||||
if(t.isElementDecl())
|
||||
return getBindInfo(t.asElementDecl().getType()).get(BIDom.class);
|
||||
// similarly the model group in a model group definition may have one.
|
||||
if(t.isModelGroupDecl())
|
||||
return getBindInfo(t.asModelGroupDecl().getModelGroup()).get(BIDom.class);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the component should be processed by purple.
|
||||
*/
|
||||
private final XSFinder toPurple = new XSFinder() {
|
||||
@Override
|
||||
public Boolean attributeUse(XSAttributeUse use) {
|
||||
// attribute use always maps to a property
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean simpleType(XSSimpleType xsSimpleType) {
|
||||
// simple type always maps to a type, hence we should take purple
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean wildcard(XSWildcard xsWildcard) {
|
||||
// attribute wildcards always maps to a property.
|
||||
// element wildcards should have been processed with particle binders
|
||||
return true;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* If the component maps to a property, forwards to purple, otherwise to green.
|
||||
*
|
||||
* If the component is mapped to a type, this method needs to return true.
|
||||
* See the chart at the class javadoc.
|
||||
*/
|
||||
public void ying( XSComponent sc, @Nullable XSComponent referer ) {
|
||||
if(sc.apply(toPurple)==true || getClassSelector().bindToType(sc,referer)!=null)
|
||||
sc.visit(purple);
|
||||
else
|
||||
sc.visit(green);
|
||||
}
|
||||
|
||||
private Transformer identityTransformer;
|
||||
|
||||
/**
|
||||
* Gets the shared instance of the identity transformer.
|
||||
*/
|
||||
public Transformer getIdentityTransformer() {
|
||||
try {
|
||||
if(identityTransformer==null) {
|
||||
TransformerFactory tf = XmlFactory.createTransformerFactory(model.options.disableXmlSecurity);
|
||||
identityTransformer = tf.newTransformer();
|
||||
}
|
||||
return identityTransformer;
|
||||
} catch (TransformerConfigurationException e) {
|
||||
throw new Error(e); // impossible
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all types that refer to the given complex type.
|
||||
*/
|
||||
public Set<XSComponent> getReferer(XSType c) {
|
||||
if(refFinder==null) {
|
||||
refFinder = new RefererFinder();
|
||||
refFinder.schemaSet(Ring.get(XSSchemaSet.class));
|
||||
}
|
||||
return refFinder.getReferer(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the QName of the declaration.
|
||||
* @return null
|
||||
* if the declaration is anonymous.
|
||||
*/
|
||||
public static QName getName(XSDeclaration decl) {
|
||||
String local = decl.getName();
|
||||
if(local==null) return null;
|
||||
return new QName(decl.getTargetNamespace(),local);
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives a name from a schema component.
|
||||
*
|
||||
* This method handles prefix/suffix modification and
|
||||
* XML-to-Java name conversion.
|
||||
*
|
||||
* @param name
|
||||
* The base name. This should be things like element names
|
||||
* or type names.
|
||||
* @param comp
|
||||
* The component from which the base name was taken.
|
||||
* Used to determine how names are modified.
|
||||
*/
|
||||
public String deriveName( String name, XSComponent comp ) {
|
||||
XSSchema owner = comp.getOwnerSchema();
|
||||
|
||||
name = getNameConverter().toClassName(name);
|
||||
|
||||
if( owner!=null ) {
|
||||
BISchemaBinding sb = getBindInfo(owner).get(BISchemaBinding.class);
|
||||
|
||||
if(sb!=null) name = sb.mangleClassName(name,comp);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean isGenerateMixedExtensions() {
|
||||
if (globalBinding != null) {
|
||||
return globalBinding.isGenerateMixedExtensions();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema;
|
||||
|
||||
import com.sun.xml.internal.xsom.XSAttGroupDecl;
|
||||
import com.sun.xml.internal.xsom.XSAttributeDecl;
|
||||
import com.sun.xml.internal.xsom.XSAttributeUse;
|
||||
import com.sun.xml.internal.xsom.XSComplexType;
|
||||
import com.sun.xml.internal.xsom.XSContentType;
|
||||
import com.sun.xml.internal.xsom.XSElementDecl;
|
||||
import com.sun.xml.internal.xsom.XSModelGroup;
|
||||
import com.sun.xml.internal.xsom.XSModelGroupDecl;
|
||||
import com.sun.xml.internal.xsom.XSParticle;
|
||||
import com.sun.xml.internal.xsom.XSSimpleType;
|
||||
import com.sun.xml.internal.xsom.XSWildcard;
|
||||
|
||||
/**
|
||||
* This is the first color invoked from the parent component.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class BindBlue extends ColorBinder {
|
||||
|
||||
public void complexType(XSComplexType ct) {
|
||||
// TODO: implement this method later
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void elementDecl(XSElementDecl e) {
|
||||
// TODO: implement this method later
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void wildcard(XSWildcard xsWildcard) {
|
||||
// TODO: implement this method later
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void attGroupDecl(XSAttGroupDecl xsAttGroupDecl) {
|
||||
// TODO
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void attributeDecl(XSAttributeDecl xsAttributeDecl) {
|
||||
// TODO
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void attributeUse(XSAttributeUse use) {
|
||||
// TODO
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void modelGroupDecl(XSModelGroupDecl xsModelGroupDecl) {
|
||||
// TODO
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void modelGroup(XSModelGroup xsModelGroup) {
|
||||
// TODO
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void particle(XSParticle xsParticle) {
|
||||
// TODO
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void empty(XSContentType xsContentType) {
|
||||
// TODO
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Components that always map to a type
|
||||
*/
|
||||
public void simpleType(XSSimpleType type) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.sun.tools.internal.xjc.reader.Ring;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.ct.ComplexTypeFieldBuilder;
|
||||
import com.sun.xml.internal.xsom.XSAttContainer;
|
||||
import com.sun.xml.internal.xsom.XSAttGroupDecl;
|
||||
import com.sun.xml.internal.xsom.XSAttributeDecl;
|
||||
import com.sun.xml.internal.xsom.XSAttributeUse;
|
||||
import com.sun.xml.internal.xsom.XSComplexType;
|
||||
import com.sun.xml.internal.xsom.XSContentType;
|
||||
import com.sun.xml.internal.xsom.XSElementDecl;
|
||||
import com.sun.xml.internal.xsom.XSModelGroup;
|
||||
import com.sun.xml.internal.xsom.XSModelGroupDecl;
|
||||
import com.sun.xml.internal.xsom.XSParticle;
|
||||
import com.sun.xml.internal.xsom.XSSimpleType;
|
||||
import com.sun.xml.internal.xsom.XSWildcard;
|
||||
|
||||
/**
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class BindGreen extends ColorBinder {
|
||||
|
||||
private final ComplexTypeFieldBuilder ctBuilder = Ring.get(ComplexTypeFieldBuilder.class);
|
||||
|
||||
public void attGroupDecl(XSAttGroupDecl ag) {
|
||||
attContainer(ag);
|
||||
}
|
||||
|
||||
public void attContainer(XSAttContainer cont) {
|
||||
// inline
|
||||
Iterator itr = cont.iterateDeclaredAttributeUses();
|
||||
while(itr.hasNext())
|
||||
builder.ying((XSAttributeUse)itr.next(),cont);
|
||||
itr = cont.iterateAttGroups();
|
||||
while(itr.hasNext())
|
||||
builder.ying((XSAttGroupDecl)itr.next(),cont);
|
||||
|
||||
XSWildcard w = cont.getAttributeWildcard();
|
||||
if(w!=null)
|
||||
builder.ying(w,cont);
|
||||
}
|
||||
|
||||
public void complexType(XSComplexType ct) {
|
||||
ctBuilder.build(ct);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public void attributeDecl(XSAttributeDecl xsAttributeDecl) {
|
||||
// TODO: implement this method later
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void wildcard(XSWildcard xsWildcard) {
|
||||
// TODO: implement this method later
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void modelGroupDecl(XSModelGroupDecl xsModelGroupDecl) {
|
||||
// TODO: implement this method later
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void modelGroup(XSModelGroup xsModelGroup) {
|
||||
// TODO: implement this method later
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void elementDecl(XSElementDecl xsElementDecl) {
|
||||
// TODO: implement this method later
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void particle(XSParticle xsParticle) {
|
||||
// TODO: implement this method later
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void empty(XSContentType xsContentType) {
|
||||
// TODO: implement this method later
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Components for which ying should yield to purple.
|
||||
|
||||
*/
|
||||
public void simpleType(XSSimpleType xsSimpleType) {
|
||||
// simple type always maps to a type, so this is never possible
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
public void attributeUse(XSAttributeUse use) {
|
||||
// attribute use always maps to a property
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema;
|
||||
|
||||
import com.sun.tools.internal.xjc.model.CClassInfo;
|
||||
import com.sun.tools.internal.xjc.model.CDefaultValue;
|
||||
import com.sun.tools.internal.xjc.model.CPropertyInfo;
|
||||
import com.sun.tools.internal.xjc.model.TypeUse;
|
||||
import com.sun.tools.internal.xjc.model.CClass;
|
||||
import com.sun.tools.internal.xjc.reader.Ring;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIProperty;
|
||||
import com.sun.xml.internal.xsom.XSAttGroupDecl;
|
||||
import com.sun.xml.internal.xsom.XSAttributeDecl;
|
||||
import com.sun.xml.internal.xsom.XSAttributeUse;
|
||||
import com.sun.xml.internal.xsom.XSComplexType;
|
||||
import com.sun.xml.internal.xsom.XSContentType;
|
||||
import com.sun.xml.internal.xsom.XSElementDecl;
|
||||
import com.sun.xml.internal.xsom.XSModelGroup;
|
||||
import com.sun.xml.internal.xsom.XSModelGroupDecl;
|
||||
import com.sun.xml.internal.xsom.XSParticle;
|
||||
import com.sun.xml.internal.xsom.XSSimpleType;
|
||||
import com.sun.xml.internal.xsom.XSWildcard;
|
||||
|
||||
/**
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public class BindPurple extends ColorBinder {
|
||||
public void attGroupDecl(XSAttGroupDecl xsAttGroupDecl) {
|
||||
// TODO
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void attributeDecl(XSAttributeDecl xsAttributeDecl) {
|
||||
// TODO
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Attribute use always becomes a property.
|
||||
*/
|
||||
public void attributeUse(XSAttributeUse use) {
|
||||
boolean hasFixedValue = use.getFixedValue()!=null;
|
||||
BIProperty pc = BIProperty.getCustomization(use);
|
||||
|
||||
// map to a constant property ?
|
||||
boolean toConstant = pc.isConstantProperty() && hasFixedValue;
|
||||
TypeUse attType = bindAttDecl(use.getDecl());
|
||||
|
||||
CPropertyInfo prop = pc.createAttributeProperty( use, attType );
|
||||
|
||||
if(toConstant) {
|
||||
prop.defaultValue = CDefaultValue.create(attType,use.getFixedValue());
|
||||
prop.realization = builder.fieldRendererFactory.getConst(prop.realization);
|
||||
} else
|
||||
if(!attType.isCollection() && (prop.baseType == null ? true : !prop.baseType.isPrimitive())) {
|
||||
// don't support a collection default value. That's difficult to do.
|
||||
// primitive types default value is problematic too - we can't check whether it has been set or no ( ==null) isn't possible TODO: emit a waring in these cases
|
||||
|
||||
if(use.getDefaultValue()!=null) {
|
||||
// this attribute use has a default value.
|
||||
// the item type is guaranteed to be a leaf type... or TODO: is it really so?
|
||||
// don't support default values if it's a list
|
||||
prop.defaultValue = CDefaultValue.create(attType,use.getDefaultValue());
|
||||
} else
|
||||
if(use.getFixedValue()!=null) {
|
||||
prop.defaultValue = CDefaultValue.create(attType,use.getFixedValue());
|
||||
}
|
||||
} else if(prop.baseType != null && prop.baseType.isPrimitive()) {
|
||||
ErrorReporter errorReporter = Ring.get(ErrorReporter.class);
|
||||
|
||||
errorReporter.warning(prop.getLocator(), Messages.WARN_DEFAULT_VALUE_PRIMITIVE_TYPE, prop.baseType.name());
|
||||
}
|
||||
|
||||
getCurrentBean().addProperty(prop);
|
||||
}
|
||||
|
||||
private TypeUse bindAttDecl(XSAttributeDecl decl) {
|
||||
SimpleTypeBuilder stb = Ring.get(SimpleTypeBuilder.class);
|
||||
stb.refererStack.push( decl );
|
||||
try {
|
||||
return stb.build(decl.getType());
|
||||
} finally {
|
||||
stb.refererStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void complexType(XSComplexType ct) {
|
||||
CClass ctBean = selector.bindToType(ct,null,false);
|
||||
if(getCurrentBean()!=ctBean)
|
||||
// in some case complex type and element binds to the same class
|
||||
// don't make it has-a. Just make it is-a.
|
||||
getCurrentBean().setBaseClass(ctBean);
|
||||
}
|
||||
|
||||
public void wildcard(XSWildcard xsWildcard) {
|
||||
// element wildcards are processed by particle binders,
|
||||
// so this one is for attribute wildcard.
|
||||
|
||||
getCurrentBean().hasAttributeWildcard(true);
|
||||
}
|
||||
|
||||
public void modelGroupDecl(XSModelGroupDecl xsModelGroupDecl) {
|
||||
// TODO
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void modelGroup(XSModelGroup xsModelGroup) {
|
||||
// TODO
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void elementDecl(XSElementDecl xsElementDecl) {
|
||||
// TODO
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void simpleType(XSSimpleType type) {
|
||||
createSimpleTypeProperty(type,"Value");
|
||||
}
|
||||
|
||||
public void particle(XSParticle xsParticle) {
|
||||
// TODO
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void empty(XSContentType ct) {
|
||||
// empty generates nothing
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema;
|
||||
|
||||
import com.sun.tools.internal.xjc.reader.Ring;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.ct.ComplexTypeFieldBuilder;
|
||||
import com.sun.xml.internal.bind.v2.TODO;
|
||||
import com.sun.xml.internal.xsom.XSAttGroupDecl;
|
||||
import com.sun.xml.internal.xsom.XSAttributeDecl;
|
||||
import com.sun.xml.internal.xsom.XSAttributeUse;
|
||||
import com.sun.xml.internal.xsom.XSComplexType;
|
||||
import com.sun.xml.internal.xsom.XSContentType;
|
||||
import com.sun.xml.internal.xsom.XSElementDecl;
|
||||
import com.sun.xml.internal.xsom.XSModelGroup;
|
||||
import com.sun.xml.internal.xsom.XSModelGroupDecl;
|
||||
import com.sun.xml.internal.xsom.XSParticle;
|
||||
import com.sun.xml.internal.xsom.XSSimpleType;
|
||||
import com.sun.xml.internal.xsom.XSWildcard;
|
||||
|
||||
/**
|
||||
* This is where a binding of a new class starts.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class BindRed extends ColorBinder {
|
||||
|
||||
private final ComplexTypeFieldBuilder ctBuilder = Ring.get(ComplexTypeFieldBuilder.class);
|
||||
|
||||
public void complexType(XSComplexType ct) {
|
||||
ctBuilder.build(ct);
|
||||
}
|
||||
|
||||
public void wildcard(XSWildcard xsWildcard) {
|
||||
// TODO: implement this method later
|
||||
// I guess we might allow this to be mapped to a generic element property ---
|
||||
// not sure exactly how do we do it.
|
||||
TODO.checkSpec();
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void elementDecl(XSElementDecl e) {
|
||||
SimpleTypeBuilder stb = Ring.get(SimpleTypeBuilder.class);
|
||||
stb.refererStack.push(e); // referer is element
|
||||
builder.ying(e.getType(),e);
|
||||
stb.refererStack.pop();
|
||||
}
|
||||
|
||||
public void simpleType(XSSimpleType type) {
|
||||
SimpleTypeBuilder stb = Ring.get(SimpleTypeBuilder.class);
|
||||
stb.refererStack.push(type); // referer is itself
|
||||
createSimpleTypeProperty(type,"Value");
|
||||
stb.refererStack.pop();
|
||||
}
|
||||
|
||||
/*
|
||||
Components that can never be mapped to a class
|
||||
*/
|
||||
public void attGroupDecl(XSAttGroupDecl ag) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
public void attributeDecl(XSAttributeDecl ad) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
public void attributeUse(XSAttributeUse au) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
public void empty(XSContentType xsContentType) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
public void modelGroupDecl(XSModelGroupDecl xsModelGroupDecl) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
public void modelGroup(XSModelGroup xsModelGroup) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
public void particle(XSParticle p) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema;
|
||||
|
||||
import com.sun.xml.internal.xsom.XSAttGroupDecl;
|
||||
import com.sun.xml.internal.xsom.XSAttributeDecl;
|
||||
import com.sun.xml.internal.xsom.XSAttributeUse;
|
||||
import com.sun.xml.internal.xsom.XSComplexType;
|
||||
import com.sun.xml.internal.xsom.XSContentType;
|
||||
import com.sun.xml.internal.xsom.XSElementDecl;
|
||||
import com.sun.xml.internal.xsom.XSModelGroup;
|
||||
import com.sun.xml.internal.xsom.XSModelGroupDecl;
|
||||
import com.sun.xml.internal.xsom.XSParticle;
|
||||
import com.sun.xml.internal.xsom.XSSimpleType;
|
||||
import com.sun.xml.internal.xsom.XSWildcard;
|
||||
|
||||
/**
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class BindYellow extends ColorBinder {
|
||||
public void complexType(XSComplexType ct) {
|
||||
}
|
||||
|
||||
public void wildcard(XSWildcard xsWildcard) {
|
||||
// TODO: implement this method later
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void elementDecl(XSElementDecl xsElementDecl) {
|
||||
// TODO: implement this method later
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void simpleType(XSSimpleType xsSimpleType) {
|
||||
// TODO: implement this method later
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void attributeDecl(XSAttributeDecl xsAttributeDecl) {
|
||||
// TODO: implement this method later
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Components that can never map to a type
|
||||
|
||||
*/
|
||||
public void attGroupDecl(XSAttGroupDecl xsAttGroupDecl) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
public void attributeUse(XSAttributeUse use) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
public void modelGroupDecl(XSModelGroupDecl xsModelGroupDecl) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
public void modelGroup(XSModelGroup xsModelGroup) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
public void particle(XSParticle xsParticle) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
public void empty(XSContentType xsContentType) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema;
|
||||
|
||||
import com.sun.tools.internal.xjc.reader.Ring;
|
||||
|
||||
/**
|
||||
* Component accessible from {@link Ring}.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public abstract class BindingComponent {
|
||||
protected BindingComponent() {
|
||||
Ring.add(this);
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// Accessor to common components.
|
||||
//
|
||||
//
|
||||
|
||||
protected final ErrorReporter getErrorReporter() {
|
||||
return Ring.get(ErrorReporter.class);
|
||||
}
|
||||
protected final ClassSelector getClassSelector() {
|
||||
return Ring.get(ClassSelector.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema;
|
||||
|
||||
import com.sun.tools.internal.xjc.model.CClassInfo;
|
||||
import com.sun.tools.internal.xjc.model.CElement;
|
||||
import com.sun.tools.internal.xjc.model.CElementInfo;
|
||||
import com.sun.xml.internal.xsom.visitor.XSFunction;
|
||||
|
||||
/**
|
||||
* Marker interface for an object that determines how to map
|
||||
* a component to a class. If a component is mapped to a class,
|
||||
* this object returns a {@link CClassInfo} pr {@link CElementInfo} object.
|
||||
*
|
||||
* Otherwise, return null.
|
||||
*/
|
||||
interface ClassBinder extends XSFunction<CElement> {
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema;
|
||||
|
||||
import com.sun.tools.internal.xjc.model.CElement;
|
||||
import com.sun.xml.internal.xsom.XSAnnotation;
|
||||
import com.sun.xml.internal.xsom.XSAttGroupDecl;
|
||||
import com.sun.xml.internal.xsom.XSAttributeDecl;
|
||||
import com.sun.xml.internal.xsom.XSAttributeUse;
|
||||
import com.sun.xml.internal.xsom.XSComplexType;
|
||||
import com.sun.xml.internal.xsom.XSContentType;
|
||||
import com.sun.xml.internal.xsom.XSElementDecl;
|
||||
import com.sun.xml.internal.xsom.XSFacet;
|
||||
import com.sun.xml.internal.xsom.XSIdentityConstraint;
|
||||
import com.sun.xml.internal.xsom.XSModelGroup;
|
||||
import com.sun.xml.internal.xsom.XSModelGroupDecl;
|
||||
import com.sun.xml.internal.xsom.XSNotation;
|
||||
import com.sun.xml.internal.xsom.XSParticle;
|
||||
import com.sun.xml.internal.xsom.XSSchema;
|
||||
import com.sun.xml.internal.xsom.XSSimpleType;
|
||||
import com.sun.xml.internal.xsom.XSWildcard;
|
||||
import com.sun.xml.internal.xsom.XSXPath;
|
||||
|
||||
/**
|
||||
* {@link ClassBinder} that delegates the call to another {@link ClassBinder}.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi (kk@kohsuke.org)
|
||||
*/
|
||||
abstract class ClassBinderFilter implements ClassBinder {
|
||||
private final ClassBinder core;
|
||||
|
||||
protected ClassBinderFilter(ClassBinder core) {
|
||||
this.core = core;
|
||||
}
|
||||
|
||||
public CElement annotation(XSAnnotation xsAnnotation) {
|
||||
return core.annotation(xsAnnotation);
|
||||
}
|
||||
|
||||
public CElement attGroupDecl(XSAttGroupDecl xsAttGroupDecl) {
|
||||
return core.attGroupDecl(xsAttGroupDecl);
|
||||
}
|
||||
|
||||
public CElement attributeDecl(XSAttributeDecl xsAttributeDecl) {
|
||||
return core.attributeDecl(xsAttributeDecl);
|
||||
}
|
||||
|
||||
public CElement attributeUse(XSAttributeUse xsAttributeUse) {
|
||||
return core.attributeUse(xsAttributeUse);
|
||||
}
|
||||
|
||||
public CElement complexType(XSComplexType xsComplexType) {
|
||||
return core.complexType(xsComplexType);
|
||||
}
|
||||
|
||||
public CElement schema(XSSchema xsSchema) {
|
||||
return core.schema(xsSchema);
|
||||
}
|
||||
|
||||
public CElement facet(XSFacet xsFacet) {
|
||||
return core.facet(xsFacet);
|
||||
}
|
||||
|
||||
public CElement notation(XSNotation xsNotation) {
|
||||
return core.notation(xsNotation);
|
||||
}
|
||||
|
||||
public CElement simpleType(XSSimpleType xsSimpleType) {
|
||||
return core.simpleType(xsSimpleType);
|
||||
}
|
||||
|
||||
public CElement particle(XSParticle xsParticle) {
|
||||
return core.particle(xsParticle);
|
||||
}
|
||||
|
||||
public CElement empty(XSContentType xsContentType) {
|
||||
return core.empty(xsContentType);
|
||||
}
|
||||
|
||||
public CElement wildcard(XSWildcard xsWildcard) {
|
||||
return core.wildcard(xsWildcard);
|
||||
}
|
||||
|
||||
public CElement modelGroupDecl(XSModelGroupDecl xsModelGroupDecl) {
|
||||
return core.modelGroupDecl(xsModelGroupDecl);
|
||||
}
|
||||
|
||||
public CElement modelGroup(XSModelGroup xsModelGroup) {
|
||||
return core.modelGroup(xsModelGroup);
|
||||
}
|
||||
|
||||
public CElement elementDecl(XSElementDecl xsElementDecl) {
|
||||
return core.elementDecl(xsElementDecl);
|
||||
}
|
||||
|
||||
public CElement identityConstraint(XSIdentityConstraint xsIdentityConstraint) {
|
||||
return core.identityConstraint(xsIdentityConstraint);
|
||||
}
|
||||
|
||||
public CElement xpath(XSXPath xsxPath) {
|
||||
return core.xpath(xsxPath);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,485 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema;
|
||||
|
||||
import java.io.StringWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
|
||||
import com.sun.codemodel.internal.JCodeModel;
|
||||
import com.sun.codemodel.internal.JJavaName;
|
||||
import com.sun.codemodel.internal.JPackage;
|
||||
import com.sun.codemodel.internal.util.JavadocEscapeWriter;
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import com.sun.tools.internal.xjc.model.CBuiltinLeafInfo;
|
||||
import com.sun.tools.internal.xjc.model.CClassInfo;
|
||||
import com.sun.tools.internal.xjc.model.CClassInfoParent;
|
||||
import com.sun.tools.internal.xjc.model.CElement;
|
||||
import com.sun.tools.internal.xjc.model.CElementInfo;
|
||||
import com.sun.tools.internal.xjc.model.CTypeInfo;
|
||||
import com.sun.tools.internal.xjc.model.TypeUse;
|
||||
import com.sun.tools.internal.xjc.model.CClass;
|
||||
import com.sun.tools.internal.xjc.model.CNonElement;
|
||||
import com.sun.tools.internal.xjc.reader.Ring;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIProperty;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BISchemaBinding;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.LocalScoping;
|
||||
import com.sun.xml.internal.bind.v2.WellKnownNamespace;
|
||||
import com.sun.xml.internal.xsom.XSComplexType;
|
||||
import com.sun.xml.internal.xsom.XSComponent;
|
||||
import com.sun.xml.internal.xsom.XSDeclaration;
|
||||
import com.sun.xml.internal.xsom.XSElementDecl;
|
||||
import com.sun.xml.internal.xsom.XSSchema;
|
||||
import com.sun.xml.internal.xsom.XSSchemaSet;
|
||||
import com.sun.xml.internal.xsom.XSSimpleType;
|
||||
import com.sun.xml.internal.xsom.XSType;
|
||||
import com.sun.xml.internal.xsom.impl.util.SchemaWriter;
|
||||
import com.sun.xml.internal.xsom.util.ComponentNameFunction;
|
||||
|
||||
import org.xml.sax.Locator;
|
||||
|
||||
/**
|
||||
* Manages association between {@link XSComponent}s and generated
|
||||
* {@link CTypeInfo}s.
|
||||
*
|
||||
* <p>
|
||||
* This class determines which component is mapped to (or is not mapped to)
|
||||
* what types.
|
||||
*
|
||||
* @author
|
||||
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
public final class ClassSelector extends BindingComponent {
|
||||
/** Center of owner classes. */
|
||||
private final BGMBuilder builder = Ring.get(BGMBuilder.class);
|
||||
|
||||
|
||||
/**
|
||||
* Map from XSComponents to {@link Binding}s. Keeps track of all
|
||||
* content interfaces that are already built or being built.
|
||||
*/
|
||||
private final Map<XSComponent,Binding> bindMap = new HashMap<XSComponent,Binding>();
|
||||
|
||||
/**
|
||||
* UGLY HACK.
|
||||
* <p>
|
||||
* To avoid cyclic dependency between binding elements and types,
|
||||
* we need additional markers that tell which elements are definitely not bound
|
||||
* to a class.
|
||||
* <p>
|
||||
* the cyclic dependency is as follows:
|
||||
* elements need to bind its types first, because otherwise it can't
|
||||
* determine T of JAXBElement<T>.
|
||||
* OTOH, types need to know whether its parent is bound to a class to decide
|
||||
* which class name to use.
|
||||
*/
|
||||
/*package*/ final Map<XSComponent,CElementInfo> boundElements = new HashMap<XSComponent,CElementInfo>();
|
||||
|
||||
/**
|
||||
* A list of {@link Binding}s object that needs to be built.
|
||||
*/
|
||||
private final Stack<Binding> bindQueue = new Stack<Binding>();
|
||||
|
||||
/**
|
||||
* {@link CClassInfo}s that are already {@link Binding#build() built}.
|
||||
*/
|
||||
private final Set<CClassInfo> built = new HashSet<CClassInfo>();
|
||||
|
||||
/**
|
||||
* Object that determines components that are mapped
|
||||
* to classes.
|
||||
*/
|
||||
private final ClassBinder classBinder;
|
||||
|
||||
/**
|
||||
* {@link CClassInfoParent}s that determines where a new class
|
||||
* should be created.
|
||||
*/
|
||||
private final Stack<CClassInfoParent> classScopes = new Stack<CClassInfoParent>();
|
||||
|
||||
/**
|
||||
* The component that is being bound to {@link #currentBean}.
|
||||
*/
|
||||
private XSComponent currentRoot;
|
||||
/**
|
||||
* The bean representation we are binding right now.
|
||||
*/
|
||||
private CClassInfo currentBean;
|
||||
|
||||
|
||||
private final class Binding {
|
||||
private final XSComponent sc;
|
||||
private final CTypeInfo bean;
|
||||
|
||||
public Binding(XSComponent sc, CTypeInfo bean) {
|
||||
this.sc = sc;
|
||||
this.bean = bean;
|
||||
}
|
||||
|
||||
void build() {
|
||||
if(!(this.bean instanceof CClassInfo))
|
||||
return; // no need to "build"
|
||||
|
||||
CClassInfo bean = (CClassInfo)this.bean;
|
||||
|
||||
if(!built.add(bean))
|
||||
return; // already built
|
||||
|
||||
for( String reservedClassName : reservedClassNames ) {
|
||||
if( bean.getName().equals(reservedClassName) ) {
|
||||
getErrorReporter().error( sc.getLocator(),
|
||||
Messages.ERR_RESERVED_CLASS_NAME, reservedClassName );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if this schema component is an element declaration
|
||||
// and it satisfies a set of conditions specified in the spec,
|
||||
// this class will receive a constructor.
|
||||
if(needValueConstructor(sc)) {
|
||||
// TODO: fragile. There is no guarantee that the property name
|
||||
// is in fact "value".
|
||||
bean.addConstructor("value");
|
||||
}
|
||||
|
||||
if(bean.javadoc==null)
|
||||
addSchemaFragmentJavadoc(bean,sc);
|
||||
|
||||
// build the body
|
||||
if(builder.getGlobalBinding().getFlattenClasses()==LocalScoping.NESTED)
|
||||
pushClassScope(bean);
|
||||
else
|
||||
pushClassScope(bean.parent());
|
||||
XSComponent oldRoot = currentRoot;
|
||||
CClassInfo oldBean = currentBean;
|
||||
currentRoot = sc;
|
||||
currentBean = bean;
|
||||
sc.visit(Ring.get(BindRed.class));
|
||||
currentBean = oldBean;
|
||||
currentRoot = oldRoot;
|
||||
popClassScope();
|
||||
|
||||
// acknowledge property customization on this schema component,
|
||||
// since it is OK to have a customization at the point of declaration
|
||||
// even when no one is using it.
|
||||
BIProperty prop = builder.getBindInfo(sc).get(BIProperty.class);
|
||||
if(prop!=null) prop.markAsAcknowledged();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// should be instanciated only from BGMBuilder.
|
||||
public ClassSelector() {
|
||||
classBinder = new Abstractifier(new DefaultClassBinder());
|
||||
Ring.add(ClassBinder.class,classBinder);
|
||||
|
||||
classScopes.push(null); // so that the getClassFactory method returns null
|
||||
|
||||
XSComplexType anyType = Ring.get(XSSchemaSet.class).getComplexType(WellKnownNamespace.XML_SCHEMA,"anyType");
|
||||
bindMap.put(anyType,new Binding(anyType,CBuiltinLeafInfo.ANYTYPE));
|
||||
}
|
||||
|
||||
/** Gets the current class scope. */
|
||||
public final CClassInfoParent getClassScope() {
|
||||
assert !classScopes.isEmpty();
|
||||
return classScopes.peek();
|
||||
}
|
||||
|
||||
public final void pushClassScope( CClassInfoParent clsFctry ) {
|
||||
assert clsFctry!=null;
|
||||
classScopes.push(clsFctry);
|
||||
}
|
||||
|
||||
public final void popClassScope() {
|
||||
classScopes.pop();
|
||||
}
|
||||
|
||||
public XSComponent getCurrentRoot() {
|
||||
return currentRoot;
|
||||
}
|
||||
|
||||
public CClassInfo getCurrentBean() {
|
||||
return currentBean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given component is bound to a class.
|
||||
*/
|
||||
public final CElement isBound( XSElementDecl x, XSComponent referer ) {
|
||||
CElementInfo r = boundElements.get(x);
|
||||
if(r!=null)
|
||||
return r;
|
||||
return bindToType(x,referer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given component is being mapped to a type.
|
||||
* If so, build that type and return that object.
|
||||
* If it is not being mapped to a type item, return null.
|
||||
*/
|
||||
public CTypeInfo bindToType( XSComponent sc, XSComponent referer ) {
|
||||
return _bindToClass(sc,referer,false);
|
||||
}
|
||||
|
||||
//
|
||||
// some schema components are guaranteed to map to a particular CTypeInfo.
|
||||
// the following versions capture those constraints in the signature
|
||||
// and making the bindToType invocation more type safe.
|
||||
//
|
||||
|
||||
public CElement bindToType( XSElementDecl e, XSComponent referer ) {
|
||||
return (CElement)_bindToClass(e,referer,false);
|
||||
}
|
||||
|
||||
public CClass bindToType( XSComplexType t, XSComponent referer, boolean cannotBeDelayed ) {
|
||||
// this assumption that a complex type always binds to a ClassInfo
|
||||
// does not hold for xs:anyType --- our current approach of handling
|
||||
// this idiosynchracy is to make sure that xs:anyType doesn't use
|
||||
// this codepath.
|
||||
return (CClass)_bindToClass(t,referer,cannotBeDelayed);
|
||||
}
|
||||
|
||||
public TypeUse bindToType( XSType t, XSComponent referer ) {
|
||||
if(t instanceof XSSimpleType) {
|
||||
return Ring.get(SimpleTypeBuilder.class).build((XSSimpleType)t);
|
||||
} else
|
||||
return (CNonElement)_bindToClass(t,referer,false);
|
||||
}
|
||||
|
||||
/**
|
||||
* The real meat of the "bindToType" code.
|
||||
*
|
||||
* @param cannotBeDelayed
|
||||
* if the binding of the body of the class cannot be defered
|
||||
* and needs to be done immediately. If the flag is false,
|
||||
* the binding of the body will be done later, to avoid
|
||||
* cyclic binding problem.
|
||||
* @param referer
|
||||
* The component that refers to <tt>sc</tt>. This can be null,
|
||||
* if figuring out the referer is too hard, in which case
|
||||
* the error message might be less user friendly.
|
||||
*/
|
||||
// TODO: consider getting rid of "cannotBeDelayed"
|
||||
CTypeInfo _bindToClass( @NotNull XSComponent sc, XSComponent referer, boolean cannotBeDelayed ) {
|
||||
// check if this class is already built.
|
||||
if(!bindMap.containsKey(sc)) {
|
||||
// craete a bind task
|
||||
|
||||
// if this is a global declaration, make sure they will be generated
|
||||
// under a package.
|
||||
boolean isGlobal = false;
|
||||
if( sc instanceof XSDeclaration ) {
|
||||
isGlobal = ((XSDeclaration)sc).isGlobal();
|
||||
if( isGlobal )
|
||||
pushClassScope( new CClassInfoParent.Package(
|
||||
getPackage(((XSDeclaration)sc).getTargetNamespace())) );
|
||||
}
|
||||
|
||||
// otherwise check if this component should become a class.
|
||||
CElement bean = sc.apply(classBinder);
|
||||
|
||||
if( isGlobal )
|
||||
popClassScope();
|
||||
|
||||
if(bean==null)
|
||||
return null;
|
||||
|
||||
// can this namespace generate a class?
|
||||
if (bean instanceof CClassInfo) {
|
||||
XSSchema os = sc.getOwnerSchema();
|
||||
BISchemaBinding sb = builder.getBindInfo(os).get(BISchemaBinding.class);
|
||||
if(sb!=null && !sb.map) {
|
||||
// nope
|
||||
getErrorReporter().error(sc.getLocator(),
|
||||
Messages.ERR_REFERENCE_TO_NONEXPORTED_CLASS, sc.apply( new ComponentNameFunction() ) );
|
||||
getErrorReporter().error(sb.getLocation(),
|
||||
Messages.ERR_REFERENCE_TO_NONEXPORTED_CLASS_MAP_FALSE, os.getTargetNamespace() );
|
||||
if(referer!=null)
|
||||
getErrorReporter().error(referer.getLocator(),
|
||||
Messages.ERR_REFERENCE_TO_NONEXPORTED_CLASS_REFERER, referer.apply( new ComponentNameFunction() ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
queueBuild( sc, bean );
|
||||
}
|
||||
|
||||
Binding bind = bindMap.get(sc);
|
||||
if( cannotBeDelayed )
|
||||
bind.build();
|
||||
|
||||
return bind.bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs all the pending build tasks.
|
||||
*/
|
||||
public void executeTasks() {
|
||||
while( bindQueue.size()!=0 )
|
||||
bindQueue.pop().build();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Determines if the given component needs to have a value
|
||||
* constructor (a constructor that takes a parmater.) on ObjectFactory.
|
||||
*/
|
||||
private boolean needValueConstructor( XSComponent sc ) {
|
||||
if(!(sc instanceof XSElementDecl)) return false;
|
||||
|
||||
XSElementDecl decl = (XSElementDecl)sc;
|
||||
if(!decl.getType().isSimpleType()) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static final String[] reservedClassNames = new String[]{"ObjectFactory"};
|
||||
|
||||
public void queueBuild( XSComponent sc, CElement bean ) {
|
||||
// it is an error if the same component is built twice,
|
||||
// or the association is modified.
|
||||
Binding b = new Binding(sc,bean);
|
||||
bindQueue.push(b);
|
||||
Binding old = bindMap.put(sc, b);
|
||||
assert old==null || old.bean==bean;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copies a schema fragment into the javadoc of the generated class.
|
||||
*/
|
||||
private void addSchemaFragmentJavadoc( CClassInfo bean, XSComponent sc ) {
|
||||
|
||||
// first, pick it up from <documentation> if any.
|
||||
String doc = builder.getBindInfo(sc).getDocumentation();
|
||||
if(doc!=null)
|
||||
append(bean, doc);
|
||||
|
||||
// then the description of where this component came from
|
||||
Locator loc = sc.getLocator();
|
||||
String fileName = null;
|
||||
if(loc!=null) {
|
||||
fileName = loc.getPublicId();
|
||||
if(fileName==null)
|
||||
fileName = loc.getSystemId();
|
||||
}
|
||||
if(fileName==null) fileName="";
|
||||
|
||||
String lineNumber=Messages.format( Messages.JAVADOC_LINE_UNKNOWN);
|
||||
if(loc!=null && loc.getLineNumber()!=-1)
|
||||
lineNumber = String.valueOf(loc.getLineNumber());
|
||||
|
||||
String componentName = sc.apply( new ComponentNameFunction() );
|
||||
String jdoc = Messages.format( Messages.JAVADOC_HEADING, componentName, fileName, lineNumber );
|
||||
append(bean,jdoc);
|
||||
|
||||
// then schema fragment
|
||||
StringWriter out = new StringWriter();
|
||||
out.write("<pre>\n");
|
||||
SchemaWriter sw = new SchemaWriter(new JavadocEscapeWriter(out));
|
||||
sc.visit(sw);
|
||||
out.write("</pre>");
|
||||
append(bean,out.toString());
|
||||
}
|
||||
|
||||
private void append(CClassInfo bean, String doc) {
|
||||
if(bean.javadoc==null)
|
||||
bean.javadoc = doc+'\n';
|
||||
else
|
||||
bean.javadoc += '\n'+doc+'\n';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set of package names that are tested (set of <code>String</code>s.)
|
||||
*
|
||||
* This set is used to avoid duplicating "incorrect package name"
|
||||
* errors.
|
||||
*/
|
||||
private static Set<String> checkedPackageNames = new HashSet<String>();
|
||||
|
||||
/**
|
||||
* Gets the Java package to which classes from
|
||||
* this namespace should go.
|
||||
*
|
||||
* <p>
|
||||
* Usually, the getOuterClass method should be used
|
||||
* to determine where to put a class.
|
||||
*/
|
||||
public JPackage getPackage(String targetNamespace) {
|
||||
XSSchema s = Ring.get(XSSchemaSet.class).getSchema(targetNamespace);
|
||||
|
||||
BISchemaBinding sb =
|
||||
builder.getBindInfo(s).get(BISchemaBinding.class);
|
||||
if(sb!=null) sb.markAsAcknowledged();
|
||||
|
||||
String name = null;
|
||||
|
||||
// "-p" takes precedence over everything else
|
||||
if( builder.defaultPackage1 != null )
|
||||
name = builder.defaultPackage1;
|
||||
|
||||
// use the <jaxb:package> customization
|
||||
if( name == null && sb!=null && sb.getPackageName()!=null )
|
||||
name = sb.getPackageName();
|
||||
|
||||
// the JAX-RPC option goes below the <jaxb:package>
|
||||
if( name == null && builder.defaultPackage2 != null )
|
||||
name = builder.defaultPackage2;
|
||||
|
||||
// generate the package name from the targetNamespace
|
||||
if( name == null )
|
||||
name = builder.getNameConverter().toPackageName( targetNamespace );
|
||||
|
||||
// hardcode a package name because the code doesn't compile
|
||||
// if it generated into the default java package
|
||||
if( name == null )
|
||||
name = "generated"; // the last resort
|
||||
|
||||
|
||||
// check if the package name is a valid name.
|
||||
if( checkedPackageNames.add(name) ) {
|
||||
// this is the first time we hear about this package name.
|
||||
if( !JJavaName.isJavaPackageName(name) )
|
||||
// TODO: s.getLocator() is not very helpful.
|
||||
// ideally, we'd like to use the locator where this package name
|
||||
// comes from.
|
||||
getErrorReporter().error(s.getLocator(),
|
||||
Messages.ERR_INCORRECT_PACKAGE_NAME, targetNamespace, name );
|
||||
}
|
||||
|
||||
return Ring.get(JCodeModel.class)._package(name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema;
|
||||
|
||||
import org.xml.sax.Locator;
|
||||
|
||||
/**
|
||||
* Details of a name collision.
|
||||
*
|
||||
* @author
|
||||
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
final class CollisionInfo {
|
||||
private final String name;
|
||||
private final Locator source1;
|
||||
private final Locator source2;
|
||||
|
||||
public CollisionInfo(String name, Locator source1, Locator source2) {
|
||||
this.name = name;
|
||||
this.source1 = source1;
|
||||
this.source2 = source2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a localized message that describes the collision.
|
||||
*/
|
||||
public String toString() {
|
||||
return Messages.format( Messages.MSG_COLLISION_INFO,
|
||||
name, printLocator(source1), printLocator(source2) );
|
||||
}
|
||||
|
||||
private String printLocator(Locator loc) {
|
||||
if( loc==null ) return "";
|
||||
|
||||
int line = loc.getLineNumber();
|
||||
String sysId = loc.getSystemId();
|
||||
if(sysId==null) sysId = Messages.format(Messages.MSG_UNKNOWN_FILE);
|
||||
|
||||
if( line!=-1 )
|
||||
return Messages.format( Messages.MSG_LINE_X_OF_Y,
|
||||
Integer.toString(line), sysId );
|
||||
else
|
||||
return sysId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema;
|
||||
|
||||
import com.sun.tools.internal.xjc.model.CClassInfo;
|
||||
import com.sun.tools.internal.xjc.model.CPropertyInfo;
|
||||
import com.sun.tools.internal.xjc.reader.Ring;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIProperty;
|
||||
import com.sun.xml.internal.xsom.XSAnnotation;
|
||||
import com.sun.xml.internal.xsom.XSComponent;
|
||||
import com.sun.xml.internal.xsom.XSFacet;
|
||||
import com.sun.xml.internal.xsom.XSIdentityConstraint;
|
||||
import com.sun.xml.internal.xsom.XSNotation;
|
||||
import com.sun.xml.internal.xsom.XSSchema;
|
||||
import com.sun.xml.internal.xsom.XSSimpleType;
|
||||
import com.sun.xml.internal.xsom.XSXPath;
|
||||
import com.sun.xml.internal.xsom.visitor.XSVisitor;
|
||||
|
||||
/**
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
abstract class ColorBinder extends BindingComponent implements XSVisitor {
|
||||
protected final BGMBuilder builder = Ring.get(BGMBuilder.class);
|
||||
protected final ClassSelector selector = getClassSelector();
|
||||
|
||||
protected final CClassInfo getCurrentBean() {
|
||||
return selector.getCurrentBean();
|
||||
}
|
||||
protected final XSComponent getCurrentRoot() {
|
||||
return selector.getCurrentRoot();
|
||||
}
|
||||
|
||||
|
||||
protected final void createSimpleTypeProperty(XSSimpleType type,String propName) {
|
||||
BIProperty prop = BIProperty.getCustomization(type);
|
||||
|
||||
SimpleTypeBuilder stb = Ring.get(SimpleTypeBuilder.class);
|
||||
// since we are building the simple type here, use buildDef
|
||||
CPropertyInfo p = prop.createValueProperty(propName,false,type,stb.buildDef(type),BGMBuilder.getName(type));
|
||||
getCurrentBean().addProperty(p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public final void annotation(XSAnnotation xsAnnotation) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
public final void schema(XSSchema xsSchema) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
public final void facet(XSFacet xsFacet) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
public final void notation(XSNotation xsNotation) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
public final void identityConstraint(XSIdentityConstraint xsIdentityConstraint) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
public final void xpath(XSXPath xsxPath) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,558 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema;
|
||||
import static com.sun.tools.internal.xjc.reader.xmlschema.BGMBuilder.getName;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import com.sun.codemodel.internal.JJavaName;
|
||||
import com.sun.codemodel.internal.JPackage;
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import com.sun.istack.internal.Nullable;
|
||||
import com.sun.tools.internal.xjc.ErrorReceiver;
|
||||
import com.sun.tools.internal.xjc.model.CClassInfo;
|
||||
import com.sun.tools.internal.xjc.model.CClassInfoParent;
|
||||
import com.sun.tools.internal.xjc.model.CClassRef;
|
||||
import com.sun.tools.internal.xjc.model.CCustomizations;
|
||||
import com.sun.tools.internal.xjc.model.CElement;
|
||||
import com.sun.tools.internal.xjc.model.CElementInfo;
|
||||
import com.sun.tools.internal.xjc.model.Model;
|
||||
import com.sun.tools.internal.xjc.reader.Ring;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIClass;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIGlobalBinding;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BISchemaBinding;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BindInfo;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIXSubstitutable;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.ct.ComplexTypeFieldBuilder;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.ct.ComplexTypeBindingMode;
|
||||
import com.sun.xml.internal.xsom.XSAnnotation;
|
||||
import com.sun.xml.internal.xsom.XSAttGroupDecl;
|
||||
import com.sun.xml.internal.xsom.XSAttributeDecl;
|
||||
import com.sun.xml.internal.xsom.XSAttributeUse;
|
||||
import com.sun.xml.internal.xsom.XSComplexType;
|
||||
import com.sun.xml.internal.xsom.XSComponent;
|
||||
import com.sun.xml.internal.xsom.XSContentType;
|
||||
import com.sun.xml.internal.xsom.XSDeclaration;
|
||||
import com.sun.xml.internal.xsom.XSElementDecl;
|
||||
import com.sun.xml.internal.xsom.XSFacet;
|
||||
import com.sun.xml.internal.xsom.XSIdentityConstraint;
|
||||
import com.sun.xml.internal.xsom.XSModelGroup;
|
||||
import com.sun.xml.internal.xsom.XSModelGroupDecl;
|
||||
import com.sun.xml.internal.xsom.XSNotation;
|
||||
import com.sun.xml.internal.xsom.XSParticle;
|
||||
import com.sun.xml.internal.xsom.XSSchema;
|
||||
import com.sun.xml.internal.xsom.XSSchemaSet;
|
||||
import com.sun.xml.internal.xsom.XSSimpleType;
|
||||
import com.sun.xml.internal.xsom.XSType;
|
||||
import com.sun.xml.internal.xsom.XSWildcard;
|
||||
import com.sun.xml.internal.xsom.XSXPath;
|
||||
|
||||
import org.xml.sax.Locator;
|
||||
|
||||
/**
|
||||
* Default classBinder implementation. Honors <jaxb:class> customizations
|
||||
* and default bindings.
|
||||
*/
|
||||
final class DefaultClassBinder implements ClassBinder
|
||||
{
|
||||
private final SimpleTypeBuilder stb = Ring.get(SimpleTypeBuilder.class);
|
||||
private final Model model = Ring.get(Model.class);
|
||||
|
||||
protected final BGMBuilder builder = Ring.get(BGMBuilder.class);
|
||||
protected final ClassSelector selector = Ring.get(ClassSelector.class);
|
||||
|
||||
protected final XSSchemaSet schemas = Ring.get(XSSchemaSet.class);
|
||||
|
||||
public CElement attGroupDecl(XSAttGroupDecl decl) {
|
||||
return allow(decl,decl.getName());
|
||||
}
|
||||
|
||||
public CElement attributeDecl(XSAttributeDecl decl) {
|
||||
return allow(decl,decl.getName());
|
||||
}
|
||||
|
||||
public CElement modelGroup(XSModelGroup mgroup) {
|
||||
return never();
|
||||
}
|
||||
|
||||
public CElement modelGroupDecl(XSModelGroupDecl decl) {
|
||||
return never();
|
||||
}
|
||||
|
||||
|
||||
public CElement complexType(XSComplexType type) {
|
||||
CElement ci = allow(type,type.getName());
|
||||
if(ci!=null) return ci;
|
||||
|
||||
// no customization is given -- do as the default binding.
|
||||
|
||||
BindInfo bi = builder.getBindInfo(type);
|
||||
|
||||
if(type.isGlobal()) {
|
||||
QName tagName = null;
|
||||
String className = deriveName(type);
|
||||
Locator loc = type.getLocator();
|
||||
|
||||
if(getGlobalBinding().isSimpleMode()) {
|
||||
// in the simple mode, we may optimize it away
|
||||
XSElementDecl referer = getSoleElementReferer(type);
|
||||
if(referer!=null && isCollapsable(referer)) {
|
||||
// if a global element contains
|
||||
// a collpsable complex type, we bind this element to a named one
|
||||
// and collapses element and complex type.
|
||||
tagName = getName(referer);
|
||||
className = deriveName(referer);
|
||||
loc = referer.getLocator();
|
||||
}
|
||||
}
|
||||
|
||||
// by default, global ones get their own classes.
|
||||
|
||||
JPackage pkg = selector.getPackage(type.getTargetNamespace());
|
||||
|
||||
return new CClassInfo(model,pkg,className, loc,getTypeName(type),tagName,type,bi.toCustomizationList());
|
||||
} else {
|
||||
XSElementDecl element = type.getScope();
|
||||
|
||||
if( element.isGlobal() && isCollapsable(element)) {
|
||||
if(builder.getBindInfo(element).get(BIClass.class)!=null)
|
||||
// the parent element was bound to a class. Don't bind this again to
|
||||
// cause unnecessary wrapping
|
||||
return null;
|
||||
|
||||
// generate one class from element and complex type together.
|
||||
// this needs to be done before selector.isBound to avoid infinite recursion.
|
||||
|
||||
// but avoid doing so when the element is mapped to a class,
|
||||
// which creates unnecessary classes
|
||||
return new CClassInfo( model, selector.getClassScope(),
|
||||
deriveName(element), element.getLocator(), null,
|
||||
getName(element), element, bi.toCustomizationList() );
|
||||
}
|
||||
|
||||
|
||||
CElement parentType = selector.isBound(element,type);
|
||||
|
||||
String className;
|
||||
CClassInfoParent scope;
|
||||
|
||||
|
||||
if( parentType!=null
|
||||
&& parentType instanceof CElementInfo
|
||||
&& ((CElementInfo)parentType).hasClass() ) {
|
||||
// special case where we put a nested 'Type' element
|
||||
scope = (CElementInfo)parentType;
|
||||
className = "Type";
|
||||
} else {
|
||||
// since the parent element isn't bound to a type, merge the customizations associated to it, too.
|
||||
// custs = CCustomizations.merge( custs, builder.getBindInfo(type.getScope()).toCustomizationList());
|
||||
className = builder.getNameConverter().toClassName(element.getName());
|
||||
|
||||
BISchemaBinding sb = builder.getBindInfo(
|
||||
type.getOwnerSchema() ).get(BISchemaBinding.class);
|
||||
if(sb!=null) className = sb.mangleAnonymousTypeClassName(className);
|
||||
scope = selector.getClassScope();
|
||||
}
|
||||
|
||||
return new CClassInfo(model, scope, className, type.getLocator(), null, null, type, bi.toCustomizationList() );
|
||||
}
|
||||
}
|
||||
|
||||
private QName getTypeName(XSComplexType type) {
|
||||
if(type.getRedefinedBy()!=null)
|
||||
return null;
|
||||
else
|
||||
return getName(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the complex type of the given element can be "optimized away"
|
||||
* and unified with its parent element decl to form a single class.
|
||||
*/
|
||||
private boolean isCollapsable(XSElementDecl decl) {
|
||||
XSType type = decl.getType();
|
||||
|
||||
if(!type.isComplexType())
|
||||
return false; // not a complex type
|
||||
|
||||
if(decl.getSubstitutables().size()>1 || decl.getSubstAffiliation()!=null)
|
||||
// because element substitution calls for a proper JAXBElement hierarchy
|
||||
return false;
|
||||
|
||||
if(decl.isNillable())
|
||||
// because nillable needs JAXBElement to represent correctly
|
||||
return false;
|
||||
|
||||
BIXSubstitutable bixSubstitutable = builder.getBindInfo(decl).get(BIXSubstitutable.class);
|
||||
if(bixSubstitutable !=null) {
|
||||
// see https://jaxb.dev.java.net/issues/show_bug.cgi?id=289
|
||||
// this customization forces non-collapsing behavior.
|
||||
bixSubstitutable.markAsAcknowledged();
|
||||
return false;
|
||||
}
|
||||
|
||||
if( getGlobalBinding().isSimpleMode() && decl.isGlobal()) {
|
||||
// in the simple mode, we do more aggressive optimization, and get rid of
|
||||
// a complex type class if it's only used once from a global element
|
||||
XSElementDecl referer = getSoleElementReferer(decl.getType());
|
||||
if(referer!=null) {
|
||||
assert referer==decl; // I must be the sole referer
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!type.isLocal() || !type.isComplexType())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* If only one global {@link XSElementDecl} is refering to {@link XSType},
|
||||
* return that element, otherwise null.
|
||||
*/
|
||||
private @Nullable XSElementDecl getSoleElementReferer(@NotNull XSType t) {
|
||||
Set<XSComponent> referer = builder.getReferer(t);
|
||||
|
||||
XSElementDecl sole = null;
|
||||
for (XSComponent r : referer) {
|
||||
if(r instanceof XSElementDecl) {
|
||||
XSElementDecl x = (XSElementDecl) r;
|
||||
if(!x.isGlobal())
|
||||
// local element references can be ignored, as their names are either given
|
||||
// by the property, or by the JAXBElement (for things like mixed contents)
|
||||
continue;
|
||||
if(sole==null) sole=x;
|
||||
else return null; // more than one
|
||||
} else {
|
||||
// if another type refers to this type, that means
|
||||
// this type has a sub-type, so type substitution is possible now.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return sole;
|
||||
}
|
||||
|
||||
public CElement elementDecl(XSElementDecl decl) {
|
||||
CElement r = allow(decl,decl.getName());
|
||||
|
||||
if(r==null) {
|
||||
QName tagName = getName(decl);
|
||||
CCustomizations custs = builder.getBindInfo(decl).toCustomizationList();
|
||||
|
||||
if(decl.isGlobal()) {
|
||||
if(isCollapsable(decl)) {
|
||||
// we want the returned type to be built as a complex type,
|
||||
// so the binding cannot be delayed.
|
||||
return selector.bindToType(decl.getType().asComplexType(),decl,true);
|
||||
} else {
|
||||
String className = null;
|
||||
if(getGlobalBinding().isGenerateElementClass())
|
||||
className = deriveName(decl);
|
||||
|
||||
// otherwise map global elements to JAXBElement
|
||||
CElementInfo cei = new CElementInfo(
|
||||
model, tagName, selector.getClassScope(), className, custs, decl.getLocator());
|
||||
selector.boundElements.put(decl,cei);
|
||||
|
||||
stb.refererStack.push(decl); // referer is element
|
||||
cei.initContentType( selector.bindToType(decl.getType(),decl), decl, decl.getDefaultValue() );
|
||||
stb.refererStack.pop();
|
||||
r = cei;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// have the substitution member derive from the substitution head
|
||||
XSElementDecl top = decl.getSubstAffiliation();
|
||||
if(top!=null) {
|
||||
CElement topci = selector.bindToType(top,decl);
|
||||
|
||||
if(r instanceof CClassInfo && topci instanceof CClassInfo)
|
||||
((CClassInfo)r).setBaseClass((CClassInfo)topci);
|
||||
if (r instanceof CElementInfo && topci instanceof CElementInfo)
|
||||
((CElementInfo)r).setSubstitutionHead((CElementInfo)topci);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
public CClassInfo empty( XSContentType ct ) { return null; }
|
||||
|
||||
public CClassInfo identityConstraint(XSIdentityConstraint xsIdentityConstraint) {
|
||||
return never();
|
||||
}
|
||||
|
||||
public CClassInfo xpath(XSXPath xsxPath) {
|
||||
return never();
|
||||
}
|
||||
|
||||
public CClassInfo attributeUse(XSAttributeUse use) {
|
||||
return never();
|
||||
}
|
||||
|
||||
public CElement simpleType(XSSimpleType type) {
|
||||
CElement c = allow(type,type.getName());
|
||||
if(c!=null) return c;
|
||||
|
||||
if(getGlobalBinding().isSimpleTypeSubstitution() && type.isGlobal()) {
|
||||
return new CClassInfo(model,selector.getClassScope(),
|
||||
deriveName(type), type.getLocator(), getName(type), null, type, null );
|
||||
}
|
||||
|
||||
return never();
|
||||
}
|
||||
|
||||
public CClassInfo particle(XSParticle particle) {
|
||||
return never();
|
||||
}
|
||||
|
||||
public CClassInfo wildcard(XSWildcard wc) {
|
||||
return never();
|
||||
}
|
||||
|
||||
|
||||
// these methods won't be used
|
||||
public CClassInfo annotation(XSAnnotation annon) {
|
||||
assert false;
|
||||
return null;
|
||||
}
|
||||
|
||||
public CClassInfo notation(XSNotation not) {
|
||||
assert false;
|
||||
return null;
|
||||
}
|
||||
|
||||
public CClassInfo facet(XSFacet decl) {
|
||||
assert false;
|
||||
return null;
|
||||
}
|
||||
public CClassInfo schema(XSSchema schema) {
|
||||
assert false;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Makes sure that the component doesn't carry a {@link BIClass}
|
||||
* customization.
|
||||
*
|
||||
* @return
|
||||
* return value is unused. Since most of the caller needs to
|
||||
* return null, to make the code a little bit shorter, this
|
||||
* method always return null (so that the caller can always
|
||||
* say <code>return never(sc);</code>.
|
||||
*/
|
||||
private CClassInfo never() {
|
||||
// all we need to do here is just not to acknowledge
|
||||
// any class customization. Then this class customization
|
||||
// will be reported as an error later when we check all
|
||||
// unacknowledged customizations.
|
||||
|
||||
|
||||
// BIDeclaration cust=owner.getBindInfo(component).get(BIClass.NAME);
|
||||
// if(cust!=null) {
|
||||
// // error
|
||||
// owner.errorReporter.error(
|
||||
// cust.getLocation(),
|
||||
// "test {0}", NameGetter.get(component) );
|
||||
// }
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a component carries a customization to map it to a class.
|
||||
* If so, make it a class.
|
||||
*
|
||||
* @param defaultBaseName
|
||||
* The token which will be used as the basis of the class name
|
||||
* if the class name is not specified in the customization.
|
||||
* This is usually the name of an element declaration, and so on.
|
||||
*
|
||||
* This parameter can be null, in that case it would be an error
|
||||
* if a name is not given by the customization.
|
||||
*/
|
||||
private CElement allow( XSComponent component, String defaultBaseName ) {
|
||||
|
||||
BIClass decl = null;
|
||||
|
||||
if(component instanceof XSComplexType) {
|
||||
XSType complexType = (XSType)component;
|
||||
|
||||
BIClass lastFoundRecursiveBiClass = null;
|
||||
|
||||
if(complexType.getName() != null) {
|
||||
while( ! schemas.getAnyType().equals(complexType)) {
|
||||
BindInfo bindInfo = builder.getBindInfo(complexType);
|
||||
BIClass biClass = bindInfo.get(BIClass.class);
|
||||
|
||||
if(biClass != null && "true".equals(biClass.getRecursive()))
|
||||
lastFoundRecursiveBiClass = biClass;
|
||||
|
||||
complexType = complexType.getBaseType();
|
||||
}
|
||||
}
|
||||
|
||||
// use this as biclass for current component
|
||||
decl = lastFoundRecursiveBiClass;
|
||||
|
||||
}
|
||||
|
||||
BindInfo bindInfo = builder.getBindInfo(component);
|
||||
if(decl == null) {
|
||||
decl = bindInfo.get(BIClass.class);
|
||||
if(decl==null) return null;
|
||||
}
|
||||
|
||||
decl.markAsAcknowledged();
|
||||
|
||||
// first consider binding to the class reference.
|
||||
String ref = decl.getExistingClassRef();
|
||||
if(ref!=null) {
|
||||
if(!JJavaName.isFullyQualifiedClassName(ref)) {
|
||||
Ring.get(ErrorReceiver.class).error( decl.getLocation(),
|
||||
Messages.format(Messages.ERR_INCORRECT_CLASS_NAME,ref) );
|
||||
// recover by ignoring @ref
|
||||
} else {
|
||||
if(component instanceof XSComplexType) {
|
||||
// UGLY UGLY UGLY
|
||||
// since we are not going to bind this complex type, we need to figure out
|
||||
// its binding mode without actually binding it (and also expose this otherwise
|
||||
// hidden mechanism into this part of the code.)
|
||||
//
|
||||
// this code is potentially dangerous as the base class might have been bound
|
||||
// in different ways. To be correct, we need to figure out how the content type
|
||||
// would have been bound, from the schema.
|
||||
Ring.get(ComplexTypeFieldBuilder.class).recordBindingMode(
|
||||
(XSComplexType)component, ComplexTypeBindingMode.NORMAL
|
||||
);
|
||||
}
|
||||
return new CClassRef(model, component, decl, bindInfo.toCustomizationList() );
|
||||
}
|
||||
}
|
||||
|
||||
String clsName = decl.getClassName();
|
||||
if(clsName==null) {
|
||||
// if the customiztion doesn't give us a name, derive one
|
||||
// from the current component.
|
||||
if( defaultBaseName==null ) {
|
||||
Ring.get(ErrorReceiver.class).error( decl.getLocation(),
|
||||
Messages.format(Messages.ERR_CLASS_NAME_IS_REQUIRED) );
|
||||
|
||||
// recover by generating a pseudo-random name
|
||||
defaultBaseName = "undefined"+component.hashCode();
|
||||
}
|
||||
clsName = builder.deriveName( defaultBaseName, component );
|
||||
} else {
|
||||
if( !JJavaName.isJavaIdentifier(clsName) ) {
|
||||
// not a valid Java class name
|
||||
Ring.get(ErrorReceiver.class).error( decl.getLocation(),
|
||||
Messages.format( Messages.ERR_INCORRECT_CLASS_NAME, clsName ));
|
||||
// recover by a dummy name
|
||||
clsName = "Undefined"+component.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
QName typeName = null;
|
||||
QName elementName = null;
|
||||
|
||||
if(component instanceof XSType) {
|
||||
XSType t = (XSType) component;
|
||||
typeName = getName(t);
|
||||
}
|
||||
|
||||
if (component instanceof XSElementDecl) {
|
||||
XSElementDecl e = (XSElementDecl) component;
|
||||
elementName = getName(e);
|
||||
}
|
||||
|
||||
if (component instanceof XSElementDecl && !isCollapsable((XSElementDecl)component)) {
|
||||
XSElementDecl e = ((XSElementDecl)component);
|
||||
|
||||
CElementInfo cei = new CElementInfo(model, elementName,
|
||||
selector.getClassScope(), clsName,
|
||||
bindInfo.toCustomizationList(), decl.getLocation() );
|
||||
selector.boundElements.put(e,cei);
|
||||
|
||||
stb.refererStack.push(component); // referer is element
|
||||
cei.initContentType(
|
||||
selector.bindToType(e.getType(),e),
|
||||
e,e.getDefaultValue());
|
||||
stb.refererStack.pop();
|
||||
return cei;
|
||||
// TODO: support javadoc and userSpecifiedImplClass
|
||||
} else {
|
||||
CClassInfo bt = new CClassInfo(model,selector.getClassScope(),
|
||||
clsName, decl.getLocation(), typeName, elementName, component, bindInfo.toCustomizationList() );
|
||||
|
||||
// set javadoc class comment.
|
||||
if(decl.getJavadoc()!=null )
|
||||
bt.javadoc = decl.getJavadoc()+"\n\n";
|
||||
// add extra blank lines so that the schema fragment
|
||||
// and user-specified javadoc would be separated
|
||||
|
||||
|
||||
// if the implClass is given, set it to ClassItem
|
||||
String implClass = decl.getUserSpecifiedImplClass();
|
||||
if( implClass!=null )
|
||||
bt.setUserSpecifiedImplClass( implClass );
|
||||
|
||||
return bt;
|
||||
}
|
||||
}
|
||||
|
||||
private BIGlobalBinding getGlobalBinding() {
|
||||
return builder.getGlobalBinding();
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives a name from a schema component.
|
||||
* Use the name of the schema component as the default name.
|
||||
*/
|
||||
private String deriveName( XSDeclaration comp ) {
|
||||
return builder.deriveName( comp.getName(), comp );
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives a name from a schema component.
|
||||
* For complex types, we take redefinition into account when
|
||||
* deriving a default name.
|
||||
*/
|
||||
private String deriveName( XSComplexType comp ) {
|
||||
String seed = builder.deriveName( comp.getName(), comp );
|
||||
int cnt = comp.getRedefinedCount();
|
||||
for( ; cnt>0; cnt-- )
|
||||
seed = "Original"+seed;
|
||||
return seed;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,392 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.sun.tools.internal.xjc.model.CClassInfo;
|
||||
import com.sun.tools.internal.xjc.model.CPropertyInfo;
|
||||
import com.sun.tools.internal.xjc.model.CReferencePropertyInfo;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIProperty;
|
||||
import com.sun.xml.internal.xsom.XSElementDecl;
|
||||
import com.sun.xml.internal.xsom.XSModelGroup;
|
||||
import com.sun.xml.internal.xsom.XSModelGroupDecl;
|
||||
import com.sun.xml.internal.xsom.XSParticle;
|
||||
import com.sun.xml.internal.xsom.XSTerm;
|
||||
import com.sun.xml.internal.xsom.XSWildcard;
|
||||
import com.sun.xml.internal.xsom.visitor.XSTermVisitor;
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* {@link ParticleBinder} that follows the JAXB spec.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class DefaultParticleBinder extends ParticleBinder {
|
||||
|
||||
@Override
|
||||
public void build( XSParticle p, Collection<XSParticle> forcedProps ) {
|
||||
Checker checker = checkCollision(p,forcedProps);
|
||||
|
||||
if(checker.hasNameCollision()) {
|
||||
CReferencePropertyInfo prop = new CReferencePropertyInfo(
|
||||
getCurrentBean().getBaseClass()==null?"Content":"Rest",
|
||||
true, false, false, p,
|
||||
builder.getBindInfo(p).toCustomizationList(),
|
||||
p.getLocator(), false, false, false);
|
||||
RawTypeSetBuilder.build(p,false).addTo(prop);
|
||||
prop.javadoc = Messages.format( Messages.MSG_FALLBACK_JAVADOC,
|
||||
checker.getCollisionInfo().toString() );
|
||||
|
||||
getCurrentBean().addProperty(prop);
|
||||
} else {
|
||||
new Builder(checker.markedParticles).particle(p);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkFallback( XSParticle p ) {
|
||||
return checkCollision(p,Collections.<XSParticle>emptyList()).hasNameCollision();
|
||||
}
|
||||
|
||||
private Checker checkCollision( XSParticle p, Collection<XSParticle> forcedProps ) {
|
||||
// scan the tree by a checker.
|
||||
Checker checker = new Checker(forcedProps);
|
||||
|
||||
CClassInfo superClass = getCurrentBean().getBaseClass();
|
||||
|
||||
if(superClass!=null)
|
||||
checker.readSuperClass(superClass);
|
||||
checker.particle(p);
|
||||
|
||||
return checker;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Marks particles that need to be mapped to properties,
|
||||
* by reading customization info.
|
||||
*/
|
||||
private final class Checker implements XSTermVisitor {
|
||||
|
||||
Checker(Collection<XSParticle> forcedProps) {
|
||||
this.forcedProps = forcedProps;
|
||||
}
|
||||
|
||||
boolean hasNameCollision() {
|
||||
return collisionInfo!=null;
|
||||
}
|
||||
|
||||
CollisionInfo getCollisionInfo() {
|
||||
return collisionInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* If a collision is found, this field will be non-null.
|
||||
*/
|
||||
private CollisionInfo collisionInfo = null;
|
||||
|
||||
/** Used to check name collision. */
|
||||
private final NameCollisionChecker cchecker = new NameCollisionChecker();
|
||||
|
||||
/**
|
||||
* @see DefaultParticleBinder#build(XSParticle, Collection<com.sun.xml.internal.xsom.XSParticle>)
|
||||
*/
|
||||
private final Collection<XSParticle> forcedProps;
|
||||
|
||||
public void particle( XSParticle p ) {
|
||||
|
||||
if(getLocalPropCustomization(p)!=null
|
||||
|| builder.getLocalDomCustomization(p)!=null) {
|
||||
// if a property customization is specfied,
|
||||
// check that value and turn around.
|
||||
check(p);
|
||||
mark(p);
|
||||
return;
|
||||
}
|
||||
|
||||
XSTerm t = p.getTerm();
|
||||
|
||||
if(p.isRepeated() && (t.isModelGroup() || t.isModelGroupDecl())) {
|
||||
// a repeated model group gets its own property
|
||||
mark(p);
|
||||
return;
|
||||
}
|
||||
|
||||
if(forcedProps.contains(p)) {
|
||||
// this particle must become a property
|
||||
mark(p);
|
||||
return;
|
||||
}
|
||||
|
||||
outerParticle = p;
|
||||
t.visit(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* This field points to the parent XSParticle.
|
||||
* The value is only valid when we are processing XSTerm.
|
||||
*/
|
||||
private XSParticle outerParticle;
|
||||
|
||||
public void elementDecl(XSElementDecl decl) {
|
||||
check(outerParticle);
|
||||
mark(outerParticle);
|
||||
}
|
||||
|
||||
public void modelGroup(XSModelGroup mg) {
|
||||
// choice gets mapped to a property
|
||||
if(mg.getCompositor()== XSModelGroup.Compositor.CHOICE && builder.getGlobalBinding().isChoiceContentPropertyEnabled()) {
|
||||
mark(outerParticle);
|
||||
return;
|
||||
}
|
||||
|
||||
for( XSParticle child : mg.getChildren() )
|
||||
particle(child);
|
||||
}
|
||||
|
||||
public void modelGroupDecl(XSModelGroupDecl decl) {
|
||||
modelGroup(decl.getModelGroup());
|
||||
}
|
||||
|
||||
public void wildcard(XSWildcard wc) {
|
||||
mark(outerParticle);
|
||||
}
|
||||
|
||||
void readSuperClass( CClassInfo ci ) {
|
||||
cchecker.readSuperClass(ci);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Checks the name collision of a newly found particle.
|
||||
*/
|
||||
private void check( XSParticle p ) {
|
||||
if( collisionInfo==null )
|
||||
collisionInfo = cchecker.check(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks a particle that it's going to be mapped to a property.
|
||||
*/
|
||||
private void mark( XSParticle p ) {
|
||||
markedParticles.put(p,computeLabel(p));
|
||||
}
|
||||
|
||||
/**
|
||||
* Marked particles.
|
||||
*
|
||||
* A map from XSParticle to its label.
|
||||
*/
|
||||
public final Map<XSParticle,String> markedParticles = new HashMap<XSParticle,String>();
|
||||
|
||||
|
||||
/**
|
||||
* Checks name collisions among particles that belong to sequences.
|
||||
*/
|
||||
private final class NameCollisionChecker {
|
||||
|
||||
/**
|
||||
* Checks the label conflict of a particle.
|
||||
* This method shall be called for each marked particle.
|
||||
*
|
||||
* @return
|
||||
* a description of a collision if a name collision is
|
||||
* found. Otherwise null.
|
||||
*/
|
||||
CollisionInfo check( XSParticle p ) {
|
||||
// this can be used for particles with a property customization,
|
||||
// which may not have element declaration as its term.
|
||||
// // we only check particles with element declarations.
|
||||
// _assert( p.getTerm().isElementDecl() );
|
||||
|
||||
String label = computeLabel(p);
|
||||
if( occupiedLabels.containsKey(label) ) {
|
||||
// collide with occupied labels
|
||||
return new CollisionInfo(label,p.getLocator(),
|
||||
occupiedLabels.get(label).locator);
|
||||
}
|
||||
|
||||
for( XSParticle jp : particles ) {
|
||||
if(!check( p, jp )) {
|
||||
// problem was found. no need to check further
|
||||
return new CollisionInfo( label, p.getLocator(), jp.getLocator() );
|
||||
}
|
||||
}
|
||||
particles.add(p);
|
||||
return null;
|
||||
}
|
||||
|
||||
/** List of particles reported through the check method. */
|
||||
private final List<XSParticle> particles = new ArrayList<XSParticle>();
|
||||
|
||||
/**
|
||||
* Label names already used in the base type.
|
||||
*/
|
||||
private final Map<String,CPropertyInfo> occupiedLabels = new HashMap<String,CPropertyInfo>();
|
||||
|
||||
/**
|
||||
* Checks the conflict of two particles.
|
||||
* @return
|
||||
* true if the check was successful.
|
||||
*/
|
||||
private boolean check( XSParticle p1, XSParticle p2 ) {
|
||||
return !computeLabel(p1).equals(computeLabel(p2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads fields of the super class and includes them
|
||||
* to name collision tests.
|
||||
*/
|
||||
void readSuperClass( CClassInfo base ) {
|
||||
for( ; base!=null; base=base.getBaseClass() ) {
|
||||
for( CPropertyInfo p : base.getProperties() )
|
||||
occupiedLabels.put(p.getName(true),p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Keep the computed label names for particles. */
|
||||
private final Map<XSParticle,String> labelCache = new Hashtable<XSParticle,String>();
|
||||
|
||||
/**
|
||||
* Hides the computeLabel method of the outer class
|
||||
* and adds caching.
|
||||
*/
|
||||
private String computeLabel( XSParticle p ) {
|
||||
String label = labelCache.get(p);
|
||||
if(label==null)
|
||||
labelCache.put( p, label=DefaultParticleBinder.this.computeLabel(p) );
|
||||
return label;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Builds properties by using the result computed by Checker
|
||||
*/
|
||||
private final class Builder implements XSTermVisitor {
|
||||
Builder( Map<XSParticle,String> markedParticles ) {
|
||||
this.markedParticles = markedParticles;
|
||||
}
|
||||
|
||||
/** All marked particles. */
|
||||
private final Map<XSParticle,String/*label*/> markedParticles;
|
||||
|
||||
/**
|
||||
* When we are visiting inside an optional particle, this flag
|
||||
* is set to true.
|
||||
*
|
||||
* <p>
|
||||
* This allows us to correctly generate primitive/boxed types.
|
||||
*/
|
||||
private boolean insideOptionalParticle;
|
||||
|
||||
|
||||
/** Returns true if a particle is marked. */
|
||||
private boolean marked( XSParticle p ) {
|
||||
return markedParticles.containsKey(p);
|
||||
}
|
||||
/** Gets a label of a particle. */
|
||||
private String getLabel( XSParticle p ) {
|
||||
return markedParticles.get(p);
|
||||
}
|
||||
|
||||
public void particle( XSParticle p ) {
|
||||
XSTerm t = p.getTerm();
|
||||
|
||||
if(marked(p)) {
|
||||
BIProperty cust = BIProperty.getCustomization(p);
|
||||
CPropertyInfo prop = cust.createElementOrReferenceProperty(
|
||||
getLabel(p), false, p, RawTypeSetBuilder.build(p,insideOptionalParticle));
|
||||
getCurrentBean().addProperty(prop);
|
||||
} else {
|
||||
// repeated model groups should have been marked already
|
||||
assert !p.isRepeated();
|
||||
|
||||
boolean oldIOP = insideOptionalParticle;
|
||||
insideOptionalParticle |= BigInteger.ZERO.equals(p.getMinOccurs());
|
||||
// this is an unmarked particle
|
||||
t.visit(this);
|
||||
insideOptionalParticle = oldIOP;
|
||||
}
|
||||
}
|
||||
|
||||
public void elementDecl( XSElementDecl e ) {
|
||||
// because the corresponding particle must be marked.
|
||||
assert false;
|
||||
}
|
||||
|
||||
public void wildcard( XSWildcard wc ) {
|
||||
// because the corresponding particle must be marked.
|
||||
assert false;
|
||||
}
|
||||
|
||||
public void modelGroupDecl( XSModelGroupDecl decl ) {
|
||||
modelGroup(decl.getModelGroup());
|
||||
}
|
||||
|
||||
public void modelGroup( XSModelGroup mg ) {
|
||||
boolean oldIOP = insideOptionalParticle;
|
||||
insideOptionalParticle |= mg.getCompositor()==XSModelGroup.CHOICE;
|
||||
|
||||
for( XSParticle p : mg.getChildren())
|
||||
particle(p);
|
||||
|
||||
insideOptionalParticle = oldIOP;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema;
|
||||
|
||||
import com.sun.tools.internal.xjc.ErrorReceiver;
|
||||
import com.sun.tools.internal.xjc.reader.Ring;
|
||||
|
||||
import org.xml.sax.ErrorHandler;
|
||||
import org.xml.sax.Locator;
|
||||
import org.xml.sax.SAXParseException;
|
||||
|
||||
/**
|
||||
* Provides error report capability to other owner components
|
||||
* by encapsulating user-specified {@link ErrorHandler}
|
||||
* and exposing utlity methods.
|
||||
*
|
||||
* <p>
|
||||
* This class also wraps SAXException to a RuntimeException
|
||||
* so that the exception thrown inside the error handler
|
||||
* can abort the process.
|
||||
*
|
||||
* <p>
|
||||
* At the end of the day, we need to know if there was any error.
|
||||
* So it is important that all the error messages go through this
|
||||
* object. This is done by hiding the errorHandler from the rest
|
||||
* of the components.
|
||||
*
|
||||
* @author
|
||||
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
public final class ErrorReporter extends BindingComponent {
|
||||
|
||||
/**
|
||||
* Error handler to report any binding error to.
|
||||
* To report errors, use the error method.
|
||||
*/
|
||||
private final ErrorReceiver errorReceiver = Ring.get(ErrorReceiver.class);
|
||||
|
||||
|
||||
//
|
||||
// helper methods for classes in this package.
|
||||
// properties are localized through the Messages.properties file
|
||||
// in this package
|
||||
//
|
||||
void error( Locator loc, String prop, Object... args ) {
|
||||
errorReceiver.error( loc, Messages.format(prop,args) );
|
||||
}
|
||||
|
||||
void warning( Locator loc, String prop, Object... args ) {
|
||||
errorReceiver.warning( new SAXParseException(
|
||||
Messages.format(prop,args), loc ));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
private String format( String prop, Object[] args ) {
|
||||
// use a bit verbose code to make it portable.
|
||||
String className = this.getClass().getName();
|
||||
int idx = className.lastIndexOf('.');
|
||||
String packageName = className.substring(0,idx);
|
||||
|
||||
String fmt = ResourceBundle.getBundle(packageName+".Messages").getString(prop);
|
||||
|
||||
return MessageFormat.format(fmt,args);
|
||||
}
|
||||
*/
|
||||
|
||||
////
|
||||
////
|
||||
//// ErrorHandler implementation
|
||||
////
|
||||
////
|
||||
// public void error(SAXParseException exception) {
|
||||
// errorReceiver.error(exception);
|
||||
// }
|
||||
//
|
||||
// public void fatalError(SAXParseException exception) {
|
||||
// errorReceiver.fatalError(exception);
|
||||
// }
|
||||
//
|
||||
// public void warning(SAXParseException exception) {
|
||||
// errorReceiver.warning(exception);
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAnyElement;
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import com.sun.tools.internal.xjc.reader.gbind.Choice;
|
||||
import com.sun.tools.internal.xjc.reader.gbind.Element;
|
||||
import com.sun.tools.internal.xjc.reader.gbind.Expression;
|
||||
import com.sun.tools.internal.xjc.reader.gbind.OneOrMore;
|
||||
import com.sun.tools.internal.xjc.reader.gbind.Sequence;
|
||||
import com.sun.xml.internal.xsom.XSElementDecl;
|
||||
import com.sun.xml.internal.xsom.XSModelGroup;
|
||||
import com.sun.xml.internal.xsom.XSModelGroupDecl;
|
||||
import com.sun.xml.internal.xsom.XSParticle;
|
||||
import com.sun.xml.internal.xsom.XSWildcard;
|
||||
import com.sun.xml.internal.xsom.visitor.XSTermFunction;
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* Visits {@link XSParticle} and creates a corresponding {@link Expression} tree.
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class ExpressionBuilder implements XSTermFunction<Expression> {
|
||||
|
||||
public static Expression createTree(XSParticle p) {
|
||||
return new ExpressionBuilder().particle(p);
|
||||
}
|
||||
|
||||
private ExpressionBuilder() {}
|
||||
|
||||
/**
|
||||
* Wildcard instance needs to be consolidated to one,
|
||||
* and this is such instance (if any.)
|
||||
*/
|
||||
private GWildcardElement wildcard = null;
|
||||
|
||||
private final Map<QName,GElementImpl> decls = new HashMap<QName,GElementImpl>();
|
||||
|
||||
private XSParticle current;
|
||||
|
||||
/**
|
||||
* We can only have one {@link XmlAnyElement} property,
|
||||
* so all the wildcards need to be treated as one node.
|
||||
*/
|
||||
public Expression wildcard(XSWildcard wc) {
|
||||
if(wildcard==null)
|
||||
wildcard = new GWildcardElement();
|
||||
wildcard.merge(wc);
|
||||
wildcard.particles.add(current);
|
||||
return wildcard;
|
||||
}
|
||||
|
||||
public Expression modelGroupDecl(XSModelGroupDecl decl) {
|
||||
return modelGroup(decl.getModelGroup());
|
||||
}
|
||||
|
||||
public Expression modelGroup(XSModelGroup group) {
|
||||
XSModelGroup.Compositor comp = group.getCompositor();
|
||||
if(comp==XSModelGroup.CHOICE) {
|
||||
// empty choice is not epsilon, but empty set,
|
||||
// so this initial value is incorrect. But this
|
||||
// kinda works.
|
||||
// properly handling empty set requires more work.
|
||||
Expression e = Expression.EPSILON;
|
||||
for (XSParticle p : group.getChildren()) {
|
||||
if(e==null) e = particle(p);
|
||||
else e = new Choice(e,particle(p));
|
||||
}
|
||||
return e;
|
||||
} else {
|
||||
Expression e = Expression.EPSILON;
|
||||
for (XSParticle p : group.getChildren()) {
|
||||
if(e==null) e = particle(p);
|
||||
else e = new Sequence(e,particle(p));
|
||||
}
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
public Element elementDecl(XSElementDecl decl) {
|
||||
QName n = BGMBuilder.getName(decl);
|
||||
|
||||
GElementImpl e = decls.get(n);
|
||||
if(e==null)
|
||||
decls.put(n,e=new GElementImpl(n,decl));
|
||||
|
||||
e.particles.add(current);
|
||||
assert current.getTerm()==decl;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
public Expression particle(XSParticle p) {
|
||||
current = p;
|
||||
Expression e = p.getTerm().apply(this);
|
||||
|
||||
if(p.isRepeated())
|
||||
e = new OneOrMore(e);
|
||||
|
||||
if (BigInteger.ZERO.equals(p.getMinOccurs()))
|
||||
e = new Choice(e,Expression.EPSILON);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.sun.tools.internal.xjc.model.CPropertyInfo;
|
||||
import com.sun.tools.internal.xjc.model.Multiplicity;
|
||||
import com.sun.tools.internal.xjc.reader.RawTypeSet;
|
||||
import com.sun.tools.internal.xjc.reader.gbind.ConnectedComponent;
|
||||
import com.sun.tools.internal.xjc.reader.gbind.Element;
|
||||
import com.sun.tools.internal.xjc.reader.gbind.Expression;
|
||||
import com.sun.tools.internal.xjc.reader.gbind.Graph;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIProperty;
|
||||
import com.sun.xml.internal.bind.v2.model.core.WildcardMode;
|
||||
import com.sun.xml.internal.xsom.XSParticle;
|
||||
|
||||
/**
|
||||
* {@link ParticleBinder} that uses {@link ExpressionBuilder} et al
|
||||
* for better, more intuitive (but non spec-conforming) binding.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class ExpressionParticleBinder extends ParticleBinder {
|
||||
public void build(XSParticle p, Collection<XSParticle> forcedProps) {
|
||||
// this class isn't about spec conformance, but
|
||||
// for the ease of use.
|
||||
// so we don't give a damn about 'forcedProps'.
|
||||
// although, for a future note, it's conceivable to expand
|
||||
// the binding algorithm to cover this notion.
|
||||
|
||||
Expression tree = ExpressionBuilder.createTree(p);
|
||||
Graph g = new Graph(tree);
|
||||
for (ConnectedComponent cc : g) {
|
||||
buildProperty(cc);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a property ouf ot a connected component.
|
||||
*/
|
||||
private void buildProperty(ConnectedComponent cc) {
|
||||
StringBuilder propName = new StringBuilder(); // property name
|
||||
int nameTokenCount = 0; // combine only up to 3
|
||||
|
||||
RawTypeSetBuilder rtsb = new RawTypeSetBuilder();
|
||||
for (Element e : cc) {
|
||||
GElement ge = (GElement)e;
|
||||
|
||||
if(nameTokenCount<3) {
|
||||
if(nameTokenCount!=0)
|
||||
propName.append("And");
|
||||
propName.append(makeJavaName(cc.isCollection(),ge.getPropertyNameSeed()));
|
||||
nameTokenCount++;
|
||||
}
|
||||
|
||||
if(e instanceof GElementImpl) {
|
||||
GElementImpl ei = (GElementImpl) e;
|
||||
rtsb.elementDecl(ei.decl);
|
||||
continue;
|
||||
}
|
||||
if(e instanceof GWildcardElement) {
|
||||
GWildcardElement w = (GWildcardElement)e;
|
||||
rtsb.getRefs().add(new RawTypeSetBuilder.WildcardRef(
|
||||
w.isStrict() ? WildcardMode.STRICT : WildcardMode.SKIP));
|
||||
continue;
|
||||
}
|
||||
assert false : e; // no other kind should be here
|
||||
}
|
||||
|
||||
Multiplicity m = Multiplicity.ONE;
|
||||
if(cc.isCollection())
|
||||
m = m.makeRepeated();
|
||||
if(!cc.isRequired())
|
||||
m = m.makeOptional();
|
||||
|
||||
RawTypeSet rts = new RawTypeSet(rtsb.getRefs(),m);
|
||||
|
||||
XSParticle p = findSourceParticle(cc);
|
||||
|
||||
BIProperty cust = BIProperty.getCustomization(p);
|
||||
CPropertyInfo prop = cust.createElementOrReferenceProperty(
|
||||
propName.toString(), false, p, rts );
|
||||
getCurrentBean().addProperty(prop);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a {@link XSParticle} that can serve as the representative property of
|
||||
* the given {@link ConnectedComponent}.
|
||||
*
|
||||
* The representative property is used for reporting an error location and
|
||||
* taking {@link BIProperty} customization. Right now, the algorithm is just pick
|
||||
* the first one with {@link BIProperty}, but one can think of a better algorithm,
|
||||
* such as taking a choice of (A|B) if CC={A,B}.
|
||||
*/
|
||||
private XSParticle findSourceParticle(ConnectedComponent cc) {
|
||||
XSParticle first = null;
|
||||
|
||||
for (Element e : cc) {
|
||||
GElement ge = (GElement)e;
|
||||
for (XSParticle p : ge.particles) {
|
||||
if(first==null)
|
||||
first = p;
|
||||
if(getLocalPropCustomization(p)!=null)
|
||||
return p;
|
||||
}
|
||||
// if there are multiple property customizations,
|
||||
// all but one will be left unused, which will be detected as an error
|
||||
// later, so no need to check that now.
|
||||
}
|
||||
|
||||
// if no customization was found, just use the first one.
|
||||
return first;
|
||||
}
|
||||
|
||||
public boolean checkFallback(XSParticle p) {
|
||||
// this algorithm never falls back to 'getContent'.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.sun.tools.internal.xjc.reader.gbind.Element;
|
||||
import com.sun.xml.internal.xsom.XSElementDecl;
|
||||
import com.sun.xml.internal.xsom.XSParticle;
|
||||
|
||||
/**
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
abstract class GElement extends Element {
|
||||
/**
|
||||
* All the {@link XSParticle}s (whose term is {@link XSElementDecl})
|
||||
* that are coereced into a single {@link Element}.
|
||||
*/
|
||||
final Set<XSParticle> particles = new HashSet<XSParticle>();
|
||||
|
||||
/**
|
||||
* Gets the seed (raw XML name) to be used to generate a property name.
|
||||
*/
|
||||
abstract String getPropertyNameSeed();
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import com.sun.tools.internal.xjc.reader.gbind.Element;
|
||||
import com.sun.xml.internal.xsom.XSElementDecl;
|
||||
|
||||
/**
|
||||
* {@link Element} that wraps {@link XSElementDecl}.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class GElementImpl extends GElement {
|
||||
public final QName tagName;
|
||||
|
||||
/**
|
||||
* The representative {@link XSElementDecl}.
|
||||
*
|
||||
* Even though multiple {@link XSElementDecl}s maybe represented by
|
||||
* a single {@link GElementImpl} (especially when they are local),
|
||||
* the schema spec requires that they share the same type and other
|
||||
* characteristic.
|
||||
*
|
||||
* (To be really precise, you may have different default values,
|
||||
* nillability, all that, so if that becomes a real issue we have
|
||||
* to reconsider this design.)
|
||||
*/
|
||||
public final XSElementDecl decl;
|
||||
|
||||
public GElementImpl(QName tagName, XSElementDecl decl) {
|
||||
this.tagName = tagName;
|
||||
this.decl = decl;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return tagName.toString();
|
||||
}
|
||||
|
||||
String getPropertyNameSeed() {
|
||||
return tagName.getLocalPart();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema;
|
||||
|
||||
import com.sun.tools.internal.xjc.reader.gbind.Element;
|
||||
import com.sun.xml.internal.xsom.XSWildcard;
|
||||
|
||||
/**
|
||||
* {@link Element} that represents a wildcard,
|
||||
* for the "ease of binding" we always just bind this to DOM elements.
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class GWildcardElement extends GElement {
|
||||
|
||||
/**
|
||||
* If true, bind to <tt>Object</tt> for eager JAXB unmarshalling.
|
||||
* Otherwise bind to DOM (I hate "you can put both" semantics,
|
||||
* so I'm not going to do that in this binding mode.)
|
||||
*/
|
||||
private boolean strict = true;
|
||||
|
||||
public String toString() {
|
||||
return "#any";
|
||||
}
|
||||
|
||||
String getPropertyNameSeed() {
|
||||
return "any";
|
||||
}
|
||||
|
||||
public void merge(XSWildcard wc) {
|
||||
switch(wc.getMode()) {
|
||||
case XSWildcard.LAX:
|
||||
case XSWildcard.SKIP:
|
||||
strict = false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isStrict() {
|
||||
return strict;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
/**
|
||||
* Formats error messages.
|
||||
*/
|
||||
public class Messages
|
||||
{
|
||||
/** Loads a string resource and formats it with specified arguments. */
|
||||
public static String format( String property, Object... args ) {
|
||||
String text = ResourceBundle.getBundle(Messages.class.getPackage().getName() +".MessageBundle").getString(property);
|
||||
return MessageFormat.format(text,args);
|
||||
}
|
||||
|
||||
|
||||
static final String WARN_NO_GLOBAL_ELEMENT =
|
||||
"BGMBuilder.NoGlobalElement";
|
||||
|
||||
public static final String WARN_UNUSED_EXPECTED_CONTENT_TYPES =
|
||||
"UnusedCustomizationChecker.WarnUnusedExpectedContentTypes";
|
||||
|
||||
static final String ERR_MULTIPLE_SCHEMA_BINDINGS =
|
||||
"BGMBuilder.MultipleSchemaBindings"; // arg:1
|
||||
|
||||
static final String ERR_MULTIPLE_SCHEMA_BINDINGS_LOCATION =
|
||||
"BGMBuilder.MultipleSchemaBindings.Location"; // arg:0
|
||||
|
||||
static final String JAVADOC_HEADING = // 1 arg
|
||||
"ClassSelector.JavadocHeading";
|
||||
|
||||
static final String ERR_RESERVED_CLASS_NAME = // 1 arg
|
||||
"ClassSelector.ReservedClassName";
|
||||
|
||||
static final String ERR_CLASS_NAME_IS_REQUIRED =
|
||||
"ClassSelector.ClassNameIsRequired"; // arg:0
|
||||
|
||||
static final String ERR_INCORRECT_CLASS_NAME =
|
||||
"ClassSelector.IncorrectClassName"; // arg:1
|
||||
|
||||
static final String ERR_INCORRECT_PACKAGE_NAME =
|
||||
"ClassSelector.IncorrectPackageName"; // arg:2
|
||||
|
||||
static final String ERR_CANNOT_BE_TYPE_SAFE_ENUM =
|
||||
"ConversionFinder.CannotBeTypeSafeEnum"; // arg:0
|
||||
|
||||
static final String ERR_CANNOT_BE_TYPE_SAFE_ENUM_LOCATION =
|
||||
"ConversionFinder.CannotBeTypeSafeEnum.Location"; // arg:0
|
||||
|
||||
static final String ERR_NO_ENUM_NAME_AVAILABLE =
|
||||
"ConversionFinder.NoEnumNameAvailable"; // arg:0
|
||||
|
||||
static final String ERR_NO_ENUM_FACET =
|
||||
"ConversionFinder.NoEnumFacet"; // arg:0
|
||||
|
||||
static final String ERR_ILLEGAL_EXPECTED_MIME_TYPE =
|
||||
"ERR_ILLEGAL_EXPECTED_MIME_TYPE"; // args:2
|
||||
|
||||
static final String ERR_DATATYPE_ERROR =
|
||||
"DatatypeBuilder.DatatypeError"; // arg:1
|
||||
|
||||
static final String ERR_UNABLE_TO_GENERATE_NAME_FROM_MODELGROUP =
|
||||
"DefaultParticleBinder.UnableToGenerateNameFromModelGroup"; // arg:0
|
||||
|
||||
static final String ERR_INCORRECT_FIXED_VALUE =
|
||||
"FieldBuilder.IncorrectFixedValue"; // arg:1
|
||||
|
||||
static final String ERR_INCORRECT_DEFAULT_VALUE =
|
||||
"FieldBuilder.IncorrectDefaultValue"; // arg:1
|
||||
|
||||
static final String ERR_CONFLICT_BETWEEN_USERTYPE_AND_ACTUALTYPE_ATTUSE =
|
||||
"FieldBuilder.ConflictBetweenUserTypeAndActualType.AttUse"; // arg:2
|
||||
|
||||
static final String ERR_CONFLICT_BETWEEN_USERTYPE_AND_ACTUALTYPE_ATTUSE_SOURCE =
|
||||
"FieldBuilder.ConflictBetweenUserTypeAndActualType.AttUse.Source"; // arg:0
|
||||
|
||||
static final String ERR_UNNESTED_JAVATYPE_CUSTOMIZATION_ON_SIMPLETYPE =
|
||||
"SimpleTypeBuilder.UnnestedJavaTypeCustomization"; // arg:0
|
||||
|
||||
static final String JAVADOC_NIL_PROPERTY =
|
||||
"FieldBuilder.Javadoc.NilProperty"; // arg:1
|
||||
|
||||
static final String JAVADOC_LINE_UNKNOWN = // 0 args
|
||||
"ClassSelector.JavadocLineUnknown";
|
||||
|
||||
static final String JAVADOC_VALUEOBJECT_PROPERTY =
|
||||
"FieldBuilder.Javadoc.ValueObject"; // args:2
|
||||
|
||||
static final String MSG_COLLISION_INFO =
|
||||
"CollisionInfo.CollisionInfo"; // args:3
|
||||
|
||||
static final String MSG_UNKNOWN_FILE =
|
||||
"CollisionInfo.UnknownFile"; // arg:1
|
||||
|
||||
static final String MSG_LINE_X_OF_Y =
|
||||
"CollisionInfo.LineXOfY"; // args:2
|
||||
|
||||
static final String MSG_FALLBACK_JAVADOC =
|
||||
"DefaultParticleBinder.FallbackJavadoc"; // arg:1
|
||||
|
||||
static final String ERR_ENUM_MEMBER_NAME_COLLISION =
|
||||
"ERR_ENUM_MEMBER_NAME_COLLISION";
|
||||
static final String ERR_ENUM_MEMBER_NAME_COLLISION_RELATED =
|
||||
"ERR_ENUM_MEMBER_NAME_COLLISION_RELATED";
|
||||
static final String ERR_CANNOT_GENERATE_ENUM_NAME =
|
||||
"ERR_CANNOT_GENERATE_ENUM_NAME";
|
||||
static final String WARN_ENUM_MEMBER_SIZE_CAP =
|
||||
"WARN_ENUM_MEMBER_SIZE_CAP"; // args: 3
|
||||
|
||||
|
||||
// they are shared from the model
|
||||
public static final String ERR_UNACKNOWLEDGED_CUSTOMIZATION =
|
||||
"UnusedCustomizationChecker.UnacknolwedgedCustomization"; // arg:1
|
||||
public static final String ERR_UNACKNOWLEDGED_CUSTOMIZATION_LOCATION =
|
||||
"UnusedCustomizationChecker.UnacknolwedgedCustomization.Relevant"; // arg:0
|
||||
|
||||
public static final String ERR_MULTIPLE_GLOBAL_BINDINGS =
|
||||
"ERR_MULTIPLE_GLOBAL_BINDINGS";
|
||||
public static final String ERR_MULTIPLE_GLOBAL_BINDINGS_OTHER =
|
||||
"ERR_MULTIPLE_GLOBAL_BINDINGS_OTHER";
|
||||
|
||||
public static final String ERR_REFERENCE_TO_NONEXPORTED_CLASS =
|
||||
"ERR_REFERENCE_TO_NONEXPORTED_CLASS";
|
||||
public static final String ERR_REFERENCE_TO_NONEXPORTED_CLASS_MAP_FALSE =
|
||||
"ERR_REFERENCE_TO_NONEXPORTED_CLASS_MAP_FALSE";
|
||||
public static final String ERR_REFERENCE_TO_NONEXPORTED_CLASS_REFERER =
|
||||
"ERR_REFERENCE_TO_NONEXPORTED_CLASS_REFERER";
|
||||
|
||||
static final String WARN_DEFAULT_VALUE_PRIMITIVE_TYPE =
|
||||
"WARN_DEFAULT_VALUE_PRIMITIVE_TYPE";
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import com.sun.tools.internal.xjc.model.Multiplicity;
|
||||
import com.sun.xml.internal.xsom.XSElementDecl;
|
||||
import com.sun.xml.internal.xsom.XSModelGroup;
|
||||
import com.sun.xml.internal.xsom.XSModelGroupDecl;
|
||||
import com.sun.xml.internal.xsom.XSParticle;
|
||||
import com.sun.xml.internal.xsom.XSWildcard;
|
||||
import com.sun.xml.internal.xsom.visitor.XSTermFunction;
|
||||
|
||||
import static com.sun.tools.internal.xjc.model.Multiplicity.ONE;
|
||||
import static com.sun.tools.internal.xjc.model.Multiplicity.ZERO;
|
||||
|
||||
/**
|
||||
* Counts {@link Multiplicity} for a particle/term.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public final class MultiplicityCounter implements XSTermFunction<Multiplicity> {
|
||||
|
||||
public static final MultiplicityCounter theInstance = new MultiplicityCounter();
|
||||
|
||||
private MultiplicityCounter() {}
|
||||
|
||||
public Multiplicity particle( XSParticle p ) {
|
||||
Multiplicity m = p.getTerm().apply(this);
|
||||
|
||||
BigInteger max;
|
||||
if (m.max==null || (BigInteger.valueOf(XSParticle.UNBOUNDED).equals(p.getMaxOccurs())))
|
||||
max=null;
|
||||
else
|
||||
max=p.getMaxOccurs();
|
||||
|
||||
return Multiplicity.multiply( m, Multiplicity.create(p.getMinOccurs(),max) );
|
||||
}
|
||||
|
||||
public Multiplicity wildcard(XSWildcard wc) {
|
||||
return ONE;
|
||||
}
|
||||
|
||||
public Multiplicity modelGroupDecl(XSModelGroupDecl decl) {
|
||||
return modelGroup(decl.getModelGroup());
|
||||
}
|
||||
|
||||
public Multiplicity modelGroup(XSModelGroup group) {
|
||||
boolean isChoice = group.getCompositor() == XSModelGroup.CHOICE;
|
||||
|
||||
Multiplicity r = ZERO;
|
||||
|
||||
for( XSParticle p : group.getChildren()) {
|
||||
Multiplicity m = particle(p);
|
||||
|
||||
if(r==null) {
|
||||
r=m;
|
||||
continue;
|
||||
}
|
||||
if(isChoice) {
|
||||
r = Multiplicity.choice(r,m);
|
||||
} else {
|
||||
r = Multiplicity.group(r,m);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
public Multiplicity elementDecl(XSElementDecl decl) {
|
||||
return ONE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import com.sun.codemodel.internal.JJavaName;
|
||||
import com.sun.tools.internal.xjc.model.CClassInfo;
|
||||
import com.sun.tools.internal.xjc.model.CPropertyInfo;
|
||||
import com.sun.tools.internal.xjc.reader.Ring;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIDeclaration;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIProperty;
|
||||
import com.sun.xml.internal.xsom.XSElementDecl;
|
||||
import com.sun.xml.internal.xsom.XSModelGroup;
|
||||
import com.sun.xml.internal.xsom.XSModelGroupDecl;
|
||||
import com.sun.xml.internal.xsom.XSParticle;
|
||||
import com.sun.xml.internal.xsom.XSTerm;
|
||||
import com.sun.xml.internal.xsom.XSWildcard;
|
||||
import com.sun.xml.internal.xsom.visitor.XSTermVisitor;
|
||||
|
||||
/**
|
||||
* Binds the content models of {@link XSParticle} as properties of the class that's being built.
|
||||
*
|
||||
* @author
|
||||
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
public abstract class ParticleBinder {
|
||||
|
||||
protected final BGMBuilder builder = Ring.get(BGMBuilder.class);
|
||||
|
||||
protected ParticleBinder() {
|
||||
// make sure that this object is available as ParticleBinder, not as their actual implementation classes
|
||||
Ring.add(ParticleBinder.class,this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the {@link CPropertyInfo}s from the given particle
|
||||
* (and its descendants), and set them to the class returned by
|
||||
* {@link ClassSelector#getCurrentBean()}.
|
||||
*/
|
||||
public final void build( XSParticle p ) {
|
||||
build(p, Collections.<XSParticle>emptySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* The version of the build method that forces a specified set of particles
|
||||
* to become a property.
|
||||
*/
|
||||
public abstract void build( XSParticle p, Collection<XSParticle> forcedProps );
|
||||
|
||||
/**
|
||||
* Similar to the build method but this method only checks if
|
||||
* the BGM that will be built by the build method will
|
||||
* do the fallback (map all the properties into one list) or not.
|
||||
*
|
||||
* @return
|
||||
* false if the fallback will not happen.
|
||||
*/
|
||||
public abstract boolean checkFallback( XSParticle p );
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
// convenient utility methods
|
||||
//
|
||||
//
|
||||
|
||||
protected final CClassInfo getCurrentBean() {
|
||||
return getClassSelector().getCurrentBean();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the BIProperty object that applies to the given particle.
|
||||
*/
|
||||
protected final BIProperty getLocalPropCustomization( XSParticle p ) {
|
||||
return getLocalCustomization(p,BIProperty.class);
|
||||
}
|
||||
|
||||
protected final <T extends BIDeclaration> T getLocalCustomization( XSParticle p, Class<T> type ) {
|
||||
// check the property customization of this component first
|
||||
T cust = builder.getBindInfo(p).get(type);
|
||||
if(cust!=null) return cust;
|
||||
|
||||
// if not, the term might have one.
|
||||
cust = builder.getBindInfo(p.getTerm()).get(type);
|
||||
if(cust!=null) return cust;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the label of a given particle.
|
||||
* Usually, the getLabel method should be used instead.
|
||||
*/
|
||||
protected final String computeLabel( XSParticle p ) {
|
||||
// if the particle carries a customization, use that value.
|
||||
// since we are binding content models, it's always non-constant properties.
|
||||
BIProperty cust = getLocalPropCustomization(p);
|
||||
if(cust!=null && cust.getPropertyName(false)!=null)
|
||||
return cust.getPropertyName(false);
|
||||
|
||||
// no explicit property name is given. Compute one.
|
||||
|
||||
XSTerm t = p.getTerm();
|
||||
|
||||
// // first, check if a term is going to be a class, if so, use that name.
|
||||
// ClassItem ci = owner.selector.select(t);
|
||||
// if(ci!=null) {
|
||||
// return makeJavaName(ci.getTypeAsDefined().name());
|
||||
// }
|
||||
|
||||
// if it fails, compute the default name according to the spec.
|
||||
if(t.isElementDecl())
|
||||
// for element, take the element name.
|
||||
return makeJavaName(p,t.asElementDecl().getName());
|
||||
if(t.isModelGroupDecl())
|
||||
// for named model groups, take that name
|
||||
return makeJavaName(p,t.asModelGroupDecl().getName());
|
||||
if(t.isWildcard())
|
||||
// the spec says it will map to "any" by default.
|
||||
return makeJavaName(p,"Any");
|
||||
if(t.isModelGroup()) {
|
||||
try {
|
||||
return getSpecDefaultName(t.asModelGroup(),p.isRepeated());
|
||||
} catch( ParseException e ) {
|
||||
// unable to generate a name.
|
||||
getErrorReporter().error(t.getLocator(),
|
||||
Messages.ERR_UNABLE_TO_GENERATE_NAME_FROM_MODELGROUP);
|
||||
return "undefined"; // recover from error by assuming something
|
||||
}
|
||||
}
|
||||
|
||||
// there are only four types of XSTerm.
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
/** Converts an XML name to the corresponding Java name. */
|
||||
protected final String makeJavaName( boolean isRepeated, String xmlName ) {
|
||||
String name = builder.getNameConverter().toPropertyName(xmlName);
|
||||
if(builder.getGlobalBinding().isSimpleMode() && isRepeated )
|
||||
name = JJavaName.getPluralForm(name);
|
||||
return name;
|
||||
}
|
||||
|
||||
protected final String makeJavaName( XSParticle p, String xmlName ) {
|
||||
return makeJavaName(p.isRepeated(),xmlName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a name from unnamed model group by following the spec.
|
||||
*
|
||||
* Taking first three elements and combine them.
|
||||
*
|
||||
* @param repeated
|
||||
* if the said model group is repeated more than once
|
||||
*
|
||||
* @exception ParseException
|
||||
* If the method cannot generate a name. For example, when
|
||||
* a model group doesn't contain any element reference/declaration
|
||||
* at all.
|
||||
*/
|
||||
protected final String getSpecDefaultName( XSModelGroup mg, final boolean repeated ) throws ParseException {
|
||||
|
||||
final StringBuilder name = new StringBuilder();
|
||||
|
||||
mg.visit(new XSTermVisitor() {
|
||||
/**
|
||||
* Count the number of tokens we combined.
|
||||
* We will concat up to 3.
|
||||
*/
|
||||
private int count=0;
|
||||
|
||||
/**
|
||||
* Is the current particple/term repeated?
|
||||
*/
|
||||
private boolean rep = repeated;
|
||||
|
||||
public void wildcard(XSWildcard wc) {
|
||||
append("any");
|
||||
}
|
||||
|
||||
public void modelGroupDecl(XSModelGroupDecl mgd) {
|
||||
modelGroup(mgd.getModelGroup());
|
||||
}
|
||||
|
||||
public void modelGroup(XSModelGroup mg) {
|
||||
String operator;
|
||||
if(mg.getCompositor()==XSModelGroup.CHOICE) operator = "Or";
|
||||
else operator = "And";
|
||||
|
||||
int size = mg.getSize();
|
||||
for( int i=0; i<size; i++ ) {
|
||||
XSParticle p = mg.getChild(i);
|
||||
boolean oldRep = rep;
|
||||
rep |= p.isRepeated();
|
||||
p.getTerm().visit(this);
|
||||
rep = oldRep;
|
||||
|
||||
if(count==3) return; // we have enough
|
||||
if(i!=size-1) name.append(operator);
|
||||
}
|
||||
}
|
||||
|
||||
public void elementDecl(XSElementDecl ed) {
|
||||
append(ed.getName());
|
||||
}
|
||||
|
||||
private void append(String token) {
|
||||
if( count<3 ) {
|
||||
name.append(makeJavaName(rep,token));
|
||||
count++;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if(name.length()==0) throw new ParseException("no element",-1);
|
||||
|
||||
return name.toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected final ErrorReporter getErrorReporter() {
|
||||
return Ring.get(ErrorReporter.class);
|
||||
}
|
||||
protected final ClassSelector getClassSelector() {
|
||||
return Ring.get(ClassSelector.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,379 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.activation.MimeType;
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import com.sun.tools.internal.xjc.model.CAdapter;
|
||||
import com.sun.tools.internal.xjc.model.CClass;
|
||||
import com.sun.tools.internal.xjc.model.CClassInfo;
|
||||
import com.sun.tools.internal.xjc.model.CCustomizations;
|
||||
import com.sun.tools.internal.xjc.model.CElement;
|
||||
import com.sun.tools.internal.xjc.model.CElementInfo;
|
||||
import com.sun.tools.internal.xjc.model.CElementPropertyInfo;
|
||||
import com.sun.tools.internal.xjc.model.CReferencePropertyInfo;
|
||||
import com.sun.tools.internal.xjc.model.CTypeRef;
|
||||
import com.sun.tools.internal.xjc.model.Model;
|
||||
import com.sun.tools.internal.xjc.model.Multiplicity;
|
||||
import com.sun.tools.internal.xjc.model.TypeUse;
|
||||
import com.sun.tools.internal.xjc.reader.RawTypeSet;
|
||||
import com.sun.tools.internal.xjc.reader.Ring;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIDom;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIGlobalBinding;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIXSubstitutable;
|
||||
import com.sun.xml.internal.bind.v2.model.core.ID;
|
||||
import com.sun.xml.internal.bind.v2.model.core.WildcardMode;
|
||||
import com.sun.xml.internal.xsom.XSElementDecl;
|
||||
import com.sun.xml.internal.xsom.XSModelGroup;
|
||||
import com.sun.xml.internal.xsom.XSModelGroupDecl;
|
||||
import com.sun.xml.internal.xsom.XSParticle;
|
||||
import com.sun.xml.internal.xsom.XSWildcard;
|
||||
import com.sun.xml.internal.xsom.visitor.XSTermVisitor;
|
||||
|
||||
/**
|
||||
* Builds {@link RawTypeSet} for XML Schema.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public class RawTypeSetBuilder implements XSTermVisitor {
|
||||
/**
|
||||
* @param optional
|
||||
* if this whole property is optional due to the
|
||||
* occurrence constraints on ancestors, set this to true.
|
||||
* this will prevent the primitive types to be generated.
|
||||
*/
|
||||
public static RawTypeSet build( XSParticle p, boolean optional ) {
|
||||
RawTypeSetBuilder rtsb = new RawTypeSetBuilder();
|
||||
rtsb.particle(p);
|
||||
Multiplicity mul = MultiplicityCounter.theInstance.particle(p);
|
||||
|
||||
if(optional)
|
||||
mul = mul.makeOptional();
|
||||
|
||||
return new RawTypeSet(rtsb.refs,mul);
|
||||
}
|
||||
|
||||
/**
|
||||
* To avoid declaring the same element twice for a content model like
|
||||
* (A,A), we keep track of element names here while we are building up
|
||||
* this instance.
|
||||
*/
|
||||
private final Set<QName> elementNames = new LinkedHashSet<QName>();
|
||||
|
||||
private final Set<RawTypeSet.Ref> refs = new LinkedHashSet<RawTypeSet.Ref>();
|
||||
|
||||
protected final BGMBuilder builder = Ring.get(BGMBuilder.class);
|
||||
|
||||
public RawTypeSetBuilder() {}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the {@link RawTypeSet.Ref}s that were built.
|
||||
*/
|
||||
public Set<RawTypeSet.Ref> getRefs() {
|
||||
return refs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build up {@link #refs} and compute the total multiplicity of this {@link RawTypeSet.Ref} set.
|
||||
*/
|
||||
private void particle( XSParticle p ) {
|
||||
// if the DOM customization is present, bind it like a wildcard
|
||||
BIDom dom = builder.getLocalDomCustomization(p);
|
||||
if(dom!=null) {
|
||||
dom.markAsAcknowledged();
|
||||
refs.add(new WildcardRef(WildcardMode.SKIP));
|
||||
} else {
|
||||
p.getTerm().visit(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void wildcard(XSWildcard wc) {
|
||||
refs.add(new WildcardRef(wc));
|
||||
}
|
||||
|
||||
public void modelGroupDecl(XSModelGroupDecl decl) {
|
||||
modelGroup(decl.getModelGroup());
|
||||
}
|
||||
|
||||
public void modelGroup(XSModelGroup group) {
|
||||
for( XSParticle p : group.getChildren())
|
||||
particle(p);
|
||||
}
|
||||
|
||||
public void elementDecl(XSElementDecl decl) {
|
||||
|
||||
QName n = BGMBuilder.getName(decl);
|
||||
if(elementNames.add(n)) {
|
||||
CElement elementBean = Ring.get(ClassSelector.class).bindToType(decl,null);
|
||||
if(elementBean==null)
|
||||
refs.add(new XmlTypeRef(decl));
|
||||
else {
|
||||
// yikes!
|
||||
if(elementBean instanceof CClass)
|
||||
refs.add(new CClassRef(decl,(CClass)elementBean));
|
||||
else
|
||||
refs.add(new CElementInfoRef(decl,(CElementInfo)elementBean));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reference to a wildcard.
|
||||
*/
|
||||
public static final class WildcardRef extends RawTypeSet.Ref {
|
||||
private final WildcardMode mode;
|
||||
|
||||
WildcardRef(XSWildcard wildcard) {
|
||||
this.mode = getMode(wildcard);
|
||||
}
|
||||
WildcardRef(WildcardMode mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
private static WildcardMode getMode(XSWildcard wildcard) {
|
||||
switch(wildcard.getMode()) {
|
||||
case XSWildcard.LAX:
|
||||
return WildcardMode.LAX;
|
||||
case XSWildcard.STRTICT:
|
||||
return WildcardMode.STRICT;
|
||||
case XSWildcard.SKIP:
|
||||
return WildcardMode.SKIP;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
protected CTypeRef toTypeRef(CElementPropertyInfo ep) {
|
||||
// we don't allow a mapping to typeRef if the wildcard is present
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
protected void toElementRef(CReferencePropertyInfo prop) {
|
||||
prop.setWildcard(mode);
|
||||
}
|
||||
|
||||
protected RawTypeSet.Mode canBeType(RawTypeSet parent) {
|
||||
return RawTypeSet.Mode.MUST_BE_REFERENCE;
|
||||
}
|
||||
|
||||
protected boolean isListOfValues() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected ID id() {
|
||||
return ID.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reference to a class that maps from an element.
|
||||
*/
|
||||
public static final class CClassRef extends RawTypeSet.Ref {
|
||||
public final CClass target;
|
||||
public final XSElementDecl decl;
|
||||
|
||||
CClassRef(XSElementDecl decl, CClass target) {
|
||||
this.decl = decl;
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
protected CTypeRef toTypeRef(CElementPropertyInfo ep) {
|
||||
return new CTypeRef(target,decl);
|
||||
}
|
||||
|
||||
protected void toElementRef(CReferencePropertyInfo prop) {
|
||||
prop.getElements().add(target);
|
||||
}
|
||||
|
||||
protected RawTypeSet.Mode canBeType(RawTypeSet parent) {
|
||||
// if element substitution can occur, no way it can be mapped to a list of types
|
||||
if(decl.getSubstitutables().size()>1)
|
||||
return RawTypeSet.Mode.MUST_BE_REFERENCE;
|
||||
|
||||
return RawTypeSet.Mode.SHOULD_BE_TYPEREF;
|
||||
}
|
||||
|
||||
protected boolean isListOfValues() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected ID id() {
|
||||
return ID.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reference to a class that maps from an element.
|
||||
*/
|
||||
public final class CElementInfoRef extends RawTypeSet.Ref {
|
||||
public final CElementInfo target;
|
||||
public final XSElementDecl decl;
|
||||
|
||||
CElementInfoRef(XSElementDecl decl, CElementInfo target) {
|
||||
this.decl = decl;
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
protected CTypeRef toTypeRef(CElementPropertyInfo ep) {
|
||||
assert !target.isCollection();
|
||||
CAdapter a = target.getProperty().getAdapter();
|
||||
if(a!=null && ep!=null) ep.setAdapter(a);
|
||||
|
||||
return new CTypeRef(target.getContentType(),decl);
|
||||
}
|
||||
|
||||
protected void toElementRef(CReferencePropertyInfo prop) {
|
||||
prop.getElements().add(target);
|
||||
}
|
||||
|
||||
protected RawTypeSet.Mode canBeType(RawTypeSet parent) {
|
||||
// if element substitution can occur, no way it can be mapped to a list of types
|
||||
if(decl.getSubstitutables().size()>1)
|
||||
return RawTypeSet.Mode.MUST_BE_REFERENCE;
|
||||
// BIXSubstitutable also simulates this effect. Useful for separate compilation
|
||||
BIXSubstitutable subst = builder.getBindInfo(decl).get(BIXSubstitutable.class);
|
||||
if(subst!=null) {
|
||||
subst.markAsAcknowledged();
|
||||
return RawTypeSet.Mode.MUST_BE_REFERENCE;
|
||||
}
|
||||
|
||||
// we have no place to put an adater if this thing maps to a type
|
||||
CElementPropertyInfo p = target.getProperty();
|
||||
// if we have an adapter or IDness, which requires special
|
||||
// annotation, and there's more than one element,
|
||||
// we have no place to put the special annotation, so we need JAXBElement.
|
||||
if((parent.refs.size()>1 || !parent.mul.isAtMostOnce()) && p.id()!=ID.NONE)
|
||||
return RawTypeSet.Mode.MUST_BE_REFERENCE;
|
||||
if(parent.refs.size() > 1 && p.getAdapter() != null)
|
||||
return RawTypeSet.Mode.MUST_BE_REFERENCE;
|
||||
|
||||
if(target.hasClass())
|
||||
// if the CElementInfo was explicitly bound to a class (which happen if and only if
|
||||
// the user requested so, then map that to reference property so that the user sees a class
|
||||
return RawTypeSet.Mode.CAN_BE_TYPEREF;
|
||||
else
|
||||
return RawTypeSet.Mode.SHOULD_BE_TYPEREF;
|
||||
}
|
||||
|
||||
protected boolean isListOfValues() {
|
||||
return target.getProperty().isValueList();
|
||||
}
|
||||
|
||||
protected ID id() {
|
||||
return target.getProperty().id();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MimeType getExpectedMimeType() {
|
||||
return target.getProperty().getExpectedMimeType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* References to a type. Could be global or local.
|
||||
*/
|
||||
public static final class XmlTypeRef extends RawTypeSet.Ref {
|
||||
private final XSElementDecl decl;
|
||||
private final TypeUse target;
|
||||
|
||||
public XmlTypeRef(XSElementDecl decl) {
|
||||
this.decl = decl;
|
||||
SimpleTypeBuilder stb = Ring.get(SimpleTypeBuilder.class);
|
||||
stb.refererStack.push(decl);
|
||||
TypeUse r = Ring.get(ClassSelector.class).bindToType(decl.getType(),decl);
|
||||
stb.refererStack.pop();
|
||||
target = r;
|
||||
}
|
||||
|
||||
protected CTypeRef toTypeRef(CElementPropertyInfo ep) {
|
||||
if(ep!=null && target.getAdapterUse()!=null)
|
||||
ep.setAdapter(target.getAdapterUse());
|
||||
return new CTypeRef(target.getInfo(),decl);
|
||||
}
|
||||
|
||||
/**
|
||||
* The whole type set can be later bound to a reference property,
|
||||
* in which case we need to generate additional code to wrap this
|
||||
* type reference into an element class.
|
||||
*
|
||||
* This method generates such an element class and returns it.
|
||||
*/
|
||||
protected void toElementRef(CReferencePropertyInfo prop) {
|
||||
CClassInfo scope = Ring.get(ClassSelector.class).getCurrentBean();
|
||||
Model model = Ring.get(Model.class);
|
||||
|
||||
CCustomizations custs = Ring.get(BGMBuilder.class).getBindInfo(decl).toCustomizationList();
|
||||
|
||||
if(target instanceof CClassInfo && Ring.get(BIGlobalBinding.class).isSimpleMode()) {
|
||||
CClassInfo bean = new CClassInfo(model,scope,
|
||||
model.getNameConverter().toClassName(decl.getName()),
|
||||
decl.getLocator(), null, BGMBuilder.getName(decl), decl,
|
||||
custs);
|
||||
bean.setBaseClass((CClassInfo)target);
|
||||
prop.getElements().add(bean);
|
||||
} else {
|
||||
CElementInfo e = new CElementInfo(model,BGMBuilder.getName(decl),scope,target,
|
||||
decl.getDefaultValue(), decl, custs, decl.getLocator());
|
||||
prop.getElements().add(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected RawTypeSet.Mode canBeType(RawTypeSet parent) {
|
||||
// if we have an adapter or IDness, which requires special
|
||||
// annotation, and there's more than one element,
|
||||
// we have no place to put the special annotation, so we need JAXBElement.
|
||||
if((parent.refs.size()>1 || !parent.mul.isAtMostOnce()) && target.idUse()!=ID.NONE)
|
||||
return RawTypeSet.Mode.MUST_BE_REFERENCE;
|
||||
if(parent.refs.size() > 1 && target.getAdapterUse() != null)
|
||||
return RawTypeSet.Mode.MUST_BE_REFERENCE;
|
||||
|
||||
// nillable and optional at the same time. needs an element wrapper to distinguish those
|
||||
// two states. But this is not a hard requirement.
|
||||
if(decl.isNillable() && parent.mul.isOptional())
|
||||
return RawTypeSet.Mode.CAN_BE_TYPEREF;
|
||||
|
||||
return RawTypeSet.Mode.SHOULD_BE_TYPEREF;
|
||||
}
|
||||
|
||||
protected boolean isListOfValues() {
|
||||
return target.isCollection();
|
||||
}
|
||||
|
||||
protected ID id() {
|
||||
return target.idUse();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MimeType getExpectedMimeType() {
|
||||
return target.getExpectedMimeType();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Collections;
|
||||
|
||||
import com.sun.xml.internal.xsom.XSAnnotation;
|
||||
import com.sun.xml.internal.xsom.XSAttGroupDecl;
|
||||
import com.sun.xml.internal.xsom.XSAttributeDecl;
|
||||
import com.sun.xml.internal.xsom.XSAttributeUse;
|
||||
import com.sun.xml.internal.xsom.XSComplexType;
|
||||
import com.sun.xml.internal.xsom.XSComponent;
|
||||
import com.sun.xml.internal.xsom.XSContentType;
|
||||
import com.sun.xml.internal.xsom.XSElementDecl;
|
||||
import com.sun.xml.internal.xsom.XSFacet;
|
||||
import com.sun.xml.internal.xsom.XSIdentityConstraint;
|
||||
import com.sun.xml.internal.xsom.XSModelGroup;
|
||||
import com.sun.xml.internal.xsom.XSModelGroupDecl;
|
||||
import com.sun.xml.internal.xsom.XSNotation;
|
||||
import com.sun.xml.internal.xsom.XSParticle;
|
||||
import com.sun.xml.internal.xsom.XSSchema;
|
||||
import com.sun.xml.internal.xsom.XSSchemaSet;
|
||||
import com.sun.xml.internal.xsom.XSSimpleType;
|
||||
import com.sun.xml.internal.xsom.XSType;
|
||||
import com.sun.xml.internal.xsom.XSWildcard;
|
||||
import com.sun.xml.internal.xsom.XSXPath;
|
||||
import com.sun.xml.internal.xsom.visitor.XSVisitor;
|
||||
|
||||
/**
|
||||
* Finds which {@link XSComponent}s refer to which {@link XSComplexType}s.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
final class RefererFinder implements XSVisitor {
|
||||
private final Set<Object> visited = new HashSet<Object>();
|
||||
|
||||
private final Map<XSComponent,Set<XSComponent>> referers = new HashMap<XSComponent,Set<XSComponent>>();
|
||||
|
||||
public Set<XSComponent> getReferer(XSComponent src) {
|
||||
Set<XSComponent> r = referers.get(src);
|
||||
if(r==null) return Collections.emptySet();
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
public void schemaSet(XSSchemaSet xss) {
|
||||
if(!visited.add(xss)) return;
|
||||
|
||||
for (XSSchema xs : xss.getSchemas()) {
|
||||
schema(xs);
|
||||
}
|
||||
}
|
||||
|
||||
public void schema(XSSchema xs) {
|
||||
if(!visited.add(xs)) return;
|
||||
|
||||
for (XSComplexType ct : xs.getComplexTypes().values()) {
|
||||
complexType(ct);
|
||||
}
|
||||
|
||||
for (XSElementDecl e : xs.getElementDecls().values()) {
|
||||
elementDecl(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void elementDecl(XSElementDecl e) {
|
||||
if(!visited.add(e)) return;
|
||||
|
||||
refer(e,e.getType());
|
||||
e.getType().visit(this);
|
||||
}
|
||||
|
||||
public void complexType(XSComplexType ct) {
|
||||
if(!visited.add(ct)) return;
|
||||
|
||||
refer(ct,ct.getBaseType());
|
||||
ct.getBaseType().visit(this);
|
||||
ct.getContentType().visit(this);
|
||||
}
|
||||
|
||||
public void modelGroupDecl(XSModelGroupDecl decl) {
|
||||
if(!visited.add(decl)) return;
|
||||
|
||||
modelGroup(decl.getModelGroup());
|
||||
}
|
||||
|
||||
public void modelGroup(XSModelGroup group) {
|
||||
if(!visited.add(group)) return;
|
||||
|
||||
for (XSParticle p : group.getChildren()) {
|
||||
particle(p);
|
||||
}
|
||||
}
|
||||
|
||||
public void particle(XSParticle particle) {
|
||||
// since the particle method is side-effect free, no need to check for double-visit.
|
||||
particle.getTerm().visit(this);
|
||||
}
|
||||
|
||||
|
||||
// things we don't care
|
||||
public void simpleType(XSSimpleType simpleType) {}
|
||||
public void annotation(XSAnnotation ann) {}
|
||||
public void attGroupDecl(XSAttGroupDecl decl) {}
|
||||
public void attributeDecl(XSAttributeDecl decl) {}
|
||||
public void attributeUse(XSAttributeUse use) {}
|
||||
public void facet(XSFacet facet) {}
|
||||
public void notation(XSNotation notation) {}
|
||||
public void identityConstraint(XSIdentityConstraint decl) {}
|
||||
public void xpath(XSXPath xp) {}
|
||||
public void wildcard(XSWildcard wc) {}
|
||||
public void empty(XSContentType empty) {}
|
||||
|
||||
/**
|
||||
* Called for each reference to record the fact.
|
||||
*
|
||||
* So far we only care about references to types.
|
||||
*/
|
||||
private void refer(XSComponent source, XSType target) {
|
||||
Set<XSComponent> r = referers.get(target);
|
||||
if(r==null) {
|
||||
r = new HashSet<XSComponent>();
|
||||
referers.put(target,r);
|
||||
}
|
||||
r.add(source);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,918 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema;
|
||||
|
||||
import java.io.StringWriter;
|
||||
import java.math.BigInteger;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
|
||||
import javax.activation.MimeTypeParseException;
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
|
||||
import com.sun.codemodel.internal.JJavaName;
|
||||
import com.sun.codemodel.internal.util.JavadocEscapeWriter;
|
||||
import com.sun.xml.internal.bind.v2.WellKnownNamespace;
|
||||
import com.sun.tools.internal.xjc.ErrorReceiver;
|
||||
import com.sun.tools.internal.xjc.model.CBuiltinLeafInfo;
|
||||
import com.sun.tools.internal.xjc.model.CClassInfo;
|
||||
import com.sun.tools.internal.xjc.model.CClassInfoParent;
|
||||
import com.sun.tools.internal.xjc.model.CClassRef;
|
||||
import com.sun.tools.internal.xjc.model.CEnumConstant;
|
||||
import com.sun.tools.internal.xjc.model.CEnumLeafInfo;
|
||||
import com.sun.tools.internal.xjc.model.CNonElement;
|
||||
import com.sun.tools.internal.xjc.model.Model;
|
||||
import com.sun.tools.internal.xjc.model.TypeUse;
|
||||
import com.sun.tools.internal.xjc.model.TypeUseFactory;
|
||||
import com.sun.tools.internal.xjc.reader.Const;
|
||||
import com.sun.tools.internal.xjc.reader.Ring;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIConversion;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIEnum;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIEnumMember;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIProperty;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BindInfo;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.EnumMemberMode;
|
||||
import com.sun.tools.internal.xjc.util.MimeTypeRange;
|
||||
|
||||
import static com.sun.xml.internal.bind.v2.WellKnownNamespace.XML_MIME_URI;
|
||||
|
||||
import com.sun.xml.internal.bind.v2.runtime.SwaRefAdapterMarker;
|
||||
import com.sun.xml.internal.xsom.XSAttributeDecl;
|
||||
import com.sun.xml.internal.xsom.XSComplexType;
|
||||
import com.sun.xml.internal.xsom.XSComponent;
|
||||
import com.sun.xml.internal.xsom.XSElementDecl;
|
||||
import com.sun.xml.internal.xsom.XSFacet;
|
||||
import com.sun.xml.internal.xsom.XSListSimpleType;
|
||||
import com.sun.xml.internal.xsom.XSRestrictionSimpleType;
|
||||
import com.sun.xml.internal.xsom.XSSimpleType;
|
||||
import com.sun.xml.internal.xsom.XSUnionSimpleType;
|
||||
import com.sun.xml.internal.xsom.XSVariety;
|
||||
import com.sun.xml.internal.xsom.impl.util.SchemaWriter;
|
||||
import com.sun.xml.internal.xsom.visitor.XSSimpleTypeFunction;
|
||||
import com.sun.xml.internal.xsom.visitor.XSVisitor;
|
||||
|
||||
import org.xml.sax.Locator;
|
||||
|
||||
/**
|
||||
* Builds {@link TypeUse} from simple types.
|
||||
*
|
||||
* <p>
|
||||
* This code consists of two main portions. The {@link #compose(XSSimpleType)} method
|
||||
* and {@link #composer} forms an outer cycle, which gradually ascends the type
|
||||
* inheritance chain until it finds the suitable binding. When it does this
|
||||
* {@link #initiatingType} is set to the type which started binding, so that we can refer
|
||||
* to the actual constraint facets and such that are applicable on the type.
|
||||
*
|
||||
* <p>
|
||||
* For each intermediate type in the chain, the {@link #find(XSSimpleType)} method
|
||||
* is used to find the binding on that type, sine the outer loop is doing the ascending,
|
||||
* this method only sees if the current type has some binding available.
|
||||
*
|
||||
* <p>
|
||||
* There is at least one ugly code that you need to aware of
|
||||
* when you are modifying the code. See the documentation
|
||||
* about <a href="package.html#stref_cust">
|
||||
* "simple type customization at the point of reference."</a>
|
||||
*
|
||||
*
|
||||
* @author
|
||||
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
public final class SimpleTypeBuilder extends BindingComponent {
|
||||
|
||||
protected final BGMBuilder builder = Ring.get(BGMBuilder.class);
|
||||
|
||||
private final Model model = Ring.get(Model.class);
|
||||
|
||||
/**
|
||||
* The component that is refering to the simple type
|
||||
* which we are building. This is ugly but necessary
|
||||
* to support the customization of simple types at
|
||||
* its point of reference. See my comment at the header
|
||||
* of this class for details.
|
||||
*
|
||||
* UGLY: Implemented as a Stack of XSComponent to fix a bug
|
||||
*/
|
||||
public final Stack<XSComponent> refererStack = new Stack<XSComponent>();
|
||||
|
||||
/**
|
||||
* Records what xmime:expectedContentTypes annotations we honored and processed,
|
||||
* so that we can later check if the user had these annotations in the places
|
||||
* where we didn't anticipate them.
|
||||
*/
|
||||
private final Set<XSComponent> acknowledgedXmimeContentTypes = new HashSet<XSComponent>();
|
||||
|
||||
/**
|
||||
* The type that was originally passed to this {@link SimpleTypeBuilder#build(XSSimpleType)}.
|
||||
* Never null.
|
||||
*/
|
||||
private XSSimpleType initiatingType;
|
||||
|
||||
/** {@link TypeUse}s for the built-in types. Read-only. */
|
||||
public static final Map<String,TypeUse> builtinConversions = new HashMap<String,TypeUse>();
|
||||
|
||||
|
||||
/**
|
||||
* Entry point from outside. Builds a BGM type expression
|
||||
* from a simple type schema component.
|
||||
*
|
||||
* @param type
|
||||
* the simple type to be bound.
|
||||
*/
|
||||
public TypeUse build( XSSimpleType type ) {
|
||||
XSSimpleType oldi = initiatingType;
|
||||
this.initiatingType = type;
|
||||
|
||||
TypeUse e = checkRefererCustomization(type);
|
||||
if(e==null)
|
||||
e = compose(type);
|
||||
|
||||
initiatingType = oldi;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
/**
|
||||
* A version of the {@link #build(XSSimpleType)} method
|
||||
* used to bind the definition of a class generated from
|
||||
* the given simple type.
|
||||
*/
|
||||
public TypeUse buildDef( XSSimpleType type ) {
|
||||
XSSimpleType oldi = initiatingType;
|
||||
this.initiatingType = type;
|
||||
|
||||
TypeUse e = type.apply(composer);
|
||||
|
||||
initiatingType = oldi;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a javaType customization specified to the referer, if present.
|
||||
* @return can be null.
|
||||
*/
|
||||
private BIConversion getRefererCustomization() {
|
||||
BindInfo info = builder.getBindInfo(getReferer());
|
||||
BIProperty prop = info.get(BIProperty.class);
|
||||
if(prop==null) return null;
|
||||
return prop.getConv();
|
||||
}
|
||||
|
||||
public XSComponent getReferer() {
|
||||
return refererStack.peek();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the referer has a conversion customization or not.
|
||||
* If it does, use it to bind this simple type. Otherwise
|
||||
* return null;
|
||||
*/
|
||||
private TypeUse checkRefererCustomization( XSSimpleType type ) {
|
||||
|
||||
// assertion check. referer must be set properly
|
||||
// before the build method is called.
|
||||
// since the handling of the simple type point-of-reference
|
||||
// customization is very error prone, it deserves a strict
|
||||
// assertion check.
|
||||
// UGLY CODE WARNING
|
||||
XSComponent top = getReferer();
|
||||
|
||||
if( top instanceof XSElementDecl ) {
|
||||
// if the parent is element type, its content type must be us.
|
||||
XSElementDecl eref = (XSElementDecl)top;
|
||||
assert eref.getType()==type;
|
||||
|
||||
// for elements, you can't use <property>,
|
||||
// so we allow javaType to appear directly.
|
||||
BindInfo info = builder.getBindInfo(top);
|
||||
BIConversion conv = info.get(BIConversion.class);
|
||||
if(conv!=null) {
|
||||
conv.markAsAcknowledged();
|
||||
// the conversion is given.
|
||||
return conv.getTypeUse(type);
|
||||
}
|
||||
detectJavaTypeCustomization();
|
||||
} else
|
||||
if( top instanceof XSAttributeDecl ) {
|
||||
XSAttributeDecl aref = (XSAttributeDecl)top;
|
||||
assert aref.getType()==type;
|
||||
detectJavaTypeCustomization();
|
||||
} else
|
||||
if( top instanceof XSComplexType ) {
|
||||
XSComplexType tref = (XSComplexType)top;
|
||||
assert tref.getBaseType()==type || tref.getContentType()==type;
|
||||
detectJavaTypeCustomization();
|
||||
} else
|
||||
if( top == type ) {
|
||||
// this means the simple type is built by itself and
|
||||
// not because it's referenced by something.
|
||||
} else
|
||||
// unexpected referer type.
|
||||
assert false;
|
||||
|
||||
// now we are certain that the referer is OK.
|
||||
// see if it has a conversion customization.
|
||||
BIConversion conv = getRefererCustomization();
|
||||
if(conv!=null) {
|
||||
conv.markAsAcknowledged();
|
||||
// the conversion is given.
|
||||
return conv.getTypeUse(type);
|
||||
} else
|
||||
// not found
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect "javaType" customizations placed directly on simple types, rather
|
||||
* than being enclosed by "property" and "baseType" customizations (see
|
||||
* sec 6.8.1 of the spec).
|
||||
*
|
||||
* Report an error if any exist.
|
||||
*/
|
||||
private void detectJavaTypeCustomization() {
|
||||
BindInfo info = builder.getBindInfo(getReferer());
|
||||
BIConversion conv = info.get(BIConversion.class);
|
||||
|
||||
if( conv != null ) {
|
||||
// ack this conversion to prevent further error messages
|
||||
conv.markAsAcknowledged();
|
||||
|
||||
// report the error
|
||||
getErrorReporter().error( conv.getLocation(),
|
||||
Messages.ERR_UNNESTED_JAVATYPE_CUSTOMIZATION_ON_SIMPLETYPE );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively decend the type inheritance chain to find a binding.
|
||||
*/
|
||||
TypeUse compose( XSSimpleType t ) {
|
||||
TypeUse e = find(t);
|
||||
if(e!=null) return e;
|
||||
return t.apply(composer);
|
||||
}
|
||||
|
||||
public final XSSimpleTypeFunction<TypeUse> composer = new XSSimpleTypeFunction<TypeUse>() {
|
||||
|
||||
public TypeUse listSimpleType(XSListSimpleType type) {
|
||||
// bind item type individually and then compose them into a list
|
||||
// facets on the list shouldn't be taken account when binding item types,
|
||||
// so weed to call build(), not compose().
|
||||
XSSimpleType itemType = type.getItemType();
|
||||
refererStack.push(itemType);
|
||||
TypeUse tu = TypeUseFactory.makeCollection(build(type.getItemType()));
|
||||
refererStack.pop();
|
||||
return tu;
|
||||
}
|
||||
|
||||
public TypeUse unionSimpleType(XSUnionSimpleType type) {
|
||||
boolean isCollection = false;
|
||||
for( int i=0; i<type.getMemberSize(); i++ )
|
||||
if(type.getMember(i).getVariety()==XSVariety.LIST || type.getMember(i).getVariety()==XSVariety.UNION) {
|
||||
isCollection = true;
|
||||
break;
|
||||
}
|
||||
|
||||
TypeUse r = CBuiltinLeafInfo.STRING;
|
||||
if(isCollection)
|
||||
r = TypeUseFactory.makeCollection(r);
|
||||
return r;
|
||||
}
|
||||
|
||||
public TypeUse restrictionSimpleType(XSRestrictionSimpleType type) {
|
||||
// just process the base type.
|
||||
return compose(type.getSimpleBaseType());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if there's any binding available on the given type.
|
||||
*
|
||||
* @return
|
||||
* null if not (which causes the {@link #compose(XSSimpleType)} method
|
||||
* to do ascending.
|
||||
*/
|
||||
private TypeUse find( XSSimpleType type ) {
|
||||
TypeUse r;
|
||||
boolean noAutoEnum = false;
|
||||
|
||||
// check for user specified conversion
|
||||
BindInfo info = builder.getBindInfo(type);
|
||||
BIConversion conv = info.get(BIConversion.class);
|
||||
|
||||
if( conv!=null ) {
|
||||
// a conversion was found
|
||||
conv.markAsAcknowledged();
|
||||
return conv.getTypeUse(type);
|
||||
}
|
||||
|
||||
// look for enum customization, which is another user specified conversion
|
||||
BIEnum en = info.get(BIEnum.class);
|
||||
if( en!=null ) {
|
||||
en.markAsAcknowledged();
|
||||
|
||||
if(!en.isMapped()) {
|
||||
noAutoEnum = true;
|
||||
} else {
|
||||
// if an enum customization is specified, make sure
|
||||
// the type is OK
|
||||
if( !canBeMappedToTypeSafeEnum(type) ) {
|
||||
getErrorReporter().error( en.getLocation(),
|
||||
Messages.ERR_CANNOT_BE_TYPE_SAFE_ENUM );
|
||||
getErrorReporter().error( type.getLocator(),
|
||||
Messages.ERR_CANNOT_BE_TYPE_SAFE_ENUM_LOCATION );
|
||||
// recover by ignoring this customization
|
||||
return null;
|
||||
}
|
||||
|
||||
// reference?
|
||||
if(en.ref!=null) {
|
||||
if(!JJavaName.isFullyQualifiedClassName(en.ref)) {
|
||||
Ring.get(ErrorReceiver.class).error( en.getLocation(),
|
||||
Messages.format(Messages.ERR_INCORRECT_CLASS_NAME, en.ref) );
|
||||
// recover by ignoring @ref
|
||||
return null;
|
||||
}
|
||||
|
||||
return new CClassRef(model, type, en, info.toCustomizationList() );
|
||||
}
|
||||
|
||||
// list and union cannot be mapped to a type-safe enum,
|
||||
// so in this stage we can safely cast it to XSRestrictionSimpleType
|
||||
return bindToTypeSafeEnum( (XSRestrictionSimpleType)type,
|
||||
en.className, en.javadoc, en.members,
|
||||
getEnumMemberMode().getModeWithEnum(),
|
||||
en.getLocation() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// if the type is built in, look for the default binding
|
||||
if(type.getTargetNamespace().equals(WellKnownNamespace.XML_SCHEMA)) {
|
||||
String name = type.getName();
|
||||
if(name!=null) {
|
||||
r = lookupBuiltin(name);
|
||||
if(r!=null)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
// also check for swaRef
|
||||
if(type.getTargetNamespace().equals(WellKnownNamespace.SWA_URI)) {
|
||||
String name = type.getName();
|
||||
if(name!=null && name.equals("swaRef"))
|
||||
return CBuiltinLeafInfo.STRING.makeAdapted(SwaRefAdapterMarker.class,false);
|
||||
}
|
||||
|
||||
|
||||
// see if this type should be mapped to a type-safe enumeration by default.
|
||||
// if so, built a EnumXDucer from it and return it.
|
||||
if(type.isRestriction() && !noAutoEnum) {
|
||||
XSRestrictionSimpleType rst = type.asRestriction();
|
||||
if(shouldBeMappedToTypeSafeEnumByDefault(rst)) {
|
||||
r = bindToTypeSafeEnum(rst,null,null, Collections.<String, BIEnumMember>emptyMap(),
|
||||
getEnumMemberMode(),null);
|
||||
if(r!=null)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
return (CNonElement)getClassSelector()._bindToClass(type,null,false);
|
||||
}
|
||||
|
||||
private static Set<XSRestrictionSimpleType> reportedEnumMemberSizeWarnings;
|
||||
|
||||
/**
|
||||
* Returns true if a type-safe enum should be created from
|
||||
* the given simple type by default without an explicit <jaxb:enum> customization.
|
||||
*/
|
||||
private boolean shouldBeMappedToTypeSafeEnumByDefault( XSRestrictionSimpleType type ) {
|
||||
|
||||
// if not, there will be a problem wrt the class name of this type safe enum type.
|
||||
if( type.isLocal() ) return false;
|
||||
|
||||
// if redefined, we should map the new definition, not the old one.
|
||||
if( type.getRedefinedBy()!=null ) return false;
|
||||
|
||||
List<XSFacet> facets = type.getDeclaredFacets(XSFacet.FACET_ENUMERATION);
|
||||
if( facets.isEmpty() )
|
||||
// if the type itself doesn't have the enumeration facet,
|
||||
// it won't be mapped to a type-safe enum.
|
||||
return false;
|
||||
|
||||
if(facets.size() > builder.getGlobalBinding().getDefaultEnumMemberSizeCap()) {
|
||||
// if there are too many facets, it's not very useful
|
||||
// produce warning when simple type is not mapped to enum
|
||||
// see issue https://jaxb.dev.java.net/issues/show_bug.cgi?id=711
|
||||
|
||||
if(reportedEnumMemberSizeWarnings == null)
|
||||
reportedEnumMemberSizeWarnings = new HashSet<XSRestrictionSimpleType>();
|
||||
|
||||
if(!reportedEnumMemberSizeWarnings.contains(type)) {
|
||||
getErrorReporter().warning(type.getLocator(), Messages.WARN_ENUM_MEMBER_SIZE_CAP,
|
||||
type.getName(), facets.size(), builder.getGlobalBinding().getDefaultEnumMemberSizeCap());
|
||||
|
||||
reportedEnumMemberSizeWarnings.add(type);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !canBeMappedToTypeSafeEnum(type) )
|
||||
// we simply can't map this to an enumeration
|
||||
return false;
|
||||
|
||||
// check for collisions among constant names. if a collision will happen,
|
||||
// don't try to bind it to an enum.
|
||||
|
||||
// return true only when this type is derived from one of the "enum base type".
|
||||
for( XSSimpleType t = type; t!=null; t=t.getSimpleBaseType() )
|
||||
if( t.isGlobal() && builder.getGlobalBinding().canBeMappedToTypeSafeEnum(t) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private static final Set<String> builtinTypeSafeEnumCapableTypes;
|
||||
|
||||
static {
|
||||
Set<String> s = new HashSet<String>();
|
||||
|
||||
// see a bullet of 6.5.1 of the spec.
|
||||
String[] typeNames = new String[] {
|
||||
"string", "boolean", "float", "decimal", "double", "anyURI"
|
||||
};
|
||||
s.addAll(Arrays.asList(typeNames));
|
||||
|
||||
builtinTypeSafeEnumCapableTypes = Collections.unmodifiableSet(s);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the given simple type can be mapped to a
|
||||
* type-safe enum class.
|
||||
*
|
||||
* <p>
|
||||
* JAXB spec places a restrictrion as to what type can be
|
||||
* mapped to a type-safe enum. This method enforces this
|
||||
* constraint.
|
||||
*/
|
||||
public static boolean canBeMappedToTypeSafeEnum( XSSimpleType type ) {
|
||||
do {
|
||||
if( WellKnownNamespace.XML_SCHEMA.equals(type.getTargetNamespace()) ) {
|
||||
// type must be derived from one of these types
|
||||
String localName = type.getName();
|
||||
if( localName!=null ) {
|
||||
if( localName.equals("anySimpleType") )
|
||||
return false; // catch all case
|
||||
if( localName.equals("ID") || localName.equals("IDREF") )
|
||||
return false; // not ID/IDREF
|
||||
|
||||
// other allowed list
|
||||
if( builtinTypeSafeEnumCapableTypes.contains(localName) )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
type = type.getSimpleBaseType();
|
||||
} while( type!=null );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Builds a type-safe enum conversion from a simple type
|
||||
* with enumeration facets.
|
||||
*
|
||||
* @param className
|
||||
* The class name of the type-safe enum. Or null to
|
||||
* create a default name.
|
||||
* @param javadoc
|
||||
* Additional javadoc that will be added at the beginning of the
|
||||
* class, or null if none is necessary.
|
||||
* @param members
|
||||
* A map from enumeration values (as String) to BIEnumMember objects.
|
||||
* if some of the value names need to be overrided.
|
||||
* Cannot be null, but the map may not contain entries
|
||||
* for all enumeration values.
|
||||
* @param loc
|
||||
* The source location where the above customizations are
|
||||
* specified, or null if none is available.
|
||||
*/
|
||||
private TypeUse bindToTypeSafeEnum( XSRestrictionSimpleType type,
|
||||
String className, String javadoc, Map<String,BIEnumMember> members,
|
||||
EnumMemberMode mode, Locator loc ) {
|
||||
|
||||
if( loc==null ) // use the location of the simple type as the default
|
||||
loc = type.getLocator();
|
||||
|
||||
if( className==null ) {
|
||||
// infer the class name. For this to be possible,
|
||||
// the simple type must be a global one.
|
||||
if( !type.isGlobal() ) {
|
||||
getErrorReporter().error( loc, Messages.ERR_NO_ENUM_NAME_AVAILABLE );
|
||||
// recover by returning a meaningless conversion
|
||||
return CBuiltinLeafInfo.STRING;
|
||||
}
|
||||
className = type.getName();
|
||||
}
|
||||
|
||||
// we apply name conversion in any case
|
||||
className = builder.deriveName(className,type);
|
||||
|
||||
{// compute Javadoc
|
||||
StringWriter out = new StringWriter();
|
||||
SchemaWriter sw = new SchemaWriter(new JavadocEscapeWriter(out));
|
||||
type.visit((XSVisitor)sw);
|
||||
|
||||
if(javadoc!=null) javadoc += "\n\n";
|
||||
else javadoc = "";
|
||||
|
||||
javadoc += Messages.format( Messages.JAVADOC_HEADING, type.getName() )
|
||||
+"\n<p>\n<pre>\n"+out.getBuffer()+"</pre>";
|
||||
|
||||
}
|
||||
|
||||
// build base type
|
||||
refererStack.push(type.getSimpleBaseType());
|
||||
TypeUse use = build(type.getSimpleBaseType());
|
||||
refererStack.pop();
|
||||
|
||||
if(use.isCollection())
|
||||
return null; // can't bind a list to enum constant
|
||||
|
||||
CNonElement baseDt = use.getInfo(); // for now just ignore that case
|
||||
|
||||
if(baseDt instanceof CClassInfo)
|
||||
return null; // can't bind to an enum if the base is a class, since we don't have the value constrctor
|
||||
|
||||
// if the member names collide, re-generate numbered constant names.
|
||||
XSFacet[] errorRef = new XSFacet[1];
|
||||
List<CEnumConstant> memberList = buildCEnumConstants(type, false, members, errorRef);
|
||||
if(memberList==null || checkMemberNameCollision(memberList)!=null) {
|
||||
switch(mode) {
|
||||
case SKIP:
|
||||
// abort
|
||||
return null;
|
||||
case ERROR:
|
||||
// error
|
||||
if(memberList==null) {
|
||||
getErrorReporter().error( errorRef[0].getLocator(),
|
||||
Messages.ERR_CANNOT_GENERATE_ENUM_NAME,
|
||||
errorRef[0].getValue() );
|
||||
} else {
|
||||
CEnumConstant[] collision = checkMemberNameCollision(memberList);
|
||||
getErrorReporter().error( collision[0].getLocator(),
|
||||
Messages.ERR_ENUM_MEMBER_NAME_COLLISION,
|
||||
collision[0].getName() );
|
||||
getErrorReporter().error( collision[1].getLocator(),
|
||||
Messages.ERR_ENUM_MEMBER_NAME_COLLISION_RELATED );
|
||||
}
|
||||
return null; // recover from error
|
||||
case GENERATE:
|
||||
// generate
|
||||
memberList = buildCEnumConstants(type,true,members,null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(memberList.isEmpty()) {
|
||||
getErrorReporter().error( loc, Messages.ERR_NO_ENUM_FACET );
|
||||
return null;
|
||||
}
|
||||
|
||||
// use the name of the simple type as the name of the class.
|
||||
CClassInfoParent scope;
|
||||
if(type.isGlobal())
|
||||
scope = new CClassInfoParent.Package(getClassSelector().getPackage(type.getTargetNamespace()));
|
||||
else
|
||||
scope = getClassSelector().getClassScope();
|
||||
CEnumLeafInfo xducer = new CEnumLeafInfo( model, BGMBuilder.getName(type), scope,
|
||||
className, baseDt, memberList, type,
|
||||
builder.getBindInfo(type).toCustomizationList(), loc );
|
||||
xducer.javadoc = javadoc;
|
||||
|
||||
BIConversion conv = new BIConversion.Static( type.getLocator(),xducer);
|
||||
conv.markAsAcknowledged();
|
||||
|
||||
// attach this new conversion object to this simple type
|
||||
// so that successive look up will use the same object.
|
||||
builder.getOrCreateBindInfo(type).addDecl(conv);
|
||||
|
||||
return conv.getTypeUse(type);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param errorRef
|
||||
* if constant names couldn't be generated, return a reference to that enum facet.
|
||||
* @return
|
||||
* null if unable to generate names for some of the constants.
|
||||
*/
|
||||
private List<CEnumConstant> buildCEnumConstants(XSRestrictionSimpleType type, boolean needsToGenerateMemberName, Map<String, BIEnumMember> members, XSFacet[] errorRef) {
|
||||
List<CEnumConstant> memberList = new ArrayList<CEnumConstant>();
|
||||
int idx=1;
|
||||
Set<String> enums = new HashSet<String>(); // to avoid duplicates. See issue #366
|
||||
|
||||
for( XSFacet facet : type.getDeclaredFacets(XSFacet.FACET_ENUMERATION)) {
|
||||
String name=null;
|
||||
String mdoc=builder.getBindInfo(facet).getDocumentation();
|
||||
|
||||
if(!enums.add(facet.getValue().value))
|
||||
continue; // ignore the 2nd occasion
|
||||
|
||||
if( needsToGenerateMemberName ) {
|
||||
// generate names for all member names.
|
||||
// this will even override names specified by the user. that's crazy.
|
||||
name = "VALUE_"+(idx++);
|
||||
} else {
|
||||
String facetValue = facet.getValue().value;
|
||||
BIEnumMember mem = members.get(facetValue);
|
||||
if( mem==null )
|
||||
// look at the one attached to the facet object
|
||||
mem = builder.getBindInfo(facet).get(BIEnumMember.class);
|
||||
|
||||
if (mem!=null) {
|
||||
name = mem.name;
|
||||
if (mdoc == null) {
|
||||
mdoc = mem.javadoc;
|
||||
}
|
||||
}
|
||||
|
||||
if(name==null) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for( int i=0; i<facetValue.length(); i++) {
|
||||
char ch = facetValue.charAt(i);
|
||||
if(Character.isJavaIdentifierPart(ch))
|
||||
sb.append(ch);
|
||||
else
|
||||
sb.append('_');
|
||||
}
|
||||
name = model.getNameConverter().toConstantName(sb.toString());
|
||||
}
|
||||
}
|
||||
|
||||
if(!JJavaName.isJavaIdentifier(name)) {
|
||||
if(errorRef!=null) errorRef[0] = facet;
|
||||
return null; // unable to generate a name
|
||||
}
|
||||
|
||||
memberList.add(new CEnumConstant(name,mdoc,facet.getValue().value,facet,builder.getBindInfo(facet).toCustomizationList(),facet.getLocator()));
|
||||
}
|
||||
return memberList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns non-null if {@link CEnumConstant}s have name collisions among them.
|
||||
*
|
||||
* @return
|
||||
* if there's a collision, return two {@link CEnumConstant}s that collided.
|
||||
* otherwise return null.
|
||||
*/
|
||||
private CEnumConstant[] checkMemberNameCollision( List<CEnumConstant> memberList ) {
|
||||
Map<String,CEnumConstant> names = new HashMap<String,CEnumConstant>();
|
||||
for (CEnumConstant c : memberList) {
|
||||
CEnumConstant old = names.put(c.getName(),c);
|
||||
if(old!=null)
|
||||
// collision detected
|
||||
return new CEnumConstant[]{old,c};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private EnumMemberMode getEnumMemberMode() {
|
||||
return builder.getGlobalBinding().getEnumMemberMode();
|
||||
}
|
||||
|
||||
private TypeUse lookupBuiltin( String typeLocalName ) {
|
||||
if(typeLocalName.equals("integer") || typeLocalName.equals("long")) {
|
||||
/*
|
||||
attempt an optimization so that we can
|
||||
improve the binding for types like this:
|
||||
|
||||
<simpleType>
|
||||
<restriciton baseType="integer">
|
||||
<maxInclusive value="100" />
|
||||
</
|
||||
</
|
||||
|
||||
... to int, not BigInteger.
|
||||
*/
|
||||
|
||||
BigInteger xe = readFacet(XSFacet.FACET_MAXEXCLUSIVE,-1);
|
||||
BigInteger xi = readFacet(XSFacet.FACET_MAXINCLUSIVE,0);
|
||||
BigInteger max = min(xe,xi); // most restrictive one takes precedence
|
||||
|
||||
if(max!=null) {
|
||||
BigInteger ne = readFacet(XSFacet.FACET_MINEXCLUSIVE,+1);
|
||||
BigInteger ni = readFacet(XSFacet.FACET_MININCLUSIVE,0);
|
||||
BigInteger min = max(ne,ni);
|
||||
|
||||
if(min!=null) {
|
||||
if(min.compareTo(INT_MIN )>=0 && max.compareTo(INT_MAX )<=0)
|
||||
typeLocalName = "int";
|
||||
else
|
||||
if(min.compareTo(LONG_MIN)>=0 && max.compareTo(LONG_MAX)<=0)
|
||||
typeLocalName = "long";
|
||||
}
|
||||
}
|
||||
} else
|
||||
if(typeLocalName.equals("boolean") && isRestrictedTo0And1()) {
|
||||
// this is seen in the SOAP schema and too common to ignore
|
||||
return CBuiltinLeafInfo.BOOLEAN_ZERO_OR_ONE;
|
||||
} else
|
||||
if(typeLocalName.equals("base64Binary")) {
|
||||
return lookupBinaryTypeBinding();
|
||||
} else
|
||||
if(typeLocalName.equals("anySimpleType")) {
|
||||
if(getReferer() instanceof XSAttributeDecl || getReferer() instanceof XSSimpleType)
|
||||
return CBuiltinLeafInfo.STRING;
|
||||
else
|
||||
return CBuiltinLeafInfo.ANYTYPE;
|
||||
}
|
||||
return builtinConversions.get(typeLocalName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decides the way xs:base64Binary binds.
|
||||
*
|
||||
* This method checks the expected media type.
|
||||
*/
|
||||
private TypeUse lookupBinaryTypeBinding() {
|
||||
XSComponent referer = getReferer();
|
||||
String emt = referer.getForeignAttribute(XML_MIME_URI, Const.EXPECTED_CONTENT_TYPES);
|
||||
if(emt!=null) {
|
||||
acknowledgedXmimeContentTypes.add(referer);
|
||||
try {
|
||||
// see http://www.xml.com/lpt/a/2004/07/21/dive.html
|
||||
List<MimeTypeRange> types = MimeTypeRange.parseRanges(emt);
|
||||
MimeTypeRange mt = MimeTypeRange.merge(types);
|
||||
|
||||
// see spec table I-1 in appendix I section 2.1.1 for bindings
|
||||
if(mt.majorType.equalsIgnoreCase("image"))
|
||||
return CBuiltinLeafInfo.IMAGE.makeMimeTyped(mt.toMimeType());
|
||||
|
||||
if(( mt.majorType.equalsIgnoreCase("application") || mt.majorType.equalsIgnoreCase("text"))
|
||||
&& isXml(mt.subType))
|
||||
return CBuiltinLeafInfo.XML_SOURCE.makeMimeTyped(mt.toMimeType());
|
||||
|
||||
if((mt.majorType.equalsIgnoreCase("text") && (mt.subType.equalsIgnoreCase("plain")) )) {
|
||||
return CBuiltinLeafInfo.STRING.makeMimeTyped(mt.toMimeType());
|
||||
}
|
||||
|
||||
return CBuiltinLeafInfo.DATA_HANDLER.makeMimeTyped(mt.toMimeType());
|
||||
} catch (ParseException e) {
|
||||
getErrorReporter().error( referer.getLocator(),
|
||||
Messages.format(Messages.ERR_ILLEGAL_EXPECTED_MIME_TYPE,emt, e.getMessage()) );
|
||||
// recover by using the default
|
||||
} catch (MimeTypeParseException e) {
|
||||
getErrorReporter().error( referer.getLocator(),
|
||||
Messages.format(Messages.ERR_ILLEGAL_EXPECTED_MIME_TYPE,emt, e.getMessage()) );
|
||||
}
|
||||
}
|
||||
// default
|
||||
return CBuiltinLeafInfo.BASE64_BYTE_ARRAY;
|
||||
}
|
||||
|
||||
public boolean isAcknowledgedXmimeContentTypes(XSComponent c) {
|
||||
return acknowledgedXmimeContentTypes.contains(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the specified sub-type is an XML type.
|
||||
*/
|
||||
private boolean isXml(String subType) {
|
||||
return subType.equals("xml") || subType.endsWith("+xml");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the {@link #initiatingType} is restricted
|
||||
* to '0' and '1'. This logic is not complete, but it at least
|
||||
* finds the such definition in SOAP @mustUnderstand.
|
||||
*/
|
||||
private boolean isRestrictedTo0And1() {
|
||||
XSFacet pattern = initiatingType.getFacet(XSFacet.FACET_PATTERN);
|
||||
if(pattern!=null) {
|
||||
String v = pattern.getValue().value;
|
||||
if(v.equals("0|1") || v.equals("1|0") || v.equals("\\d"))
|
||||
return true;
|
||||
}
|
||||
XSFacet enumf = initiatingType.getFacet(XSFacet.FACET_ENUMERATION);
|
||||
if(enumf!=null) {
|
||||
String v = enumf.getValue().value;
|
||||
if(v.equals("0") || v.equals("1"))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private BigInteger readFacet(String facetName,int offset) {
|
||||
XSFacet me = initiatingType.getFacet(facetName);
|
||||
if(me==null)
|
||||
return null;
|
||||
BigInteger bi = DatatypeConverter.parseInteger(me.getValue().value);
|
||||
if(offset!=0)
|
||||
bi = bi.add(BigInteger.valueOf(offset));
|
||||
return bi;
|
||||
}
|
||||
|
||||
private BigInteger min(BigInteger a, BigInteger b) {
|
||||
if(a==null) return b;
|
||||
if(b==null) return a;
|
||||
return a.min(b);
|
||||
}
|
||||
|
||||
private BigInteger max(BigInteger a, BigInteger b) {
|
||||
if(a==null) return b;
|
||||
if(b==null) return a;
|
||||
return a.max(b);
|
||||
}
|
||||
|
||||
private static final BigInteger LONG_MIN = BigInteger.valueOf(Long.MIN_VALUE);
|
||||
private static final BigInteger LONG_MAX = BigInteger.valueOf(Long.MAX_VALUE);
|
||||
private static final BigInteger INT_MIN = BigInteger.valueOf(Integer.MIN_VALUE);
|
||||
private static final BigInteger INT_MAX = BigInteger.valueOf(Integer.MAX_VALUE);
|
||||
|
||||
static {
|
||||
// list of datatypes which have built-in conversions.
|
||||
// note that although xs:token and xs:normalizedString are not
|
||||
// specified in the spec, they need to be here because they
|
||||
// have different whitespace normalization semantics.
|
||||
Map<String,TypeUse> m = builtinConversions;
|
||||
|
||||
// TODO: this is so dumb
|
||||
m.put("string", CBuiltinLeafInfo.STRING);
|
||||
m.put("anyURI", CBuiltinLeafInfo.STRING);
|
||||
m.put("boolean", CBuiltinLeafInfo.BOOLEAN);
|
||||
// we'll also look at the expected media type, so don't just add this to the map
|
||||
// m.put("base64Binary", CBuiltinLeafInfo.BASE64_BYTE_ARRAY);
|
||||
m.put("hexBinary", CBuiltinLeafInfo.HEXBIN_BYTE_ARRAY);
|
||||
m.put("float", CBuiltinLeafInfo.FLOAT);
|
||||
m.put("decimal", CBuiltinLeafInfo.BIG_DECIMAL);
|
||||
m.put("integer", CBuiltinLeafInfo.BIG_INTEGER);
|
||||
m.put("long", CBuiltinLeafInfo.LONG);
|
||||
m.put("unsignedInt", CBuiltinLeafInfo.LONG);
|
||||
m.put("int", CBuiltinLeafInfo.INT);
|
||||
m.put("unsignedShort", CBuiltinLeafInfo.INT);
|
||||
m.put("short", CBuiltinLeafInfo.SHORT);
|
||||
m.put("unsignedByte", CBuiltinLeafInfo.SHORT);
|
||||
m.put("byte", CBuiltinLeafInfo.BYTE);
|
||||
m.put("double", CBuiltinLeafInfo.DOUBLE);
|
||||
m.put("QName", CBuiltinLeafInfo.QNAME);
|
||||
m.put("NOTATION", CBuiltinLeafInfo.QNAME);
|
||||
m.put("dateTime", CBuiltinLeafInfo.CALENDAR);
|
||||
m.put("date", CBuiltinLeafInfo.CALENDAR);
|
||||
m.put("time", CBuiltinLeafInfo.CALENDAR);
|
||||
m.put("gYearMonth", CBuiltinLeafInfo.CALENDAR);
|
||||
m.put("gYear", CBuiltinLeafInfo.CALENDAR);
|
||||
m.put("gMonthDay", CBuiltinLeafInfo.CALENDAR);
|
||||
m.put("gDay", CBuiltinLeafInfo.CALENDAR);
|
||||
m.put("gMonth", CBuiltinLeafInfo.CALENDAR);
|
||||
m.put("duration", CBuiltinLeafInfo.DURATION);
|
||||
m.put("token", CBuiltinLeafInfo.TOKEN);
|
||||
m.put("normalizedString",CBuiltinLeafInfo.NORMALIZED_STRING);
|
||||
m.put("ID", CBuiltinLeafInfo.ID);
|
||||
m.put("IDREF", CBuiltinLeafInfo.IDREF);
|
||||
// TODO: handling dateTime, time, and date type
|
||||
// String[] names = {
|
||||
// "date", "dateTime", "time", "hexBinary" };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.sun.tools.internal.xjc.reader.Const;
|
||||
import com.sun.tools.internal.xjc.reader.Ring;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIDeclaration;
|
||||
import com.sun.xml.internal.bind.v2.WellKnownNamespace;
|
||||
import com.sun.xml.internal.xsom.XSAnnotation;
|
||||
import com.sun.xml.internal.xsom.XSAttContainer;
|
||||
import com.sun.xml.internal.xsom.XSAttGroupDecl;
|
||||
import com.sun.xml.internal.xsom.XSAttributeDecl;
|
||||
import com.sun.xml.internal.xsom.XSAttributeUse;
|
||||
import com.sun.xml.internal.xsom.XSComplexType;
|
||||
import com.sun.xml.internal.xsom.XSComponent;
|
||||
import com.sun.xml.internal.xsom.XSContentType;
|
||||
import com.sun.xml.internal.xsom.XSElementDecl;
|
||||
import com.sun.xml.internal.xsom.XSFacet;
|
||||
import com.sun.xml.internal.xsom.XSIdentityConstraint;
|
||||
import com.sun.xml.internal.xsom.XSListSimpleType;
|
||||
import com.sun.xml.internal.xsom.XSModelGroup;
|
||||
import com.sun.xml.internal.xsom.XSModelGroupDecl;
|
||||
import com.sun.xml.internal.xsom.XSNotation;
|
||||
import com.sun.xml.internal.xsom.XSParticle;
|
||||
import com.sun.xml.internal.xsom.XSRestrictionSimpleType;
|
||||
import com.sun.xml.internal.xsom.XSSchema;
|
||||
import com.sun.xml.internal.xsom.XSSchemaSet;
|
||||
import com.sun.xml.internal.xsom.XSSimpleType;
|
||||
import com.sun.xml.internal.xsom.XSUnionSimpleType;
|
||||
import com.sun.xml.internal.xsom.XSWildcard;
|
||||
import com.sun.xml.internal.xsom.XSXPath;
|
||||
import com.sun.xml.internal.xsom.visitor.XSSimpleTypeVisitor;
|
||||
import com.sun.xml.internal.xsom.visitor.XSVisitor;
|
||||
|
||||
/**
|
||||
* Reports all unacknowledged customizations as errors.
|
||||
*
|
||||
* <p>
|
||||
* Since we scan the whole content tree, we use this to check for unused
|
||||
* <tt>xmime:expectedContentTypes</tt> attributes. TODO: if we find this kind of error checks more
|
||||
* common, use the visitors so that we don't have to mix everything in one class.
|
||||
*
|
||||
* @author
|
||||
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
class UnusedCustomizationChecker extends BindingComponent implements XSVisitor, XSSimpleTypeVisitor {
|
||||
private final BGMBuilder builder = Ring.get(BGMBuilder.class);
|
||||
private final SimpleTypeBuilder stb = Ring.get(SimpleTypeBuilder.class);
|
||||
|
||||
private final Set<XSComponent> visitedComponents = new HashSet<XSComponent>();
|
||||
|
||||
/**
|
||||
* Runs the check.
|
||||
*/
|
||||
void run() {
|
||||
for( XSSchema s : Ring.get(XSSchemaSet.class).getSchemas() ) {
|
||||
schema(s);
|
||||
run( s.getAttGroupDecls() );
|
||||
run( s.getAttributeDecls() );
|
||||
run( s.getComplexTypes() );
|
||||
run( s.getElementDecls() );
|
||||
run( s.getModelGroupDecls() );
|
||||
run( s.getNotations() );
|
||||
run( s.getSimpleTypes() );
|
||||
}
|
||||
}
|
||||
|
||||
private void run( Map<String,? extends XSComponent> col ) {
|
||||
for( XSComponent c : col.values() )
|
||||
c.visit(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks unused customizations on this component
|
||||
* and returns true if this is the first time this
|
||||
* component is checked.
|
||||
*/
|
||||
private boolean check( XSComponent c ) {
|
||||
if( !visitedComponents.add(c) )
|
||||
return false; // already processed
|
||||
|
||||
for( BIDeclaration decl : builder.getBindInfo(c).getDecls() )
|
||||
check(decl, c);
|
||||
|
||||
checkExpectedContentTypes(c);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void checkExpectedContentTypes(XSComponent c) {
|
||||
if(c.getForeignAttribute(WellKnownNamespace.XML_MIME_URI, Const.EXPECTED_CONTENT_TYPES)==null)
|
||||
return; // no such attribute
|
||||
if(c instanceof XSParticle)
|
||||
return; // particles get the same foreign attributes as local element decls,
|
||||
// so we need to skip them
|
||||
|
||||
if(!stb.isAcknowledgedXmimeContentTypes(c)) {
|
||||
// this is not used
|
||||
getErrorReporter().warning(c.getLocator(),Messages.WARN_UNUSED_EXPECTED_CONTENT_TYPES);
|
||||
}
|
||||
}
|
||||
|
||||
private void check(BIDeclaration decl, XSComponent c) {
|
||||
if( !decl.isAcknowledged() ) {
|
||||
getErrorReporter().error(
|
||||
decl.getLocation(),
|
||||
Messages.ERR_UNACKNOWLEDGED_CUSTOMIZATION,
|
||||
decl.getName().getLocalPart()
|
||||
);
|
||||
getErrorReporter().error(
|
||||
c.getLocator(),
|
||||
Messages.ERR_UNACKNOWLEDGED_CUSTOMIZATION_LOCATION);
|
||||
// mark it as acknowledged to avoid
|
||||
// duplicated error messages.
|
||||
decl.markAsAcknowledged();
|
||||
}
|
||||
for (BIDeclaration d : decl.getChildren())
|
||||
check(d,c);
|
||||
}
|
||||
|
||||
|
||||
public void annotation(XSAnnotation ann) {}
|
||||
|
||||
public void attGroupDecl(XSAttGroupDecl decl) {
|
||||
if(check(decl))
|
||||
attContainer(decl);
|
||||
}
|
||||
|
||||
public void attributeDecl(XSAttributeDecl decl) {
|
||||
if(check(decl))
|
||||
decl.getType().visit((XSSimpleTypeVisitor)this);
|
||||
}
|
||||
|
||||
public void attributeUse(XSAttributeUse use) {
|
||||
if(check(use))
|
||||
use.getDecl().visit(this);
|
||||
}
|
||||
|
||||
public void complexType(XSComplexType type) {
|
||||
if(check(type)) {
|
||||
// don't need to check the base type -- it must be global, thus
|
||||
// it is covered already
|
||||
type.getContentType().visit(this);
|
||||
attContainer(type);
|
||||
}
|
||||
}
|
||||
|
||||
private void attContainer( XSAttContainer cont ) {
|
||||
for( Iterator itr = cont.iterateAttGroups(); itr.hasNext(); )
|
||||
((XSAttGroupDecl)itr.next()).visit(this);
|
||||
|
||||
for( Iterator itr = cont.iterateDeclaredAttributeUses(); itr.hasNext(); )
|
||||
((XSAttributeUse)itr.next()).visit(this);
|
||||
|
||||
XSWildcard wc = cont.getAttributeWildcard();
|
||||
if(wc!=null) wc.visit(this);
|
||||
}
|
||||
|
||||
public void schema(XSSchema schema) {
|
||||
check(schema);
|
||||
}
|
||||
|
||||
public void facet(XSFacet facet) {
|
||||
check(facet);
|
||||
}
|
||||
|
||||
public void notation(XSNotation notation) {
|
||||
check(notation);
|
||||
}
|
||||
|
||||
public void wildcard(XSWildcard wc) {
|
||||
check(wc);
|
||||
}
|
||||
|
||||
public void modelGroupDecl(XSModelGroupDecl decl) {
|
||||
if(check(decl))
|
||||
decl.getModelGroup().visit(this);
|
||||
}
|
||||
|
||||
public void modelGroup(XSModelGroup group) {
|
||||
if(check(group)) {
|
||||
for( int i=0; i<group.getSize(); i++ )
|
||||
group.getChild(i).visit(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void elementDecl(XSElementDecl decl) {
|
||||
if(check(decl)) {
|
||||
decl.getType().visit(this);
|
||||
for( XSIdentityConstraint id : decl.getIdentityConstraints() )
|
||||
id.visit(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void simpleType(XSSimpleType simpleType) {
|
||||
if(check(simpleType))
|
||||
simpleType.visit( (XSSimpleTypeVisitor)this );
|
||||
}
|
||||
|
||||
public void particle(XSParticle particle) {
|
||||
if(check(particle))
|
||||
particle.getTerm().visit(this);
|
||||
}
|
||||
|
||||
public void empty(XSContentType empty) {
|
||||
check(empty);
|
||||
}
|
||||
|
||||
public void listSimpleType(XSListSimpleType type) {
|
||||
if(check(type))
|
||||
type.getItemType().visit((XSSimpleTypeVisitor)this);
|
||||
}
|
||||
|
||||
public void restrictionSimpleType(XSRestrictionSimpleType type) {
|
||||
if(check(type))
|
||||
type.getBaseType().visit(this);
|
||||
}
|
||||
|
||||
public void unionSimpleType(XSUnionSimpleType type) {
|
||||
if(check(type)) {
|
||||
for( int i=0; i<type.getMemberSize(); i++ )
|
||||
type.getMember(i).visit((XSSimpleTypeVisitor)this);
|
||||
}
|
||||
}
|
||||
|
||||
public void identityConstraint(XSIdentityConstraint id) {
|
||||
if(check(id)) {
|
||||
id.getSelector().visit(this);
|
||||
for( XSXPath xp : id.getFields() )
|
||||
xp.visit(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void xpath(XSXPath xp) {
|
||||
check(xp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.sun.xml.internal.xsom.XSWildcard;
|
||||
import com.sun.xml.internal.xsom.visitor.XSWildcardFunction;
|
||||
|
||||
import com.sun.xml.internal.rngom.nc.AnyNameExceptNameClass;
|
||||
import com.sun.xml.internal.rngom.nc.ChoiceNameClass;
|
||||
import com.sun.xml.internal.rngom.nc.NameClass;
|
||||
import com.sun.xml.internal.rngom.nc.NsNameClass;
|
||||
|
||||
/**
|
||||
* Builds a name class representation of a wildcard.
|
||||
*
|
||||
* <p>
|
||||
* Singleton. Use the build method to create a NameClass.
|
||||
*
|
||||
* @author
|
||||
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
public final class WildcardNameClassBuilder implements XSWildcardFunction<NameClass> {
|
||||
private WildcardNameClassBuilder() {}
|
||||
|
||||
private static final XSWildcardFunction<NameClass> theInstance =
|
||||
new WildcardNameClassBuilder();
|
||||
|
||||
public static NameClass build( XSWildcard wc ) {
|
||||
return wc.apply(theInstance);
|
||||
}
|
||||
|
||||
public NameClass any(XSWildcard.Any wc) {
|
||||
return NameClass.ANY;
|
||||
}
|
||||
|
||||
public NameClass other(XSWildcard.Other wc) {
|
||||
return new AnyNameExceptNameClass(
|
||||
new ChoiceNameClass(
|
||||
new NsNameClass(""),
|
||||
new NsNameClass(wc.getOtherNamespace())));
|
||||
}
|
||||
|
||||
public NameClass union(XSWildcard.Union wc) {
|
||||
NameClass nc = null;
|
||||
for (Iterator itr = wc.iterateNamespaces(); itr.hasNext();) {
|
||||
String ns = (String) itr.next();
|
||||
|
||||
if(nc==null) nc = new NsNameClass(ns);
|
||||
else
|
||||
nc = new ChoiceNameClass(nc,new NsNameClass(ns));
|
||||
}
|
||||
|
||||
// there should be at least one.
|
||||
assert nc!=null;
|
||||
|
||||
return nc;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema.bindinfo;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import com.sun.codemodel.internal.JCodeModel;
|
||||
import com.sun.tools.internal.xjc.reader.Ring;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.BGMBuilder;
|
||||
import com.sun.xml.internal.bind.annotation.XmlLocation;
|
||||
import com.sun.xml.internal.xsom.XSComponent;
|
||||
|
||||
import org.xml.sax.Locator;
|
||||
|
||||
/**
|
||||
* Abstract partial implementation of {@link BIDeclaration}
|
||||
*
|
||||
* @author
|
||||
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
abstract class AbstractDeclarationImpl implements BIDeclaration {
|
||||
|
||||
@Deprecated // eventually delete this in favor of using JAXB
|
||||
protected AbstractDeclarationImpl(Locator loc) {
|
||||
this.loc = loc;
|
||||
}
|
||||
|
||||
protected AbstractDeclarationImpl() {}
|
||||
|
||||
|
||||
@XmlLocation
|
||||
Locator loc; // set by JAXB
|
||||
public Locator getLocation() { return loc; }
|
||||
|
||||
protected BindInfo parent;
|
||||
public void setParent(BindInfo p) { this.parent=p; }
|
||||
|
||||
protected final XSComponent getOwner() {
|
||||
return parent.getOwner();
|
||||
}
|
||||
protected final BGMBuilder getBuilder() {
|
||||
return parent.getBuilder();
|
||||
}
|
||||
protected final JCodeModel getCodeModel() {
|
||||
return Ring.get(JCodeModel.class);
|
||||
}
|
||||
|
||||
|
||||
private boolean isAcknowledged = false;
|
||||
|
||||
public final boolean isAcknowledged() { return isAcknowledged; }
|
||||
|
||||
public void onSetOwner() {
|
||||
}
|
||||
|
||||
public Collection<BIDeclaration> getChildren() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public void markAsAcknowledged() {
|
||||
isAcknowledged = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema.bindinfo;
|
||||
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import javax.xml.bind.UnmarshallerHandler;
|
||||
import javax.xml.bind.helpers.DefaultValidationEventHandler;
|
||||
import javax.xml.validation.ValidatorHandler;
|
||||
|
||||
import com.sun.tools.internal.xjc.Options;
|
||||
import com.sun.tools.internal.xjc.reader.Const;
|
||||
import com.sun.xml.internal.xsom.parser.AnnotationContext;
|
||||
import com.sun.xml.internal.xsom.parser.AnnotationParser;
|
||||
import com.sun.xml.internal.xsom.parser.AnnotationParserFactory;
|
||||
import com.sun.xml.internal.bind.v2.WellKnownNamespace;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.EntityResolver;
|
||||
import org.xml.sax.ErrorHandler;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXParseException;
|
||||
import org.xml.sax.helpers.XMLFilterImpl;
|
||||
|
||||
/**
|
||||
* Implementation of XSOM {@link AnnotationParserFactory} that
|
||||
* parses JAXB customization declarations.
|
||||
*
|
||||
* @author
|
||||
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
public class AnnotationParserFactoryImpl implements AnnotationParserFactory {
|
||||
public AnnotationParserFactoryImpl(Options opts) {
|
||||
this.options=opts;
|
||||
}
|
||||
|
||||
private final Options options;
|
||||
/**
|
||||
* Lazily created validator, so that the schema for binding won't be
|
||||
* prepared unless absolutely necessary.
|
||||
*/
|
||||
private ValidatorHandler validator;
|
||||
|
||||
public AnnotationParser create() {
|
||||
return new AnnotationParser() {
|
||||
private Unmarshaller u = BindInfo.getCustomizationUnmarshaller();
|
||||
|
||||
private UnmarshallerHandler handler;
|
||||
|
||||
public ContentHandler getContentHandler(
|
||||
AnnotationContext context, String parentElementName,
|
||||
final ErrorHandler errorHandler, EntityResolver entityResolver ) {
|
||||
|
||||
// return a ContentHandler that validates the customization and also
|
||||
// parses them into the internal structure.
|
||||
if(handler!=null)
|
||||
// interface contract violation.
|
||||
// this method will be called only once.
|
||||
throw new AssertionError();
|
||||
|
||||
if(options.debugMode)
|
||||
try {
|
||||
u.setEventHandler(new DefaultValidationEventHandler());
|
||||
} catch (JAXBException e) {
|
||||
throw new AssertionError(e); // ridiculous!
|
||||
}
|
||||
|
||||
handler = u.getUnmarshallerHandler();
|
||||
|
||||
// configure so that the validator will receive events for JAXB islands
|
||||
return new ForkingFilter(handler) {
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
|
||||
super.startElement(uri, localName, qName, atts);
|
||||
if((uri.equals(Const.JAXB_NSURI) || uri.equals(Const.XJC_EXTENSION_URI))
|
||||
&& getSideHandler()==null) {
|
||||
// set up validator
|
||||
if(validator==null)
|
||||
validator = BindInfo.bindingFileSchema.newValidator();
|
||||
validator.setErrorHandler(errorHandler);
|
||||
startForking(uri,localName,qName,atts,new ValidatorProtecter(validator));
|
||||
}
|
||||
|
||||
// check for xmime:expectedContentTypes attributes in annotations and report them
|
||||
for( int i=atts.getLength()-1; i>=0; i-- ) {
|
||||
if(atts.getURI(i).equals(WellKnownNamespace.XML_MIME_URI)
|
||||
&& atts.getLocalName(i).equals(Const.EXPECTED_CONTENT_TYPES))
|
||||
errorHandler.warning(new SAXParseException(
|
||||
com.sun.tools.internal.xjc.reader.xmlschema.Messages.format(
|
||||
com.sun.tools.internal.xjc.reader.xmlschema.Messages.WARN_UNUSED_EXPECTED_CONTENT_TYPES),
|
||||
getDocumentLocator()
|
||||
));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public BindInfo getResult( Object existing ) {
|
||||
if(handler==null)
|
||||
// interface contract violation.
|
||||
// the getContentHandler method must have been called.
|
||||
throw new AssertionError();
|
||||
|
||||
try {
|
||||
BindInfo result = (BindInfo)handler.getResult();
|
||||
|
||||
if(existing!=null) {
|
||||
BindInfo bie = (BindInfo)existing;
|
||||
bie.absorb(result);
|
||||
return bie;
|
||||
} else {
|
||||
if(!result.isPointless())
|
||||
return result; // just annotation. no meaningful customization
|
||||
else
|
||||
return null;
|
||||
}
|
||||
} catch (JAXBException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static final class ValidatorProtecter extends XMLFilterImpl {
|
||||
public ValidatorProtecter(ContentHandler h) {
|
||||
setContentHandler(h);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startPrefixMapping(String prefix, String uri) throws SAXException {
|
||||
// work around a bug in the validator implementation in Tiger
|
||||
super.startPrefixMapping(prefix.intern(),uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema.bindinfo;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import com.sun.tools.internal.xjc.reader.Const;
|
||||
import com.sun.xml.internal.bind.api.impl.NameConverter;
|
||||
import com.sun.istack.internal.Nullable;
|
||||
|
||||
/**
|
||||
* Class declaration.
|
||||
*
|
||||
* This customization turns arbitrary schema component into a Java
|
||||
* content interface.
|
||||
*
|
||||
* <p>
|
||||
* This customization is acknowledged by the ClassSelector.
|
||||
*
|
||||
* @author
|
||||
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
@XmlRootElement(name="class")
|
||||
public final class BIClass extends AbstractDeclarationImpl {
|
||||
protected BIClass() {
|
||||
}
|
||||
|
||||
@XmlAttribute(name="name")
|
||||
private String className;
|
||||
|
||||
/**
|
||||
* Gets the specified class name, or null if not specified.
|
||||
* (Not a fully qualified name.)
|
||||
*
|
||||
* @return
|
||||
* Returns a class name. The caller should <em>NOT</em>
|
||||
* apply XML-to-Java name conversion to the name
|
||||
* returned from this method.
|
||||
*/
|
||||
public @Nullable String getClassName() {
|
||||
if( className==null ) return null;
|
||||
|
||||
BIGlobalBinding gb = getBuilder().getGlobalBinding();
|
||||
NameConverter nc = getBuilder().model.getNameConverter();
|
||||
|
||||
if(gb.isJavaNamingConventionEnabled()) return nc.toClassName(className);
|
||||
else
|
||||
// don't change it
|
||||
return className;
|
||||
}
|
||||
|
||||
@XmlAttribute(name="implClass")
|
||||
private String userSpecifiedImplClass;
|
||||
|
||||
/**
|
||||
* Gets the fully qualified name of the
|
||||
* user-specified implementation class, if any.
|
||||
* Or null.
|
||||
*/
|
||||
public String getUserSpecifiedImplClass() {
|
||||
return userSpecifiedImplClass;
|
||||
}
|
||||
|
||||
@XmlAttribute(name="ref")
|
||||
private String ref;
|
||||
|
||||
@XmlAttribute(name="recursive", namespace=Const.XJC_EXTENSION_URI)
|
||||
private String recursive;
|
||||
|
||||
/**
|
||||
* Reference to the existing class, or null.
|
||||
* Fully qualified name.
|
||||
*
|
||||
* <p>
|
||||
* Caller needs to perform error check on this.
|
||||
*/
|
||||
public String getExistingClassRef() {
|
||||
return ref;
|
||||
}
|
||||
|
||||
public String getRecursive() {
|
||||
return recursive;
|
||||
}
|
||||
|
||||
@XmlElement
|
||||
private String javadoc;
|
||||
/**
|
||||
* Gets the javadoc comment specified in the customization.
|
||||
* Can be null if none is specified.
|
||||
*/
|
||||
public String getJavadoc() { return javadoc; }
|
||||
|
||||
public QName getName() { return NAME; }
|
||||
|
||||
public void setParent(BindInfo p) {
|
||||
super.setParent(p);
|
||||
// if this specifies a reference to external class,
|
||||
// then it's OK even if noone actually refers this class.
|
||||
if(ref!=null)
|
||||
markAsAcknowledged();
|
||||
}
|
||||
|
||||
/** Name of this declaration. */
|
||||
public static final QName NAME = new QName( Const.JAXB_NSURI, "class" );
|
||||
}
|
||||
@@ -0,0 +1,349 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema.bindinfo;
|
||||
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.adapters.XmlAdapter;
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import com.sun.codemodel.internal.JClass;
|
||||
import com.sun.codemodel.internal.JClassAlreadyExistsException;
|
||||
import com.sun.codemodel.internal.JCodeModel;
|
||||
import com.sun.codemodel.internal.JDefinedClass;
|
||||
import com.sun.codemodel.internal.JExpr;
|
||||
import com.sun.codemodel.internal.JExpression;
|
||||
import com.sun.codemodel.internal.JMethod;
|
||||
import com.sun.codemodel.internal.JMod;
|
||||
import com.sun.codemodel.internal.JPackage;
|
||||
import com.sun.codemodel.internal.JType;
|
||||
import com.sun.codemodel.internal.JVar;
|
||||
import com.sun.codemodel.internal.JConditional;
|
||||
import com.sun.tools.internal.xjc.ErrorReceiver;
|
||||
import com.sun.tools.internal.xjc.model.CAdapter;
|
||||
import com.sun.tools.internal.xjc.model.CBuiltinLeafInfo;
|
||||
import com.sun.tools.internal.xjc.model.TypeUse;
|
||||
import com.sun.tools.internal.xjc.model.TypeUseFactory;
|
||||
import com.sun.tools.internal.xjc.reader.Const;
|
||||
import com.sun.tools.internal.xjc.reader.Ring;
|
||||
import com.sun.tools.internal.xjc.reader.TypeUtil;
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.ClassSelector;
|
||||
import com.sun.xml.internal.bind.v2.WellKnownNamespace;
|
||||
import com.sun.xml.internal.xsom.XSSimpleType;
|
||||
|
||||
import org.xml.sax.Locator;
|
||||
|
||||
/**
|
||||
* Conversion declaration.
|
||||
*
|
||||
* <p>
|
||||
* A conversion declaration specifies how an XML type gets mapped
|
||||
* to a Java type.
|
||||
*
|
||||
* @author
|
||||
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
public abstract class BIConversion extends AbstractDeclarationImpl {
|
||||
@Deprecated
|
||||
public BIConversion( Locator loc ) {
|
||||
super(loc);
|
||||
}
|
||||
|
||||
protected BIConversion() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link TypeUse} object that this conversion represents.
|
||||
* <p>
|
||||
* The returned {@link TypeUse} object is properly adapted.
|
||||
*
|
||||
* @param owner
|
||||
* A {@link BIConversion} is always associated with one
|
||||
* {@link XSSimpleType}, but that's not always available
|
||||
* when a {@link BIConversion} is built. So we pass this
|
||||
* as a parameter to this method.
|
||||
*/
|
||||
public abstract TypeUse getTypeUse( XSSimpleType owner );
|
||||
|
||||
public QName getName() { return NAME; }
|
||||
|
||||
/** Name of the conversion declaration. */
|
||||
public static final QName NAME = new QName(
|
||||
Const.JAXB_NSURI, "conversion" );
|
||||
|
||||
/**
|
||||
* Implementation that returns a statically-determined constant {@link TypeUse}.
|
||||
*/
|
||||
public static final class Static extends BIConversion {
|
||||
/**
|
||||
* Always non-null.
|
||||
*/
|
||||
private final TypeUse transducer;
|
||||
|
||||
public Static(Locator loc, TypeUse transducer) {
|
||||
super(loc);
|
||||
this.transducer = transducer;
|
||||
}
|
||||
|
||||
public TypeUse getTypeUse(XSSimpleType owner) {
|
||||
return transducer;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* User-specified <javaType> customization.
|
||||
*
|
||||
* The parse/print methods are allowed to be null,
|
||||
* and their default values are determined based on the
|
||||
* owner of the token.
|
||||
*/
|
||||
@XmlRootElement(name="javaType")
|
||||
public static class User extends BIConversion {
|
||||
@XmlAttribute
|
||||
private String parseMethod;
|
||||
@XmlAttribute
|
||||
private String printMethod;
|
||||
@XmlAttribute(name="name")
|
||||
private String type = "java.lang.String";
|
||||
|
||||
/**
|
||||
* If null, computed from {@link #type}.
|
||||
* Sometimes this can be set instead of {@link #type}.
|
||||
*/
|
||||
private JType inMemoryType;
|
||||
|
||||
public User(Locator loc, String parseMethod, String printMethod, JType inMemoryType) {
|
||||
super(loc);
|
||||
this.parseMethod = parseMethod;
|
||||
this.printMethod = printMethod;
|
||||
this.inMemoryType = inMemoryType;
|
||||
}
|
||||
|
||||
public User() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache used by {@link #getTypeUse(XSSimpleType)} to improve the performance.
|
||||
*/
|
||||
private TypeUse typeUse;
|
||||
|
||||
public TypeUse getTypeUse(XSSimpleType owner) {
|
||||
if(typeUse!=null)
|
||||
return typeUse;
|
||||
|
||||
JCodeModel cm = getCodeModel();
|
||||
|
||||
if(inMemoryType==null)
|
||||
inMemoryType = TypeUtil.getType(cm,type,Ring.get(ErrorReceiver.class),getLocation());
|
||||
|
||||
JDefinedClass adapter = generateAdapter(parseMethodFor(owner),printMethodFor(owner),owner);
|
||||
|
||||
// XmlJavaType customization always converts between string and an user-defined type.
|
||||
typeUse = TypeUseFactory.adapt(CBuiltinLeafInfo.STRING,new CAdapter(adapter));
|
||||
|
||||
return typeUse;
|
||||
}
|
||||
|
||||
/**
|
||||
* generate the adapter class.
|
||||
*/
|
||||
private JDefinedClass generateAdapter(String parseMethod, String printMethod,XSSimpleType owner) {
|
||||
JDefinedClass adapter = null;
|
||||
|
||||
int id = 1;
|
||||
while(adapter==null) {
|
||||
try {
|
||||
JPackage pkg = Ring.get(ClassSelector.class).getClassScope().getOwnerPackage();
|
||||
adapter = pkg._class("Adapter"+id);
|
||||
} catch (JClassAlreadyExistsException e) {
|
||||
// try another name in search for an unique name.
|
||||
// this isn't too efficient, but we expect people to usually use
|
||||
// a very small number of adapters.
|
||||
id++;
|
||||
}
|
||||
}
|
||||
|
||||
JClass bim = inMemoryType.boxify();
|
||||
|
||||
adapter._extends(getCodeModel().ref(XmlAdapter.class).narrow(String.class).narrow(bim));
|
||||
|
||||
JMethod unmarshal = adapter.method(JMod.PUBLIC, bim, "unmarshal");
|
||||
JVar $value = unmarshal.param(String.class, "value");
|
||||
|
||||
JExpression inv;
|
||||
|
||||
if( parseMethod.equals("new") ) {
|
||||
// "new" indicates that the constructor of the target type
|
||||
// will do the unmarshalling.
|
||||
|
||||
// RESULT: new <type>()
|
||||
inv = JExpr._new(bim).arg($value);
|
||||
} else {
|
||||
int idx = parseMethod.lastIndexOf('.');
|
||||
if(idx<0) {
|
||||
// parseMethod specifies the static method of the target type
|
||||
// which will do the unmarshalling.
|
||||
|
||||
// because of an error check at the constructor,
|
||||
// we can safely assume that this cast works.
|
||||
inv = bim.staticInvoke(parseMethod).arg($value);
|
||||
} else {
|
||||
inv = JExpr.direct(parseMethod+"(value)");
|
||||
}
|
||||
}
|
||||
unmarshal.body()._return(inv);
|
||||
|
||||
|
||||
JMethod marshal = adapter.method(JMod.PUBLIC, String.class, "marshal");
|
||||
$value = marshal.param(bim,"value");
|
||||
|
||||
if(printMethod.startsWith("javax.xml.bind.DatatypeConverter.")) {
|
||||
// UGLY: if this conversion is the system-driven conversion,
|
||||
// check for null
|
||||
marshal.body()._if($value.eq(JExpr._null()))._then()._return(JExpr._null());
|
||||
}
|
||||
|
||||
int idx = printMethod.lastIndexOf('.');
|
||||
if(idx<0) {
|
||||
// printMethod specifies a method in the target type
|
||||
// which performs the serialization.
|
||||
|
||||
// RESULT: <value>.<method>()
|
||||
inv = $value.invoke(printMethod);
|
||||
|
||||
// check value is not null ... if(value == null) return null;
|
||||
JConditional jcon = marshal.body()._if($value.eq(JExpr._null()));
|
||||
jcon._then()._return(JExpr._null());
|
||||
} else {
|
||||
// RESULT: <className>.<method>(<value>)
|
||||
if(this.printMethod==null) {
|
||||
// HACK HACK HACK
|
||||
JType t = inMemoryType.unboxify();
|
||||
inv = JExpr.direct(printMethod+"(("+findBaseConversion(owner).toLowerCase()+")("+t.fullName()+")value)");
|
||||
} else
|
||||
inv = JExpr.direct(printMethod+"(value)");
|
||||
}
|
||||
marshal.body()._return(inv);
|
||||
|
||||
return adapter;
|
||||
}
|
||||
|
||||
private String printMethodFor(XSSimpleType owner) {
|
||||
if(printMethod!=null) return printMethod;
|
||||
|
||||
if(inMemoryType.unboxify().isPrimitive()) {
|
||||
String method = getConversionMethod("print",owner);
|
||||
if(method!=null)
|
||||
return method;
|
||||
}
|
||||
|
||||
return "toString";
|
||||
}
|
||||
|
||||
private String parseMethodFor(XSSimpleType owner) {
|
||||
if(parseMethod!=null) return parseMethod;
|
||||
|
||||
if(inMemoryType.unboxify().isPrimitive()) {
|
||||
String method = getConversionMethod("parse", owner);
|
||||
if(method!=null) {
|
||||
// this cast is necessary for conversion between primitive Java types
|
||||
return '('+inMemoryType.unboxify().fullName()+')'+method;
|
||||
}
|
||||
}
|
||||
|
||||
return "new";
|
||||
}
|
||||
|
||||
private static final String[] knownBases = new String[]{
|
||||
"Float", "Double", "Byte", "Short", "Int", "Long", "Boolean"
|
||||
};
|
||||
|
||||
private String getConversionMethod(String methodPrefix, XSSimpleType owner) {
|
||||
String bc = findBaseConversion(owner);
|
||||
if(bc==null) return null;
|
||||
|
||||
return DatatypeConverter.class.getName()+'.'+methodPrefix+bc;
|
||||
}
|
||||
|
||||
private String findBaseConversion(XSSimpleType owner) {
|
||||
// find the base simple type mapping.
|
||||
for( XSSimpleType st=owner; st!=null; st = st.getSimpleBaseType() ) {
|
||||
if( !WellKnownNamespace.XML_SCHEMA.equals(st.getTargetNamespace()) )
|
||||
continue; // user-defined type
|
||||
|
||||
String name = st.getName().intern();
|
||||
for( String s : knownBases )
|
||||
if(name.equalsIgnoreCase(s))
|
||||
return s;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public QName getName() { return NAME; }
|
||||
|
||||
/** Name of the conversion declaration. */
|
||||
public static final QName NAME = new QName(
|
||||
Const.JAXB_NSURI, "javaType" );
|
||||
}
|
||||
|
||||
@XmlRootElement(name="javaType",namespace=Const.XJC_EXTENSION_URI)
|
||||
public static class UserAdapter extends BIConversion {
|
||||
@XmlAttribute(name="name")
|
||||
private String type = null;
|
||||
|
||||
@XmlAttribute
|
||||
private String adapter = null;
|
||||
|
||||
private TypeUse typeUse;
|
||||
|
||||
public TypeUse getTypeUse(XSSimpleType owner) {
|
||||
if(typeUse!=null)
|
||||
return typeUse;
|
||||
|
||||
JCodeModel cm = getCodeModel();
|
||||
|
||||
JDefinedClass a;
|
||||
try {
|
||||
a = cm._class(adapter);
|
||||
a.hide(); // we assume this is given by the user
|
||||
a._extends(cm.ref(XmlAdapter.class).narrow(String.class).narrow(
|
||||
cm.ref(type)));
|
||||
} catch (JClassAlreadyExistsException e) {
|
||||
a = e.getExistingClass();
|
||||
}
|
||||
|
||||
// TODO: it's not correct to say that it adapts from String,
|
||||
// but OTOH I don't think we can compute that.
|
||||
typeUse = TypeUseFactory.adapt(
|
||||
CBuiltinLeafInfo.STRING,
|
||||
new CAdapter(a));
|
||||
|
||||
return typeUse;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.internal.xjc.reader.xmlschema.bindinfo;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import com.sun.tools.internal.xjc.reader.xmlschema.BGMBuilder;
|
||||
|
||||
import org.xml.sax.Locator;
|
||||
|
||||
/**
|
||||
* Base interface for all binding customization declarations.
|
||||
*
|
||||
* <p>
|
||||
* Because of the setParent method, one customization declaration
|
||||
* can be attached to one component alone.
|
||||
*
|
||||
* @author
|
||||
* Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
|
||||
*/
|
||||
public interface BIDeclaration {
|
||||
|
||||
/**
|
||||
* Sets the parent BindInfo object of this declaration.
|
||||
* A declaration object can use this pointer to access
|
||||
* context information, such as other customizations.
|
||||
*
|
||||
* <p>
|
||||
* This method can be only called from {@link BindInfo},
|
||||
* and only once. This is a good opportunity to do some
|
||||
* follow-up initialization after JAXB unmarshalling
|
||||
* populated {@link BIDeclaration}.
|
||||
*/
|
||||
void setParent( BindInfo parent );
|
||||
|
||||
/**
|
||||
* Gets the name of this binding declaration,
|
||||
* which is the same as the tag name of the binding element.
|
||||
*/
|
||||
QName getName();
|
||||
|
||||
/**
|
||||
* Gets the source location where this declaration was written.
|
||||
* For declarations that are generated by XJC itself,
|
||||
* this method returns null.
|
||||
*/
|
||||
Locator getLocation();
|
||||
|
||||
/**
|
||||
* Marks this declaration to be acknowledged -- either actually
|
||||
* used or the existence is admitted (for example when
|
||||
* a property customization is given at the point of definition.)
|
||||
*
|
||||
* <p>
|
||||
* Declarations that are not acknowledged will be considered
|
||||
* as an error.
|
||||
*/
|
||||
void markAsAcknowledged();
|
||||
|
||||
/**
|
||||
* Checks if this declaration was acknowledged.
|
||||
*/
|
||||
boolean isAcknowledged();
|
||||
|
||||
/**
|
||||
* Called when the parent {@link BindInfo} got its owner set.
|
||||
*
|
||||
* This is when declarations are connected to {@link BGMBuilder} and
|
||||
* its sibling components.
|
||||
*/
|
||||
void onSetOwner();
|
||||
|
||||
/**
|
||||
* Gets child {@link BIDeclaration}s if any.
|
||||
*
|
||||
* @return
|
||||
* can be empty but always non-null. read-only.
|
||||
*/
|
||||
Collection<BIDeclaration> getChildren();
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user