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.Iterator;
21  import javax.xml.XMLConstants;
22  import javax.xml.namespace.NamespaceContext;
23  import javax.xml.xpath.XPath;
24  import javax.xml.xpath.XPathExpression;
25  import javax.xml.xpath.XPathExpressionException;
26  import javax.xml.xpath.XPathFactory;
27  import org.w3c.dom.Document;
28  import at.ac.tuwien.infosys.sm4all.copal.api.util.Constants;
29  import at.ac.tuwien.infosys.sm4all.copal.api.util.FailedUnmarshallingException;
30  
31  /**
32   * The abstract class for all COPAL elements.
33   * 
34   * @param <T> the type of element's value.
35   * @author sanjin
36   */
37  public abstract class XMLElement<T> {
38  
39      private static final XPathFactory XPATH_FACTORY = XPathFactory.newInstance();
40      private static final COPALNamespaceContext NAMESPACE_CONTEXT = new COPALNamespaceContext();
41  
42      private final Class<?> type;
43      private final String qualifiedName;
44      private final XPathExpression xPathExpression;
45  
46      /**
47       * @param type the XML type of this COPAL element returned by the XPath.
48       */
49      protected XMLElement(final Class<?> type) {
50          super();
51  
52          this.type = type;
53          this.qualifiedName = Constants.COPAL_PREFIX + ":"
54                  + getClass().getSimpleName();
55          this.xPathExpression = createXPathExpression(getXPath());
56      }
57  
58      /**
59       * @return the XPath which can be used to retrieve the value of this COPAL
60       *         element from a {@link Document}.
61       */
62      public abstract String getXPath();
63  
64      /**
65       * Retrieve the value of this element from specified {@link Document}.
66       * 
67       * @param document the {@link Document}.
68       * @return the value of this property.
69       * @throws FailedUnmarshallingException if retrieving was not successful.
70       */
71      public abstract T retrieve(Document document)
72              throws FailedUnmarshallingException;
73  
74      /**
75       * @return the qualified name of this XML element.
76       */
77      public String getQualifiedName() {
78          return this.qualifiedName;
79      }
80  
81      /**
82       * @return the XML type of this COPAL element returned by the XPath.
83       */
84      public Class<?> getXMLType() {
85          return this.type;
86      }
87  
88      /**
89       * @return the XPath expression created from the {@link #getXPath()}.
90       */
91      protected XPathExpression getExpression() {
92          return this.xPathExpression;
93      }
94  
95      private static XPathExpression createXPathExpression(final String expression) {
96          final XPath xPath = XPATH_FACTORY.newXPath();
97          XPathExpression result = null;
98  
99          xPath.setNamespaceContext(NAMESPACE_CONTEXT);
100         try {
101             result = xPath.compile(expression);
102         } catch (final XPathExpressionException ex) {
103             throw new IllegalArgumentException("XPath is invalid.", ex);
104         }
105 
106         return result;
107     }
108 
109     private static class COPALNamespaceContext implements NamespaceContext {
110 
111         public COPALNamespaceContext() {
112             super();
113         }
114 
115         @Override
116         public Iterator<?> getPrefixes(final String namespaceURI) {
117             throw new UnsupportedOperationException();
118         }
119 
120         @Override
121         public String getPrefix(final String namespaceURI) {
122             throw new UnsupportedOperationException();
123         }
124 
125         @Override
126         public String getNamespaceURI(final String prefix) {
127             if (Constants.COPAL_PREFIX.equals(prefix))
128                 return Constants.COPAL_NAMESPACE;
129 
130             return XMLConstants.NULL_NS_URI;
131         }
132     }
133 }