src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/PropertyInfoImpl.java

Thu, 12 Oct 2017 19:44:07 +0800

author
aoqi
date
Thu, 12 Oct 2017 19:44:07 +0800
changeset 760
e530533619ec
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation. Oracle designates this
aoqi@0 8 * particular file as subject to the "Classpath" exception as provided
aoqi@0 9 * by Oracle in the LICENSE file that accompanied this code.
aoqi@0 10 *
aoqi@0 11 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 14 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 15 * accompanied this code).
aoqi@0 16 *
aoqi@0 17 * You should have received a copy of the GNU General Public License version
aoqi@0 18 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 20 *
aoqi@0 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 22 * or visit www.oracle.com if you need additional information or have any
aoqi@0 23 * questions.
aoqi@0 24 */
aoqi@0 25
aoqi@0 26 package com.sun.xml.internal.bind.v2.model.impl;
aoqi@0 27
aoqi@0 28 import java.util.Collection;
aoqi@0 29 import java.lang.annotation.Annotation;
aoqi@0 30
aoqi@0 31 import javax.activation.MimeType;
aoqi@0 32 import javax.xml.bind.annotation.XmlAttachmentRef;
aoqi@0 33 import javax.xml.bind.annotation.XmlElement;
aoqi@0 34 import javax.xml.bind.annotation.XmlElementWrapper;
aoqi@0 35 import javax.xml.bind.annotation.XmlID;
aoqi@0 36 import javax.xml.bind.annotation.XmlIDREF;
aoqi@0 37 import javax.xml.bind.annotation.XmlInlineBinaryData;
aoqi@0 38 import javax.xml.bind.annotation.XmlMimeType;
aoqi@0 39 import javax.xml.bind.annotation.XmlSchema;
aoqi@0 40 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
aoqi@0 41 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
aoqi@0 42 import javax.xml.bind.annotation.adapters.XmlAdapter;
aoqi@0 43 import javax.xml.namespace.QName;
aoqi@0 44
aoqi@0 45 import com.sun.xml.internal.bind.v2.TODO;
aoqi@0 46 import com.sun.xml.internal.bind.v2.model.annotation.AnnotationReader;
aoqi@0 47 import com.sun.xml.internal.bind.v2.model.annotation.Locatable;
aoqi@0 48 import com.sun.xml.internal.bind.v2.model.core.Adapter;
aoqi@0 49 import com.sun.xml.internal.bind.v2.model.core.ID;
aoqi@0 50 import com.sun.xml.internal.bind.v2.model.core.PropertyInfo;
aoqi@0 51 import com.sun.xml.internal.bind.v2.model.core.TypeInfo;
aoqi@0 52 import com.sun.xml.internal.bind.v2.model.core.TypeInfoSet;
aoqi@0 53 import com.sun.xml.internal.bind.v2.model.nav.Navigator;
aoqi@0 54 import com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationException;
aoqi@0 55 import com.sun.xml.internal.bind.v2.runtime.Location;
aoqi@0 56 import com.sun.xml.internal.bind.v2.runtime.SwaRefAdapter;
aoqi@0 57
aoqi@0 58 /**
aoqi@0 59 * Default partial implementation for {@link PropertyInfo}.
aoqi@0 60 *
aoqi@0 61 * @author Kohsuke Kawaguchi
aoqi@0 62 */
aoqi@0 63 abstract class PropertyInfoImpl<T,C,F,M>
aoqi@0 64 implements PropertyInfo<T,C>, Locatable, Comparable<PropertyInfoImpl> /*by their names*/ {
aoqi@0 65
aoqi@0 66 /**
aoqi@0 67 * Object that reads annotations.
aoqi@0 68 */
aoqi@0 69 protected final PropertySeed<T,C,F,M> seed;
aoqi@0 70
aoqi@0 71 private final boolean isCollection;
aoqi@0 72
aoqi@0 73 private final ID id;
aoqi@0 74
aoqi@0 75 private final MimeType expectedMimeType;
aoqi@0 76 private final boolean inlineBinary;
aoqi@0 77 private final QName schemaType;
aoqi@0 78
aoqi@0 79 protected final ClassInfoImpl<T,C,F,M> parent;
aoqi@0 80
aoqi@0 81 private final Adapter<T,C> adapter;
aoqi@0 82
aoqi@0 83 protected PropertyInfoImpl(ClassInfoImpl<T,C,F,M> parent, PropertySeed<T,C,F,M> spi) {
aoqi@0 84 this.seed = spi;
aoqi@0 85 this.parent = parent;
aoqi@0 86
aoqi@0 87 if(parent==null)
aoqi@0 88 /*
aoqi@0 89 Various people reported a bug where this parameter is somehow null.
aoqi@0 90 In an attempt to catch the error better, let's do an explicit check here.
aoqi@0 91
aoqi@0 92 http://forums.java.net/jive/thread.jspa?threadID=18479
aoqi@0 93 http://forums.java.net/jive/thread.jspa?messageID=165946
aoqi@0 94 */
aoqi@0 95 throw new AssertionError();
aoqi@0 96
aoqi@0 97 MimeType mt = Util.calcExpectedMediaType(seed,parent.builder);
aoqi@0 98 if(mt!=null && !kind().canHaveXmlMimeType) {
aoqi@0 99 parent.builder.reportError(new IllegalAnnotationException(
aoqi@0 100 Messages.ILLEGAL_ANNOTATION.format(XmlMimeType.class.getName()),
aoqi@0 101 seed.readAnnotation(XmlMimeType.class)
aoqi@0 102 ));
aoqi@0 103 mt = null;
aoqi@0 104 }
aoqi@0 105 this.expectedMimeType = mt;
aoqi@0 106 this.inlineBinary = seed.hasAnnotation(XmlInlineBinaryData.class);
aoqi@0 107
aoqi@0 108 T t = seed.getRawType();
aoqi@0 109
aoqi@0 110 // check if there's an adapter applicable to the whole property
aoqi@0 111 XmlJavaTypeAdapter xjta = getApplicableAdapter(t);
aoqi@0 112 if(xjta!=null) {
aoqi@0 113 isCollection = false;
aoqi@0 114 adapter = new Adapter<T,C>(xjta,reader(),nav());
aoqi@0 115 } else {
aoqi@0 116 // check if the adapter is applicable to the individual item in the property
aoqi@0 117
aoqi@0 118 this.isCollection = nav().isSubClassOf(t, nav().ref(Collection.class))
aoqi@0 119 || nav().isArrayButNotByteArray(t);
aoqi@0 120
aoqi@0 121 xjta = getApplicableAdapter(getIndividualType());
aoqi@0 122 if(xjta==null) {
aoqi@0 123 // ugly ugly hack, but we implement swaRef as adapter
aoqi@0 124 XmlAttachmentRef xsa = seed.readAnnotation(XmlAttachmentRef.class);
aoqi@0 125 if(xsa!=null) {
aoqi@0 126 parent.builder.hasSwaRef = true;
aoqi@0 127 adapter = new Adapter<T,C>(nav().asDecl(SwaRefAdapter.class),nav());
aoqi@0 128 } else {
aoqi@0 129 adapter = null;
aoqi@0 130
aoqi@0 131 // if this field has adapter annotation but not applicable,
aoqi@0 132 // that must be an error of the user
aoqi@0 133 xjta = seed.readAnnotation(XmlJavaTypeAdapter.class);
aoqi@0 134 if(xjta!=null) {
aoqi@0 135 T ad = reader().getClassValue(xjta,"value");
aoqi@0 136 parent.builder.reportError(new IllegalAnnotationException(
aoqi@0 137 Messages.UNMATCHABLE_ADAPTER.format(
aoqi@0 138 nav().getTypeName(ad), nav().getTypeName(t)),
aoqi@0 139 xjta
aoqi@0 140 ));
aoqi@0 141 }
aoqi@0 142 }
aoqi@0 143 } else {
aoqi@0 144 adapter = new Adapter<T,C>(xjta,reader(),nav());
aoqi@0 145 }
aoqi@0 146 }
aoqi@0 147
aoqi@0 148 this.id = calcId();
aoqi@0 149 this.schemaType = Util.calcSchemaType(reader(),seed,parent.clazz,
aoqi@0 150 getIndividualType(),this);
aoqi@0 151 }
aoqi@0 152
aoqi@0 153
aoqi@0 154 public ClassInfoImpl<T,C,F,M> parent() {
aoqi@0 155 return parent;
aoqi@0 156 }
aoqi@0 157
aoqi@0 158 protected final Navigator<T,C,F,M> nav() {
aoqi@0 159 return parent.nav();
aoqi@0 160 }
aoqi@0 161 protected final AnnotationReader<T,C,F,M> reader() {
aoqi@0 162 return parent.reader();
aoqi@0 163 }
aoqi@0 164
aoqi@0 165 public T getRawType() {
aoqi@0 166 return seed.getRawType();
aoqi@0 167 }
aoqi@0 168
aoqi@0 169 public T getIndividualType() {
aoqi@0 170 if(adapter!=null)
aoqi@0 171 return adapter.defaultType;
aoqi@0 172 T raw = getRawType();
aoqi@0 173 if(!isCollection()) {
aoqi@0 174 return raw;
aoqi@0 175 } else {
aoqi@0 176 if(nav().isArrayButNotByteArray(raw))
aoqi@0 177 return nav().getComponentType(raw);
aoqi@0 178
aoqi@0 179 T bt = nav().getBaseClass(raw, nav().asDecl(Collection.class) );
aoqi@0 180 if(nav().isParameterizedType(bt))
aoqi@0 181 return nav().getTypeArgument(bt,0);
aoqi@0 182 else
aoqi@0 183 return nav().ref(Object.class);
aoqi@0 184 }
aoqi@0 185 }
aoqi@0 186
aoqi@0 187 public final String getName() {
aoqi@0 188 return seed.getName();
aoqi@0 189 }
aoqi@0 190
aoqi@0 191 /**
aoqi@0 192 * Checks if the given adapter is applicable to the declared property type.
aoqi@0 193 */
aoqi@0 194 private boolean isApplicable(XmlJavaTypeAdapter jta, T declaredType ) {
aoqi@0 195 if(jta==null) return false;
aoqi@0 196
aoqi@0 197 T type = reader().getClassValue(jta,"type");
aoqi@0 198 if(nav().isSameType(declaredType, type))
aoqi@0 199 return true; // for types explicitly marked in XmlJavaTypeAdapter.type()
aoqi@0 200
aoqi@0 201 T ad = reader().getClassValue(jta,"value");
aoqi@0 202 T ba = nav().getBaseClass(ad, nav().asDecl(XmlAdapter.class));
aoqi@0 203 if(!nav().isParameterizedType(ba))
aoqi@0 204 return true; // can't check type applicability. assume Object, which means applicable to any.
aoqi@0 205 T inMemType = nav().getTypeArgument(ba, 1);
aoqi@0 206
aoqi@0 207 return nav().isSubClassOf(declaredType,inMemType);
aoqi@0 208 }
aoqi@0 209
aoqi@0 210 private XmlJavaTypeAdapter getApplicableAdapter(T type) {
aoqi@0 211 XmlJavaTypeAdapter jta = seed.readAnnotation(XmlJavaTypeAdapter.class);
aoqi@0 212 if(jta!=null && isApplicable(jta,type))
aoqi@0 213 return jta;
aoqi@0 214
aoqi@0 215 // check the applicable adapters on the package
aoqi@0 216 XmlJavaTypeAdapters jtas = reader().getPackageAnnotation(XmlJavaTypeAdapters.class, parent.clazz, seed );
aoqi@0 217 if(jtas!=null) {
aoqi@0 218 for (XmlJavaTypeAdapter xjta : jtas.value()) {
aoqi@0 219 if(isApplicable(xjta,type))
aoqi@0 220 return xjta;
aoqi@0 221 }
aoqi@0 222 }
aoqi@0 223 jta = reader().getPackageAnnotation(XmlJavaTypeAdapter.class, parent.clazz, seed );
aoqi@0 224 if(isApplicable(jta,type))
aoqi@0 225 return jta;
aoqi@0 226
aoqi@0 227 // then on the target class
aoqi@0 228 C refType = nav().asDecl(type);
aoqi@0 229 if(refType!=null) {
aoqi@0 230 jta = reader().getClassAnnotation(XmlJavaTypeAdapter.class, refType, seed );
aoqi@0 231 if(jta!=null && isApplicable(jta,type)) // the one on the type always apply.
aoqi@0 232 return jta;
aoqi@0 233 }
aoqi@0 234
aoqi@0 235 return null;
aoqi@0 236 }
aoqi@0 237
aoqi@0 238 /**
aoqi@0 239 * This is the default implementation of the getAdapter method
aoqi@0 240 * defined on many of the {@link PropertyInfo}-derived classes.
aoqi@0 241 */
aoqi@0 242 public Adapter<T,C> getAdapter() {
aoqi@0 243 return adapter;
aoqi@0 244 }
aoqi@0 245
aoqi@0 246
aoqi@0 247 public final String displayName() {
aoqi@0 248 return nav().getClassName(parent.getClazz())+'#'+getName();
aoqi@0 249 }
aoqi@0 250
aoqi@0 251 public final ID id() {
aoqi@0 252 return id;
aoqi@0 253 }
aoqi@0 254
aoqi@0 255 private ID calcId() {
aoqi@0 256 if(seed.hasAnnotation(XmlID.class)) {
aoqi@0 257 // check the type
aoqi@0 258 if(!nav().isSameType(getIndividualType(), nav().ref(String.class)))
aoqi@0 259 parent.builder.reportError(new IllegalAnnotationException(
aoqi@0 260 Messages.ID_MUST_BE_STRING.format(getName()), seed )
aoqi@0 261 );
aoqi@0 262 return ID.ID;
aoqi@0 263 } else
aoqi@0 264 if(seed.hasAnnotation(XmlIDREF.class)) {
aoqi@0 265 return ID.IDREF;
aoqi@0 266 } else {
aoqi@0 267 return ID.NONE;
aoqi@0 268 }
aoqi@0 269 }
aoqi@0 270
aoqi@0 271 public final MimeType getExpectedMimeType() {
aoqi@0 272 return expectedMimeType;
aoqi@0 273 }
aoqi@0 274
aoqi@0 275 public final boolean inlineBinaryData() {
aoqi@0 276 return inlineBinary;
aoqi@0 277 }
aoqi@0 278
aoqi@0 279 public final QName getSchemaType() {
aoqi@0 280 return schemaType;
aoqi@0 281 }
aoqi@0 282
aoqi@0 283 public final boolean isCollection() {
aoqi@0 284 return isCollection;
aoqi@0 285 }
aoqi@0 286
aoqi@0 287 /**
aoqi@0 288 * Called after all the {@link TypeInfo}s are collected into the governing {@link TypeInfoSet}.
aoqi@0 289 *
aoqi@0 290 * Derived class can do additional actions to complete the model.
aoqi@0 291 */
aoqi@0 292 protected void link() {
aoqi@0 293 if(id==ID.IDREF) {
aoqi@0 294 // make sure that the refereced type has ID
aoqi@0 295 for (TypeInfo<T,C> ti : ref()) {
aoqi@0 296 if(!ti.canBeReferencedByIDREF())
aoqi@0 297 parent.builder.reportError(new IllegalAnnotationException(
aoqi@0 298 Messages.INVALID_IDREF.format(
aoqi@0 299 parent.builder.nav.getTypeName(ti.getType())), this ));
aoqi@0 300 }
aoqi@0 301 }
aoqi@0 302 }
aoqi@0 303
aoqi@0 304 /**
aoqi@0 305 * A {@link PropertyInfoImpl} is always referenced by its enclosing class,
aoqi@0 306 * so return that as the upstream.
aoqi@0 307 */
aoqi@0 308 public Locatable getUpstream() {
aoqi@0 309 return parent;
aoqi@0 310 }
aoqi@0 311
aoqi@0 312 public Location getLocation() {
aoqi@0 313 return seed.getLocation();
aoqi@0 314 }
aoqi@0 315
aoqi@0 316
aoqi@0 317 //
aoqi@0 318 //
aoqi@0 319 // convenience methods for derived classes
aoqi@0 320 //
aoqi@0 321 //
aoqi@0 322
aoqi@0 323
aoqi@0 324 /**
aoqi@0 325 * Computes the tag name from a {@link XmlElement} by taking the defaulting into account.
aoqi@0 326 */
aoqi@0 327 protected final QName calcXmlName(XmlElement e) {
aoqi@0 328 if(e!=null)
aoqi@0 329 return calcXmlName(e.namespace(),e.name());
aoqi@0 330 else
aoqi@0 331 return calcXmlName("##default","##default");
aoqi@0 332 }
aoqi@0 333
aoqi@0 334 /**
aoqi@0 335 * Computes the tag name from a {@link XmlElementWrapper} by taking the defaulting into account.
aoqi@0 336 */
aoqi@0 337 protected final QName calcXmlName(XmlElementWrapper e) {
aoqi@0 338 if(e!=null)
aoqi@0 339 return calcXmlName(e.namespace(),e.name());
aoqi@0 340 else
aoqi@0 341 return calcXmlName("##default","##default");
aoqi@0 342 }
aoqi@0 343
aoqi@0 344 private QName calcXmlName(String uri,String local) {
aoqi@0 345 // compute the default
aoqi@0 346 TODO.checkSpec();
aoqi@0 347 if(local.length()==0 || local.equals("##default"))
aoqi@0 348 local = seed.getName();
aoqi@0 349 if(uri.equals("##default")) {
aoqi@0 350 XmlSchema xs = reader().getPackageAnnotation( XmlSchema.class, parent.getClazz(), this );
aoqi@0 351 // JAX-RPC doesn't want the default namespace URI swapping to take effect to
aoqi@0 352 // local "unqualified" elements. UGLY.
aoqi@0 353 if(xs!=null) {
aoqi@0 354 switch(xs.elementFormDefault()) {
aoqi@0 355 case QUALIFIED:
aoqi@0 356 QName typeName = parent.getTypeName();
aoqi@0 357 if(typeName!=null)
aoqi@0 358 uri = typeName.getNamespaceURI();
aoqi@0 359 else
aoqi@0 360 uri = xs.namespace();
aoqi@0 361 if(uri.length()==0)
aoqi@0 362 uri = parent.builder.defaultNsUri;
aoqi@0 363 break;
aoqi@0 364 case UNQUALIFIED:
aoqi@0 365 case UNSET:
aoqi@0 366 uri = "";
aoqi@0 367 }
aoqi@0 368 } else {
aoqi@0 369 uri = "";
aoqi@0 370 }
aoqi@0 371 }
aoqi@0 372 return new QName(uri.intern(),local.intern());
aoqi@0 373 }
aoqi@0 374
aoqi@0 375 public int compareTo(PropertyInfoImpl that) {
aoqi@0 376 return this.getName().compareTo(that.getName());
aoqi@0 377 }
aoqi@0 378
aoqi@0 379 public final <A extends Annotation> A readAnnotation(Class<A> annotationType) {
aoqi@0 380 return seed.readAnnotation(annotationType);
aoqi@0 381 }
aoqi@0 382
aoqi@0 383 public final boolean hasAnnotation(Class<? extends Annotation> annotationType) {
aoqi@0 384 return seed.hasAnnotation(annotationType);
aoqi@0 385 }
aoqi@0 386 }

mercurial