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 org.apache.log4j.Logger;
21  import org.w3c.dom.Document;
22  import org.w3c.dom.Element;
23  import at.ac.tuwien.infosys.sm4all.copal.api.ContextException;
24  import at.ac.tuwien.infosys.sm4all.copal.api.processor.ProcessorAction;
25  import at.ac.tuwien.infosys.sm4all.copal.api.xml.Constants;
26  import at.ac.tuwien.infosys.sm4all.copal.api.xml.ElementUtil;
27  import at.ac.tuwien.infosys.sm4all.copal.api.xml.Marshaller;
28  import at.ac.tuwien.infosys.sm4all.copal.api.xml.MissingFieldException;
29  import at.ac.tuwien.infosys.sm4all.copal.api.xml.Unmarshaller;
30  
31  /**
32   * Command that marshalls and unmarshalls a {@link ProcessorAction} into/from an
33   * {@link Element}.
34   * 
35   * @author sanjin
36   */
37  public class XMLProcessorAction extends ElementUtil implements
38          Unmarshaller<ProcessorAction>, Marshaller<ProcessorAction> {
39  
40      private static final String INPUT_ELEMENT_NAME = "Input";
41      private static final String OUTPUT_ELEMENT_NAME = "Output";
42      private static final String[] EMPTY_STRING_ARRAY = new String[0];
43  
44      private static final Logger LOGGER = Logger.getLogger(XMLProcessorAction.class);
45  
46      private final Element element;
47  
48      /**
49       * Creates instance of {@link ProcessorAction} marshaller and unmarshaller
50       * which uses specified {@link Element} to marshal and/or unmarshal a
51       * {@link ProcessorAction}.
52       * 
53       * @param element the {@link Element} used for marshalling and
54       *        unmarshalling.
55       * @throws NullPointerException if specified {@link Element} is
56       *         <code>null</code>.
57       */
58      public XMLProcessorAction(final Element element) {
59          super(element);
60  
61          this.element = element;
62      }
63  
64      /**
65       * Returns a {@link ProcessorAction} with its name equal to the
66       * <code>name</code> attribute of specified {@link Element}, input equal to
67       * the <code>event</code> attribute of the <code>Input</code> child
68       * {@link Element}, and, if present, output equal to the <code>name</code>
69       * attributes of the <code>Output</code>'s <code>Event</code>
70       * {@link Element}s.
71       * 
72       * @return the unmarshalled {@link ProcessorAction}.
73       * @throws ContextException if unmarshalling fails.
74       */
75      @Override
76      public ProcessorAction unmarshal() throws ContextException {
77          final String name = new ProcessorActionName(this.element).unmarshal();
78          final String input = new ProcessorActionInput(getChildElement(
79                  Constants.COPAL_NAMESPACE_URI, INPUT_ELEMENT_NAME)).unmarshal();
80  
81          Element outputElement = null;
82          try {
83              outputElement = getChildElement(Constants.COPAL_NAMESPACE_URI,
84                      OUTPUT_ELEMENT_NAME);
85          } catch (final MissingFieldException ex) {
86              if (LOGGER.isDebugEnabled())
87                  LOGGER.debug(
88                          "Processor action output element is missing! Ignoring.",
89                          ex);
90          }
91          final String[] output;
92          if (outputElement != null)
93              output = new ProcessorActionOutput(outputElement).unmarshal();
94          else
95              output = EMPTY_STRING_ARRAY;
96  
97          return new ProcessorAction(name, input, output);
98      }
99  
100     /**
101      * Sets the <code>name</code> attribute of specified {@link Element} to name
102      * of specified {@link ProcessorAction}, the <code>event</code> attribute of
103      * the <code>Input</code> child {@link Element} to input of specified
104      * {@link ProcessorAction}, and <code>name</code> attributes of
105      * <code>Output</code>'s <code>Event</code> {@link Element}s to output of
106      * specified {@link ProcessorAction}. If specified {@link ProcessorAction}
107      * does not have an output the <code>Output</code> child {@link Element} is
108      * removed from specified {@link Element}.
109      * 
110      * @param action the {@link ProcessorAction}.
111      * @throws NullPointerException if specified {@link ProcessorAction} is
112      *         <code>null</code>.
113      */
114     @Override
115     public void marshal(final ProcessorAction action) {
116         if (action == null)
117             throw new NullPointerException("Action cannot be null.");
118 
119         new ProcessorActionName(this.element).marshal(action);
120 
121         final Document document = this.element.getOwnerDocument();
122 
123         Element output = null;
124         if (action.hasOutput()) {
125             try {
126                 output = getChildElement(Constants.COPAL_NAMESPACE_URI,
127                         OUTPUT_ELEMENT_NAME);
128             } catch (final MissingFieldException ex) {
129                 if (LOGGER.isDebugEnabled())
130                     LOGGER.debug(
131                             "Processor action output element is missing! Appending new one.",
132                             ex);
133                 output = document.createElementNS(
134                         Constants.COPAL_NAMESPACE_URI, Constants.COPAL_PREFIX
135                                 + ":" + OUTPUT_ELEMENT_NAME);
136                 this.element.appendChild(output);
137             }
138             new ProcessorActionOutput(output).marshal(action.getOutput());
139         } else
140             try {
141                 this.element.removeChild(getChildElement(
142                         Constants.COPAL_NAMESPACE_URI, OUTPUT_ELEMENT_NAME));
143             } catch (final MissingFieldException ex) {
144                 if (LOGGER.isDebugEnabled())
145                     LOGGER.debug(
146                             "Processor action output element is missing! Ignoring.",
147                             ex);
148             }
149 
150         Element input = null;
151         try {
152             input = getChildElement(Constants.COPAL_NAMESPACE_URI,
153                     INPUT_ELEMENT_NAME);
154         } catch (final MissingFieldException ex) {
155             if (LOGGER.isDebugEnabled())
156                 LOGGER.debug(
157                         "Processor action input element is missing! Appending new one.",
158                         ex);
159             input = document.createElementNS(Constants.COPAL_NAMESPACE_URI,
160                     Constants.COPAL_PREFIX + ":" + INPUT_ELEMENT_NAME);
161             if (output == null)
162                 this.element.appendChild(input);
163             else
164                 this.element.insertBefore(input, output);
165         }
166         new ProcessorActionInput(input).marshal(action);
167     }
168 }