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