1/*
2 * Copyright (c) 1997, 2014, 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
26package com.sun.xml.internal.bind.v2.runtime;
27
28import java.io.IOException;
29import java.lang.reflect.Array;
30import java.util.List;
31
32import javax.xml.bind.JAXBException;
33import javax.xml.bind.ValidationEvent;
34import javax.xml.bind.helpers.ValidationEventImpl;
35import javax.xml.stream.XMLStreamException;
36
37import com.sun.istack.internal.FinalArrayList;
38import com.sun.xml.internal.bind.WhiteSpaceProcessor;
39import com.sun.xml.internal.bind.api.AccessorException;
40import com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader;
41import com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext;
42
43import org.xml.sax.SAXException;
44
45/**
46 * {@link JaxBeanInfo} implementation that binds T[] to a list of simple types.
47 *
48 * @author Kohsuke Kawaguchi
49 */
50final class ValueListBeanInfoImpl extends JaxBeanInfo {
51
52    private final Class itemType;
53    private final Transducer xducer;    // for items
54
55    public ValueListBeanInfoImpl(JAXBContextImpl owner, Class arrayType) throws JAXBException {
56        super(owner, null, arrayType, false, true, false);
57        this.itemType = jaxbType.getComponentType();
58        this.xducer = owner.getBeanInfo(arrayType.getComponentType(),true).getTransducer();
59        assert xducer!=null;
60    }
61
62    private final Loader loader = new Loader(true) {
63        @Override
64        public void text(UnmarshallingContext.State state, CharSequence text) throws SAXException {
65            List<Object> r = new FinalArrayList<Object>();
66
67            int idx = 0;
68            int len = text.length();
69
70            while(true) {
71                int p = idx;
72                while( p<len && !WhiteSpaceProcessor.isWhiteSpace(text.charAt(p)) )
73                    p++;
74
75                CharSequence token = text.subSequence(idx,p);
76                if (!token.equals(""))
77                    try {
78                        r.add(xducer.parse(token));
79                    } catch (AccessorException e) {
80                        handleGenericException(e,true);
81                        continue;   // move on to next
82                    }
83
84                if(p==len)      break;  // done
85
86                while( p<len && WhiteSpaceProcessor.isWhiteSpace(text.charAt(p)) )
87                    p++;
88                if(p==len)      break;  // done
89
90                idx = p;
91            }
92
93            state.setTarget(toArray(r));
94        }
95    };
96
97    private Object toArray( List list ) {
98        int len = list.size();
99        Object array = Array.newInstance(itemType,len);
100        for( int i=0; i<len; i++ )
101            Array.set(array,i,list.get(i));
102        return array;
103    }
104
105    public void serializeBody(Object array, XMLSerializer target) throws SAXException, IOException, XMLStreamException {
106        int len = Array.getLength(array);
107        for( int i=0; i<len; i++ )  {
108            Object item = Array.get(array,i);
109            try {
110                xducer.writeText(target,item,"arrayItem");
111            } catch (AccessorException e) {
112                target.reportError("arrayItem",e);
113            }
114        }
115    }
116
117    public final void serializeURIs(Object array, XMLSerializer target) throws SAXException {
118        if(xducer.useNamespace()) {
119            int len = Array.getLength(array);
120            for( int i=0; i<len; i++ )  {
121                Object item = Array.get(array,i);
122                try {
123                    xducer.declareNamespace(item,target);
124                } catch (AccessorException e) {
125                    target.reportError("arrayItem",e);
126                }
127            }
128        }
129    }
130
131    public final String getElementNamespaceURI(Object array) {
132        throw new UnsupportedOperationException();
133    }
134
135    public final String getElementLocalName(Object array) {
136        throw new UnsupportedOperationException();
137    }
138
139    public final Object createInstance(UnmarshallingContext context) {
140        throw new UnsupportedOperationException();
141    }
142
143    public final boolean reset(Object array, UnmarshallingContext context) {
144        return false;
145    }
146
147    public final String getId(Object array, XMLSerializer target) {
148        return null;
149    }
150
151    public final void serializeAttributes(Object array, XMLSerializer target) {
152        // noop
153    }
154
155    public final void serializeRoot(Object array, XMLSerializer target) throws SAXException {
156        target.reportError(
157                new ValidationEventImpl(
158                        ValidationEvent.ERROR,
159                        Messages.UNABLE_TO_MARSHAL_NON_ELEMENT.format(array.getClass().getName()),
160                        null,
161                        null));
162    }
163
164    public final Transducer getTransducer() {
165        return null;
166    }
167
168    public final Loader getLoader(JAXBContextImpl context, boolean typeSubstitutionCapable) {
169        // type substitution impossible
170        return loader;
171    }
172}
173