001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common Development
008: * and Distribution License("CDDL") (collectively, the "License"). You
009: * may not use this file except in compliance with the License. You can obtain
010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
012: * language governing permissions and limitations under the License.
013: *
014: * When distributing the software, include this License Header Notice in each
015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016: * Sun designates this particular file as subject to the "Classpath" exception
017: * as provided by Sun in the GPL Version 2 section of the License file that
018: * accompanied this code. If applicable, add the following below the License
019: * Header, with the fields enclosed by brackets [] replaced by your own
020: * identifying information: "Portions Copyrighted [year]
021: * [name of copyright owner]"
022: *
023: * Contributor(s):
024: *
025: * If you wish your version of this file to be governed by only the CDDL or
026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
027: * elects to include this software in this distribution under the [CDDL or GPL
028: * Version 2] license." If you don't indicate a single choice of license, a
029: * recipient has the option to distribute your version of this file under
030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
031: * its licensees as provided above. However, if you add GPL Version 2 code
032: * and therefore, elected the GPL Version 2 license, then the option applies
033: * only if the new code is made subject to such option by the copyright
034: * holder.
035: */
036:
037: package com.sun.xml.bind.v2.model.impl;
038:
039: import java.util.LinkedHashSet;
040: import java.util.Set;
041:
042: import javax.xml.bind.annotation.XmlElementDecl;
043:
044: import com.sun.xml.bind.v2.model.annotation.Locatable;
045: import com.sun.xml.bind.v2.model.annotation.MethodLocatable;
046: import com.sun.xml.bind.v2.model.core.RegistryInfo;
047: import com.sun.xml.bind.v2.model.core.TypeInfo;
048: import com.sun.xml.bind.v2.model.nav.Navigator;
049: import com.sun.xml.bind.v2.runtime.IllegalAnnotationException;
050: import com.sun.xml.bind.v2.runtime.Location;
051: import com.sun.xml.bind.v2.ContextFactory;
052:
053: /**
054: * Implementation of {@link RegistryInfo}.
055: *
056: * @author Kohsuke Kawaguchi
057: */
058: // experimenting with shorter type parameters for <T,C,F,M> quadruple.
059: // the idea is that they show so often that you'd understand the meaning
060: // without relying on the whole name.
061: final class RegistryInfoImpl<T, C, F, M> implements Locatable,
062: RegistryInfo<T, C> {
063:
064: final C registryClass;
065: private final Locatable upstream;
066: private final Navigator<T, C, F, M> nav;
067:
068: /**
069: * Types that are referenced from this registry.
070: */
071: private final Set<TypeInfo<T, C>> references = new LinkedHashSet<TypeInfo<T, C>>();
072:
073: /**
074: * Picks up references in this registry to other types.
075: */
076: RegistryInfoImpl(ModelBuilder<T, C, F, M> builder,
077: Locatable upstream, C registryClass) {
078: this .nav = builder.nav;
079: this .registryClass = registryClass;
080: this .upstream = upstream;
081: builder.registries.put(getPackageName(), this );
082:
083: if (nav.getDeclaredField(registryClass,
084: ContextFactory.USE_JAXB_PROPERTIES) != null) {
085: // the user is trying to use ObjectFactory that we generate for interfaces,
086: // that means he's missing jaxb.properties
087: builder.reportError(new IllegalAnnotationException(
088: Messages.MISSING_JAXB_PROPERTIES
089: .format(getPackageName()), this ));
090: // looking at members will only add more errors, so just abort now
091: return;
092: }
093:
094: for (M m : nav.getDeclaredMethods(registryClass)) {
095: XmlElementDecl em = builder.reader.getMethodAnnotation(
096: XmlElementDecl.class, m, this );
097:
098: if (em == null) {
099: if (nav.getMethodName(m).startsWith("create")) {
100: // this is a factory method. visit this class
101: references.add(builder.getTypeInfo(nav
102: .getReturnType(m), new MethodLocatable<M>(
103: this , m, nav)));
104: }
105:
106: continue;
107: }
108:
109: ElementInfoImpl<T, C, F, M> ei;
110: try {
111: ei = builder.createElementInfo(this , m);
112: } catch (IllegalAnnotationException e) {
113: builder.reportError(e);
114: continue; // recover by ignoring this element
115: }
116:
117: // register this mapping
118: // TODO: any chance this could cause a stack overflow (by recursively visiting classes)?
119: builder.typeInfoSet.add(ei, builder);
120: references.add(ei);
121: }
122: }
123:
124: public Locatable getUpstream() {
125: return upstream;
126: }
127:
128: public Location getLocation() {
129: return nav.getClassLocation(registryClass);
130: }
131:
132: public Set<TypeInfo<T, C>> getReferences() {
133: return references;
134: }
135:
136: /**
137: * Gets the name of the package that this registry governs.
138: */
139: public String getPackageName() {
140: return nav.getPackageName(registryClass);
141: }
142:
143: public C getClazz() {
144: return registryClass;
145: }
146: }
|