Remove unneeded checkNotNull() calls
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.core / src / org / eclipse / tracecompass / tmf / core / parsers / custom / CustomTxtTraceDefinition.java
CommitLineData
be222f56 1/*******************************************************************************
c9b31f60 2 * Copyright (c) 2010, 2015 Ericsson
be222f56
PT
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 * Patrick Tasse - Initial API and implementation
890916ec 11 * Matthew Khouzam - Add support for default parsers
be222f56
PT
12 *******************************************************************************/
13
2bdf0193 14package org.eclipse.tracecompass.tmf.core.parsers.custom;
be222f56 15
7a0b1e3c
PT
16import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
17
be222f56
PT
18import java.io.File;
19import java.io.FileWriter;
20import java.io.IOException;
21import java.io.StringWriter;
22import java.util.ArrayList;
890916ec
MK
23import java.util.Arrays;
24import java.util.Comparator;
be222f56
PT
25import java.util.List;
26import java.util.Map;
890916ec
MK
27import java.util.Set;
28import java.util.TreeSet;
be222f56
PT
29import java.util.regex.Pattern;
30import java.util.regex.PatternSyntaxException;
31
32import javax.xml.parsers.DocumentBuilder;
33import javax.xml.parsers.DocumentBuilderFactory;
34import javax.xml.parsers.ParserConfigurationException;
35import javax.xml.transform.OutputKeys;
36import javax.xml.transform.Transformer;
37import javax.xml.transform.TransformerConfigurationException;
38import javax.xml.transform.TransformerException;
39import javax.xml.transform.TransformerFactory;
40import javax.xml.transform.TransformerFactoryConfigurationError;
41import javax.xml.transform.dom.DOMSource;
42import javax.xml.transform.stream.StreamResult;
43
890916ec 44import org.eclipse.core.runtime.Platform;
2bdf0193
AM
45import org.eclipse.tracecompass.internal.tmf.core.Activator;
46import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType;
be222f56
PT
47import org.w3c.dom.Document;
48import org.w3c.dom.Element;
49import org.w3c.dom.Node;
50import org.w3c.dom.NodeList;
be222f56 51import org.xml.sax.SAXException;
be222f56 52
a0a88f65
AM
53/**
54 * Trace definition for custom text traces.
55 *
56 * @author Patrick Tassé
57 */
be222f56
PT
58public class CustomTxtTraceDefinition extends CustomTraceDefinition {
59
a0a88f65
AM
60 /** Input lines */
61 public List<InputLine> inputs;
62
c9b31f60
BH
63 /**
64 * Custom text label used internally and therefore should not be
65 * externalized
66 */
67 public static final String CUSTOM_TXT_CATEGORY = "Custom Text"; //$NON-NLS-1$
68
69
890916ec
MK
70 /** File name of the default definition file */
71 protected static final String CUSTOM_TXT_TRACE_DEFINITIONS_DEFAULT_FILE_NAME = "custom_txt_default_parsers.xml"; //$NON-NLS-1$
a0a88f65 72 /** File name of the definition file */
be222f56 73 protected static final String CUSTOM_TXT_TRACE_DEFINITIONS_FILE_NAME = "custom_txt_parsers.xml"; //$NON-NLS-1$
a0a88f65 74
890916ec
MK
75 /** Path of the definition file */
76 protected static final String CUSTOM_TXT_TRACE_DEFINITIONS_DEFAULT_PATH_NAME =
cb1cf0e8
MK
77 Platform.getInstallLocation().getURL().getPath() + "templates/org.eclipse.linuxtools.tmf.core/" + //$NON-NLS-1$
78 CUSTOM_TXT_TRACE_DEFINITIONS_DEFAULT_FILE_NAME;
a0a88f65 79 /** Path of the definition file */
be222f56 80 protected static final String CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME =
890916ec 81 Activator.getDefault().getStateLocation().addTrailingSeparator().append(CUSTOM_TXT_TRACE_DEFINITIONS_FILE_NAME).toString();
be222f56 82
cb1cf0e8 83 /**
c9b31f60 84 * Legacy path to the XML definitions file (in the UI plug-in of linuxtools) TODO Remove
cb1cf0e8
MK
85 * once we feel the transition phase is over.
86 */
c9b31f60 87 private static final String CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME_LEGACY_UI =
03573754
AM
88 Activator.getDefault().getStateLocation().removeLastSegments(1).addTrailingSeparator()
89 .append("org.eclipse.linuxtools.tmf.ui") //$NON-NLS-1$
90 .append(CUSTOM_TXT_TRACE_DEFINITIONS_FILE_NAME).toString();
91
c9b31f60
BH
92 /**
93 * Legacy path to the XML definitions file (in the core plug-in of linuxtools) TODO Remove
94 * once we feel the transition phase is over.
95 */
96 private static final String CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME_LEGACY_CORE =
97 Activator.getDefault().getStateLocation().removeLastSegments(1).addTrailingSeparator()
98 .append("org.eclipse.linuxtools.tmf.core") //$NON-NLS-1$
99 .append(CUSTOM_TXT_TRACE_DEFINITIONS_FILE_NAME).toString();
100
be222f56
PT
101 private static final String CUSTOM_TXT_TRACE_DEFINITION_ROOT_ELEMENT = Messages.CustomTxtTraceDefinition_definitionRootElement;
102 private static final String DEFINITION_ELEMENT = Messages.CustomTxtTraceDefinition_definition;
332527a4 103 private static final String CATEGORY_ATTRIBUTE = Messages.CustomTxtTraceDefinition_category;
be222f56
PT
104 private static final String NAME_ATTRIBUTE = Messages.CustomTxtTraceDefinition_name;
105 private static final String TIME_STAMP_OUTPUT_FORMAT_ELEMENT = Messages.CustomTxtTraceDefinition_timestampOutputFormat;
106 private static final String INPUT_LINE_ELEMENT = Messages.CustomTxtTraceDefinition_inputLine;
107 private static final String CARDINALITY_ELEMENT = Messages.CustomTxtTraceDefinition_cardinality;
108 private static final String MIN_ATTRIBUTE = Messages.CustomTxtTraceDefinition_min;
109 private static final String MAX_ATTRIBUTE = Messages.CustomTxtTraceDefinition_max;
110 private static final String REGEX_ELEMENT = Messages.CustomTxtTraceDefinition_regEx;
111 private static final String INPUT_DATA_ELEMENT = Messages.CustomTxtTraceDefinition_inputData;
112 private static final String ACTION_ATTRIBUTE = Messages.CustomTxtTraceDefinition_action;
113 private static final String FORMAT_ATTRIBUTE = Messages.CustomTxtTraceDefinition_format;
114 private static final String OUTPUT_COLUMN_ELEMENT = Messages.CustomTxtTraceDefinition_outputColumn;
115
a0a88f65
AM
116 /**
117 * Default constructor.
118 */
be222f56 119 public CustomTxtTraceDefinition() {
c9b31f60 120 this(CUSTOM_TXT_CATEGORY, "", new ArrayList<InputLine>(0), new ArrayList<OutputColumn>(0), ""); //$NON-NLS-1$ //$NON-NLS-2$
be222f56
PT
121 }
122
332527a4
PT
123 /**
124 * Full constructor.
125 *
126 * @param category
127 * Category of the trace type
128 * @param traceType
129 * Name of the trace type
130 * @param inputs
131 * List of inputs
132 * @param outputs
133 * List of output columns
134 * @param timeStampOutputFormat
135 * The timestamp format to use
332527a4
PT
136 */
137 public CustomTxtTraceDefinition(String category, String traceType, List<InputLine> inputs,
138 List<OutputColumn> outputs, String timeStampOutputFormat) {
139 this.categoryName = category;
140 this.definitionName = traceType;
be222f56
PT
141 this.inputs = inputs;
142 this.outputs = outputs;
143 this.timeStampOutputFormat = timeStampOutputFormat;
144 }
145
a0a88f65
AM
146 /**
147 * Wrapper to store a line of the log file
148 */
be222f56 149 public static class InputLine {
a0a88f65
AM
150
151 /** Data columns of this line */
be222f56 152 public List<InputData> columns;
a0a88f65
AM
153
154 /** Cardinality of this line (see {@link Cardinality}) */
be222f56 155 public Cardinality cardinality;
a0a88f65
AM
156
157 /** Parent line */
be222f56 158 public InputLine parentInput;
a0a88f65
AM
159
160 /** Level of this line */
be222f56 161 public int level;
a0a88f65
AM
162
163 /** Next input line in the file */
be222f56 164 public InputLine nextInput;
a0a88f65
AM
165
166 /** Children of this line (if one "event" spans many lines) */
be222f56
PT
167 public List<InputLine> childrenInputs;
168
a0a88f65
AM
169 private String regex;
170 private Pattern pattern;
171
172 /**
173 * Default (empty) constructor.
174 */
cb1cf0e8
MK
175 public InputLine() {
176 }
be222f56 177
a0a88f65
AM
178 /**
179 * Constructor.
180 *
cb1cf0e8
MK
181 * @param cardinality
182 * Cardinality of this line.
183 * @param regex
184 * Regex
185 * @param columns
186 * Columns to use
a0a88f65 187 */
be222f56
PT
188 public InputLine(Cardinality cardinality, String regex, List<InputData> columns) {
189 this.cardinality = cardinality;
190 this.regex = regex;
191 this.columns = columns;
192 }
193
a0a88f65
AM
194 /**
195 * Set the regex of this input line
196 *
197 * @param regex
198 * Regex to set
199 */
be222f56
PT
200 public void setRegex(String regex) {
201 this.regex = regex;
202 this.pattern = null;
203 }
204
a0a88f65
AM
205 /**
206 * Get the current regex
207 *
208 * @return The current regex
209 */
be222f56
PT
210 public String getRegex() {
211 return regex;
212 }
213
a0a88f65
AM
214 /**
215 * Get the Pattern object of this line's regex
216 *
217 * @return The Pattern
218 * @throws PatternSyntaxException
219 * If the regex does not parse correctly
220 */
be222f56
PT
221 public Pattern getPattern() throws PatternSyntaxException {
222 if (pattern == null) {
223 pattern = Pattern.compile(regex);
224 }
225 return pattern;
226 }
227
a0a88f65
AM
228 /**
229 * Add a child line to this line.
230 *
231 * @param input
232 * The child input line
233 */
be222f56
PT
234 public void addChild(InputLine input) {
235 if (childrenInputs == null) {
507b1336 236 childrenInputs = new ArrayList<>(1);
be222f56
PT
237 } else if (childrenInputs.size() > 0) {
238 InputLine last = childrenInputs.get(childrenInputs.size() - 1);
239 last.nextInput = input;
240 }
241 childrenInputs.add(input);
242 input.parentInput = this;
243 input.level = this.level + 1;
244 }
245
a0a88f65
AM
246 /**
247 * Set the next input line.
248 *
249 * @param input
250 * The next input line
251 */
be222f56
PT
252 public void addNext(InputLine input) {
253 if (parentInput != null) {
254 int index = parentInput.childrenInputs.indexOf(this);
255 parentInput.childrenInputs.add(index + 1, input);
256 InputLine next = nextInput;
257 nextInput = input;
258 input.nextInput = next;
259 }
260 input.parentInput = this.parentInput;
261 input.level = this.level;
262 }
263
a0a88f65
AM
264 /**
265 * Move this line up in its parent's children.
266 */
be222f56
PT
267 public void moveUp() {
268 if (parentInput != null) {
269 int index = parentInput.childrenInputs.indexOf(this);
270 if (index > 0) {
890916ec 271 parentInput.childrenInputs.add(index - 1, parentInput.childrenInputs.remove(index));
be222f56
PT
272 parentInput.childrenInputs.get(index).nextInput = nextInput;
273 nextInput = parentInput.childrenInputs.get(index);
274 }
275 }
276 }
277
a0a88f65
AM
278 /**
279 * Move this line down in its parent's children.
280 */
be222f56
PT
281 public void moveDown() {
282 if (parentInput != null) {
283 int index = parentInput.childrenInputs.indexOf(this);
284 if (index < parentInput.childrenInputs.size() - 1) {
890916ec 285 parentInput.childrenInputs.add(index + 1, parentInput.childrenInputs.remove(index));
be222f56
PT
286 nextInput = parentInput.childrenInputs.get(index).nextInput;
287 parentInput.childrenInputs.get(index).nextInput = this;
288 }
289 }
290 }
291
a0a88f65
AM
292 /**
293 * Add a data column to this line
294 *
295 * @param column
296 * The column to add
297 */
be222f56
PT
298 public void addColumn(InputData column) {
299 if (columns == null) {
507b1336 300 columns = new ArrayList<>(1);
be222f56
PT
301 }
302 columns.add(column);
303 }
304
a0a88f65
AM
305 /**
306 * Get the next input lines.
307 *
308 * @param countMap
309 * The map of line "sets".
310 * @return The next list of lines.
311 */
be222f56 312 public List<InputLine> getNextInputs(Map<InputLine, Integer> countMap) {
507b1336 313 List<InputLine> nextInputs = new ArrayList<>();
be222f56
PT
314 InputLine next = nextInput;
315 while (next != null) {
316 nextInputs.add(next);
317 if (next.cardinality.min > 0) {
318 return nextInputs;
319 }
320 next = next.nextInput;
321 }
322 if (parentInput != null && parentInput.level > 0) {
202956f1 323 int parentCount = checkNotNull(countMap.get(parentInput));
be222f56
PT
324 if (parentCount < parentInput.getMaxCount()) {
325 nextInputs.add(parentInput);
326 }
327 if (parentCount < parentInput.getMinCount()) {
328 return nextInputs;
329 }
330 nextInputs.addAll(parentInput.getNextInputs(countMap));
331 }
332 return nextInputs;
333 }
334
a0a88f65
AM
335 /**
336 * Get the minimum possible amount of entries.
337 *
338 * @return The minimum
339 */
be222f56
PT
340 public int getMinCount() {
341 return cardinality.min;
342 }
343
a0a88f65
AM
344 /**
345 * Get the maximum possible amount of entries.
346 *
347 * @return The maximum
348 */
be222f56
PT
349 public int getMaxCount() {
350 return cardinality.max;
351 }
352
353 @Override
354 public String toString() {
355 return regex + " " + cardinality; //$NON-NLS-1$
356 }
be222f56
PT
357 }
358
a0a88f65
AM
359 /**
360 * Data column for input lines.
361 */
be222f56 362 public static class InputData {
a0a88f65
AM
363
364 /** Name of this column */
be222f56 365 public String name;
a0a88f65
AM
366
367 /** Action id */
be222f56 368 public int action;
a0a88f65
AM
369
370 /** Format */
be222f56
PT
371 public String format;
372
a0a88f65
AM
373 /**
374 * Default (empty) constructor
375 */
cb1cf0e8
MK
376 public InputData() {
377 }
be222f56 378
a0a88f65
AM
379 /**
380 * Full constructor
381 *
cb1cf0e8
MK
382 * @param name
383 * Name
384 * @param action
385 * Action
386 * @param format
387 * Format
a0a88f65 388 */
be222f56
PT
389 public InputData(String name, int action, String format) {
390 this.name = name;
391 this.action = action;
392 this.format = format;
393 }
394
a0a88f65
AM
395 /**
396 * Constructor with default format
397 *
cb1cf0e8
MK
398 * @param name
399 * Name
400 * @param action
401 * Action
a0a88f65 402 */
be222f56
PT
403 public InputData(String name, int action) {
404 this.name = name;
405 this.action = action;
406 }
407 }
408
a0a88f65
AM
409 /**
410 * Input line cardinality
411 */
be222f56 412 public static class Cardinality {
a0a88f65
AM
413
414 /** Representation of infinity */
978d20f1 415 public static final int INF = Integer.MAX_VALUE;
a0a88f65
AM
416
417 /** Preset for [1, 1] */
978d20f1 418 public static final Cardinality ONE = new Cardinality(1, 1);
a0a88f65
AM
419
420 /** Preset for [1, inf] */
978d20f1 421 public static final Cardinality ONE_OR_MORE = new Cardinality(1, INF);
a0a88f65
AM
422
423 /** Preset for [0, 1] */
978d20f1 424 public static final Cardinality ZERO_OR_ONE = new Cardinality(0, 1);
a0a88f65
AM
425
426 /** Preset for [0, inf] */
978d20f1 427 public static final Cardinality ZERO_OR_MORE = new Cardinality(0, INF);
be222f56
PT
428
429 private final int min;
430 private final int max;
431
a0a88f65
AM
432 /**
433 * Constructor.
434 *
435 * @param min
436 * Minimum
437 * @param max
438 * Maximum
439 */
be222f56
PT
440 public Cardinality(int min, int max) {
441 this.min = min;
442 this.max = max;
443 }
444
890916ec 445 @Override
be222f56 446 public String toString() {
0126a8ca 447 return "(" + (min >= 0 ? min : "?") + ',' + (max == INF ? "\u221E" : (max >= 0 ? max : "?")) + ')'; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
be222f56
PT
448 }
449
be222f56
PT
450 @Override
451 public int hashCode() {
452 final int prime = 31;
453 int result = 1;
454 result = prime * result + max;
455 result = prime * result + min;
456 return result;
457 }
458
be222f56
PT
459 @Override
460 public boolean equals(Object obj) {
461 if (this == obj) {
462 return true;
463 }
464 if (obj == null) {
465 return false;
466 }
467 if (!(obj instanceof Cardinality)) {
468 return false;
469 }
470 Cardinality other = (Cardinality) obj;
471 return (this.min == other.min && this.max == other.max);
472 }
473 }
474
475 @Override
890916ec 476 public void save() {
be222f56
PT
477 save(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME);
478 }
479
480 @Override
a0a88f65 481 public void save(String path) {
be222f56
PT
482 try {
483 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
484 DocumentBuilder db = dbf.newDocumentBuilder();
485
486 // The following allows xml parsing without access to the dtd
cb1cf0e8 487 db.setEntityResolver(createEmptyEntityResolver());
be222f56
PT
488
489 // The following catches xml parsing exceptions
cb1cf0e8 490 db.setErrorHandler(createErrorHandler());
be222f56
PT
491
492 Document doc = null;
493 File file = new File(path);
494 if (file.canRead()) {
495 doc = db.parse(file);
890916ec 496 if (!doc.getDocumentElement().getNodeName().equals(CUSTOM_TXT_TRACE_DEFINITION_ROOT_ELEMENT)) {
be222f56
PT
497 return;
498 }
499 } else {
500 doc = db.newDocument();
501 Node node = doc.createElement(CUSTOM_TXT_TRACE_DEFINITION_ROOT_ELEMENT);
502 doc.appendChild(node);
503 }
504
505 Element root = doc.getDocumentElement();
506
332527a4
PT
507 Element oldDefinitionElement = findDefinitionElement(root, categoryName, definitionName);
508 if (oldDefinitionElement != null) {
509 root.removeChild(oldDefinitionElement);
be222f56
PT
510 }
511 Element definitionElement = doc.createElement(DEFINITION_ELEMENT);
512 root.appendChild(definitionElement);
332527a4 513 definitionElement.setAttribute(CATEGORY_ATTRIBUTE, categoryName);
be222f56
PT
514 definitionElement.setAttribute(NAME_ATTRIBUTE, definitionName);
515
516 Element formatElement = doc.createElement(TIME_STAMP_OUTPUT_FORMAT_ELEMENT);
517 definitionElement.appendChild(formatElement);
518 formatElement.appendChild(doc.createTextNode(timeStampOutputFormat));
519
520 if (inputs != null) {
521 for (InputLine inputLine : inputs) {
522 definitionElement.appendChild(createInputLineElement(inputLine, doc));
523 }
524 }
525
526 if (outputs != null) {
527 for (OutputColumn output : outputs) {
528 Element outputColumnElement = doc.createElement(OUTPUT_COLUMN_ELEMENT);
529 definitionElement.appendChild(outputColumnElement);
530 outputColumnElement.setAttribute(NAME_ATTRIBUTE, output.name);
531 }
532 }
533
534 Transformer transformer = TransformerFactory.newInstance().newTransformer();
535 transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
536
890916ec 537 // initialize StreamResult with File object to save to file
be222f56
PT
538 StreamResult result = new StreamResult(new StringWriter());
539 DOMSource source = new DOMSource(doc);
540 transformer.transform(source, result);
541 String xmlString = result.getWriter().toString();
542
507b1336
AM
543 try (FileWriter writer = new FileWriter(file);) {
544 writer.write(xmlString);
545 }
52885aeb 546
4b3b667b 547 TmfTraceType.addCustomTraceType(CustomTxtTrace.class, categoryName, definitionName);
52885aeb 548
be222f56 549 } catch (ParserConfigurationException e) {
47aafe74 550 Activator.logError("Error saving CustomTxtTraceDefinition: path=" + path, e); //$NON-NLS-1$
be222f56 551 } catch (TransformerConfigurationException e) {
47aafe74 552 Activator.logError("Error saving CustomTxtTraceDefinition: path=" + path, e); //$NON-NLS-1$
be222f56 553 } catch (TransformerFactoryConfigurationError e) {
47aafe74 554 Activator.logError("Error saving CustomTxtTraceDefinition: path=" + path, e); //$NON-NLS-1$
be222f56 555 } catch (TransformerException e) {
47aafe74 556 Activator.logError("Error saving CustomTxtTraceDefinition: path=" + path, e); //$NON-NLS-1$
be222f56 557 } catch (IOException e) {
47aafe74 558 Activator.logError("Error saving CustomTxtTraceDefinition: path=" + path, e); //$NON-NLS-1$
be222f56 559 } catch (SAXException e) {
47aafe74 560 Activator.logError("Error saving CustomTxtTraceDefinition: path=" + path, e); //$NON-NLS-1$
be222f56
PT
561 }
562 }
563
564 private Element createInputLineElement(InputLine inputLine, Document doc) {
565 Element inputLineElement = doc.createElement(INPUT_LINE_ELEMENT);
566
567 Element cardinalityElement = doc.createElement(CARDINALITY_ELEMENT);
568 inputLineElement.appendChild(cardinalityElement);
569 cardinalityElement.setAttribute(MIN_ATTRIBUTE, Integer.toString(inputLine.cardinality.min));
570 cardinalityElement.setAttribute(MAX_ATTRIBUTE, Integer.toString(inputLine.cardinality.max));
571
572 Element regexElement = doc.createElement(REGEX_ELEMENT);
573 inputLineElement.appendChild(regexElement);
574 regexElement.appendChild(doc.createTextNode(inputLine.regex));
575
576 if (inputLine.columns != null) {
577 for (InputData inputData : inputLine.columns) {
578 Element inputDataElement = doc.createElement(INPUT_DATA_ELEMENT);
579 inputLineElement.appendChild(inputDataElement);
580 inputDataElement.setAttribute(NAME_ATTRIBUTE, inputData.name);
581 inputDataElement.setAttribute(ACTION_ATTRIBUTE, Integer.toString(inputData.action));
582 if (inputData.format != null) {
583 inputDataElement.setAttribute(FORMAT_ATTRIBUTE, inputData.format);
584 }
585 }
586 }
587
588 if (inputLine.childrenInputs != null) {
589 for (InputLine childInputLine : inputLine.childrenInputs) {
590 inputLineElement.appendChild(createInputLineElement(childInputLine, doc));
591 }
592 }
593
594 return inputLineElement;
595 }
596
a0a88f65 597 /**
54af96ab
PT
598 * Load all custom text trace definitions, including the user-defined and
599 * default (built-in) parsers.
a0a88f65
AM
600 *
601 * @return The loaded trace definitions
602 */
be222f56 603 public static CustomTxtTraceDefinition[] loadAll() {
54af96ab
PT
604 return loadAll(true);
605 }
606
607 /**
608 * Load all custom text trace definitions, including the user-defined and,
609 * optionally, the default (built-in) parsers.
610 *
611 * @param includeDefaults
612 * if true, the default (built-in) parsers are included
613 *
614 * @return The loaded trace definitions
54af96ab
PT
615 */
616 public static CustomTxtTraceDefinition[] loadAll(boolean includeDefaults) {
03573754 617 File defaultFile = new File(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME);
c9b31f60
BH
618 File legacyFileCore = new File(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME_LEGACY_CORE);
619 File legacyFileUI = new File(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME_LEGACY_UI);
03573754
AM
620
621 /*
622 * If there is no file at the expected location, check the legacy
c9b31f60 623 * locations instead.
03573754 624 */
c9b31f60
BH
625 if (!defaultFile.exists()) {
626 if (legacyFileCore.exists()) {
627 transferDefinitions(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME_LEGACY_CORE);
628 } else if (legacyFileUI.exists()) {
629 transferDefinitions(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME_LEGACY_UI);
03573754
AM
630 }
631 }
632
890916ec
MK
633 Set<CustomTxtTraceDefinition> defs = new TreeSet<>(new Comparator<CustomTxtTraceDefinition>() {
634 @Override
635 public int compare(CustomTxtTraceDefinition o1, CustomTxtTraceDefinition o2) {
c22ca172
PT
636 int result = o1.categoryName.compareTo(o2.categoryName);
637 if (result != 0) {
638 return result;
639 }
890916ec
MK
640 return o1.definitionName.compareTo(o2.definitionName);
641 }
642 });
643 defs.addAll(Arrays.asList(loadAll(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME)));
54af96ab
PT
644 if (includeDefaults) {
645 defs.addAll(Arrays.asList(loadAll(CUSTOM_TXT_TRACE_DEFINITIONS_DEFAULT_PATH_NAME)));
646 }
890916ec
MK
647 return defs.toArray(new CustomTxtTraceDefinition[0]);
648
be222f56
PT
649 }
650
c9b31f60
BH
651 private static void transferDefinitions(String defFile) {
652 CustomTxtTraceDefinition[] oldDefs = loadAll(defFile);
653 for (CustomTxtTraceDefinition def : oldDefs) {
654 /* Save in the new location */
655 def.save();
656 }
657 }
658
a0a88f65
AM
659 /**
660 * Load a specific text trace definition file.
661 *
cb1cf0e8
MK
662 * @param path
663 * The path to the file to load
a0a88f65
AM
664 * @return The loaded trace definitions
665 */
be222f56
PT
666 public static CustomTxtTraceDefinition[] loadAll(String path) {
667 try {
668 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
669 DocumentBuilder db = dbf.newDocumentBuilder();
670
671 // The following allows xml parsing without access to the dtd
cb1cf0e8 672 db.setEntityResolver(createEmptyEntityResolver());
be222f56
PT
673
674 // The following catches xml parsing exceptions
cb1cf0e8 675 db.setErrorHandler(createErrorHandler());
be222f56
PT
676
677 File file = new File(path);
678 if (!file.canRead()) {
679 return new CustomTxtTraceDefinition[0];
680 }
681 Document doc = db.parse(file);
682
683 Element root = doc.getDocumentElement();
890916ec 684 if (!root.getNodeName().equals(CUSTOM_TXT_TRACE_DEFINITION_ROOT_ELEMENT)) {
be222f56
PT
685 return new CustomTxtTraceDefinition[0];
686 }
687
507b1336 688 ArrayList<CustomTxtTraceDefinition> defList = new ArrayList<>();
be222f56
PT
689 NodeList nodeList = root.getChildNodes();
690 for (int i = 0; i < nodeList.getLength(); i++) {
691 Node node = nodeList.item(i);
692 if (node instanceof Element && node.getNodeName().equals(DEFINITION_ELEMENT)) {
693 CustomTxtTraceDefinition def = extractDefinition((Element) node);
694 if (def != null) {
695 defList.add(def);
696 }
697 }
698 }
699 return defList.toArray(new CustomTxtTraceDefinition[0]);
700 } catch (ParserConfigurationException e) {
47aafe74 701 Activator.logError("Error loading all in CustomTxtTraceDefinition: path=" + path, e); //$NON-NLS-1$
be222f56 702 } catch (SAXException e) {
47aafe74 703 Activator.logError("Error loading all in CustomTxtTraceDefinition: path=" + path, e); //$NON-NLS-1$
be222f56 704 } catch (IOException e) {
47aafe74 705 Activator.logError("Error loading all in CustomTxtTraceDefinition: path=" + path, e); //$NON-NLS-1$
be222f56
PT
706 }
707 return new CustomTxtTraceDefinition[0];
708 }
709
332527a4
PT
710 /**
711 * Load a single definition.
712 *
713 * @param categoryName
714 * Category of the definition to load
715 * @param definitionName
716 * Name of the definition to load
717 * @return The loaded trace definition
332527a4
PT
718 */
719 public static CustomTxtTraceDefinition load(String categoryName, String definitionName) {
be222f56
PT
720 try {
721 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
722 DocumentBuilder db = dbf.newDocumentBuilder();
723
724 // The following allows xml parsing without access to the dtd
cb1cf0e8 725 db.setEntityResolver(createEmptyEntityResolver());
be222f56
PT
726
727 // The following catches xml parsing exceptions
cb1cf0e8 728 db.setErrorHandler(createErrorHandler());
be222f56 729
332527a4 730 CustomTxtTraceDefinition value = lookupDefinition(categoryName, definitionName, db, CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME);
890916ec 731 if (value == null) {
332527a4 732 return lookupDefinition(categoryName, definitionName, db, CUSTOM_TXT_TRACE_DEFINITIONS_DEFAULT_PATH_NAME);
be222f56 733 }
890916ec 734 return value;
cb1cf0e8 735 } catch (ParserConfigurationException | SAXException | IOException e) {
890916ec
MK
736 Activator.logError("Error loading CustomTxtTraceDefinition: definitionName=" + definitionName, e); //$NON-NLS-1$
737 }
738 return null;
739 }
be222f56 740
332527a4 741 private static CustomTxtTraceDefinition lookupDefinition(String categoryName, String definitionName, DocumentBuilder db, String source) throws SAXException, IOException {
890916ec
MK
742 File file = new File(source);
743 if (!file.exists()) {
744 return null;
745 }
746 Document doc = db.parse(file);
747
748 Element root = doc.getDocumentElement();
749 if (!root.getNodeName().equals(CUSTOM_TXT_TRACE_DEFINITION_ROOT_ELEMENT)) {
750 return null;
751 }
752
332527a4
PT
753 Element definitionElement = findDefinitionElement(root, categoryName, definitionName);
754 if (definitionElement != null) {
755 return extractDefinition(definitionElement);
756 }
757 return null;
758 }
759
760 private static Element findDefinitionElement(Element root, String categoryName, String definitionName) {
890916ec
MK
761 NodeList nodeList = root.getChildNodes();
762 for (int i = 0; i < nodeList.getLength(); i++) {
763 Node node = nodeList.item(i);
332527a4
PT
764 if (node instanceof Element && node.getNodeName().equals(DEFINITION_ELEMENT)) {
765 Element element = (Element) node;
766 String categoryAttribute = element.getAttribute(CATEGORY_ATTRIBUTE);
767 if (categoryAttribute.isEmpty()) {
c9b31f60 768 categoryAttribute = CUSTOM_TXT_CATEGORY;
332527a4
PT
769 }
770 String nameAttribute = element.getAttribute(NAME_ATTRIBUTE);
771 if (categoryName.equals(categoryAttribute) &&
772 definitionName.equals(nameAttribute)) {
773 return element;
774 }
be222f56 775 }
be222f56
PT
776 }
777 return null;
778 }
779
a0a88f65
AM
780 /**
781 * Get the definition from a definition element.
782 *
cb1cf0e8
MK
783 * @param definitionElement
784 * The Element to extract from
a0a88f65
AM
785 * @return The loaded trace definition
786 */
be222f56
PT
787 public static CustomTxtTraceDefinition extractDefinition(Element definitionElement) {
788 CustomTxtTraceDefinition def = new CustomTxtTraceDefinition();
789
332527a4
PT
790 def.categoryName = definitionElement.getAttribute(CATEGORY_ATTRIBUTE);
791 if (def.categoryName.isEmpty()) {
c9b31f60 792 def.categoryName = CUSTOM_TXT_CATEGORY;
332527a4 793 }
be222f56 794 def.definitionName = definitionElement.getAttribute(NAME_ATTRIBUTE);
332527a4 795 if (def.definitionName.isEmpty()) {
be222f56
PT
796 return null;
797 }
798
799 NodeList nodeList = definitionElement.getChildNodes();
800 for (int i = 0; i < nodeList.getLength(); i++) {
801 Node node = nodeList.item(i);
802 String nodeName = node.getNodeName();
803 if (nodeName.equals(TIME_STAMP_OUTPUT_FORMAT_ELEMENT)) {
804 Element formatElement = (Element) node;
805 def.timeStampOutputFormat = formatElement.getTextContent();
806 } else if (nodeName.equals(INPUT_LINE_ELEMENT)) {
807 InputLine inputLine = extractInputLine((Element) node);
808 if (inputLine != null) {
809 def.inputs.add(inputLine);
810 }
811 } else if (nodeName.equals(OUTPUT_COLUMN_ELEMENT)) {
812 Element outputColumnElement = (Element) node;
813 OutputColumn outputColumn = new OutputColumn();
0e4f957e 814 outputColumn.name = outputColumnElement.getAttribute(NAME_ATTRIBUTE);
be222f56
PT
815 def.outputs.add(outputColumn);
816 }
817 }
818 return def;
819 }
820
821 private static InputLine extractInputLine(Element inputLineElement) {
822 InputLine inputLine = new InputLine();
823 NodeList nodeList = inputLineElement.getChildNodes();
824 for (int i = 0; i < nodeList.getLength(); i++) {
825 Node node = nodeList.item(i);
826 String nodeName = node.getNodeName();
827 if (nodeName.equals(CARDINALITY_ELEMENT)) {
828 Element cardinalityElement = (Element) node;
829 try {
830 int min = Integer.parseInt(cardinalityElement.getAttribute(MIN_ATTRIBUTE));
831 int max = Integer.parseInt(cardinalityElement.getAttribute(MAX_ATTRIBUTE));
832 inputLine.cardinality = new Cardinality(min, max);
833 } catch (NumberFormatException e) {
834 return null;
835 }
836 } else if (nodeName.equals(REGEX_ELEMENT)) {
837 Element regexElement = (Element) node;
838 inputLine.regex = regexElement.getTextContent();
839 } else if (nodeName.equals(INPUT_DATA_ELEMENT)) {
840 Element inputDataElement = (Element) node;
841 InputData inputData = new InputData();
842 inputData.name = inputDataElement.getAttribute(NAME_ATTRIBUTE);
843 inputData.action = Integer.parseInt(inputDataElement.getAttribute(ACTION_ATTRIBUTE));
844 inputData.format = inputDataElement.getAttribute(FORMAT_ATTRIBUTE);
845 inputLine.addColumn(inputData);
846 } else if (nodeName.equals(INPUT_LINE_ELEMENT)) {
847 Element childInputLineElement = (Element) node;
848 InputLine childInputLine = extractInputLine(childInputLineElement);
849 if (childInputLine != null) {
850 inputLine.addChild(childInputLine);
851 }
852 }
853 }
854 return inputLine;
855 }
856
332527a4
PT
857 /**
858 * Delete a definition from the currently loaded ones.
859 *
860 * @param categoryName
861 * The category of the definition to delete
862 * @param definitionName
863 * The name of the definition to delete
332527a4
PT
864 */
865 public static void delete(String categoryName, String definitionName) {
be222f56
PT
866 try {
867 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
868 DocumentBuilder db = dbf.newDocumentBuilder();
869
870 // The following allows xml parsing without access to the dtd
cb1cf0e8 871 db.setEntityResolver(createEmptyEntityResolver());
be222f56
PT
872
873 // The following catches xml parsing exceptions
cb1cf0e8 874 db.setErrorHandler(createErrorHandler());
be222f56
PT
875
876 File file = new File(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME);
877 Document doc = db.parse(file);
878
879 Element root = doc.getDocumentElement();
890916ec 880 if (!root.getNodeName().equals(CUSTOM_TXT_TRACE_DEFINITION_ROOT_ELEMENT)) {
be222f56
PT
881 return;
882 }
883
332527a4
PT
884 Element definitionElement = findDefinitionElement(root, categoryName, definitionName);
885 if (definitionElement != null) {
886 root.removeChild(definitionElement);
be222f56
PT
887 }
888
889 Transformer transformer = TransformerFactory.newInstance().newTransformer();
890 transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
891
890916ec 892 // initialize StreamResult with File object to save to file
be222f56
PT
893 StreamResult result = new StreamResult(new StringWriter());
894 DOMSource source = new DOMSource(doc);
895 transformer.transform(source, result);
896 String xmlString = result.getWriter().toString();
897
507b1336
AM
898 try (FileWriter writer = new FileWriter(file);) {
899 writer.write(xmlString);
900 }
52885aeb 901
4b3b667b 902 TmfTraceType.removeCustomTraceType(CustomTxtTrace.class, categoryName, definitionName);
0621dbae 903 // Check if default definition needs to be reloaded
4b3b667b 904 TmfTraceType.addCustomTraceType(CustomTxtTrace.class, categoryName, definitionName);
52885aeb 905
cb1cf0e8 906 } catch (ParserConfigurationException | SAXException | IOException | TransformerFactoryConfigurationError | TransformerException e) {
47aafe74 907 Activator.logError("Error deleting CustomTxtTraceDefinition: definitionName=" + definitionName, e); //$NON-NLS-1$
be222f56
PT
908 }
909 }
910}
This page took 0.170997 seconds and 5 git commands to generate.