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.event.xml;
19  
20  import java.util.Arrays;
21  import java.util.LinkedList;
22  import java.util.List;
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.event.DefaultAction;
26  import at.ac.tuwien.infosys.sm4all.copal.api.security.Authorization;
27  import at.ac.tuwien.infosys.sm4all.copal.api.util.Attribute;
28  import at.ac.tuwien.infosys.sm4all.copal.api.util.FailedUnmarshallingException;
29  import at.ac.tuwien.infosys.sm4all.copal.api.util.MissingFieldException;
30  import at.ac.tuwien.infosys.sm4all.copal.api.util.Unmarshaller;
31  import at.ac.tuwien.infosys.sm4all.copal.api.xml.BaseUnmarshallerBuilder;
32  import at.ac.tuwien.infosys.sm4all.copal.api.xml.ElementUnmarshaller;
33  import at.ac.tuwien.infosys.sm4all.copal.api.xml.IntegerAttribute;
34  import at.ac.tuwien.infosys.sm4all.copal.api.xml.ListUnmarshaller;
35  import at.ac.tuwien.infosys.sm4all.copal.api.xml.LongAttribute;
36  import at.ac.tuwien.infosys.sm4all.copal.api.xml.Optional;
37  import at.ac.tuwien.infosys.sm4all.copal.api.xml.RemoveStrategy;
38  import at.ac.tuwien.infosys.sm4all.copal.api.xml.StringAttribute;
39  import static at.ac.tuwien.infosys.sm4all.copal.api.event.ContextEventType.PRIORITY_DEFAULT;
40  import static at.ac.tuwien.infosys.sm4all.copal.api.event.ContextEventType.TTL_DEFAULT;
41  
42  /**
43   * Unmarshals and marshals a {@link ContextEventType} from/into an
44   * {@link Element}.
45   * 
46   * @author sanjin
47   */
48  public class ContextEventTypeUnmarshaller implements
49          Unmarshaller<ContextEventType> {
50  
51      /**
52       * The local name of child {@link Element}s used in the
53       * {@link ListUnmarshaller.Builder} that is returned by the
54       * {@link #getListBuilder()}.
55       */
56      public static final String EVENT_TYPE_ELEMENT = "Event";
57      /**
58       * The name of attribute that holds marshaled name.
59       */
60      public static final String NAME_ATTRIBUTE = "name";
61      /**
62       * The name of attribute that holds marshaled time-to-live.
63       */
64      public static final String TTL_ATTRIBUTE = "ttl";
65      /**
66       * The name of attribute that holds marshaled priority.
67       */
68      public static final String PRIORITY_ATTRIBUTE = "priority";
69      /**
70       * The local name of child {@link Element} that holds marshaled
71       * {@link Attribute}s.
72       */
73      public static final String ATTRIBUTES_ELEMENT = "Attributes";
74      /**
75       * The local name of child {@link Element} that holds marshaled
76       * {@link Authorization}s.
77       */
78      public static final String AUTHORIZATIONS_ELEMENT = "Authorizations";
79      /**
80       * The local name of child {@link Element} that holds marshaled
81       * {@link DefaultAction}s.
82       */
83      public static final String ACTIONS_ELEMENT = "Actions";
84  
85      private static final ListUnmarshaller.Builder<ContextEventType> LIST_BUILDER = new ListUnmarshaller.Builder<ContextEventType>().withChildName(
86              EVENT_TYPE_ELEMENT).withBuilder(new Builder());
87  
88      private final Element element;
89      private final Unmarshaller<String> name;
90      private final Unmarshaller<Long> ttl;
91      private final Unmarshaller<Integer> priority;
92      private final Unmarshaller<List<Attribute>> attributes;
93      private final Unmarshaller<List<Authorization>> authorizations;
94      private final Unmarshaller<List<DefaultAction>> actions;
95  
96      /**
97       * Creates instance of {@link ContextEventType} {@link Unmarshaller} which
98       * uses specified {@link Element} for unmarshalling and/or marshalling.
99       * 
100      * @param element the {@link Element} used for unmarshalling and
101      *        marshalling.
102      * @throws NullPointerException if specified {@link Element} is
103      *         <code>null</code>.
104      */
105     public ContextEventTypeUnmarshaller(final Element element) {
106         super();
107 
108         if (null == element) {
109             throw new NullPointerException("XML DOM element cannot be null.");
110         }
111 
112         this.element = element;
113         this.name = new StringAttribute(NAME_ATTRIBUTE, element);
114         this.ttl = new Optional<Long>(new LongAttribute(TTL_ATTRIBUTE, element));
115         this.priority = new Optional<Integer>(new IntegerAttribute(
116                 PRIORITY_ATTRIBUTE, element));
117         this.attributes = new ElementUnmarshaller<List<Attribute>>(element,
118                 ATTRIBUTES_ELEMENT, AttributeUnmarshaller.getListBuilder(),
119                 RemoveStrategy.RemoveElement);
120         this.authorizations = new ElementUnmarshaller<List<Authorization>>(
121                 element, AUTHORIZATIONS_ELEMENT,
122                 AuthorizationUnmarshaller.getListBuilder(),
123                 RemoveStrategy.RemoveElement);
124         this.actions = new ElementUnmarshaller<List<DefaultAction>>(element,
125                 ACTIONS_ELEMENT, DefaultActionUnmarshaller.getListBuilder(),
126                 RemoveStrategy.RemoveElement);
127     }
128 
129     /**
130      * Returns the {@link Element} used for unmarshalling and marshalling.
131      * 
132      * @return the {@link Element} used for unmarshalling and marshalling.
133      */
134     public Element getElement() {
135         return this.element;
136     }
137 
138     /**
139      * Unmarshals an {@link ContextEventType} from the {@link Element}.
140      * 
141      * @return the unmarshaled {@link ContextEventType}.
142      * @throws FailedUnmarshallingException if unmarshalling was unsuccessful.
143      */
144     @Override
145     public ContextEventType unmarshal() throws FailedUnmarshallingException {
146         final ContextEventType result = new ContextEventType(unmarshalName());
147 
148         result.setTTL(unmarshalTTL());
149         result.setPriority(unmarshalPriority());
150         for (final Attribute attribute : unmarshalAttributes()) {
151             result.add(attribute);
152         }
153         for (final Authorization authorization : unmarshalAuthorizations()) {
154             result.add(authorization);
155         }
156         result.append(unmarshalActions());
157 
158         return result;
159     }
160 
161     /**
162      * Unmarshals name of {@link ContextEventType} from the {@link Element}.
163      * 
164      * @return the name of marshaled {@link ContextEventType}.
165      * @throws FailedUnmarshallingException if unmarshalling was unsuccessful.
166      */
167     public String unmarshalName() throws FailedUnmarshallingException {
168         final String result;
169 
170         try {
171             result = this.name.unmarshal();
172         } catch (final MissingFieldException ex) {
173             throw new MissingFieldException("Event name", ex);
174         }
175 
176         return result;
177     }
178 
179     /**
180      * Unmarshals time-to-live of {@link ContextEventType} from the
181      * {@link Element}. If the time-to-live value is missing then the
182      * {@link ContextEventType#TTL_DEFAULT} is returned.
183      * 
184      * @return the time-to-live of marshaled {@link ContextEventType}.
185      * @throws FailedUnmarshallingException if unmarshalling was unsuccessful.
186      */
187     public long unmarshalTTL() throws FailedUnmarshallingException {
188         Long result = this.ttl.unmarshal();
189 
190         if (null == result) {
191             result = TTL_DEFAULT;
192         }
193 
194         return result;
195     }
196 
197     /**
198      * Unmarshals priority of {@link ContextEventType} from the {@link Element}
199      * . If the priority value is missing then the
200      * {@link ContextEventType#PRIORITY_DEFAULT} is returned.
201      * 
202      * @return the priority of marshaled {@link ContextEventType}.
203      * @throws FailedUnmarshallingException if unmarshalling was unsuccessful.
204      */
205     public int unmarshalPriority() throws FailedUnmarshallingException {
206         Integer result = this.priority.unmarshal();
207 
208         if (null == result) {
209             result = PRIORITY_DEFAULT;
210         }
211 
212         return result;
213     }
214 
215     /**
216      * Unmarshals {@link Attribute}s of {@link ContextEventType} from the
217      * {@link Element}.
218      * 
219      * @return the {@link Attribute}s of marshaled {@link ContextEventType}.
220      * @throws FailedUnmarshallingException if unmarshalling was unsuccessful.
221      */
222     public Attribute[] unmarshalAttributes()
223             throws FailedUnmarshallingException {
224         List<Attribute> result;
225 
226         try {
227             result = this.attributes.unmarshal();
228         } catch (final MissingFieldException ex) {
229             if (ATTRIBUTES_ELEMENT.equals(ex.getFieldName())) {
230                 result = new LinkedList<Attribute>();
231             } else {
232                 throw ex;
233             }
234         }
235 
236         return result.toArray(new Attribute[result.size()]);
237     }
238 
239     /**
240      * Unmarshals {@link Authorization}s of {@link ContextEventType} from the
241      * {@link Element}.
242      * 
243      * @return the {@link Authorization}s of marshaled {@link ContextEventType}
244      *         .
245      * @throws FailedUnmarshallingException if unmarshalling was unsuccessful.
246      */
247     public Authorization[] unmarshalAuthorizations()
248             throws FailedUnmarshallingException {
249         List<Authorization> result;
250 
251         try {
252             result = this.authorizations.unmarshal();
253         } catch (final MissingFieldException ex) {
254             if (AUTHORIZATIONS_ELEMENT.equals(ex.getFieldName())) {
255                 result = new LinkedList<Authorization>();
256             } else {
257                 throw ex;
258             }
259         }
260 
261         return result.toArray(new Authorization[result.size()]);
262     }
263 
264     /**
265      * Unmarshals {@link DefaultAction}s of {@link ContextEventType} from the
266      * {@link Element}.
267      * 
268      * @return the {@link DefaultAction}s of marshaled {@link ContextEventType}
269      *         .
270      * @throws FailedUnmarshallingException if unmarshalling was unsuccessful.
271      */
272     public DefaultAction[] unmarshalActions()
273             throws FailedUnmarshallingException {
274         List<DefaultAction> result;
275 
276         try {
277             result = this.actions.unmarshal();
278         } catch (final MissingFieldException ex) {
279             if (ACTIONS_ELEMENT.equals(ex.getFieldName())) {
280                 result = new LinkedList<DefaultAction>();
281             } else {
282                 throw ex;
283             }
284         }
285 
286         return result.toArray(new DefaultAction[result.size()]);
287     }
288 
289     /**
290      * Marshals specified {@link ContextEventType} into the {@link Element}.
291      * 
292      * @param eventType the {@link ContextEventType}.
293      * @throws NullPointerException if specified {@link ContextEventType} is
294      *         <code>null</code>.
295      */
296     @Override
297     public void marshal(final ContextEventType eventType) {
298         if (null == eventType) {
299             throw new NullPointerException("Event type cannot be null.");
300         }
301 
302         this.name.marshal(eventType.getName());
303         @SuppressWarnings("hiding")
304         final long ttl = eventType.getTTL();
305         if (ttl == TTL_DEFAULT) {
306             this.ttl.remove();
307         } else {
308             this.ttl.marshal(eventType.getTTL());
309         }
310         @SuppressWarnings("hiding")
311         final int priority = eventType.getPriority();
312         if (priority == PRIORITY_DEFAULT) {
313             this.priority.remove();
314         } else {
315             this.priority.marshal(eventType.getPriority());
316         }
317         @SuppressWarnings("hiding")
318         final Attribute[] attributes = eventType.getAttributes();
319         if (attributes.length > 0) {
320             this.attributes.marshal(Arrays.asList(attributes));
321         } else {
322             this.attributes.remove();
323         }
324         @SuppressWarnings("hiding")
325         final Authorization[] authorizations = eventType.getAuthorizations();
326         if (authorizations.length > 0) {
327             this.authorizations.marshal(Arrays.asList(authorizations));
328         } else {
329             this.authorizations.remove();
330         }
331         @SuppressWarnings("hiding")
332         final DefaultAction[] actions = eventType.getActions();
333         if (actions.length > 0) {
334             this.actions.marshal(Arrays.asList(actions));
335         } else {
336             this.actions.remove();
337         }
338     }
339 
340     /**
341      * Removes any marshaled {@link ContextEventType} from the {@link Element}.
342      */
343     @Override
344     public void remove() {
345         this.name.remove();
346         this.ttl.remove();
347         this.priority.remove();
348         this.attributes.remove();
349         this.authorizations.remove();
350         this.actions.remove();
351     }
352 
353     /**
354      * Creates instance of {@link ListUnmarshaller.Builder} for
355      * {@link ContextEventType}s. The returned {@link ListUnmarshaller.Builder}
356      * does not have the parent {@link Element} set and caller should set it
357      * before building the {@link ListUnmarshaller} for {@link ContextEventType}
358      * s. The name for child {@link Element}s is set to
359      * {@link #EVENT_TYPE_ELEMENT}.
360      * 
361      * @return the {@link ListUnmarshaller.Builder} for {@link ContextEventType}
362      *         s.
363      */
364     public static ListUnmarshaller.Builder<ContextEventType> getListBuilder() {
365         return LIST_BUILDER;
366     }
367 
368     /**
369      * Builder of {@link ContextEventTypeUnmarshaller}.
370      * 
371      * @author sanjin
372      */
373     public static class Builder extends
374             BaseUnmarshallerBuilder<ContextEventType> {
375 
376         /**
377          * Create uninitialized instance of
378          * {@link ContextEventTypeUnmarshaller.Builder}.
379          */
380         public Builder() {
381             super();
382         }
383 
384         /**
385          * Clone-constructor.
386          * 
387          * @param builder the cloned
388          *        {@link ContextEventTypeUnmarshaller.Builder}.
389          */
390         private Builder(final Builder builder) {
391             super(builder);
392         }
393 
394         /**
395          * Create instance of {@link ContextEventTypeUnmarshaller}.
396          * 
397          * @return a {@link ContextEventTypeUnmarshaller}.
398          */
399         @Override
400         public ContextEventTypeUnmarshaller build() {
401             return new ContextEventTypeUnmarshaller(getElement());
402         }
403 
404         @Override
405         protected Builder copy() {
406             return new Builder(this);
407         }
408     }
409 }