tracefw/tracecompiler/src/com.nokia.tracecompiler/src/com/nokia/tracecompiler/engine/rules/RulesEngine.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tracefw/tracecompiler/src/com.nokia.tracecompiler/src/com/nokia/tracecompiler/engine/rules/RulesEngine.java Mon Aug 23 15:29:36 2010 +0300
@@ -0,0 +1,383 @@
+/*
+* 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 TraceObjectRuleFactory interface
+*
+*/
+package com.nokia.tracecompiler.engine.rules;
+
+import java.util.Iterator;
+
+import com.nokia.tracecompiler.engine.TraceCompilerEngineConfiguration;
+import com.nokia.tracecompiler.engine.TraceCompilerEngineConfigurationListener;
+import com.nokia.tracecompiler.engine.TraceCompilerEngineGlobals;
+import com.nokia.tracecompiler.engine.header.ComplexHeaderRule;
+import com.nokia.tracecompiler.engine.rules.osttrace.OstTraceFormatRule;
+import com.nokia.tracecompiler.engine.source.SourceParserRule;
+import com.nokia.tracecompiler.engine.source.TraceParameterFormattingRule;
+import com.nokia.tracecompiler.model.Trace;
+import com.nokia.tracecompiler.model.TraceCompilerException;
+import com.nokia.tracecompiler.model.TraceModel;
+import com.nokia.tracecompiler.model.TraceModelExtension;
+import com.nokia.tracecompiler.model.TraceModelListener;
+import com.nokia.tracecompiler.model.TraceModelPersistentExtension;
+import com.nokia.tracecompiler.model.TraceModelResetListener;
+import com.nokia.tracecompiler.model.TraceObject;
+import com.nokia.tracecompiler.model.TraceObjectRuleFactory;
+import com.nokia.tracecompiler.model.TraceParameter;
+import com.nokia.tracecompiler.project.TraceProjectAPI;
+import com.nokia.tracecompiler.rules.FillerParameterRule;
+import com.nokia.tracecompiler.source.SourceUtils;
+
+/**
+ * Provides rules for trace objects.
+ *
+ */
+public class RulesEngine implements TraceObjectRuleFactory {
+
+ /**
+ * Number of parameters in a simple trace
+ */
+ private static final int SIMPLE_TRACE_MAX_PARAMETER_COUNT = 1;
+
+ /**
+ * Trace model listener updates the fillers and complex type flagging when
+ * traces and parameters are modified
+ */
+ private TraceModelListener modelListener;
+
+ /**
+ * Trace model reset listener uses modelValid to update the complex header
+ * rules
+ */
+ private TraceModelResetListener resetListener;
+
+ /**
+ * Manager for plug-in API's
+ */
+ private RulesEnginePluginManager pluginManager;
+
+ /**
+ * Configuration listener for source format changes
+ */
+ private TraceCompilerEngineConfigurationListener configurationListener = new RulesEngineConfigurationListener(
+ this);
+
+ /**
+ * Trace model
+ */
+ private TraceModel model;
+
+ /**
+ * Constructor
+ */
+ public RulesEngine() {
+ TraceCompilerEngineGlobals.getConfiguration().addConfigurationListener(
+ configurationListener);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.nokia.tracecompiler.model.TraceObjectRuleFactory#
+ * createExtension(com.nokia.tracecompiler.model.TraceObject,
+ * java.lang.String)
+ */
+ public TraceModelPersistentExtension createExtension(TraceObject target,
+ String name) {
+ TraceModelPersistentExtension retval = null;
+ ClassNameWrapper[] table = RulesEngineConstants.PERSISTENT_EXTENSIONS;
+ for (int i = 0; i < table.length && retval == null; i++) {
+ if (name.equals(table[i].name)) {
+ retval = createPersistentExtensionAt(target, i);
+ }
+ }
+ return retval;
+ }
+
+ /**
+ * Creates a persistent extension
+ *
+ * @param target
+ * the target object
+ * @param i
+ * index to the persistent extensions array
+ * @return the extension
+ */
+ private TraceModelPersistentExtension createPersistentExtensionAt(
+ TraceObject target, int i) {
+ ClassNameWrapper wrapper = RulesEngineConstants.PERSISTENT_EXTENSIONS[i];
+ TraceModelPersistentExtension retval = null;
+ TraceModelPersistentExtension o = target.getExtension(wrapper.clasz);
+ if (o == null) {
+ try {
+ retval = wrapper.clasz.newInstance();
+ } catch (Exception e) {
+ if (TraceCompilerEngineConfiguration.ASSERTIONS_ENABLED) {
+ TraceCompilerEngineGlobals.getEvents().postAssertionFailed(
+ "Invalid extension - " + wrapper.name, null); //$NON-NLS-1$
+ }
+ }
+ }
+ return retval;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.nokia.tracecompiler.model.TraceObjectRuleFactory#
+ * preProcessNewRules(com.nokia.tracecompiler.model.TraceObject)
+ */
+ public void preProcessNewRules(TraceObject object) {
+ if (object instanceof TraceModel) {
+ // NOTE: This is only called once when builder is started
+ // There is no cleanup code
+ this.model = (TraceModel) object;
+ modelListener = new RulesEngineModelListener(this);
+ resetListener = new RulesEngineResetListener(this, model);
+ model.addModelListener(modelListener);
+ model.addResetListener(resetListener);
+ // Adds the plug-in trace parser / formatter manager to the model as
+ // extension. The plug-in manager delegates the formatters and
+ // parsers to this object when plug-in components register to
+ // TraceCompiler.
+ pluginManager = new RulesEnginePluginManager(this);
+ model.addExtension(pluginManager);
+ createTraceParsers();
+ createTraceAPIs();
+ }
+ }
+
+ /**
+ * Creates the trace parsers and stores them to the model
+ */
+ private void createTraceParsers() {
+ for (SourceParserRule element : RulesEngineConstants.TRACE_PARSERS) {
+ // Creates all source parsers specified in the constants
+ model.addExtension(element);
+ }
+ }
+
+ /**
+ * Creates the default trace API's and adds them to the plug-in manager
+ */
+ private void createTraceAPIs() {
+ for (TraceProjectAPI api : RulesEngineConstants.TRACE_APIS) {
+ pluginManager.addAPI(api);
+ }
+ }
+
+ /**
+ * Creates the trace formatter and stores it to the model
+ */
+ void setDefaultTraceAPI() {
+ // If the formatter did not exist in the project file, it is added based
+ // on the configuration default
+ if (model.getExtension(TraceProjectAPI.class) == null) {
+ String api = TraceCompilerEngineGlobals.getConfiguration().getText(
+ TraceCompilerEngineConfiguration.FORMATTER_NAME);
+ traceAPIChanged(api);
+ }
+ }
+
+ /**
+ * API change notification
+ *
+ * @param apiName
+ * the name of new api
+ */
+ void traceAPIChanged(String apiName) {
+ TraceProjectAPI api = model.getExtension(TraceProjectAPI.class);
+ boolean found = false;
+ if (api != null) {
+ if (api.getName().equals(apiName)) {
+ found = true;
+ } else {
+ model.removeExtension(api);
+ }
+ }
+ if (!found) {
+ changeTraceAPI(apiName);
+ }
+ }
+
+ /**
+ * Creates a trace API
+ *
+ * @param apiName
+ * the name of the API to be created
+ */
+ void changeTraceAPI(String apiName) {
+ if (apiName == null || apiName.length() == 0) {
+ apiName = OstTraceFormatRule.STORAGE_NAME;
+ }
+ Iterator<TraceProjectAPI> apis = pluginManager.getAPIs();
+ boolean apifound = false;
+ while (apis.hasNext()) {
+ TraceProjectAPI api = apis.next();
+ if (api.getName().equals(apiName)) {
+ model.addExtension(api);
+ apifound = true;
+ }
+ }
+ if (!apifound) {
+ // If API from configuration was not found, the first one is used
+ apis = pluginManager.getAPIs();
+ if (apis.hasNext()) {
+ model.addExtension(apis.next());
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.nokia.tracecompiler.model.TraceObjectRuleFactory#
+ * postProcessNewRules(com.nokia.tracecompiler.model.TraceObject)
+ */
+ public void postProcessNewRules(TraceObject object) {
+ }
+
+ /**
+ * Checks the count and types of parameters of given trace and flags it with
+ * ComplexParameterRule if necessary
+ *
+ * @param trace
+ * the trace
+ */
+ void checkParameterTypes(Trace trace) {
+ // When converting traces from source, the converter takes care of
+ // flagging the traces as complex. The complex flag needs to be checked
+ // when trace are modified via UI
+ if (!TraceCompilerEngineGlobals.getSourceContextManager().isConverting()) {
+ boolean complex = false;
+ int count = trace.getParameterCount();
+ Iterator<TraceParameter> itr = trace.getParameters();
+ while (itr.hasNext() && !complex) {
+ TraceParameter parameter = itr.next();
+ TraceParameterFormattingRule rule = parameter
+ .getExtension(TraceParameterFormattingRule.class);
+ boolean isShown = true;
+ if (rule != null && !rule.isShownInSource()) {
+ isShown = false;
+ }
+ if (isShown) {
+ complex = !SourceUtils.isSimpleType(parameter);
+ } else {
+ count--;
+ }
+ }
+ // Any trace with more than one parameter is a complex trace
+ if (!complex && count > SIMPLE_TRACE_MAX_PARAMETER_COUNT) {
+ complex = true;
+ }
+ ComplexHeaderRule rule = trace
+ .getExtension(ComplexHeaderRule.class);
+ if (complex && rule == null) {
+ trace.addExtension(new ComplexHeaderRuleImpl());
+ } else if (!complex && rule != null) {
+ trace.removeExtension(rule);
+ }
+ }
+ }
+
+ /**
+ * Adds fillers to align trace parameters to 32-bit boundaries.
+ *
+ * @param trace
+ * the trace to be updated
+ * @throws TraceCompilerException
+ */
+ void checkFillerParameters(Trace trace) throws TraceCompilerException {
+ // Flags the model so listeners don't perform intermediate updates
+ trace.getModel().startProcessing();
+ try {
+ // Removes all existing fillers
+ for (int i = 0; i < trace.getParameterCount(); i++) {
+ TraceParameter parameter = trace.getParameter(i);
+ if (parameter.getExtension(FillerParameterRule.class) != null) {
+ trace.removeParameterAt(i);
+ i--;
+ }
+ }
+ int bytesInBlock = 0;
+ int parameterIndex = 0;
+ for (; parameterIndex < trace.getParameterCount(); parameterIndex++) {
+ TraceParameter parameter = trace.getParameter(parameterIndex);
+ int paramSize = SourceUtils.mapParameterTypeToSize(parameter);
+ // Parameters are aligned to 32 bits. Parameter after
+ // end-of-string is aligned dynamically and thus no filler is
+ // created for it
+ if (paramSize == 0 || paramSize == 4 || paramSize == 8) { // CodForChk_Dis_Magic
+ if (bytesInBlock > 0) {
+ int fillerCount = 4 - bytesInBlock; // CodForChk_Dis_Magic
+ for (int i = 0; i < fillerCount; i++) {
+ createFillerParameter(trace, parameterIndex++);
+ }
+ bytesInBlock = 0;
+ }
+ } else if (paramSize == 2) { // CodForChk_Dis_Magic
+ if (bytesInBlock == 1 || bytesInBlock == 3) { // CodForChk_Dis_Magic
+ createFillerParameter(trace, parameterIndex++);
+ // If there was 1 existing byte and filler was added,
+ // the number of bytes in the block is now 4 including
+ // the 2-byte parameter. If there was 3 bytes, the
+ // filler brings it to 4 and the 16-bit parameter
+ // changes it to 2
+ bytesInBlock += 3; // CodForChk_Dis_Magic
+ } else {
+ bytesInBlock += 2; // CodForChk_Dis_Magic
+ }
+ if (bytesInBlock >= 4) { // CodForChk_Dis_Magic
+ bytesInBlock -= 4; // CodForChk_Dis_Magic
+ }
+ } else {
+ bytesInBlock++;
+ if (bytesInBlock == 4) { // CodForChk_Dis_Magic
+ bytesInBlock = 0;
+ }
+ }
+ }
+ // Adds fillers also the the end of the parameter list
+ if (bytesInBlock > 0) {
+ int fillerCount = 4 - bytesInBlock; // CodForChk_Dis_Magic
+ for (int i = 0; i < fillerCount; i++) {
+ createFillerParameter(trace, parameterIndex++);
+ }
+ bytesInBlock = 0;
+ }
+ } finally {
+ trace.getModel().processingComplete();
+ }
+ }
+
+ /**
+ * Creates a filler parameter
+ *
+ * @param trace
+ * the trace for the parameter
+ * @param parameterIndex
+ * the index where the filler is inserted
+ * @throws TraceCompilerException
+ */
+ private void createFillerParameter(Trace trace, int parameterIndex) throws TraceCompilerException {
+ trace.getModel().getFactory().createTraceParameter(parameterIndex,
+ trace, trace.getParameterCount(),
+ "Filler", //$NON-NLS-1$
+ TraceParameter.HEX8,
+ new TraceModelExtension[] { new FillerParameterRuleImpl() });
+ }
+
+}