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.model;
027:
028: import java.util.ArrayList;
029: import java.util.Collection;
030: import java.util.HashSet;
031: import java.util.List;
032: import java.util.Set;
033:
034: import javax.xml.bind.annotation.XmlElement;
035: import javax.xml.bind.annotation.XmlID;
036: import javax.xml.bind.annotation.XmlIDREF;
037: import javax.xml.bind.annotation.XmlTransient;
038: import javax.xml.namespace.QName;
039:
040: import com.sun.codemodel.internal.JClass;
041: import com.sun.codemodel.internal.JCodeModel;
042: import com.sun.codemodel.internal.JPackage;
043: import com.sun.tools.internal.xjc.model.nav.NClass;
044: import com.sun.tools.internal.xjc.model.nav.NType;
045: import com.sun.tools.internal.xjc.outline.Aspect;
046: import com.sun.tools.internal.xjc.outline.Outline;
047: import com.sun.xml.internal.bind.v2.model.core.ClassInfo;
048: import com.sun.xml.internal.bind.v2.model.core.Element;
049: import com.sun.xml.internal.xsom.XSComponent;
050:
051: import org.xml.sax.Locator;
052:
053: /**
054: * Mutable {@link ClassInfo} represenatation.
055: *
056: * <p>
057: * Schema parsers build these objects.
058: *
059: * @author Kohsuke Kawaguchi
060: */
061: public final class CClassInfo extends AbstractCTypeInfoImpl implements
062: ClassInfo<NType, NClass>, CClassInfoParent, CElement,
063: CNonElement, NClass, CTypeInfo {
064:
065: @XmlIDREF
066: private CClassInfo baseClass;
067:
068: /**
069: * @see #getTypeName()
070: */
071: private final QName typeName;
072: /**
073: * Can be null.
074: */
075: private final QName elementName;
076:
077: private boolean isOrdered = true;
078:
079: private final List<CPropertyInfo> properties = new ArrayList<CPropertyInfo>();
080:
081: /**
082: * TODO: revisit this design.
083: * we should at least do a basic encapsulation to avoid careless
084: * mistakes. Maybe we should even differ the javadoc generation
085: * by queueing runners.
086: */
087: public String javadoc;
088:
089: @XmlIDREF
090: private final CClassInfoParent parent;
091:
092: /**
093: * short name.
094: */
095: public final String shortName;
096:
097: /**
098: * The location in the source file where this class was declared.
099: */
100: @XmlTransient
101: private final Locator location;
102:
103: private boolean isAbstract;
104:
105: /**
106: * Optional user-specified implementation override class.
107: */
108: private String implClass;
109:
110: /**
111: * The {@link Model} object to which this bean belongs.
112: */
113: public final Model model;
114:
115: /**
116: * @see #hasAttributeWildcard()
117: */
118: private boolean hasAttributeWildcard;
119:
120: public CClassInfo(Model model, JPackage pkg, String shortName,
121: Locator location, QName typeName, QName elementName,
122: XSComponent source, CCustomizations customizations) {
123: this (model, model.getPackage(pkg), shortName, location,
124: typeName, elementName, source, customizations);
125: }
126:
127: public CClassInfo(Model model, CClassInfoParent p,
128: String shortName, Locator location, QName typeName,
129: QName elementName, XSComponent source,
130: CCustomizations customizations) {
131: super (model, source, customizations);
132: this .model = model;
133: this .parent = p;
134: this .shortName = model.allocator.assignClassName(parent,
135: shortName);
136: this .location = location;
137: this .typeName = typeName;
138: this .elementName = elementName;
139:
140: model.add(this );
141: }
142:
143: public CClassInfo(Model model, JCodeModel cm, String fullName,
144: Locator location, QName typeName, QName elementName,
145: XSComponent source, CCustomizations customizations) {
146: super (model, source, customizations);
147: this .model = model;
148: int idx = fullName.indexOf('.');
149: if (idx < 0) {
150: this .parent = model.getPackage(cm.rootPackage());
151: this .shortName = model.allocator.assignClassName(parent,
152: fullName);
153: } else {
154: this .parent = model.getPackage(cm._package(fullName
155: .substring(0, idx)));
156: this .shortName = model.allocator.assignClassName(parent,
157: fullName.substring(idx + 1));
158: }
159: this .location = location;
160: this .typeName = typeName;
161: this .elementName = elementName;
162:
163: model.add(this );
164: }
165:
166: public Locator getLocator() {
167: return location;
168: }
169:
170: public boolean hasAttributeWildcard() {
171: return hasAttributeWildcard;
172: }
173:
174: public void hasAttributeWildcard(boolean hasAttributeWildcard) {
175: this .hasAttributeWildcard = hasAttributeWildcard;
176: }
177:
178: public boolean hasSubClasses() {
179: throw new UnsupportedOperationException();
180: }
181:
182: /**
183: * Returns true iff a new attribute wildcard property needs to be
184: * declared on this class.
185: */
186: public boolean declaresAttributeWildcard() {
187: return hasAttributeWildcard && !inheritsAttributeWildcard();
188: }
189:
190: /**
191: * Returns true iff this class inherits a wildcard attribute property
192: * from its ancestor classes.
193: */
194: public boolean inheritsAttributeWildcard() {
195: for (CClassInfo c = getBaseClass(); c != null; c = c
196: .getBaseClass()) {
197: if (hasAttributeWildcard)
198: return true;
199: }
200: return false;
201: }
202:
203: public NClass getClazz() {
204: return this ;
205: }
206:
207: public CClassInfo getScope() {
208: return null;
209: }
210:
211: @XmlID
212: public String getName() {
213: return fullName();
214: }
215:
216: /**
217: * Returns the "squeezed name" of this bean token.
218: * <p>
219: * The squeezed name of a bean is the concatenation of
220: * the names of its outer classes and itself.
221: * <p>
222: * Thus if the bean is "org.acme.foo.Bean", then the squeezed name is "Bean",
223: * if the bean is "org.acme.foo.Outer1.Outer2.Bean", then "Outer1Outer2Bean".
224: * <p>
225: * This is used by the code generator
226: */
227: @XmlElement
228: public String getSqueezedName() {
229: return calcSqueezedName.onBean(this );
230: }
231:
232: private static final CClassInfoParent.Visitor<String> calcSqueezedName = new Visitor<String>() {
233: public String onBean(CClassInfo bean) {
234: return bean.parent.accept(this ) + bean.shortName;
235: }
236:
237: public String onElement(CElementInfo element) {
238: return element.parent.accept(this ) + element.shortName();
239: }
240:
241: public String onPackage(JPackage pkg) {
242: return "";
243: }
244: };
245:
246: /**
247: * Returns a mutable list.
248: */
249: public List<CPropertyInfo> getProperties() {
250: return properties;
251: }
252:
253: /**
254: * Gets a propery by name.
255: *
256: * TODO: consider moving this up to {@link ClassInfo}
257: */
258: public CPropertyInfo getProperty(String name) {
259: // TODO: does this method need to be fast?
260: for (CPropertyInfo p : properties)
261: if (p.getName(false).equals(name))
262: return p;
263: return null;
264: }
265:
266: public boolean hasProperties() {
267: return !getProperties().isEmpty();
268: }
269:
270: public boolean isElement() {
271: return elementName != null;
272: }
273:
274: public Element<NType, NClass> asElement() {
275: if (isElement())
276: return this ;
277: else
278: return null;
279: }
280:
281: public boolean isOrdered() {
282: return isOrdered;
283: }
284:
285: /**
286: * @deprecated
287: * if you are calling this method directly, you must be doing something wrong.
288: */
289: public boolean isFinal() {
290: return false;
291: }
292:
293: public void setOrdered(boolean value) {
294: isOrdered = value;
295: }
296:
297: public QName getElementName() {
298: return elementName;
299: }
300:
301: public QName getTypeName() {
302: return typeName;
303: }
304:
305: public boolean isSimpleType() {
306: throw new UnsupportedOperationException();
307: }
308:
309: /**
310: * Returns the FQCN of this bean.
311: */
312: public String fullName() {
313: String r = parent.fullName();
314: if (r.length() == 0)
315: return shortName;
316: else
317: return r + '.' + shortName;
318: }
319:
320: public CClassInfoParent parent() {
321: return parent;
322: }
323:
324: public void setUserSpecifiedImplClass(String implClass) {
325: assert this .implClass == null;
326: assert implClass != null;
327: this .implClass = implClass;
328: }
329:
330: public String getUserSpecifiedImplClass() {
331: return implClass;
332: }
333:
334: /**
335: * Adds a new property.
336: */
337: public void addProperty(CPropertyInfo prop) {
338: if (prop.ref().isEmpty())
339: // this property isn't contributing anything
340: // this happens when you try to map an empty sequence to a property
341: return;
342: prop.setParent(this );
343: properties.add(prop);
344: }
345:
346: public void setBaseClass(CClassInfo base) {
347: assert baseClass == null;
348: assert base != null;
349: baseClass = base;
350: }
351:
352: public CClassInfo getBaseClass() {
353: return baseClass;
354: }
355:
356: public CClassInfo getSubstitutionHead() {
357: CClassInfo c = baseClass;
358: while (c != null && !c.isElement())
359: c = c.baseClass;
360: return c;
361: }
362:
363: /**
364: * Interfaces to be implemented.
365: * Lazily constructed.
366: */
367: private Set<JClass> _implements = null;
368:
369: public void _implements (JClass c) {
370: if (_implements == null)
371: _implements = new HashSet<JClass>();
372: _implements .add(c);
373: }
374:
375: /** Constructor declarations. array of {@link Constructor}s. */
376: private final List<Constructor> constructors = new ArrayList<Constructor>(
377: 1);
378:
379: /** Creates a new constructor declaration and adds it. */
380: public void addConstructor(String... fieldNames) {
381: constructors.add(new Constructor(fieldNames));
382: }
383:
384: /** list all constructor declarations. */
385: public Collection<? extends Constructor> getConstructors() {
386: return constructors;
387: }
388:
389: public final <T> T accept(Visitor<T> visitor) {
390: return visitor.onBean(this );
391: }
392:
393: public JPackage getOwnerPackage() {
394: return parent.getOwnerPackage();
395: }
396:
397: public final NClass getType() {
398: return this ;
399: }
400:
401: public final JClass toType(Outline o, Aspect aspect) {
402: switch (aspect) {
403: case IMPLEMENTATION:
404: return o.getClazz(this ).implRef;
405: case EXPOSED:
406: return o.getClazz(this ).ref;
407: default:
408: throw new IllegalStateException();
409: }
410: }
411:
412: public boolean isBoxedType() {
413: return false;
414: }
415:
416: public String toString() {
417: return fullName();
418: }
419:
420: public void setAbstract() {
421: isAbstract = true;
422: }
423:
424: public boolean isAbstract() {
425: return isAbstract;
426: }
427: }
|