trace/tracebuilder/com.nokia.tracebuilder/src/com/nokia/tracebuilder/engine/rules/SourceParserRuleBase.java
author Jussi Ryoma <ext-jussi.s.ryoma@nokia.com>
Tue, 24 Aug 2010 14:01:48 +0300
changeset 16 72f198be1c1d
parent 10 ed1c9f64298a
permissions -rw-r--r--
Crash Analyser Carbide Extension 1.4.0

/*
* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). 
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
* Implementation of parser rule
*
*/
package com.nokia.tracebuilder.engine.rules;

import java.util.ArrayList;
import java.util.Iterator;

import com.nokia.tracebuilder.engine.TraceLocation;
import com.nokia.tracebuilder.engine.TraceBuilderErrorCodes.TraceBuilderErrorCode;
import com.nokia.tracebuilder.engine.source.SourceParserRule;
import com.nokia.tracebuilder.engine.utils.TraceUtils;
import com.nokia.tracebuilder.model.Trace;
import com.nokia.tracebuilder.model.TraceBuilderException;
import com.nokia.tracebuilder.model.TraceGroup;
import com.nokia.tracebuilder.model.TraceModelExtension;
import com.nokia.tracebuilder.project.TraceLocationParser;
import com.nokia.tracebuilder.project.TraceProjectAPI;
import com.nokia.tracebuilder.source.FormatMapping;
import com.nokia.tracebuilder.source.SourceExcludedArea;
import com.nokia.tracebuilder.source.SourceIterator;
import com.nokia.tracebuilder.source.SourceParser;
import com.nokia.tracebuilder.source.SourceParserException;

/**
 * Base class for parser rules. Instances of this class are added to the trace
 * model. The source engine uses the parses it finds from the model to find
 * trace locations from source files
 * 
 */
public abstract class SourceParserRuleBase extends RuleBase implements
		SourceParserRule, TraceLocationParser {

	/**
	 * Length of line comment tag "// "
	 */
	private static final int LINE_COMMENT_TAG_LENGTH = 3; // CodForChk_Dis_Magic

	/**
	 * Tag to be searched from source
	 */
	private String tag;

	/**
	 * Allowed tag suffixes
	 */
	private ArrayList<String> tagSuffixes = new ArrayList<String>();

	/**
	 * Constructor
	 * 
	 * @param tag
	 *            the tag to be searched from source
	 * @param tagSuffixes
	 *            the list of allowed suffixes to the tag
	 */
	protected SourceParserRuleBase(String tag, String[] tagSuffixes) {
		this.tag = tag;
		// Adds the sub-formats to the parsers
		if (tagSuffixes != null) {
			int len = tagSuffixes.length;
			for (int i = 0; i < len; i++) {
				this.tagSuffixes.add(tagSuffixes[i]);
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.nokia.tracebuilder.engine.source.SourceParserRule#getSearchTag()
	 */
	public String getSearchTag() {
		return tag;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.nokia.tracebuilder.engine.source.SourceParserRule#
	 *      isAllowedTagSuffix(java.lang.String)
	 */
	public boolean isAllowedTagSuffix(String tag) {
		boolean retval = false;
		if (tag != null) {
			if (tag.length() == 0 && tagSuffixes.isEmpty()) {
				retval = true;
			} else {
				for (int i = 0; i < tagSuffixes.size() && !retval; i++) {
					String s = tagSuffixes.get(i);
					if (s.length() == tag.length()) {
						retval = true;
						for (int j = 0; j < s.length() && retval; j++) {
							char c1 = s.charAt(j);
							// '?' can be any character
							if (c1 != '?') {
								retval = tag.charAt(j) == c1;
							}
						}
					}
				}
			}
		}
		return retval;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.nokia.tracebuilder.engine.source.SourceParserRule#
	 *      processNewLocation(com.nokia.tracebuilder.engine.TraceLocation)
	 */
	public void processNewLocation(TraceLocation location) {
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.nokia.tracebuilder.project.TraceLocationParser#getLocationGroup()
	 */
	public String getLocationGroup() {
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.nokia.tracebuilder.engine.source.SourceParserRule#
	 *      convertLocation(com.nokia.tracebuilder.engine.TraceLocation)
	 */
	public TraceConversionResult convertLocation(TraceLocation location)
			throws TraceBuilderException {
		// If converting an unrelated location to trace, the name
		// from the location is used
		TraceConversionResult result = new TraceConversionResult();
		result.name = location.getConvertedName();
		// Old Symbian traces could include comment associated with the location
		// If it exists, it will be used as text
		String listTitle = location.getLocationList().getListTitle();
		if (listTitle != null && listTitle.equals("SymbianTrace")) { //$NON-NLS-1$
			SourceExcludedArea excludedArea = findLocationComment(location);
			if (excludedArea != null
					&& excludedArea.getType() == SourceExcludedArea.LINE_COMMENT) {
				// This expects the %FORMATTED_TRACE% formatting
				// Removes the '// ' from the comment
				SourceParser parser = location.getParser();
				String comment = parser.getData(excludedArea.getOffset()
						+ LINE_COMMENT_TAG_LENGTH, excludedArea.getLength()
						- LINE_COMMENT_TAG_LENGTH);
				Iterator<TraceGroup> groups = getOwner().getModel().getGroups();
				if (groups.hasNext()) {
					result.group = groups.next().getName();
				}
				result.text = comment.trim();
			}			
		}
		Iterator<String> params = location.getParameters();
		if (params.hasNext()) {
			result.parameters = new ArrayList<ParameterConversionResult>();
			while (params.hasNext()) {
				String label = params.next();
				ParameterConversionResult res = new ParameterConversionResult();
				res.name = TraceUtils.convertName(label);
				res.type = null; // Unknown type -> Warning will be created
				result.parameters.add(res);
			}
		}
		return result;
	}

	/**
	 * Maps a format to conversion result
	 * 
	 * @param mapping
	 *            the mapping
	 * @return the conversion result
	 */
	protected ParameterConversionResult mapFormatToConversionResult(
			FormatMapping mapping) {
		ParameterConversionResult param = new ParameterConversionResult();
		param.type = mapping.type;
		if (mapping.isArray) {
			param.extensions = new ArrayList<TraceModelExtension>();
			param.extensions.add(new ArrayParameterRuleImpl());
		}
		return param;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.nokia.tracebuilder.engine.source.SourceParserRule#
	 *      findLocationComment(com.nokia.tracebuilder.engine.TraceLocation)
	 */
	public SourceExcludedArea findLocationComment(TraceLocation location) {
		SourceParser parser = location.getParser();
		SourceExcludedArea excludedArea = null;
		if (parser != null) {
			try {
				int offset = location.getOffset() + location.getLength();
				SourceIterator itr = parser.createIterator(offset,
						SourceParser.SKIP_WHITE_SPACES);
				char c = itr.next();
				if (c == ';') {
					offset = itr.currentIndex();
					c = itr.next();
				}
				boolean skippedReturn = false;
				int commentStart = itr.currentIndex();
				for (int i = offset; i < commentStart; i++) {
					c = parser.getData(i);
					if (c == '\n') {
						skippedReturn = true;
					}
				}
				// Comment must be on same line
				if (!skippedReturn) {
					excludedArea = parser.getExcludedArea(commentStart);
				}
				if (excludedArea == null) {
					// If comment is not on same line, the previous line is
					// checked
					offset = parser.findStartOfLine(location.getOffset(), true,
							true);
					excludedArea = parser.getExcludedArea(offset - 1);
				}
			} catch (SourceParserException e) {
			}
		}
		return excludedArea;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.nokia.tracebuilder.engine.source.SourceParserRule#getLocationParser()
	 */
	public TraceLocationParser getLocationParser() {
		return this;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.nokia.tracebuilder.project.TraceLocationParser#
	 *      isLocationConverted(com.nokia.tracebuilder.engine.TraceLocation)
	 */
	public boolean isLocationConverted(TraceLocation location) {
		return false;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.nokia.tracebuilder.project.TraceLocationParser#
	 *      checkLocationValidity(com.nokia.tracebuilder.engine.TraceLocation)
	 */
	public TraceBuilderErrorCode checkLocationValidity(TraceLocation location) {
		Trace trace = location.getTrace();
		TraceBuilderErrorCode retval = TraceBuilderErrorCode.TRACE_DOES_NOT_EXIST;
		if (trace != null) {
			retval = TraceBuilderErrorCode.OK;
		} else {
			// If the API does not match the parser, the needs conversion flag
			// is set
			TraceProjectAPI api = getOwner().getModel().getExtension(
					TraceProjectAPI.class);
			if (!api.getName().equals(location.getParserRule().getName())) {
				retval = TraceBuilderErrorCode.TRACE_NEEDS_CONVERSION;
			}
		}
		return retval;
	}

}