ohair@286: /* alanb@368: * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. ohair@286: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ohair@286: * ohair@286: * This code is free software; you can redistribute it and/or modify it ohair@286: * under the terms of the GNU General Public License version 2 only, as ohair@286: * published by the Free Software Foundation. Oracle designates this ohair@286: * particular file as subject to the "Classpath" exception as provided ohair@286: * by Oracle in the LICENSE file that accompanied this code. ohair@286: * ohair@286: * This code is distributed in the hope that it will be useful, but WITHOUT ohair@286: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ohair@286: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ohair@286: * version 2 for more details (a copy is included in the LICENSE file that ohair@286: * accompanied this code). ohair@286: * ohair@286: * You should have received a copy of the GNU General Public License version ohair@286: * 2 along with this work; if not, write to the Free Software Foundation, ohair@286: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ohair@286: * ohair@286: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@286: * or visit www.oracle.com if you need additional information or have any ohair@286: * questions. ohair@286: */ ohair@286: ohair@286: package com.sun.tools.internal.xjc.reader.xmlschema; ohair@286: ohair@286: import java.util.ArrayList; ohair@286: import java.util.HashMap; ohair@286: import java.util.List; ohair@286: import java.util.Map; ohair@286: import java.util.Set; ohair@286: ohair@286: import javax.xml.namespace.QName; ohair@286: import javax.xml.transform.Transformer; ohair@286: import javax.xml.transform.TransformerConfigurationException; ohair@286: import javax.xml.transform.TransformerFactory; ohair@286: ohair@286: import com.sun.codemodel.internal.JCodeModel; ohair@286: import com.sun.codemodel.internal.fmt.JTextFile; ohair@286: import com.sun.istack.internal.NotNull; ohair@286: import com.sun.istack.internal.Nullable; ohair@286: import com.sun.tools.internal.xjc.ErrorReceiver; ohair@286: import com.sun.tools.internal.xjc.Options; ohair@286: import com.sun.tools.internal.xjc.Plugin; ohair@286: import com.sun.tools.internal.xjc.generator.bean.field.FieldRendererFactory; ohair@286: import com.sun.tools.internal.xjc.model.CClassInfoParent; ohair@286: import com.sun.tools.internal.xjc.model.Model; ohair@286: import com.sun.tools.internal.xjc.reader.ModelChecker; ohair@286: import com.sun.tools.internal.xjc.reader.Ring; ohair@286: import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIDeclaration; ohair@286: import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIDom; ohair@286: import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIGlobalBinding; ohair@286: import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BISchemaBinding; ohair@286: import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BISerializable; ohair@286: import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BindInfo; ohair@286: import com.sun.tools.internal.xjc.util.CodeModelClassFactory; ohair@286: import com.sun.tools.internal.xjc.util.ErrorReceiverFilter; ohair@286: import com.sun.xml.internal.bind.api.impl.NameConverter; alanb@368: import com.sun.xml.internal.bind.v2.util.XmlFactory; ohair@286: import com.sun.xml.internal.xsom.XSAnnotation; ohair@286: import com.sun.xml.internal.xsom.XSAttributeUse; ohair@286: import com.sun.xml.internal.xsom.XSComponent; ohair@286: import com.sun.xml.internal.xsom.XSDeclaration; ohair@286: import com.sun.xml.internal.xsom.XSParticle; ohair@286: import com.sun.xml.internal.xsom.XSSchema; ohair@286: import com.sun.xml.internal.xsom.XSSchemaSet; ohair@286: import com.sun.xml.internal.xsom.XSSimpleType; ohair@286: import com.sun.xml.internal.xsom.XSTerm; ohair@286: import com.sun.xml.internal.xsom.XSType; ohair@286: import com.sun.xml.internal.xsom.XSWildcard; ohair@286: import com.sun.xml.internal.xsom.util.XSFinder; ohair@286: ohair@286: import org.xml.sax.Locator; ohair@286: ohair@286: /** ohair@286: * Root of the XML Schema binder. ohair@286: * ohair@286: *
ohair@286: * ohair@286: * @author Kohsuke Kawaguchi ohair@286: */ ohair@286: public class BGMBuilder extends BindingComponent { ohair@286: ohair@286: /** ohair@286: * Entry point. ohair@286: */ ohair@286: public static Model build( XSSchemaSet _schemas, JCodeModel codeModel, ohair@286: ErrorReceiver _errorReceiver, Options opts ) { ohair@286: // set up a ring ohair@286: final Ring old = Ring.begin(); ohair@286: try { ohair@286: ErrorReceiverFilter ef = new ErrorReceiverFilter(_errorReceiver); ohair@286: ohair@286: Ring.add(XSSchemaSet.class,_schemas); ohair@286: Ring.add(codeModel); ohair@286: Model model = new Model(opts, codeModel, null/*set later*/, opts.classNameAllocator, _schemas); ohair@286: Ring.add(model); ohair@286: Ring.add(ErrorReceiver.class,ef); ohair@286: Ring.add(CodeModelClassFactory.class,new CodeModelClassFactory(ef)); ohair@286: ohair@286: BGMBuilder builder = new BGMBuilder(opts.defaultPackage,opts.defaultPackage2, ohair@286: opts.isExtensionMode(),opts.getFieldRendererFactory(), opts.activePlugins); ohair@286: builder._build(); ohair@286: ohair@286: if(ef.hadError()) return null; ohair@286: else return model; ohair@286: } finally { ohair@286: Ring.end(old); ohair@286: } ohair@286: } ohair@286: ohair@286: ohair@286: /** ohair@286: * True if the compiler is running in the extension mode ohair@286: * (as opposed to the strict conformance mode.) ohair@286: */ ohair@286: public final boolean inExtensionMode; ohair@286: ohair@286: /** ohair@286: * If this is non-null, this package name takes over ohair@286: * all the schema customizations. ohair@286: */ ohair@286: public final String defaultPackage1; ohair@286: ohair@286: /** ohair@286: * If this is non-null, this package name will be ohair@286: * used when no customization is specified. ohair@286: */ ohair@286: public final String defaultPackage2; ohair@286: ohair@286: private final BindGreen green = Ring.get(BindGreen.class); ohair@286: private final BindPurple purple = Ring.get(BindPurple.class); ohair@286: ohair@286: public final Model model = Ring.get(Model.class); ohair@286: ohair@286: public final FieldRendererFactory fieldRendererFactory; ohair@286: ohair@286: /** ohair@286: * Lazily computed {@link RefererFinder}. ohair@286: * ohair@286: * @see #getReferer ohair@286: */ ohair@286: private RefererFinder refFinder; ohair@286: ohair@286: private List
ohair@286: * This object should be used to perform any name conversion
ohair@286: * needs, instead of the JJavaName class in CodeModel.
ohair@286: */
ohair@286: public NameConverter getNameConverter() { return model.getNameConverter(); }
ohair@286:
ohair@286: /** Fill-in the contents of each classes. */
ohair@286: private void buildContents() {
ohair@286: ClassSelector cs = getClassSelector();
ohair@286: SimpleTypeBuilder stb = Ring.get(SimpleTypeBuilder.class);
ohair@286:
ohair@286: for( XSSchema s : Ring.get(XSSchemaSet.class).getSchemas() ) {
ohair@286: BISchemaBinding sb = getBindInfo(s).get(BISchemaBinding.class);
ohair@286:
ohair@286: if(sb!=null && !sb.map) {
ohair@286: sb.markAsAcknowledged();
ohair@286: continue; // no mapping for this package
ohair@286: }
ohair@286:
ohair@286: getClassSelector().pushClassScope( new CClassInfoParent.Package(
ohair@286: getClassSelector().getPackage(s.getTargetNamespace())) );
ohair@286:
ohair@286: checkMultipleSchemaBindings(s);
ohair@286: processPackageJavadoc(s);
ohair@286: populate(s.getAttGroupDecls(),s);
ohair@286: populate(s.getAttributeDecls(),s);
ohair@286: populate(s.getElementDecls(),s);
ohair@286: populate(s.getModelGroupDecls(),s);
ohair@286:
ohair@286: // fill in typeUses
ohair@286: for (XSType t : s.getTypes().values()) {
ohair@286: stb.refererStack.push(t);
ohair@286: model.typeUses().put( getName(t), cs.bindToType(t,s) );
ohair@286: stb.refererStack.pop();
ohair@286: }
ohair@286:
ohair@286: getClassSelector().popClassScope();
ohair@286: }
ohair@286: }
ohair@286:
ohair@286: /** Reports an error if there are more than one jaxb:schemaBindings customization. */
ohair@286: private void checkMultipleSchemaBindings( XSSchema schema ) {
ohair@286: ArrayListpackage.html
if the customization
ohair@286: * says so.
ohair@286: */
ohair@286: private void processPackageJavadoc( XSSchema s ) {
ohair@286: // look for the schema-wide customization
ohair@286: BISchemaBinding cust = getBindInfo(s).get(BISchemaBinding.class);
ohair@286: if(cust==null) return; // not present
ohair@286:
ohair@286: cust.markAsAcknowledged();
ohair@286: if( cust.getJavadoc()==null ) return; // no javadoc customization
ohair@286:
ohair@286: // produce a HTML file
ohair@286: JTextFile html = new JTextFile("package.html");
ohair@286: html.setContents(cust.getJavadoc());
ohair@286: getClassSelector().getPackage(s.getTargetNamespace()).addResourceFile(html);
ohair@286: }
ohair@286:
ohair@286:
ohair@286:
ohair@286:
ohair@286:
ohair@286:
ohair@286: /**
ohair@286: * Gets or creates the BindInfo object associated to a schema component.
ohair@286: *
ohair@286: * @return
ohair@286: * Always return a non-null valid BindInfo object.
ohair@286: * Even if no declaration was specified, this method creates
ohair@286: * a new BindInfo so that new decls can be added.
ohair@286: */
ohair@286: public BindInfo getOrCreateBindInfo( XSComponent schemaComponent ) {
ohair@286:
ohair@286: BindInfo bi = _getBindInfoReadOnly(schemaComponent);
ohair@286: if(bi!=null) return bi;
ohair@286:
ohair@286: // XSOM is read-only, so we cannot add new annotations.
ohair@286: // for components that didn't have annotations,
ohair@286: // we maintain an external map.
ohair@286: bi = new BindInfo();
ohair@286: bi.setOwner(this,schemaComponent);
ohair@286: externalBindInfos.put(schemaComponent,bi);
ohair@286: return bi;
ohair@286: }
ohair@286:
ohair@286:
ohair@286: /**
ohair@286: * Used as a constant instance to represent the empty {@link BindInfo}.
ohair@286: */
ohair@286: private final BindInfo emptyBindInfo = new BindInfo();
ohair@286:
ohair@286: /**
ohair@286: * Gets the BindInfo object associated to a schema component.
ohair@286: *
ohair@286: * @return
ohair@286: * always return a valid {@link BindInfo} object. If none
ohair@286: * is specified for the given component, a dummy empty BindInfo
ohair@286: * will be returned.
ohair@286: */
ohair@286: public BindInfo getBindInfo( XSComponent schemaComponent ) {
ohair@286: BindInfo bi = _getBindInfoReadOnly(schemaComponent);
ohair@286: if(bi!=null) return bi;
ohair@286: else return emptyBindInfo;
ohair@286: }
ohair@286:
ohair@286: /**
ohair@286: * Gets the BindInfo object associated to a schema component.
ohair@286: *
ohair@286: * @return
ohair@286: * null if no bind info is associated to this schema component.
ohair@286: */
ohair@286: private BindInfo _getBindInfoReadOnly( XSComponent schemaComponent ) {
ohair@286:
ohair@286: BindInfo bi = externalBindInfos.get(schemaComponent);
ohair@286: if(bi!=null) return bi;
ohair@286:
ohair@286: XSAnnotation annon = schemaComponent.getAnnotation();
ohair@286: if(annon!=null) {
ohair@286: bi = (BindInfo)annon.getAnnotation();
ohair@286: if(bi!=null) {
ohair@286: if(bi.getOwner()==null)
ohair@286: bi.setOwner(this,schemaComponent);
ohair@286: return bi;
ohair@286: }
ohair@286: }
ohair@286:
ohair@286: return null;
ohair@286: }
ohair@286:
ohair@286: /**
ohair@286: * A map that stores binding declarations augmented by XJC.
ohair@286: */
ohair@286: private final Map