001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.camel.model.dataformat;
018    
019    import java.util.ArrayList;
020    import java.util.Arrays;
021    import java.util.HashMap;
022    import java.util.List;
023    import java.util.Map;
024    
025    import javax.xml.bind.annotation.XmlAccessType;
026    import javax.xml.bind.annotation.XmlAccessorType;
027    import javax.xml.bind.annotation.XmlAttribute;
028    import javax.xml.bind.annotation.XmlElement;
029    import javax.xml.bind.annotation.XmlRootElement;
030    import javax.xml.bind.annotation.XmlTransient;
031    import javax.xml.bind.annotation.adapters.XmlAdapter;
032    import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
033    
034    import org.apache.camel.model.DataFormatDefinition;
035    import org.apache.camel.spi.DataFormat;
036    import org.apache.camel.spi.RouteContext;
037    
038    /**
039     * Represents the XStream XML {@link org.apache.camel.spi.DataFormat}
040     *
041     * @version $Revision: 20332 $
042     */
043    @XmlRootElement(name = "xstream")
044    @XmlAccessorType(XmlAccessType.NONE)
045    public class XStreamDataFormat extends DataFormatDefinition {
046        @XmlAttribute
047        private String encoding;
048    
049        @XmlAttribute
050        private String driver = "xml";
051    
052        @XmlJavaTypeAdapter(ConvertersAdapter.class)
053        @XmlElement(name = "converters")
054        private List<String> converters;
055    
056        @XmlJavaTypeAdapter(AliasAdapter.class)
057        @XmlElement(name = "aliases")
058        private Map<String, String> aliases;
059    
060        @XmlJavaTypeAdapter(ImplicitCollectionsAdapter.class)
061        @XmlElement(name = "implicitCollections")
062        private Map<String, String[]> implicitCollections;
063    
064    
065        public XStreamDataFormat() {
066            super("xstream");
067        }
068        
069        public XStreamDataFormat(String encoding) {
070            this();
071            setEncoding(encoding);
072        }
073        
074        public String getEncoding() {
075            return encoding;
076        }
077        
078        public void setEncoding(String encoding) {
079            this.encoding = encoding;
080        }
081    
082        public String getDriver() {
083            return driver;
084        }
085    
086        public void setDriver(String driver) {
087            this.driver = driver;
088        }
089    
090        public List<String> getConverters() {
091            return converters;
092        }
093    
094        public void setConverters(List<String> converters) {
095            this.converters = converters;
096        }
097    
098        public Map<String, String> getAliases() {
099            return aliases;
100        }
101    
102        public void setAliases(Map<String, String> aliases) {
103            this.aliases = aliases;
104        }
105    
106        public Map<String, String[]> getImplicitCollections() {
107            return implicitCollections;
108        }
109    
110        public void setImplicitCollections(Map<String, String[]> implicitCollections) {
111            this.implicitCollections = implicitCollections;
112        }
113    
114        @Override
115        protected DataFormat createDataFormat(RouteContext routeContext) {
116            if ("json".equals(this.driver)) {
117                setProperty(this, "dataFormatName", "json-xstream");
118            }
119            return super.createDataFormat(routeContext);
120        }
121    
122        @Override
123        protected void configureDataFormat(DataFormat dataFormat) {
124            if (encoding != null) {
125                setProperty(dataFormat, "encoding", encoding);
126            }
127    
128            if (this.converters != null) {
129                setProperty(dataFormat, "converters", this.converters);
130            }
131    
132            if (this.aliases != null) {
133                setProperty(dataFormat, "aliases", this.aliases);
134            }
135    
136            if (this.implicitCollections != null) {
137                setProperty(dataFormat, "implicitCollections", this.implicitCollections);
138            }
139        }
140    
141    
142        @XmlTransient
143        public static class ConvertersAdapter extends XmlAdapter<ConverterList, List<String>> {
144            @Override
145            public ConverterList marshal(List<String> v) throws Exception {
146                List<ConverterEntry> list = new ArrayList<ConverterEntry>();
147                for (String str : v) {
148                    ConverterEntry entry = new ConverterEntry();
149                    entry.setClsName(str);
150                    list.add(entry);
151                }
152    
153                ConverterList converterList = new ConverterList();
154                converterList.setList(list);
155                return converterList;
156            }
157    
158            @Override
159            public List<String> unmarshal(ConverterList v) throws Exception {
160                List<String> list = new ArrayList<String>();
161                for (ConverterEntry entry : v.getList()) {
162                    list.add(entry.getClsName());
163                }
164                return list;
165            }
166        }
167    
168        @XmlAccessorType(XmlAccessType.NONE)
169        public static class ConverterList {
170            @XmlElement(name = "converter")
171            private List<ConverterEntry> list = new ArrayList<ConverterEntry>();
172    
173            public List<ConverterEntry> getList() {
174                return list;
175            }
176    
177            public void setList(List<ConverterEntry> list) {
178                this.list = list;
179            }
180        }
181    
182        @XmlAccessorType(XmlAccessType.NONE)
183        public static class ConverterEntry {
184            @XmlAttribute(name = "class")
185            private String clsName;
186    
187            public String getClsName() {
188                return clsName;
189            }
190    
191            public void setClsName(String clsName) {
192                this.clsName = clsName;
193            }
194    
195        }
196    
197        @XmlTransient
198        public static class ImplicitCollectionsAdapter 
199                extends XmlAdapter<ImplicitCollectionList, Map<String, String[]>> {
200    
201            @Override
202            public ImplicitCollectionList marshal(Map<String, String[]> v) throws Exception {
203                List<ImplicitCollectionEntry> list = new ArrayList<ImplicitCollectionEntry>();
204                for (String clsName : v.keySet()) {
205                    ImplicitCollectionEntry entry = new ImplicitCollectionEntry(
206                            clsName, v.get(clsName));
207                    list.add(entry);
208                }
209    
210                ImplicitCollectionList collectionList = new ImplicitCollectionList();
211                collectionList.setList(list);
212    
213                return collectionList;
214            }
215    
216            @Override
217            public Map<String, String[]> unmarshal(ImplicitCollectionList v) throws Exception {
218                Map<String, String[]> map = new HashMap<String, String[]>();
219                for (ImplicitCollectionEntry entry : v.getList()) {
220                    map.put(entry.getClsName(), entry.getFields());
221                }
222                return map;
223            }
224        }
225    
226        @XmlAccessorType(XmlAccessType.NONE)
227        public static class ImplicitCollectionList {
228            @XmlElement(name = "class")
229            private List<ImplicitCollectionEntry> list = new ArrayList<ImplicitCollectionEntry>();
230    
231            public List<ImplicitCollectionEntry> getList() {
232                return list;
233            }
234    
235            public void setList(List<ImplicitCollectionEntry> list) {
236                this.list = list;
237            }
238        }
239    
240        @XmlAccessorType(XmlAccessType.NONE)
241        public static class ImplicitCollectionEntry {
242            @XmlAttribute(name = "name")
243            private String clsName;
244    
245            @XmlElement(name = "field")
246            private String[] fields;
247    
248            public ImplicitCollectionEntry() {
249            }
250    
251            public ImplicitCollectionEntry(String clsName, String[] fields) {
252                this.clsName = clsName;
253                this.fields = fields;
254            }
255    
256            public String getClsName() {
257                return clsName;
258            }
259    
260            public void setClsName(String clsName) {
261                this.clsName = clsName;
262            }
263    
264            public String[] getFields() {
265                return fields;
266            }
267    
268            public void setFields(String[] fields) {
269                this.fields = fields;
270            }
271    
272            @Override
273            public String toString() {
274                return "Alias [ImplicitCollection=" + clsName + ", fields=" + Arrays.asList(this.fields) + "]";
275            }
276        }
277    
278        @XmlTransient
279        public static class AliasAdapter extends XmlAdapter<AliasList, Map<String, String>> {
280    
281            @Override
282            public AliasList marshal(Map<String, String> value) throws Exception {
283                if (value == null || value.isEmpty()) {
284                    return new AliasList();
285                }
286    
287                List<AliasEntry> ret = new ArrayList<AliasEntry>(value.size());
288                for (Map.Entry<String, String> entry : value.entrySet()) {
289                    ret.add(new AliasEntry(entry.getKey(), entry.getValue()));
290                }
291                AliasList jaxbMap = new AliasList();
292                jaxbMap.setList(ret);
293                return jaxbMap; // ret.toArray( new JaxbMapEntry[ret.size()] );
294            }
295    
296            @Override
297            public Map<String, String> unmarshal(AliasList value) throws Exception {
298                Map<String, String> answer = new HashMap<String, String>();
299                for (AliasEntry alias : value.getList()) {
300                    answer.put(alias.getName(), alias.getClsName());
301                }
302                return answer;
303            }
304    
305        }
306    
307        @XmlAccessorType(XmlAccessType.NONE)
308        public static class AliasList {
309            @XmlElement(name = "alias")
310            private List<AliasEntry> list = new ArrayList<AliasEntry>();
311    
312            public List<AliasEntry> getList() {
313                return list;
314            }
315    
316            public void setList(List<AliasEntry> list) {
317                this.list = list;
318            }
319        }
320    
321        @XmlAccessorType(XmlAccessType.NONE)
322        public static class AliasEntry {
323    
324            @XmlAttribute
325            private String name;
326    
327            @XmlAttribute(name = "class")
328            private String clsName;
329    
330            public AliasEntry() {
331            }
332    
333            public AliasEntry(String key, String clsName) {
334                this.name = key;
335                this.clsName = clsName;
336            }
337    
338            public String getName() {
339                return name;
340            }
341    
342            public void setName(String name) {
343                this.name = name;
344            }
345    
346            public String getClsName() {
347                return clsName;
348            }
349    
350            public void setClsName(String clsName) {
351                this.clsName = clsName;
352            }
353    
354            @Override
355            public String toString() {
356                return "Alias [name=" + name + ", class=" + clsName + "]";
357            }
358        }
359    }