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