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