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.List;
21  import java.util.concurrent.atomic.AtomicReference;
22  import org.w3c.dom.Element;
23  import at.ac.tuwien.infosys.sm4all.copal.api.util.FailedUnmarshallingException;
24  import at.ac.tuwien.infosys.sm4all.copal.api.util.Marshaller;
25  import at.ac.tuwien.infosys.sm4all.copal.api.util.Unmarshaller;
26  
27  /**
28   * Unmarshals and marshals a child {@link Element} of a parent {@link Element} .
29   * 
30   * @param <T> the type of unmarshaled and marshaled value.
31   * @author sanjin
32   */
33  public class ElementUnmarshaller<T> extends ElementMarshaller<T> implements
34          Unmarshaller<T> {
35  
36      private final UnmarshallerBuilder<T> builder;
37  
38      /**
39       * Creates instance of child {@link Element} {@link Marshaller} of specified
40       * parent {@link Element}. Child {@link Element} will have specified local
41       * name and will be in {@link Constants#COPAL_NAMESPACE}. Specified
42       * {@link UnmarshallerBuilder} is used to create an {@link Unmarshaller}
43       * that will unmarshal and/or marshal a value into the child {@link Element}
44       * and specified {@link RemoveStrategy} is used to remove marshaled value.
45       * 
46       * @param parent the parent {@link Element}.
47       * @param childName the local name of the child {@link Element}.
48       * @param builder the {@link UnmarshallerBuilder} to create a
49       *        {@link Unmarshaller} for the child {@link Element}.
50       * @param strategy the {@link RemoveStrategy}.
51       * @throws NullPointerException if specified parent {@link Element}, name of
52       *         child {@link Element}, {@link UnmarshallerBuilder} or
53       *         {@link RemoveStrategy} is <code>null</code>.
54       * @throws IllegalArgumentException if specified name of child
55       *         {@link Element} is an empty or blank string.
56       */
57      public ElementUnmarshaller(final Element parent, final String childName,
58              final UnmarshallerBuilder<T> builder, final RemoveStrategy strategy) {
59          super(parent, childName, builder, strategy);
60  
61          this.builder = builder;
62      }
63  
64      /**
65       * Unmarshals a child {@link Element} using an {@link Unmarshaller} created
66       * with the {@link UnmarshallerBuilder}.
67       * 
68       * @return the {@link List} of unmarshaled child {@link Element}s.
69       * @throws FailedUnmarshallingException if unmarshalling was unsuccessful.
70       */
71      @Override
72      public T unmarshal() throws FailedUnmarshallingException {
73          return this.builder.withElement(getChildElement()).build().unmarshal();
74      }
75  
76      /**
77       * Builder of {@link ElementUnmarshaller}.
78       * 
79       * @param <T> the type of unmarshaled and marshaled value.
80       * @author sanjin
81       */
82      public static class Builder<T> extends ElementMarshaller.Builder<T>
83              implements UnmarshallerBuilder<T> {
84  
85          private final AtomicReference<UnmarshallerBuilder<T>> builderRef = new AtomicReference<UnmarshallerBuilder<T>>();
86  
87          /**
88           * Create uninitialized instance of {@link ElementUnmarshaller.Builder}.
89           */
90          public Builder() {
91              super();
92          }
93  
94          /**
95           * Clone-constructor.
96           * 
97           * @param builder the cloned {@link ElementUnmarshaller.Builder}.
98           */
99          private Builder(final Builder<T> builder) {
100             super(builder);
101 
102             this.builderRef.set(builder.builderRef.get());
103         }
104 
105         /**
106          * Returns the {@link UnmarshallerBuilder} to create an
107          * {@link Unmarshaller} for the child {@link Element}.
108          * 
109          * @return the {@link UnmarshallerBuilder} to create an
110          *         {@link Unmarshaller} for the child {@link Element}.
111          */
112         @Override
113         public UnmarshallerBuilder<T> getBuilder() {
114             return this.builderRef.get();
115         }
116 
117         /**
118          * Create instance of {@link ElementUnmarshaller.Builder} that will
119          * build {@link ElementUnmarshaller}s that will unmarshal and/or marshal
120          * values to specified parent {@link Element}.
121          * 
122          * @param element the parent {@link Element}.
123          * @return an {@link ElementUnmarshaller.Builder}.
124          */
125         @Override
126         public Builder<T> withElement(final Element element) {
127             return (Builder<T>) super.withElement(element);
128         }
129 
130         /**
131          * Create instance of {@link ElementUnmarshaller.Builder} that will
132          * build {@link ElementUnmarshaller}s that will unmarshal and/or marshal
133          * values using specified local name for the child {@link Element}.
134          * 
135          * @param childName the local name of the child {@link Element}.
136          * @return an {@link ElementUnmarshaller.Builder}.
137          */
138         @Override
139         public Builder<T> withChildName(final String childName) {
140             return (Builder<T>) super.withChildName(childName);
141         }
142 
143         /**
144          * Create instance of {@link ElementUnmarshaller.Builder} that will
145          * build {@link ElementUnmarshaller}s that will unmarshal and/or marshal
146          * values using specified {@link UnmarshallerBuilder} to create an
147          * {@link Unmarshaller} for the child {@link Element}.
148          * 
149          * @param builder the {@link UnmarshallerBuilder} to create an
150          *        {@link Unmarshaller} for the child {@link Element}.
151          * @return an {@link ElementUnmarshaller.Builder}.
152          */
153         @Override
154         @Deprecated
155         public Builder<T> withBuilder(final MarshallerBuilder<T> builder) {
156             if (!(builder instanceof UnmarshallerBuilder)) {
157                 throw new IllegalArgumentException(
158                         "Marshaller builder is not an unmarshaller builder.");
159             }
160 
161             return withBuilder((UnmarshallerBuilder<T>) builder);
162         }
163 
164         /**
165          * Create instance of {@link ElementUnmarshaller.Builder} that will
166          * build {@link ElementUnmarshaller}s that will unmarshal and/or marshal
167          * values using specified {@link UnmarshallerBuilder} to create an
168          * {@link Unmarshaller} for the child {@link Element}.
169          * 
170          * @param builder the {@link UnmarshallerBuilder} to create an
171          *        {@link Unmarshaller} for the child {@link Element}.
172          * @return an {@link ElementUnmarshaller.Builder}.
173          */
174         public Builder<T> withBuilder(final UnmarshallerBuilder<T> builder) {
175             final Builder<T> result = copy();
176 
177             result.builderRef.set(builder);
178 
179             return result;
180         }
181 
182         /**
183          * Create instance of {@link ElementUnmarshaller.Builder} that will
184          * build {@link ElementUnmarshaller}s that will remove marshaled values
185          * using specified {@link RemoveStrategy}.
186          * 
187          * @param strategy the {@link RemoveStrategy}.
188          * @return an {@link ElementUnmarshaller.Builder}.
189          */
190         @Override
191         public Builder<T> withStrategy(final RemoveStrategy strategy) {
192             return (Builder<T>) super.withStrategy(strategy);
193         }
194 
195         /**
196          * Create instance of {@link ElementUnmarshaller}.
197          * 
198          * @return a {@link ElementUnmarshaller}.
199          */
200         @Override
201         public ElementUnmarshaller<T> build() {
202             return new ElementUnmarshaller<T>(getElement(), getChildName(),
203                     getBuilder(), getStrategy());
204         }
205 
206         @Override
207         protected Builder<T> copy() {
208             return new Builder<T>(this);
209         }
210     }
211 }