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

     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  */
    26 package com.sun.xml.internal.bind.v2.model.impl;
    28 import java.util.Collection;
    29 import java.lang.annotation.Annotation;
    31 import javax.activation.MimeType;
    32 import javax.xml.bind.annotation.XmlAttachmentRef;
    33 import javax.xml.bind.annotation.XmlElement;
    34 import javax.xml.bind.annotation.XmlElementWrapper;
    35 import javax.xml.bind.annotation.XmlID;
    36 import javax.xml.bind.annotation.XmlIDREF;
    37 import javax.xml.bind.annotation.XmlInlineBinaryData;
    38 import javax.xml.bind.annotation.XmlMimeType;
    39 import javax.xml.bind.annotation.XmlSchema;
    40 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
    41 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
    42 import javax.xml.bind.annotation.adapters.XmlAdapter;
    43 import javax.xml.namespace.QName;
    45 import com.sun.xml.internal.bind.v2.TODO;
    46 import com.sun.xml.internal.bind.v2.model.annotation.AnnotationReader;
    47 import com.sun.xml.internal.bind.v2.model.annotation.Locatable;
    48 import com.sun.xml.internal.bind.v2.model.core.Adapter;
    49 import com.sun.xml.internal.bind.v2.model.core.ID;
    50 import com.sun.xml.internal.bind.v2.model.core.PropertyInfo;
    51 import com.sun.xml.internal.bind.v2.model.core.TypeInfo;
    52 import com.sun.xml.internal.bind.v2.model.core.TypeInfoSet;
    53 import com.sun.xml.internal.bind.v2.model.nav.Navigator;
    54 import com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationException;
    55 import com.sun.xml.internal.bind.v2.runtime.Location;
    56 import com.sun.xml.internal.bind.v2.runtime.SwaRefAdapter;
    58 /**
    59  * Default partial implementation for {@link PropertyInfo}.
    60  *
    61  * @author Kohsuke Kawaguchi
    62  */
    63 abstract class PropertyInfoImpl<T,C,F,M>
    64     implements PropertyInfo<T,C>, Locatable, Comparable<PropertyInfoImpl> /*by their names*/ {
    66     /**
    67      * Object that reads annotations.
    68      */
    69     protected final PropertySeed<T,C,F,M> seed;
    71     private final boolean isCollection;
    73     private final ID id;
    75     private final MimeType expectedMimeType;
    76     private final boolean inlineBinary;
    77     private final QName schemaType;
    79     protected final ClassInfoImpl<T,C,F,M> parent;
    81     private final Adapter<T,C> adapter;
    83     protected PropertyInfoImpl(ClassInfoImpl<T,C,F,M> parent, PropertySeed<T,C,F,M> spi) {
    84         this.seed = spi;
    85         this.parent = parent;
    87         if(parent==null)
    88             /*
    89                 Various people reported a bug where this parameter is somehow null.
    90                 In an attempt to catch the error better, let's do an explicit check here.
    92                 http://forums.java.net/jive/thread.jspa?threadID=18479
    93                 http://forums.java.net/jive/thread.jspa?messageID=165946
    94              */
    95             throw new AssertionError();
    97         MimeType mt = Util.calcExpectedMediaType(seed,parent.builder);
    98         if(mt!=null && !kind().canHaveXmlMimeType) {
    99             parent.builder.reportError(new IllegalAnnotationException(
   100                 Messages.ILLEGAL_ANNOTATION.format(XmlMimeType.class.getName()),
   101                 seed.readAnnotation(XmlMimeType.class)
   102             ));
   103             mt = null;
   104         }
   105         this.expectedMimeType = mt;
   106         this.inlineBinary = seed.hasAnnotation(XmlInlineBinaryData.class);
   108         T t = seed.getRawType();
   110         // check if there's an adapter applicable to the whole property
   111         XmlJavaTypeAdapter xjta = getApplicableAdapter(t);
   112         if(xjta!=null) {
   113             isCollection = false;
   114             adapter = new Adapter<T,C>(xjta,reader(),nav());
   115         } else {
   116             // check if the adapter is applicable to the individual item in the property
   118             this.isCollection = nav().isSubClassOf(t, nav().ref(Collection.class))
   119                              || nav().isArrayButNotByteArray(t);
   121             xjta = getApplicableAdapter(getIndividualType());
   122             if(xjta==null) {
   123                 // ugly ugly hack, but we implement swaRef as adapter
   124                 XmlAttachmentRef xsa = seed.readAnnotation(XmlAttachmentRef.class);
   125                 if(xsa!=null) {
   126                     parent.builder.hasSwaRef = true;
   127                     adapter = new Adapter<T,C>(nav().asDecl(SwaRefAdapter.class),nav());
   128                 } else {
   129                     adapter = null;
   131                     // if this field has adapter annotation but not applicable,
   132                     // that must be an error of the user
   133                     xjta = seed.readAnnotation(XmlJavaTypeAdapter.class);
   134                     if(xjta!=null) {
   135                         T ad = reader().getClassValue(xjta,"value");
   136                         parent.builder.reportError(new IllegalAnnotationException(
   137                             Messages.UNMATCHABLE_ADAPTER.format(
   138                                     nav().getTypeName(ad), nav().getTypeName(t)),
   139                             xjta
   140                         ));
   141                     }
   142                 }
   143             } else {
   144                 adapter = new Adapter<T,C>(xjta,reader(),nav());
   145             }
   146         }
   148         this.id = calcId();
   149         this.schemaType = Util.calcSchemaType(reader(),seed,parent.clazz,
   150                 getIndividualType(),this);
   151     }
   154     public ClassInfoImpl<T,C,F,M> parent() {
   155         return parent;
   156     }
   158     protected final Navigator<T,C,F,M> nav() {
   159         return parent.nav();
   160     }
   161     protected final AnnotationReader<T,C,F,M> reader() {
   162         return parent.reader();
   163     }
   165     public T getRawType() {
   166         return seed.getRawType();
   167     }
   169     public T getIndividualType() {
   170         if(adapter!=null)
   171             return adapter.defaultType;
   172         T raw = getRawType();
   173         if(!isCollection()) {
   174             return raw;
   175         } else {
   176             if(nav().isArrayButNotByteArray(raw))
   177                 return nav().getComponentType(raw);
   179             T bt = nav().getBaseClass(raw, nav().asDecl(Collection.class) );
   180             if(nav().isParameterizedType(bt))
   181                 return nav().getTypeArgument(bt,0);
   182             else
   183                 return nav().ref(Object.class);
   184         }
   185     }
   187     public final String getName() {
   188         return seed.getName();
   189     }
   191     /**
   192      * Checks if the given adapter is applicable to the declared property type.
   193      */
   194     private boolean isApplicable(XmlJavaTypeAdapter jta, T declaredType ) {
   195         if(jta==null)   return false;
   197         T type = reader().getClassValue(jta,"type");
   198         if(nav().isSameType(declaredType, type))
   199             return true;    // for types explicitly marked in XmlJavaTypeAdapter.type()
   201         T ad = reader().getClassValue(jta,"value");
   202         T ba = nav().getBaseClass(ad, nav().asDecl(XmlAdapter.class));
   203         if(!nav().isParameterizedType(ba))
   204             return true;   // can't check type applicability. assume Object, which means applicable to any.
   205         T inMemType = nav().getTypeArgument(ba, 1);
   207         return nav().isSubClassOf(declaredType,inMemType);
   208     }
   210     private XmlJavaTypeAdapter getApplicableAdapter(T type) {
   211         XmlJavaTypeAdapter jta = seed.readAnnotation(XmlJavaTypeAdapter.class);
   212         if(jta!=null && isApplicable(jta,type))
   213             return jta;
   215         // check the applicable adapters on the package
   216         XmlJavaTypeAdapters jtas = reader().getPackageAnnotation(XmlJavaTypeAdapters.class, parent.clazz, seed );
   217         if(jtas!=null) {
   218             for (XmlJavaTypeAdapter xjta : jtas.value()) {
   219                 if(isApplicable(xjta,type))
   220                     return xjta;
   221             }
   222         }
   223         jta = reader().getPackageAnnotation(XmlJavaTypeAdapter.class, parent.clazz, seed );
   224         if(isApplicable(jta,type))
   225             return jta;
   227         // then on the target class
   228         C refType = nav().asDecl(type);
   229         if(refType!=null) {
   230             jta = reader().getClassAnnotation(XmlJavaTypeAdapter.class, refType, seed );
   231             if(jta!=null && isApplicable(jta,type)) // the one on the type always apply.
   232                 return jta;
   233         }
   235         return null;
   236     }
   238     /**
   239      * This is the default implementation of the getAdapter method
   240      * defined on many of the {@link PropertyInfo}-derived classes.
   241      */
   242     public Adapter<T,C> getAdapter() {
   243         return adapter;
   244     }
   247     public final String displayName() {
   248         return nav().getClassName(parent.getClazz())+'#'+getName();
   249     }
   251     public final ID id() {
   252         return id;
   253     }
   255     private ID calcId() {
   256         if(seed.hasAnnotation(XmlID.class)) {
   257             // check the type
   258             if(!nav().isSameType(getIndividualType(), nav().ref(String.class)))
   259                 parent.builder.reportError(new IllegalAnnotationException(
   260                     Messages.ID_MUST_BE_STRING.format(getName()), seed )
   261                 );
   262             return ID.ID;
   263         } else
   264         if(seed.hasAnnotation(XmlIDREF.class)) {
   265             return ID.IDREF;
   266         } else {
   267             return ID.NONE;
   268         }
   269     }
   271     public final MimeType getExpectedMimeType() {
   272         return expectedMimeType;
   273     }
   275     public final boolean inlineBinaryData() {
   276         return inlineBinary;
   277     }
   279     public final QName getSchemaType() {
   280         return schemaType;
   281     }
   283     public final boolean isCollection() {
   284         return isCollection;
   285     }
   287     /**
   288      * Called after all the {@link TypeInfo}s are collected into the governing {@link TypeInfoSet}.
   289      *
   290      * Derived class can do additional actions to complete the model.
   291      */
   292     protected void link() {
   293         if(id==ID.IDREF) {
   294             // make sure that the refereced type has ID
   295             for (TypeInfo<T,C> ti : ref()) {
   296                 if(!ti.canBeReferencedByIDREF())
   297                     parent.builder.reportError(new IllegalAnnotationException(
   298                     Messages.INVALID_IDREF.format(
   299                         parent.builder.nav.getTypeName(ti.getType())), this ));
   300             }
   301         }
   302     }
   304     /**
   305      * A {@link PropertyInfoImpl} is always referenced by its enclosing class,
   306      * so return that as the upstream.
   307      */
   308     public Locatable getUpstream() {
   309         return parent;
   310     }
   312     public Location getLocation() {
   313         return seed.getLocation();
   314     }
   317 //
   318 //
   319 // convenience methods for derived classes
   320 //
   321 //
   324     /**
   325      * Computes the tag name from a {@link XmlElement} by taking the defaulting into account.
   326      */
   327     protected final QName calcXmlName(XmlElement e) {
   328         if(e!=null)
   329             return calcXmlName(e.namespace(),e.name());
   330         else
   331             return calcXmlName("##default","##default");
   332     }
   334     /**
   335      * Computes the tag name from a {@link XmlElementWrapper} by taking the defaulting into account.
   336      */
   337     protected final QName calcXmlName(XmlElementWrapper e) {
   338         if(e!=null)
   339             return calcXmlName(e.namespace(),e.name());
   340         else
   341             return calcXmlName("##default","##default");
   342     }
   344     private QName calcXmlName(String uri,String local) {
   345         // compute the default
   346         TODO.checkSpec();
   347         if(local.length()==0 || local.equals("##default"))
   348             local = seed.getName();
   349         if(uri.equals("##default")) {
   350             XmlSchema xs = reader().getPackageAnnotation( XmlSchema.class, parent.getClazz(), this );
   351             // JAX-RPC doesn't want the default namespace URI swapping to take effect to
   352             // local "unqualified" elements. UGLY.
   353             if(xs!=null) {
   354                 switch(xs.elementFormDefault()) {
   355                 case QUALIFIED:
   356                     QName typeName = parent.getTypeName();
   357                     if(typeName!=null)
   358                         uri = typeName.getNamespaceURI();
   359                     else
   360                         uri = xs.namespace();
   361                     if(uri.length()==0)
   362                         uri = parent.builder.defaultNsUri;
   363                     break;
   364                 case UNQUALIFIED:
   365                 case UNSET:
   366                     uri = "";
   367                 }
   368             } else {
   369                 uri = "";
   370             }
   371         }
   372         return new QName(uri.intern(),local.intern());
   373     }
   375     public int compareTo(PropertyInfoImpl that) {
   376         return this.getName().compareTo(that.getName());
   377     }
   379     public final <A extends Annotation> A readAnnotation(Class<A> annotationType) {
   380         return seed.readAnnotation(annotationType);
   381     }
   383     public final boolean hasAnnotation(Class<? extends Annotation> annotationType) {
   384         return seed.hasAnnotation(annotationType);
   385     }
   386 }

mercurial