creatorextension/com.nokia.s60tools.creator/src/com/nokia/s60tools/creator/xml/CreatorXMLParser.java
changeset 0 61163b28edca
equal deleted inserted replaced
-1:000000000000 0:61163b28edca
       
     1 /*
       
     2 * Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 package com.nokia.s60tools.creator.xml;
       
    20 
       
    21 import java.io.CharArrayWriter;
       
    22 import java.io.FileNotFoundException;
       
    23 import java.io.IOException;
       
    24 import java.io.InputStream;
       
    25 import java.util.Iterator;
       
    26 import java.util.LinkedHashMap;
       
    27 import java.util.Map;
       
    28 import java.util.Set;
       
    29 import java.util.Stack;
       
    30 import java.util.Vector;
       
    31 
       
    32 import org.xml.sax.Attributes;
       
    33 import org.xml.sax.ErrorHandler;
       
    34 import org.xml.sax.InputSource;
       
    35 import org.xml.sax.SAXException;
       
    36 import org.xml.sax.SAXParseException;
       
    37 import org.xml.sax.XMLReader;
       
    38 import org.xml.sax.helpers.DefaultHandler;
       
    39 import org.xml.sax.helpers.XMLReaderFactory;
       
    40 
       
    41 import com.nokia.s60tools.creator.components.AbstractComponent;
       
    42 import com.nokia.s60tools.creator.components.AbstractValue;
       
    43 import com.nokia.s60tools.creator.components.AbstractVariables;
       
    44 import com.nokia.s60tools.creator.components.ComponentServices;
       
    45 import com.nokia.s60tools.creator.components.Components;
       
    46 import com.nokia.s60tools.creator.components.AbstractValue.ModeTypes;
       
    47 import com.nokia.s60tools.creator.components.calendar.CalendarValue;
       
    48 import com.nokia.s60tools.creator.components.filetype.FileTypeValue;
       
    49 import com.nokia.s60tools.creator.components.filetype.FileTypeVariables;
       
    50 import com.nokia.s60tools.creator.components.messaging.MessageValue;
       
    51 import com.nokia.s60tools.creator.components.messaging.MessageVariables;
       
    52 import com.nokia.s60tools.creator.core.CreatorEditorSettings;
       
    53 import com.nokia.s60tools.creator.util.CreatorEditorConsole;
       
    54 
       
    55 /**
       
    56  * Class for parsing Creator XML Script file to Object model (Components)
       
    57  */
       
    58 public class CreatorXMLParser {
       
    59 
       
    60 	public CreatorXMLParser() {
       
    61 	}
       
    62 
       
    63 	CreatorXMLHandler handler = null;
       
    64 
       
    65 	/**
       
    66 	 * Was there errors when parsing (e.g. component type that is not supported)
       
    67 	 * 
       
    68 	 * @return true if there was some errors, false otherwise
       
    69 	 */
       
    70 	public boolean wasErrors() {
       
    71 		return handler.getErrors().trim().length() == 0 ? false : true;
       
    72 	}
       
    73 
       
    74 	/**
       
    75 	 * Get errors
       
    76 	 * 
       
    77 	 * @return description for errors or empty string if not any
       
    78 	 */
       
    79 	public String getErrors() {
       
    80 		return handler.getErrors();
       
    81 	}
       
    82 
       
    83 	/**
       
    84 	 * 
       
    85 	 * @param fileName
       
    86 	 *            file to be parsed
       
    87 	 * @return CreatorXML object with all elements and attributes set
       
    88 	 * @throws SAXException
       
    89 	 * @throws IOException
       
    90 	 * @throws CreatorScriptNotValidException
       
    91 	 *             if parsed data was not valid
       
    92 	 */
       
    93 	public Components parse(InputStream inStreamAsUTF8)
       
    94 			throws CreatorScriptNotValidException {
       
    95 		XMLReader reader;
       
    96 		Components components = null;
       
    97 		try {
       
    98 			handler = new CreatorXMLHandler();
       
    99 			reader = XMLReaderFactory.createXMLReader();
       
   100 
       
   101 			reader.setContentHandler(handler);
       
   102 			CreatorXMLErrorHandler errorHandler = new CreatorXMLErrorHandler();
       
   103 			reader.setErrorHandler(errorHandler);
       
   104 
       
   105 			InputSource in = new InputSource();			
       
   106 			in.setByteStream(inStreamAsUTF8);
       
   107 
       
   108 			reader.parse(in);
       
   109 
       
   110 			components = handler.getComponents();
       
   111 
       
   112 			if (components != null) {
       
   113 				return components;
       
   114 			} else {
       
   115 				throw new CreatorScriptNotValidException(handler.getErrors());
       
   116 			}
       
   117 
       
   118 		} catch (SAXException e) {
       
   119 			e.printStackTrace();
       
   120 			CreatorEditorConsole.getInstance().println(
       
   121 					"SAXException on parsing: " + e.toString());
       
   122 			throw new CreatorScriptNotValidException(e.getMessage());
       
   123 		} catch (FileNotFoundException e) {
       
   124 			CreatorEditorConsole.getInstance().println(
       
   125 					"FileNotFoundException on parsing: " + e.toString());
       
   126 			e.printStackTrace();
       
   127 			throw new CreatorScriptNotValidException(e.getMessage());
       
   128 		} catch (IOException e) {
       
   129 			CreatorEditorConsole.getInstance().println(
       
   130 					"IOException on parsing: " + e.toString());
       
   131 			e.printStackTrace();
       
   132 			throw new CreatorScriptNotValidException(e.getMessage());
       
   133 		}
       
   134 
       
   135 	}
       
   136 
       
   137 	/**
       
   138 	 * Error handler implementation
       
   139 	 */
       
   140 	public class CreatorXMLErrorHandler implements ErrorHandler {
       
   141 
       
   142 		public void error(SAXParseException e) throws SAXException {
       
   143 			CreatorEditorConsole.getInstance().println(
       
   144 					"SAXParseException (error) on parsing: " + e.toString());
       
   145 
       
   146 		}
       
   147 
       
   148 		public void fatalError(SAXParseException e) throws SAXException {
       
   149 			CreatorEditorConsole.getInstance().println(
       
   150 					"SAXParseException (fatal) on parsing: " + e.toString());
       
   151 		}
       
   152 
       
   153 		public void warning(SAXParseException e) throws SAXException {
       
   154 			CreatorEditorConsole.getInstance().println(
       
   155 					"SAXParseException (warning) on parsing: " + e.toString());
       
   156 		}
       
   157 
       
   158 	}
       
   159 
       
   160 	// //////////////////////////////////////////////////////////////////
       
   161 	// Event handlers.
       
   162 	// //////////////////////////////////////////////////////////////////
       
   163 
       
   164 	/**
       
   165 	 * Handler implementaion
       
   166 	 */
       
   167 	public class CreatorXMLHandler extends DefaultHandler {
       
   168 
       
   169 
       
   170 
       
   171 		private static final String AMOUNT = "amount";
       
   172 
       
   173 		private static final String CREATORSCRIPT = "creatorscript";
       
   174 
       
   175 		private static final String MEMBERS = "members";
       
   176 
       
   177 		// Local variables and flags
       
   178 
       
   179 		private static final String FIELDS = "fields";
       
   180 
       
   181 		// flags to know depth
       
   182 		private int depth = 0;
       
   183 
       
   184 		private boolean creatorscript = false;
       
   185 		private boolean fields = false;
       
   186 		private boolean component = false;
       
   187 		private boolean subComponent = false;
       
   188 		private boolean item = false;
       
   189 		private boolean subitem = false;
       
   190 		private String subItemBaseName = "";
       
   191 		private Map<String, String> subItemMap;
       
   192 		Stack<String> elementNames = new Stack<String>();
       
   193 
       
   194 		private AbstractComponent aComponent;
       
   195 		private AbstractComponent aSubComponent;
       
   196 		private String componentType = "";
       
   197 		private String subComponentType = "";
       
   198 		// A name of element e.g. "<mobile>" on:
       
   199 		// <creatorscript version="1.0"><contact><fields><mobile>
       
   200 		private String itemName = "";
       
   201 		private Map<String, Vector<AbstractValue>> componentItems;
       
   202 		private Map<String, Vector<AbstractValue>> subComponentItems;
       
   203 		private Components components;
       
   204 		private CharArrayWriter elementContent = new CharArrayWriter();
       
   205 
       
   206 		private StringBuffer errors = new StringBuffer();
       
   207 		private int itemAmountParam;
       
   208 		private ModeTypes randomType;
       
   209 
       
   210 		private int itemIdParam;
       
   211 
       
   212 		private int itemMaxAmountParam;
       
   213 		
       
   214 		private String rightType = null;
       
   215 		
       
   216 		private String incvalueforeachcopy = null;
       
   217 
       
   218 		private int userDefinedRandomLen = -1;
       
   219 
       
   220 
       
   221 		public CreatorXMLHandler() {
       
   222 			components = new Components();
       
   223 
       
   224 		}
       
   225 
       
   226 		/**
       
   227 		 * Get components
       
   228 		 * @return components parsed
       
   229 		 */
       
   230 		public Components getComponents() {
       
   231 			return components;
       
   232 		}
       
   233 
       
   234 		/*
       
   235 		 * (non-Javadoc)
       
   236 		 * 
       
   237 		 * @see org.xml.sax.helpers.DefaultHandler#startDocument()
       
   238 		 */
       
   239 		public void startDocument() {
       
   240 		}
       
   241 
       
   242 		/*
       
   243 		 * (non-Javadoc)
       
   244 		 * 
       
   245 		 * @see org.xml.sax.helpers.DefaultHandler#endDocument()
       
   246 		 */
       
   247 		public void endDocument() {
       
   248 		}
       
   249 
       
   250 		/*
       
   251 		 * (non-Javadoc)
       
   252 		 * 
       
   253 		 * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String,
       
   254 		 *      java.lang.String, java.lang.String, org.xml.sax.Attributes)
       
   255 		 */
       
   256 		public void startElement(String uri, String name_, String qName,
       
   257 				Attributes atts) {
       
   258 
       
   259 			String name = name_.toLowerCase();//Element names is fixed always to be on lowercase
       
   260 			
       
   261 			elementNames.push(name);
       
   262 			 depth++;
       
   263 
       
   264 			 
       
   265 			// <creatorscript>
       
   266 			if (name.equalsIgnoreCase(CREATORSCRIPT)) {
       
   267 				creatorscript = true;
       
   268 			}
       
   269 			// <fields>
       
   270 			else if (name.equalsIgnoreCase(FIELDS) || name.equalsIgnoreCase(MEMBERS)) {
       
   271 				fields = true;
       
   272 			}			 
       
   273 			// <component>
       
   274 			else if (creatorscript && !component && !fields && !item) {
       
   275 				aComponent = ComponentServices
       
   276 						.getComponentByXMLElementName(name);
       
   277 				if (aComponent != null) {
       
   278 					component = true;
       
   279 					componentType = name;
       
   280 					componentItems = new LinkedHashMap<String, Vector<AbstractValue>>();
       
   281 					
       
   282 					handleComponentParameters(atts, aComponent);
       
   283 
       
   284 				}// if(aComponent != null){
       
   285 				else {
       
   286 					String errMsg = "Could not found component type: " + name + CreatorXML.NEW_LINE;
       
   287 					CreatorEditorConsole.getInstance().println("Error on parsing: " + errMsg);
       
   288 					errors.append(errMsg);
       
   289 				}
       
   290 			}// if(creatorscript &&!component && !fields && !item){
       
   291 
       
   292 			//sub component <component><component> e.g. <contact-set><contact>
       
   293 			else if (creatorscript && component && !fields && !item) {
       
   294 				//We found a sub component, if component is open, and field is not opened
       
   295 				aSubComponent = ComponentServices
       
   296 						.getComponentByXMLElementName(name);
       
   297 				if (aSubComponent != null) {
       
   298 					subComponent = true;
       
   299 					subComponentType = name;
       
   300 					subComponentItems = new LinkedHashMap<String, Vector<AbstractValue>>();
       
   301 					handleComponentParameters(atts, aSubComponent);
       
   302 					
       
   303 
       
   304 				}// if(aComponent != null){
       
   305 				else {
       
   306 					String errMsg = "Could not found component type: " + name + CreatorXML.NEW_LINE;
       
   307 					CreatorEditorConsole.getInstance().println("Error on parsing: " + errMsg);
       
   308 					errors.append(errMsg);
       
   309 				}
       
   310 			}// if(creatorscript &&!component && !fields && !item){			
       
   311 			
       
   312 			// <item>
       
   313 			else if (creatorscript && component && fields) {
       
   314 
       
   315 				// subitem, e.g.
       
   316 				// <creatorscript><calendar><items><attendees><attendee>
       
   317 				if (item) {
       
   318 					if (!subitem) {
       
   319 						subitem = true;
       
   320 						// subItemsStack = new Stack<AbstractValue>();
       
   321 						subItemMap = new LinkedHashMap<String, String>();
       
   322 						subItemBaseName = name;
       
   323 					}
       
   324 
       
   325 				}// else if(creatorscript && component && fields && item){
       
   326 				itemName = name;//ItemName is used with item, newer with the subitem
       
   327 				item = true;
       
   328 
       
   329 				//handle params for item
       
   330 				handleItemParams(atts, aComponent, name);
       
   331 			}// else if(creatorscript && component && fields
       
   332 
       
   333 
       
   334 			// If component was unknown (errors on XML) and we are inside of
       
   335 			// field.
       
   336 			else if (creatorscript && !component && fields) {
       
   337 				// Skipping all attributes of this component.
       
   338 			}
       
   339 			else{
       
   340 				errors.append("Unknown error when parsing component: '"+getComponent().getType() +"' with element: '" + uri +"', element local name: '" +name +"', name: '" + qName +"'." );
       
   341 			}
       
   342 
       
   343 			elementContent.reset();
       
   344 
       
   345 		}
       
   346 
       
   347 		/**
       
   348 		 * handles item level parameters
       
   349 		 * @param atts
       
   350 		 */
       
   351 		private void handleItemParams(Attributes atts,
       
   352 				AbstractComponent com, String elementName) {
       
   353 
       
   354 
       
   355 			boolean foundRandomLen = false;
       
   356 			int len = atts.getLength();
       
   357 			for (int i = 0; i < len; i++) {
       
   358 				String key = atts.getQName(i);
       
   359 				if(key.equalsIgnoreCase(AMOUNT)){
       
   360 					//Set amount to component
       
   361 					itemAmountParam = getIntParameter(key, atts.getValue(key));					
       
   362 				}
       
   363 				else if(key.equalsIgnoreCase("randomlength")){
       
   364 				
       
   365 					// randomlength parameter 
       
   366 					handleRandomParam(atts.getValue(key), com);
       
   367 					foundRandomLen = true;
       
   368 				}
       
   369 				else if(key.equalsIgnoreCase(AbstractComponent.ID_PARAMETER_ID)){
       
   370 				
       
   371 					itemIdParam = getIntParameter(key, atts.getValue(key));
       
   372 				}				
       
   373 				else if(key.equalsIgnoreCase("maxamount")){
       
   374 					itemMaxAmountParam = getIntParameter(key, atts.getValue(key));
       
   375 				}
       
   376 				else if(key.equalsIgnoreCase(AbstractComponent.INCVALUEFOREACHCOPY_PARAMETER_ID)){
       
   377 					incvalueforeachcopy = atts.getValue(key);
       
   378 				}				
       
   379 				
       
   380 				//Ecryption right type on FileType <encryption type="DRM-CD"><right type="print">
       
   381 				else if(key.equalsIgnoreCase(FileTypeVariables.TYPE_XML)){
       
   382 
       
   383 					//Handling encryption type parameter for File
       
   384 					if(elementName.equalsIgnoreCase(FileTypeVariables.ENCRYPTION_TYPE_XML)){
       
   385 						handleFileTypeEncryptionTypeParam(atts, com, elementName, key);						
       
   386 					}
       
   387 					//It's encryption right type parameter
       
   388 					else{
       
   389 						rightType = atts.getValue(key);
       
   390 					}
       
   391 					
       
   392 				}				
       
   393 				
       
   394 			}	
       
   395 			//Always must handle randomlength, even if parameter was not found
       
   396 			if(!foundRandomLen){
       
   397 				handleRandomParam(null, com);
       
   398 			}
       
   399 		}
       
   400 
       
   401 		/**
       
   402 		 * Handle <encryption type=[type]> -parameter from FileType Component
       
   403 		 * @param atts
       
   404 		 * @param com
       
   405 		 * @param elementName
       
   406 		 * @param key
       
   407 		 */
       
   408 		private void handleFileTypeEncryptionTypeParam(Attributes atts,
       
   409 				AbstractComponent com, String elementName, String key) {
       
   410 			
       
   411 			String encryptionType = atts.getValue(key);
       
   412 
       
   413 			if(com.getType().equals(CreatorEditorSettings.TYPE_FILE)){
       
   414 				AbstractValue val = ComponentServices
       
   415 					.getValueByXMLElementName(com.getXMLElementName());							
       
   416 			
       
   417 				if(encryptionType != null && !CreatorEditorSettings.isRandomText(encryptionType)){
       
   418 					val.setValue(encryptionType);								
       
   419 					val.setRandom(false);
       
   420 				}else{
       
   421 					val.setModeType(AbstractValue.ModeTypes.RandomTypeDefaultLength);
       
   422 				}
       
   423 				String itemId = com.getValueById(elementName);
       
   424 				addValueToComponent(val, itemId, componentItems);								
       
   425 			}
       
   426 		}
       
   427 
       
   428 		/**
       
   429 		 * Handles possible component level parameters
       
   430 		 * @param atts
       
   431 		 * @param comp
       
   432 		 */
       
   433 		private void handleComponentParameters(Attributes atts, AbstractComponent comp) {
       
   434 			
       
   435 			int len = atts.getLength();
       
   436 			for (int i = 0; i < len; i++) {
       
   437 				String key = atts.getQName(i);
       
   438 			
       
   439 				if(key.equalsIgnoreCase(AMOUNT)){
       
   440 					//Set amount to component
       
   441 					handleComponentAmountParameter(atts.getValue(key), comp);
       
   442 				}
       
   443 				else if(key.equalsIgnoreCase(AbstractComponent.TYPE_PARAMETER_ID)){
       
   444 				
       
   445 					//Required Type parameter for Calendar and Messages
       
   446 					handleTypeParameter(atts.getValue(key), comp);
       
   447 				}
       
   448 				else if(key.equalsIgnoreCase(AbstractComponent.ID_PARAMETER_ID)){
       
   449 				
       
   450 					//If there is "id" parameter set that to component id
       
   451 					handleIdParameter(atts.getValue(key), comp);
       
   452 				}				
       
   453 				else if(key.equalsIgnoreCase(AbstractComponent.NAME_PARAMETER_ID)){
       
   454 					String name = atts.getValue(key);
       
   455 					if(name != null && name.trim().length() > 0){
       
   456 						comp.addAdditionalParameter(AbstractComponent.NAME_PARAMETER_ID,
       
   457 								name.trim());
       
   458 					}				
       
   459 				}
       
   460 				else if(key.equalsIgnoreCase(AbstractComponent.NUMBER_OF_EXISTING_CONTACTS_PARAMETER_ID)){
       
   461 					//handle numberofexistingcontacts parameter
       
   462 					handleNumberOfExistingContactsParameters(atts.getValue(key), comp);
       
   463 				}
       
   464 				
       
   465 			}
       
   466 
       
   467 		}
       
   468 
       
   469 		/**
       
   470 		 * Handles AbstractComponent.NUMBER_OF_EXISTING_CONTACTS_PARAMETER_ID and AbstractComponent.NAME_PARAMETER_ID parameters
       
   471 		 * @param atts
       
   472 		 * @param comp
       
   473 		 */
       
   474 		private void handleNumberOfExistingContactsParameters(String value,
       
   475 				AbstractComponent comp) {
       
   476 
       
   477 			int numberOfExistingParams = AbstractComponent.NULL_ID;
       
   478 			if (value != null && value.trim().length() > 0) {
       
   479 				try {
       
   480 					numberOfExistingParams = Integer.parseInt(value);
       
   481 					comp
       
   482 							.addAdditionalParameter(
       
   483 									AbstractComponent.NUMBER_OF_EXISTING_CONTACTS_PARAMETER_ID,
       
   484 									"" + numberOfExistingParams);
       
   485 
       
   486 				} catch (Exception e) {
       
   487 					// Adding error message
       
   488 					errors
       
   489 							.append("Invalid '"
       
   490 									+ "AbstractComponent.NUMBER_OF_EXISTING_CONTACTS_PARAMETER_ID"
       
   491 									+ "' parameter in component: '"
       
   492 									+ comp.getType() + "'.");
       
   493 				}
       
   494 			}
       
   495 
       
   496 		}
       
   497 
       
   498 		/**
       
   499 		 * Sets id parameter to compoent if valid
       
   500 		 * @param value
       
   501 		 * @param com
       
   502 		 */
       
   503 		private void handleIdParameter(String value,
       
   504 				AbstractComponent com) {
       
   505 
       
   506 			if(value != null && value.trim().length() > 0){
       
   507 				try {
       
   508 					int id = Integer.parseInt(value);
       
   509 					com.setId(id);
       
   510 				} catch (Exception e) {
       
   511 					errors.append("Invalid id parameter value: '" +value +"' in component: '" +com.getType() +"'.");
       
   512 				}
       
   513 			}
       
   514 			
       
   515 		}
       
   516 
       
   517 		/**
       
   518 		 * Handles type parameter to component
       
   519 		 * @param typeParameter
       
   520 		 * @param comp
       
   521 		 */
       
   522 		private void handleTypeParameter(String typeParameter, AbstractComponent comp) {
       
   523 			if(typeParameter != null && typeParameter.trim().length() > 0){
       
   524 				comp.addAdditionalParameter(AbstractComponent.TYPE_PARAMETER_ID, typeParameter.trim());
       
   525 			}
       
   526 		}
       
   527 
       
   528 		/**
       
   529 		 * Handles random parameter
       
   530 		 * @param randomlength
       
   531 		 */
       
   532 		private void handleRandomParam(String randomlength,
       
   533 				AbstractComponent com) {
       
   534 			//if randomlenght parameter is set
       
   535 			if (randomlength != null && randomlength.trim().length() > 0) {
       
   536 
       
   537 				if (randomlength.equalsIgnoreCase(AbstractVariables.RANDOM_LEN_DEFAULT_XML_VALUE)) {
       
   538 					randomType = ModeTypes.RandomTypeDefaultLength;
       
   539 				} else if (randomlength.equalsIgnoreCase(AbstractVariables.RANDOM_LEN_MAX_XML_VALUE)) {
       
   540 					randomType = ModeTypes.RandomTypeMaxLength;
       
   541 				}
       
   542 				else {
       
   543 					// Set to user defined random length
       
   544 					try {
       
   545 						userDefinedRandomLen = Integer
       
   546 									.parseInt(randomlength);
       
   547 						randomType = ModeTypes.RandomTypeUserDefinedLength;
       
   548 					} catch (Exception e) {
       
   549 						// set to default length when error occurs
       
   550 						randomType = ModeTypes.RandomTypeDefaultLength;
       
   551 						errors.append("Invalid randomlength parameter value: '" +randomlength +"' in component: '" +com.getType() +"'.");
       
   552 						userDefinedRandomLen = -1;
       
   553 					}
       
   554 
       
   555 				}
       
   556 			}
       
   557 			//randomlength parameter was not set 
       
   558 			else {
       
   559 				// NOTE: item might also be default len random type if not
       
   560 				// set and there is no value
       
   561 				// that will be taken care of in endElement. In here just
       
   562 				// setting value so known at it was not set
       
   563 				randomType = ModeTypes.RandomTypeNotRandom;
       
   564 			}
       
   565 		}
       
   566 
       
   567 
       
   568 		
       
   569 		
       
   570 		/**
       
   571 		 * Get int parameter
       
   572 		 * @param value
       
   573 		 * @return 0 if not found or invalid, value as int otherwise
       
   574 		 */
       
   575 		private int getIntParameter(String parameterName, String value) {
       
   576 			int valueInt = 0;
       
   577 			if (value != null && value.trim().length() > 0) {
       
   578 				try {
       
   579 					valueInt = Integer.parseInt(value);
       
   580 				} catch (Exception e) {
       
   581 					errors.append("Not supported '" +parameterName +"' value: '" + value
       
   582 							+ "' attribute in item: '" + itemName
       
   583 							+ "' in component: '" + componentType + "'");
       
   584 					valueInt = 0;
       
   585 				}
       
   586 			} 
       
   587 			return valueInt;
       
   588 		}
       
   589 		
       
   590 		
       
   591 		/**
       
   592 		 * Handles component amount parameter
       
   593 		 * @param amount
       
   594 		 * @param comp
       
   595 		 */
       
   596 		private void handleComponentAmountParameter(String amount, AbstractComponent comp) {
       
   597 			if (amount != null && amount.trim().length() > 0) {
       
   598 				try {
       
   599 					int am = Integer.parseInt(amount);
       
   600 					comp.setAmount(am);
       
   601 				} catch (Exception e) {
       
   602 					errors.append("Not supported amout: '" + amount
       
   603 							+ "' attribute in component: '"
       
   604 							+ componentType + "'");
       
   605 				}
       
   606 			}// if(aComponent != null){
       
   607 		}
       
   608 
       
   609 		/*
       
   610 		 * (non-Javadoc)
       
   611 		 * 
       
   612 		 * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String,
       
   613 		 *      java.lang.String, java.lang.String)
       
   614 		 */
       
   615 		public void endElement(String uri, String name_, String qName) {
       
   616 
       
   617 			String name = name_.toLowerCase();//Element names is fixed always to be on lowercase
       
   618 			
       
   619 			
       
   620 			elementNames.pop();
       
   621 			depth--;
       
   622 
       
   623 			
       
   624 			// </creatorscript>
       
   625 			if (name.equalsIgnoreCase(CREATORSCRIPT)) {
       
   626 				creatorscript = false;
       
   627 			}
       
   628 
       
   629 			// </fields>
       
   630 			else if (name.equalsIgnoreCase(FIELDS) || name.equalsIgnoreCase(MEMBERS)) {
       
   631 				fields = false;
       
   632 			}			
       
   633 			// </component>
       
   634 			else if (creatorscript && component && !subComponent && !fields) {
       
   635 
       
   636 				if (name.equals(componentType)) {
       
   637 					aComponent.setAttributes(componentItems);
       
   638 					// If component is known, e.g. is not type UnknownCompoment
       
   639 					// (CreatorEditorSettings.TYPE_UNKNOWN)
       
   640 					if (!aComponent.getType().equals(
       
   641 							CreatorEditorSettings.TYPE_UNKNOWN)) {
       
   642 						components.addComponent(aComponent);
       
   643 					}
       
   644 					// Else component is UnknownComponent and is added to errors
       
   645 					else {
       
   646 						String errMsg = "Component type: '" + componentType
       
   647 							+ "' not supported. Component with following information was skipped: "
       
   648 							+ aComponent.toString();
       
   649 						errors.append(errMsg);
       
   650 						CreatorEditorConsole.getInstance().println(
       
   651 								"Error on parsing component, error was; " + errMsg);							
       
   652 
       
   653 					}
       
   654 					component = false;
       
   655 					componentType = "";
       
   656 					//Making sure that also sub component is closed when component is closed
       
   657 					subComponent = false;
       
   658 					subComponentType = "";
       
   659 				}
       
   660 
       
   661 			}
       
   662 			// </component></component> == subcomponent closing
       
   663 			else if (creatorscript && component && subComponent && !fields) {
       
   664 
       
   665 				//Collecting subcomponent data, and adding it as reference to component
       
   666 				if (name.equals(subComponentType)) {
       
   667 					aSubComponent.setAttributes(subComponentItems);
       
   668 					// If component is known, e.g. is not type UnknownCompoment
       
   669 					// (CreatorEditorSettings.TYPE_UNKNOWN)
       
   670 					if (!aSubComponent.getType().equals(
       
   671 							CreatorEditorSettings.TYPE_UNKNOWN)) {
       
   672 						//This might seems to be hazard code, but it goest that way, that 
       
   673 						//sub component has a reference to component, not vice versa
       
   674 						aSubComponent.setReferenceToAnotherComponent(aComponent);
       
   675 						components.addComponent(aSubComponent);
       
   676 					}
       
   677 					// Else component is UnknownComponent and is added to errors
       
   678 					else {
       
   679 						String errMsg = "Component type: '" + subComponentType
       
   680 										+ "' under component: '" +componentType 
       
   681 										+ "' not supported. Component with following information was skipped: "
       
   682 										+ aSubComponent.toString();
       
   683 						errors.append(errMsg);
       
   684 						CreatorEditorConsole.getInstance().println(
       
   685 								"Error on parsing sub component, error was; " + errMsg);						
       
   686 					}
       
   687 					subComponent = false;
       
   688 					subComponentType = "";
       
   689 				}
       
   690 
       
   691 			}			
       
   692 			
       
   693 			// </item>
       
   694 			else if (creatorscript && component && fields && item && !subitem) {
       
   695 				
       
   696 				if (name.equals(itemName) ) {					
       
   697 
       
   698 					// Get real value type by component type
       
   699 					AbstractValue val = ComponentServices
       
   700 							.getValueByXMLElementName(getComponent().getXMLElementName());								
       
   701 
       
   702 					// If there was component type that is not supported
       
   703 					if (val != null) {
       
   704 						
       
   705 						if (val instanceof FileTypeValue && name.equalsIgnoreCase(FileTypeVariables.ENCRYPTION_TYPE_XML)){
       
   706 							
       
   707 							//Because of file type encryption is handled in #handleFileTypeEncryptionTypeParam()
       
   708 							//We skip handling it here. Thats because of encryption has no value, but only parameter
       
   709 							//and default implementation is that empty element means random value, and there is no random 
       
   710 							//encryption values. Element is added earlier because of component order in list occurs how they
       
   711 							//added and it causes other issues to handle first possible elements and later on element parameters
       
   712 							//(mainly element parameters is handled first, and so its done with encryption parameters also).
       
   713 							
       
   714 						}else{
       
   715 						
       
   716 							setValueParamsAndSetAsContactSetReference(val, itemName);
       
   717 	
       
   718 							// Get Vector where all same named values is stored,
       
   719 							// e.g. if one contact has many "First names" all is
       
   720 							// stored to same vector
       
   721 							String itemId = getComponent().getValueById(itemName);
       
   722 							if (itemId != null) {
       
   723 								
       
   724 								// When found closing point to subitem		
       
   725 								if(subComponent){
       
   726 									addValueToComponent(val, itemId, subComponentItems);
       
   727 								}else{
       
   728 									addValueToComponent(val, itemId, componentItems);
       
   729 								}
       
   730 								
       
   731 							}					
       
   732 							else {
       
   733 								String errMsg = "Element: ' " + itemName
       
   734 										+ "' in component: '"
       
   735 										+ getComponent().getXMLElementName()
       
   736 										+ "' is not supported." +CreatorXML.NEW_LINE;
       
   737 								errors.append(errMsg);
       
   738 							}
       
   739 						}
       
   740 
       
   741 					}// if(val != null){					
       
   742 					// Else we found a component value that is not supported.
       
   743 					else {
       
   744 						String errMsg = "Could not found values for component: "
       
   745 								+ getComponent().getType() + CreatorXML.NEW_LINE;
       
   746 						CreatorEditorConsole.getInstance().println(
       
   747 								"Error on parsing: " + errMsg);
       
   748 						errors.append(errMsg);
       
   749 					}
       
   750 				}
       
   751 					
       
   752 				
       
   753 				itemName = "";
       
   754 				item = false;
       
   755 				itemAmountParam = 0;						
       
   756 
       
   757 			}// else if(creatorscript && component && fields && item &&  !subitem){
       
   758 			//<subitem>
       
   759 			else if (creatorscript && component && fields && item && subitem) {
       
   760 				
       
   761 				//E.g. <attendee> in calendar are subitems
       
   762 				//<calendar type="appointment"><fields><summary>MEETING</summary><attendees><attendee><email>...
       
   763 				
       
   764 				// Get real value type by component type
       
   765 				AbstractValue val = ComponentServices
       
   766 						.getValueByXMLElementName(aComponent.getXMLElementName());
       
   767 
       
   768 				// If there was component type that is not supported
       
   769 				if (val != null) {
       
   770 
       
   771 					setValueParamsAndSetAsContactSetReference(val, subItemBaseName);
       
   772 
       
   773 					//If sub item is closing
       
   774 					if (name.equals(subItemBaseName)) {
       
   775 						
       
   776 						subitem = false;
       
   777 
       
   778 						// Get Vector where all same named values is stored,
       
   779 						// e.g. if one contact has many "First names" all is
       
   780 						// stored to same vector
       
   781 						String itemId = aComponent.getValueById(subItemBaseName);
       
   782 						
       
   783 						if (itemId != null) {
       
   784 
       
   785 							// If we are inside of element where is sub elements
       
   786 							if (val instanceof CalendarValue) {
       
   787 
       
   788 								handleCalendarSubValue(name, qName, val, itemId);
       
   789 
       
   790 
       
   791 							}// if(subitem && val instanceof CalendarValue){
       
   792 							//When its message value, and its under from or to, get item ID so it will be from / to							
       
   793 							else if (val instanceof MessageValue) {
       
   794 								
       
   795 								handleMessageSubValue(name, qName, val, subItemBaseName, elementNames.lastElement());
       
   796 
       
   797 							}// if(subitem && val instanceof CalendarValue){
       
   798 							//When it's a FileType, there can be encryption 
       
   799 							//<ecryption><type="DRM-CD"><right type="[value]"><count></count>...  
       
   800 							else if (val instanceof FileTypeValue) {
       
   801 								
       
   802 								handleFileTypeSubValue(name);
       
   803 
       
   804 							}// if(subitem && val instanceof CalendarValue){								
       
   805 							// Error: 
       
   806 							else {
       
   807 								errors.append("Unknown subelement type: '" +itemId +"' found in: " +val.getType() +CreatorXML.NEW_LINE);
       
   808 							}
       
   809 						}// if(itemId != null){
       
   810 						else {
       
   811 							String errMsg = "Element: ' " + subItemBaseName + "' in component: '" 
       
   812 								+ aComponent.getXMLElementName() + "' is not supported." +CreatorXML.NEW_LINE;
       
   813 							errors.append(errMsg);
       
   814 						}
       
   815 
       
   816 						
       
   817 						
       
   818 					}// if(name.equals(subItemBaseName)){
       
   819 					//else sub item does not closed yet but it was a element of sub element
       
   820 					else {
       
   821 						// Creating sub value values and put them a side for waiting until closing point of
       
   822 						// sub element is found  e.g. email and common name in
       
   823 						// <attendee><email/><commonname/></attendee> 
       
   824 						
       
   825 						//When type is file, there can be several count, starttime, endtime, 
       
   826 						//interval and accumulated elemets, those must be possible to distinguish each other, 
       
   827 						//thats why encryption Right type is used in parameter name inside of Creator editor  
       
   828 						if(val instanceof FileTypeValue && rightType != null) {
       
   829 
       
   830 							String uiId = FileTypeVariables.getEncryptionId(rightType, name);
       
   831 							String uiCompName = aComponent.getValueById(uiId);
       
   832 							if(uiCompName != null){
       
   833 								addValueToComponent(val, uiCompName, componentItems);
       
   834 							}else{
       
   835 								String errMsg = "Element: ' " + name + "' under " +FileTypeVariables.RIGHT_XML +" " 
       
   836 									+FileTypeVariables.TYPE_XML +": '" +rightType
       
   837 									+  "' in component: '" + aComponent.getXMLElementName() 
       
   838 									+ "' is not supported." +CreatorXML.NEW_LINE;
       
   839 								errors.append(errMsg);
       
   840 							}
       
   841 						}else{
       
   842 							subItemMap.put(name, val.getValue());
       
   843 						}
       
   844 					}
       
   845 				}// if(val != null){
       
   846 
       
   847 				// Else we found a sub component value that is not supported.
       
   848 				else {
       
   849 					String errMsg = "Could not found values for component: " + aComponent.getType() + CreatorXML.NEW_LINE;
       
   850 					CreatorEditorConsole.getInstance().println( "Error on parsing: " + errMsg);
       
   851 					errors.append(errMsg);
       
   852 				}
       
   853 
       
   854 			}//else if (creatorscript && component && fields && item && subitem) {
       
   855 
       
   856 		}
       
   857 
       
   858 		/**
       
   859 		 * @param name
       
   860 		 */
       
   861 		private void handleFileTypeSubValue(String name) {
       
   862 			
       
   863 			if(name.equalsIgnoreCase(FileTypeVariables.RIGHT_XML)){
       
   864 				rightType = null;
       
   865 			}
       
   866 
       
   867 		}
       
   868 
       
   869 		/**
       
   870 		 * @param name
       
   871 		 * @param qName
       
   872 		 * @param val
       
   873 		 * @param currentElementName
       
   874 		 * @param superElementType
       
   875 		 */
       
   876 		private void handleMessageSubValue(String name, String qName,
       
   877 				AbstractValue val, String currentElementName, String superElementType) {
       
   878 
       
   879 
       
   880 			MessageValue mesVal = (MessageValue) val; 
       
   881 
       
   882 			//What value types was in under <item><subitem> -subitems
       
   883 			Set<String> subItemKeys = subItemMap
       
   884 						.keySet();
       
   885 				// Looping through all sub elements and add
       
   886 				// them to element (value)
       
   887 				for (Iterator<String> iterator = subItemKeys
       
   888 						.iterator(); iterator.hasNext();) {
       
   889 
       
   890 					String key = (String) iterator.next();
       
   891 					mesVal.setValue(subItemMap
       
   892 							.get(key));
       
   893 				}
       
   894 				mesVal.setType(MessageVariables.getValueByIds(superElementType, name));
       
   895 
       
   896 				String id = MessageVariables.getInstance().getIDByValueAndType(currentElementName, superElementType);
       
   897 				
       
   898 				// When found closing point to subitem									
       
   899 				if(subComponent){
       
   900 					addValueToComponent(val, id, subComponentItems);
       
   901 				}else{
       
   902 					addValueToComponent(val, id, componentItems);
       
   903 				}									
       
   904 		}		
       
   905 		
       
   906 		/**
       
   907 		 * Handles sub value of calendar type
       
   908 		 * @param name
       
   909 		 * @param qName
       
   910 		 * @param val
       
   911 		 * @param itemId
       
   912 		 */
       
   913 		private void handleCalendarSubValue(String name, String qName,
       
   914 				AbstractValue val, String itemId) {
       
   915 			// If this is the closing point of element where
       
   916 			// was sub elements
       
   917 			// Collecting sub element datas and add them to
       
   918 			// element
       
   919 			// e.g. //e.g. attendee in
       
   920 			// <calendar><attendee><email/><commonname/></attendee></calendar>
       
   921 
       
   922 
       
   923 				CalendarValue calVal = (CalendarValue) val;
       
   924 
       
   925 				Set<String> subItemKeys = subItemMap
       
   926 						.keySet();
       
   927 				// Looping through all sub elements and add
       
   928 				// them to element (value)
       
   929 				for (Iterator<String> iterator = subItemKeys
       
   930 						.iterator(); iterator.hasNext();) {
       
   931 
       
   932 					String key = (String) iterator.next();
       
   933 					calVal.setValue(key, subItemMap
       
   934 							.get(key));
       
   935 				}
       
   936 
       
   937 				// When found closing point to subitem									
       
   938 				if(subComponent){
       
   939 					addValueToComponent(val, itemId, subComponentItems);
       
   940 				}else{
       
   941 					addValueToComponent(val, itemId, componentItems);
       
   942 				}									
       
   943 		}
       
   944 
       
   945 		/**
       
   946 		 * Get component or sub component, depending on value of subComponent
       
   947 		 * @return a aSubComponent if subComponent == true
       
   948 		 */
       
   949 		private AbstractComponent getComponent() {
       
   950 			if(subComponent){
       
   951 				return aSubComponent;
       
   952 			}else{
       
   953 				return aComponent;
       
   954 			}
       
   955 		}
       
   956 
       
   957 		/**
       
   958 		 * Set Parameters to value, resets Parameter values when used.
       
   959 		 * @param value
       
   960 		 * @param XML element name where parameters belongs to.
       
   961 		 */
       
   962 		private void setValueParamsAndSetAsContactSetReference(AbstractValue val, String xmlElementName) {
       
   963 			
       
   964 			
       
   965 			if(CreatorEditorSettings.isContactSetReference(xmlElementName)){
       
   966 				val.setContactSetReference(true);
       
   967 			}
       
   968 			
       
   969 			// If there is some content, its not a random value,
       
   970 			// otherwise it is a random value
       
   971 			if (itemAmountParam != 0) {
       
   972 				val.setAmount(itemAmountParam);
       
   973 				itemAmountParam = 0;
       
   974 			}
       
   975 			
       
   976 			if ( itemIdParam != 0) {
       
   977 				val.setId(itemIdParam);
       
   978 				itemIdParam = 0;
       
   979 			}
       
   980 
       
   981 			if ( itemMaxAmountParam != 0) {
       
   982 				val.setMaxAmount(itemMaxAmountParam);
       
   983 				itemMaxAmountParam = 0;
       
   984 			}		
       
   985 			
       
   986 			
       
   987 			//
       
   988 			//Setting random values & modes
       
   989 			//
       
   990 
       
   991 			if (elementContent != null
       
   992 					&& elementContent.toString().trim().length() > 0) {
       
   993 				val.setValue(elementContent.toString());
       
   994 				val.setRandom(false);
       
   995 				
       
   996 				if(incvalueforeachcopy != null && incvalueforeachcopy.equalsIgnoreCase(AbstractComponent.TRUE)){
       
   997 					//Setting value to null when its used.
       
   998 					val.setModeType(ModeTypes.ModeTypeIncValueForEachCopy);					
       
   999 					incvalueforeachcopy = null;
       
  1000 				}					
       
  1001 				
       
  1002 			}else if(val.isContactSetReference()){
       
  1003 				val.setRandom(false);//Contact set reference cannot be random
       
  1004 			}
       
  1005 			//Otherwise its a random
       
  1006 			else {
       
  1007 				if (randomType != ModeTypes.RandomTypeNotRandom) {
       
  1008 					val.setModeType(randomType);
       
  1009 					if(randomType == ModeTypes.RandomTypeUserDefinedLength){
       
  1010 						val.setRandomValueLenght(userDefinedRandomLen);
       
  1011 					}
       
  1012 				} else {
       
  1013 					val.setModeType(ModeTypes.RandomTypeDefaultLength);
       
  1014 				}
       
  1015 
       
  1016 			}
       
  1017 		}
       
  1018 
       
  1019 		/**
       
  1020 		 * Add a value to component
       
  1021 		 * @param val
       
  1022 		 * @param itemId
       
  1023 		 * @param items
       
  1024 		 */
       
  1025 		private void addValueToComponent(AbstractValue val, String itemId, Map<String, Vector<AbstractValue>> items) {
       
  1026 			Vector<AbstractValue> itemValues = items.get(itemId);
       
  1027 			if (itemValues == null) {
       
  1028 				// If this was a first item with this name, creating a new
       
  1029 				// Vector to store values
       
  1030 				itemValues = new Vector<AbstractValue>();
       
  1031 			}
       
  1032 			itemValues.add(val);
       
  1033 			//putting items bact to table
       
  1034 			items.put(itemId, itemValues);
       
  1035 		}
       
  1036 
       
  1037 		/* (non-Javadoc)
       
  1038 		 * @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
       
  1039 		 */
       
  1040 		public void characters(char ch[], int start, int length) {
       
  1041 			elementContent.write(ch, start, length);
       
  1042 		}
       
  1043 
       
  1044 		/**
       
  1045 		 * @return Errors String
       
  1046 		 */
       
  1047 		public String getErrors() {
       
  1048 			return errors.toString();
       
  1049 		}
       
  1050 
       
  1051 	}
       
  1052 
       
  1053 }