src/share/jaxws_classes/com/sun/xml/internal/bind/v2/model/impl/ElementInfoImpl.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.lang.annotation.Annotation;
    29 import java.util.Collection;
    30 import java.util.Collections;
    31 import java.util.List;
    33 import javax.activation.MimeType;
    34 import javax.xml.bind.JAXBElement;
    35 import javax.xml.bind.annotation.XmlAttachmentRef;
    36 import javax.xml.bind.annotation.XmlElementDecl;
    37 import javax.xml.bind.annotation.XmlID;
    38 import javax.xml.bind.annotation.XmlIDREF;
    39 import javax.xml.bind.annotation.XmlInlineBinaryData;
    40 import javax.xml.bind.annotation.XmlSchema;
    41 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
    42 import javax.xml.namespace.QName;
    44 import com.sun.istack.internal.FinalArrayList;
    45 import com.sun.xml.internal.bind.v2.TODO;
    46 import com.sun.xml.internal.bind.v2.model.annotation.AnnotationSource;
    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.ClassInfo;
    50 import com.sun.xml.internal.bind.v2.model.core.ElementInfo;
    51 import com.sun.xml.internal.bind.v2.model.core.ElementPropertyInfo;
    52 import com.sun.xml.internal.bind.v2.model.core.ID;
    53 import com.sun.xml.internal.bind.v2.model.core.NonElement;
    54 import com.sun.xml.internal.bind.v2.model.core.PropertyInfo;
    55 import com.sun.xml.internal.bind.v2.model.core.PropertyKind;
    56 import com.sun.xml.internal.bind.v2.model.core.TypeInfo;
    57 import com.sun.xml.internal.bind.v2.model.core.TypeRef;
    58 import com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationException;
    59 import com.sun.xml.internal.bind.v2.runtime.Location;
    60 import com.sun.xml.internal.bind.v2.runtime.SwaRefAdapter;
    62 /**
    63  * {@link ElementInfo} implementation.
    64  *
    65  * @author Kohsuke Kawaguchi
    66  */
    67 class ElementInfoImpl<T,C,F,M> extends TypeInfoImpl<T,C,F,M> implements ElementInfo<T,C> {
    69     private final QName tagName;
    71     private final NonElement<T,C> contentType;
    73     private final T tOfJAXBElementT;
    75     private final T elementType;
    77     private final ClassInfo<T,C> scope;
    79     /**
    80      * Annotation that controls the binding.
    81      */
    82     private final XmlElementDecl anno;
    84     /**
    85      * If this element can substitute another element, the element name.
    86      * @see #link()
    87      */
    88     private ElementInfoImpl<T,C,F,M> substitutionHead;
    90     /**
    91      * Lazily constructed list of {@link ElementInfo}s that can substitute this element.
    92      * This could be null.
    93      * @see #link()
    94      */
    95     private FinalArrayList<ElementInfoImpl<T,C,F,M>> substitutionMembers;
    97     /**
    98      * The factory method from which this mapping was created.
    99      */
   100     private final M method;
   102     /**
   103      * If the content type is adapter, return that adapter.
   104      */
   105     private final Adapter<T,C> adapter;
   107     private final boolean isCollection;
   109     private final ID id;
   111     private final PropertyImpl property;
   112     private final MimeType expectedMimeType;
   113     private final boolean inlineBinary;
   114     private final QName schemaType;
   116     /**
   117      * Singleton instance of {@link ElementPropertyInfo} for this element.
   118      */
   119     protected class PropertyImpl implements
   120             ElementPropertyInfo<T,C>,
   121             TypeRef<T,C>,
   122             AnnotationSource {
   123         //
   124         // TypeRef impl
   125         //
   126         public NonElement<T,C> getTarget() {
   127             return contentType;
   128         }
   129         public QName getTagName() {
   130             return tagName;
   131         }
   133         public List<? extends TypeRef<T,C>> getTypes() {
   134             return Collections.singletonList(this);
   135         }
   137         public List<? extends NonElement<T,C>> ref() {
   138             return Collections.singletonList(contentType);
   139         }
   141         public QName getXmlName() {
   142             return tagName;
   143         }
   145         public boolean isCollectionRequired() {
   146             return false;
   147         }
   149         public boolean isCollectionNillable() {
   150             return true;
   151         }
   153         public boolean isNillable() {
   154             return true;
   155         }
   157         public String getDefaultValue() {
   158             String v = anno.defaultValue();
   159             if(v.equals("\u0000"))
   160                 return null;
   161             else
   162                 return v;
   163         }
   165         public ElementInfoImpl<T,C,F,M> parent() {
   166             return ElementInfoImpl.this;
   167         }
   169         public String getName() {
   170             return "value";
   171         }
   173         public String displayName() {
   174             return "JAXBElement#value";
   175         }
   177         public boolean isCollection() {
   178             return isCollection;
   179         }
   181         /**
   182          * For {@link ElementInfo}s, a collection always means a list of values.
   183          */
   184         public boolean isValueList() {
   185             return isCollection;
   186         }
   188         public boolean isRequired() {
   189             return true;
   190         }
   192         public PropertyKind kind() {
   193             return PropertyKind.ELEMENT;
   194         }
   196         public Adapter<T,C> getAdapter() {
   197             return adapter;
   198         }
   200         public ID id() {
   201             return id;
   202         }
   204         public MimeType getExpectedMimeType() {
   205             return expectedMimeType;
   206         }
   208         public QName getSchemaType() {
   209             return schemaType;
   210         }
   212         public boolean inlineBinaryData() {
   213             return inlineBinary;
   214         }
   216         public PropertyInfo<T,C> getSource() {
   217             return this;
   218         }
   220         //
   221         //
   222         // AnnotationSource impl
   223         //
   224         //
   225         public <A extends Annotation> A readAnnotation(Class<A> annotationType) {
   226             return reader().getMethodAnnotation(annotationType,method,ElementInfoImpl.this);
   227         }
   229         public boolean hasAnnotation(Class<? extends Annotation> annotationType) {
   230             return reader().hasMethodAnnotation(annotationType,method);
   231         }
   232     }
   234     /**
   235      * @param m
   236      *      The factory method on ObjectFactory that comes with {@link XmlElementDecl}.
   237      */
   238     public ElementInfoImpl(ModelBuilder<T,C,F,M> builder,
   239                            RegistryInfoImpl<T,C,F,M> registry, M m ) throws IllegalAnnotationException {
   240         super(builder,registry);
   242         this.method = m;
   243         anno = reader().getMethodAnnotation( XmlElementDecl.class, m, this );
   244         assert anno!=null;  // the caller should check this
   245         assert anno instanceof Locatable;
   247         elementType = nav().getReturnType(m);
   248         T baseClass = nav().getBaseClass(elementType,nav().asDecl(JAXBElement.class));
   249         if(baseClass==null)
   250             throw new IllegalAnnotationException(
   251                 Messages.XML_ELEMENT_MAPPING_ON_NON_IXMLELEMENT_METHOD.format(nav().getMethodName(m)),
   252                 anno );
   254         tagName = parseElementName(anno);
   255         T[] methodParams = nav().getMethodParameters(m);
   257         // adapter
   258         Adapter<T,C> a = null;
   259         if(methodParams.length>0) {
   260             XmlJavaTypeAdapter adapter = reader().getMethodAnnotation(XmlJavaTypeAdapter.class,m,this);
   261             if(adapter!=null)
   262                 a = new Adapter<T,C>(adapter,reader(),nav());
   263             else {
   264                 XmlAttachmentRef xsa = reader().getMethodAnnotation(XmlAttachmentRef.class,m,this);
   265                 if(xsa!=null) {
   266                     TODO.prototype("in Annotation Processing swaRefAdapter isn't avaialble, so this returns null");
   267                     a = new Adapter<T,C>(owner.nav.asDecl(SwaRefAdapter.class),owner.nav);
   268                 }
   269             }
   270         }
   271         this.adapter = a;
   273         // T of JAXBElement<T>
   274         tOfJAXBElementT =
   275             methodParams.length>0 ? methodParams[0] // this is more reliable, as it works even for ObjectFactory that sometimes have to return public types
   276             : nav().getTypeArgument(baseClass,0); // fall back to infer from the return type if no parameter.
   278         if(adapter==null) {
   279             T list = nav().getBaseClass(tOfJAXBElementT,nav().asDecl(List.class));
   280             if(list==null) {
   281                 isCollection = false;
   282                 contentType = builder.getTypeInfo(tOfJAXBElementT,this);  // suck this type into the current set.
   283             } else {
   284                 isCollection = true;
   285                 contentType = builder.getTypeInfo(nav().getTypeArgument(list,0),this);
   286             }
   287         } else {
   288             // but if adapted, use the adapted type
   289             contentType = builder.getTypeInfo(this.adapter.defaultType,this);
   290             isCollection = false;
   291         }
   293         // scope
   294         T s = reader().getClassValue(anno,"scope");
   295         if(nav().isSameType(s, nav().ref(XmlElementDecl.GLOBAL.class)))
   296             scope = null;
   297         else {
   298             // TODO: what happens if there's an error?
   299             NonElement<T,C> scp = builder.getClassInfo(nav().asDecl(s),this);
   300             if(!(scp instanceof ClassInfo)) {
   301                 throw new IllegalAnnotationException(
   302                     Messages.SCOPE_IS_NOT_COMPLEXTYPE.format(nav().getTypeName(s)),
   303                     anno );
   304             }
   305             scope = (ClassInfo<T,C>)scp;
   306         }
   308         id = calcId();
   310         property = createPropertyImpl();
   312         this.expectedMimeType = Util.calcExpectedMediaType(property,builder);
   313         this.inlineBinary = reader().hasMethodAnnotation(XmlInlineBinaryData.class,method);
   314         this.schemaType = Util.calcSchemaType(reader(),property,registry.registryClass,
   315                 getContentInMemoryType(),this);
   316     }
   318     final QName parseElementName(XmlElementDecl e) {
   319         String local = e.name();
   320         String nsUri = e.namespace();
   321         if(nsUri.equals("##default")) {
   322             // if defaulted ...
   323             XmlSchema xs = reader().getPackageAnnotation(XmlSchema.class,
   324                 nav().getDeclaringClassForMethod(method),this);
   325             if(xs!=null)
   326                 nsUri = xs.namespace();
   327             else {
   328                 nsUri = builder.defaultNsUri;
   329             }
   330         }
   332         return new QName(nsUri.intern(),local.intern());
   333     }
   335     protected PropertyImpl createPropertyImpl() {
   336         return new PropertyImpl();
   337     }
   339     public ElementPropertyInfo<T,C> getProperty() {
   340         return property;
   341     }
   343     public NonElement<T,C> getContentType() {
   344         return contentType;
   345     }
   347     public T getContentInMemoryType() {
   348         if(adapter==null) {
   349             return tOfJAXBElementT;
   350         } else {
   351             return adapter.customType;
   352         }
   353     }
   355     public QName getElementName() {
   356         return tagName;
   357     }
   359     public T getType() {
   360         return elementType;
   361     }
   363     /**
   364      * Leaf-type cannot be referenced from IDREF.
   365      *
   366      * @deprecated
   367      *      why are you calling a method whose return value is always known?
   368      */
   369     public final boolean canBeReferencedByIDREF() {
   370         return false;
   371     }
   373     private ID calcId() {
   374         // TODO: share code with PropertyInfoImpl
   375         if(reader().hasMethodAnnotation(XmlID.class,method)) {
   376             return ID.ID;
   377         } else
   378         if(reader().hasMethodAnnotation(XmlIDREF.class,method)) {
   379             return ID.IDREF;
   380         } else {
   381             return ID.NONE;
   382         }
   383     }
   385     public ClassInfo<T, C> getScope() {
   386         return scope;
   387     }
   389     public ElementInfo<T,C> getSubstitutionHead() {
   390         return substitutionHead;
   391     }
   393     public Collection<? extends ElementInfoImpl<T,C,F,M>> getSubstitutionMembers() {
   394         if(substitutionMembers==null)
   395             return Collections.emptyList();
   396         else
   397             return substitutionMembers;
   398     }
   400     /**
   401      * Called after all the {@link TypeInfo}s are collected into the {@link #owner}.
   402      */
   403     /*package*/ void link() {
   404         // substitution head
   405         if(anno.substitutionHeadName().length()!=0) {
   406             QName name = new QName(
   407                 anno.substitutionHeadNamespace(), anno.substitutionHeadName() );
   408             substitutionHead = owner.getElementInfo(null,name);
   409             if(substitutionHead==null) {
   410                 builder.reportError(
   411                     new IllegalAnnotationException(Messages.NON_EXISTENT_ELEMENT_MAPPING.format(
   412                         name.getNamespaceURI(),name.getLocalPart()), anno));
   413                 // recover by ignoring this substitution declaration
   414             } else
   415                 substitutionHead.addSubstitutionMember(this);
   416         } else
   417             substitutionHead = null;
   418         super.link();
   419     }
   421     private void addSubstitutionMember(ElementInfoImpl<T,C,F,M> child) {
   422         if(substitutionMembers==null)
   423             substitutionMembers = new FinalArrayList<ElementInfoImpl<T,C,F,M>>();
   424         substitutionMembers.add(child);
   425     }
   427     public Location getLocation() {
   428         return nav().getMethodLocation(method);
   429     }
   430 }

mercurial