1 /*
2 * Copyright 2012 Olivier Godineau
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * the License at http://www.apache.org/licenses/LICENSE-2.0
7 *
8 * Unless required by applicable law or agreed to in writing, software
9 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11 * License for the specific language governing permissions and limitations under
12 * the License.
13 */
14 package olg.csv.bean.loader.parser;
15
16 import javax.xml.xpath.XPathConstants;
17 import javax.xml.xpath.XPathExpressionException;
18
19 import olg.csv.base.UsageInvalideException;
20 import olg.csv.bean.loader.LoadException;
21 import olg.csv.bean.loader.Util;
22 import olg.csv.bean.loader.parser.impl.CustomParserLoader;
23 import olg.csv.bean.loader.parser.impl.DateParserLoader;
24 import olg.csv.bean.parser.AbstractParser;
25
26 import org.w3c.dom.Element;
27 import org.w3c.dom.Node;
28
29 /**
30 * Class dedicated to load a parser from an XML element conformed to XML schema
31 * ParserType specification. Each concret class shall have the responsibility to
32 * load a concrete AbstractLoader class.
33 *
34 * <p>
35 * Class based on Chain of responsability pattern used to chain concret Filter
36 * Loaders.
37 * </p>
38 *
39 * @author Olivier Godineau
40 * @see AbstractParser
41 *
42 */
43 public abstract class AbstractParserLoader {
44
45 /**
46 * Singleton responsible of parsers loading.
47 */
48 private static AbstractParserLoader instance = new DateParserLoader(new CustomParserLoader(null));
49
50 /**
51 * Returns Singleton responsible of parsers loading. This is this instance
52 * you have to be used to load every type of parser from XML element
53 * conformed to XML Schema ParserType specification.
54 *
55 * @return the parser loader instance.
56 */
57 public static AbstractParserLoader getInstance() {
58 return instance;
59 }
60
61 /**
62 * This Xpath expression allows to identify xml node which describe the
63 * corresponding concret parser under parser Type node.
64 */
65 protected String xPathExpression;
66
67 /**
68 * ParserLoader successor as describe in Chain of responsability pattern.
69 * Each parserLoader has the responsability of only one parser type.
70 */
71 protected AbstractParserLoader successor;
72
73 /**
74 *
75 * Returns a concret parser identified from the given XML Element.
76 *
77 * @param clazz
78 * the class that the parser should return
79 *
80 * @param element
81 * XML node corresponding to correspondant to XML ParserType as
82 * described in our XML schema
83 * @param <T>
84 * the type the parser treats.
85 * @return a concret parser or <code>null</code> if the given element
86 * doesn't match concret parser this loader has responsability and
87 * doesn't match any successor
88 * @throws XPathExpressionException
89 * on invalid XPathExpression
90 * @throws LoadException
91 * on Error occurs during loading
92 */
93 @SuppressWarnings("unchecked")
94 public final <T> AbstractParser<T> getParser(Class<T> clazz, Element element) throws XPathExpressionException,
95 LoadException {
96 AbstractParser<T> retour = null;
97 if (element == null) {
98 try {
99 retour = AbstractParser.identifyDefaultParser(clazz);
100 } catch (UsageInvalideException e) {
101 throw new LoadException(e);
102 }
103
104 } else {
105 Node node = (Node) Util.evaluerDOM(element, xPathExpression, XPathConstants.NODE);
106 if (node != null) { // NOPMD by olivier on 01/02/12 00:50
107 retour = getConcreteParser(clazz, (Element) node);
108 } else {
109 if (successor != null) {
110 retour = successor.getParser(clazz, element);
111 }
112 }
113 }
114 return retour;
115 }
116
117 /**
118 *
119 * @param xPathExpression
120 * the XPath expression that allows to identify the concret
121 * parser under the XML FilterType node
122 * @param successor
123 * following concret loader in the chain of responsability
124 */
125 protected AbstractParserLoader(String xPathExpression, AbstractParserLoader successor) {
126 super();
127 this.successor = successor;
128 this.xPathExpression = xPathExpression;
129 }
130
131 /**
132 * Returns a concret parser this concret loader has the responsablity to
133 * create.
134 *
135 * @param clazz
136 * the class that the parser should return
137 * @param node
138 * XML Element corresponding to the XPath expression from which
139 * load corresponding parser
140 * @param <T>
141 * the type the parser treats.
142 * @return the concret parser. <code>null</code> if the given node doesn't
143 * match the type this loader should return
144 *
145 * @throws XPathExpressionException
146 * on invalid XPathExpression
147 * @throws LoadException
148 * if Error occurs during loading
149 * @see #xPathExpression
150 */
151 protected abstract <T> AbstractParser<T> getConcreteParser(Class<T> clazz, Element node)
152 throws XPathExpressionException, LoadException;
153
154 }