View Javadoc
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 }