src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/RawTypeSetBuilder.java

changeset 0
373ffda63c9a
equal deleted inserted replaced
-1:000000000000 0:373ffda63c9a
1 /*
2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.tools.internal.xjc.reader.xmlschema;
27
28 import java.util.LinkedHashSet;
29 import java.util.Set;
30
31 import javax.activation.MimeType;
32 import javax.xml.namespace.QName;
33
34 import com.sun.tools.internal.xjc.model.CAdapter;
35 import com.sun.tools.internal.xjc.model.CClass;
36 import com.sun.tools.internal.xjc.model.CClassInfo;
37 import com.sun.tools.internal.xjc.model.CCustomizations;
38 import com.sun.tools.internal.xjc.model.CElement;
39 import com.sun.tools.internal.xjc.model.CElementInfo;
40 import com.sun.tools.internal.xjc.model.CElementPropertyInfo;
41 import com.sun.tools.internal.xjc.model.CReferencePropertyInfo;
42 import com.sun.tools.internal.xjc.model.CTypeRef;
43 import com.sun.tools.internal.xjc.model.Model;
44 import com.sun.tools.internal.xjc.model.Multiplicity;
45 import com.sun.tools.internal.xjc.model.TypeUse;
46 import com.sun.tools.internal.xjc.reader.RawTypeSet;
47 import com.sun.tools.internal.xjc.reader.Ring;
48 import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIDom;
49 import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIGlobalBinding;
50 import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIXSubstitutable;
51 import com.sun.xml.internal.bind.v2.model.core.ID;
52 import com.sun.xml.internal.bind.v2.model.core.WildcardMode;
53 import com.sun.xml.internal.xsom.XSElementDecl;
54 import com.sun.xml.internal.xsom.XSModelGroup;
55 import com.sun.xml.internal.xsom.XSModelGroupDecl;
56 import com.sun.xml.internal.xsom.XSParticle;
57 import com.sun.xml.internal.xsom.XSWildcard;
58 import com.sun.xml.internal.xsom.visitor.XSTermVisitor;
59
60 /**
61 * Builds {@link RawTypeSet} for XML Schema.
62 *
63 * @author Kohsuke Kawaguchi
64 */
65 public class RawTypeSetBuilder implements XSTermVisitor {
66 /**
67 * @param optional
68 * if this whole property is optional due to the
69 * occurrence constraints on ancestors, set this to true.
70 * this will prevent the primitive types to be generated.
71 */
72 public static RawTypeSet build( XSParticle p, boolean optional ) {
73 RawTypeSetBuilder rtsb = new RawTypeSetBuilder();
74 rtsb.particle(p);
75 Multiplicity mul = MultiplicityCounter.theInstance.particle(p);
76
77 if(optional)
78 mul = mul.makeOptional();
79
80 return new RawTypeSet(rtsb.refs,mul);
81 }
82
83 /**
84 * To avoid declaring the same element twice for a content model like
85 * (A,A), we keep track of element names here while we are building up
86 * this instance.
87 */
88 private final Set<QName> elementNames = new LinkedHashSet<QName>();
89
90 private final Set<RawTypeSet.Ref> refs = new LinkedHashSet<RawTypeSet.Ref>();
91
92 protected final BGMBuilder builder = Ring.get(BGMBuilder.class);
93
94 public RawTypeSetBuilder() {}
95
96
97 /**
98 * Gets the {@link RawTypeSet.Ref}s that were built.
99 */
100 public Set<RawTypeSet.Ref> getRefs() {
101 return refs;
102 }
103
104 /**
105 * Build up {@link #refs} and compute the total multiplicity of this {@link RawTypeSet.Ref} set.
106 */
107 private void particle( XSParticle p ) {
108 // if the DOM customization is present, bind it like a wildcard
109 BIDom dom = builder.getLocalDomCustomization(p);
110 if(dom!=null) {
111 dom.markAsAcknowledged();
112 refs.add(new WildcardRef(WildcardMode.SKIP));
113 } else {
114 p.getTerm().visit(this);
115 }
116 }
117
118 public void wildcard(XSWildcard wc) {
119 refs.add(new WildcardRef(wc));
120 }
121
122 public void modelGroupDecl(XSModelGroupDecl decl) {
123 modelGroup(decl.getModelGroup());
124 }
125
126 public void modelGroup(XSModelGroup group) {
127 for( XSParticle p : group.getChildren())
128 particle(p);
129 }
130
131 public void elementDecl(XSElementDecl decl) {
132
133 QName n = BGMBuilder.getName(decl);
134 if(elementNames.add(n)) {
135 CElement elementBean = Ring.get(ClassSelector.class).bindToType(decl,null);
136 if(elementBean==null)
137 refs.add(new XmlTypeRef(decl));
138 else {
139 // yikes!
140 if(elementBean instanceof CClass)
141 refs.add(new CClassRef(decl,(CClass)elementBean));
142 else
143 refs.add(new CElementInfoRef(decl,(CElementInfo)elementBean));
144 }
145 }
146 }
147
148 /**
149 * Reference to a wildcard.
150 */
151 public static final class WildcardRef extends RawTypeSet.Ref {
152 private final WildcardMode mode;
153
154 WildcardRef(XSWildcard wildcard) {
155 this.mode = getMode(wildcard);
156 }
157 WildcardRef(WildcardMode mode) {
158 this.mode = mode;
159 }
160
161 private static WildcardMode getMode(XSWildcard wildcard) {
162 switch(wildcard.getMode()) {
163 case XSWildcard.LAX:
164 return WildcardMode.LAX;
165 case XSWildcard.STRTICT:
166 return WildcardMode.STRICT;
167 case XSWildcard.SKIP:
168 return WildcardMode.SKIP;
169 default:
170 throw new IllegalStateException();
171 }
172 }
173
174 protected CTypeRef toTypeRef(CElementPropertyInfo ep) {
175 // we don't allow a mapping to typeRef if the wildcard is present
176 throw new IllegalStateException();
177 }
178
179 protected void toElementRef(CReferencePropertyInfo prop) {
180 prop.setWildcard(mode);
181 }
182
183 protected RawTypeSet.Mode canBeType(RawTypeSet parent) {
184 return RawTypeSet.Mode.MUST_BE_REFERENCE;
185 }
186
187 protected boolean isListOfValues() {
188 return false;
189 }
190
191 protected ID id() {
192 return ID.NONE;
193 }
194 }
195
196 /**
197 * Reference to a class that maps from an element.
198 */
199 public static final class CClassRef extends RawTypeSet.Ref {
200 public final CClass target;
201 public final XSElementDecl decl;
202
203 CClassRef(XSElementDecl decl, CClass target) {
204 this.decl = decl;
205 this.target = target;
206 }
207
208 protected CTypeRef toTypeRef(CElementPropertyInfo ep) {
209 return new CTypeRef(target,decl);
210 }
211
212 protected void toElementRef(CReferencePropertyInfo prop) {
213 prop.getElements().add(target);
214 }
215
216 protected RawTypeSet.Mode canBeType(RawTypeSet parent) {
217 // if element substitution can occur, no way it can be mapped to a list of types
218 if(decl.getSubstitutables().size()>1)
219 return RawTypeSet.Mode.MUST_BE_REFERENCE;
220
221 return RawTypeSet.Mode.SHOULD_BE_TYPEREF;
222 }
223
224 protected boolean isListOfValues() {
225 return false;
226 }
227
228 protected ID id() {
229 return ID.NONE;
230 }
231 }
232
233 /**
234 * Reference to a class that maps from an element.
235 */
236 public final class CElementInfoRef extends RawTypeSet.Ref {
237 public final CElementInfo target;
238 public final XSElementDecl decl;
239
240 CElementInfoRef(XSElementDecl decl, CElementInfo target) {
241 this.decl = decl;
242 this.target = target;
243 }
244
245 protected CTypeRef toTypeRef(CElementPropertyInfo ep) {
246 assert !target.isCollection();
247 CAdapter a = target.getProperty().getAdapter();
248 if(a!=null && ep!=null) ep.setAdapter(a);
249
250 return new CTypeRef(target.getContentType(),decl);
251 }
252
253 protected void toElementRef(CReferencePropertyInfo prop) {
254 prop.getElements().add(target);
255 }
256
257 protected RawTypeSet.Mode canBeType(RawTypeSet parent) {
258 // if element substitution can occur, no way it can be mapped to a list of types
259 if(decl.getSubstitutables().size()>1)
260 return RawTypeSet.Mode.MUST_BE_REFERENCE;
261 // BIXSubstitutable also simulates this effect. Useful for separate compilation
262 BIXSubstitutable subst = builder.getBindInfo(decl).get(BIXSubstitutable.class);
263 if(subst!=null) {
264 subst.markAsAcknowledged();
265 return RawTypeSet.Mode.MUST_BE_REFERENCE;
266 }
267
268 // we have no place to put an adater if this thing maps to a type
269 CElementPropertyInfo p = target.getProperty();
270 // if we have an adapter or IDness, which requires special
271 // annotation, and there's more than one element,
272 // we have no place to put the special annotation, so we need JAXBElement.
273 if((parent.refs.size()>1 || !parent.mul.isAtMostOnce()) && p.id()!=ID.NONE)
274 return RawTypeSet.Mode.MUST_BE_REFERENCE;
275 if(parent.refs.size() > 1 && p.getAdapter() != null)
276 return RawTypeSet.Mode.MUST_BE_REFERENCE;
277
278 if(target.hasClass())
279 // if the CElementInfo was explicitly bound to a class (which happen if and only if
280 // the user requested so, then map that to reference property so that the user sees a class
281 return RawTypeSet.Mode.CAN_BE_TYPEREF;
282 else
283 return RawTypeSet.Mode.SHOULD_BE_TYPEREF;
284 }
285
286 protected boolean isListOfValues() {
287 return target.getProperty().isValueList();
288 }
289
290 protected ID id() {
291 return target.getProperty().id();
292 }
293
294 @Override
295 protected MimeType getExpectedMimeType() {
296 return target.getProperty().getExpectedMimeType();
297 }
298 }
299
300 /**
301 * References to a type. Could be global or local.
302 */
303 public static final class XmlTypeRef extends RawTypeSet.Ref {
304 private final XSElementDecl decl;
305 private final TypeUse target;
306
307 public XmlTypeRef(XSElementDecl decl) {
308 this.decl = decl;
309 SimpleTypeBuilder stb = Ring.get(SimpleTypeBuilder.class);
310 stb.refererStack.push(decl);
311 TypeUse r = Ring.get(ClassSelector.class).bindToType(decl.getType(),decl);
312 stb.refererStack.pop();
313 target = r;
314 }
315
316 protected CTypeRef toTypeRef(CElementPropertyInfo ep) {
317 if(ep!=null && target.getAdapterUse()!=null)
318 ep.setAdapter(target.getAdapterUse());
319 return new CTypeRef(target.getInfo(),decl);
320 }
321
322 /**
323 * The whole type set can be later bound to a reference property,
324 * in which case we need to generate additional code to wrap this
325 * type reference into an element class.
326 *
327 * This method generates such an element class and returns it.
328 */
329 protected void toElementRef(CReferencePropertyInfo prop) {
330 CClassInfo scope = Ring.get(ClassSelector.class).getCurrentBean();
331 Model model = Ring.get(Model.class);
332
333 CCustomizations custs = Ring.get(BGMBuilder.class).getBindInfo(decl).toCustomizationList();
334
335 if(target instanceof CClassInfo && Ring.get(BIGlobalBinding.class).isSimpleMode()) {
336 CClassInfo bean = new CClassInfo(model,scope,
337 model.getNameConverter().toClassName(decl.getName()),
338 decl.getLocator(), null, BGMBuilder.getName(decl), decl,
339 custs);
340 bean.setBaseClass((CClassInfo)target);
341 prop.getElements().add(bean);
342 } else {
343 CElementInfo e = new CElementInfo(model,BGMBuilder.getName(decl),scope,target,
344 decl.getDefaultValue(), decl, custs, decl.getLocator());
345 prop.getElements().add(e);
346 }
347 }
348
349 protected RawTypeSet.Mode canBeType(RawTypeSet parent) {
350 // if we have an adapter or IDness, which requires special
351 // annotation, and there's more than one element,
352 // we have no place to put the special annotation, so we need JAXBElement.
353 if((parent.refs.size()>1 || !parent.mul.isAtMostOnce()) && target.idUse()!=ID.NONE)
354 return RawTypeSet.Mode.MUST_BE_REFERENCE;
355 if(parent.refs.size() > 1 && target.getAdapterUse() != null)
356 return RawTypeSet.Mode.MUST_BE_REFERENCE;
357
358 // nillable and optional at the same time. needs an element wrapper to distinguish those
359 // two states. But this is not a hard requirement.
360 if(decl.isNillable() && parent.mul.isOptional())
361 return RawTypeSet.Mode.CAN_BE_TYPEREF;
362
363 return RawTypeSet.Mode.SHOULD_BE_TYPEREF;
364 }
365
366 protected boolean isListOfValues() {
367 return target.isCollection();
368 }
369
370 protected ID id() {
371 return target.idUse();
372 }
373
374 @Override
375 protected MimeType getExpectedMimeType() {
376 return target.getExpectedMimeType();
377 }
378 }
379 }

mercurial