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
26package com.sun.xml.internal.ws.spi.db;
27
28import java.util.HashSet;
29import java.util.Iterator;
30import java.util.Collection;
31import java.util.List;
32import java.util.Set;
33import java.io.InputStream;
34import java.io.OutputStream;
35import java.util.NoSuchElementException;
36
37import javax.xml.bind.JAXBException;
38import javax.xml.bind.attachment.AttachmentMarshaller;
39import javax.xml.bind.attachment.AttachmentUnmarshaller;
40import javax.xml.namespace.NamespaceContext;
41import javax.xml.stream.XMLStreamReader;
42import javax.xml.stream.XMLStreamWriter;
43import javax.xml.transform.Result;
44import javax.xml.transform.Source;
45
46import org.w3c.dom.Node;
47import org.xml.sax.ContentHandler;
48
49/**
50 * RepeatedElementBridge
51 *
52 * @author shih-chang.chen@oracle.com
53 */
54@SuppressWarnings({"rawtypes", "unchecked"})
55public class RepeatedElementBridge<T> implements XMLBridge<T> {
56
57    XMLBridge<T> delegate;
58    CollectionHandler collectionHandler;
59
60    public RepeatedElementBridge(TypeInfo typeInfo, XMLBridge xb) {
61        delegate = xb;
62        collectionHandler = create(typeInfo);
63    }
64
65    public CollectionHandler collectionHandler() {
66        return collectionHandler;
67    }
68
69    @Override
70    public BindingContext context() {
71        return delegate.context();
72    }
73
74    @Override
75    public void marshal(T object, XMLStreamWriter output, AttachmentMarshaller am) throws JAXBException {
76        delegate.marshal(object, output, am);
77    }
78
79    @Override
80    public void marshal(T object, OutputStream output, NamespaceContext nsContext, AttachmentMarshaller am) throws JAXBException {
81        delegate.marshal(object, output, nsContext, am);
82    }
83
84    @Override
85    public void marshal(T object, Node output) throws JAXBException {
86        delegate.marshal(object, output);
87    }
88
89    @Override
90    public void marshal(T object, ContentHandler contentHandler, AttachmentMarshaller am) throws JAXBException {
91        delegate.marshal(object, contentHandler, am);
92    }
93
94    @Override
95    public void marshal(T object, Result result) throws JAXBException {
96        delegate.marshal(object, result);
97    }
98
99    @Override
100    public T unmarshal(XMLStreamReader in, AttachmentUnmarshaller au) throws JAXBException {
101        return delegate.unmarshal(in, au);
102    }
103
104    @Override
105    public T unmarshal(Source in, AttachmentUnmarshaller au) throws JAXBException {
106        return delegate.unmarshal(in, au);
107    }
108
109    @Override
110    public T unmarshal(InputStream in) throws JAXBException {
111        return delegate.unmarshal(in);
112    }
113
114    @Override
115    public T unmarshal(Node n, AttachmentUnmarshaller au) throws JAXBException {
116        return delegate.unmarshal(n, au);
117    }
118
119    @Override
120    public TypeInfo getTypeInfo() {
121        return delegate.getTypeInfo();
122    }
123
124    @Override
125    public boolean supportOutputStream() {
126        return delegate.supportOutputStream();
127    }
128
129    static public interface CollectionHandler {
130        int getSize(Object c);
131        Iterator iterator(Object c);
132        Object convert(List list);
133    }
134
135    static class BaseCollectionHandler implements CollectionHandler {
136        Class type;
137        BaseCollectionHandler(Class c) {type = c;}
138        @Override
139        public int getSize(Object c) { return ((Collection) c).size(); }
140        @Override
141        public Object convert(List list) {
142            try {
143                Object o = type.newInstance();
144                ((Collection)o).addAll(list);
145                return o;
146            } catch (Exception e) {
147                e.printStackTrace();
148            }
149            return list;
150        }
151        @Override
152        public Iterator iterator(Object c) {return ((Collection)c).iterator();}
153    }
154
155    static final CollectionHandler ListHandler = new BaseCollectionHandler(List.class) {
156        @Override
157        public Object convert(List list) {return list;}
158    };
159
160    static final CollectionHandler HashSetHandler = new BaseCollectionHandler(HashSet.class) {
161        @Override
162        public Object convert(List list) { return new HashSet(list);}
163    };
164
165    static public CollectionHandler create(TypeInfo ti) {
166        Class javaClass = (Class) ti.type;
167        if (javaClass.isArray()) {
168            return new ArrayHandler((Class) ti.getItemType().type);
169        } else if (List.class.equals(javaClass) || Collection.class.equals(javaClass)) {
170            return ListHandler;
171        } else if (Set.class.equals(javaClass) || HashSet.class.equals(javaClass)) {
172            return HashSetHandler;
173        } else {
174            return new BaseCollectionHandler(javaClass);
175        }
176    }
177
178    static class ArrayHandler implements CollectionHandler {
179        Class componentClass;
180        public ArrayHandler(Class component) {
181            componentClass = component;
182        }
183        @Override
184        public int getSize(Object c) {
185            return java.lang.reflect.Array.getLength(c);
186        }
187        @Override
188        public Object convert(List list) {
189            Object array = java.lang.reflect.Array.newInstance(componentClass, list.size());
190            for (int i = 0; i < list.size(); i++) {
191                java.lang.reflect.Array.set(array, i, list.get(i));
192            }
193            return array;
194        }
195        @Override
196        public Iterator iterator(final Object c) {
197            return new Iterator() {
198                int index = 0;
199                @Override
200                public boolean hasNext() {
201                    if (c == null || java.lang.reflect.Array.getLength(c) == 0) {
202                        return false;
203                    }
204                    return (index != java.lang.reflect.Array.getLength(c));
205                }
206                @Override
207                public Object next() throws NoSuchElementException {
208                    Object retVal = null;
209                    try {
210                        retVal = java.lang.reflect.Array.get(c, index++);
211                    } catch (ArrayIndexOutOfBoundsException ex) {
212                        throw new NoSuchElementException();
213                    }
214                    return retVal;
215                }
216                @Override
217                public void remove() {}
218            };
219        }
220    }
221}
222