View Javadoc
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.model;
27  
28  import java.util.Collection;
29  import java.util.HashSet;
30  import java.util.Set;
31  import java.util.Map;
32  
33  import javax.activation.MimeType;
34  import javax.xml.bind.annotation.W3CDomHandler;
35  import javax.xml.namespace.QName;
36  
37  import com.sun.tools.internal.xjc.model.nav.NClass;
38  import com.sun.tools.internal.xjc.model.nav.NType;
39  import com.sun.tools.internal.xjc.model.nav.NavigatorImpl;
40  import com.sun.xml.internal.bind.v2.model.core.ID;
41  import com.sun.xml.internal.bind.v2.model.core.PropertyKind;
42  import com.sun.xml.internal.bind.v2.model.core.ReferencePropertyInfo;
43  import com.sun.xml.internal.bind.v2.model.core.WildcardMode;
44  import com.sun.xml.internal.xsom.XSComponent;
45  
46  import org.xml.sax.Locator;
47  
48  /**
49   * {@link ReferencePropertyInfo} for the compiler.
50   *
51   * @author Kohsuke Kawaguchi
52   */
53  public final class CReferencePropertyInfo extends CPropertyInfo implements ReferencePropertyInfo<NType,NClass> {
54  
55      /**
56       * True if this property can never be absent legally.
57       */
58      private final boolean required;
59  
60      /**
61       * List of referenced elements.
62       */
63      private final Set<CElement> elements = new HashSet<CElement>();
64  
65      private final boolean isMixed;
66      private WildcardMode wildcard;
67      private boolean dummy;
68      private boolean content;
69      private boolean isMixedExtendedCust = false;
70  
71      public CReferencePropertyInfo(String name, boolean collection, boolean required, boolean isMixed, XSComponent source,
72                                    CCustomizations customizations, Locator locator, boolean dummy, boolean content, boolean isMixedExtended) {   // 'dummy' and 'content' here for NHIN fix - a hack in order to be able to handle extended mixed types better
73          super(name, (collection||isMixed) && (!dummy), source, customizations, locator);
74          this.isMixed = isMixed;
75          this.required = required;
76          this.dummy = dummy;
77          this.content = content;
78          this.isMixedExtendedCust = isMixedExtended;
79      }
80  
81      public Set<? extends CTypeInfo> ref() {
82  //        if(wildcard==null && !isMixed())
83  //            return getElements();
84  
85          // ugly hack to get the signature right for substitution groups
86          // when a class is generated for elements,they don't form a nice type hierarchy,
87          // so the Java types of the substitution members need to be taken into account
88          // when computing the signature
89  
90          final class RefList extends HashSet<CTypeInfo> {
91              RefList() {
92                  super(elements.size());
93                  addAll(elements);
94              }
95              @Override
96              public boolean addAll( Collection<? extends CTypeInfo> col ) {
97                  boolean r = false;
98                  for (CTypeInfo e : col) {
99                      if(e instanceof CElementInfo) {
100                         // UGLY. element substitution is implemented in a way that
101                         // the derived elements are not assignable to base elements.
102                         // so when we compute the signature, we have to take derived types
103                         // into account
104                         r |= addAll( ((CElementInfo)e).getSubstitutionMembers());
105                     }
106                     r |= add(e);
107                 }
108                 return r;
109             }
110         }
111 
112         RefList r = new RefList();
113         if(wildcard!=null) {
114             if(wildcard.allowDom)
115                 r.add(CWildcardTypeInfo.INSTANCE);
116             if(wildcard.allowTypedObject)
117                 // we aren't really adding an AnyType.
118                 // this is a kind of hack to generate Object as a signature
119                 r.add(CBuiltinLeafInfo.ANYTYPE);
120         }
121         if(isMixed())
122             r.add(CBuiltinLeafInfo.STRING);
123 
124         return r;
125     }
126 
127     public Set<CElement> getElements() {
128         return elements;
129     }
130 
131     public boolean isMixed() {
132         return isMixed;
133     }
134 
135     public boolean isDummy() {
136         return dummy;
137     }
138 
139     public boolean isContent() {
140         return content;
141     }
142 
143     public boolean isMixedExtendedCust() {
144         return isMixedExtendedCust;
145     }
146 
147     /**
148      * We'll never use a wrapper element in XJC. Always return null.
149      */
150     @Deprecated
151     public QName getXmlName() {
152         return null;
153     }
154 
155     /**
156      * Reference properties refer to elements, and none of the Java primitive type
157      * maps to an element. Thus a reference property is always unboxable.
158      */
159     @Override
160     public boolean isUnboxable() {
161         return false;
162     }
163 
164     // the same as above
165     @Override
166     public boolean isOptionalPrimitive() {
167         return false;
168     }
169 
170     public <V> V accept(CPropertyVisitor<V> visitor) {
171         return visitor.onReference(this);
172     }
173 
174     public CAdapter getAdapter() {
175         return null;
176     }
177 
178     public final PropertyKind kind() {
179         return PropertyKind.REFERENCE;
180     }
181 
182     /**
183      * A reference property can never be ID/IDREF because they always point to
184      * other element classes.
185      */
186     public ID id() {
187         return ID.NONE;
188     }
189 
190     public WildcardMode getWildcard() {
191         return wildcard;
192     }
193 
194     public void setWildcard(WildcardMode mode) {
195         this.wildcard = mode;
196     }
197 
198     public NClass getDOMHandler() {
199         // TODO: support other DOM handlers
200         if(getWildcard()!=null)
201             return NavigatorImpl.create(W3CDomHandler.class);
202         else
203             return null;
204     }
205 
206     public MimeType getExpectedMimeType() {
207         return null;
208     }
209 
210     public boolean isCollectionNillable() {
211         // in XJC, we never recognize a nillable collection pattern, so this is always false.
212         return false;
213     }
214 
215     public boolean isCollectionRequired() {
216         // in XJC, we never recognize a nillable collection pattern, so this is always false.
217         return false;
218     }
219 
220     // reference property cannot have a type.
221     public QName getSchemaType() {
222         return null;
223     }
224 
225     public boolean isRequired() {
226         return required;
227     }
228 
229     @Override
230     public QName collectElementNames(Map<QName, CPropertyInfo> table) {
231         for (CElement e : elements) {
232             QName n = e.getElementName();
233             if(table.containsKey(n))
234                 return n;
235             table.put(n,this);
236         }
237         return null;
238     }
239 }