src/share/jaxws_classes/com/sun/xml/internal/bind/v2/runtime/property/ArrayElementProperty.java

Fri, 04 Oct 2013 16:21:34 +0100

author
mkos
date
Fri, 04 Oct 2013 16:21:34 +0100
changeset 408
b0610cd08440
parent 0
373ffda63c9a
permissions
-rw-r--r--

8025054: Update JAX-WS RI integration to 2.2.9-b130926.1035
Reviewed-by: chegar

     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.runtime.property;
    28 import java.io.IOException;
    29 import java.lang.reflect.Type;
    30 import java.util.HashMap;
    31 import java.util.List;
    32 import java.util.Map;
    34 import javax.xml.bind.JAXBException;
    35 import javax.xml.stream.XMLStreamException;
    37 import com.sun.xml.internal.bind.api.AccessorException;
    38 import com.sun.xml.internal.bind.v2.model.core.PropertyKind;
    39 import com.sun.xml.internal.bind.v2.model.core.TypeRef;
    40 import com.sun.xml.internal.bind.v2.model.runtime.RuntimeElementPropertyInfo;
    41 import com.sun.xml.internal.bind.v2.model.runtime.RuntimeTypeRef;
    42 import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl;
    43 import com.sun.xml.internal.bind.v2.runtime.JaxBeanInfo;
    44 import com.sun.xml.internal.bind.v2.runtime.Name;
    45 import com.sun.xml.internal.bind.v2.runtime.RuntimeUtil;
    46 import com.sun.xml.internal.bind.v2.runtime.Transducer;
    47 import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
    48 import com.sun.xml.internal.bind.v2.runtime.reflect.Accessor;
    49 import com.sun.xml.internal.bind.v2.runtime.reflect.ListIterator;
    50 import com.sun.xml.internal.bind.v2.runtime.reflect.Lister;
    51 import com.sun.xml.internal.bind.v2.runtime.reflect.NullSafeAccessor;
    52 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.ChildLoader;
    53 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.DefaultValueLoaderDecorator;
    54 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader;
    55 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Receiver;
    56 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.TextLoader;
    57 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.XsiNilLoader;
    58 import com.sun.xml.internal.bind.v2.util.QNameMap;
    60 import org.xml.sax.SAXException;
    62 /**
    63  * {@link Property} implementation for multi-value property that maps to an element.
    64  *
    65  * @author Kohsuke Kawaguchi
    66  */
    67 abstract class ArrayElementProperty<BeanT,ListT,ItemT> extends ArrayERProperty<BeanT,ListT,ItemT> {
    69     private final Map<Class,TagAndType> typeMap  = new HashMap<Class,TagAndType>();
    70     /**
    71      * Set by the constructor and reset in the {@link #wrapUp()} method.
    72      */
    73     private Map<TypeRef<Type,Class>,JaxBeanInfo> refs = new HashMap<TypeRef<Type, Class>, JaxBeanInfo>();
    74     /**
    75      * Set by the constructor and reset in the {@link #wrapUp()} method.
    76      */
    77     protected RuntimeElementPropertyInfo prop;
    79     /**
    80      * Tag name used when we see null in the collection. Can be null.
    81      */
    82     private final Name nillableTagName;
    84     protected ArrayElementProperty(JAXBContextImpl grammar, RuntimeElementPropertyInfo prop) {
    85         super(grammar, prop, prop.getXmlName(), prop.isCollectionNillable());
    86         this.prop = prop;
    88         List<? extends RuntimeTypeRef> types = prop.getTypes();
    90         Name n = null;
    92         for (RuntimeTypeRef typeRef : types) {
    93             Class type = (Class)typeRef.getTarget().getType();
    94             if(type.isPrimitive())
    95                 type = RuntimeUtil.primitiveToBox.get(type);
    97             JaxBeanInfo beanInfo = grammar.getOrCreate(typeRef.getTarget());
    98             TagAndType tt = new TagAndType(
    99                                 grammar.nameBuilder.createElementName(typeRef.getTagName()),
   100                                 beanInfo);
   101             typeMap.put(type,tt);
   102             refs.put(typeRef,beanInfo);
   103             if(typeRef.isNillable() && n==null)
   104                 n = tt.tagName;
   105         }
   107         nillableTagName = n;
   108     }
   110     @Override
   111     public void wrapUp() {
   112         super.wrapUp();
   113         refs = null;
   114         prop = null;    // avoid keeping model objects live
   115     }
   117     protected void serializeListBody(BeanT beanT, XMLSerializer w, ListT list) throws IOException, XMLStreamException, SAXException, AccessorException {
   118         ListIterator<ItemT> itr = lister.iterator(list, w);
   120         boolean isIdref = itr instanceof Lister.IDREFSIterator; // UGLY
   122         while(itr.hasNext()) {
   123             try {
   124                 ItemT item = itr.next();
   125                 if (item != null) {
   126                     Class itemType = item.getClass();
   127                     if(isIdref)
   128                         // This should be the only place where we need to be aware
   129                         // that the iterator is iterating IDREFS.
   130                         itemType = ((Lister.IDREFSIterator)itr).last().getClass();
   132                     // normally, this returns non-null
   133                     TagAndType tt = typeMap.get(itemType);
   134                     while(tt==null && itemType!=null) {
   135                         // otherwise we'll just have to try the slow way
   136                         itemType = itemType.getSuperclass();
   137                         tt = typeMap.get(itemType);
   138                     }
   140                     if(tt==null) {
   141                         // item is not of the expected type.
   142 //                        w.reportError(new ValidationEventImpl(ValidationEvent.ERROR,
   143 //                            Messages.UNEXPECTED_JAVA_TYPE.format(
   144 //                                item.getClass().getName(),
   145 //                                getExpectedClassNameList()
   146 //                            ),
   147 //                            w.getCurrentLocation(fieldName)));
   148 //                        continue;
   150                         // see the similar code in SingleElementNodeProperty.
   151                         // for the purpose of simple type substitution, make it a non-error
   153                         w.startElement(typeMap.values().iterator().next().tagName,null);
   154                         w.childAsXsiType(item,fieldName,w.grammar.getBeanInfo(Object.class), false);
   155                     } else {
   156                         w.startElement(tt.tagName,null);
   157                         serializeItem(tt.beanInfo,item,w);
   158                     }
   160                     w.endElement();
   161                 } else {
   162                     if(nillableTagName!=null) {
   163                         w.startElement(nillableTagName,null);
   164                         w.writeXsiNilTrue();
   165                         w.endElement();
   166                     }
   167                 }
   168             } catch (JAXBException e) {
   169                 w.reportError(fieldName,e);
   170                 // recover by ignoring this item
   171             }
   172         }
   173     }
   175     /**
   176      * Serializes one item of the property.
   177      */
   178     protected abstract void serializeItem(JaxBeanInfo expected, ItemT item, XMLSerializer w) throws SAXException, AccessorException, IOException, XMLStreamException;
   181     public void createBodyUnmarshaller(UnmarshallerChain chain, QNameMap<ChildLoader> loaders) {
   183         // all items go to the same lister,
   184         // so they should share the same offset.
   185         int offset = chain.allocateOffset();
   186         Receiver recv = new ReceiverImpl(offset);
   188         for (RuntimeTypeRef typeRef : prop.getTypes()) {
   190             Name tagName = chain.context.nameBuilder.createElementName(typeRef.getTagName());
   191             Loader item = createItemUnmarshaller(chain,typeRef);
   193             if(typeRef.isNillable() || chain.context.allNillable)
   194                 item = new XsiNilLoader.Array(item);
   195             if(typeRef.getDefaultValue()!=null)
   196                 item = new DefaultValueLoaderDecorator(item,typeRef.getDefaultValue());
   198             loaders.put(tagName,new ChildLoader(item,recv));
   199         }
   200     }
   202     public final PropertyKind getKind() {
   203         return PropertyKind.ELEMENT;
   204     }
   206     /**
   207      * Creates a loader handler that unmarshals the body of the item.
   208      *
   209      * <p>
   210      * This will be sandwiched into <item> ... </item>.
   211      *
   212      * <p>
   213      * When unmarshalling the body of item, the Pack of {@link Lister} is available
   214      * as the handler state.
   215      *
   216      * @param chain
   217      * @param typeRef
   218      */
   219     private Loader createItemUnmarshaller(UnmarshallerChain chain, RuntimeTypeRef typeRef) {
   220         if(PropertyFactory.isLeaf(typeRef.getSource())) {
   221             final Transducer xducer = typeRef.getTransducer();
   222             return new TextLoader(xducer);
   223         } else {
   224             return refs.get(typeRef).getLoader(chain.context,true);
   225         }
   226     }
   228     public Accessor getElementPropertyAccessor(String nsUri, String localName) {
   229         if(wrapperTagName!=null) {
   230             if(wrapperTagName.equals(nsUri,localName))
   231                 return acc;
   232         } else {
   233             for (TagAndType tt : typeMap.values()) {
   234                 if(tt.tagName.equals(nsUri,localName))
   235                     // when we can't distinguish null and empty list, JAX-WS doesn't want to see
   236                     // null (just like any user apps), but since we are providing a raw accessor,
   237                     // which just grabs the value from the field, we wrap it so that it won't return
   238                     // null.
   239                     return new NullSafeAccessor<BeanT,ListT,Object>(acc,lister);
   240             }
   241         }
   242         return null;
   243     }
   244 }

mercurial