1 /*
2 * $HeadURL: $
3 * $Date: $
4 * $Revision: $
5 * $Author: $
6 *
7 * Copyright (c) 2005 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
25 package com.mindtree.techworks.insight.preferences.xmlpersistence;
26
27 import java.util.ArrayList;
28 import java.util.Stack;
29
30 import org.xml.sax.Attributes;
31 import org.xml.sax.SAXException;
32 import org.xml.sax.helpers.DefaultHandler;
33
34 import com.mindtree.techworks.insight.preferences.model.ListPreferenceAttribute;
35 import com.mindtree.techworks.insight.preferences.model.Preference;
36 import com.mindtree.techworks.insight.preferences.model.PreferenceAttribute;
37 import com.mindtree.techworks.insight.preferences.model.PreferenceAttributeType;
38 import com.mindtree.techworks.insight.preferences.util.Crypt;
39
40
41 /**
42 * Reads data from the XML Preference store and populates the preference objects
43 * into the {@link XMLPreferenceDataCache Data Cache}.
44 *
45 * This class is a specialization of {@link org.xml.sax.helpers.DefaultHandler
46 * Default Handler}.
47 *
48 * This class reads XML data for the following Schema
49 *
50 * <pre>
51 * <?xml version="1.0" encoding="UTF-8"?>
52 * <!-- edited with XMLSPY v5 rel. 4 U (http://www.xmlspy.com) by Bindul Bhowmik (GALILEO INTERNATIONAL) -->
53 * <xs:schema targetNamespace="http://mindtree.com/logging/insight/Preferences" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:preferences="http://mindtree.com/logging/insight/Preferences" elementFormDefault="qualified" attributeFormDefault="unqualified" version="1.0">
54 * <!-- Root element -->
55 * <xs:element name="InsightPreferences">
56 * <xs:annotation>
57 * <xs:documentation>Stores all the preferences for Insight. All preferences are to be configured in an XML file conforming to this XSD, this Schema will also define the storage of the preference values in a user's system.</xs:documentation>
58 * </xs:annotation>
59 * <xs:complexType>
60 * <xs:sequence>
61 * <xs:element name="preference" type="preferences:Preference" minOccurs="0" maxOccurs="unbounded">
62 * <xs:annotation>
63 * <xs:documentation>See documentation with Preference</xs:documentation>
64 * </xs:annotation>
65 * </xs:element>
66 * </xs:sequence>
67 * </xs:complexType>
68 * </xs:element>
69 * <!-- ComplexType representing a particular Preference -->
70 * <xs:complexType name="Preference">
71 * <xs:annotation>
72 * <xs:documentation>Correspons to a particular Preference, which in turn will have a list of preference attributes</xs:documentation>
73 * </xs:annotation>
74 * <xs:sequence>
75 * <xs:element name="preferenceAttribute" type="preferences:PreferenceAttribute" maxOccurs="unbounded">
76 * <xs:annotation>
77 * <xs:documentation>See documentation with PreferenceAttribute</xs:documentation>
78 * </xs:annotation>
79 * </xs:element>
80 * </xs:sequence>
81 * <xs:attribute name="id" use="required">
82 * <xs:annotation>
83 * <xs:documentation>The ID of the Preference Attribute. Each attribute will be uniquely identified by a combination of the Preference ID and the Preference Attribute ID</xs:documentation>
84 * </xs:annotation>
85 * <xs:simpleType>
86 * <xs:restriction base="xs:string">
87 * <xs:whiteSpace value="collapse"/>
88 * <xs:minLength value="3"/>
89 * </xs:restriction>
90 * </xs:simpleType>
91 * </xs:attribute>
92 * <xs:attribute name="name" use="required">
93 * <xs:annotation>
94 * <xs:documentation>The Display name of the Preference Attribute</xs:documentation>
95 * </xs:annotation>
96 * <xs:simpleType>
97 * <xs:restriction base="xs:string">
98 * <xs:minLength value="5"/>
99 * <xs:whiteSpace value="collapse"/>
100 * </xs:restriction>
101 * </xs:simpleType>
102 * </xs:attribute>
103 * </xs:complexType>
104 * <!-- Complex type representing a PreferenceAttribute -->
105 * <xs:complexType name="PreferenceAttribute">
106 * <xs:annotation>
107 * <xs:documentation>A Preference Attribute is a particular value within a Preference. It is uniquely identified by the id of this element.</xs:documentation>
108 * </xs:annotation>
109 * <xs:sequence>
110 * <xs:element name="defaultValue" type="xs:string" minOccurs="0">
111 * <xs:annotation>
112 * <xs:documentation>The value to be supplied when no value is set.</xs:documentation>
113 * </xs:annotation>
114 * </xs:element>
115 * <xs:element name="value" type="xs:string" minOccurs="0">
116 * <xs:annotation>
117 * <xs:documentation>The value of the attribute. The value if set for transient attributes will be ignored, and will not be stored back.</xs:documentation>
118 * </xs:annotation>
119 * </xs:element>
120 * <xs:element name="type" default="TEXT">
121 * <xs:annotation>
122 * <xs:documentation>The type of the attribute, as of version 1.0 only two types are supported, TEXT and LIST</xs:documentation>
123 * </xs:annotation>
124 * <xs:simpleType>
125 * <xs:restriction base="xs:string">
126 * <xs:enumeration value="TEXT"/>
127 * <xs:enumeration value="LIST"/>
128 * </xs:restriction>
129 * </xs:simpleType>
130 * </xs:element>
131 * <xs:element name="persistant" type="xs:boolean" default="true">
132 * <xs:annotation>
133 * <xs:documentation>Indicates whether a particular preference attribute value will persist across instances of the application</xs:documentation>
134 * </xs:annotation>
135 * </xs:element>
136 * <xs:element name="userModifiable" type="xs:string" default="true">
137 * <xs:annotation>
138 * <xs:documentation>Identifies whether the user can modify this attribute using the GUI.</xs:documentation>
139 * </xs:annotation>
140 * </xs:element>
141 * </xs:sequence>
142 * <xs:attribute name="id" use="required">
143 * <xs:annotation>
144 * <xs:documentation>The ID of the Preference Attribute. Each attribute will be uniquely identified by a combination of the Preference ID and the Preference Attribute ID</xs:documentation>
145 * </xs:annotation>
146 * <xs:simpleType>
147 * <xs:restriction base="xs:string">
148 * <xs:whiteSpace value="collapse"/>
149 * <xs:minLength value="3"/>
150 * </xs:restriction>
151 * </xs:simpleType>
152 * </xs:attribute>
153 * <xs:attribute name="name" use="required">
154 * <xs:annotation>
155 * <xs:documentation>The Display name of the Preference Attribute</xs:documentation>
156 * </xs:annotation>
157 * <xs:simpleType>
158 * <xs:restriction base="xs:string">
159 * <xs:minLength value="5"/>
160 * <xs:whiteSpace value="collapse"/>
161 * </xs:restriction>
162 * </xs:simpleType>
163 * </xs:attribute>
164 * </xs:complexType>
165 * <!-- A specialization of the Preference Attribute to have a list of values -->
166 * <xs:complexType name="ListPreferenceAttribute">
167 * <xs:annotation>
168 * <xs:documentation>A specialized form of attribute where a list of possible values or options are provided.</xs:documentation>
169 * </xs:annotation>
170 * <xs:complexContent>
171 * <xs:extension base="preferences:PreferenceAttribute">
172 * <xs:sequence>
173 * <xs:element name="options">
174 * <xs:annotation>
175 * <xs:documentation>The various optoins from which the value of the preference attribute this list is part of can be derived</xs:documentation>
176 * </xs:annotation>
177 * <xs:complexType>
178 * <xs:sequence>
179 * <xs:element name="option" type="xs:string" maxOccurs="unbounded">
180 * <xs:annotation>
181 * <xs:documentation>A particular option. See documentation for options.</xs:documentation>
182 * </xs:annotation>
183 * </xs:element>
184 * </xs:sequence>
185 * </xs:complexType>
186 * </xs:element>
187 * </xs:sequence>
188 * </xs:extension>
189 * </xs:complexContent>
190 * </xs:complexType>
191 * </xs:schema>
192 *
193 *
194 *
195 * </pre>
196 * @author Bindul Bhowmik
197 * @version $Revision: 161 $ $Date: 2008-04-04 22:48:39 -0600 (Fri, 04 Apr 2008) $
198 */
199 public class XMLPreferenceDataReader extends DefaultHandler implements PreferenceXMLNameConstants {
200
201 /**
202 * The current Preference being read
203 */
204 private Preference currentPreference;
205
206 /**
207 * Stack for nested Preferences.
208 */
209 private Stack preferenceStack;
210
211 /**
212 * The id of the current PreferenceAttribute being read
213 */
214 private String currentPreferenceAttributeId;
215
216 /**
217 * The name of the current PreferenceAttribute being read
218 */
219 private String currentPreferenceAttributeName;
220
221 /**
222 * The xsi:type of the current PreferenceAttribute being read
223 */
224 private String currentPreferenceAttributeXSIType;
225
226 /**
227 * The defaultValue of the current PreferenceAttribute being read
228 */
229 private String currentPreferenceAttributeDefaultValue = "";
230
231 /**
232 * The value of the current PreferenceAttribute being read
233 */
234 private String currentPreferenceAttributeValue = "";
235
236 /**
237 * Tells whether the value of the current PreferenceAttribute is encrypted.
238 */
239 private boolean isPreferenceAttributeValueEncrypted = false;
240
241 /**
242 * The isPersistant of the current PreferenceAttribute being read
243 */
244 private boolean isCurrentPreferenceAttributePersistant = true;
245
246 /**
247 * The isUserModifiable of the current PreferenceAttribute being read
248 */
249 private boolean isCurrentPreferenceAttributeUserModifiable = true;
250
251 /**
252 * Read CDATA for the which element?
253 */
254 private String currentElementToReadDataFor;
255
256 /**
257 * The type of the current PreferenceAttribute being read
258 */
259 private PreferenceAttributeType currentPreferenceAttributeType;
260
261 /**
262 * Instance of the cache to which preferences will be stored.
263 */
264 private XMLPreferenceDataCache cache;
265
266 /**
267 * The of the current PreferenceAttribute being read
268 */
269 private ArrayList currentPreferenceAttributeOptionList;
270
271 /**
272 * The character buffer is used to hold the character data being parsed.
273 */
274 private StringBuffer characterBuffer;
275
276 /**
277 * Default constructor
278 */
279 public XMLPreferenceDataReader () {
280
281 cache = XMLPreferenceDataCache.getInstance();
282 preferenceStack = new Stack();
283 characterBuffer = new StringBuffer();
284 }
285
286 /**
287 * @see org.xml.sax.ContentHandler#endElement(java.lang.String,
288 * java.lang.String, java.lang.String)
289 */
290 public void endElement (String uri, String localName, String qName)
291 throws SAXException {
292
293 // Set the value of the element
294 if (null != currentElementToReadDataFor && characterBuffer.length() > 0) {
295 if (currentElementToReadDataFor
296 .equals(XMLNAME_PREF_ATT_DEFAULT_VALUE)) {
297 currentPreferenceAttributeDefaultValue = currentPreferenceAttributeDefaultValue + characterBuffer.toString();
298 } else if (currentElementToReadDataFor
299 .equals(XMLNAME_PREF_ATT_VALUE)) {
300 currentPreferenceAttributeValue = currentPreferenceAttributeValue + characterBuffer.toString();
301 } else if (currentElementToReadDataFor
302 .equals(XMLNAME_PREF_ATT_TYPE)) {
303 currentPreferenceAttributeType = PreferenceAttributeType
304 .getPreferenceAttributeByName(characterBuffer.toString());
305 } else if (currentElementToReadDataFor
306 .equals(XMLNAME_PREF_ATT_ENCRYPTED)) {
307 isPreferenceAttributeValueEncrypted = TRUE.equals(characterBuffer.toString());
308 if(isPreferenceAttributeValueEncrypted)
309 currentPreferenceAttributeValue =
310 Crypt.decryptHexString(currentPreferenceAttributeValue);
311 } else if (currentElementToReadDataFor
312 .equals(XMLNAME_PREF_ATT_PERSISTANT)) {
313 isCurrentPreferenceAttributePersistant = TRUE.equals(characterBuffer.toString());
314 } else if (currentElementToReadDataFor
315 .equals(XMLNAME_PREF_ATT_USER_MOD)) {
316 isCurrentPreferenceAttributeUserModifiable = TRUE.equals(characterBuffer.toString());
317 } else if (currentElementToReadDataFor
318 .equals(XMLNAME_PREF_ATT_OPTION_VAL)
319 && null != currentPreferenceAttributeOptionList) {
320 currentPreferenceAttributeOptionList.add(characterBuffer.toString());
321 }
322
323 characterBuffer.setLength(0);
324 }
325
326 if (XMLNAME_PREFERENCE.equals(localName)) {
327 endPreference();
328 } else if (XMLNAME_INSIGHT_PREFERENCE.equals(localName)) {
329 //System.out.println("End insight preferences");
330 } else if (XMLNAME_PREFERENCE_ATTRIBUTE.equals(localName)) {
331 endPreferenceAttribute();
332 } else if (XMLNAME_PREF_ATT_DEFAULT_VALUE.equals(localName)
333 || XMLNAME_PREF_ATT_VALUE.equals(localName)
334 || XMLNAME_PREF_ATT_TYPE.equals(localName)
335 || XMLNAME_PREF_ATT_ENCRYPTED.equals(localName)
336 || XMLNAME_PREF_ATT_PERSISTANT.equals(localName)
337 || XMLNAME_PREF_ATT_USER_MOD.equals(localName)
338 || XMLNAME_PREF_ATT_OPTION_VAL.equals(localName)) {
339 currentElementToReadDataFor = null;
340 } else if (XMLNAME_PREF_ATT_OPTIONS.equals(localName)) {
341 //do nothing
342 } else {
343 System.out.println("END-" + uri + "_" + localName + "_" + qName);
344 }
345 }
346
347 /**
348 * @see org.xml.sax.ContentHandler#startElement(java.lang.String,
349 * java.lang.String, java.lang.String, org.xml.sax.Attributes)
350 */
351 public void startElement (String uri, String localName, String qName,
352 Attributes attributes) throws SAXException {
353
354 if (XMLNAME_PREFERENCE.equals(localName)) {
355 startPreference(attributes);
356 } else if (XMLNAME_INSIGHT_PREFERENCE.equals(localName)) {
357 //System.out.println("Started insight preferences");
358 } else if (XMLNAME_PREFERENCE_ATTRIBUTE.equals(localName)) {
359 startPreferenceAttribute(attributes);
360 } else if (XMLNAME_PREF_ATT_DEFAULT_VALUE.equals(localName)
361 || XMLNAME_PREF_ATT_VALUE.equals(localName)
362 || XMLNAME_PREF_ATT_TYPE.equals(localName)
363 || XMLNAME_PREF_ATT_ENCRYPTED.equals(localName)
364 || XMLNAME_PREF_ATT_PERSISTANT.equals(localName)
365 || XMLNAME_PREF_ATT_USER_MOD.equals(localName)
366 || XMLNAME_PREF_ATT_OPTION_VAL.equals(localName)) {
367 currentElementToReadDataFor = localName;
368 } else if (XMLNAME_PREF_ATT_OPTIONS.equals(localName)) {
369 startOptions();
370 } else {
371 System.out.println("START-" + uri + "_" + localName + "_" + qName);
372 }
373
374 // Clear the character buffer
375 characterBuffer.setLength(0);
376 }
377
378 /**
379 * @see org.xml.sax.ContentHandler#characters(char[], int, int)
380 */
381 public void characters (char [] ch, int start, int length)
382 throws SAXException {
383
384 if (null != currentElementToReadDataFor) {
385 characterBuffer.append(ch, start, length);
386 }
387
388 }
389
390 /**
391 * Creates a Preference Object
392 *
393 * @param attributes attributes of the preference
394 */
395 private void startPreference (Attributes attributes) {
396
397 String id = attributes.getValue(XMLNAME_PREFERENCE_ID);
398 String name = attributes.getValue(XMLNAME_PREFERENCE_NAME);
399 String isUserModifableValue = attributes.getValue(XMLNAME_PREFERENCE_ISUSERMOD);
400 boolean isUserModifiable = TRUE.equals(isUserModifableValue);
401 String isAggregatedValue = attributes.getValue(XMLNAME_PREFERENCE_ISAGGREGATED);
402 boolean isAggregated = TRUE.equals(isAggregatedValue);
403 String displayClass = attributes.getValue(XMLNAME_PREFERENCE_DISPLAY_CLASS);
404
405 if (null != currentPreference) {
406 // Nested Preferences
407 preferenceStack.push(currentPreference);
408
409 currentPreference = new Preference(id, isUserModifiable, isAggregated, name);
410 currentPreference.setDisplayClass(displayClass);
411
412 Preference parentPreference = (Preference) preferenceStack.peek();
413 parentPreference.addChildPreference(currentPreference);
414 } else {
415 currentPreference = new Preference(id, isUserModifiable, isAggregated, name);
416 currentPreference.setDisplayClass(displayClass);
417 }
418 }
419
420 /**
421 * Clears the current Preference after saving it to the cache.
422 */
423 private void endPreference () {
424
425 if (preferenceStack.empty()) {
426 cache.addPreference(currentPreference);
427 currentPreference = null;
428 } else {
429 // Nested Preferences
430 currentPreference = (Preference) preferenceStack.pop();
431 }
432
433 }
434
435 /**
436 * Marks the start of an Preference Attribute element.
437 *
438 * @param attributes The XML attributes of the Preference Attribute
439 */
440 private void startPreferenceAttribute (Attributes attributes) {
441
442 currentPreferenceAttributeId = attributes
443 .getValue(XMLNAME_PREFERENCE_ATT_ID);
444 currentPreferenceAttributeName = attributes
445 .getValue(XMLNAME_PREFERENCE_ATT_NAME);
446 currentPreferenceAttributeXSIType = attributes.getValue(XSI_NAMESPACE,
447 XMLNAME_XSI_TYPE);
448 }
449
450 /**
451 * Creates the appropriate Preference Attribute object and adds it to the
452 * current Preference
453 */
454 private void endPreferenceAttribute () {
455
456 if (!currentPreference.isUserModifiable()) {
457 isCurrentPreferenceAttributeUserModifiable = false;
458 }
459
460 if (XMLNAME_LIST_PREFERENCE_ATTRIBUTE
461 .equals(currentPreferenceAttributeXSIType)) {
462 //List Preference Attribute
463 ListPreferenceAttribute preferenceAttribute = new ListPreferenceAttribute(
464 currentPreferenceAttributeId,
465 currentPreferenceAttributeValue,
466 isPreferenceAttributeValueEncrypted,
467 isCurrentPreferenceAttributePersistant,
468 isCurrentPreferenceAttributeUserModifiable,
469 currentPreference, currentPreferenceAttributeOptionList);
470
471 if (null != currentPreferenceAttributeDefaultValue) {
472 preferenceAttribute.setDefaultValue(currentPreferenceAttributeDefaultValue);
473 }
474 preferenceAttribute.setName(currentPreferenceAttributeName);
475 currentPreference.addPreferenceAttribute(preferenceAttribute);
476
477 } else {
478 PreferenceAttribute preferenceAttribute = new PreferenceAttribute(
479 currentPreferenceAttributeType,
480 currentPreferenceAttributeId,
481 currentPreferenceAttributeValue,
482 isPreferenceAttributeValueEncrypted,
483 isCurrentPreferenceAttributePersistant,
484 isCurrentPreferenceAttributeUserModifiable,
485 currentPreference);
486
487 if (null != currentPreferenceAttributeDefaultValue) {
488 preferenceAttribute.setDefaultValue(currentPreferenceAttributeDefaultValue);
489 }
490 preferenceAttribute.setName(currentPreferenceAttributeName);
491 currentPreference.addPreferenceAttribute(preferenceAttribute);
492 }
493
494 currentPreferenceAttributeId = null;
495 currentPreferenceAttributeName = null;
496 currentPreferenceAttributeXSIType = null;
497 currentPreferenceAttributeDefaultValue = "";
498 currentPreferenceAttributeValue = "";
499 currentPreferenceAttributeType = null;
500 isPreferenceAttributeValueEncrypted = false;
501 isCurrentPreferenceAttributePersistant = true;
502 isCurrentPreferenceAttributeUserModifiable = true;
503 currentPreferenceAttributeOptionList = null;
504 }
505
506 /**
507 * Starts an options section of ListPreferenceAttribute.
508 * Intializes the arraylist.
509 */
510 private void startOptions () {
511
512 currentPreferenceAttributeOptionList = new ArrayList();
513 }
514 }