trace/traceviewer/com.nokia.trace.dictionary/src/com/nokia/trace/dictionary/model/handlers/DefHandler.java
changeset 11 5b9d4d8641ce
equal deleted inserted replaced
10:ed1c9f64298a 11:5b9d4d8641ce
       
     1 /*
       
     2  * Copyright (c) 2007-2010 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  * Def handler
       
    17  *
       
    18  */
       
    19 package com.nokia.trace.dictionary.model.handlers;
       
    20 
       
    21 import org.xml.sax.Attributes;
       
    22 
       
    23 import com.nokia.trace.dictionary.TraceDictionaryEngine;
       
    24 import com.nokia.trace.dictionary.model.DecodeObject;
       
    25 import com.nokia.trace.dictionary.model.DictionaryContentHandler;
       
    26 import com.nokia.trace.dictionary.model.DictionaryDecodeModel;
       
    27 import com.nokia.trace.dictionary.model.TraceData;
       
    28 import com.nokia.trace.dictionary.model.decodeparameters.ArrayParameter;
       
    29 import com.nokia.trace.dictionary.model.decodeparameters.ConstantParameter;
       
    30 import com.nokia.trace.dictionary.model.decodeparameters.DecodeParameter;
       
    31 import com.nokia.trace.dictionary.model.decodeparameters.HexParameter;
       
    32 import com.nokia.trace.dictionary.model.decodeparameters.IntegerParameter;
       
    33 import com.nokia.trace.eventrouter.TraceEvent;
       
    34 
       
    35 /**
       
    36  * Def handler
       
    37  */
       
    38 final class DefHandler extends BaseHandler {
       
    39 
       
    40 	/**
       
    41 	 * Tag name this handler handles
       
    42 	 */
       
    43 	private static final String DEF_TAG = "def"; //$NON-NLS-1$
       
    44 
       
    45 	/**
       
    46 	 * Bytes in block
       
    47 	 */
       
    48 	private int bytesInBlock;
       
    49 
       
    50 	/**
       
    51 	 * Constructor
       
    52 	 * 
       
    53 	 * @param model
       
    54 	 *            the model
       
    55 	 */
       
    56 	DefHandler(DictionaryDecodeModel model) {
       
    57 		super(model, DEF_TAG);
       
    58 	}
       
    59 
       
    60 	/*
       
    61 	 * (non-Javadoc)
       
    62 	 * 
       
    63 	 * @see com.nokia.trace.dictionary.model.handlers.BaseHandler#
       
    64 	 * processStartElement(org.xml.sax.Attributes,
       
    65 	 * com.nokia.trace.dictionary.model.DictionaryContentHandler)
       
    66 	 */
       
    67 	@Override
       
    68 	public void processStartElement(Attributes atts,
       
    69 			DictionaryContentHandler handler) {
       
    70 		TraceData traceData = new TraceData(
       
    71 				Integer.parseInt(atts.getValue(ID)), atts.getValue(TYPE));
       
    72 		handler.catchElementContents(traceData);
       
    73 	}
       
    74 
       
    75 	/*
       
    76 	 * (non-Javadoc)
       
    77 	 * 
       
    78 	 * @see
       
    79 	 * com.nokia.trace.dictionary.model.handlers.BaseHandler#processEndElement
       
    80 	 * (java.lang.StringBuffer, java.lang.Object,
       
    81 	 * com.nokia.trace.dictionary.model.DictionaryContentHandler,
       
    82 	 * com.nokia.trace.dictionary.model.DecodeObject)
       
    83 	 */
       
    84 	@Override
       
    85 	public void processEndElement(StringBuffer elementContent,
       
    86 			Object unFinishedObject, DictionaryContentHandler handler,
       
    87 			DecodeObject parentObject) {
       
    88 
       
    89 		TraceData traceData = (TraceData) unFinishedObject;
       
    90 
       
    91 		// Check if there is only one variable in the trace. If
       
    92 		// split has two parts, there is only one variable indicator
       
    93 		if (elementContent.toString().split(VARIABLE_INDICATOR).length <= 2) {
       
    94 			traceData.setContainsOnlyOneVariable(true);
       
    95 		}
       
    96 
       
    97 		int startOffset = 0;
       
    98 		int foundOffset = 0;
       
    99 		int endOffset = 0;
       
   100 
       
   101 		// Search all variables from the string
       
   102 		while ((foundOffset = elementContent.indexOf(VARIABLE_INDICATOR,
       
   103 				startOffset)) != -1) {
       
   104 			createConstantParameter(elementContent, traceData, startOffset,
       
   105 					foundOffset);
       
   106 
       
   107 			String parameterType;
       
   108 			StringBuilder digitsSB = new StringBuilder();
       
   109 			boolean isArray = false;
       
   110 
       
   111 			int nextCharOffset = foundOffset + 1;
       
   112 
       
   113 			// First gather all possible digits to variable. e.g. from %02x
       
   114 			// gather 02
       
   115 			char c = elementContent.charAt(nextCharOffset);
       
   116 			while (Character.isDigit(c)) {
       
   117 				digitsSB.append(c);
       
   118 				nextCharOffset++;
       
   119 				c = elementContent.charAt(nextCharOffset);
       
   120 			}
       
   121 
       
   122 			// Check if next char is {
       
   123 			if (c == START_BRACKET) {
       
   124 				// Find offset of char }
       
   125 				endOffset = elementContent.indexOf(Character
       
   126 						.toString(END_BRACKET), foundOffset) + 1;
       
   127 
       
   128 				// End offset was not found,let's change it to end of whole
       
   129 				// string to get some reasonable error message
       
   130 				if (endOffset == 0) {
       
   131 					endOffset = elementContent.length();
       
   132 				}
       
   133 
       
   134 				// Try to find array indicator characters
       
   135 				int indexOfBrackets = elementContent.indexOf(ARRAY_INDICATOR,
       
   136 						nextCharOffset);
       
   137 				// Indicator is found and is inside this parameter -> array
       
   138 				if (indexOfBrackets != -1
       
   139 						&& indexOfBrackets + ARRAY_INDICATOR.length() < endOffset) {
       
   140 					isArray = true;
       
   141 				}
       
   142 
       
   143 				// Parse from between
       
   144 				parameterType = elementContent.substring(nextCharOffset,
       
   145 						endOffset);
       
   146 
       
   147 				// Next char is not {, so it's a format char
       
   148 			} else {
       
   149 
       
   150 				// If the first char is L, l, or h, format char has 2 or 3 chars
       
   151 				if (c == FORMATCHAR_INDICATOR_BIG_L
       
   152 						|| c == FORMATCHAR_INDICATOR_SMALL_L
       
   153 						|| c == FORMATCHAR_INDICATOR_H) {
       
   154 					c = elementContent.charAt(nextCharOffset + 1);
       
   155 
       
   156 					// Next char is also h or l, format char is 3 chars
       
   157 					if (c == FORMATCHAR_INDICATOR_H
       
   158 							|| c == FORMATCHAR_INDICATOR_SMALL_L) {
       
   159 						parameterType = elementContent.substring(
       
   160 								nextCharOffset, nextCharOffset
       
   161 										+ LONG_FORMATCHAR_LENGTH + 1);
       
   162 						endOffset = nextCharOffset + LONG_FORMATCHAR_LENGTH + 1;
       
   163 
       
   164 						// Format char is 2 chars
       
   165 					} else {
       
   166 						parameterType = elementContent.substring(
       
   167 								nextCharOffset, nextCharOffset
       
   168 										+ LONG_FORMATCHAR_LENGTH);
       
   169 						endOffset = nextCharOffset + LONG_FORMATCHAR_LENGTH;
       
   170 					}
       
   171 
       
   172 					// Only 1 char
       
   173 				} else {
       
   174 					parameterType = elementContent.substring(nextCharOffset,
       
   175 							nextCharOffset + SHORT_FORMATCHAR_LENGTH);
       
   176 					endOffset = nextCharOffset + SHORT_FORMATCHAR_LENGTH;
       
   177 				}
       
   178 			}
       
   179 
       
   180 			DecodeParameter parameter;
       
   181 
       
   182 			// Array parameter
       
   183 			if (isArray) {
       
   184 				parameter = handleArray(traceData, parameterType, digitsSB
       
   185 						.toString());
       
   186 
       
   187 				// Normal parameter
       
   188 			} else {
       
   189 				parameter = getDecodeParameter(parameterType, digitsSB
       
   190 						.toString());
       
   191 
       
   192 				if (parameter != null) {
       
   193 					// Add possible fillers before this new parameter
       
   194 					addFillers(traceData, parameter.getSize());
       
   195 
       
   196 					// Add to the parameter list
       
   197 					traceData.addDecodeParameter(parameter);
       
   198 				}
       
   199 			}
       
   200 
       
   201 			// Parameter couldn't be found or created, inform user
       
   202 			if (parameter == null) {
       
   203 				postParameterNotFoundMsg(handler, parameterType);
       
   204 			}
       
   205 
       
   206 			// Set start offset to previous end offset
       
   207 			startOffset = endOffset;
       
   208 		} // while ends
       
   209 
       
   210 		// Create constant from the remaining
       
   211 		createConstantParameter(elementContent, traceData, startOffset,
       
   212 				elementContent.length());
       
   213 
       
   214 		// Add trace data to model
       
   215 		model.addTraceData(traceData);
       
   216 
       
   217 		// Null bytes in block value afterwards
       
   218 		bytesInBlock = 0;
       
   219 	}
       
   220 
       
   221 	/**
       
   222 	 * Handles array
       
   223 	 * 
       
   224 	 * @param traceData
       
   225 	 *            trace data
       
   226 	 * @param parameterType
       
   227 	 *            parameter type
       
   228 	 * @param digits
       
   229 	 * @return created parameter or null if cannot be created
       
   230 	 */
       
   231 	private DecodeParameter handleArray(TraceData traceData,
       
   232 			String parameterType, String digits) {
       
   233 		DecodeParameter parameter = null;
       
   234 
       
   235 		// Remove array indicator and try decode parameter again
       
   236 		String arrayContainsStr = parameterType.replace(ARRAY_INDICATOR, ""); //$NON-NLS-1$
       
   237 		DecodeParameter arrayContains = getDecodeParameter(arrayContainsStr,
       
   238 				digits);
       
   239 
       
   240 		// Basic type is found, create array parameter and add it
       
   241 		// also to the model and to the trace parameter list
       
   242 		if (arrayContains != null) {
       
   243 			parameter = new ArrayParameter(parameterType, false, arrayContains);
       
   244 
       
   245 			model.addDecodeParameter(parameter);
       
   246 			traceData.addDecodeParameter(parameter);
       
   247 		}
       
   248 
       
   249 		return parameter;
       
   250 	}
       
   251 
       
   252 	/**
       
   253 	 * Gets (either from model or creates new) decode parameter
       
   254 	 * 
       
   255 	 * @param parameterType
       
   256 	 *            parameter type to be get
       
   257 	 * @param digits
       
   258 	 *            possible format digits
       
   259 	 * @return found or new decode parameter or null if not found
       
   260 	 */
       
   261 	private DecodeParameter getDecodeParameter(String parameterType,
       
   262 			String digits) {
       
   263 		String parameterWithFormat = digits + parameterType;
       
   264 
       
   265 		// Find from parameter list using the possible formatting (e.g. %02)
       
   266 		DecodeParameter parameter = model
       
   267 				.getDecodeParameter(parameterWithFormat);
       
   268 
       
   269 		// Not found, try to find without the formatting
       
   270 		if (parameter == null) {
       
   271 			parameter = model.getDecodeParameter(parameterType);
       
   272 
       
   273 			// If found, we need to create new decode parameter with the
       
   274 			// formatting included
       
   275 			if (parameter != null) {
       
   276 				parameter = createNewFormatDecodeParameter(parameter,
       
   277 						parameterWithFormat, digits);
       
   278 			}
       
   279 		}
       
   280 
       
   281 		return parameter;
       
   282 	}
       
   283 
       
   284 	/**
       
   285 	 * Create new decode parameter with formatting
       
   286 	 * 
       
   287 	 * @param oldParameter
       
   288 	 *            old parameter
       
   289 	 * @param parameterWithFormat
       
   290 	 *            new parameter name
       
   291 	 * @param digits
       
   292 	 *            how should the parameter be formatted
       
   293 	 * @return new decode parameter
       
   294 	 */
       
   295 	private DecodeParameter createNewFormatDecodeParameter(
       
   296 			DecodeParameter oldParameter, String parameterWithFormat,
       
   297 			String digits) {
       
   298 		DecodeParameter newParameter = null;
       
   299 
       
   300 		// This is already checked with "isDigit()" so doesn't need try catch
       
   301 		int digit = Integer.parseInt(digits);
       
   302 
       
   303 		// Integer parameter
       
   304 		if (oldParameter instanceof IntegerParameter) {
       
   305 			newParameter = new IntegerParameter(parameterWithFormat, false,
       
   306 					oldParameter.getSize(), true);
       
   307 			((IntegerParameter) newParameter).setFormatToChars(digit);
       
   308 		}
       
   309 
       
   310 		// Hex parameter
       
   311 		else if (oldParameter instanceof HexParameter) {
       
   312 			newParameter = new HexParameter(parameterWithFormat, false,
       
   313 					oldParameter.getSize());
       
   314 			((HexParameter) newParameter)
       
   315 					.setPrintInUpperCase(((HexParameter) oldParameter)
       
   316 							.getPrintInUpperCase());
       
   317 			((HexParameter) newParameter).setFormatToChars(digit);
       
   318 		}
       
   319 
       
   320 		// Add to the parameter list
       
   321 		if (newParameter != null) {
       
   322 			model.addDecodeParameter(newParameter);
       
   323 		}
       
   324 
       
   325 		return newParameter;
       
   326 	}
       
   327 
       
   328 	/**
       
   329 	 * Posts parameter not found message to user
       
   330 	 * 
       
   331 	 * @param handler
       
   332 	 *            Dictionary handler
       
   333 	 * @param parameterType
       
   334 	 *            parameter type that is not found
       
   335 	 */
       
   336 	private void postParameterNotFoundMsg(DictionaryContentHandler handler,
       
   337 			String parameterType) {
       
   338 		String parameterNotFound = Messages
       
   339 				.getString("DefHandler.ParameterNotFoundMsg"); //$NON-NLS-1$
       
   340 		TraceEvent event = new TraceEvent(TraceEvent.ERROR, parameterNotFound
       
   341 				+ parameterType);
       
   342 		event.setCategory(EVENT_CATEGORY);
       
   343 		event.setSource(Integer.valueOf(handler.getLocator().getLineNumber()));
       
   344 		TraceDictionaryEngine.postEvent(event);
       
   345 	}
       
   346 
       
   347 	/**
       
   348 	 * Adds possible filler parameters to traceData
       
   349 	 * 
       
   350 	 * @param traceData
       
   351 	 *            traceData
       
   352 	 * @param paramSize
       
   353 	 *            size of the new item
       
   354 	 */
       
   355 	private void addFillers(TraceData traceData, int paramSize) {
       
   356 		// Parameters are aligned to 32 bits. Parameter after
       
   357 		// end-of-string is aligned dynamically and thus no filler is
       
   358 		// created for it
       
   359 		if (paramSize == 0 || paramSize == 4 || paramSize == 8) {
       
   360 			if (bytesInBlock > 0) {
       
   361 				int fillerCount = 4 - bytesInBlock;
       
   362 				for (int i = 0; i < fillerCount; i++) {
       
   363 					traceData.addDecodeParameter(model.getFillerParameter());
       
   364 				}
       
   365 				bytesInBlock = 0;
       
   366 			}
       
   367 		} else if (paramSize == 2) {
       
   368 			if (bytesInBlock == 1 || bytesInBlock == 3) {
       
   369 				traceData.addDecodeParameter(model.getFillerParameter());
       
   370 				// If there was 1 existing byte and filler was added,
       
   371 				// the number of bytes in the block is now 4 including
       
   372 				// the 2-byte parameter. If there was 3 bytes, the
       
   373 				// filler brings it to 4 and the 16-bit parameter
       
   374 				// changes it to 2
       
   375 				bytesInBlock += 3;
       
   376 			} else {
       
   377 				bytesInBlock += 2;
       
   378 			}
       
   379 			if (bytesInBlock >= 4) {
       
   380 				bytesInBlock -= 4;
       
   381 			}
       
   382 		} else {
       
   383 			bytesInBlock++;
       
   384 			if (bytesInBlock == 4) {
       
   385 				bytesInBlock = 0;
       
   386 			}
       
   387 		}
       
   388 	}
       
   389 
       
   390 	/**
       
   391 	 * Create constant parameter
       
   392 	 * 
       
   393 	 * @param elementContent
       
   394 	 *            buffer where data is
       
   395 	 * @param traceData
       
   396 	 *            TraceData where to insert this parameter
       
   397 	 * @param startOffset
       
   398 	 *            start offset from buffer
       
   399 	 * @param endOffset
       
   400 	 *            end offset from buffer
       
   401 	 */
       
   402 	private void createConstantParameter(StringBuffer elementContent,
       
   403 			TraceData traceData, int startOffset, int endOffset) {
       
   404 
       
   405 		// Remove line breaks from the buffer
       
   406 		int len = elementContent.length();
       
   407 		for (int i = 0; i < len; i++) {
       
   408 			char c = elementContent.charAt(i);
       
   409 			if (c == '\n' || c == '\r') {
       
   410 				elementContent.setCharAt(i, ' ');
       
   411 			}
       
   412 		}
       
   413 
       
   414 		// First create constant parameter
       
   415 		String constantPar = elementContent.substring(startOffset, endOffset);
       
   416 		if (constantPar.length() > 0) {
       
   417 			// Try to find from the list
       
   418 			ConstantParameter parameter = model
       
   419 					.getConstantParameter(constantPar);
       
   420 
       
   421 			// Couldn't be found
       
   422 			if (parameter == null) {
       
   423 				parameter = new ConstantParameter(constantPar, false);
       
   424 			}
       
   425 
       
   426 			// Add to lists
       
   427 			traceData.addDecodeParameter(parameter);
       
   428 			model.addConstantParameter(parameter);
       
   429 		}
       
   430 	}
       
   431 
       
   432 }