1 /*
   2  * Copyright (c) 1997, 2013, 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  */
  25 
  26 package com.sun.xml.internal.bind.v2.runtime.property;
  27 
  28 import java.io.IOException;
  29 
  30 import javax.xml.stream.XMLStreamException;
  31 
  32 import com.sun.xml.internal.bind.api.AccessorException;
  33 import com.sun.xml.internal.bind.v2.util.QNameMap;
  34 import com.sun.xml.internal.bind.v2.model.core.ElementPropertyInfo;
  35 import com.sun.xml.internal.bind.v2.model.core.PropertyKind;
  36 import com.sun.xml.internal.bind.v2.model.runtime.RuntimeElementPropertyInfo;
  37 import com.sun.xml.internal.bind.v2.model.runtime.RuntimeTypeRef;
  38 import com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl;
  39 import com.sun.xml.internal.bind.v2.runtime.Name;
  40 import com.sun.xml.internal.bind.v2.runtime.Transducer;
  41 import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
  42 import com.sun.xml.internal.bind.v2.runtime.reflect.ListTransducedAccessorImpl;
  43 import com.sun.xml.internal.bind.v2.runtime.reflect.TransducedAccessor;
  44 import com.sun.xml.internal.bind.v2.runtime.reflect.Accessor;
  45 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.ChildLoader;
  46 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.DefaultValueLoaderDecorator;
  47 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.LeafPropertyLoader;
  48 import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader;
  49 
  50 import org.xml.sax.SAXException;
  51 
  52 /**
  53  * {@link Property} implementation for {@link ElementPropertyInfo} whose
  54  * {@link ElementPropertyInfo#isValueList()} is true.
  55  *
  56  * @author Kohsuke Kawaguchi
  57  */
  58 final class ListElementProperty<BeanT,ListT,ItemT> extends ArrayProperty<BeanT,ListT,ItemT> {
  59 
  60     private final Name tagName;
  61     private final String defaultValue;
  62 
  63     /**
  64      * Converts all the values to a list and back.
  65      */
  66     private final TransducedAccessor<BeanT> xacc;
  67 
  68     public ListElementProperty(JAXBContextImpl grammar, RuntimeElementPropertyInfo prop) {
  69         super(grammar, prop);
  70 
  71         assert prop.isValueList();
  72         assert prop.getTypes().size()==1;   // required by the contract of isValueList
  73         RuntimeTypeRef ref = prop.getTypes().get(0);
  74 
  75         tagName = grammar.nameBuilder.createElementName(ref.getTagName());
  76         defaultValue = ref.getDefaultValue();
  77 
  78         // transducer for each item
  79         Transducer xducer = ref.getTransducer();
  80         // transduced accessor for the whole thing
  81         xacc = new ListTransducedAccessorImpl(xducer,acc,lister);
  82     }
  83 
  84     public PropertyKind getKind() {
  85         return PropertyKind.ELEMENT;
  86     }
  87 
  88     public void buildChildElementUnmarshallers(UnmarshallerChain chain, QNameMap<ChildLoader> handlers) {
  89         Loader l = new LeafPropertyLoader(xacc);
  90         l = new DefaultValueLoaderDecorator(l, defaultValue);
  91         handlers.put(tagName, new ChildLoader(l,null));
  92     }
  93 
  94     @Override
  95     public void serializeBody(BeanT o, XMLSerializer w, Object outerPeer) throws SAXException, AccessorException, IOException, XMLStreamException {
  96         ListT list = acc.get(o);
  97 
  98         if(list!=null) {
  99             if(xacc.useNamespace()) {
 100                 w.startElement(tagName,null);
 101                 xacc.declareNamespace(o,w);
 102                 w.endNamespaceDecls(list);
 103                 w.endAttributes();
 104                 xacc.writeText(w,o,fieldName);
 105                 w.endElement();
 106             } else {
 107                 xacc.writeLeafElement(w, tagName, o, fieldName);
 108             }
 109         }
 110     }
 111 
 112     @Override
 113     public Accessor getElementPropertyAccessor(String nsUri, String localName) {
 114         if(tagName!=null) {
 115             if(tagName.equals(nsUri,localName))
 116                 return acc;
 117         }
 118         return null;
 119     }
 120 }