CReferencePropertyInfo.java revision 567:42d4089329e7
1233294Sstas/*
2178825Sdfr * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
3178825Sdfr * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4178825Sdfr *
5233294Sstas * This code is free software; you can redistribute it and/or modify it
6233294Sstas * under the terms of the GNU General Public License version 2 only, as
7178825Sdfr * published by the Free Software Foundation.  Oracle designates this
8178825Sdfr * particular file as subject to the "Classpath" exception as provided
9178825Sdfr * by Oracle in the LICENSE file that accompanied this code.
10178825Sdfr *
11178825Sdfr * This code is distributed in the hope that it will be useful, but WITHOUT
12178825Sdfr * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13178825Sdfr * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14178825Sdfr * version 2 for more details (a copy is included in the LICENSE file that
15178825Sdfr * accompanied this code).
16178825Sdfr *
17178825Sdfr * You should have received a copy of the GNU General Public License version
18233294Sstas * 2 along with this work; if not, write to the Free Software Foundation,
19178825Sdfr * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20233294Sstas *
21178825Sdfr * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22233294Sstas * or visit www.oracle.com if you need additional information or have any
23178825Sdfr * questions.
24178825Sdfr */
25178825Sdfr
26233294Sstaspackage com.sun.tools.internal.xjc.model;
27178825Sdfr
28233294Sstasimport java.util.Collection;
29178825Sdfrimport java.util.LinkedHashSet;
30178825Sdfrimport java.util.Set;
31178825Sdfrimport java.util.Map;
32178825Sdfr
33178825Sdfrimport javax.activation.MimeType;
34178825Sdfrimport javax.xml.bind.annotation.W3CDomHandler;
35178825Sdfrimport javax.xml.namespace.QName;
36178825Sdfr
37178825Sdfrimport com.sun.tools.internal.xjc.model.nav.NClass;
38178825Sdfrimport com.sun.tools.internal.xjc.model.nav.NType;
39178825Sdfrimport com.sun.tools.internal.xjc.model.nav.NavigatorImpl;
40178825Sdfrimport com.sun.xml.internal.bind.v2.model.core.ID;
41178825Sdfrimport com.sun.xml.internal.bind.v2.model.core.PropertyKind;
42178825Sdfrimport com.sun.xml.internal.bind.v2.model.core.ReferencePropertyInfo;
43178825Sdfrimport com.sun.xml.internal.bind.v2.model.core.WildcardMode;
44178825Sdfrimport com.sun.xml.internal.xsom.XSComponent;
45178825Sdfr
46178825Sdfrimport org.xml.sax.Locator;
47178825Sdfr
48178825Sdfr/**
49178825Sdfr * {@link ReferencePropertyInfo} for the compiler.
50233294Sstas *
51178825Sdfr * @author Kohsuke Kawaguchi
52178825Sdfr */
53178825Sdfrpublic final class CReferencePropertyInfo extends CPropertyInfo implements ReferencePropertyInfo<NType,NClass> {
54178825Sdfr
55178825Sdfr    /**
56178825Sdfr     * True if this property can never be absent legally.
57178825Sdfr     */
58178825Sdfr    private final boolean required;
59178825Sdfr
60178825Sdfr    /**
61178825Sdfr     * List of referenced elements.
62178825Sdfr     */
63178825Sdfr    private final Set<CElement> elements = new LinkedHashSet<CElement>();
64178825Sdfr
65233294Sstas    private final boolean isMixed;
66178825Sdfr    private WildcardMode wildcard;
67178825Sdfr    private boolean dummy;
68178825Sdfr    private boolean content;
69178825Sdfr    private boolean isMixedExtendedCust = false;
70178825Sdfr
71178825Sdfr    public CReferencePropertyInfo(String name, boolean collection, boolean required, boolean isMixed, XSComponent source,
72178825Sdfr                                  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
73178825Sdfr        super(name, (collection||isMixed) && (!dummy), source, customizations, locator);
74178825Sdfr        this.isMixed = isMixed;
75178825Sdfr        this.required = required;
76178825Sdfr        this.dummy = dummy;
77178825Sdfr        this.content = content;
78178825Sdfr        this.isMixedExtendedCust = isMixedExtended;
79233294Sstas    }
80233294Sstas
81233294Sstas    public Set<? extends CTypeInfo> ref() {
82233294Sstas//        if(wildcard==null && !isMixed())
83233294Sstas//            return getElements();
84233294Sstas
85178825Sdfr        // ugly hack to get the signature right for substitution groups
86178825Sdfr        // when a class is generated for elements,they don't form a nice type hierarchy,
87178825Sdfr        // so the Java types of the substitution members need to be taken into account
88178825Sdfr        // when computing the signature
89178825Sdfr
90178825Sdfr        final class RefList extends LinkedHashSet<CTypeInfo> {
91178825Sdfr            RefList() {
92233294Sstas                super(elements.size());
93178825Sdfr                addAll(elements);
94178825Sdfr            }
95178825Sdfr            @Override
96178825Sdfr            public boolean addAll( Collection<? extends CTypeInfo> col ) {
97178825Sdfr                boolean r = false;
98233294Sstas                for (CTypeInfo e : col) {
99178825Sdfr                    if(e instanceof CElementInfo) {
100178825Sdfr                        // UGLY. element substitution is implemented in a way that
101178825Sdfr                        // the derived elements are not assignable to base elements.
102178825Sdfr                        // so when we compute the signature, we have to take derived types
103233294Sstas                        // into account
104233294Sstas                        r |= addAll( ((CElementInfo)e).getSubstitutionMembers());
105178825Sdfr                    }
106178825Sdfr                    r |= add(e);
107178825Sdfr                }
108178825Sdfr                return r;
109233294Sstas            }
110233294Sstas        }
111233294Sstas
112233294Sstas        RefList r = new RefList();
113178825Sdfr        if(wildcard!=null) {
114233294Sstas            if(wildcard.allowDom)
115233294Sstas                r.add(CWildcardTypeInfo.INSTANCE);
116233294Sstas            if(wildcard.allowTypedObject)
117178825Sdfr                // we aren't really adding an AnyType.
118178825Sdfr                // this is a kind of hack to generate Object as a signature
119178825Sdfr                r.add(CBuiltinLeafInfo.ANYTYPE);
120178825Sdfr        }
121178825Sdfr        if(isMixed())
122178825Sdfr            r.add(CBuiltinLeafInfo.STRING);
123178825Sdfr
124178825Sdfr        return r;
125178825Sdfr    }
126178825Sdfr
127178825Sdfr    public Set<CElement> getElements() {
128233294Sstas        return elements;
129233294Sstas    }
130233294Sstas
131233294Sstas    public boolean isMixed() {
132233294Sstas        return isMixed;
133233294Sstas    }
134233294Sstas
135233294Sstas    public boolean isDummy() {
136233294Sstas        return dummy;
137233294Sstas    }
138233294Sstas
139233294Sstas    public boolean isContent() {
140233294Sstas        return content;
141233294Sstas    }
142233294Sstas
143233294Sstas    public boolean isMixedExtendedCust() {
144233294Sstas        return isMixedExtendedCust;
145233294Sstas    }
146233294Sstas
147233294Sstas    /**
148233294Sstas     * We'll never use a wrapper element in XJC. Always return null.
149178825Sdfr     */
150178825Sdfr    @Deprecated
151178825Sdfr    public QName getXmlName() {
152178825Sdfr        return null;
153178825Sdfr    }
154178825Sdfr
155178825Sdfr    /**
156178825Sdfr     * Reference properties refer to elements, and none of the Java primitive type
157178825Sdfr     * maps to an element. Thus a reference property is always unboxable.
158233294Sstas     */
159233294Sstas    @Override
160178825Sdfr    public boolean isUnboxable() {
161178825Sdfr        return false;
162178825Sdfr    }
163178825Sdfr
164178825Sdfr    // the same as above
165233294Sstas    @Override
166233294Sstas    public boolean isOptionalPrimitive() {
167178825Sdfr        return false;
168178825Sdfr    }
169178825Sdfr
170233294Sstas    public <V> V accept(CPropertyVisitor<V> visitor) {
171178825Sdfr        return visitor.onReference(this);
172178825Sdfr    }
173178825Sdfr
174178825Sdfr    @Override
175178825Sdfr    public <R, P> R accept(CPropertyVisitor2<R, P> visitor, P p) {
176233294Sstas        return visitor.visit(this, p);
177178825Sdfr    }
178178825Sdfr
179233294Sstas    public CAdapter getAdapter() {
180178825Sdfr        return null;
181178825Sdfr    }
182178825Sdfr
183178825Sdfr    public final PropertyKind kind() {
184233294Sstas        return PropertyKind.REFERENCE;
185233294Sstas    }
186233294Sstas
187178825Sdfr    /**
188178825Sdfr     * A reference property can never be ID/IDREF because they always point to
189178825Sdfr     * other element classes.
190178825Sdfr     */
191178825Sdfr    public ID id() {
192233294Sstas        return ID.NONE;
193178825Sdfr    }
194178825Sdfr
195178825Sdfr    public WildcardMode getWildcard() {
196178825Sdfr        return wildcard;
197178825Sdfr    }
198178825Sdfr
199233294Sstas    public void setWildcard(WildcardMode mode) {
200233294Sstas        this.wildcard = mode;
201178825Sdfr    }
202178825Sdfr
203233294Sstas    public NClass getDOMHandler() {
204178825Sdfr        // TODO: support other DOM handlers
205178825Sdfr        if(getWildcard()!=null)
206178825Sdfr            return NavigatorImpl.create(W3CDomHandler.class);
207178825Sdfr        else
208178825Sdfr            return null;
209233294Sstas    }
210178825Sdfr
211178825Sdfr    public MimeType getExpectedMimeType() {
212178825Sdfr        return null;
213178825Sdfr    }
214178825Sdfr
215178825Sdfr    public boolean isCollectionNillable() {
216178825Sdfr        // in XJC, we never recognize a nillable collection pattern, so this is always false.
217178825Sdfr        return false;
218178825Sdfr    }
219178825Sdfr
220178825Sdfr    public boolean isCollectionRequired() {
221178825Sdfr        // in XJC, we never recognize a nillable collection pattern, so this is always false.
222178825Sdfr        return false;
223178825Sdfr    }
224178825Sdfr
225178825Sdfr    // reference property cannot have a type.
226178825Sdfr    public QName getSchemaType() {
227178825Sdfr        return null;
228178825Sdfr    }
229178825Sdfr
230178825Sdfr    public boolean isRequired() {
231178825Sdfr        return required;
232178825Sdfr    }
233233294Sstas
234178825Sdfr    @Override
235178825Sdfr    public QName collectElementNames(Map<QName, CPropertyInfo> table) {
236233294Sstas        for (CElement e : elements) {
237178825Sdfr            QName n = e.getElementName();
238178825Sdfr            if(table.containsKey(n))
239178825Sdfr                return n;
240178825Sdfr            table.put(n,this);
241178825Sdfr        }
242178825Sdfr        return null;
243178825Sdfr    }
244178825Sdfr}
245178825Sdfr