alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (PropertyInfoImpl.java)

This example Java source code file (PropertyInfoImpl.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

adapter, annotation, classinfoimpl, illegalannotationexception, locatable, mimetype, propertyinfoimpl, propertyseed, qname, string, unset, util, xmljavatypeadapter, xmljavatypeadapters

The PropertyInfoImpl.java Java example source code

/*
 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.xml.internal.bind.v2.model.impl;

import java.util.Collection;
import java.lang.annotation.Annotation;

import javax.activation.MimeType;
import javax.xml.bind.annotation.XmlAttachmentRef;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlID;
import javax.xml.bind.annotation.XmlIDREF;
import javax.xml.bind.annotation.XmlInlineBinaryData;
import javax.xml.bind.annotation.XmlMimeType;
import javax.xml.bind.annotation.XmlSchema;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.namespace.QName;

import com.sun.xml.internal.bind.v2.TODO;
import com.sun.xml.internal.bind.v2.model.annotation.AnnotationReader;
import com.sun.xml.internal.bind.v2.model.annotation.Locatable;
import com.sun.xml.internal.bind.v2.model.core.Adapter;
import com.sun.xml.internal.bind.v2.model.core.ID;
import com.sun.xml.internal.bind.v2.model.core.PropertyInfo;
import com.sun.xml.internal.bind.v2.model.core.TypeInfo;
import com.sun.xml.internal.bind.v2.model.core.TypeInfoSet;
import com.sun.xml.internal.bind.v2.model.nav.Navigator;
import com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationException;
import com.sun.xml.internal.bind.v2.runtime.Location;
import com.sun.xml.internal.bind.v2.runtime.SwaRefAdapter;

/**
 * Default partial implementation for {@link PropertyInfo}.
 *
 * @author Kohsuke Kawaguchi
 */
abstract class PropertyInfoImpl<T,C,F,M>
    implements PropertyInfo<T,C>, Locatable, Comparable /*by their names*/ {

    /**
     * Object that reads annotations.
     */
    protected final PropertySeed<T,C,F,M> seed;

    private final boolean isCollection;

    private final ID id;

    private final MimeType expectedMimeType;
    private final boolean inlineBinary;
    private final QName schemaType;

    protected final ClassInfoImpl<T,C,F,M> parent;

    private final Adapter<T,C> adapter;

    protected PropertyInfoImpl(ClassInfoImpl<T,C,F,M> parent, PropertySeed spi) {
        this.seed = spi;
        this.parent = parent;

        if(parent==null)
            /*
                Various people reported a bug where this parameter is somehow null.
                In an attempt to catch the error better, let's do an explicit check here.

                http://forums.java.net/jive/thread.jspa?threadID=18479
                http://forums.java.net/jive/thread.jspa?messageID=165946
             */
            throw new AssertionError();

        MimeType mt = Util.calcExpectedMediaType(seed,parent.builder);
        if(mt!=null && !kind().canHaveXmlMimeType) {
            parent.builder.reportError(new IllegalAnnotationException(
                Messages.ILLEGAL_ANNOTATION.format(XmlMimeType.class.getName()),
                seed.readAnnotation(XmlMimeType.class)
            ));
            mt = null;
        }
        this.expectedMimeType = mt;
        this.inlineBinary = seed.hasAnnotation(XmlInlineBinaryData.class);

        T t = seed.getRawType();

        // check if there's an adapter applicable to the whole property
        XmlJavaTypeAdapter xjta = getApplicableAdapter(t);
        if(xjta!=null) {
            isCollection = false;
            adapter = new Adapter<T,C>(xjta,reader(),nav());
        } else {
            // check if the adapter is applicable to the individual item in the property

            this.isCollection = nav().isSubClassOf(t, nav().ref(Collection.class))
                             || nav().isArrayButNotByteArray(t);

            xjta = getApplicableAdapter(getIndividualType());
            if(xjta==null) {
                // ugly ugly hack, but we implement swaRef as adapter
                XmlAttachmentRef xsa = seed.readAnnotation(XmlAttachmentRef.class);
                if(xsa!=null) {
                    parent.builder.hasSwaRef = true;
                    adapter = new Adapter<T,C>(nav().asDecl(SwaRefAdapter.class),nav());
                } else {
                    adapter = null;

                    // if this field has adapter annotation but not applicable,
                    // that must be an error of the user
                    xjta = seed.readAnnotation(XmlJavaTypeAdapter.class);
                    if(xjta!=null) {
                        T ad = reader().getClassValue(xjta,"value");
                        parent.builder.reportError(new IllegalAnnotationException(
                            Messages.UNMATCHABLE_ADAPTER.format(
                                    nav().getTypeName(ad), nav().getTypeName(t)),
                            xjta
                        ));
                    }
                }
            } else {
                adapter = new Adapter<T,C>(xjta,reader(),nav());
            }
        }

        this.id = calcId();
        this.schemaType = Util.calcSchemaType(reader(),seed,parent.clazz,
                getIndividualType(),this);
    }


    public ClassInfoImpl<T,C,F,M> parent() {
        return parent;
    }

    protected final Navigator<T,C,F,M> nav() {
        return parent.nav();
    }
    protected final AnnotationReader<T,C,F,M> reader() {
        return parent.reader();
    }

    public T getRawType() {
        return seed.getRawType();
    }

    public T getIndividualType() {
        if(adapter!=null)
            return adapter.defaultType;
        T raw = getRawType();
        if(!isCollection()) {
            return raw;
        } else {
            if(nav().isArrayButNotByteArray(raw))
                return nav().getComponentType(raw);

            T bt = nav().getBaseClass(raw, nav().asDecl(Collection.class) );
            if(nav().isParameterizedType(bt))
                return nav().getTypeArgument(bt,0);
            else
                return nav().ref(Object.class);
        }
    }

    public final String getName() {
        return seed.getName();
    }

    /**
     * Checks if the given adapter is applicable to the declared property type.
     */
    private boolean isApplicable(XmlJavaTypeAdapter jta, T declaredType ) {
        if(jta==null)   return false;

        T type = reader().getClassValue(jta,"type");
        if(nav().isSameType(declaredType, type))
            return true;    // for types explicitly marked in XmlJavaTypeAdapter.type()

        T ad = reader().getClassValue(jta,"value");
        T ba = nav().getBaseClass(ad, nav().asDecl(XmlAdapter.class));
        if(!nav().isParameterizedType(ba))
            return true;   // can't check type applicability. assume Object, which means applicable to any.
        T inMemType = nav().getTypeArgument(ba, 1);

        return nav().isSubClassOf(declaredType,inMemType);
    }

    private XmlJavaTypeAdapter getApplicableAdapter(T type) {
        XmlJavaTypeAdapter jta = seed.readAnnotation(XmlJavaTypeAdapter.class);
        if(jta!=null && isApplicable(jta,type))
            return jta;

        // check the applicable adapters on the package
        XmlJavaTypeAdapters jtas = reader().getPackageAnnotation(XmlJavaTypeAdapters.class, parent.clazz, seed );
        if(jtas!=null) {
            for (XmlJavaTypeAdapter xjta : jtas.value()) {
                if(isApplicable(xjta,type))
                    return xjta;
            }
        }
        jta = reader().getPackageAnnotation(XmlJavaTypeAdapter.class, parent.clazz, seed );
        if(isApplicable(jta,type))
            return jta;

        // then on the target class
        C refType = nav().asDecl(type);
        if(refType!=null) {
            jta = reader().getClassAnnotation(XmlJavaTypeAdapter.class, refType, seed );
            if(jta!=null && isApplicable(jta,type)) // the one on the type always apply.
                return jta;
        }

        return null;
    }

    /**
     * This is the default implementation of the getAdapter method
     * defined on many of the {@link PropertyInfo}-derived classes.
     */
    public Adapter<T,C> getAdapter() {
        return adapter;
    }


    public final String displayName() {
        return nav().getClassName(parent.getClazz())+'#'+getName();
    }

    public final ID id() {
        return id;
    }

    private ID calcId() {
        if(seed.hasAnnotation(XmlID.class)) {
            // check the type
            if(!nav().isSameType(getIndividualType(), nav().ref(String.class)))
                parent.builder.reportError(new IllegalAnnotationException(
                    Messages.ID_MUST_BE_STRING.format(getName()), seed )
                );
            return ID.ID;
        } else
        if(seed.hasAnnotation(XmlIDREF.class)) {
            return ID.IDREF;
        } else {
            return ID.NONE;
        }
    }

    public final MimeType getExpectedMimeType() {
        return expectedMimeType;
    }

    public final boolean inlineBinaryData() {
        return inlineBinary;
    }

    public final QName getSchemaType() {
        return schemaType;
    }

    public final boolean isCollection() {
        return isCollection;
    }

    /**
     * Called after all the {@link TypeInfo}s are collected into the governing {@link TypeInfoSet}.
     *
     * Derived class can do additional actions to complete the model.
     */
    protected void link() {
        if(id==ID.IDREF) {
            // make sure that the refereced type has ID
            for (TypeInfo<T,C> ti : ref()) {
                if(!ti.canBeReferencedByIDREF())
                    parent.builder.reportError(new IllegalAnnotationException(
                    Messages.INVALID_IDREF.format(
                        parent.builder.nav.getTypeName(ti.getType())), this ));
            }
        }
    }

    /**
     * A {@link PropertyInfoImpl} is always referenced by its enclosing class,
     * so return that as the upstream.
     */
    public Locatable getUpstream() {
        return parent;
    }

    public Location getLocation() {
        return seed.getLocation();
    }


//
//
// convenience methods for derived classes
//
//


    /**
     * Computes the tag name from a {@link XmlElement} by taking the defaulting into account.
     */
    protected final QName calcXmlName(XmlElement e) {
        if(e!=null)
            return calcXmlName(e.namespace(),e.name());
        else
            return calcXmlName("##default","##default");
    }

    /**
     * Computes the tag name from a {@link XmlElementWrapper} by taking the defaulting into account.
     */
    protected final QName calcXmlName(XmlElementWrapper e) {
        if(e!=null)
            return calcXmlName(e.namespace(),e.name());
        else
            return calcXmlName("##default","##default");
    }

    private QName calcXmlName(String uri,String local) {
        // compute the default
        TODO.checkSpec();
        if(local.length()==0 || local.equals("##default"))
            local = seed.getName();
        if(uri.equals("##default")) {
            XmlSchema xs = reader().getPackageAnnotation( XmlSchema.class, parent.getClazz(), this );
            // JAX-RPC doesn't want the default namespace URI swapping to take effect to
            // local "unqualified" elements. UGLY.
            if(xs!=null) {
                switch(xs.elementFormDefault()) {
                case QUALIFIED:
                    QName typeName = parent.getTypeName();
                    if(typeName!=null)
                        uri = typeName.getNamespaceURI();
                    else
                        uri = xs.namespace();
                    if(uri.length()==0)
                        uri = parent.builder.defaultNsUri;
                    break;
                case UNQUALIFIED:
                case UNSET:
                    uri = "";
                }
            } else {
                uri = "";
            }
        }
        return new QName(uri.intern(),local.intern());
    }

    public int compareTo(PropertyInfoImpl that) {
        return this.getName().compareTo(that.getName());
    }

    public final <A extends Annotation> A readAnnotation(Class annotationType) {
        return seed.readAnnotation(annotationType);
    }

    public final boolean hasAnnotation(Class<? extends Annotation> annotationType) {
        return seed.hasAnnotation(annotationType);
    }
}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.