src/share/jaxws_classes/com/sun/tools/internal/xjc/reader/xmlschema/DefaultParticleBinder.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.ArrayList;
29 import java.util.Collection;
30 import java.util.Collections;
31 import java.util.HashMap;
32 import java.util.Hashtable;
33 import java.util.List;
34 import java.util.Map;
35
36 import com.sun.tools.internal.xjc.model.CClassInfo;
37 import com.sun.tools.internal.xjc.model.CPropertyInfo;
38 import com.sun.tools.internal.xjc.model.CReferencePropertyInfo;
39 import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIProperty;
40 import com.sun.xml.internal.xsom.XSElementDecl;
41 import com.sun.xml.internal.xsom.XSModelGroup;
42 import com.sun.xml.internal.xsom.XSModelGroupDecl;
43 import com.sun.xml.internal.xsom.XSParticle;
44 import com.sun.xml.internal.xsom.XSTerm;
45 import com.sun.xml.internal.xsom.XSWildcard;
46 import com.sun.xml.internal.xsom.visitor.XSTermVisitor;
47 import java.math.BigInteger;
48
49 /**
50 * {@link ParticleBinder} that follows the JAXB spec.
51 *
52 * @author Kohsuke Kawaguchi
53 */
54 final class DefaultParticleBinder extends ParticleBinder {
55
56 @Override
57 public void build( XSParticle p, Collection<XSParticle> forcedProps ) {
58 Checker checker = checkCollision(p,forcedProps);
59
60 if(checker.hasNameCollision()) {
61 CReferencePropertyInfo prop = new CReferencePropertyInfo(
62 getCurrentBean().getBaseClass()==null?"Content":"Rest",
63 true, false, false, p,
64 builder.getBindInfo(p).toCustomizationList(),
65 p.getLocator(), false, false, false);
66 RawTypeSetBuilder.build(p,false).addTo(prop);
67 prop.javadoc = Messages.format( Messages.MSG_FALLBACK_JAVADOC,
68 checker.getCollisionInfo().toString() );
69
70 getCurrentBean().addProperty(prop);
71 } else {
72 new Builder(checker.markedParticles).particle(p);
73 }
74 }
75
76 @Override
77 public boolean checkFallback( XSParticle p ) {
78 return checkCollision(p,Collections.<XSParticle>emptyList()).hasNameCollision();
79 }
80
81 private Checker checkCollision( XSParticle p, Collection<XSParticle> forcedProps ) {
82 // scan the tree by a checker.
83 Checker checker = new Checker(forcedProps);
84
85 CClassInfo superClass = getCurrentBean().getBaseClass();
86
87 if(superClass!=null)
88 checker.readSuperClass(superClass);
89 checker.particle(p);
90
91 return checker;
92 }
93
94
95
96
97
98
99
100
101
102
103 /**
104 * Marks particles that need to be mapped to properties,
105 * by reading customization info.
106 */
107 private final class Checker implements XSTermVisitor {
108
109 Checker(Collection<XSParticle> forcedProps) {
110 this.forcedProps = forcedProps;
111 }
112
113 boolean hasNameCollision() {
114 return collisionInfo!=null;
115 }
116
117 CollisionInfo getCollisionInfo() {
118 return collisionInfo;
119 }
120
121 /**
122 * If a collision is found, this field will be non-null.
123 */
124 private CollisionInfo collisionInfo = null;
125
126 /** Used to check name collision. */
127 private final NameCollisionChecker cchecker = new NameCollisionChecker();
128
129 /**
130 * @see DefaultParticleBinder#build(XSParticle, Collection<com.sun.xml.internal.xsom.XSParticle>)
131 */
132 private final Collection<XSParticle> forcedProps;
133
134 public void particle( XSParticle p ) {
135
136 if(getLocalPropCustomization(p)!=null
137 || builder.getLocalDomCustomization(p)!=null) {
138 // if a property customization is specfied,
139 // check that value and turn around.
140 check(p);
141 mark(p);
142 return;
143 }
144
145 XSTerm t = p.getTerm();
146
147 if(p.isRepeated() && (t.isModelGroup() || t.isModelGroupDecl())) {
148 // a repeated model group gets its own property
149 mark(p);
150 return;
151 }
152
153 if(forcedProps.contains(p)) {
154 // this particle must become a property
155 mark(p);
156 return;
157 }
158
159 outerParticle = p;
160 t.visit(this);
161 }
162
163 /**
164 * This field points to the parent XSParticle.
165 * The value is only valid when we are processing XSTerm.
166 */
167 private XSParticle outerParticle;
168
169 public void elementDecl(XSElementDecl decl) {
170 check(outerParticle);
171 mark(outerParticle);
172 }
173
174 public void modelGroup(XSModelGroup mg) {
175 // choice gets mapped to a property
176 if(mg.getCompositor()== XSModelGroup.Compositor.CHOICE && builder.getGlobalBinding().isChoiceContentPropertyEnabled()) {
177 mark(outerParticle);
178 return;
179 }
180
181 for( XSParticle child : mg.getChildren() )
182 particle(child);
183 }
184
185 public void modelGroupDecl(XSModelGroupDecl decl) {
186 modelGroup(decl.getModelGroup());
187 }
188
189 public void wildcard(XSWildcard wc) {
190 mark(outerParticle);
191 }
192
193 void readSuperClass( CClassInfo ci ) {
194 cchecker.readSuperClass(ci);
195 }
196
197
198
199
200 /**
201 * Checks the name collision of a newly found particle.
202 */
203 private void check( XSParticle p ) {
204 if( collisionInfo==null )
205 collisionInfo = cchecker.check(p);
206 }
207
208 /**
209 * Marks a particle that it's going to be mapped to a property.
210 */
211 private void mark( XSParticle p ) {
212 markedParticles.put(p,computeLabel(p));
213 }
214
215 /**
216 * Marked particles.
217 *
218 * A map from XSParticle to its label.
219 */
220 public final Map<XSParticle,String> markedParticles = new HashMap<XSParticle,String>();
221
222
223 /**
224 * Checks name collisions among particles that belong to sequences.
225 */
226 private final class NameCollisionChecker {
227
228 /**
229 * Checks the label conflict of a particle.
230 * This method shall be called for each marked particle.
231 *
232 * @return
233 * a description of a collision if a name collision is
234 * found. Otherwise null.
235 */
236 CollisionInfo check( XSParticle p ) {
237 // this can be used for particles with a property customization,
238 // which may not have element declaration as its term.
239 // // we only check particles with element declarations.
240 // _assert( p.getTerm().isElementDecl() );
241
242 String label = computeLabel(p);
243 if( occupiedLabels.containsKey(label) ) {
244 // collide with occupied labels
245 return new CollisionInfo(label,p.getLocator(),
246 occupiedLabels.get(label).locator);
247 }
248
249 for( XSParticle jp : particles ) {
250 if(!check( p, jp )) {
251 // problem was found. no need to check further
252 return new CollisionInfo( label, p.getLocator(), jp.getLocator() );
253 }
254 }
255 particles.add(p);
256 return null;
257 }
258
259 /** List of particles reported through the check method. */
260 private final List<XSParticle> particles = new ArrayList<XSParticle>();
261
262 /**
263 * Label names already used in the base type.
264 */
265 private final Map<String,CPropertyInfo> occupiedLabels = new HashMap<String,CPropertyInfo>();
266
267 /**
268 * Checks the conflict of two particles.
269 * @return
270 * true if the check was successful.
271 */
272 private boolean check( XSParticle p1, XSParticle p2 ) {
273 return !computeLabel(p1).equals(computeLabel(p2));
274 }
275
276 /**
277 * Reads fields of the super class and includes them
278 * to name collision tests.
279 */
280 void readSuperClass( CClassInfo base ) {
281 for( ; base!=null; base=base.getBaseClass() ) {
282 for( CPropertyInfo p : base.getProperties() )
283 occupiedLabels.put(p.getName(true),p);
284 }
285 }
286 }
287
288
289
290
291
292 /** Keep the computed label names for particles. */
293 private final Map<XSParticle,String> labelCache = new Hashtable<XSParticle,String>();
294
295 /**
296 * Hides the computeLabel method of the outer class
297 * and adds caching.
298 */
299 private String computeLabel( XSParticle p ) {
300 String label = labelCache.get(p);
301 if(label==null)
302 labelCache.put( p, label=DefaultParticleBinder.this.computeLabel(p) );
303 return label;
304 }
305 }
306
307
308
309
310
311
312
313
314
315
316
317
318 /**
319 * Builds properties by using the result computed by Checker
320 */
321 private final class Builder implements XSTermVisitor {
322 Builder( Map<XSParticle,String> markedParticles ) {
323 this.markedParticles = markedParticles;
324 }
325
326 /** All marked particles. */
327 private final Map<XSParticle,String/*label*/> markedParticles;
328
329 /**
330 * When we are visiting inside an optional particle, this flag
331 * is set to true.
332 *
333 * <p>
334 * This allows us to correctly generate primitive/boxed types.
335 */
336 private boolean insideOptionalParticle;
337
338
339 /** Returns true if a particle is marked. */
340 private boolean marked( XSParticle p ) {
341 return markedParticles.containsKey(p);
342 }
343 /** Gets a label of a particle. */
344 private String getLabel( XSParticle p ) {
345 return markedParticles.get(p);
346 }
347
348 public void particle( XSParticle p ) {
349 XSTerm t = p.getTerm();
350
351 if(marked(p)) {
352 BIProperty cust = BIProperty.getCustomization(p);
353 CPropertyInfo prop = cust.createElementOrReferenceProperty(
354 getLabel(p), false, p, RawTypeSetBuilder.build(p,insideOptionalParticle));
355 getCurrentBean().addProperty(prop);
356 } else {
357 // repeated model groups should have been marked already
358 assert !p.isRepeated();
359
360 boolean oldIOP = insideOptionalParticle;
361 insideOptionalParticle |= BigInteger.ZERO.equals(p.getMinOccurs());
362 // this is an unmarked particle
363 t.visit(this);
364 insideOptionalParticle = oldIOP;
365 }
366 }
367
368 public void elementDecl( XSElementDecl e ) {
369 // because the corresponding particle must be marked.
370 assert false;
371 }
372
373 public void wildcard( XSWildcard wc ) {
374 // because the corresponding particle must be marked.
375 assert false;
376 }
377
378 public void modelGroupDecl( XSModelGroupDecl decl ) {
379 modelGroup(decl.getModelGroup());
380 }
381
382 public void modelGroup( XSModelGroup mg ) {
383 boolean oldIOP = insideOptionalParticle;
384 insideOptionalParticle |= mg.getCompositor()==XSModelGroup.CHOICE;
385
386 for( XSParticle p : mg.getChildren())
387 particle(p);
388
389 insideOptionalParticle = oldIOP;
390 }
391 }
392 }

mercurial