View Javadoc

1   /* This file is part of COPAL (COntext Provisioning for All).
2    *
3    * COPAL is a part of SM4All (Smart hoMes for All) project.
4    *
5    * COPAL is free software: you can redistribute it and/or modify
6    * it under the terms of the GNU Lesser General Public License as published by
7    * the Free Software Foundation, either version 3 of the License, or
8    * (at your option) any later version.
9    *
10   * COPAL is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU Lesser General Public License for more details.
14   *
15   * You should have received a copy of the GNU Lesser General Public License
16   * along with COPAL. If not, see <http://www.gnu.org/licenses/>.
17   */
18  package at.ac.tuwien.infosys.sm4all.copal.api.xml;
19  
20  import java.util.Collections;
21  import java.util.LinkedList;
22  import java.util.List;
23  import java.util.concurrent.atomic.AtomicReference;
24  import org.w3c.dom.Element;
25  import at.ac.tuwien.infosys.sm4all.copal.api.util.FailedUnmarshallingException;
26  import at.ac.tuwien.infosys.sm4all.copal.api.util.Marshaller;
27  import at.ac.tuwien.infosys.sm4all.copal.api.util.Unmarshaller;
28  
29  /**
30   * Unmarshals and marshals a {@link List} of values from/to an {@link Element} .
31   * 
32   * @param <T> the type of unmarshaled and marshaled {@link List} elements.
33   * @author sanjin
34   */
35  public class ListUnmarshaller<T> extends ListMarshaller<T> implements
36          Unmarshaller<List<T>> {
37  
38      private final UnmarshallerBuilder<T> builder;
39  
40      /**
41       * Creates instance of {@link List} {@link Marshaller} that marshals each
42       * value from a {@link List} into a separate child {@link Element} of
43       * specified parent {@link Element}. Child {@link Element}s will have
44       * specified local name and will be in {@link Constants#COPAL_NAMESPACE}.
45       * Specified {@link UnmarshallerBuilder} is used to create an
46       * {@link Unmarshaller} that will unmarshal and/or marshal a value into a
47       * child {@link Element}.
48       * 
49       * @param parent the parent {@link Element}.
50       * @param childName the local name of child {@link Element}s.
51       * @param builder the {@link UnmarshallerBuilder} to create
52       *        {@link Unmarshaller}s for child {@link Element}s.
53       * @throws NullPointerException if specified parent {@link Element}, name of
54       *         child {@link Element}s or {@link MarshallerBuilder} is
55       *         <code>null</code>.
56       * @throws IllegalArgumentException if specified name of child
57       *         {@link Element}s is an empty or blank string.
58       */
59      public ListUnmarshaller(final Element parent, final String childName,
60              final UnmarshallerBuilder<T> builder) {
61          super(parent, childName, builder);
62  
63          this.builder = builder;
64      }
65  
66      /**
67       * Unmarshals each child {@link Element} using an {@link Unmarshaller}
68       * created with the {@link UnmarshallerBuilder}.
69       * 
70       * @return the {@link List} of unmarshaled child {@link Element}s.
71       * @throws FailedUnmarshallingException if unmarshalling was unsuccessful.
72       */
73      @Override
74      public List<T> unmarshal() throws FailedUnmarshallingException {
75          final List<T> result = new LinkedList<T>();
76  
77          for (final Element child : getChildElements()) {
78              result.add(this.builder.withElement(child).build().unmarshal());
79          }
80  
81          return Collections.unmodifiableList(result);
82      }
83  
84      /**
85       * Builder of {@link ListUnmarshaller}.
86       * 
87       * @param <T> the type of unmarshaled and marshaled {@link List} elements.
88       * @author sanjin
89       */
90      public static class Builder<T> extends ListMarshaller.Builder<T> implements
91              UnmarshallerBuilder<List<T>> {
92  
93          private final AtomicReference<UnmarshallerBuilder<T>> builderRef = new AtomicReference<UnmarshallerBuilder<T>>();
94  
95          /**
96           * Create uninitialized instance of {@link ListUnmarshaller.Builder}.
97           */
98          public Builder() {
99              super();
100         }
101 
102         /**
103          * Clone-constructor.
104          * 
105          * @param builder the cloned {@link ListUnmarshaller.Builder}.
106          */
107         private Builder(final Builder<T> builder) {
108             super(builder);
109 
110             this.builderRef.set(builder.builderRef.get());
111         }
112 
113         /**
114          * Returns the {@link UnmarshallerBuilder} to create
115          * {@link Unmarshaller}s for child {@link Element}s.
116          * 
117          * @return the {@link UnmarshallerBuilder} to create
118          *         {@link Unmarshaller}s for child {@link Element}s.
119          */
120         @Override
121         public UnmarshallerBuilder<T> getBuilder() {
122             return this.builderRef.get();
123         }
124 
125         /**
126          * Create instance of {@link ListUnmarshaller.Builder} that will build
127          * {@link ListUnmarshaller}s that will unmarshal and/or marshal values
128          * to specified parent {@link Element}.
129          * 
130          * @param element the parent {@link Element}.
131          * @return an {@link ListUnmarshaller.Builder}.
132          */
133         @Override
134         public Builder<T> withElement(final Element element) {
135             return (Builder<T>) super.withElement(element);
136         }
137 
138         /**
139          * Create instance of {@link ListUnmarshaller.Builder} that will build
140          * {@link ListUnmarshaller}s that will unmarshal and/or marshal values
141          * using specified local name for the child {@link Element}.
142          * 
143          * @param childName the local name of the child {@link Element}.
144          * @return an {@link ListUnmarshaller.Builder}.
145          */
146         @Override
147         public Builder<T> withChildName(final String childName) {
148             return (Builder<T>) super.withChildName(childName);
149         }
150 
151         /**
152          * Create instance of {@link ListUnmarshaller.Builder} that will build
153          * {@link ListUnmarshaller}s that will unmarshal and/or marshal values
154          * using specified {@link UnmarshallerBuilder} to create an
155          * {@link Unmarshaller} for the child {@link Element}.
156          * 
157          * @param builder the {@link UnmarshallerBuilder} to create an
158          *        {@link Unmarshaller} for the child {@link Element}.
159          * @return an {@link ListUnmarshaller.Builder}.
160          */
161         @Override
162         @Deprecated
163         public Builder<T> withBuilder(final MarshallerBuilder<T> builder) {
164             if (!(builder instanceof UnmarshallerBuilder)) {
165                 throw new IllegalArgumentException(
166                         "Marshaller builder is not an unmarshaller builder.");
167             }
168 
169             return withBuilder((UnmarshallerBuilder<T>) builder);
170         }
171 
172         /**
173          * Create instance of {@link ListUnmarshaller.Builder} that will build
174          * {@link ListUnmarshaller}s that will unmarshal and/or marshal values
175          * using specified {@link UnmarshallerBuilder} to create a
176          * {@link Unmarshaller} for the child {@link Element}.
177          * 
178          * @param builder the {@link UnmarshallerBuilder} to create a
179          *        {@link Unmarshaller} for the child {@link Element}.
180          * @return a {@link ListUnmarshaller.Builder}.
181          */
182         public Builder<T> withBuilder(final UnmarshallerBuilder<T> builder) {
183             final Builder<T> result = copy();
184 
185             result.builderRef.set(builder);
186 
187             return result;
188         }
189 
190         /**
191          * Create instance of {@link ListUnmarshaller}.
192          * 
193          * @return a {@link ListUnmarshaller}.
194          */
195         @Override
196         public ListUnmarshaller<T> build() {
197             return new ListUnmarshaller<T>(getElement(), getChildName(),
198                     getBuilder());
199         }
200 
201         @Override
202         protected Builder<T> copy() {
203             return new Builder<T>(this);
204         }
205     }
206 }