org.eclipse.tracecompass.analysis.timing.core
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-ActivationPolicy: lazy
-Import-Package: com.google.common.collect;version="10.0.1",
- org.eclipse.tracecompass.testtraces.ctf;version="1.0.0",
+Import-Package: com.google.common.base;version="15.0.0",
+ com.google.common.collect,
+ org.eclipse.tracecompass.testtraces.ctf,
org.junit.runners
Export-Package: org.eclipse.tracecompass.tmf.analysis.xml.core.tests,
org.eclipse.tracecompass.tmf.analysis.xml.core.tests.common;x-friends:="org.eclipse.tracecompass.tmf.analysis.xml.ui.tests,org.eclipse.tracecompass.tmf.analysis.xml.ui.swtbot.tests",
/** A valid pattern file to test the initialState element */
INITIAL_STATE_ELEMENT_TEST_FILE_2("test_xml_files/test_valid/test_initialState_element2.xml"),
/** A valid xml timegraph view */
- VALID_TIMEGRAPH_VIEW_ELEMENT_FILE("test_xml_files/test_valid/test_valid_xml_timegraphView.xml");
+ VALID_TIMEGRAPH_VIEW_ELEMENT_FILE("test_xml_files/test_valid/test_valid_xml_timegraphView.xml"),
+ /** A valid test with elements from an extended XSD */
+ VALID_FILE_EXTENDED("test_xml_files/test_valid/test_valid_extended.xml");
private final String fPath;
<xsdfile
file="test_xml_files/extension.xsd">
</xsdfile>
+ <schemaParser
+ class="org.eclipse.tracecompass.tmf.analysis.xml.core.tests.stubs.XmlSchemaParserStub">
+ </schemaParser>
</extension>
</plugin>
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.XmlAnalysisModuleSource;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.XmlUtils;
-import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.TmfAnalysisModuleHelperXml.XmlAnalysisModuleType;
+import org.eclipse.tracecompass.tmf.analysis.xml.core.module.TmfAnalysisModuleHelperXml.XmlAnalysisModuleType;
import org.eclipse.tracecompass.tmf.analysis.xml.core.tests.common.TmfXmlTestFiles;
import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModuleHelper;
import org.eclipse.tracecompass.tmf.core.analysis.TmfAnalysisManager;
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2017 École Polytechnique de Montréal
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.tmf.analysis.xml.core.tests.module;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.util.Collection;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.XmlAnalysisModuleSource;
+import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.XmlUtils;
+import org.eclipse.tracecompass.tmf.analysis.xml.core.module.ITmfXmlSchemaParser;
+import org.eclipse.tracecompass.tmf.analysis.xml.core.tests.common.TmfXmlTestFiles;
+import org.eclipse.tracecompass.tmf.analysis.xml.core.tests.stubs.ExternalAnalysisModuleStub;
+import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule;
+import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModuleHelper;
+import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.Iterables;
+
+/**
+ * Test the extended XSD analysis mechanisms and {@link ITmfXmlSchemaParser}
+ * with stub analyzes
+ *
+ * @author Geneviève Bastien
+ */
+public class XmlSchemaParserTest {
+
+ private static final @NonNull String TEST_TRACE = "test_traces/testTrace4.xml";
+ private static final @NonNull String MY_MODULE = "extended.my";
+ private static final @NonNull String ABC_MODULE = "extended.abc";
+
+ private static void emptyXmlFolder() {
+ File fFolder = XmlUtils.getXmlFilesPath().toFile();
+ if (!(fFolder.isDirectory() && fFolder.exists())) {
+ return;
+ }
+ for (File xmlFile : fFolder.listFiles()) {
+ xmlFile.delete();
+ }
+ XmlAnalysisModuleSource.notifyModuleChange();
+ }
+
+ /**
+ * Empty the XML directory before the test, just in case
+ */
+ @Before
+ public void setUp() {
+ emptyXmlFolder();
+ }
+
+ /**
+ * Empty the XML directory after the test
+ */
+ @After
+ public void cleanUp() {
+ emptyXmlFolder();
+ }
+
+ /**
+ * Test getting the extra schema parsers from the extension point
+ */
+ @Test
+ public void testGettingSchemaParser() {
+ Collection<ITmfXmlSchemaParser> parsers = XmlUtils.getExtraSchemaParsers();
+
+ assertTrue(!parsers.isEmpty());
+ }
+
+ /**
+ * Test the {@link XmlAnalysisModuleSource#getAnalysisModules()} method
+ */
+ @Test
+ public void testPopulateExtendedModules() {
+ XmlAnalysisModuleSource source = new XmlAnalysisModuleSource();
+
+ Iterable<IAnalysisModuleHelper> modules = source.getAnalysisModules();
+ assertNull("Module not present", findModule(modules, MY_MODULE));
+
+ /* use the valid extended XML test file */
+ File testXmlFile = TmfXmlTestFiles.VALID_FILE_EXTENDED.getFile();
+ if ((testXmlFile == null) || !testXmlFile.exists()) {
+ fail("XML test file does not exist");
+ }
+
+ XmlUtils.addXmlFile(testXmlFile);
+ XmlAnalysisModuleSource.notifyModuleChange();
+ modules = source.getAnalysisModules();
+
+ assertTrue("Modules available from source", modules.iterator().hasNext());
+ assertNotNull("'My' module present", findModule(modules, MY_MODULE));
+ assertNotNull("'abc' module present", findModule(modules, ABC_MODULE));
+ }
+
+ private static @Nullable IAnalysisModuleHelper findModule(Iterable<IAnalysisModuleHelper> modules, String moduleName) {
+ return Iterables.tryFind(modules, helper -> moduleName.equals(helper.getId())).orNull();
+ }
+
+ /**
+ * Test the {@link XmlAnalysisModuleSource#getAnalysisModules()} method
+ *
+ * @throws TmfAnalysisException
+ * Propagates exceptions
+ */
+ @Test
+ public void testExtendedModuleCreated() throws TmfAnalysisException {
+ XmlAnalysisModuleSource source = new XmlAnalysisModuleSource();
+
+ /* use the valid extended XML test file */
+ File testXmlFile = TmfXmlTestFiles.VALID_FILE_EXTENDED.getFile();
+ if ((testXmlFile == null) || !testXmlFile.exists()) {
+ fail("XML test file does not exist");
+ }
+ XmlUtils.addXmlFile(testXmlFile);
+ XmlAnalysisModuleSource.notifyModuleChange();
+ Iterable<IAnalysisModuleHelper> modules = source.getAnalysisModules();
+
+ ITmfTrace trace = XmlUtilsTest.initializeTrace(TEST_TRACE);
+ try {
+ IAnalysisModuleHelper helper = findModule(modules, MY_MODULE);
+ assertNotNull(helper);
+
+ IAnalysisModule newModule = helper.newModule(trace);
+ try {
+ assertTrue("Extended module class", newModule instanceof ExternalAnalysisModuleStub);
+ assertEquals("Extended module ID", MY_MODULE, newModule.getId());
+ } finally {
+ if (newModule != null) {
+ newModule.dispose();
+ }
+ }
+
+ helper = findModule(modules, ABC_MODULE);
+ assertNotNull(helper);
+
+ newModule = helper.newModule(trace);
+ try {
+ assertTrue("Extended module class", newModule instanceof ExternalAnalysisModuleStub);
+ assertEquals("Extended module ID", ABC_MODULE, newModule.getId());
+ } finally {
+ if (newModule != null) {
+ newModule.dispose();
+ }
+ }
+ } finally {
+ trace.dispose();
+ }
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2017 École Polytechnique de Montréal
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.tmf.analysis.xml.core.tests.stubs;
+
+import java.nio.file.Path;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.tracecompass.tmf.core.analysis.TmfAbstractAnalysisModule;
+import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException;
+
+/**
+ * A stub analysis module provided externally by an XML analysis using an
+ * extension XSD file
+ *
+ * @author Geneviève Bastien
+ */
+public class ExternalAnalysisModuleStub extends TmfAbstractAnalysisModule {
+
+ private final Path fXmlFile;
+ private final String fType;
+
+ /**
+ * Constructor
+ *
+ * @param file
+ * The XML file where this module is defined
+ * @param type
+ * The type of the module
+ */
+ public ExternalAnalysisModuleStub(Path file, String type) {
+ fXmlFile = file;
+ fType = type;
+ }
+
+ @Override
+ protected boolean executeAnalysis(@NonNull IProgressMonitor monitor) throws TmfAnalysisException {
+ System.out.println("Executing analysis " + getId() + " of type " + fType + " from XML file " + fXmlFile);
+ return true;
+ }
+
+ @Override
+ protected void canceling() {
+
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2017 École Polytechnique de Montréal
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.tmf.analysis.xml.core.tests.stubs;
+
+import java.io.File;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.tracecompass.tmf.analysis.xml.core.module.TmfAnalysisModuleHelperXml;
+import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule;
+import org.w3c.dom.Element;
+
+/**
+ * A stub XML module helper
+ *
+ * @author Geneviève Bastien
+ */
+@NonNullByDefault
+public class OtherModuleHelperStub extends TmfAnalysisModuleHelperXml {
+
+ /**
+ * Constructor
+ *
+ * @param xmlFile
+ * The XML file containing the extra module
+ * @param node
+ * The corresponding XML element
+ */
+ public OtherModuleHelperStub(File xmlFile, Element node) {
+ super(xmlFile, node, XmlAnalysisModuleType.OTHER);
+ }
+
+ @Override
+ protected IAnalysisModule createOtherModule(String analysisid, String name) {
+ Element sourceElement = getSourceElement();
+ ExternalAnalysisModuleStub module = null;
+ switch (sourceElement.getTagName()) {
+ case "my":
+ module = new ExternalAnalysisModuleStub(getSourceFile(), "my");
+ break;
+ case "abc":
+ module = new ExternalAnalysisModuleStub(getSourceFile(), "abc");
+ break;
+ default:
+ break;
+ }
+ if (module == null) {
+ throw new IllegalArgumentException("This element should not have parsed");
+ }
+ module.setId(analysisid);
+ module.setName(name);
+ return module;
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2017 École Polytechnique de Montréal
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.tmf.analysis.xml.core.tests.stubs;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.tracecompass.tmf.analysis.xml.core.module.ITmfXmlSchemaParser;
+import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModuleHelper;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+/**
+ * Schema parser stub for the extension.xsd extra schema
+ *
+ * @author Geneviève Bastien
+ */
+public class XmlSchemaParserStub implements ITmfXmlSchemaParser {
+
+ private static final @NonNull String MY_MODULE = "my";
+ private static final @NonNull String ABC_MODULE = "abc";
+
+ @Override
+ public @NonNull Collection<? extends @NonNull IAnalysisModuleHelper> getModuleHelpers(File xmlFile, Document doc) {
+ List<@NonNull IAnalysisModuleHelper> modules = new ArrayList<>();
+ /* get the "my" modules */
+ NodeList xmlNodes = doc.getElementsByTagName(MY_MODULE);
+ for (int i = 0; i < xmlNodes.getLength(); i++) {
+ Element node = (Element) xmlNodes.item(i);
+
+ IAnalysisModuleHelper helper = new OtherModuleHelperStub(xmlFile, node);
+ modules.add(helper);
+ }
+
+ /* get the "abc" modules */
+ xmlNodes = doc.getElementsByTagName(ABC_MODULE);
+ for (int i = 0; i < xmlNodes.getLength(); i++) {
+ Element node = (Element) xmlNodes.item(i);
+
+ IAnalysisModuleHelper helper = new OtherModuleHelperStub(xmlFile, node);
+ modules.add(helper);
+ }
+
+ return modules;
+ }
+
+}
<xs:documentation>Example type to extend the XML with new functionalities</xs:documentation>
</xs:annotation>
<xs:sequence>
+ <xs:element maxOccurs="1" minOccurs="0" name="head" type="headPattern" >
+ <xs:annotation>
+ <xs:documentation>Provides meta-information on this pattern provider, like labels and applicable trace types.</xs:documentation>
+ </xs:annotation>
+ </xs:element>
<xs:element maxOccurs="unbounded" minOccurs="0" name="mySubElement" type="xs:string">
<xs:annotation>
<xs:documentation>A sub-element to this new type</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
+ <xs:attribute name="id" type="xs:string" use="required" >
+ <xs:annotation>
+ <xs:documentation>The unique ID of this analysis. It will be used to identify the analysis that will be built from this element.</xs:documentation></xs:annotation>
+ </xs:attribute>
<xs:attribute name="name" type="xs:string" use="optional">
<xs:annotation>
<xs:documentation>An extra attribute</xs:documentation>
<tmfxml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="xmlDefinition.xsd">
- <my name="extended element 1">
+ <my id="extended.my" name="extended element 1">
<mySubElement>Test</mySubElement>
<mySubElement>Test2</mySubElement>
</my>
</entry>
</xyView>
- <abc name="extended element abc">
+ <abc id="extended.abc" name="extended element abc">
<mySubElement>Test</mySubElement>
<mySubElement>Test2</mySubElement>
</abc>
Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Bundle-Vendor: %Bundle-Vendor
-Bundle-Version: 2.1.1.qualifier
+Bundle-Version: 2.2.0.qualifier
Bundle-Localization: plugin
Bundle-SymbolicName: org.eclipse.tracecompass.tmf.analysis.xml.core;singleton:=true
Bundle-Activator: org.eclipse.tracecompass.internal.tmf.analysis.xml.core.Activator
org.eclipse.tracecompass.tmf.analysis.xml.ui.tests",
org.eclipse.tracecompass.internal.tmf.analysis.xml.core.pattern.stateprovider;x-friends:="org.eclipse.tracecompass.tmf.analysis.xml.ui,org.eclipse.tracecompass.tmf.analysis.xml.core.tests",
org.eclipse.tracecompass.internal.tmf.analysis.xml.core.segment;x-friends:="org.eclipse.tracecompass.tmf.analysis.xml.core.tests",
- org.eclipse.tracecompass.internal.tmf.analysis.xml.core.stateprovider;x-friends:="org.eclipse.tracecompass.tmf.analysis.xml.core.tests,org.eclipse.tracecompass.tmf.analysis.xml.ui"
+ org.eclipse.tracecompass.internal.tmf.analysis.xml.core.stateprovider;x-friends:="org.eclipse.tracecompass.tmf.analysis.xml.core.tests,org.eclipse.tracecompass.tmf.analysis.xml.ui",
+ org.eclipse.tracecompass.tmf.analysis.xml.core.module
Import-Package: com.google.common.collect,
org.apache.commons.io
<complexType>
<sequence>
<element ref="xsdfile" minOccurs="1" maxOccurs="unbounded"/>
+ <element ref="schemaParser" minOccurs="1" maxOccurs="unbounded"/>
</sequence>
<attribute name="point" type="string" use="required">
<annotation>
</complexType>
</element>
+ <element name="schemaParser">
+ <complexType>
+ <attribute name="class" type="string">
+ <annotation>
+ <documentation>
+ The class that contains the extra schema parsing information.
+ </documentation>
+ <appinfo>
+ <meta.attribute kind="java" basedOn=":org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.ITmfXmlSchemaParser"/>
+ </appinfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
<annotation>
<appinfo>
<meta.section type="since"/>
+++ /dev/null
-/*******************************************************************************
- * Copyright (c) 2014, 2016 École Polytechnique de Montréal
- *
- * All rights reserved. This program and the accompanying materials are
- * made available under the terms of the Eclipse Public License v1.0 which
- * accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *******************************************************************************/
-
-package org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module;
-
-import java.io.File;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.tracecompass.common.core.NonNullUtils;
-import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.Activator;
-import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.pattern.stateprovider.XmlPatternAnalysis;
-import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.stateprovider.TmfXmlStrings;
-import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.stateprovider.XmlStateSystemModule;
-import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule;
-import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModuleHelper;
-import org.eclipse.tracecompass.tmf.core.analysis.TmfAnalysisManager;
-import org.eclipse.tracecompass.tmf.core.analysis.requirements.TmfAbstractAnalysisRequirement;
-import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException;
-import org.eclipse.tracecompass.tmf.core.project.model.ITmfPropertiesProvider;
-import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType;
-import org.eclipse.tracecompass.tmf.core.project.model.TraceTypeHelper;
-import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
-import org.osgi.framework.Bundle;
-import org.w3c.dom.Element;
-
-/**
- * Analysis module helpers for modules provided by XML files
- *
- * @author Geneviève Bastien
- * @since 2.0
- */
-public class TmfAnalysisModuleHelperXml implements IAnalysisModuleHelper, ITmfPropertiesProvider {
-
- private static final String ICON_ANALYSIS = "/icons/analysis.png"; //$NON-NLS-1$
-
- /**
- * The types of analysis that can be XML-defined
- */
- public enum XmlAnalysisModuleType {
- /** Analysis will be of type XmlStateSystemModule */
- STATE_SYSTEM,
-
- /**
- * Analysis will be of type XmlPatternAnalysisModule
- *
- * @since 2.0
- */
- PATTERN
- }
-
- private final File fSourceFile;
- private final Element fSourceElement;
- private final XmlAnalysisModuleType fType;
-
- /**
- * Constructor
- *
- * @param xmlFile
- * The XML file containing the details of this analysis
- * @param node
- * The XML node element
- * @param type
- * The type of analysis
- */
- public TmfAnalysisModuleHelperXml(File xmlFile, Element node, XmlAnalysisModuleType type) {
- fSourceFile = xmlFile;
- fSourceElement = node;
- fType = type;
- }
-
- @Override
- public String getId() {
- /*
- * The attribute ID cannot be null because the XML has been validated
- * and it is mandatory
- */
- return fSourceElement.getAttribute(TmfXmlStrings.ID);
- }
-
- @Override
- public String getName() {
- String name = null;
- /* Label may be available in XML header */
- List<Element> head = XmlUtils.getChildElements(fSourceElement, TmfXmlStrings.HEAD);
- if (head.size() == 1) {
- List<Element> labels = XmlUtils.getChildElements(head.get(0), TmfXmlStrings.LABEL);
- if (!labels.isEmpty()) {
- name = labels.get(0).getAttribute(TmfXmlStrings.VALUE);
- }
- }
-
- if (name == null) {
- name = getId();
- }
- return name;
- }
-
- @Override
- public boolean isAutomatic() {
- return false;
- }
-
- /**
- * @since 1.0
- */
- @Override
- public boolean appliesToExperiment() {
- return false;
- }
-
- @Override
- public String getHelpText() {
- return ""; //$NON-NLS-1$
- }
-
- @Override
- public String getHelpText(@NonNull ITmfTrace trace) {
- return ""; //$NON-NLS-1$
- }
-
- @Override
- public String getIcon() {
- return ICON_ANALYSIS;
- }
-
- @Override
- public Bundle getBundle() {
- return Activator.getDefault().getBundle();
- }
-
- @Override
- public boolean appliesToTraceType(Class<? extends ITmfTrace> traceClass) {
- /* Trace types may be available in XML header */
- List<Element> head = XmlUtils.getChildElements(fSourceElement, TmfXmlStrings.HEAD);
- if (head.size() != 1) {
- return true;
- }
- /*
- * TODO: Test with custom trace types
- */
- List<Element> elements = XmlUtils.getChildElements(head.get(0), TmfXmlStrings.TRACETYPE);
- if (elements.isEmpty()) {
- return true;
- }
-
- for (Element element : elements) {
- String traceTypeId = element.getAttribute(TmfXmlStrings.ID);
- traceTypeId = TmfTraceType.buildCompatibilityTraceTypeId(traceTypeId);
- TraceTypeHelper helper = TmfTraceType.getTraceType(traceTypeId);
- if ((helper != null) && helper.getTrace().getClass().isAssignableFrom(traceClass)) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public Iterable<Class<? extends ITmfTrace>> getValidTraceTypes() {
- return Collections.EMPTY_SET;
- }
-
- @Override
- public Iterable<TmfAbstractAnalysisRequirement> getAnalysisRequirements() {
- return Collections.EMPTY_SET;
- }
-
- @Override
- public IAnalysisModule newModule(ITmfTrace trace) throws TmfAnalysisException {
- String analysisid = getId();
- IAnalysisModule module = null;
- switch (fType) {
- case STATE_SYSTEM:
- module = new XmlStateSystemModule();
- XmlStateSystemModule ssModule = (XmlStateSystemModule) module;
- module.setId(analysisid);
- ssModule.setXmlFile(fSourceFile.toPath());
-
- break;
- case PATTERN:
- module = new XmlPatternAnalysis();
- module.setName(getName());
- module.setId(analysisid);
- XmlPatternAnalysis paModule = (XmlPatternAnalysis) module;
- paModule.setXmlFile(fSourceFile.toPath());
-
- break;
- default:
- break;
-
- }
- if (module != null) {
- if (module.setTrace(trace)) {
- TmfAnalysisManager.analysisModuleCreated(module);
- } else {
- /* The analysis does not apply to the trace, dispose of the module */
- module.dispose();
- module = null;
- }
- }
-
- return module;
- }
-
- // ------------------------------------------------------------------------
- // ITmfPropertiesProvider
- // ------------------------------------------------------------------------
-
- @Override
- public @NonNull Map<@NonNull String, @NonNull String> getProperties() {
- Map<@NonNull String, @NonNull String> properties = new HashMap<>();
- properties.put(NonNullUtils.checkNotNull(Messages.XmlModuleHelper_PropertyFile), fSourceFile.getName());
- properties.put(NonNullUtils.checkNotNull(Messages.XmlModuleHelper_PropertyType), fType.name());
- return properties;
- }
-
-}
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.Activator;
-import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.TmfAnalysisModuleHelperXml.XmlAnalysisModuleType;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.stateprovider.TmfXmlStrings;
+import org.eclipse.tracecompass.tmf.analysis.xml.core.module.ITmfXmlSchemaParser;
+import org.eclipse.tracecompass.tmf.analysis.xml.core.module.TmfAnalysisModuleHelperXml;
+import org.eclipse.tracecompass.tmf.analysis.xml.core.module.TmfAnalysisModuleHelperXml.XmlAnalysisModuleType;
import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModuleHelper;
import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModuleSource;
import org.eclipse.tracecompass.tmf.core.analysis.TmfAnalysisManager;
return modules;
}
- private static void processFile(File xmlFile) {
+ private static void processFile(@NonNull File xmlFile) {
if (!XmlUtils.xmlValidate(xmlFile).isOK()) {
return;
}
IAnalysisModuleHelper helper = new TmfAnalysisModuleHelperXml(xmlFile, node, XmlAnalysisModuleType.PATTERN);
fModules.add(helper);
}
+
+ Iterable<ITmfXmlSchemaParser> extraSchemaParsers = XmlUtils.getExtraSchemaParsers();
+ for (ITmfXmlSchemaParser parser : extraSchemaParsers) {
+ fModules.addAll(parser.getModuleHelpers(xmlFile, doc));
+ }
} catch (ParserConfigurationException | SAXException | IOException e) {
Activator.logError("Error opening XML file", e); //$NON-NLS-1$
}
private static void populateBuiltinModules() {
Map<String, IPath> files = XmlUtils.listBuiltinFiles();
for (IPath xmlPath : files.values()) {
- processFile(xmlPath.toFile());
+ processFile(NonNullUtils.checkNotNull(xmlPath.toFile()));
}
}
}
}
}
- Map<String, File> files = XmlUtils.listFiles();
+ Map<String, @NonNull File> files = XmlUtils.listFiles();
for (File xmlFile : files.values()) {
processFile(xmlFile);
}
import java.net.URL;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import javax.xml.validation.Validator;
import org.apache.commons.io.FilenameUtils;
+import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IPath;
import org.eclipse.tracecompass.common.core.NonNullUtils;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.Activator;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.stateprovider.TmfXmlStrings;
+import org.eclipse.tracecompass.tmf.analysis.xml.core.module.ITmfXmlSchemaParser;
import org.osgi.framework.Bundle;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
private static final String TMF_XSD_ID = "org.eclipse.tracecompass.tmf.analysis.xml.core.xsd"; //$NON-NLS-1$
private static final String XSD_FILE_ELEMENT = "xsdfile"; //$NON-NLS-1$
private static final String XSD_FILE_ATTRIB = "file"; //$NON-NLS-1$
+ private static final String XSD_SCHEMA_PARSER_ELEMENT = "schemaParser"; //$NON-NLS-1$
+ private static final String XSD_PARSER_CLASS_ATTRIB = "class"; //$NON-NLS-1$
/**
* Extension for XML files
*
* @return A map with all the XML analysis files
*/
- public static synchronized @NonNull Map<String, File> listFiles() {
+ public static synchronized @NonNull Map<@NonNull String, @NonNull File> listFiles() {
IPath pathToFiles = XmlUtils.getXmlFilesPath();
File folder = pathToFiles.toFile();
- Map<String, File> fileMap = new HashMap<>();
+ Map<@NonNull String, @NonNull File> fileMap = new HashMap<>();
if ((folder.isDirectory() && folder.exists())) {
File[] listOfFiles = folder.listFiles();
if (listOfFiles != null) {
return list;
}
+ /**
+ * List all the additional files advertised through the XSD extension point
+ *
+ * @return A map with all the XMl analysis builtin files
+ */
+ public static synchronized @NonNull Collection<ITmfXmlSchemaParser> getExtraSchemaParsers() {
+ /* Get the XSD files advertised through the extension point */
+ IConfigurationElement[] elements = Platform.getExtensionRegistry().getConfigurationElementsFor(TMF_XSD_ID);
+ List<org.eclipse.tracecompass.tmf.analysis.xml.core.module.ITmfXmlSchemaParser> list = new ArrayList<>();
+ for (IConfigurationElement element : elements) {
+ if (element.getName().equals(XSD_SCHEMA_PARSER_ELEMENT)) {
+ try {
+ ITmfXmlSchemaParser parser = NonNullUtils.checkNotNull((ITmfXmlSchemaParser) element.createExecutableExtension(XSD_PARSER_CLASS_ATTRIB));
+ list.add(parser);
+ } catch (CoreException e) {
+ Activator.logError("Error getting analysis modules from configuration files", e); //$NON-NLS-1$
+ }
+ }
+ }
+ return list;
+ }
+
/**
* Delete an XML analysis file
*
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2017 École Polytechnique de Montréal
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.tmf.analysis.xml.core.module;
+
+import java.io.File;
+import java.util.Collection;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModuleHelper;
+import org.w3c.dom.Document;
+
+/**
+ * An interface to be implemented by classes that parse XML files to additional
+ * analyses provided by schemas advertised through the extension point. Each
+ * additional XSD schema should be accompanied by at least one schema parser
+ * class.
+ *
+ * @author Geneviève Bastien
+ * @since 2.2
+ */
+@NonNullByDefault
+public interface ITmfXmlSchemaParser {
+
+ /**
+ * Parses the XML document to get any additional analysis module it may
+ * contain. The helper may extend {@link TmfAnalysisModuleHelperXml} or can
+ * implement their own helper.
+ *
+ * @param xmlFile
+ * The XML file from which the document was read
+ * @param doc
+ * The XML document to get the modules from
+ * @return The list of modules parsed by this parser
+ */
+ Collection<? extends IAnalysisModuleHelper> getModuleHelpers(File xmlFile, Document doc);
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2014, 2016 École Polytechnique de Montréal
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.tmf.analysis.xml.core.module;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
+import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.Activator;
+import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.Messages;
+import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.XmlUtils;
+import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.pattern.stateprovider.XmlPatternAnalysis;
+import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.stateprovider.TmfXmlStrings;
+import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.stateprovider.XmlStateSystemModule;
+import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule;
+import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModuleHelper;
+import org.eclipse.tracecompass.tmf.core.analysis.TmfAnalysisManager;
+import org.eclipse.tracecompass.tmf.core.analysis.requirements.TmfAbstractAnalysisRequirement;
+import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException;
+import org.eclipse.tracecompass.tmf.core.project.model.ITmfPropertiesProvider;
+import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType;
+import org.eclipse.tracecompass.tmf.core.project.model.TraceTypeHelper;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.osgi.framework.Bundle;
+import org.w3c.dom.Element;
+
+/**
+ * Analysis module helpers for modules provided by XML files
+ *
+ * @author Geneviève Bastien
+ * @since 2.2
+ */
+public class TmfAnalysisModuleHelperXml implements IAnalysisModuleHelper, ITmfPropertiesProvider {
+
+ private static final String ICON_ANALYSIS = "/icons/analysis.png"; //$NON-NLS-1$
+
+ /**
+ * The types of analysis that can be XML-defined
+ */
+ public enum XmlAnalysisModuleType {
+ /** Analysis will be of type XmlStateSystemModule */
+ STATE_SYSTEM,
+
+ /**
+ * Analysis will be of type XmlPatternAnalysisModule
+ */
+ PATTERN,
+ /**
+ * Analysis is of type other.
+ */
+ OTHER
+ }
+
+ private final File fSourceFile;
+ private final Element fSourceElement;
+ private final XmlAnalysisModuleType fType;
+
+ /**
+ * Constructor
+ *
+ * @param xmlFile
+ * The XML file containing the details of this analysis
+ * @param node
+ * The XML node element
+ * @param type
+ * The type of analysis
+ */
+ public TmfAnalysisModuleHelperXml(File xmlFile, Element node, XmlAnalysisModuleType type) {
+ fSourceFile = xmlFile;
+ fSourceElement = node;
+ fType = type;
+ }
+
+ @Override
+ public String getId() {
+ /*
+ * The attribute ID cannot be null because the XML has been validated
+ * and it is mandatory
+ */
+ return fSourceElement.getAttribute(TmfXmlStrings.ID);
+ }
+
+ @Override
+ public String getName() {
+ String name = null;
+ /* Label may be available in XML header */
+ List<Element> head = XmlUtils.getChildElements(fSourceElement, TmfXmlStrings.HEAD);
+ if (head.size() == 1) {
+ List<Element> labels = XmlUtils.getChildElements(head.get(0), TmfXmlStrings.LABEL);
+ if (!labels.isEmpty()) {
+ name = labels.get(0).getAttribute(TmfXmlStrings.VALUE);
+ }
+ }
+
+ if (name == null) {
+ name = getId();
+ }
+ return name;
+ }
+
+ @Override
+ public boolean isAutomatic() {
+ return false;
+ }
+
+ @Override
+ public boolean appliesToExperiment() {
+ return false;
+ }
+
+ @Override
+ public String getHelpText() {
+ return ""; //$NON-NLS-1$
+ }
+
+ @Override
+ public String getHelpText(@NonNull ITmfTrace trace) {
+ return ""; //$NON-NLS-1$
+ }
+
+ @Override
+ public String getIcon() {
+ return ICON_ANALYSIS;
+ }
+
+ @Override
+ public Bundle getBundle() {
+ return Activator.getDefault().getBundle();
+ }
+
+ @Override
+ public boolean appliesToTraceType(Class<? extends ITmfTrace> traceClass) {
+ /* Trace types may be available in XML header */
+ List<Element> head = XmlUtils.getChildElements(fSourceElement, TmfXmlStrings.HEAD);
+ if (head.size() != 1) {
+ return true;
+ }
+ /*
+ * TODO: Test with custom trace types
+ */
+ List<Element> elements = XmlUtils.getChildElements(head.get(0), TmfXmlStrings.TRACETYPE);
+ if (elements.isEmpty()) {
+ return true;
+ }
+
+ for (Element element : elements) {
+ String traceTypeId = element.getAttribute(TmfXmlStrings.ID);
+ traceTypeId = TmfTraceType.buildCompatibilityTraceTypeId(traceTypeId);
+ TraceTypeHelper helper = TmfTraceType.getTraceType(traceTypeId);
+ if ((helper != null) && helper.getTrace().getClass().isAssignableFrom(traceClass)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public Iterable<Class<? extends ITmfTrace>> getValidTraceTypes() {
+ return Collections.EMPTY_SET;
+ }
+
+ @Override
+ public Iterable<TmfAbstractAnalysisRequirement> getAnalysisRequirements() {
+ return Collections.EMPTY_SET;
+ }
+
+ @Override
+ public final @Nullable IAnalysisModule newModule(ITmfTrace trace) throws TmfAnalysisException {
+ String analysisid = getId();
+ IAnalysisModule module = null;
+ switch (fType) {
+ case STATE_SYSTEM:
+ module = new XmlStateSystemModule();
+ XmlStateSystemModule ssModule = (XmlStateSystemModule) module;
+ module.setId(analysisid);
+ ssModule.setXmlFile(fSourceFile.toPath());
+
+ break;
+ case PATTERN:
+ module = new XmlPatternAnalysis();
+ module.setName(getName());
+ module.setId(analysisid);
+ XmlPatternAnalysis paModule = (XmlPatternAnalysis) module;
+ paModule.setXmlFile(fSourceFile.toPath());
+
+ break;
+ case OTHER:
+ String name = getName();
+ module = createOtherModule(analysisid, name);
+ break;
+ default:
+ break;
+
+ }
+ if (module != null) {
+ if (module.setTrace(trace)) {
+ TmfAnalysisManager.analysisModuleCreated(module);
+ } else {
+ /*
+ * The analysis does not apply to the trace, dispose of the
+ * module
+ */
+ module.dispose();
+ module = null;
+ }
+ }
+
+ return module;
+ }
+
+ /**
+ * Create an analysis module from a type not provided by the main XML code.
+ * Typically a plugin that provides new schema information through the xsd
+ * extension point will also provide a schema parser. The schema parser may
+ * create a module helper for a module of type OTHER that will override this
+ * method.
+ *
+ * The returned module should have its name and id initialized and any other
+ * specific information. Values for analysisid and name are provided in
+ * parameter using the pattern of mandatory ID attribute in the main element
+ * and an optional {@link TmfXmlStrings#HEAD} element in the sequence. But
+ * the analysis is free to override those. The trace will be set later.
+ *
+ * @param analysisid
+ * The analysis ID, as found in the ID attribute of the analysis
+ * element
+ * @param name
+ * The name of the analysis as obtained from calling the
+ * {@link #getName()} method.
+ *
+ * @return The newly created module
+ */
+ protected IAnalysisModule createOtherModule(@NonNull String analysisid, @NonNull String name) {
+ throw new UnsupportedOperationException("Other modules should be implemented by their own helper classes"); //$NON-NLS-1$
+ }
+
+ /**
+ * Get the source file where this XML element was found
+ *
+ * @return The source file
+ */
+ protected Path getSourceFile() {
+ return fSourceFile.toPath();
+ }
+
+ /**
+ * Get the source element for this module
+ *
+ * @return The source element for this module
+ */
+ protected Element getSourceElement() {
+ return fSourceElement;
+ }
+
+ // ------------------------------------------------------------------------
+ // ITmfPropertiesProvider
+ // ------------------------------------------------------------------------
+
+ @Override
+ public @NonNull Map<@NonNull String, @NonNull String> getProperties() {
+ Map<@NonNull String, @NonNull String> properties = new HashMap<>();
+ properties.put(NonNullUtils.checkNotNull(Messages.XmlModuleHelper_PropertyFile), fSourceFile.getName());
+ properties.put(NonNullUtils.checkNotNull(Messages.XmlModuleHelper_PropertyType), fType.name());
+ return properties;
+ }
+
+}