View Javadoc

1   /*
2    * $HeadURL: $
3    * $Date: $
4    * $Revision: $
5    * $Author: $
6    * 
7    * Copyright (c) 2006 MindTree Consulting Ltd. 
8    * 
9    * This file is part of Insight.
10   * 
11   * Insight is free software: you can redistribute it and/or modify it under the 
12   * terms of the GNU General Public License as published by the Free Software 
13   * Foundation, either version 3 of the License, or (at your option) any later 
14   * version.
15   * 
16   * Insight is distributed in the hope that it will be useful, but 
17   * WITHOUT ANY WARRANTY; without even the implied warranty of 
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General 
19   * Public License for more details.
20   * 
21   * You should have received a copy of the GNU General Public License along with 
22   * Insight.  If not, see <http://www.gnu.org/licenses/>.
23   */
24  package com.mindtree.techworks.insight.reporting.verifiers;
25  
26  import org.w3c.dom.Document;
27  import org.w3c.dom.Element;
28  import org.w3c.dom.NodeList;
29  
30  import com.mindtree.techworks.insight.reporting.InitializationException;
31  import com.mindtree.techworks.insight.reporting.SerializationXmlUtils;
32  import com.mindtree.techworks.insight.reporting.jobs.Job;
33  import com.mindtree.techworks.insight.reporting.jobs.JobInitializationException;
34  import com.mindtree.techworks.insight.reporting.jobs.JobPersistanceHandler;
35  
36  /**
37   * This is the default implementation of the <code>VerifierDeserializer</code>
38   * interface in the <code>Verifier</code> framework.
39   * <p>
40   * <code>Verifiers</code> may use the services of this class to deserialize them
41   * and to do that, they must:
42   * <ul>
43   * 	<li>Implement the <code>DefaultImplDeserializable</code> interface </li>
44   * 	<li>Return an instance of this class on the <code>#getDeserializer()</code>
45   * 		method.</li>
46   * 	<li>Their serialized form must exactly conform to the format described in 
47   * 		the documentation of the <code>VerifierDeserializer</code> class.</li>
48   * </ul>
49   * </p>
50   * <p>
51   * The <code>Verifier</code> framework also uses this class for deserialization
52   * of any <code>Verifier</code>. The <code>#deserialize(String)</code> method
53   * looks at the serialized form of the <code>Verifier</code> and tries to get
54   * the instance of the Verifier and then calls the appropriate 
55   * <code>VerifierDeserializer</code> for the <code>Verifier</code>.
56   * </p>
57   * 
58   * @see com.mindtree.techworks.insight.reporting.verifiers.VerifierDeserializer
59   * @see com.mindtree.techworks.insight.reporting.verifiers.DefaultImplDeserializable
60   * 
61   * @author <a href="mailto:bindul_bhowmik@mindtree.com">Bindul Bhowmik</a>
62   * @version $Revision: 27 $ $Date: 2007-12-16 04:58:03 -0700 (Sun, 16 Dec 2007) $
63   * @since Insight 1.5
64   */
65  public class VerifierDeserializerImpl implements VerifierDeserializer {
66  
67  	/**
68  	 * Inspects the serialized <code>Verifier</code> and calls the appropriate
69  	 * <code>VerifierDeserializer</code>. If the <code>Verifier</code>
70  	 * class cannot be found, or the serialized data is ill formatted, then the
71  	 * deserialization fails and the method throws a
72  	 * <code>VerifierInitializationException</code>.
73  	 * 
74  	 * @param serializedVerifier
75  	 *            The serialized form of the Verifier.
76  	 * 
77  	 * @return The deserialized verifier.
78  	 * 
79  	 * @throws VerifierInitializationException
80  	 *             If the verifier cannot be deserialized.
81  	 */
82  	public static Verifier deserialize (String serializedVerifier)
83  			throws VerifierInitializationException {
84  
85  		Document document = null;
86  		try {
87  			document = SerializationXmlUtils.createDocument (serializedVerifier);
88  		} catch (InitializationException e) {
89  			throw new VerifierInitializationException (
90  					"Error creating document", e);
91  		}
92  
93  		// Try to initialize the Verifier and get its deserializer, and
94  		// delegate the call to the deserializer
95  		String className = null;
96  		try {
97  			className = SerializationXmlUtils
98  					.getSerializedObjectClassName (document);
99  		} catch (InitializationException e) {
100 			throw new VerifierInitializationException (
101 					"Could not get class for Verifier.", e);
102 		}
103 
104 		try {
105 			Verifier newVerifier = (Verifier) Class.forName (className)
106 					.newInstance ();
107 			VerifierDeserializer deserializer = newVerifier.getDeserializer ();
108 
109 			// Finally... deserialize the verifier!
110 			return deserializer.deserializeVerifier (serializedVerifier);
111 		} catch (InstantiationException e) {
112 			throw new VerifierInitializationException (
113 					"Could not get verifier class or instance.");
114 		} catch (IllegalAccessException e) {
115 			throw new VerifierInitializationException (
116 					"Could not get verifier class or instance.");
117 		} catch (ClassNotFoundException e) {
118 			throw new VerifierInitializationException (
119 					"Could not get verifier class or instance.");
120 		}
121 
122 	}
123 
124 	/**
125 	 * Deserializes a verifier serialized in the format specified in 
126 	 * {@link VerifierDeserializer VerifierDeserializer}. The 
127 	 * <code>Verifier</code> needs to implement the 
128 	 * <code>DefaultImplDeserializable</code> interface.
129 	 * 
130 	 * @see com.mindtree.techworks.insight.reporting.verifiers.VerifierDeserializer#deserializeVerifier(String)
131 	 */
132 	public Verifier deserializeVerifier (String serializedVerifier)
133 			throws VerifierInitializationException {
134 
135 		// Get the verifier class
136 		Document document = null;
137 		try {
138 			document = SerializationXmlUtils.createDocument (serializedVerifier);
139 		} catch (InitializationException e) {
140 			throw new VerifierInitializationException (
141 					"Could not create XML document", e);
142 		}
143 		
144 		// Get the class name for the Verifier
145 		String className = null;
146 		try {
147 			className = SerializationXmlUtils
148 					.getSerializedObjectClassName (document);
149 		} catch (InitializationException e) {
150 			throw new VerifierInitializationException (
151 					"Could not get class for Verifier.", e);
152 		}
153 
154 		Verifier newVerifier = null;
155 
156 		try {
157 			// Get the instance.
158 			newVerifier = (Verifier) Class.forName (className).newInstance ();
159 
160 		} catch (InstantiationException e) {
161 			throw new VerifierInitializationException (
162 					"Could not get verifier class or instance.");
163 		} catch (IllegalAccessException e) {
164 			throw new VerifierInitializationException (
165 					"Could not get verifier class or instance.");
166 		} catch (ClassNotFoundException e) {
167 			throw new VerifierInitializationException (
168 					"Could not get verifier class or instance.");
169 		}
170 
171 		// For this class to deserialize the verifier it needs to implement
172 		// DefaultImplDeserializable
173 		if ( !(newVerifier instanceof DefaultImplDeserializable)) {
174 			throw new VerifierInitializationException (
175 					"The verifier cannot be deserialized by this class - " +
176 					"needs to implement DefaultImplDeserializable.");
177 		}
178 
179 		DefaultImplDeserializable deserializable = (DefaultImplDeserializable) newVerifier;
180 
181 		// Get the fields element
182 		Element documentElement = document.getDocumentElement (); // <verifier/>
183 		NodeList fieldsList = documentElement.getElementsByTagName ("fields");
184 
185 		// We will take just the first one!
186 		if (fieldsList.getLength () > 0) {
187 			Element fieldsRoot = (Element) fieldsList.item (0);
188 			NodeList fields = fieldsRoot.getElementsByTagName ("field");
189 			for (int i = 0; i < fields.getLength (); i++ ) {
190 				processField ((Element) fields.item (i), deserializable);
191 			}
192 		}
193 		
194 		// Get the jobs
195 		NodeList jobsList = documentElement.getElementsByTagName("jobs");
196 		// We will take just the first one!
197 		if (jobsList.getLength () > 0) {
198 			Element jobsRoot = (Element) jobsList.item (0);
199 			NodeList jobs = jobsRoot.getElementsByTagName (
200 			                    JobPersistanceHandler.SERIALIZED_JOB_ROOT_TAG);
201 			for (int i = 0; i < jobs.getLength (); i++ ) {
202 				processJob ((Element) jobs.item (i), newVerifier);
203 			}
204 		}
205 
206 		return newVerifier;
207 	}
208 	
209 	// -------------------------------------------------------------------------
210 	// Private Utility methods
211 	// -------------------------------------------------------------------------
212 
213 	/**
214 	 * Process the section of the serialized <code>Verifier</code>
215 	 * corresponding to a single field in the <code>Verifier</code>. It uses
216 	 * the
217 	 * {@link DefaultImplDeserializable#deserializeField(String, String) DefaultImplDeserializable#deserializeField(String, String)}
218 	 * method to populate the fields. If a field is an array, then the method is
219 	 * called multiple times with the same <code>fieldName</code> but the
220 	 * different values of the <code>fieldValue</code>.
221 	 * 
222 	 * @param field
223 	 *            The <code>Element</code> representing the field to
224 	 *            deserialize.
225 	 * @param deserializable
226 	 *            The <code>Verifier</code> which is being deserialized.
227 	 * @throws VerifierInitializationException
228 	 *             If there is an error deserializing the field.
229 	 */
230 	private void processField (Element field,
231 			DefaultImplDeserializable deserializable)
232 			throws VerifierInitializationException {
233 
234 		// Get the name of the field - should be only one, taking the first one.
235 		Element nameElement = (Element) field.getElementsByTagName ("name")
236 				.item (0);
237 
238 		if (null == nameElement) {
239 			throw new VerifierInitializationException (
240 					"Each field needs a name!");
241 		}
242 
243 		String name = SerializationXmlUtils.getTextValue (nameElement);
244 
245 		// Get the values... may be more than one!
246 		NodeList values = field.getElementsByTagName ("value");
247 		for (int i = 0; i < values.getLength (); i++ ) {
248 			String value = SerializationXmlUtils.getTextValue ((Element) values
249 					.item (i));
250 
251 			// Set the value
252 			deserializable.deserializeField (name, value);
253 		}
254 	}
255 	
256 	/**
257 	 * Process the section of the serialized <code>Verifier</code>
258 	 * corresponding to a single <code>Job</code> in the <code>Verifier</code>.
259 	 * The actual deserialization of the <code>Job</code> is delegated to the
260 	 * deserialization mechanism of the <code>Job</code>. The
261 	 * {@link Verifier#registerJob(Job) Verifier#registerJob(Job)} method is
262 	 * used to attach the deserialized <code>Job</code>s to the
263 	 * <code>Verifier</code> being deserialized.
264 	 * 
265 	 * @param serializedJob
266 	 *            The <code>Element</code> representing the serialized
267 	 *            <code>Job</code>.
268 	 * @param verifier
269 	 *            The <code>Verifier</code> being deserialized.
270 	 * @throws VerifierInitializationException
271 	 *             If there is an exception deserializing the <code>Job</code>.
272 	 */
273 	private void processJob (Element serializedJob, Verifier verifier)
274 			throws VerifierInitializationException {
275 
276 		// Get the string version of the job
277 		String jobString = null;
278 		try {
279 			jobString = SerializationXmlUtils.serializeXmlElement(serializedJob);
280 		} catch (InitializationException e) {
281 			throw new VerifierInitializationException (
282 					"Could not serialize Job DOM Element for processing.", e);
283 		}
284 		Job deserializedJob = null;
285 		
286 		// Delegate the processing to a Job deserializer!
287 		try {
288 			deserializedJob = JobPersistanceHandler.deserializeJob(jobString);
289 		} catch (JobInitializationException e) {
290 			// Just throw it
291 			throw new VerifierInitializationException (
292 					"Could not deserialize job", e);
293 		}
294 		
295 		// Add the Job to the verifier
296 		verifier.registerJob(deserializedJob);
297 		
298 	}
299 }