1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/jaxws_classes/com/sun/tools/internal/xjc/model/Model.java Tue Mar 06 16:09:35 2012 -0800 1.3 @@ -0,0 +1,491 @@ 1.4 +/* 1.5 + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Oracle designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Oracle in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.25 + * or visit www.oracle.com if you need additional information or have any 1.26 + * questions. 1.27 + */ 1.28 + 1.29 +package com.sun.tools.internal.xjc.model; 1.30 + 1.31 +import java.util.Collections; 1.32 +import java.util.HashMap; 1.33 +import java.util.HashSet; 1.34 +import java.util.Iterator; 1.35 +import java.util.LinkedHashMap; 1.36 +import java.util.Map; 1.37 +import java.util.Set; 1.38 + 1.39 +import javax.xml.bind.annotation.XmlAttribute; 1.40 +import javax.xml.bind.annotation.XmlNsForm; 1.41 +import javax.xml.bind.annotation.XmlTransient; 1.42 +import javax.xml.namespace.QName; 1.43 +import javax.xml.transform.Result; 1.44 + 1.45 +import com.sun.codemodel.internal.JClass; 1.46 +import com.sun.codemodel.internal.JCodeModel; 1.47 +import com.sun.codemodel.internal.JPackage; 1.48 +import com.sun.tools.internal.xjc.ErrorReceiver; 1.49 +import com.sun.tools.internal.xjc.Options; 1.50 +import com.sun.tools.internal.xjc.Plugin; 1.51 +import com.sun.tools.internal.xjc.api.ClassNameAllocator; 1.52 +import com.sun.tools.internal.xjc.generator.bean.BeanGenerator; 1.53 +import com.sun.tools.internal.xjc.generator.bean.ImplStructureStrategy; 1.54 +import com.sun.tools.internal.xjc.model.nav.NClass; 1.55 +import com.sun.tools.internal.xjc.model.nav.NType; 1.56 +import com.sun.tools.internal.xjc.model.nav.NavigatorImpl; 1.57 +import com.sun.tools.internal.xjc.outline.Outline; 1.58 +import com.sun.tools.internal.xjc.reader.xmlschema.Messages; 1.59 +import com.sun.tools.internal.xjc.util.ErrorReceiverFilter; 1.60 +import com.sun.xml.internal.bind.api.impl.NameConverter; 1.61 +import com.sun.xml.internal.bind.v2.model.core.Ref; 1.62 +import com.sun.xml.internal.bind.v2.model.core.TypeInfoSet; 1.63 +import com.sun.xml.internal.bind.v2.model.nav.Navigator; 1.64 +import com.sun.xml.internal.bind.v2.util.FlattenIterator; 1.65 +import com.sun.xml.internal.xsom.XSComponent; 1.66 +import com.sun.xml.internal.xsom.XSSchemaSet; 1.67 + 1.68 +import org.xml.sax.Locator; 1.69 +import org.xml.sax.SAXException; 1.70 +import org.xml.sax.helpers.LocatorImpl; 1.71 + 1.72 +/** 1.73 + * Root of the object model that represents the code that needs to be generated. 1.74 + * 1.75 + * <p> 1.76 + * A {@link Model} is a schema language neutral representation of the 1.77 + * result of a schema parsing. The back-end then works against this model 1.78 + * to turn this into a series of Java source code. 1.79 + * 1.80 + * @author Kohsuke Kawaguchi 1.81 + */ 1.82 +public final class Model implements TypeInfoSet<NType,NClass,Void,Void>, CCustomizable { 1.83 + 1.84 + /** 1.85 + * Generated beans. 1.86 + */ 1.87 + private final Map<NClass,CClassInfo> beans = new LinkedHashMap<NClass,CClassInfo>(); 1.88 + 1.89 + /** 1.90 + * Generated enums. 1.91 + */ 1.92 + private final Map<NClass,CEnumLeafInfo> enums = new LinkedHashMap<NClass,CEnumLeafInfo>(); 1.93 + 1.94 + /** 1.95 + * The element mappings. 1.96 + */ 1.97 + private final Map<NClass/*scope*/,Map<QName,CElementInfo>> elementMappings = 1.98 + new HashMap<NClass,Map<QName,CElementInfo>>(); 1.99 + 1.100 + private final Iterable<? extends CElementInfo> allElements = 1.101 + new Iterable<CElementInfo>() { 1.102 + public Iterator<CElementInfo> iterator() { 1.103 + return new FlattenIterator<CElementInfo>(elementMappings.values()); 1.104 + } 1.105 + }; 1.106 + 1.107 + /** 1.108 + * {@link TypeUse}s for all named types. 1.109 + * <p> 1.110 + * I really don't want to promote the notion of a 'type' in any place except in the XML Schema code, 1.111 + * but this needs to be exposed for JAX-RPC. A reference to a named XML type will be converted into 1.112 + * a reference to a Java type with annotations. 1.113 + */ 1.114 + private final Map<QName,TypeUse> typeUses = new LinkedHashMap<QName, TypeUse>(); 1.115 + 1.116 + /** 1.117 + * {@link NameConverter} to be used. 1.118 + */ 1.119 + private NameConverter nameConverter; 1.120 + 1.121 + /** 1.122 + * Single linked list that connects all {@link CCustomizations} that belong to this model. 1.123 + * 1.124 + * @see CCustomizations#next 1.125 + */ 1.126 + /*package*/ CCustomizations customizations; 1.127 + 1.128 + /** 1.129 + * This field controls the generation of package level annotations for s2j 1.130 + */ 1.131 + private boolean packageLevelAnnotations = true; 1.132 + 1.133 + /** 1.134 + * If this model was built from XML Schema, this field 1.135 + * stores the root object of the parse schema model. 1.136 + * Otherwise null. 1.137 + * 1.138 + * @sine 2.1.1 1.139 + */ 1.140 + public final XSSchemaSet schemaComponent; 1.141 + 1.142 + private CCustomizations gloablCustomizations = new CCustomizations(); 1.143 + 1.144 + /** 1.145 + * @param nc 1.146 + * Usually this should be set in the constructor, but we do allow this parameter 1.147 + * to be initially null, and then set later. 1.148 + * @param schemaComponent 1.149 + * The source schema model, if this is built from XSD. 1.150 + */ 1.151 + public Model( Options opts, JCodeModel cm, NameConverter nc, ClassNameAllocator allocator, XSSchemaSet schemaComponent ) { 1.152 + this.options = opts; 1.153 + this.codeModel = cm; 1.154 + this.nameConverter = nc; 1.155 + this.defaultSymbolSpace = new SymbolSpace(codeModel); 1.156 + defaultSymbolSpace.setType(codeModel.ref(Object.class)); 1.157 + 1.158 + elementMappings.put(null,new HashMap<QName,CElementInfo>()); 1.159 + 1.160 + if(opts.automaticNameConflictResolution) 1.161 + allocator = new AutoClassNameAllocator(allocator); 1.162 + this.allocator = new ClassNameAllocatorWrapper(allocator); 1.163 + this.schemaComponent = schemaComponent; 1.164 + this.gloablCustomizations.setParent(this,this); 1.165 + } 1.166 + 1.167 + public void setNameConverter(NameConverter nameConverter) { 1.168 + assert this.nameConverter==null; 1.169 + assert nameConverter!=null; 1.170 + this.nameConverter = nameConverter; 1.171 + } 1.172 + 1.173 + /** 1.174 + * Gets the name converter that shall be used to parse XML names into Java names. 1.175 + */ 1.176 + public final NameConverter getNameConverter() { 1.177 + return nameConverter; 1.178 + } 1.179 + 1.180 + public boolean isPackageLevelAnnotations() { 1.181 + return packageLevelAnnotations; 1.182 + } 1.183 + 1.184 + public void setPackageLevelAnnotations(boolean packageLevelAnnotations) { 1.185 + this.packageLevelAnnotations = packageLevelAnnotations; 1.186 + } 1.187 + 1.188 + /** 1.189 + * This model uses this code model exclusively. 1.190 + */ 1.191 + @XmlTransient 1.192 + public final JCodeModel codeModel; 1.193 + 1.194 + /** 1.195 + * Command-line options used for building this model. 1.196 + */ 1.197 + public final Options options; 1.198 + 1.199 + /** 1.200 + * True to generate serializable classes. 1.201 + */ 1.202 + @XmlAttribute 1.203 + public boolean serializable; 1.204 + 1.205 + /** 1.206 + * serial version UID to be generated. 1.207 + * 1.208 + * null if not to generate serialVersionUID field. 1.209 + */ 1.210 + @XmlAttribute 1.211 + public Long serialVersionUID; 1.212 + 1.213 + /** 1.214 + * If non-null, all the generated classes should eventually derive from this class. 1.215 + */ 1.216 + @XmlTransient 1.217 + public JClass rootClass; 1.218 + 1.219 + /** 1.220 + * If non-null, all the generated interfaces should eventually derive from this interface. 1.221 + */ 1.222 + @XmlTransient 1.223 + public JClass rootInterface; 1.224 + 1.225 + /** 1.226 + * Specifies the code generation strategy. 1.227 + * Must not be null. 1.228 + */ 1.229 + public ImplStructureStrategy strategy = ImplStructureStrategy.BEAN_ONLY; 1.230 + 1.231 + /** 1.232 + * This allocator has the final say on deciding the class name. 1.233 + * Must not be null. 1.234 + * 1.235 + * <p> 1.236 + * Model classes are responsible for using the allocator. 1.237 + * This allocator interaction should be transparent to the user/builder 1.238 + * of the model. 1.239 + */ 1.240 + /*package*/ final ClassNameAllocatorWrapper allocator; 1.241 + 1.242 + /** 1.243 + * Default ID/IDREF symbol space. Any ID/IDREF without explicit 1.244 + * reference to a symbol space is assumed to use this default 1.245 + * symbol space. 1.246 + */ 1.247 + @XmlTransient 1.248 + public final SymbolSpace defaultSymbolSpace; 1.249 + 1.250 + /** All the defined {@link SymbolSpace}s keyed by their name. */ 1.251 + private final Map<String,SymbolSpace> symbolSpaces = new HashMap<String,SymbolSpace>(); 1.252 + 1.253 + public SymbolSpace getSymbolSpace( String name ) { 1.254 + SymbolSpace ss = symbolSpaces.get(name); 1.255 + if(ss==null) 1.256 + symbolSpaces.put(name,ss=new SymbolSpace(codeModel)); 1.257 + return ss; 1.258 + } 1.259 + 1.260 + /** 1.261 + * Fully-generate the source code into the given model. 1.262 + * 1.263 + * @return 1.264 + * null if there was any errors. Otherwise it returns a valid 1.265 + * {@link Outline} object, which captures how the model objects 1.266 + * are mapped to the generated source code. 1.267 + * <p> 1.268 + * Add-ons can use those information to further augment the generated 1.269 + * source code. 1.270 + */ 1.271 + public Outline generateCode(Options opt,ErrorReceiver receiver) { 1.272 + ErrorReceiverFilter ehf = new ErrorReceiverFilter(receiver); 1.273 + 1.274 + // run extensions // moved to BGMBuilder._build() - issue with hyperjaxb3 1.275 +// for( Plugin ma : opt.activePlugins ) 1.276 +// ma.postProcessModel(this,ehf); 1.277 + 1.278 + Outline o = BeanGenerator.generate(this, ehf); 1.279 + 1.280 + try {// run extensions 1.281 + for( Plugin ma : opt.activePlugins ) 1.282 + ma.run(o,opt,ehf); 1.283 + } catch (SAXException e) { 1.284 + // fatal error. error should have been reported 1.285 + return null; 1.286 + } 1.287 + 1.288 + // check for unused plug-in customizations. 1.289 + // these can be only checked after the plug-ins run, so it's here. 1.290 + // the JAXB bindings are checked by XMLSchema's builder. 1.291 + Set<CCustomizations> check = new HashSet<CCustomizations>(); 1.292 + for( CCustomizations c=customizations; c!=null; c=c.next ) { 1.293 + if(!check.add(c)) { 1.294 + throw new AssertionError(); // detect a loop 1.295 + } 1.296 + for (CPluginCustomization p : c) { 1.297 + if(!p.isAcknowledged()) { 1.298 + ehf.error( 1.299 + p.locator, 1.300 + Messages.format( 1.301 + Messages.ERR_UNACKNOWLEDGED_CUSTOMIZATION, 1.302 + p.element.getNodeName() 1.303 + )); 1.304 + ehf.error( 1.305 + c.getOwner().getLocator(), 1.306 + Messages.format( 1.307 + Messages.ERR_UNACKNOWLEDGED_CUSTOMIZATION_LOCATION)); 1.308 + } 1.309 + } 1.310 + } 1.311 + 1.312 + if(ehf.hadError()) 1.313 + o = null; 1.314 + return o; 1.315 + } 1.316 + 1.317 + /** 1.318 + * Represents the "top-level binding". 1.319 + * 1.320 + * <p> 1.321 + * This is used to support the use of a schema inside WSDL. 1.322 + * For XML Schema, the top-level binding is a map from 1.323 + * global element declarations to its representation class. 1.324 + * 1.325 + * <p> 1.326 + * For other schema languages, it should follow the appendicies in 1.327 + * WSDL (but in practice no one would use WSDL with a schema language 1.328 + * other than XML Schema, so it doesn't really matter.) 1.329 + * 1.330 + * <p> 1.331 + * This needs to be filled by the front-end. 1.332 + */ 1.333 + public final Map<QName,CClassInfo> createTopLevelBindings() { 1.334 + Map<QName,CClassInfo> r = new HashMap<QName,CClassInfo>(); 1.335 + for( CClassInfo b : beans().values() ) { 1.336 + if(b.isElement()) 1.337 + r.put(b.getElementName(),b); 1.338 + } 1.339 + return r; 1.340 + } 1.341 + 1.342 + public Navigator<NType,NClass,Void,Void> getNavigator() { 1.343 + return NavigatorImpl.theInstance; 1.344 + } 1.345 + 1.346 + public CNonElement getTypeInfo(NType type) { 1.347 + CBuiltinLeafInfo leaf = CBuiltinLeafInfo.LEAVES.get(type); 1.348 + if(leaf!=null) return leaf; 1.349 + 1.350 + return getClassInfo(getNavigator().asDecl(type)); 1.351 + } 1.352 + 1.353 + public CBuiltinLeafInfo getAnyTypeInfo() { 1.354 + return CBuiltinLeafInfo.ANYTYPE; 1.355 + } 1.356 + 1.357 + public CNonElement getTypeInfo(Ref<NType,NClass> ref) { 1.358 + // TODO: handle XmlValueList 1.359 + assert !ref.valueList; 1.360 + return getTypeInfo(ref.type); 1.361 + } 1.362 + 1.363 + public Map<NClass,CClassInfo> beans() { 1.364 + return beans; 1.365 + } 1.366 + 1.367 + public Map<NClass,CEnumLeafInfo> enums() { 1.368 + return enums; 1.369 + } 1.370 + 1.371 + public Map<QName,TypeUse> typeUses() { 1.372 + return typeUses; 1.373 + } 1.374 + 1.375 + /** 1.376 + * No array mapping generation for XJC. 1.377 + */ 1.378 + public Map<NType, ? extends CArrayInfo> arrays() { 1.379 + return Collections.emptyMap(); 1.380 + } 1.381 + 1.382 + public Map<NType, ? extends CBuiltinLeafInfo> builtins() { 1.383 + return CBuiltinLeafInfo.LEAVES; 1.384 + } 1.385 + 1.386 + public CClassInfo getClassInfo(NClass t) { 1.387 + return beans.get(t); 1.388 + } 1.389 + 1.390 + public CElementInfo getElementInfo(NClass scope,QName name) { 1.391 + Map<QName,CElementInfo> m = elementMappings.get(scope); 1.392 + if(m!=null) { 1.393 + CElementInfo r = m.get(name); 1.394 + if(r!=null) return r; 1.395 + } 1.396 + return elementMappings.get(null).get(name); 1.397 + } 1.398 + 1.399 + public Map<QName,CElementInfo> getElementMappings(NClass scope) { 1.400 + return elementMappings.get(scope); 1.401 + } 1.402 + 1.403 + public Iterable<? extends CElementInfo> getAllElements() { 1.404 + return allElements; 1.405 + } 1.406 + 1.407 + /** 1.408 + * @deprecated 1.409 + * Always return null. Perhaps you are interested in {@link #schemaComponent}? 1.410 + */ 1.411 + public XSComponent getSchemaComponent() { 1.412 + return null; 1.413 + } 1.414 + 1.415 + /** 1.416 + * @deprecated 1.417 + * No line number available for the "root" component. 1.418 + */ 1.419 + public Locator getLocator() { 1.420 + LocatorImpl r = new LocatorImpl(); 1.421 + r.setLineNumber(-1); 1.422 + r.setColumnNumber(-1); 1.423 + return r; 1.424 + } 1.425 + 1.426 + /** 1.427 + * Gets the global customizations. 1.428 + */ 1.429 + public CCustomizations getCustomizations() { 1.430 + return gloablCustomizations; 1.431 + } 1.432 + 1.433 + /** 1.434 + * Not implemented in the compile-time model. 1.435 + */ 1.436 + public Map<String, String> getXmlNs(String namespaceUri) { 1.437 + return Collections.emptyMap(); 1.438 + } 1.439 + 1.440 + public Map<String, String> getSchemaLocations() { 1.441 + return Collections.emptyMap(); 1.442 + } 1.443 + 1.444 + public XmlNsForm getElementFormDefault(String nsUri) { 1.445 + throw new UnsupportedOperationException(); 1.446 + } 1.447 + 1.448 + public XmlNsForm getAttributeFormDefault(String nsUri) { 1.449 + throw new UnsupportedOperationException(); 1.450 + } 1.451 + 1.452 + public void dump(Result out) { 1.453 + // TODO 1.454 + throw new UnsupportedOperationException(); 1.455 + } 1.456 + 1.457 + /*package*/ void add( CEnumLeafInfo e ) { 1.458 + enums.put( e.getClazz(), e ); 1.459 + } 1.460 + 1.461 + /*package*/ void add( CClassInfo ci ) { 1.462 + beans.put( ci.getClazz(), ci ); 1.463 + } 1.464 + 1.465 + /*package*/ void add( CElementInfo ei ) { 1.466 + NClass clazz = null; 1.467 + if(ei.getScope()!=null) 1.468 + clazz = ei.getScope().getClazz(); 1.469 + 1.470 + Map<QName,CElementInfo> m = elementMappings.get(clazz); 1.471 + if(m==null) 1.472 + elementMappings.put(clazz,m=new HashMap<QName,CElementInfo>()); 1.473 + m.put(ei.getElementName(),ei); 1.474 + } 1.475 + 1.476 + 1.477 + private final Map<JPackage,CClassInfoParent.Package> cache = new HashMap<JPackage,CClassInfoParent.Package>(); 1.478 + 1.479 + public CClassInfoParent.Package getPackage(JPackage pkg) { 1.480 + CClassInfoParent.Package r = cache.get(pkg); 1.481 + if(r==null) 1.482 + cache.put(pkg,r=new CClassInfoParent.Package(pkg)); 1.483 + return r; 1.484 + } 1.485 + 1.486 + /*package*/ static final Locator EMPTY_LOCATOR; 1.487 + 1.488 + static { 1.489 + LocatorImpl l = new LocatorImpl(); 1.490 + l.setColumnNumber(-1); 1.491 + l.setLineNumber(-1); 1.492 + EMPTY_LOCATOR = l; 1.493 + } 1.494 +}