/*******************************************************************************
* Copyright (c) 2016 Ericsson
*
* 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.pattern.stateprovider;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.IPath;
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.model.ITmfXmlModelFactory;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.TmfXmlMapEntry;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.TmfXmlLocation;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.TmfXmlPatternEventHandler;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.TmfXmlScenarioHistoryBuilder;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.model.readwrite.TmfXmlReadWriteModelFactory;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.IXmlStateSystemContainer;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.module.XmlUtils;
import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.stateprovider.TmfXmlStrings;
import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
import org.eclipse.tracecompass.tmf.core.statesystem.AbstractTmfStateProvider;
import org.eclipse.tracecompass.tmf.core.statesystem.ITmfStateProvider;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
* State provider for the pattern analysis
*
* @author Jean-Christian Kouame
*/
public class XmlPatternStateProvider extends AbstractTmfStateProvider implements IXmlStateSystemContainer {
private final IPath fFilePath;
private final @NonNull String fStateId;
/** Map for defined values */
private final Map<String, String> fDefinedValues = new HashMap<>();
/** List of all Locations */
private final @NonNull Set<@NonNull TmfXmlLocation> fLocations;
private final @NonNull Map<@NonNull String, @NonNull Set<@NonNull TmfXmlMapEntry>> fMappingGroups;
/** Map for stored values */
private final @NonNull Map<@NonNull String, @NonNull String> fStoredFields = new HashMap<>();
private TmfXmlPatternEventHandler fHandler;
private final ISegmentListener fListener;
private final @NonNull TmfXmlScenarioHistoryBuilder fHistoryBuilder;
/**
* @param trace
* The active trace
* @param stateid
* The state id, which corresponds to the id of the analysis
* defined in the XML file
* @param file
* The XML file
* @param listener
* Listener for segment creation
*/
public XmlPatternStateProvider(@NonNull ITmfTrace trace, @NonNull String stateid, @Nullable IPath file, ISegmentListener listener) {
super(trace, stateid);
fStateId = stateid;
fFilePath = file;
fListener = listener;
fHistoryBuilder = new TmfXmlScenarioHistoryBuilder();
final String pathString = fFilePath.makeAbsolute().toOSString();
Element doc = XmlUtils.getElementInFile(pathString, TmfXmlStrings.PATTERN, fStateId);
if (doc == null) {
fLocations = new HashSet<>();
fMappingGroups = new HashMap<>();
Activator.logError("Failed to find a pattern in " + pathString); //$NON-NLS-1$
return;
}
/* parser for defined Fields */
NodeList storedFieldNodes = doc.getElementsByTagName(TmfXmlStrings.STORED_FIELD);
for (int i = 0; i < storedFieldNodes.getLength(); i++) {
Element element = (Element) storedFieldNodes.item(i);
String key = element.getAttribute(TmfXmlStrings.ALIAS);
fStoredFields.put(element.getAttribute(TmfXmlStrings.ID), key.isEmpty() ? element.getAttribute(TmfXmlStrings.ID) : key);
}
/* parser for defined Values */
NodeList definedStateNodes = doc.getElementsByTagName(TmfXmlStrings.DEFINED_VALUE);
for (int i = 0; i < definedStateNodes.getLength(); i++) {
Element element = (Element) definedStateNodes.item(i);
fDefinedValues.put(element.getAttribute(TmfXmlStrings.NAME), element.getAttribute(TmfXmlStrings.VALUE));
}
ITmfXmlModelFactory modelFactory = TmfXmlReadWriteModelFactory.getInstance();
/* parser for the locations */
NodeList locationNodes = doc.getElementsByTagName(TmfXmlStrings.LOCATION);
final Set<@NonNull TmfXmlLocation> locations = new HashSet<>();
for (int i = 0; i < locationNodes.getLength(); i++) {
Element element = (Element) locationNodes.item(i);
if (element == null) {
continue;
}
TmfXmlLocation location = modelFactory.createLocation(element, this);
locations.add(location);
}
fLocations = Collections.unmodifiableSet(locations);
/* parser for the mapping groups */
final @NonNull Map<@NonNull String, @NonNull Set<@NonNull TmfXmlMapEntry>> mapGroups = new HashMap<>();
NodeList mapNodes = doc.getElementsByTagName(TmfXmlStrings.MAPPING_GROUP);
for (int i = 0; i < mapNodes.getLength(); i++) {
Element map = (Element) mapNodes.item(i);
String id = map.getAttribute(TmfXmlStrings.ID);
Set<@NonNull TmfXmlMapEntry> entrySet = mapGroups.get(id);
if (entrySet == null) {
entrySet = new HashSet<>();
mapGroups.put(id, entrySet);
}
NodeList entryNodes = map.getElementsByTagName(TmfXmlStrings.ENTRY);
for (int j = 0; j < entryNodes.getLength(); j++) {
Element entryElement = (Element) entryNodes.item(j);
if (entryElement == null) {
continue;
}
TmfXmlMapEntry entry = modelFactory.createMapEntry(entryElement, this);
entrySet.add(entry);
}
}
fMappingGroups = Collections.unmodifiableMap(mapGroups);
/* parser for the event handlers */
NodeList nodes = doc.getElementsByTagName(TmfXmlStrings.PATTERN_HANDLER);
fHandler = modelFactory.createPatternEventHandler(NonNullUtils.checkNotNull((Element) nodes.item(0)), this);
}
@Override
public String getAttributeValue(String name) {
String attribute = name;
if (attribute.startsWith(TmfXmlStrings.VARIABLE_PREFIX)) {
/* search the attribute in the map without the fist character $ */
attribute = getDefinedValue(attribute.substring(1));
}
return attribute;
}
/**
* Get the defined value associated with a constant
*
* @param constant
* The constant defining this value
* @return The actual value corresponding to this constant
*/
public String getDefinedValue(String constant) {
return fDefinedValues.get(constant);
}
/**
* Get the stored fiels map
*
* @return The map of stored fields
*/
public @NonNull Map<@NonNull String, @NonNull String> getStoredFields() {
return fStoredFields;
}
@Override
public int getVersion() {
return 0;
}
@Override
public @NonNull ITmfStateProvider getNewInstance() {
return new XmlPatternStateProvider(getTrace(), getStateId(), fFilePath, fListener);
}
/**
* Get the state ID of the provider. It corresponds to the analysis ID.
*
* @return the state Id
*/
public @NonNull String getStateId() {
return fStateId;
}
@Override
public ITmfStateSystem getStateSystem() {
return getStateSystemBuilder();
}
@Override
public @NonNull Iterable<@NonNull TmfXmlLocation> getLocations() {
return fLocations;
}
@Override
protected void eventHandle(@NonNull ITmfEvent event) {
fHandler.handleEvent(event);
}
/**
* Get the listerner for segments creation
*
* @return The segment listener
*/
public ISegmentListener getListener() {
return fListener;
}
@Override
public void dispose() {
waitForEmptyQueue();
fListener.onNewSegment(XmlPatternSegmentStoreModule.END_SEGMENT);
fHandler.dispose();
super.dispose();
}
/**
* Get the history builder of this analysis
*
* @return The history builder
*/
public @NonNull TmfXmlScenarioHistoryBuilder getHistoryBuilder() {
return fHistoryBuilder;
}
/**
* Get the list of state value handlers defined in this top level element
*
* @param id
* The mapping group id
* @return The set of {@link TmfXmlMapEntry}
*/
public @Nullable Set<@NonNull TmfXmlMapEntry> getMappingGroup(@NonNull String id) {
return fMappingGroups.get(id);
}
}