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 }