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