TMF: Introduce the XML state provider for data driven analysis
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.analysis.xml.core / src / org / eclipse / linuxtools / tmf / analysis / xml / core / stateprovider / XmlStateProvider.java
1 /*******************************************************************************
2 * Copyright (c) 2014 École Polytechnique de Montréal
3 *
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * Florian Wininger - Initial API and implementation
11 *******************************************************************************/
12
13 package org.eclipse.linuxtools.tmf.analysis.xml.core.stateprovider;
14
15 import java.io.File;
16 import java.io.IOException;
17 import java.util.Collections;
18 import java.util.HashMap;
19 import java.util.HashSet;
20 import java.util.Map;
21 import java.util.Set;
22
23 import javax.xml.parsers.DocumentBuilder;
24 import javax.xml.parsers.DocumentBuilderFactory;
25 import javax.xml.parsers.ParserConfigurationException;
26
27 import org.eclipse.core.runtime.IPath;
28 import org.eclipse.linuxtools.internal.tmf.analysis.xml.core.Activator;
29 import org.eclipse.linuxtools.internal.tmf.analysis.xml.core.stateprovider.model.TmfXmlEventHandler;
30 import org.eclipse.linuxtools.internal.tmf.analysis.xml.core.stateprovider.model.TmfXmlLocation;
31 import org.eclipse.linuxtools.tmf.analysis.xml.core.module.Messages;
32 import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
33 import org.eclipse.linuxtools.tmf.core.statesystem.AbstractTmfStateProvider;
34 import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystemBuilder;
35 import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
36 import org.eclipse.osgi.util.NLS;
37 import org.w3c.dom.Document;
38 import org.w3c.dom.Element;
39 import org.w3c.dom.Node;
40 import org.w3c.dom.NodeList;
41 import org.xml.sax.SAXException;
42
43 /**
44 * This is the state change input plug-in for TMF's state system which handles
45 * the XML Format
46 *
47 * @author Florian Wininger
48 */
49 public class XmlStateProvider extends AbstractTmfStateProvider {
50
51 /** Root quark, to get values at the root of the state system */
52 public static final int ROOT_QUARK = -1;
53 /**
54 * Error quark, value taken when a state system quark query is in error.
55 *
56 * FIXME: Originally in the code, the -1 was used for both root quark and
57 * return errors, so it has the same value as root quark, but maybe it can
58 * be changed to something else -2? A quark can never be negative
59 */
60 public static final int ERROR_QUARK = -1;
61
62 private final IPath fFilePath;
63 private final String fStateId;
64
65 /** List of all Event Handlers */
66 private final Set<TmfXmlEventHandler> fEventHandlers = new HashSet<>();
67
68 /** List of all Locations */
69 private final Set<TmfXmlLocation> fLocations;
70
71 /** Map for defined values */
72 private final Map<String, String> fDefinedValues = new HashMap<>();
73
74 // ------------------------------------------------------------------------
75 // Constructor
76 // ------------------------------------------------------------------------
77
78 /**
79 * Instantiate a new state provider plug-in.
80 *
81 * @param trace
82 * The trace
83 * @param stateid
84 * The state system id, corresponding to the analysis_id
85 * attribute of the state provider element of the XML file
86 * @param file
87 * Path to the XML file containing the state provider definition
88 */
89 public XmlStateProvider(ITmfTrace trace, String stateid, IPath file) {
90 super(trace, ITmfEvent.class, stateid);
91 fStateId = stateid;
92 fFilePath = file;
93 Element doc = loadXMLNode();
94 if (doc == null) {
95 fLocations = new HashSet<>();
96 return;
97 }
98
99 /* parser for defined Values */
100 NodeList definedStateNodes = doc.getElementsByTagName(TmfXmlStrings.DEFINED_VALUE);
101 for (int i = 0; i < definedStateNodes.getLength(); i++) {
102 Element element = (Element) definedStateNodes.item(i);
103 fDefinedValues.put(element.getAttribute(TmfXmlStrings.NAME), element.getAttribute(TmfXmlStrings.VALUE));
104 }
105
106 /* parser for the locations */
107 NodeList locationNodes = doc.getElementsByTagName(TmfXmlStrings.LOCATION);
108 Set<TmfXmlLocation> locations = new HashSet<>();
109 for (int i = 0; i < locationNodes.getLength(); i++) {
110 Element element = (Element) locationNodes.item(i);
111 TmfXmlLocation location = new TmfXmlLocation(element, this);
112 locations.add(location);
113 }
114 fLocations = Collections.unmodifiableSet(locations);
115
116 /* parser for the event handlers */
117 NodeList nodes = doc.getElementsByTagName(TmfXmlStrings.EVENT_HANDLER);
118 for (int i = 0; i < nodes.getLength(); i++) {
119 Element element = (Element) nodes.item(i);
120 TmfXmlEventHandler handler = new TmfXmlEventHandler(element, this);
121 fEventHandlers.add(handler);
122 }
123 }
124
125 /**
126 * Get the state id of the state provider
127 *
128 * @return The state id of the state provider
129 */
130 public String getStateId() {
131 return fStateId;
132 }
133
134 // ------------------------------------------------------------------------
135 // IStateChangeInput
136 // ------------------------------------------------------------------------
137
138 @Override
139 public int getVersion() {
140 Node ssNode = loadXMLNode();
141 if (ssNode instanceof Element) {
142 Element element = (Element) ssNode;
143 return Integer.valueOf(element.getAttribute(TmfXmlStrings.VERSION));
144 }
145 /*
146 * The version attribute is mandatory and XML files that don't validate
147 * with the XSD are ignored, so this should never happen
148 */
149 throw new IllegalStateException("The state provider XML node should have a version attribute"); //$NON-NLS-1$
150 }
151
152 @Override
153 public XmlStateProvider getNewInstance() {
154 return new XmlStateProvider(this.getTrace(), getStateId(), fFilePath);
155 }
156
157 @Override
158 protected void eventHandle(ITmfEvent event) {
159 if (event == null) {
160 return;
161 }
162 for (TmfXmlEventHandler eventHandler : fEventHandlers) {
163 eventHandler.handleEvent(event);
164 }
165 }
166
167 @Override
168 public ITmfStateSystemBuilder getAssignedStateSystem() {
169 return ss;
170 }
171
172 // ------------------------------------------------------------------------
173 // Operations
174 // ------------------------------------------------------------------------
175
176 /**
177 * Loads the XML file and returns the element at the root of the current
178 * state provider.
179 *
180 * @return The XML node at the root of the state provider
181 */
182 private Element loadXMLNode() {
183
184 try {
185 File XMLFile = fFilePath.toFile();
186 if (XMLFile == null || !XMLFile.exists() || !XMLFile.isFile()) {
187 return null;
188 }
189
190 /* Load the XML File */
191 DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
192 DocumentBuilder dBuilder;
193
194 dBuilder = dbFactory.newDocumentBuilder();
195 Document doc = dBuilder.parse(XMLFile);
196 doc.getDocumentElement().normalize();
197
198 /* get the state providers and find the corresponding one */
199 NodeList stateproviderNodes = doc.getElementsByTagName(TmfXmlStrings.STATE_PROVIDER);
200 Element stateproviderNode = null;
201
202 for (int i = 0; i < stateproviderNodes.getLength(); i++) {
203 Element node = (Element) stateproviderNodes.item(i);
204 String analysisid = node.getAttribute(TmfXmlStrings.ANALYSIS_ID);
205 if (analysisid.equals(fStateId)) {
206 stateproviderNode = node;
207 }
208 }
209
210 return stateproviderNode;
211 } catch (ParserConfigurationException | IOException e) {
212 Activator.logError("Error loading XML file", e); //$NON-NLS-1$
213 } catch (SAXException e) {
214 Activator.logError(NLS.bind(Messages.XmlUtils_XmlValidationError, e.getLocalizedMessage()), e);
215 }
216
217 return null;
218 }
219
220 /**
221 * Get the list of locations defined in this state provider
222 *
223 * @return The list of {@link TmfXmlLocation}
224 */
225 public Iterable<TmfXmlLocation> getLocations() {
226 return fLocations;
227 }
228
229 /**
230 * Get the defined value associated with a constant
231 *
232 * @param constant
233 * The constant defining this value
234 * @return The actual value corresponding to this constant
235 */
236 public String getDefinedValue(String constant) {
237 return fDefinedValues.get(constant);
238 }
239
240 /**
241 * Get the requested value for an attribute. If the value is a pre-defined
242 * value, we return the string corresponding in the defined values map.
243 *
244 * @param name
245 * the string to get
246 * @return the actual string value
247 */
248 public String getAttributeValue(String name) {
249 String attribute = name;
250 if (attribute.startsWith(TmfXmlStrings.VARIABLE_PREFIX)) {
251 /* search the attribute in the map without the fist character $ */
252 attribute = getDefinedValue(attribute.substring(1));
253 }
254 return attribute;
255 }
256
257 }
This page took 0.051221 seconds and 6 git commands to generate.