--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tracesrv/tracecompiler/src/com.nokia.tracecompiler/src/com/nokia/tracecompiler/decodeplugins/dictionary/DictionaryFileWriter.java Fri Oct 08 14:56:39 2010 +0300
@@ -0,0 +1,586 @@
+/*
+* Copyright (c) 2008-2010 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:
+*
+* Writer for dictionary file
+*
+*/
+package com.nokia.tracecompiler.decodeplugins.dictionary;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+
+import com.nokia.tracecompiler.decodeplugins.dictionary.encoder.DataType;
+import com.nokia.tracecompiler.decodeplugins.dictionary.encoder.Dictionary;
+import com.nokia.tracecompiler.decodeplugins.dictionary.encoder.LocationStore;
+import com.nokia.tracecompiler.decodeplugins.dictionary.encoder.TraceComponent;
+import com.nokia.tracecompiler.decodeplugins.dictionary.encoder.TraceDataStore;
+import com.nokia.tracecompiler.decodeplugins.dictionary.encoder.TraceDictionaryEncoder;
+import com.nokia.tracecompiler.decodeplugins.dictionary.encoder.TypeDef;
+import com.nokia.tracecompiler.decodeplugins.dictionary.encoder.TypeDefStore;
+import com.nokia.tracecompiler.engine.LocationListBase;
+import com.nokia.tracecompiler.engine.LocationProperties;
+import com.nokia.tracecompiler.file.FileUtils;
+import com.nokia.tracecompiler.model.Trace;
+import com.nokia.tracecompiler.model.TraceConstantTable;
+import com.nokia.tracecompiler.model.TraceConstantTableEntry;
+import com.nokia.tracecompiler.model.TraceGroup;
+import com.nokia.tracecompiler.model.TraceModel;
+import com.nokia.tracecompiler.model.TraceObjectUtils;
+import com.nokia.tracecompiler.model.TraceParameter;
+import com.nokia.tracecompiler.project.FormattingUtils;
+import com.nokia.tracecompiler.project.PropertyNames;
+import com.nokia.tracecompiler.project.TraceProjectAPI;
+import com.nokia.tracecompiler.project.TraceProjectAPI.TraceFormatFlags;
+import com.nokia.tracecompiler.rules.FillerParameterRule;
+import com.nokia.tracecompiler.rules.HiddenTraceObjectRule;
+import com.nokia.tracecompiler.source.SourceConstants;
+import com.nokia.tracecompiler.source.SourceUtils;
+
+/**
+ * Writer for dictionary file
+ *
+ */
+final class DictionaryFileWriter {
+
+ /**
+ * Comparator for file references
+ */
+ private final class FileRefComparator implements
+ Comparator<DictionaryFileRef> {
+ public int compare(DictionaryFileRef o1, DictionaryFileRef o2) {
+ int val = o1.path.compareTo(o2.path);
+ if (val == 0) {
+ val = o1.file.compareTo(o2.file);
+ }
+ return val;
+ }
+ }
+
+ /**
+ * Dictionary file
+ */
+ private DictionaryFile dictionaryFile;
+
+ /**
+ * Sequential number for trace definitions
+ */
+ private int defref;
+
+ /**
+ * Sequential number for file definitions
+ */
+ private int fileref;
+
+ /**
+ * Constructor
+ *
+ * @param dictionaryFile
+ * the dictionary file
+ */
+ DictionaryFileWriter(DictionaryFile dictionaryFile) {
+ this.dictionaryFile = dictionaryFile;
+ }
+
+ /**
+ * Writes the dictionary file
+ */
+ void write() {
+ defref = 0;
+ fileref = 0;
+ File file = new File(dictionaryFile.getAbsolutePathWithID());
+ // Delete removes possible read-only flags
+ if (file.exists()) {
+ file.delete();
+ }
+
+ TraceDictionaryEncoder encoder = new TraceDictionaryEncoder();
+ File path = file.getParentFile();
+ if (!path.exists()) {
+ FileUtils.createDirectories(path);
+ }
+ encoder.createNewDictionary(file.getAbsolutePath());
+ Dictionary.startDictionary();
+ createTypedefs();
+ createDefs();
+ createLocations();
+ createComponent();
+ Dictionary.endDictionary();
+ }
+
+ /**
+ * Creates the type definitions
+ */
+ private void createTypedefs() {
+ TypeDefStore.startTypeDefs();
+ ArrayList<String> typeList = buildTypeList();
+ writeTypeDefinitions(typeList);
+ TypeDefStore.endTypeDefs();
+ }
+
+ /**
+ * Builds the list of parameter types
+ *
+ * @return the list of types found from the model
+ */
+ private ArrayList<String> buildTypeList() {
+ TraceModel model = dictionaryFile.getOwner().getModel();
+ ArrayList<String> typeList = new ArrayList<String>();
+ for (TraceGroup group : model) {
+ for (Trace trace : group) {
+ for (TraceParameter parameter : trace) {
+ if ((parameter.getExtension(HiddenTraceObjectRule.class) == null)
+ || (parameter
+ .getExtension(FillerParameterRule.class) != null)) {
+ String type = parameter.getType();
+ if (!typeList.contains(type)) {
+ typeList.add(type);
+ }
+ }
+ }
+ }
+ }
+ return typeList;
+ }
+
+ /**
+ * Writes the data type definitions
+ *
+ * @param typeList
+ * the list of data types
+ */
+ private void writeTypeDefinitions(ArrayList<String> typeList) {
+ for (String type : typeList) {
+ DataType dt = mapTypeToDataType(type);
+ if (dt != null) {
+ // Normal parameters
+ int size = mapParameterTypeToSize(type);
+ String formatChar = SourceUtils.mapNormalTypeToFormat(type);
+ if (formatChar != null && formatChar.length() > 1
+ && formatChar.charAt(0) == '%') {
+ formatChar = formatChar.substring(1);
+ TypeDefStore.writeTypeDef(type, size, formatChar, dt);
+
+ // Write alternative format characters
+ writeAlternativeFormatChars(formatChar, type, size, dt);
+
+ } else {
+ TypeDefStore.writeTypeDef(type, size, null, dt);
+ }
+ } else {
+ // Enum parameters
+ TraceModel model = dictionaryFile.getOwner().getModel();
+ TraceConstantTable table = model.findConstantTableByName(type);
+ if (table != null) {
+ TypeDefStore.startTypeDef(table.getName(),
+ mapParameterTypeToSize(table.getType()), null,
+ DataType.ENUM);
+ for (TraceConstantTableEntry entry : table) {
+ TypeDef.writeTypeMember(entry.getID(), entry.getName(),
+ null);
+ }
+ TypeDefStore.endTypeDef();
+ }
+ }
+ }
+ }
+
+ /**
+ * Writes alternative format characters to the Dictionary
+ *
+ * @param formatChar
+ * formatchar
+ * @param type
+ * parameter type
+ * @param size
+ * parameter size
+ * @param dt
+ * data type
+ */
+ private void writeAlternativeFormatChars(String formatChar, String type,
+ int size, DataType dt) {
+
+ // If there's big L, write also 'll' type
+ if (formatChar.indexOf('L') != -1) {
+
+ // Double small l
+ String newFormatChar = formatChar.replace("L", "ll"); //$NON-NLS-1$ //$NON-NLS-2$
+ TypeDefStore.writeTypeDef(type, size, newFormatChar, dt);
+ writeCapitalHexType(newFormatChar, type, size, dt);
+
+ }
+
+ // Write alternative option to float types
+ else if (formatChar.equals("f") || formatChar.equals("e") //$NON-NLS-1$//$NON-NLS-2$
+ || formatChar.equals("g")) { //$NON-NLS-1$
+
+ String newFormatChar = 'L' + formatChar;
+ TypeDefStore.writeTypeDef(type, size, newFormatChar, dt);
+ }
+
+ else {
+ // If length is one, add also formatchar with "l"
+ if (formatChar.length() == 1) {
+ String newFormatChar = "l" + formatChar; //$NON-NLS-1$
+ TypeDefStore.writeTypeDef(type, size, newFormatChar, dt);
+ writeCapitalHexType(newFormatChar, type, size, dt);
+ }
+
+ // Check capital hex need
+ writeCapitalHexType(formatChar, type, size, dt);
+ }
+ }
+
+ /**
+ * Writes capital hex type
+ *
+ * @param formatChar
+ * formatchar
+ * @param type
+ * parameter type
+ * @param size
+ * parameter size
+ * @param dt
+ * data type
+ */
+ private void writeCapitalHexType(String formatChar, String type, int size,
+ DataType dt) {
+
+ // Write also capital X if there are hex values
+ if (formatChar.indexOf('x') != -1) {
+ type = type.toUpperCase();
+ TypeDefStore.writeTypeDef(type, size, formatChar.replace('x', 'X'),
+ dt);
+ }
+ }
+
+ /**
+ * Gets the parameter size from type
+ *
+ * @param type
+ * the type
+ * @return the size in bytes
+ */
+ private int mapParameterTypeToSize(String type) {
+ int size = SourceUtils.mapParameterTypeToSize(type);
+ if (size == 0) {
+ if (type.equals(TraceParameter.ASCII)) {
+ size = 1;
+ } else if (type.equals(TraceParameter.UNICODE)) {
+ size = 2; // CodForChk_Dis_Magic
+ }
+ }
+ return size;
+ }
+
+ /**
+ * Creates the trace definitions
+ */
+ private void createDefs() {
+ // This should check for duplicates
+ TraceDataStore.startDataStore();
+ TraceModel model = dictionaryFile.getOwner().getModel();
+ TraceProjectAPI api = model.getExtension(TraceProjectAPI.class);
+ for (TraceGroup group : model) {
+ for (Trace trace : group) {
+ trace.addExtension(new DictionaryDefRef(++defref));
+ TraceFormatFlags flags = new TraceFormatFlags();
+ flags.isFormattingSupported = true;
+ String data = api.formatTraceForExport(trace, flags);
+ data = replaceUnescapeQuotes(data);
+ TraceDataStore.writeData(defref, DataType.STRING, data);
+ }
+ }
+ TraceDataStore.endDataStore();
+ }
+
+ /**
+ * Replaces unescape quates
+ *
+ * @param data
+ * the data
+ * @return the new string
+ */
+ private String replaceUnescapeQuotes(String data) {
+ data = data.replace("\\\"", "\""); //$NON-NLS-1$ //$NON-NLS-2$
+ return data;
+ }
+
+ /**
+ * Maps a basic type to a Dictionary data type
+ *
+ * @param type
+ * the type
+ * @return the data type
+ */
+ private DataType mapTypeToDataType(String type) { // CodForChk_Dis_ComplexFunc
+ DataType retval;
+ // Unsigned is not supported in Dictionary
+ if (type.equals(TraceParameter.SDEC32)) {
+ retval = DataType.INTEGER;
+ } else if (type.equals(TraceParameter.HEX32)) {
+ retval = DataType.HEX;
+ } else if (type.equals(TraceParameter.UDEC32)) {
+ retval = DataType.INTEGER;
+ } else if (type.equals(TraceParameter.OCT32)) {
+ retval = DataType.OCTAL;
+ } else if (type.equals(TraceParameter.SDEC16)) {
+ retval = DataType.INTEGER;
+ } else if (type.equals(TraceParameter.HEX16)) {
+ retval = DataType.HEX;
+ } else if (type.equals(TraceParameter.UDEC16)) {
+ retval = DataType.INTEGER;
+ } else if (type.equals(TraceParameter.OCT16)) {
+ retval = DataType.OCTAL;
+ } else if (type.equals(TraceParameter.SDEC8)) {
+ retval = DataType.INTEGER;
+ } else if (type.equals(TraceParameter.HEX8)) {
+ retval = DataType.HEX;
+ } else if (type.equals(TraceParameter.UDEC8)) {
+ retval = DataType.INTEGER;
+ } else if (type.equals(TraceParameter.OCT8)) {
+ retval = DataType.OCTAL;
+ } else if (type.equals(TraceParameter.SDEC64)) {
+ retval = DataType.INTEGER;
+ } else if (type.equals(TraceParameter.HEX64)) {
+ retval = DataType.HEX;
+ } else if (type.equals(TraceParameter.UDEC64)) {
+ retval = DataType.INTEGER;
+ } else if (type.equals(TraceParameter.OCT64)) {
+ retval = DataType.OCTAL;
+ } else if (type.equals(TraceParameter.ASCII)) {
+ retval = DataType.STRING;
+ } else if (type.equals(TraceParameter.UNICODE)) {
+ retval = DataType.STRING;
+ } else if (type.equals(TraceParameter.FLOAT_FIX)) {
+ retval = DataType.FLOAT;
+ } else if (type.equals(TraceParameter.FLOAT_EXP)) {
+ retval = DataType.FLOAT;
+ } else if (type.equals(TraceParameter.FLOAT_OPT)) {
+ retval = DataType.FLOAT;
+ } else if (type.equals(TraceParameter.POINTER)) {
+ retval = DataType.HEX;
+ } else {
+ retval = null;
+ }
+ return retval;
+ }
+
+ /**
+ * Creates the location definitions
+ */
+ private void createLocations() {
+ ArrayList<DictionaryFileRef> files = new ArrayList<DictionaryFileRef>();
+ LocationStore.startLocations();
+ for (TraceGroup group : dictionaryFile.getOwner().getModel()) {
+ for (Trace trace : group) {
+ writeLocation(files, trace);
+ }
+ }
+ // Build XML and assign ID's to refs
+ Collections.sort(files, new FileRefComparator());
+ String lastpath = null;
+ for (DictionaryFileRef ref : files) {
+ if (!ref.path.equals(lastpath)) {
+ if (lastpath != null) {
+ LocationStore.endPath();
+ }
+ LocationStore.startPath(ref.path);
+ lastpath = ref.path;
+ }
+ LocationStore.writeFile(++fileref, ref.file);
+ ref.refid = fileref;
+ }
+ if (lastpath != null) {
+ LocationStore.endPath();
+ }
+ LocationStore.endLocations();
+ }
+
+ /**
+ * Writes the location of a trace
+ *
+ * @param files
+ * file references
+ * @param trace
+ * trace to be written
+ */
+ private void writeLocation(ArrayList<DictionaryFileRef> files, Trace trace) {
+ LocationProperties loc = findFirstLocation(trace);
+ if (loc != null) {
+ String path = loc.getFilePath();
+ String file = loc.getFileName();
+ if (path != null) {
+ path = FileUtils.convertSeparators(
+ SourceConstants.FORWARD_SLASH_CHAR, path, true);
+ // TODO: Remove drive letter. Actually cannot remove drive
+ // letter because EPOCROOT might not be in the root of the drive
+ }
+ DictionaryFileRef ref = getRef(files, file, path);
+ if (ref == null) {
+ ref = new DictionaryFileRef(file, path, trace);
+ files.add(ref);
+ trace.addExtension(ref);
+ } else {
+ trace.addExtension(ref);
+ }
+ }
+ }
+
+ /**
+ * Finds the first location from trace
+ *
+ * @param trace
+ * the trace
+ * @return the location
+ */
+ private LocationProperties findFirstLocation(Trace trace) {
+ Iterator<LocationListBase> itr = trace
+ .getExtensions(LocationListBase.class);
+ LocationProperties loc = null;
+ while (itr.hasNext() && loc == null) {
+ Iterator<LocationProperties> locs = itr.next().iterator();
+ if (locs.hasNext()) {
+ loc = locs.next();
+ }
+ }
+ return loc;
+ }
+
+ /**
+ * Gets a file reference
+ *
+ * @param files
+ * the list of file references
+ * @param file
+ * file name
+ * @param path
+ * file path
+ * @return the file reference
+ */
+ private DictionaryFileRef getRef(ArrayList<DictionaryFileRef> files,
+ String file, String path) {
+ DictionaryFileRef retval = null;
+ for (int i = 0; i < files.size() && retval == null; i++) {
+ DictionaryFileRef ref = files.get(i);
+ if (ref.file.equals(file) && ref.path.equals(path)) {
+ retval = ref;
+ }
+ }
+ return retval;
+ }
+
+ /**
+ * Creates the component definition
+ */
+ private void createComponent() {
+ TraceModel model = dictionaryFile.getOwner().getModel();
+ int compid = model.getID();
+ // Component prefix and suffix are in property file.
+ // If not there, the default values are used
+ String prefix = TraceObjectUtils.findProperty(model,
+ PropertyNames.PREFIX);
+ if (prefix == null || prefix.length() == 0) {
+ prefix = FormattingUtils.getDefaultComponentPrefix(model);
+ }
+ String suffix = TraceObjectUtils.findProperty(model,
+ PropertyNames.SUFFIX);
+ if (suffix == null || suffix.length() == 0) {
+ suffix = FormattingUtils.getDefaultComponentSuffix(model);
+ }
+ Dictionary.startComponent(compid, dictionaryFile.getProjectName(),
+ prefix, suffix);
+ for (TraceGroup group : model) {
+ createGroup(group);
+ }
+ Dictionary.endComponent();
+ }
+
+ /**
+ * Creates a group definition
+ *
+ * @param group
+ * the group
+ */
+ private void createGroup(TraceGroup group) {
+ String prefix = TraceObjectUtils.findProperty(group,
+ PropertyNames.PREFIX);
+ if (prefix == null || prefix.length() == 0) {
+ prefix = FormattingUtils.getDefaultGroupPrefix(group);
+ }
+ String suffix = TraceObjectUtils.findProperty(group,
+ PropertyNames.SUFFIX);
+ if (suffix == null || suffix.length() == 0) {
+ suffix = FormattingUtils.getDefaultGroupSuffix(group);
+ }
+ TraceComponent.startGroup(group.getID(), group.getName(), prefix,
+ suffix);
+ for (Trace trace : group) {
+ createTrace(trace);
+ }
+ TraceComponent.endGroup();
+ }
+
+ /**
+ * Creates a trace definition
+ *
+ * @param trace
+ * the trace
+ */
+ private void createTrace(Trace trace) {
+ DictionaryDefRef defref = trace.getExtension(DictionaryDefRef.class);
+ if (defref != null) {
+ DictionaryFileRef fileref = trace
+ .getExtension(DictionaryFileRef.class);
+ com.nokia.tracecompiler.decodeplugins.dictionary.encoder.TraceGroup.startTrace(defref
+ .getRefId(), trace.getName());
+ if (fileref != null) {
+ writeTraceWithLocation(fileref.getRefId(), trace);
+ } else {
+ com.nokia.tracecompiler.decodeplugins.dictionary.encoder.Trace.writeInstance(trace
+ .getID(), 0, 0, "", //$NON-NLS-1$
+ ""); //$NON-NLS-1$
+ }
+ com.nokia.tracecompiler.decodeplugins.dictionary.encoder.TraceGroup.endTrace();
+ }
+ trace.removeExtensions(DictionaryRef.class);
+
+ }
+
+ /**
+ * Writes a trace which has a source location
+ *
+ * @param refId
+ * file reference number
+ * @param trace
+ * the trace
+ */
+ private void writeTraceWithLocation(int refId, Trace trace) {
+ LocationProperties loc = findFirstLocation(trace);
+ int line = 0;
+ String className = ""; //$NON-NLS-1$
+ String functionName = ""; //$NON-NLS-1$
+ if (loc != null) {
+ line = loc.getLineNumber();
+ className = loc.getClassName();
+ functionName = loc.getFunctionName();
+ }
+ com.nokia.tracecompiler.decodeplugins.dictionary.encoder.Trace.writeInstance(trace.getID(),
+ refId, line, functionName, className);
+ }
+
+}