1/*
2 * Copyright (c) 1997, 2014, 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
26package com.sun.tools.internal.xjc.model;
27
28import java.util.AbstractList;
29import java.util.ArrayList;
30import java.util.List;
31import java.util.Map;
32
33import javax.activation.MimeType;
34import javax.xml.namespace.QName;
35
36import com.sun.tools.internal.xjc.model.nav.NClass;
37import com.sun.tools.internal.xjc.model.nav.NType;
38import com.sun.tools.internal.xjc.reader.RawTypeSet;
39import com.sun.xml.internal.bind.v2.model.core.ElementPropertyInfo;
40import com.sun.xml.internal.bind.v2.model.core.ID;
41import com.sun.xml.internal.bind.v2.model.core.PropertyKind;
42import com.sun.xml.internal.xsom.XSComponent;
43
44import org.xml.sax.Locator;
45
46/**
47 * {@link ElementPropertyInfo} for the compiler.
48 *
49 * @author Kohsuke Kawaguchi
50 */
51public final class CElementPropertyInfo extends CPropertyInfo implements ElementPropertyInfo<NType,NClass> {
52
53    /**
54     * True if this property can never be absent legally.
55     */
56    private final boolean required;
57
58    private final MimeType expectedMimeType;
59    /**
60     *
61     * <p>
62     * Currently, this is set inside {@link RawTypeSet} in a very ugly way.
63     */
64    private CAdapter adapter;
65
66    private final boolean isValueList;
67
68    private ID id;
69
70
71    /**
72     * List of referenced types.
73     */
74    private final List<CTypeRef> types = new ArrayList<CTypeRef>();
75
76    private final List<CNonElement> ref = new AbstractList<CNonElement>() {
77        public CNonElement get(int index) {
78            return getTypes().get(index).getTarget();
79        }
80        public int size() {
81            return getTypes().size();
82        }
83    };
84
85    // TODO: shouldn't they get id and expectedMimeType from TypeUses of CTypeRef?
86    public CElementPropertyInfo(String name, CollectionMode collection, ID id, MimeType expectedMimeType, XSComponent source,
87                                CCustomizations customizations, Locator locator, boolean required) {
88        super(name, collection.col, source, customizations, locator);
89        this.required = required;
90        this.id = id;
91        this.expectedMimeType = expectedMimeType;
92        this.isValueList = collection.val;
93    }
94
95    public ID id() {
96        return id;
97    }
98
99    public List<CTypeRef> getTypes() {
100        return types;
101    }
102
103    public List<CNonElement> ref() {
104        return ref;
105    }
106
107    public QName getSchemaType() {
108        if(types.size()!=1)
109            // if more than one kind is here, can't produce @XmlSchemaType.
110            // TODO: is it allowed to have one generated if types
111            return null;
112
113        CTypeRef t = types.get(0);
114        if(needsExplicitTypeName(t.getTarget(),t.typeName))
115            return t.typeName;
116        else
117            return null;
118    }
119
120    /**
121     * XJC never uses the wrapper element. Always return null.
122     */
123    @Deprecated
124    public QName getXmlName() {
125        return null;
126    }
127
128    public boolean isCollectionRequired() {
129        // in XJC, we never recognize a nillable collection pattern, so this is always false.
130        return false;
131    }
132
133    public boolean isCollectionNillable() {
134        // in XJC, we never recognize a nillable collection pattern, so this is always false.
135        return false;
136    }
137
138    public boolean isRequired() {
139        return required;
140    }
141
142    public boolean isValueList() {
143        return isValueList;
144    }
145
146    public boolean isUnboxable() {
147        if(!isCollection() && !required)
148            // if the property can be legally absent, it's not unboxable
149            return false;
150        // we need to have null to represent the absence of value. not unboxable.
151        for (CTypeRef t : getTypes()) {
152            if(t.isNillable())
153                return false;
154        }
155        return super.isUnboxable();
156    }
157
158    @Override
159    public boolean isOptionalPrimitive() {
160        // we need to have null to represent the absence of value. not unboxable.
161        for (CTypeRef t : getTypes()) {
162            if(t.isNillable())
163                return false;
164        }
165        return !isCollection() && !required && super.isUnboxable();
166    }
167
168    public <V> V accept(CPropertyVisitor<V> visitor) {
169        return visitor.onElement(this);
170    }
171
172    @Override
173    public <R, P> R accept(CPropertyVisitor2<R, P> visitor, P p) {
174        return visitor.visit(this, p);
175    }
176
177    public CAdapter getAdapter() {
178        return adapter;
179    }
180
181    public void setAdapter(CAdapter a) {
182        assert adapter==null;
183        adapter = a;
184    }
185
186    public final PropertyKind kind() {
187        return PropertyKind.ELEMENT;
188    }
189
190    public MimeType getExpectedMimeType() {
191        return expectedMimeType;
192    }
193
194    public static enum CollectionMode {
195        NOT_REPEATED(false,false),
196        REPEATED_ELEMENT(true,false),
197        REPEATED_VALUE(true,true);
198
199        private final boolean col,val;
200
201        CollectionMode(boolean col,boolean val) {
202            this.col = col;
203            this.val = val;
204        }
205
206        public boolean isRepeated() { return col; }
207    }
208
209    @Override
210    public QName collectElementNames(Map<QName, CPropertyInfo> table) {
211        for (CTypeRef t : types) {
212            QName n = t.getTagName();
213            if(table.containsKey(n))    return n;
214            table.put(n, this);
215        }
216        return null;
217    }
218}
219