Tue, 09 Apr 2013 14:51:13 +0100
8010393: Update JAX-WS RI to 2.2.9-b12941
Reviewed-by: alanb, erikj
Contributed-by: miroslav.kos@oracle.com, martin.grebac@oracle.com
aoqi@0 | 1 | /* |
aoqi@0 | 2 | * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. |
aoqi@0 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
aoqi@0 | 4 | * |
aoqi@0 | 5 | * This code is free software; you can redistribute it and/or modify it |
aoqi@0 | 6 | * under the terms of the GNU General Public License version 2 only, as |
aoqi@0 | 7 | * published by the Free Software Foundation. Oracle designates this |
aoqi@0 | 8 | * particular file as subject to the "Classpath" exception as provided |
aoqi@0 | 9 | * by Oracle in the LICENSE file that accompanied this code. |
aoqi@0 | 10 | * |
aoqi@0 | 11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
aoqi@0 | 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
aoqi@0 | 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
aoqi@0 | 14 | * version 2 for more details (a copy is included in the LICENSE file that |
aoqi@0 | 15 | * accompanied this code). |
aoqi@0 | 16 | * |
aoqi@0 | 17 | * You should have received a copy of the GNU General Public License version |
aoqi@0 | 18 | * 2 along with this work; if not, write to the Free Software Foundation, |
aoqi@0 | 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
aoqi@0 | 20 | * |
aoqi@0 | 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
aoqi@0 | 22 | * or visit www.oracle.com if you need additional information or have any |
aoqi@0 | 23 | * questions. |
aoqi@0 | 24 | */ |
aoqi@0 | 25 | |
aoqi@0 | 26 | package com.sun.tools.internal.xjc.reader.xmlschema; |
aoqi@0 | 27 | |
aoqi@0 | 28 | import java.io.StringWriter; |
aoqi@0 | 29 | import java.util.HashMap; |
aoqi@0 | 30 | import java.util.HashSet; |
aoqi@0 | 31 | import java.util.Map; |
aoqi@0 | 32 | import java.util.Set; |
aoqi@0 | 33 | import java.util.Stack; |
aoqi@0 | 34 | |
aoqi@0 | 35 | import com.sun.codemodel.internal.JCodeModel; |
aoqi@0 | 36 | import com.sun.codemodel.internal.JJavaName; |
aoqi@0 | 37 | import com.sun.codemodel.internal.JPackage; |
aoqi@0 | 38 | import com.sun.codemodel.internal.util.JavadocEscapeWriter; |
aoqi@0 | 39 | import com.sun.istack.internal.NotNull; |
aoqi@0 | 40 | import com.sun.tools.internal.xjc.model.CBuiltinLeafInfo; |
aoqi@0 | 41 | import com.sun.tools.internal.xjc.model.CClassInfo; |
aoqi@0 | 42 | import com.sun.tools.internal.xjc.model.CClassInfoParent; |
aoqi@0 | 43 | import com.sun.tools.internal.xjc.model.CElement; |
aoqi@0 | 44 | import com.sun.tools.internal.xjc.model.CElementInfo; |
aoqi@0 | 45 | import com.sun.tools.internal.xjc.model.CTypeInfo; |
aoqi@0 | 46 | import com.sun.tools.internal.xjc.model.TypeUse; |
aoqi@0 | 47 | import com.sun.tools.internal.xjc.model.CClass; |
aoqi@0 | 48 | import com.sun.tools.internal.xjc.model.CNonElement; |
aoqi@0 | 49 | import com.sun.tools.internal.xjc.reader.Ring; |
aoqi@0 | 50 | import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIProperty; |
aoqi@0 | 51 | import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BISchemaBinding; |
aoqi@0 | 52 | import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.LocalScoping; |
aoqi@0 | 53 | import com.sun.xml.internal.bind.v2.WellKnownNamespace; |
aoqi@0 | 54 | import com.sun.xml.internal.xsom.XSComplexType; |
aoqi@0 | 55 | import com.sun.xml.internal.xsom.XSComponent; |
aoqi@0 | 56 | import com.sun.xml.internal.xsom.XSDeclaration; |
aoqi@0 | 57 | import com.sun.xml.internal.xsom.XSElementDecl; |
aoqi@0 | 58 | import com.sun.xml.internal.xsom.XSSchema; |
aoqi@0 | 59 | import com.sun.xml.internal.xsom.XSSchemaSet; |
aoqi@0 | 60 | import com.sun.xml.internal.xsom.XSSimpleType; |
aoqi@0 | 61 | import com.sun.xml.internal.xsom.XSType; |
aoqi@0 | 62 | import com.sun.xml.internal.xsom.impl.util.SchemaWriter; |
aoqi@0 | 63 | import com.sun.xml.internal.xsom.util.ComponentNameFunction; |
aoqi@0 | 64 | |
aoqi@0 | 65 | import org.xml.sax.Locator; |
aoqi@0 | 66 | |
aoqi@0 | 67 | /** |
aoqi@0 | 68 | * Manages association between {@link XSComponent}s and generated |
aoqi@0 | 69 | * {@link CTypeInfo}s. |
aoqi@0 | 70 | * |
aoqi@0 | 71 | * <p> |
aoqi@0 | 72 | * This class determines which component is mapped to (or is not mapped to) |
aoqi@0 | 73 | * what types. |
aoqi@0 | 74 | * |
aoqi@0 | 75 | * @author |
aoqi@0 | 76 | * Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com) |
aoqi@0 | 77 | */ |
aoqi@0 | 78 | public final class ClassSelector extends BindingComponent { |
aoqi@0 | 79 | /** Center of owner classes. */ |
aoqi@0 | 80 | private final BGMBuilder builder = Ring.get(BGMBuilder.class); |
aoqi@0 | 81 | |
aoqi@0 | 82 | |
aoqi@0 | 83 | /** |
aoqi@0 | 84 | * Map from XSComponents to {@link Binding}s. Keeps track of all |
aoqi@0 | 85 | * content interfaces that are already built or being built. |
aoqi@0 | 86 | */ |
aoqi@0 | 87 | private final Map<XSComponent,Binding> bindMap = new HashMap<XSComponent,Binding>(); |
aoqi@0 | 88 | |
aoqi@0 | 89 | /** |
aoqi@0 | 90 | * UGLY HACK. |
aoqi@0 | 91 | * <p> |
aoqi@0 | 92 | * To avoid cyclic dependency between binding elements and types, |
aoqi@0 | 93 | * we need additional markers that tell which elements are definitely not bound |
aoqi@0 | 94 | * to a class. |
aoqi@0 | 95 | * <p> |
aoqi@0 | 96 | * the cyclic dependency is as follows: |
aoqi@0 | 97 | * elements need to bind its types first, because otherwise it can't |
aoqi@0 | 98 | * determine T of JAXBElement<T>. |
aoqi@0 | 99 | * OTOH, types need to know whether its parent is bound to a class to decide |
aoqi@0 | 100 | * which class name to use. |
aoqi@0 | 101 | */ |
aoqi@0 | 102 | /*package*/ final Map<XSComponent,CElementInfo> boundElements = new HashMap<XSComponent,CElementInfo>(); |
aoqi@0 | 103 | |
aoqi@0 | 104 | /** |
aoqi@0 | 105 | * A list of {@link Binding}s object that needs to be built. |
aoqi@0 | 106 | */ |
aoqi@0 | 107 | private final Stack<Binding> bindQueue = new Stack<Binding>(); |
aoqi@0 | 108 | |
aoqi@0 | 109 | /** |
aoqi@0 | 110 | * {@link CClassInfo}s that are already {@link Binding#build() built}. |
aoqi@0 | 111 | */ |
aoqi@0 | 112 | private final Set<CClassInfo> built = new HashSet<CClassInfo>(); |
aoqi@0 | 113 | |
aoqi@0 | 114 | /** |
aoqi@0 | 115 | * Object that determines components that are mapped |
aoqi@0 | 116 | * to classes. |
aoqi@0 | 117 | */ |
aoqi@0 | 118 | private final ClassBinder classBinder; |
aoqi@0 | 119 | |
aoqi@0 | 120 | /** |
aoqi@0 | 121 | * {@link CClassInfoParent}s that determines where a new class |
aoqi@0 | 122 | * should be created. |
aoqi@0 | 123 | */ |
aoqi@0 | 124 | private final Stack<CClassInfoParent> classScopes = new Stack<CClassInfoParent>(); |
aoqi@0 | 125 | |
aoqi@0 | 126 | /** |
aoqi@0 | 127 | * The component that is being bound to {@link #currentBean}. |
aoqi@0 | 128 | */ |
aoqi@0 | 129 | private XSComponent currentRoot; |
aoqi@0 | 130 | /** |
aoqi@0 | 131 | * The bean representation we are binding right now. |
aoqi@0 | 132 | */ |
aoqi@0 | 133 | private CClassInfo currentBean; |
aoqi@0 | 134 | |
aoqi@0 | 135 | |
aoqi@0 | 136 | private final class Binding { |
aoqi@0 | 137 | private final XSComponent sc; |
aoqi@0 | 138 | private final CTypeInfo bean; |
aoqi@0 | 139 | |
aoqi@0 | 140 | public Binding(XSComponent sc, CTypeInfo bean) { |
aoqi@0 | 141 | this.sc = sc; |
aoqi@0 | 142 | this.bean = bean; |
aoqi@0 | 143 | } |
aoqi@0 | 144 | |
aoqi@0 | 145 | void build() { |
aoqi@0 | 146 | if(!(this.bean instanceof CClassInfo)) |
aoqi@0 | 147 | return; // no need to "build" |
aoqi@0 | 148 | |
aoqi@0 | 149 | CClassInfo bean = (CClassInfo)this.bean; |
aoqi@0 | 150 | |
aoqi@0 | 151 | if(!built.add(bean)) |
aoqi@0 | 152 | return; // already built |
aoqi@0 | 153 | |
aoqi@0 | 154 | for( String reservedClassName : reservedClassNames ) { |
aoqi@0 | 155 | if( bean.getName().equals(reservedClassName) ) { |
aoqi@0 | 156 | getErrorReporter().error( sc.getLocator(), |
aoqi@0 | 157 | Messages.ERR_RESERVED_CLASS_NAME, reservedClassName ); |
aoqi@0 | 158 | break; |
aoqi@0 | 159 | } |
aoqi@0 | 160 | } |
aoqi@0 | 161 | |
aoqi@0 | 162 | // if this schema component is an element declaration |
aoqi@0 | 163 | // and it satisfies a set of conditions specified in the spec, |
aoqi@0 | 164 | // this class will receive a constructor. |
aoqi@0 | 165 | if(needValueConstructor(sc)) { |
aoqi@0 | 166 | // TODO: fragile. There is no guarantee that the property name |
aoqi@0 | 167 | // is in fact "value". |
aoqi@0 | 168 | bean.addConstructor("value"); |
aoqi@0 | 169 | } |
aoqi@0 | 170 | |
aoqi@0 | 171 | if(bean.javadoc==null) |
aoqi@0 | 172 | addSchemaFragmentJavadoc(bean,sc); |
aoqi@0 | 173 | |
aoqi@0 | 174 | // build the body |
aoqi@0 | 175 | if(builder.getGlobalBinding().getFlattenClasses()==LocalScoping.NESTED) |
aoqi@0 | 176 | pushClassScope(bean); |
aoqi@0 | 177 | else |
aoqi@0 | 178 | pushClassScope(bean.parent()); |
aoqi@0 | 179 | XSComponent oldRoot = currentRoot; |
aoqi@0 | 180 | CClassInfo oldBean = currentBean; |
aoqi@0 | 181 | currentRoot = sc; |
aoqi@0 | 182 | currentBean = bean; |
aoqi@0 | 183 | sc.visit(Ring.get(BindRed.class)); |
aoqi@0 | 184 | currentBean = oldBean; |
aoqi@0 | 185 | currentRoot = oldRoot; |
aoqi@0 | 186 | popClassScope(); |
aoqi@0 | 187 | |
aoqi@0 | 188 | // acknowledge property customization on this schema component, |
aoqi@0 | 189 | // since it is OK to have a customization at the point of declaration |
aoqi@0 | 190 | // even when no one is using it. |
aoqi@0 | 191 | BIProperty prop = builder.getBindInfo(sc).get(BIProperty.class); |
aoqi@0 | 192 | if(prop!=null) prop.markAsAcknowledged(); |
aoqi@0 | 193 | } |
aoqi@0 | 194 | } |
aoqi@0 | 195 | |
aoqi@0 | 196 | |
aoqi@0 | 197 | // should be instanciated only from BGMBuilder. |
aoqi@0 | 198 | public ClassSelector() { |
aoqi@0 | 199 | classBinder = new Abstractifier(new DefaultClassBinder()); |
aoqi@0 | 200 | Ring.add(ClassBinder.class,classBinder); |
aoqi@0 | 201 | |
aoqi@0 | 202 | classScopes.push(null); // so that the getClassFactory method returns null |
aoqi@0 | 203 | |
aoqi@0 | 204 | XSComplexType anyType = Ring.get(XSSchemaSet.class).getComplexType(WellKnownNamespace.XML_SCHEMA,"anyType"); |
aoqi@0 | 205 | bindMap.put(anyType,new Binding(anyType,CBuiltinLeafInfo.ANYTYPE)); |
aoqi@0 | 206 | } |
aoqi@0 | 207 | |
aoqi@0 | 208 | /** Gets the current class scope. */ |
aoqi@0 | 209 | public final CClassInfoParent getClassScope() { |
aoqi@0 | 210 | assert !classScopes.isEmpty(); |
aoqi@0 | 211 | return classScopes.peek(); |
aoqi@0 | 212 | } |
aoqi@0 | 213 | |
aoqi@0 | 214 | public final void pushClassScope( CClassInfoParent clsFctry ) { |
aoqi@0 | 215 | assert clsFctry!=null; |
aoqi@0 | 216 | classScopes.push(clsFctry); |
aoqi@0 | 217 | } |
aoqi@0 | 218 | |
aoqi@0 | 219 | public final void popClassScope() { |
aoqi@0 | 220 | classScopes.pop(); |
aoqi@0 | 221 | } |
aoqi@0 | 222 | |
aoqi@0 | 223 | public XSComponent getCurrentRoot() { |
aoqi@0 | 224 | return currentRoot; |
aoqi@0 | 225 | } |
aoqi@0 | 226 | |
aoqi@0 | 227 | public CClassInfo getCurrentBean() { |
aoqi@0 | 228 | return currentBean; |
aoqi@0 | 229 | } |
aoqi@0 | 230 | |
aoqi@0 | 231 | /** |
aoqi@0 | 232 | * Checks if the given component is bound to a class. |
aoqi@0 | 233 | */ |
aoqi@0 | 234 | public final CElement isBound( XSElementDecl x, XSComponent referer ) { |
aoqi@0 | 235 | CElementInfo r = boundElements.get(x); |
aoqi@0 | 236 | if(r!=null) |
aoqi@0 | 237 | return r; |
aoqi@0 | 238 | return bindToType(x,referer); |
aoqi@0 | 239 | } |
aoqi@0 | 240 | |
aoqi@0 | 241 | /** |
aoqi@0 | 242 | * Checks if the given component is being mapped to a type. |
aoqi@0 | 243 | * If so, build that type and return that object. |
aoqi@0 | 244 | * If it is not being mapped to a type item, return null. |
aoqi@0 | 245 | */ |
aoqi@0 | 246 | public CTypeInfo bindToType( XSComponent sc, XSComponent referer ) { |
aoqi@0 | 247 | return _bindToClass(sc,referer,false); |
aoqi@0 | 248 | } |
aoqi@0 | 249 | |
aoqi@0 | 250 | // |
aoqi@0 | 251 | // some schema components are guaranteed to map to a particular CTypeInfo. |
aoqi@0 | 252 | // the following versions capture those constraints in the signature |
aoqi@0 | 253 | // and making the bindToType invocation more type safe. |
aoqi@0 | 254 | // |
aoqi@0 | 255 | |
aoqi@0 | 256 | public CElement bindToType( XSElementDecl e, XSComponent referer ) { |
aoqi@0 | 257 | return (CElement)_bindToClass(e,referer,false); |
aoqi@0 | 258 | } |
aoqi@0 | 259 | |
aoqi@0 | 260 | public CClass bindToType( XSComplexType t, XSComponent referer, boolean cannotBeDelayed ) { |
aoqi@0 | 261 | // this assumption that a complex type always binds to a ClassInfo |
aoqi@0 | 262 | // does not hold for xs:anyType --- our current approach of handling |
aoqi@0 | 263 | // this idiosynchracy is to make sure that xs:anyType doesn't use |
aoqi@0 | 264 | // this codepath. |
aoqi@0 | 265 | return (CClass)_bindToClass(t,referer,cannotBeDelayed); |
aoqi@0 | 266 | } |
aoqi@0 | 267 | |
aoqi@0 | 268 | public TypeUse bindToType( XSType t, XSComponent referer ) { |
aoqi@0 | 269 | if(t instanceof XSSimpleType) { |
aoqi@0 | 270 | return Ring.get(SimpleTypeBuilder.class).build((XSSimpleType)t); |
aoqi@0 | 271 | } else |
aoqi@0 | 272 | return (CNonElement)_bindToClass(t,referer,false); |
aoqi@0 | 273 | } |
aoqi@0 | 274 | |
aoqi@0 | 275 | /** |
aoqi@0 | 276 | * The real meat of the "bindToType" code. |
aoqi@0 | 277 | * |
aoqi@0 | 278 | * @param cannotBeDelayed |
aoqi@0 | 279 | * if the binding of the body of the class cannot be defered |
aoqi@0 | 280 | * and needs to be done immediately. If the flag is false, |
aoqi@0 | 281 | * the binding of the body will be done later, to avoid |
aoqi@0 | 282 | * cyclic binding problem. |
aoqi@0 | 283 | * @param referer |
aoqi@0 | 284 | * The component that refers to <tt>sc</tt>. This can be null, |
aoqi@0 | 285 | * if figuring out the referer is too hard, in which case |
aoqi@0 | 286 | * the error message might be less user friendly. |
aoqi@0 | 287 | */ |
aoqi@0 | 288 | // TODO: consider getting rid of "cannotBeDelayed" |
aoqi@0 | 289 | CTypeInfo _bindToClass( @NotNull XSComponent sc, XSComponent referer, boolean cannotBeDelayed ) { |
aoqi@0 | 290 | // check if this class is already built. |
aoqi@0 | 291 | if(!bindMap.containsKey(sc)) { |
aoqi@0 | 292 | // craete a bind task |
aoqi@0 | 293 | |
aoqi@0 | 294 | // if this is a global declaration, make sure they will be generated |
aoqi@0 | 295 | // under a package. |
aoqi@0 | 296 | boolean isGlobal = false; |
aoqi@0 | 297 | if( sc instanceof XSDeclaration ) { |
aoqi@0 | 298 | isGlobal = ((XSDeclaration)sc).isGlobal(); |
aoqi@0 | 299 | if( isGlobal ) |
aoqi@0 | 300 | pushClassScope( new CClassInfoParent.Package( |
aoqi@0 | 301 | getPackage(((XSDeclaration)sc).getTargetNamespace())) ); |
aoqi@0 | 302 | } |
aoqi@0 | 303 | |
aoqi@0 | 304 | // otherwise check if this component should become a class. |
aoqi@0 | 305 | CElement bean = sc.apply(classBinder); |
aoqi@0 | 306 | |
aoqi@0 | 307 | if( isGlobal ) |
aoqi@0 | 308 | popClassScope(); |
aoqi@0 | 309 | |
aoqi@0 | 310 | if(bean==null) |
aoqi@0 | 311 | return null; |
aoqi@0 | 312 | |
aoqi@0 | 313 | // can this namespace generate a class? |
aoqi@0 | 314 | if (bean instanceof CClassInfo) { |
aoqi@0 | 315 | XSSchema os = sc.getOwnerSchema(); |
aoqi@0 | 316 | BISchemaBinding sb = builder.getBindInfo(os).get(BISchemaBinding.class); |
aoqi@0 | 317 | if(sb!=null && !sb.map) { |
aoqi@0 | 318 | // nope |
aoqi@0 | 319 | getErrorReporter().error(sc.getLocator(), |
aoqi@0 | 320 | Messages.ERR_REFERENCE_TO_NONEXPORTED_CLASS, sc.apply( new ComponentNameFunction() ) ); |
aoqi@0 | 321 | getErrorReporter().error(sb.getLocation(), |
aoqi@0 | 322 | Messages.ERR_REFERENCE_TO_NONEXPORTED_CLASS_MAP_FALSE, os.getTargetNamespace() ); |
aoqi@0 | 323 | if(referer!=null) |
aoqi@0 | 324 | getErrorReporter().error(referer.getLocator(), |
aoqi@0 | 325 | Messages.ERR_REFERENCE_TO_NONEXPORTED_CLASS_REFERER, referer.apply( new ComponentNameFunction() ) ); |
aoqi@0 | 326 | } |
aoqi@0 | 327 | } |
aoqi@0 | 328 | |
aoqi@0 | 329 | |
aoqi@0 | 330 | queueBuild( sc, bean ); |
aoqi@0 | 331 | } |
aoqi@0 | 332 | |
aoqi@0 | 333 | Binding bind = bindMap.get(sc); |
aoqi@0 | 334 | if( cannotBeDelayed ) |
aoqi@0 | 335 | bind.build(); |
aoqi@0 | 336 | |
aoqi@0 | 337 | return bind.bean; |
aoqi@0 | 338 | } |
aoqi@0 | 339 | |
aoqi@0 | 340 | /** |
aoqi@0 | 341 | * Runs all the pending build tasks. |
aoqi@0 | 342 | */ |
aoqi@0 | 343 | public void executeTasks() { |
aoqi@0 | 344 | while( bindQueue.size()!=0 ) |
aoqi@0 | 345 | bindQueue.pop().build(); |
aoqi@0 | 346 | } |
aoqi@0 | 347 | |
aoqi@0 | 348 | |
aoqi@0 | 349 | |
aoqi@0 | 350 | |
aoqi@0 | 351 | |
aoqi@0 | 352 | |
aoqi@0 | 353 | |
aoqi@0 | 354 | |
aoqi@0 | 355 | /** |
aoqi@0 | 356 | * Determines if the given component needs to have a value |
aoqi@0 | 357 | * constructor (a constructor that takes a parmater.) on ObjectFactory. |
aoqi@0 | 358 | */ |
aoqi@0 | 359 | private boolean needValueConstructor( XSComponent sc ) { |
aoqi@0 | 360 | if(!(sc instanceof XSElementDecl)) return false; |
aoqi@0 | 361 | |
aoqi@0 | 362 | XSElementDecl decl = (XSElementDecl)sc; |
aoqi@0 | 363 | if(!decl.getType().isSimpleType()) return false; |
aoqi@0 | 364 | |
aoqi@0 | 365 | return true; |
aoqi@0 | 366 | } |
aoqi@0 | 367 | |
aoqi@0 | 368 | private static final String[] reservedClassNames = new String[]{"ObjectFactory"}; |
aoqi@0 | 369 | |
aoqi@0 | 370 | public void queueBuild( XSComponent sc, CElement bean ) { |
aoqi@0 | 371 | // it is an error if the same component is built twice, |
aoqi@0 | 372 | // or the association is modified. |
aoqi@0 | 373 | Binding b = new Binding(sc,bean); |
aoqi@0 | 374 | bindQueue.push(b); |
aoqi@0 | 375 | Binding old = bindMap.put(sc, b); |
aoqi@0 | 376 | assert old==null || old.bean==bean; |
aoqi@0 | 377 | } |
aoqi@0 | 378 | |
aoqi@0 | 379 | |
aoqi@0 | 380 | /** |
aoqi@0 | 381 | * Copies a schema fragment into the javadoc of the generated class. |
aoqi@0 | 382 | */ |
aoqi@0 | 383 | private void addSchemaFragmentJavadoc( CClassInfo bean, XSComponent sc ) { |
aoqi@0 | 384 | |
aoqi@0 | 385 | // first, pick it up from <documentation> if any. |
aoqi@0 | 386 | String doc = builder.getBindInfo(sc).getDocumentation(); |
aoqi@0 | 387 | if(doc!=null) |
aoqi@0 | 388 | append(bean, doc); |
aoqi@0 | 389 | |
aoqi@0 | 390 | // then the description of where this component came from |
aoqi@0 | 391 | Locator loc = sc.getLocator(); |
aoqi@0 | 392 | String fileName = null; |
aoqi@0 | 393 | if(loc!=null) { |
aoqi@0 | 394 | fileName = loc.getPublicId(); |
aoqi@0 | 395 | if(fileName==null) |
aoqi@0 | 396 | fileName = loc.getSystemId(); |
aoqi@0 | 397 | } |
aoqi@0 | 398 | if(fileName==null) fileName=""; |
aoqi@0 | 399 | |
aoqi@0 | 400 | String lineNumber=Messages.format( Messages.JAVADOC_LINE_UNKNOWN); |
aoqi@0 | 401 | if(loc!=null && loc.getLineNumber()!=-1) |
aoqi@0 | 402 | lineNumber = String.valueOf(loc.getLineNumber()); |
aoqi@0 | 403 | |
aoqi@0 | 404 | String componentName = sc.apply( new ComponentNameFunction() ); |
aoqi@0 | 405 | String jdoc = Messages.format( Messages.JAVADOC_HEADING, componentName, fileName, lineNumber ); |
aoqi@0 | 406 | append(bean,jdoc); |
aoqi@0 | 407 | |
aoqi@0 | 408 | // then schema fragment |
aoqi@0 | 409 | StringWriter out = new StringWriter(); |
aoqi@0 | 410 | out.write("<pre>\n"); |
aoqi@0 | 411 | SchemaWriter sw = new SchemaWriter(new JavadocEscapeWriter(out)); |
aoqi@0 | 412 | sc.visit(sw); |
aoqi@0 | 413 | out.write("</pre>"); |
aoqi@0 | 414 | append(bean,out.toString()); |
aoqi@0 | 415 | } |
aoqi@0 | 416 | |
aoqi@0 | 417 | private void append(CClassInfo bean, String doc) { |
aoqi@0 | 418 | if(bean.javadoc==null) |
aoqi@0 | 419 | bean.javadoc = doc+'\n'; |
aoqi@0 | 420 | else |
aoqi@0 | 421 | bean.javadoc += '\n'+doc+'\n'; |
aoqi@0 | 422 | } |
aoqi@0 | 423 | |
aoqi@0 | 424 | |
aoqi@0 | 425 | /** |
aoqi@0 | 426 | * Set of package names that are tested (set of <code>String</code>s.) |
aoqi@0 | 427 | * |
aoqi@0 | 428 | * This set is used to avoid duplicating "incorrect package name" |
aoqi@0 | 429 | * errors. |
aoqi@0 | 430 | */ |
aoqi@0 | 431 | private static Set<String> checkedPackageNames = new HashSet<String>(); |
aoqi@0 | 432 | |
aoqi@0 | 433 | /** |
aoqi@0 | 434 | * Gets the Java package to which classes from |
aoqi@0 | 435 | * this namespace should go. |
aoqi@0 | 436 | * |
aoqi@0 | 437 | * <p> |
aoqi@0 | 438 | * Usually, the getOuterClass method should be used |
aoqi@0 | 439 | * to determine where to put a class. |
aoqi@0 | 440 | */ |
aoqi@0 | 441 | public JPackage getPackage(String targetNamespace) { |
aoqi@0 | 442 | XSSchema s = Ring.get(XSSchemaSet.class).getSchema(targetNamespace); |
aoqi@0 | 443 | |
aoqi@0 | 444 | BISchemaBinding sb = |
aoqi@0 | 445 | builder.getBindInfo(s).get(BISchemaBinding.class); |
aoqi@0 | 446 | if(sb!=null) sb.markAsAcknowledged(); |
aoqi@0 | 447 | |
aoqi@0 | 448 | String name = null; |
aoqi@0 | 449 | |
aoqi@0 | 450 | // "-p" takes precedence over everything else |
aoqi@0 | 451 | if( builder.defaultPackage1 != null ) |
aoqi@0 | 452 | name = builder.defaultPackage1; |
aoqi@0 | 453 | |
aoqi@0 | 454 | // use the <jaxb:package> customization |
aoqi@0 | 455 | if( name == null && sb!=null && sb.getPackageName()!=null ) |
aoqi@0 | 456 | name = sb.getPackageName(); |
aoqi@0 | 457 | |
aoqi@0 | 458 | // the JAX-RPC option goes below the <jaxb:package> |
aoqi@0 | 459 | if( name == null && builder.defaultPackage2 != null ) |
aoqi@0 | 460 | name = builder.defaultPackage2; |
aoqi@0 | 461 | |
aoqi@0 | 462 | // generate the package name from the targetNamespace |
aoqi@0 | 463 | if( name == null ) |
aoqi@0 | 464 | name = builder.getNameConverter().toPackageName( targetNamespace ); |
aoqi@0 | 465 | |
aoqi@0 | 466 | // hardcode a package name because the code doesn't compile |
aoqi@0 | 467 | // if it generated into the default java package |
aoqi@0 | 468 | if( name == null ) |
aoqi@0 | 469 | name = "generated"; // the last resort |
aoqi@0 | 470 | |
aoqi@0 | 471 | |
aoqi@0 | 472 | // check if the package name is a valid name. |
aoqi@0 | 473 | if( checkedPackageNames.add(name) ) { |
aoqi@0 | 474 | // this is the first time we hear about this package name. |
aoqi@0 | 475 | if( !JJavaName.isJavaPackageName(name) ) |
aoqi@0 | 476 | // TODO: s.getLocator() is not very helpful. |
aoqi@0 | 477 | // ideally, we'd like to use the locator where this package name |
aoqi@0 | 478 | // comes from. |
aoqi@0 | 479 | getErrorReporter().error(s.getLocator(), |
aoqi@0 | 480 | Messages.ERR_INCORRECT_PACKAGE_NAME, targetNamespace, name ); |
aoqi@0 | 481 | } |
aoqi@0 | 482 | |
aoqi@0 | 483 | return Ring.get(JCodeModel.class)._package(name); |
aoqi@0 | 484 | } |
aoqi@0 | 485 | } |