001: /*
002: * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.tools.internal.xjc.reader.xmlschema;
027:
028: import java.util.HashSet;
029: import java.util.Set;
030:
031: import javax.activation.MimeType;
032: import javax.xml.namespace.QName;
033:
034: import com.sun.tools.internal.xjc.model.CAdapter;
035: import com.sun.tools.internal.xjc.model.CClassInfo;
036: import com.sun.tools.internal.xjc.model.CElement;
037: import com.sun.tools.internal.xjc.model.CElementInfo;
038: import com.sun.tools.internal.xjc.model.CElementPropertyInfo;
039: import com.sun.tools.internal.xjc.model.CReferencePropertyInfo;
040: import com.sun.tools.internal.xjc.model.CTypeRef;
041: import com.sun.tools.internal.xjc.model.Multiplicity;
042: import com.sun.tools.internal.xjc.reader.RawTypeSet;
043: import com.sun.tools.internal.xjc.reader.Ring;
044: import com.sun.tools.internal.xjc.reader.xmlschema.bindinfo.BIDom;
045: import com.sun.xml.internal.bind.v2.model.core.ID;
046: import com.sun.xml.internal.bind.v2.model.core.WildcardMode;
047: import com.sun.xml.internal.xsom.XSElementDecl;
048: import com.sun.xml.internal.xsom.XSModelGroup;
049: import com.sun.xml.internal.xsom.XSModelGroupDecl;
050: import com.sun.xml.internal.xsom.XSParticle;
051: import com.sun.xml.internal.xsom.XSWildcard;
052: import com.sun.xml.internal.xsom.visitor.XSTermVisitor;
053:
054: /**
055: * Builds {@link RawTypeSet} for XML Schema.
056: *
057: * @author Kohsuke Kawaguchi
058: */
059: public class RawTypeSetBuilder implements XSTermVisitor {
060: /**
061: * @param optional
062: * if this whole property is optional due to the
063: * occurence constraints on ancestors, set this to true.
064: * this will prevent the primitive types to be generated.
065: */
066: public static RawTypeSet build(XSParticle p, boolean optional) {
067: RawTypeSetBuilder rtsb = new RawTypeSetBuilder();
068: rtsb.particle(p);
069: Multiplicity mul = MultiplicityCounter.theInstance.particle(p);
070:
071: if (optional)
072: mul = mul.makeOptional();
073:
074: return new RawTypeSet(rtsb.refs, mul);
075: }
076:
077: /**
078: * To avoid declaring the same element twice for a content model like
079: * (A,A), we keep track of element names here while we are building up
080: * this instance.
081: */
082: private final Set<QName> elementNames = new HashSet<QName>();
083:
084: private final Set<RawTypeSet.Ref> refs = new HashSet<RawTypeSet.Ref>();
085:
086: protected final BGMBuilder builder = Ring.get(BGMBuilder.class);
087:
088: public RawTypeSetBuilder() {
089: }
090:
091: /**
092: * Gets the {@link RawTypeSet.Ref}s that were built.
093: */
094: public Set<RawTypeSet.Ref> getRefs() {
095: return refs;
096: }
097:
098: /**
099: * Build up {@link #refs} and compute the total multiplicity of this {@link RawTypeSet.Ref} set.
100: */
101: private void particle(XSParticle p) {
102: // if the DOM customization is present, bind it like a wildcard
103: BIDom dom = builder.getLocalDomCustomization(p);
104: if (dom != null) {
105: dom.markAsAcknowledged();
106: refs.add(new WildcardRef(WildcardMode.SKIP));
107: } else {
108: p.getTerm().visit(this );
109: }
110: }
111:
112: public void wildcard(XSWildcard wc) {
113: refs.add(new WildcardRef(wc));
114: }
115:
116: public void modelGroupDecl(XSModelGroupDecl decl) {
117: modelGroup(decl.getModelGroup());
118: }
119:
120: public void modelGroup(XSModelGroup group) {
121: for (XSParticle p : group.getChildren())
122: particle(p);
123: }
124:
125: public void elementDecl(XSElementDecl decl) {
126:
127: QName n = new QName(decl.getTargetNamespace(), decl.getName());
128: if (elementNames.add(n)) {
129: CElement elementBean = Ring.get(ClassSelector.class)
130: .bindToType(decl);
131: if (elementBean == null)
132: refs.add(new RawTypeSet.XmlTypeRef(decl));
133: else {
134: if (elementBean instanceof CClassInfo)
135: refs.add(new CClassInfoRef(decl,
136: (CClassInfo) elementBean));
137: else
138: refs.add(new CElementInfoRef(decl,
139: (CElementInfo) elementBean));
140: }
141: }
142: }
143:
144: /**
145: * Reference to a wildcard.
146: */
147: public static final class WildcardRef extends RawTypeSet.Ref {
148: private final WildcardMode mode;
149:
150: WildcardRef(XSWildcard wildcard) {
151: this .mode = getMode(wildcard);
152: }
153:
154: WildcardRef(WildcardMode mode) {
155: this .mode = mode;
156: }
157:
158: private static WildcardMode getMode(XSWildcard wildcard) {
159: switch (wildcard.getMode()) {
160: case XSWildcard.LAX:
161: return WildcardMode.LAX;
162: case XSWildcard.STRTICT:
163: return WildcardMode.STRICT;
164: case XSWildcard.SKIP:
165: return WildcardMode.SKIP;
166: default:
167: throw new IllegalStateException();
168: }
169: }
170:
171: protected CTypeRef toTypeRef(CElementPropertyInfo ep) {
172: // we don't allow a mapping to typeRef if the wildcard is present
173: throw new IllegalStateException();
174: }
175:
176: protected void toElementRef(CReferencePropertyInfo prop) {
177: prop.setWildcard(mode);
178: }
179:
180: protected RawTypeSet.Mode canBeType(RawTypeSet parent) {
181: return RawTypeSet.Mode.MUST_BE_REFERENCE;
182: }
183:
184: protected boolean isListOfValues() {
185: return false;
186: }
187:
188: protected ID id() {
189: return ID.NONE;
190: }
191: }
192:
193: /**
194: * Reference to a class that maps from an element.
195: */
196: public static final class CClassInfoRef extends RawTypeSet.Ref {
197: public final CClassInfo target;
198: public final XSElementDecl decl;
199:
200: CClassInfoRef(XSElementDecl decl, CClassInfo target) {
201: this .decl = decl;
202: this .target = target;
203: }
204:
205: protected CTypeRef toTypeRef(CElementPropertyInfo ep) {
206: return new CTypeRef(target, target.getElementName(), decl
207: .isNillable(), decl.getDefaultValue());
208: }
209:
210: protected void toElementRef(CReferencePropertyInfo prop) {
211: prop.getElements().add(target);
212: }
213:
214: protected RawTypeSet.Mode canBeType(RawTypeSet parent) {
215: // if element substitution can occur, no way it can be mapped to a list of types
216: if (decl.getSubstitutables().size() > 1)
217: return RawTypeSet.Mode.MUST_BE_REFERENCE;
218:
219: return RawTypeSet.Mode.SHOULD_BE_TYPEREF;
220: }
221:
222: protected boolean isListOfValues() {
223: return false;
224: }
225:
226: protected ID id() {
227: return ID.NONE;
228: }
229: }
230:
231: /**
232: * Reference to a class that maps from an element.
233: */
234: public static final class CElementInfoRef extends RawTypeSet.Ref {
235: public final CElementInfo target;
236: public final XSElementDecl decl;
237:
238: CElementInfoRef(XSElementDecl decl, CElementInfo target) {
239: this .decl = decl;
240: this .target = target;
241: }
242:
243: protected CTypeRef toTypeRef(CElementPropertyInfo ep) {
244: assert !target.isCollection();
245: CAdapter a = target.getProperty().getAdapter();
246: if (a != null && ep != null)
247: ep.setAdapter(a);
248:
249: return new CTypeRef(target.getContentType(), target
250: .getElementName(), decl.isNillable(), decl
251: .getDefaultValue());
252: }
253:
254: protected void toElementRef(CReferencePropertyInfo prop) {
255: prop.getElements().add(target);
256: }
257:
258: protected RawTypeSet.Mode canBeType(RawTypeSet parent) {
259: // if element substitution can occur, no way it can be mapped to a list of types
260: if (decl.getSubstitutables().size() > 1)
261: return RawTypeSet.Mode.MUST_BE_REFERENCE;
262:
263: // we have no place to put an adater if this thing maps to a type
264: CElementPropertyInfo p = target.getProperty();
265: // if we have an adapter or IDness, which requires special
266: // annotation, and there's more than one element,
267: // we have no place to put the special annotation, so we need JAXBElement.
268: if (parent.refs.size() > 1 || !parent.mul.isAtMostOnce()) {
269: if (p.getAdapter() != null || p.id() != ID.NONE)
270: return RawTypeSet.Mode.MUST_BE_REFERENCE;
271: }
272:
273: return RawTypeSet.Mode.SHOULD_BE_TYPEREF;
274: }
275:
276: protected boolean isListOfValues() {
277: return target.getProperty().isValueList();
278: }
279:
280: protected ID id() {
281: return target.getProperty().id();
282: }
283:
284: protected MimeType getExpectedMimeType() {
285: return target.getProperty().getExpectedMimeType();
286: }
287: }
288: }
|