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.AbstractList;
  29 import java.util.ArrayList;
  30 import java.util.List;
  31 import java.util.Map;
  32 
  33 import javax.activation.MimeType;
  34 import javax.xml.namespace.QName;
  35 
  36 import com.sun.tools.internal.xjc.model.nav.NClass;
  37 import com.sun.tools.internal.xjc.model.nav.NType;
  38 import com.sun.tools.internal.xjc.reader.RawTypeSet;
  39 import com.sun.xml.internal.bind.v2.model.core.ElementPropertyInfo;
  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.xsom.XSComponent;
  43 
  44 import org.xml.sax.Locator;
  45 
  46 /**
  47  * {@link ElementPropertyInfo} for the compiler.
  48  *
  49  * @author Kohsuke Kawaguchi
  50  */
  51 public 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     public CAdapter getAdapter() {
 173         return adapter;
 174     }
 175 
 176     public void setAdapter(CAdapter a) {
 177         assert adapter==null;
 178         adapter = a;
 179     }
 180 
 181     public final PropertyKind kind() {
 182         return PropertyKind.ELEMENT;
 183     }
 184 
 185     public MimeType getExpectedMimeType() {
 186         return expectedMimeType;
 187     }
 188 
 189     public static enum CollectionMode {
 190         NOT_REPEATED(false,false),
 191         REPEATED_ELEMENT(true,false),
 192         REPEATED_VALUE(true,true);
 193 
 194         private final boolean col,val;
 195 
 196         CollectionMode(boolean col,boolean val) {
 197             this.col = col;
 198             this.val = val;
 199         }
 200 
 201         public boolean isRepeated() { return col; }
 202     }
 203 
 204     @Override
 205     public QName collectElementNames(Map<QName, CPropertyInfo> table) {
 206         for (CTypeRef t : types) {
 207             QName n = t.getTagName();
 208             if(table.containsKey(n))    return n;
 209             table.put(n, this);
 210         }
 211         return null;
 212     }
 213 }