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.query.xml;
19  
20  import java.util.Arrays;
21  import java.util.List;
22  import java.util.concurrent.atomic.AtomicReference;
23  import org.w3c.dom.Element;
24  import at.ac.tuwien.infosys.sm4all.copal.api.event.ContextEventType;
25  import at.ac.tuwien.infosys.sm4all.copal.api.listener.ContextListener;
26  import at.ac.tuwien.infosys.sm4all.copal.api.listener.xml.ContextListenerMarshaller;
27  import at.ac.tuwien.infosys.sm4all.copal.api.query.ProcessedEventQuery;
28  import at.ac.tuwien.infosys.sm4all.copal.api.service.ContextQueryFactory;
29  import at.ac.tuwien.infosys.sm4all.copal.api.service.RedefinitionOfQueryException;
30  import at.ac.tuwien.infosys.sm4all.copal.api.util.FailedUnmarshallingException;
31  import at.ac.tuwien.infosys.sm4all.copal.api.util.Marshaller;
32  import at.ac.tuwien.infosys.sm4all.copal.api.util.Unmarshaller;
33  import at.ac.tuwien.infosys.sm4all.copal.api.xml.BaseUnmarshallerBuilder;
34  import at.ac.tuwien.infosys.sm4all.copal.api.xml.ElementMarshaller;
35  import at.ac.tuwien.infosys.sm4all.copal.api.xml.ListMarshaller;
36  import at.ac.tuwien.infosys.sm4all.copal.api.xml.ListUnmarshaller;
37  import at.ac.tuwien.infosys.sm4all.copal.api.xml.RemoveStrategy;
38  
39  /**
40   * Unmarshals and marshals a {@link ProcessedEventQuery} from/into an
41   * {@link Element}.
42   * 
43   * @author sanjin
44   */
45  public class ProcessedEventQueryUnmarshaller implements
46          Unmarshaller<ProcessedEventQuery> {
47  
48      /**
49       * The local name of child {@link Element}s used in the
50       * {@link ListMarshaller.Builder} that is returned by the
51       * {@link #getListBuilder(ContextQueryFactory)}.
52       */
53      public static final String QUERY_ELEMENT = ContextQueryMarshaller.QUERY_ELEMENT;
54      /**
55       * The name of attribute that holds marshaled name.
56       */
57      public static final String NAME_ATTRIBUTE = ContextQueryMarshaller.NAME_ATTRIBUTE;
58      /**
59       * The name of attribute that holds marshaled listened
60       * {@link ContextEventType}.
61       */
62      public static final String LISTENED_TYPE_ATTRIBUTE = ContextQueryMarshaller.LISTENED_TYPE_ATTRIBUTE;
63      /**
64       * The name of attribute that holds marshaled criteria.
65       */
66      public static final String CRITERIA_ATTRIBUTE = ContextQueryMarshaller.CRITERIA_ATTRIBUTE;
67      /**
68       * The local name of child {@link Element} that holds marshaled
69       * {@link ContextListener}s.
70       */
71      public static final String LISTENERS_ELEMENT = "Listeners";
72  
73      private final ContextQueryFactory factory;
74      private final Element element;
75      private final ContextQueryMarshaller queryMarshaller;
76      private final Marshaller<List<ContextListener>> listeners;
77  
78      /**
79       * Creates instance of {@link ProcessedEventQuery} {@link Unmarshaller}
80       * which uses specified {@link Element} for unmarshalling and/or marshalling
81       * and specified {@link ContextQueryFactory} to creating unmarshaled
82       * {@link ProcessedEventQuery}s.
83       * 
84       * @param factory the {@link ContextQueryFactory} used for creating the
85       *        unmarshaled {@link ProcessedEventQuery}s.
86       * @param element the {@link Element} used for unmarshalling.
87       * @throws NullPointerException if specified {@link Element} or
88       *         {@link ContextQueryFactory} is <code>null</code>.
89       */
90      public ProcessedEventQueryUnmarshaller(final ContextQueryFactory factory,
91              final Element element) {
92          super();
93  
94          if (null == factory) {
95              throw new NullPointerException("Factory cannot be null.");
96          }
97          if (null == element) {
98              throw new NullPointerException("XML DOM element cannot be null.");
99          }
100 
101         this.factory = factory;
102         this.element = element;
103         this.queryMarshaller = new ContextQueryMarshaller(element);
104         this.listeners = new ElementMarshaller<List<ContextListener>>(element,
105                 LISTENERS_ELEMENT, ContextListenerMarshaller.getListBuilder(),
106                 RemoveStrategy.RemoveElement);
107     }
108 
109     /**
110      * Returns the {@link ContextQueryFactory} used for creating the unmarshaled
111      * {@link ProcessedEventQuery}s.
112      * 
113      * @return the {@link ContextQueryFactory} used for creating the unmarshaled
114      *         {@link ProcessedEventQuery}s.
115      */
116     public ContextQueryFactory getFactory() {
117         return this.factory;
118     }
119 
120     /**
121      * Returns the {@link Element} used for marshalling.
122      * 
123      * @return the {@link Element} used for marshalling.
124      */
125     public Element getElement() {
126         return this.element;
127     }
128 
129     /**
130      * Unmarshals a {@link ProcessedEventQuery} from the {@link Element}.
131      * 
132      * @return the unmarshaled {@link ProcessedEventQuery}.
133      * @throws FailedUnmarshallingException if unmarshalling was unsuccessful.
134      */
135     @Override
136     public ProcessedEventQuery unmarshal() throws FailedUnmarshallingException {
137         final ProcessedEventQuery result;
138 
139         try {
140             final String criteria = unmarshalCriteria();
141             if (null == criteria) {
142                 result = this.factory.create(unmarshalName(),
143                         unmarshalListenedType());
144             } else {
145                 result = this.factory.create(unmarshalName(),
146                         unmarshalListenedType(), criteria);
147             }
148         } catch (final RedefinitionOfQueryException ex) {
149             throw new FailedUnmarshallingException("Creation of query failed.",
150                     ex);
151         }
152 
153         return result;
154     }
155 
156     /**
157      * Unmarshals name of {@link ProcessedEventQuery} from the {@link Element}.
158      * 
159      * @return the name of marshaled {@link ProcessedEventQuery}.
160      * @throws FailedUnmarshallingException if unmarshalling was unsuccessful.
161      */
162     public String unmarshalName() throws FailedUnmarshallingException {
163         return this.queryMarshaller.unmarshalName();
164     }
165 
166     /**
167      * Unmarshals name of listened {@link ContextEventType} of
168      * {@link ProcessedEventQuery} from the {@link Element}.
169      * 
170      * @return the name of listened {@link ContextEventType} of marshaled
171      *         {@link ProcessedEventQuery}.
172      * @throws FailedUnmarshallingException if unmarshalling was unsuccessful.
173      */
174     public String unmarshalListenedType() throws FailedUnmarshallingException {
175         return this.queryMarshaller.unmarshalListenedType();
176     }
177 
178     /**
179      * Unmarshals criteria of {@link ProcessedEventQuery} from the
180      * {@link Element}.
181      * 
182      * @return the criteria of marshaled {@link ProcessedEventQuery}.
183      * @throws FailedUnmarshallingException if unmarshalling was unsuccessful.
184      */
185     public String unmarshalCriteria() throws FailedUnmarshallingException {
186         return this.queryMarshaller.unmarshalCriteria();
187     }
188 
189     /**
190      * Marshals specified {@link ProcessedEventQuery} into the {@link Element}.
191      * 
192      * @param query the {@link ProcessedEventQuery}.
193      * @throws NullPointerException if specified {@link ProcessedEventQuery} is
194      *         <code>null</code>.
195      */
196     @Override
197     public void marshal(final ProcessedEventQuery query) {
198         this.queryMarshaller.marshal(query);
199         @SuppressWarnings("hiding")
200         final ContextListener[] listeners = query.getAll();
201         if (listeners.length > 0) {
202             this.listeners.marshal(Arrays.asList(listeners));
203         } else {
204             this.listeners.remove();
205         }
206     }
207 
208     /**
209      * Removes any marshaled {@link ProcessedEventQuery} from the
210      * {@link Element}.
211      */
212     @Override
213     public void remove() {
214         this.queryMarshaller.remove();
215         this.listeners.remove();
216     }
217 
218     /**
219      * Creates instance of {@link ListUnmarshaller.Builder} for
220      * {@link ProcessedEventQuery}s that will be created with specified
221      * {@link ContextQueryFactory}. The returned
222      * {@link ListUnmarshaller.Builder} does not have the parent {@link Element}
223      * set and caller should set it before building the {@link ListUnmarshaller}
224      * for {@link ProcessedEventQuery}s. The name for child {@link Element}s is
225      * set to {@link ContextQueryMarshaller#QUERY_ELEMENT}.
226      * 
227      * @param factory the {@link ContextQueryFactory} used to create
228      *        {@link ProcessedEventQuery}s.
229      * @return the {@link ListUnmarshaller.Builder} for
230      *         {@link ProcessedEventQuery}s.
231      */
232     public static ListUnmarshaller.Builder<ProcessedEventQuery> getListBuilder(
233             final ContextQueryFactory factory) {
234         return new ListUnmarshaller.Builder<ProcessedEventQuery>().withChildName(
235                 QUERY_ELEMENT).withBuilder(new Builder().withFactory(factory));
236     }
237 
238     /**
239      * Builder of {@link ProcessedEventQueryUnmarshaller}.
240      * 
241      * @author sanjin
242      */
243     public static class Builder extends
244             BaseUnmarshallerBuilder<ProcessedEventQuery> {
245 
246         private final AtomicReference<ContextQueryFactory> factoryRef = new AtomicReference<ContextQueryFactory>();
247 
248         /**
249          * Create uninitialized instance of
250          * {@link ProcessedEventQueryUnmarshaller.Builder}.
251          */
252         public Builder() {
253             super();
254         }
255 
256         /**
257          * Clone-constructor.
258          * 
259          * @param builder the cloned
260          *        {@link ProcessedEventQueryUnmarshaller.Builder}.
261          */
262         protected Builder(final Builder builder) {
263             super(builder);
264 
265             this.factoryRef.set(builder.factoryRef.get());
266         }
267 
268         /**
269          * Returns the {@link ContextQueryFactory}.
270          * 
271          * @return the {@link ContextQueryFactory}.
272          */
273         public ContextQueryFactory getFactory() {
274             return this.factoryRef.get();
275         }
276 
277         /**
278          * Create instance of {@link ProcessedEventQueryUnmarshaller.Builder}
279          * that will build {@link ProcessedEventQueryUnmarshaller}s that will
280          * use specified {@link ContextQueryFactory} to create
281          * {@link ProcessedEventQuery}s.
282          * 
283          * @param factory the {@link ContextQueryFactory}.
284          * @return an {@link ProcessedEventQueryUnmarshaller.Builder}.
285          */
286         public Builder withFactory(final ContextQueryFactory factory) {
287             final Builder result = copy();
288 
289             result.factoryRef.set(factory);
290 
291             return result;
292         }
293 
294         /**
295          * Create instance of {@link ProcessedEventQueryUnmarshaller}.
296          * 
297          * @return a {@link ProcessedEventQueryUnmarshaller}.
298          */
299         @Override
300         public ProcessedEventQueryUnmarshaller build() {
301             return new ProcessedEventQueryUnmarshaller(getFactory(),
302                     getElement());
303         }
304 
305         @Override
306         protected Builder copy() {
307             return new Builder(this);
308         }
309     }
310 }