All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.tools.xjc.reader.xmlschema.BGMBuilder Maven / Gradle / Ivy

The newest version!
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 * 
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License. You can obtain
 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
 * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
 * Sun designates this particular file as subject to the "Classpath" exception
 * as provided by Sun in the GPL Version 2 section of the License file that
 * accompanied this code.  If applicable, add the following below the License
 * Header, with the fields enclosed by brackets [] replaced by your own
 * identifying information: "Portions Copyrighted [year]
 * [name of copyright owner]"
 * 
 * Contributor(s):
 * 
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

package com.sun.tools.xjc.reader.xmlschema;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.xml.bind.DatatypeConverter;
import javax.xml.namespace.QName;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;

import com.sun.codemodel.JCodeModel;
import com.sun.codemodel.fmt.JTextFile;
import com.sun.istack.NotNull;
import com.sun.istack.Nullable;
import com.sun.tools.xjc.ErrorReceiver;
import com.sun.tools.xjc.Options;
import com.sun.tools.xjc.generator.bean.field.FieldRendererFactory;
import com.sun.tools.xjc.model.CClassInfoParent;
import com.sun.tools.xjc.model.Model;
import com.sun.tools.xjc.reader.ModelChecker;
import com.sun.tools.xjc.reader.Ring;
import com.sun.tools.xjc.reader.xmlschema.bindinfo.BIDeclaration;
import com.sun.tools.xjc.reader.xmlschema.bindinfo.BIDom;
import com.sun.tools.xjc.reader.xmlschema.bindinfo.BIGlobalBinding;
import com.sun.tools.xjc.reader.xmlschema.bindinfo.BISchemaBinding;
import com.sun.tools.xjc.reader.xmlschema.bindinfo.BISerializable;
import com.sun.tools.xjc.reader.xmlschema.bindinfo.BindInfo;
import com.sun.tools.xjc.util.CodeModelClassFactory;
import com.sun.tools.xjc.util.ErrorReceiverFilter;
import com.sun.xml.bind.DatatypeConverterImpl;
import com.sun.xml.bind.api.impl.NameConverter;
import com.sun.xml.xsom.XSAnnotation;
import com.sun.xml.xsom.XSAttributeUse;
import com.sun.xml.xsom.XSComponent;
import com.sun.xml.xsom.XSDeclaration;
import com.sun.xml.xsom.XSParticle;
import com.sun.xml.xsom.XSSchema;
import com.sun.xml.xsom.XSSchemaSet;
import com.sun.xml.xsom.XSSimpleType;
import com.sun.xml.xsom.XSTerm;
import com.sun.xml.xsom.XSType;
import com.sun.xml.xsom.XSWildcard;
import com.sun.xml.xsom.util.XSFinder;

import org.xml.sax.Locator;

/**
 * Root of the XML Schema binder.
 * 
 * 
* * @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()); 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; protected BGMBuilder(String defaultPackage1, String defaultPackage2, boolean _inExtensionMode, FieldRendererFactory fieldRendererFactory) { this.inExtensionMode = _inExtensionMode; this.defaultPackage1 = defaultPackage1; this.defaultPackage2 = defaultPackage2; this.fieldRendererFactory = fieldRendererFactory; DatatypeConverter.setDatatypeConverter(DatatypeConverterImpl.theInstance); 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(); } /** 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; if(globalBinding==null) { globalBinding = gb; globalBinding.markAsAcknowledged(); } else { // acknowledge this customization and report an error // otherwise the user will see "customization is attached to a wrong place" error, // which is incorrect gb.markAsAcknowledged(); 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. * *

* 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 locations = new ArrayList(); 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 col, XSSchema schema ) { ClassSelector cs = getClassSelector(); for( XSComponent sc : col.values() ) cs.bindToType(sc,schema); } /** * Generates package.html 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 externalBindInfos = new HashMap(); /** * 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() { public Boolean attributeUse(XSAttributeUse use) { // attribute use always maps to a property return true; } public Boolean simpleType(XSSimpleType xsSimpleType) { // simple type always maps to a type, hence we should take purple return true; } 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) identityTransformer = TransformerFactory.newInstance().newTransformer(); return identityTransformer; } catch (TransformerConfigurationException e) { throw new Error(e); // impossible } } /** * Find all types that refer to the given complex type. */ public Set 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; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy