1/*
2 * Copyright (c) 1997, 2012, 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.reflect;
27
28import javax.xml.bind.JAXBException;
29
30import com.sun.xml.internal.bind.WhiteSpaceProcessor;
31import com.sun.xml.internal.bind.api.AccessorException;
32import com.sun.xml.internal.bind.v2.runtime.Transducer;
33import com.sun.xml.internal.bind.v2.runtime.XMLSerializer;
34
35import org.xml.sax.SAXException;
36
37/**
38 * {@link TransducedAccessor} for a list simple type.
39 *
40 * @author Kohsuke Kawaguchi
41 */
42public final class ListTransducedAccessorImpl<BeanT,ListT,ItemT,PackT> extends DefaultTransducedAccessor<BeanT> {
43    /**
44     * {@link Transducer} for each item type.
45     */
46    private final Transducer<ItemT> xducer;
47    /**
48     * {@link Lister} for handling list of tokens.
49     */
50    private final Lister<BeanT,ListT,ItemT,PackT> lister;
51    /**
52     * {@link Accessor} to get/set the list.
53     */
54    private final Accessor<BeanT,ListT> acc;
55
56    public ListTransducedAccessorImpl(Transducer<ItemT> xducer, Accessor<BeanT,ListT> acc, Lister<BeanT,ListT,ItemT,PackT> lister) {
57        this.xducer = xducer;
58        this.lister = lister;
59        this.acc = acc;
60    }
61
62    public boolean useNamespace() {
63        return xducer.useNamespace();
64    }
65
66    public void declareNamespace(BeanT bean, XMLSerializer w) throws AccessorException, SAXException {
67        ListT list = acc.get(bean);
68
69        if(list!=null) {
70           ListIterator<ItemT> itr = lister.iterator(list, w);
71
72            while(itr.hasNext()) {
73                try {
74                    ItemT item = itr.next();
75                    if (item != null) {
76                        xducer.declareNamespace(item,w);
77                    }
78                } catch (JAXBException e) {
79                    w.reportError(null,e);
80                }
81            }
82        }
83    }
84
85    // TODO: this is inefficient, consider a redesign
86    // perhaps we should directly write to XMLSerializer,
87    // or maybe add more methods like writeLeafElement.
88    public String print(BeanT o) throws AccessorException, SAXException {
89        ListT list = acc.get(o);
90
91        if(list==null)
92            return null;
93
94        StringBuilder buf = new StringBuilder();
95        XMLSerializer w = XMLSerializer.getInstance();
96        ListIterator<ItemT> itr = lister.iterator(list, w);
97
98        while(itr.hasNext()) {
99            try {
100                ItemT item = itr.next();
101                if (item != null) {
102                    if(buf.length()>0)  buf.append(' ');
103                    buf.append(xducer.print(item));
104                }
105            } catch (JAXBException e) {
106                w.reportError(null,e);
107            }
108        }
109        return buf.toString();
110    }
111
112    private void processValue(BeanT bean, CharSequence s) throws AccessorException, SAXException {
113        PackT pack = lister.startPacking(bean,acc);
114
115        int idx = 0;
116        int len = s.length();
117
118        while(true) {
119            int p = idx;
120            while( p<len && !WhiteSpaceProcessor.isWhiteSpace(s.charAt(p)) )
121                p++;
122
123            CharSequence token = s.subSequence(idx,p);
124            if (!token.equals(""))
125                lister.addToPack(pack,xducer.parse(token));
126
127            if(p==len)      break;  // done
128
129            while( p<len && WhiteSpaceProcessor.isWhiteSpace(s.charAt(p)) )
130                p++;
131            if(p==len)      break;  // done
132
133            idx = p;
134        }
135
136        lister.endPacking(pack,bean,acc);
137    }
138
139    public void parse(BeanT bean, CharSequence lexical) throws AccessorException, SAXException {
140        processValue(bean,lexical);
141    }
142
143    public boolean hasValue(BeanT bean) throws AccessorException {
144        return acc.get(bean)!=null;
145    }
146}
147