tracefw/tracecompiler/src/com.nokia.tracecompiler/src/com/nokia/tracecompiler/engine/TraceLocationConverter.java
changeset 56 aa2539c91954
parent 54 a151135b0cf9
child 60 e54443a6878c
child 62 1c2bb2fc7c87
equal deleted inserted replaced
54:a151135b0cf9 56:aa2539c91954
     1 /*
       
     2  * Copyright (c) 2008-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  * Location converter monitors locations and converts them to traces if necessary.
       
    17  *
       
    18  */
       
    19 package com.nokia.tracecompiler.engine;
       
    20 
       
    21 import java.io.*;
       
    22 import java.util.ArrayList;
       
    23 import java.util.HashMap;
       
    24 import java.util.Iterator;
       
    25 import java.util.Map;
       
    26 import java.util.Properties;
       
    27 
       
    28 import com.nokia.tracecompiler.TraceCompilerConstants;
       
    29 import com.nokia.tracecompiler.TraceCompilerLogger;
       
    30 import com.nokia.tracecompiler.engine.TraceCompilerEngineErrorCodes.TraceCompilerErrorCode;
       
    31 import com.nokia.tracecompiler.engine.project.ProjectConstants;
       
    32 import com.nokia.tracecompiler.engine.project.ProjectEngine;
       
    33 import com.nokia.tracecompiler.engine.project.SortedProperties;
       
    34 import com.nokia.tracecompiler.engine.project.TraceIDCache;
       
    35 import com.nokia.tracecompiler.engine.rules.PerformanceEventRuleBase;
       
    36 import com.nokia.tracecompiler.engine.rules.StateTraceRule;
       
    37 import com.nokia.tracecompiler.engine.source.SourceParserRule;
       
    38 import com.nokia.tracecompiler.engine.source.SourceProperties;
       
    39 import com.nokia.tracecompiler.engine.source.SourceParserRule.ParameterConversionResult;
       
    40 import com.nokia.tracecompiler.engine.source.SourceParserRule.TraceConversionResult;
       
    41 import com.nokia.tracecompiler.model.Trace;
       
    42 import com.nokia.tracecompiler.model.TraceCompilerException;
       
    43 import com.nokia.tracecompiler.model.TraceGroup;
       
    44 import com.nokia.tracecompiler.model.TraceModel;
       
    45 import com.nokia.tracecompiler.model.TraceModelExtension;
       
    46 import com.nokia.tracecompiler.model.TraceModelPersistentExtension;
       
    47 import com.nokia.tracecompiler.model.TraceParameter;
       
    48 import com.nokia.tracecompiler.project.FormattingUtils;
       
    49 import com.nokia.tracecompiler.project.GroupNames;
       
    50 import com.nokia.tracecompiler.project.ProjectUtils;
       
    51 import com.nokia.tracecompiler.source.SourceConstants;
       
    52 
       
    53 /**
       
    54  * Location converter monitors locations and converts them to traces if
       
    55  * necessary.
       
    56  * 
       
    57  */
       
    58 public final class TraceLocationConverter {
       
    59 
       
    60 	/**
       
    61 	 * Number of deprecated groups
       
    62 	 */
       
    63 	final static int NUMBER_OF_DEPRECATED_GROUPS = 3;
       
    64 
       
    65 	/**
       
    66 	 * Deprecated group name map
       
    67 	 */
       
    68 	Map<String, String> deprecatedGroupNameMap = new HashMap<String, String>(
       
    69 			NUMBER_OF_DEPRECATED_GROUPS);
       
    70 
       
    71 	/**
       
    72 	 * Trace model
       
    73 	 */
       
    74 	private TraceModel model;
       
    75 
       
    76 	/**
       
    77 	 * Constructor
       
    78 	 * 
       
    79 	 * @param model
       
    80 	 *            the trace model
       
    81 	 */
       
    82 	TraceLocationConverter(TraceModel model) {
       
    83 		this.model = model;
       
    84 		initializeDeprecatedGroupNameMap();
       
    85 	}
       
    86 
       
    87 	/**
       
    88 	 * Initialize deprecated group name map
       
    89 	 */
       
    90 	private void initializeDeprecatedGroupNameMap() {
       
    91 		deprecatedGroupNameMap.put(GroupNames.TRACE_API,
       
    92 				GroupNames.TRACE_BORDER);
       
    93 		deprecatedGroupNameMap.put(GroupNames.TRACE_DEBUG,
       
    94 				GroupNames.TRACE_DUMP);
       
    95 		deprecatedGroupNameMap.put(GroupNames.TRACE_DETAILED,
       
    96 				GroupNames.TRACE_INTERNALS);
       
    97 	}
       
    98 
       
    99 	/**
       
   100 	 * Source opened notification
       
   101 	 * 
       
   102 	 * @param properties
       
   103 	 *            the source properties
       
   104 	 * @throws TraceCompilerException 
       
   105 	 */
       
   106 	void sourceOpened(SourceProperties properties) throws TraceCompilerException {
       
   107 		//make sure all errors are reported AFTER processing a file
       
   108 		TraceCompilerEngineGlobals.getSourceContextManager()
       
   109 				.setConverting(true);
       
   110 		model.startProcessing();
       
   111 		try {
       
   112 			// Load fixed group and trace ids from definition file to model
       
   113 			//no errors are reported here 
       
   114 			if (model.getFixedIds() == null) {
       
   115 				loadFixedIdsFromDefinitionFileToModel();
       
   116 			}
       
   117 
       
   118 			for (TraceLocation loc : properties) {
       
   119 				autoConvertLocation(loc);
       
   120 			}
       
   121 			// If there are duplicates or unused traces, they are removed
       
   122 			// Note that this will work across source files although this
       
   123 			// function is processing only one file.
       
   124 			// If a trace is created, all locations from all open source files
       
   125 			// are linked to that trace and thus it will be removed as
       
   126 			// duplicate.
       
   127 			removeDuplicateTraces();
       
   128 
       
   129 		} finally {
       
   130 			model.processingComplete();
       
   131 			SourceContextManager manager = TraceCompilerEngineGlobals
       
   132 					.getSourceContextManager();
       
   133 			manager.setConverting(false);
       
   134 			manager.setContext(null);
       
   135 		}
       
   136 	}
       
   137 
       
   138 	/**
       
   139 	 * Load fixed Ids from definiton file to properties
       
   140 	 * 
       
   141 	 */
       
   142 	private void loadFixedIdsFromDefinitionFileToModel() {
       
   143 		TraceIDCache cache = model.getExtension(TraceIDCache.class);
       
   144 
       
   145 		// Create trace Id cache if it does not exist
       
   146 		try {
       
   147 			if (cache == null) {
       
   148 				String path;
       
   149 				path = ProjectUtils.getLocationForFile(model,
       
   150 						ProjectEngine.traceFolderName,
       
   151 						ProjectConstants.FIXED_ID_DEFINITIONS_FILE_NAME, false);
       
   152 				if (path != null) {
       
   153 					cache = new TraceIDCache(new File(path).getParent());
       
   154 					model.addExtension(cache);
       
   155 				}
       
   156 			}
       
   157 			if (cache != null) {
       
   158 				File cacheFile = new File(cache.getAbsolutePath());
       
   159 				// Try to load Ids from trace Id cache file
       
   160 				try {
       
   161 					SortedProperties fixedIds = new SortedProperties();
       
   162 					if (cacheFile.exists()) {
       
   163 						String thisLine;
       
   164 						boolean allOldFixedIdsAreValid = true;
       
   165 						String group = model.GROUP_PROPERTY_PREFIX;
       
   166 						FileInputStream fis = new FileInputStream(cacheFile);
       
   167 						BufferedReader myInput = new BufferedReader(
       
   168 								new InputStreamReader(fis));
       
   169 						// Read the old fixed id definition file
       
   170 						while ((thisLine = myInput.readLine()) != null) {
       
   171 							if (thisLine.indexOf(group) != -1) {
       
   172 								thisLine = thisLine.substring(group.length(),
       
   173 										thisLine.length());
       
   174 								if (!searchForOldGroupIds(thisLine)) {						
       
   175 									String msg  = Messages.getString("TraceLocationConverter.GroupIdValueError"); //$NON-NLS-1$
       
   176 									TraceCompilerEngineGlobals.getEvents().postWarningMessage(msg, null);
       
   177 									// We need only one old invalid id to make all of them invalid
       
   178 									allOldFixedIdsAreValid = false;
       
   179 									break;
       
   180 								}
       
   181 							}
       
   182 						}
       
   183 						fis.close();
       
   184 						
       
   185 						if (allOldFixedIdsAreValid) {
       
   186 							// Create file input stream again
       
   187 							FileInputStream newFis = new FileInputStream(cacheFile);
       
   188 							fixedIds.load(newFis);
       
   189 							// Load fixed Ids from properties to model
       
   190 							model.setFixedIds(fixedIds);
       
   191 							newFis.close();
       
   192 						}
       
   193 						
       
   194 					}
       
   195 				} catch (IOException e) {
       
   196 					// If there is a problem with the cache file, just delete it
       
   197 					// make sure the model fixed ids is null
       
   198 					model.setFixedIds(null);
       
   199 					cacheFile.delete();
       
   200 					// We do not raise an exception but we need to report a info
       
   201 					TraceCompilerLogger.printWarning(Messages.getString("TraceLocationConverter.FixedIdProblemWarningBeginText") + cacheFile.toString() + Messages.getString("TraceLocationConverter.FixedIdProblemWarningMiddleText") + e.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
       
   202 				}
       
   203 			}
       
   204 		} catch (TraceCompilerException e) {
       
   205 			// This exception can probably be ignored
       
   206 			TraceCompilerLogger.printWarning("Could not create ID cache : " + e.getMessage()); //$NON-NLS-1$
       
   207 		}
       
   208 	}
       
   209 
       
   210 	/**
       
   211 	 * Searches the fixed_id file to see if there are any old definitions
       
   212 	 * 
       
   213 	 * @param string
       
   214 	 *            of text from the fixed_id files
       
   215 	 * @return boolean 
       
   216 	 */
       
   217 	public static boolean searchForOldGroupIds(String str) {
       
   218 		
       
   219 		boolean oldGroupIdValid = true;
       
   220 
       
   221 		//get group name from the string
       
   222 		int index = str.indexOf(SourceConstants.ASSIGN_WITH_OUT_SPACES);
       
   223 		if (index == -1) {
       
   224 			//not valid string, so ignore it, just return success
       
   225 			return true;
       
   226 		}
       
   227 
       
   228 		String groupName = str.substring(0, index);
       
   229 
       
   230 		//get group id
       
   231 		str = str.substring(str.indexOf(SourceConstants.HEX_PREFIX) + 2, str
       
   232 				.length());
       
   233 
       
   234 		int groupId = -1;
       
   235 
       
   236 		try {
       
   237 			groupId = Integer.parseInt(str.trim(),
       
   238 					TraceCompilerConstants.HEX_RADIX);
       
   239 		} catch (NumberFormatException e) {
       
   240 			//it's not an hex number so fail
       
   241 			oldGroupIdValid = false;
       
   242 		}
       
   243 
       
   244 		//get group id from ost header file
       
   245 		int fileGroupId = GroupNames.getIdByName(groupName);
       
   246 
       
   247 		if (fileGroupId != 0) {
       
   248 			//found 1
       
   249 			if (fileGroupId != groupId) //group id has changed, so old one can't be used
       
   250 				oldGroupIdValid = false;
       
   251 		} else {
       
   252 			if ((GroupNames.USER_GROUP_ID_FIRST > groupId)
       
   253 					|| (groupId > GroupNames.USER_GROUP_ID_LAST)) //not within new user defined Ids
       
   254 				oldGroupIdValid = false;
       
   255 		}
       
   256 
       
   257 		return oldGroupIdValid;
       
   258 	}
       
   259 
       
   260 	/**
       
   261 	 * Converts the given location to trace if parser supports auto-conversion
       
   262 	 * 
       
   263 	 * @param location
       
   264 	 *            the location
       
   265 	 */
       
   266 	private void autoConvertLocation(TraceLocation location) {
       
   267 		// Stores the context of the location to the context manager.
       
   268 		TraceCompilerEngineGlobals.getSourceContextManager().setContext(
       
   269 				location.getParser().getContext(location.getOffset()));
       
   270 		Trace trace = location.getTrace();
       
   271 		if (trace == null) {
       
   272 			// If the trace does not exist, the parser determines if the
       
   273 			// location can be converted
       
   274 			if (location.getParserRule().getLocationParser()
       
   275 					.isLocationConverted(location)) {
       
   276 				try {
       
   277 					convertLocation(location, null, true);
       
   278 				} catch (TraceCompilerException e) {
       
   279 					// If converter fails, the error code is stored into the
       
   280 					// location. The location notifies all validity listeners
       
   281 					// about the change
       
   282 					location.setConverterErrorCode((TraceCompilerErrorCode) e
       
   283 							.getErrorCode(), e.getErrorParameters());
       
   284 				}
       
   285 			}
       
   286 		} else {
       
   287 			// If the trace already exists in the model, it is updated
       
   288 			// based on the source file contents
       
   289 			updateLocation(location);
       
   290 		}
       
   291 	}
       
   292 
       
   293 	/**
       
   294 	 * Recreates the trace from changed location when source is saved
       
   295 	 * 
       
   296 	 * @param location
       
   297 	 *            the location to be checked
       
   298 	 */
       
   299 	private void updateLocation(TraceLocation location) {
       
   300 		// Parser determines if the location can be converted
       
   301 		if (location.getParserRule().getLocationParser().isLocationConverted(
       
   302 				location)) {
       
   303 			try {
       
   304 				Trace trace = location.getTrace();
       
   305 				// If a location has changed, the old trace is removed
       
   306 				// and a new one created. Persistent extensions are moved to the
       
   307 				// new trace
       
   308 				Iterator<TraceModelPersistentExtension> extensions = null;
       
   309 				if (trace != null) {
       
   310 					extensions = trace
       
   311 							.getExtensions(TraceModelPersistentExtension.class);
       
   312 					trace.getGroup().removeTrace(trace);
       
   313 				}
       
   314 				convertLocation(location, extensions, true);
       
   315 
       
   316 				// Check that the location is inside a function. Otherwise throw
       
   317 				// an error because the code is unreachable
       
   318 				if (location.getFunctionName() == null) {
       
   319 					throw new TraceCompilerException(
       
   320 							TraceCompilerErrorCode.UNREACHABLE_TRACE_LOCATION);
       
   321 				}
       
   322 
       
   323 			} catch (TraceCompilerException e) {
       
   324 				// If converter fails, the error code is stored into the
       
   325 				// location. The location notifies all validity listeners about
       
   326 				// the change
       
   327 				location.setConverterErrorCode((TraceCompilerErrorCode) e
       
   328 						.getErrorCode(), e.getErrorParameters());
       
   329 			}
       
   330 		}
       
   331 	}
       
   332 
       
   333 	/**
       
   334 	 * Removes all duplicate traces from the model
       
   335 	 * @throws TraceCompilerException 
       
   336 	 */
       
   337 	private void removeDuplicateTraces() throws TraceCompilerException {
       
   338 		boolean groupRemoved = true;
       
   339 		while (groupRemoved) {
       
   340 			groupRemoved = false;
       
   341 			for (TraceGroup group : model) {
       
   342 				removeDuplicateTracesFromGroup(group);
       
   343 				if (!group.hasTraces()) {
       
   344 					model.removeGroup(group);
       
   345 					groupRemoved = true;
       
   346 					break;
       
   347 				}
       
   348 			}
       
   349 		}
       
   350 	}
       
   351 
       
   352 	/**
       
   353 	 * Removes duplicate traces from a trace group
       
   354 	 * 
       
   355 	 * @param group
       
   356 	 *            the group
       
   357 	 * @throws TraceCompilerException 
       
   358 	 */
       
   359 	private void removeDuplicateTracesFromGroup(TraceGroup group) throws TraceCompilerException {
       
   360 		boolean traceRemoved = true;
       
   361 		while (traceRemoved) {
       
   362 			traceRemoved = false;
       
   363 			for (Trace trace : group) {
       
   364 				TraceLocationList list = trace
       
   365 						.getExtension(TraceLocationList.class);
       
   366 				if (list != null) {
       
   367 					if (list.getLocationCount() > 1) {
       
   368 						// All the locations are marked as duplicates and the
       
   369 						// trace is deleted
       
   370 						TraceCompilerErrorCode code = TraceCompilerErrorCode.TRACE_HAS_MULTIPLE_LOCATIONS;
       
   371 						for (LocationProperties loc : list) {
       
   372 							((TraceLocation) loc).setConverterErrorCode(code,
       
   373 									null);
       
   374 						}
       
   375 						group.removeTrace(trace);
       
   376 						traceRemoved = true;
       
   377 						break;
       
   378 					}
       
   379 				}
       
   380 			}
       
   381 		}
       
   382 	}
       
   383 
       
   384 	/**
       
   385 	 * Converts a location to a Trace object.
       
   386 	 * 
       
   387 	 * @param location
       
   388 	 *            the location to be converted
       
   389 	 * @param extensions
       
   390 	 *            persistent extensions to be added to the new trace
       
   391 	 * @param autoConvert
       
   392 	 *            true if converting without user interaction
       
   393 	 * @return the new trace
       
   394 	 * @throws TraceCompilerException
       
   395 	 *             if conversion fails
       
   396 	 */
       
   397 	private Trace convertLocation(TraceLocation location,
       
   398 			Iterator<TraceModelPersistentExtension> extensions,
       
   399 			boolean autoConvert) throws TraceCompilerException {
       
   400 		Trace trace = null;
       
   401 		// If the parser has failed, the validity code is not OK and the
       
   402 		// location cannot be converted. Traces marked with no-trace error code
       
   403 		// have not yet been converted, so that is OK. Traces that have
       
   404 		// duplicate ID's error code can be parsed, since the duplicates might
       
   405 		// no longer exist.
       
   406 		if (!autoConvert
       
   407 				|| location.getValidityCode() == TraceCompilerErrorCode.OK
       
   408 				|| location.getValidityCode() == TraceCompilerErrorCode.TRACE_DOES_NOT_EXIST
       
   409 				|| location.getValidityCode() == TraceCompilerErrorCode.TRACE_HAS_MULTIPLE_LOCATIONS) {
       
   410 			// The parser does the actual conversion
       
   411 			SourceParserRule rule = location.getParserRule();
       
   412 			TraceConversionResult result = rule.getLocationParser()
       
   413 					.convertLocation(location);
       
   414 			// After parser has finished, the trace is created.
       
   415 			trace = convertWithoutUI(result, extensions);
       
   416 
       
   417 			if (trace != null) {
       
   418 				model.startProcessing();
       
   419 				try {
       
   420 					createParametersFromConversionResult(location, result,
       
   421 							trace);
       
   422 					// Runs a location validity check and notifies listeners
       
   423 					// that location is now OK
       
   424 					location.setConverterErrorCode(TraceCompilerErrorCode.OK,
       
   425 							null);
       
   426 				} catch (TraceCompilerException e) {
       
   427 					// If parameters cannot be created, the trace is removed
       
   428 					TraceGroup group = trace.getGroup();
       
   429 					trace.getGroup().removeTrace(trace);
       
   430 					if (!group.hasTraces()) {
       
   431 						group.getModel().removeGroup(group);
       
   432 					}
       
   433 					throw e;
       
   434 				} finally {
       
   435 					model.processingComplete();
       
   436 				}
       
   437 			}
       
   438 		}
       
   439 		return trace;
       
   440 	}
       
   441 
       
   442 	/**
       
   443 	 * Converts a location to trace without UI
       
   444 	 * 
       
   445 	 * @param result
       
   446 	 *            the conversion result from parser
       
   447 	 * @param extensions
       
   448 	 *            persistent extensions to be added to the new trace
       
   449 	 * @return the converted trace
       
   450 	 * @throws TraceCompilerException
       
   451 	 *             if location properties are not valid
       
   452 	 */
       
   453 	private Trace convertWithoutUI(TraceConversionResult result,
       
   454 			Iterator<TraceModelPersistentExtension> extensions)
       
   455 			throws TraceCompilerException {
       
   456 		Trace trace = null;
       
   457 		if (result.group != null) {
       
   458 			String groupName = result.group;
       
   459 			TraceGroup group = handleGroup(groupName);
       
   460 			trace = handleTrace(result, extensions, group);
       
   461 		} else {
       
   462 			throw new TraceCompilerException(
       
   463 					TraceCompilerErrorCode.GROUP_NOT_SELECTED);
       
   464 		}
       
   465 		return trace;
       
   466 	}
       
   467 
       
   468 	/**
       
   469 	 * Handle trace
       
   470 	 * 
       
   471 	 * @param result
       
   472 	 *            the conversion result from parser
       
   473 	 * @param extensions
       
   474 	 *            persistent extensions to be added to the new trace
       
   475 	 * @param group
       
   476 	 *            the group where trace belongs to
       
   477 	 * @return the trace
       
   478 	 * @throws TraceCompilerException
       
   479 	 */
       
   480 	private Trace handleTrace(TraceConversionResult result,
       
   481 			Iterator<TraceModelPersistentExtension> extensions, TraceGroup group)
       
   482 			throws TraceCompilerException {
       
   483 		// First try to find Id to trace from fixed Ids
       
   484 		Trace trace = null;
       
   485 		Properties fixedIds = model.getFixedIds();
       
   486 		String groupName = result.group;
       
   487 		String traceName = result.name;
       
   488 		int groupId = group.getID();
       
   489 		String groupIdString = SourceConstants.HEX_PREFIX
       
   490 				+ Integer.toString(groupId, model.HEX_RADIX).toUpperCase();
       
   491 		int traceId = 0;
       
   492 		if (fixedIds != null) {
       
   493 			String tracePropertyName = groupName + model.GROUP_ID_PREFIX
       
   494 					+ groupIdString + model.GROUP_ID_SUFFIX
       
   495 					+ SourceConstants.UNDERSCORE + traceName;
       
   496 			String value = fixedIds.getProperty(model.TRACE_PROPERTY_PREFIX
       
   497 					+ tracePropertyName);
       
   498 			if (value != null) {
       
   499 				try {
       
   500 					traceId = Integer.decode(value).intValue();
       
   501 				} catch (NumberFormatException e) {
       
   502 					// Corrupted, assign a proper Id later on
       
   503 					traceId = 0;
       
   504 				}
       
   505 			}
       
   506 		}
       
   507 		// If there was no fixed Id to this trace, get Id from model
       
   508 		if (traceId == 0) {
       
   509 			traceId = model.getNextTraceId(group);
       
   510 		}
       
   511 
       
   512 		String text = result.text;
       
   513 		model.getVerifier().checkTraceProperties(group, null, traceId,
       
   514 				traceName, text);
       
   515 		TraceModelExtension[] extArray = createExtensionArray(result,
       
   516 				extensions);
       
   517 		trace = model.getFactory().createTrace(group, traceId, traceName, text,
       
   518 				extArray);
       
   519 
       
   520 		if ((trace.getExtension(StateTraceRule.class) == null)
       
   521 				&& (group.getName()
       
   522 						.equals("TRACE_STATE"))) { //$NON-NLS-1$
       
   523 			throw new TraceCompilerException(
       
   524 					TraceCompilerErrorCode.INVALID_USAGE_OF_TRACE_STATE_GROUP_NAME);
       
   525 		} else if ((trace.getExtension(PerformanceEventRuleBase.class) == null)
       
   526 				&& (group.getName()
       
   527 						.equals("TRACE_PERFORMANCE"))) { //$NON-NLS-1$
       
   528 			throw new TraceCompilerException(
       
   529 					TraceCompilerErrorCode.INVALID_USAGE_OF_TRACE_PERFORMACE_GROUP_NAME);
       
   530 		}
       
   531 
       
   532 		return trace;
       
   533 	}
       
   534 
       
   535 	/**
       
   536 	 * Handle group. Try to fnd group from model. If it does not exist then
       
   537 	 * create new group.
       
   538 	 * 
       
   539 	 * @param groupName
       
   540 	 *            the name of the group
       
   541 	 * @return the handled group
       
   542 	 * @throws TraceCompilerException
       
   543 	 */
       
   544 	private TraceGroup handleGroup(String groupName)
       
   545 			throws TraceCompilerException {
       
   546 		String deprecatedGroupName = null;
       
   547 		
       
   548 		// Convert deprecated group name to valid group name if needed
       
   549 		if (deprecatedGroupNameMap.containsKey(groupName)) {
       
   550 			deprecatedGroupName = groupName;
       
   551 			groupName = deprecatedGroupNameMap.get(groupName);
       
   552 		}
       
   553 
       
   554 		// If auto-convert flag is set, the location is converted without
       
   555 		// user interaction. A new trace group is created if not found
       
   556 		TraceGroup group = model.findGroupByName(groupName);
       
   557 		if (group == null) {
       
   558 			
       
   559 			// Print warning related to deprecated group name change if needed
       
   560 			if (deprecatedGroupName != null) {
       
   561 				String message = Messages
       
   562 						.getString("TraceLocationConverter.DeprecatedGroupIdWarningStart");//$NON-NLS-1$
       
   563 				message += SourceConstants.SPACE + deprecatedGroupName
       
   564 						+ SourceConstants.SPACE;
       
   565 				message += Messages
       
   566 						.getString("TraceLocationConverter.DeprecatedGroupIdWarningMiddle");//$NON-NLS-1$
       
   567 				message += SourceConstants.SPACE + groupName
       
   568 						+ SourceConstants.SPACE;
       
   569 				message += Messages
       
   570 						.getString("TraceLocationConverter.DeprecatedGroupIdWarningEnd");//$NON-NLS-1$
       
   571 				TraceCompilerLogger.printWarning(message);
       
   572 			}
       
   573 
       
   574 			int groupId = 0;
       
   575 			Properties fixedIds = model.getFixedIds();
       
   576 
       
   577 			// First try to find Id to group from fixed Ids
       
   578 			if (fixedIds != null) {
       
   579 				String value = fixedIds.getProperty(model.GROUP_PROPERTY_PREFIX
       
   580 						+ groupName);
       
   581 				if (value != null) {
       
   582 					try {
       
   583 						groupId = Integer.decode(value).intValue();
       
   584 					} catch (NumberFormatException e) {
       
   585 						// Corrupted, assign a proper Id later on
       
   586 						groupId = 0;
       
   587 					}
       
   588 				}
       
   589 			}
       
   590 			// If there was no fixed Id to this group, get Id from model
       
   591 			if (groupId == 0) {
       
   592 				groupId = FormattingUtils.getGroupID(model, groupName);
       
   593 			}
       
   594 			model.getVerifier().checkTraceGroupProperties(model, null, groupId,
       
   595 					groupName);
       
   596 			group = model.getFactory().createTraceGroup(groupId, groupName,
       
   597 					null);
       
   598 		}
       
   599 
       
   600 		return group;
       
   601 	}
       
   602 
       
   603 	/**
       
   604 	 * Combines extensions into one array
       
   605 	 * 
       
   606 	 * @param result
       
   607 	 *            the conversion result
       
   608 	 * @param extensions
       
   609 	 *            the persistent extensions from old trace
       
   610 	 * @return the combined array of extensions
       
   611 	 */
       
   612 	private TraceModelExtension[] createExtensionArray(
       
   613 			TraceConversionResult result,
       
   614 			Iterator<TraceModelPersistentExtension> extensions) {
       
   615 		TraceModelExtension[] extArray = null;
       
   616 		ArrayList<TraceModelExtension> ext = null;
       
   617 		if (result.extensions != null) {
       
   618 			ext = new ArrayList<TraceModelExtension>();
       
   619 			ext.addAll(result.extensions);
       
   620 		}
       
   621 		if (extensions != null) {
       
   622 			if (ext == null) {
       
   623 				ext = new ArrayList<TraceModelExtension>();
       
   624 			}
       
   625 			while (extensions.hasNext()) {
       
   626 				ext.add(extensions.next());
       
   627 			}
       
   628 		}
       
   629 		if (ext != null) {
       
   630 			extArray = new TraceModelExtension[ext.size()];
       
   631 			ext.toArray(extArray);
       
   632 		}
       
   633 		return extArray;
       
   634 	}
       
   635 
       
   636 	/**
       
   637 	 * Creates the trace parameters based on trace conversion result
       
   638 	 * 
       
   639 	 * @param converted
       
   640 	 *            the location that was converted
       
   641 	 * @param result
       
   642 	 *            the conversion result
       
   643 	 * @param trace
       
   644 	 *            the trace
       
   645 	 * @throws TraceCompilerException
       
   646 	 *             if parameters cannot be created
       
   647 	 */
       
   648 	private void createParametersFromConversionResult(TraceLocation converted,
       
   649 			TraceConversionResult result, Trace trace)
       
   650 			throws TraceCompilerException {
       
   651 		if (result.parameters != null) {
       
   652 			for (int i = 0; i < result.parameters.size(); i++) {
       
   653 				int id = trace.getNextParameterID();
       
   654 				ParameterConversionResult res = result.parameters.get(i);
       
   655 				boolean warning = false;
       
   656 				if (res.type == null) {
       
   657 					warning = true;
       
   658 					res.type = TraceParameter.HEX32;
       
   659 				}
       
   660 				model.getVerifier().checkTraceParameterProperties(trace, null,
       
   661 						id, res.name, res.type);
       
   662 				TraceModelExtension[] extArray = null;
       
   663 				if (res.extensions != null) {
       
   664 					extArray = new TraceModelExtension[res.extensions.size()];
       
   665 					res.extensions.toArray(extArray);
       
   666 				}
       
   667 				TraceParameter param = model.getFactory().createTraceParameter(
       
   668 						trace, id, res.name, res.type, extArray);
       
   669 				if (warning) {
       
   670 					String msg = Messages
       
   671 							.getString("TraceCompiler.UnknownTypeWarning"); //$NON-NLS-1$
       
   672 					TraceCompilerEngineGlobals.getEvents().postWarningMessage(
       
   673 							msg, param);
       
   674 				}
       
   675 			}
       
   676 		}
       
   677 	}
       
   678 
       
   679 }