blob: 1ef7e8de67c8e8aa3734a7e73f1e1f53fb47855b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2016 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Patrick Tasse - Initial API and implementation
*******************************************************************************/
package org.eclipse.tracecompass.internal.tmf.ui.parsers.wizards;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.text.ParseException;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.tracecompass.common.core.xml.XmlUtils;
import org.eclipse.tracecompass.internal.tmf.ui.Activator;
import org.eclipse.tracecompass.internal.tmf.ui.Messages;
import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomTraceDefinition;
import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomTraceDefinition.Tag;
import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomXmlInputAttribute;
import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomXmlInputElement;
import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomXmlTrace;
import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomXmlTraceDefinition;
import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType;
import org.eclipse.tracecompass.tmf.core.project.model.TraceTypeHelper;
import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestampFormat;
import org.osgi.framework.Bundle;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import com.google.common.base.Joiner;
/**
* Input wizard page for custom XML trace parsers.
*
* @author Patrick Tasse
*/
public class CustomXmlParserInputWizardPage extends WizardPage {
private static final String DEFAULT_TIMESTAMP_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS"; //$NON-NLS-1$
private static final String TIMESTAMP_FORMAT_BUNDLE = "org.eclipse.tracecompass.doc.user"; //$NON-NLS-1$
private static final String TIMESTAMP_FORMAT_PATH = "reference/api/org/eclipse/tracecompass/tmf/core/timestamp/TmfTimestampFormat.html"; //$NON-NLS-1$
private static final Image ELEMENT_IMAGE = Activator.getDefault().getImageFromPath("/icons/elcl16/element_icon.gif"); //$NON-NLS-1$
private static final Image ADD_IMAGE = Activator.getDefault().getImageFromPath("/icons/elcl16/add_button.gif"); //$NON-NLS-1$
private static final Image ADD_NEXT_IMAGE = Activator.getDefault().getImageFromPath("/icons/elcl16/addnext_button.gif"); //$NON-NLS-1$
private static final Image ADD_CHILD_IMAGE = Activator.getDefault().getImageFromPath("/icons/elcl16/addchild_button.gif"); //$NON-NLS-1$
private static final Image ADD_MANY_IMAGE = Activator.getDefault().getImageFromPath("/icons/elcl16/addmany_button.gif"); //$NON-NLS-1$
private static final Image DELETE_IMAGE = Activator.getDefault().getImageFromPath("/icons/elcl16/delete_button.gif"); //$NON-NLS-1$
private static final Image MOVE_UP_IMAGE = Activator.getDefault().getImageFromPath("/icons/elcl16/moveup_button.gif"); //$NON-NLS-1$
private static final Image MOVE_DOWN_IMAGE = Activator.getDefault().getImageFromPath("/icons/elcl16/movedown_button.gif"); //$NON-NLS-1$
private static final Image HELP_IMAGE = Activator.getDefault().getImageFromPath("/icons/elcl16/help_button.gif"); //$NON-NLS-1$
private static final Color COLOR_LIGHT_RED = new Color(Display.getDefault(), 255, 192, 192);
private static final Color COLOR_TEXT_BACKGROUND = Display.getDefault().getSystemColor(SWT.COLOR_WHITE);
private static final Color COLOR_WIDGET_BACKGROUND = Display.getDefault().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
private static final Color COLOR_GRAY = Display.getDefault().getSystemColor(SWT.COLOR_GRAY);
private final ISelection selection;
private CustomXmlTraceDefinition definition;
private String editCategoryName;
private String editDefinitionName;
private String defaultDescription;
private ElementNode selectedElement;
private Composite container;
private Text categoryText;
private Text logtypeText;
private Text timeStampOutputFormatText;
private Text timeStampPreviewText;
private Button removeButton;
private Button addChildButton;
private Button addNextButton;
private Button moveUpButton;
private Button moveDownButton;
private ScrolledComposite elementScrolledComposite;
private TreeViewer treeViewer;
private Composite elementContainer;
private Text errorText;
private StyledText inputText;
private Font fixedFont;
private UpdateListener updateListener;
private Browser helpBrowser;
private Element documentElement;
// variables used recursively through element traversal
private String timeStampValue;
private String timeStampFormat;
private boolean timeStampFound;
private int logEntriesCount;
private boolean logEntryFound;
/**
* Constructor
*
* @param selection
* Selection object
* @param definition
* Trace definition
*/
protected CustomXmlParserInputWizardPage(ISelection selection, CustomXmlTraceDefinition definition) {
super("CustomXmlParserWizardPage"); //$NON-NLS-1$
if (definition == null) {
setTitle(Messages.CustomXmlParserInputWizardPage_titleNew);
defaultDescription = Messages.CustomXmlParserInputWizardPage_descriptionNew;
} else {
setTitle(Messages.CustomXmlParserInputWizardPage_titleEdit);
defaultDescription = Messages.CustomXmlParserInputWizardPage_descriptionEdit;
}
setDescription(defaultDescription);
this.selection = selection;
this.definition = definition;
if (definition != null) {
this.editCategoryName = definition.categoryName;
this.editDefinitionName = definition.definitionName;
}
}
@Override
public void createControl(Composite parent) {
container = new Composite(parent, SWT.NULL);
container.setLayout(new GridLayout());
updateListener = new UpdateListener();
Composite headerComposite = new Composite(container, SWT.FILL);
GridLayout headerLayout = new GridLayout(5, false);
headerLayout.marginHeight = 0;
headerLayout.marginWidth = 0;
headerComposite.setLayout(headerLayout);
headerComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
Label categoryLabel = new Label(headerComposite, SWT.NULL);
categoryLabel.setText(Messages.CustomXmlParserInputWizardPage_category);
categoryText = new Text(headerComposite, SWT.BORDER | SWT.SINGLE);
categoryText.setLayoutData(new GridData(120, SWT.DEFAULT));
Label timeStampFormatLabel = new Label(headerComposite, SWT.NULL);
timeStampFormatLabel.setText(Messages.CustomXmlParserInputWizardPage_timestampFormat);
timeStampOutputFormatText = new Text(headerComposite, SWT.BORDER | SWT.SINGLE);
timeStampOutputFormatText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
timeStampOutputFormatText.setText(DEFAULT_TIMESTAMP_FORMAT);
timeStampOutputFormatText.addPaintListener(e -> {
if (!timeStampOutputFormatText.isFocusControl() && timeStampOutputFormatText.getText().trim().isEmpty()) {
e.gc.setForeground(COLOR_GRAY);
int borderWidth = timeStampOutputFormatText.getBorderWidth();
e.gc.drawText(Messages.CustomXmlParserInputWizardPage_default, borderWidth, borderWidth);
}
});
Button timeStampFormatHelpButton = new Button(headerComposite, SWT.PUSH);
timeStampFormatHelpButton.setImage(HELP_IMAGE);
timeStampFormatHelpButton.setToolTipText(Messages.CustomXmlParserInputWizardPage_timestampFormatHelp);
timeStampFormatHelpButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
Bundle plugin = Platform.getBundle(TIMESTAMP_FORMAT_BUNDLE);
IPath path = new Path(TIMESTAMP_FORMAT_PATH);
URL fileURL = FileLocator.find(plugin, path, null);
try {
URL pageURL = FileLocator.toFileURL(fileURL);
openHelpShell(pageURL.toString());
} catch (IOException e1) {
}
}
});
Label logtypeLabel = new Label(headerComposite, SWT.NULL);
logtypeLabel.setText(Messages.CustomXmlParserInputWizardPage_logType);
logtypeText = new Text(headerComposite, SWT.BORDER | SWT.SINGLE);
logtypeText.setLayoutData(new GridData(120, SWT.DEFAULT));
logtypeText.setFocus();
Label timeStampPreviewLabel = new Label(headerComposite, SWT.NULL);
timeStampPreviewLabel.setText(Messages.CustomXmlParserInputWizardPage_preview);
timeStampPreviewText = new Text(headerComposite, SWT.BORDER | SWT.SINGLE | SWT.READ_ONLY);
timeStampPreviewText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
timeStampPreviewText.setText("*no time stamp element or attribute*"); //$NON-NLS-1$
createButtonBar();
SashForm vSash = new SashForm(container, SWT.VERTICAL);
vSash.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
vSash.setBackground(COLOR_GRAY);
SashForm hSash = new SashForm(vSash, SWT.HORIZONTAL);
hSash.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
ScrolledComposite treeScrolledComposite = new ScrolledComposite(hSash, SWT.V_SCROLL | SWT.H_SCROLL);
treeScrolledComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
Composite treeContainer = new Composite(treeScrolledComposite, SWT.NONE);
treeContainer.setLayout(new FillLayout());
treeScrolledComposite.setContent(treeContainer);
treeScrolledComposite.setExpandHorizontal(true);
treeScrolledComposite.setExpandVertical(true);
treeViewer = new TreeViewer(treeContainer, SWT.SINGLE | SWT.BORDER);
treeViewer.setContentProvider(new InputElementTreeNodeContentProvider());
treeViewer.setLabelProvider(new InputElementTreeLabelProvider());
treeViewer.addSelectionChangedListener(new InputElementTreeSelectionChangedListener());
treeContainer.layout();
treeScrolledComposite
.setMinSize(treeContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x, treeContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
elementScrolledComposite = new ScrolledComposite(hSash, SWT.V_SCROLL);
elementScrolledComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
elementContainer = new Composite(elementScrolledComposite, SWT.NONE);
GridLayout gl = new GridLayout();
gl.marginHeight = 1;
gl.marginWidth = 0;
elementContainer.setLayout(gl);
elementScrolledComposite.setContent(elementContainer);
elementScrolledComposite.setExpandHorizontal(true);
elementScrolledComposite.setExpandVertical(true);
if (definition == null) {
definition = new CustomXmlTraceDefinition();
}
loadDefinition(definition);
treeViewer.expandAll();
elementContainer.layout();
categoryText.addModifyListener(updateListener);
logtypeText.addModifyListener(updateListener);
timeStampOutputFormatText.addModifyListener(updateListener);
elementScrolledComposite.setMinSize(elementContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x,
elementContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y - 1);
hSash.setWeights(new int[] { 1, 2 });
if (definition.rootInputElement == null) {
removeButton.setEnabled(false);
addChildButton.setToolTipText(Messages.CustomXmlParserInputWizardPage_addDocumentElement);
addNextButton.setEnabled(false);
moveUpButton.setEnabled(false);
moveDownButton.setEnabled(false);
} else { // root is selected
addNextButton.setEnabled(false);
}
Composite sashBottom = new Composite(vSash, SWT.NONE);
GridLayout sashBottomLayout = new GridLayout(2, false);
sashBottomLayout.marginHeight = 0;
sashBottomLayout.marginWidth = 0;
sashBottom.setLayout(sashBottomLayout);
Label previewLabel = new Label(sashBottom, SWT.NULL);
previewLabel.setText(Messages.CustomXmlParserInputWizardPage_previewInput);
errorText = new Text(sashBottom, SWT.SINGLE | SWT.READ_ONLY);
errorText.setBackground(COLOR_WIDGET_BACKGROUND);
errorText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
errorText.setVisible(false);
inputText = new StyledText(sashBottom, SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL);
if (fixedFont == null) {
if (System.getProperty("os.name").contains("Windows")) { //$NON-NLS-1$ //$NON-NLS-2$
fixedFont = new Font(Display.getCurrent(), new FontData("Courier New", 10, SWT.NORMAL)); //$NON-NLS-1$
} else {
fixedFont = new Font(Display.getCurrent(), new FontData("Monospace", 10, SWT.NORMAL)); //$NON-NLS-1$
}
}
inputText.setFont(fixedFont);
GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1);
gd.heightHint = inputText.computeSize(SWT.DEFAULT, inputText.getLineHeight() * 4).y;
gd.widthHint = 800;
inputText.setLayoutData(gd);
inputText.setText(getSelectionText());
inputText.addModifyListener(e -> parseXmlInput(inputText.getText()));
inputText.addModifyListener(updateListener);
vSash.setWeights(new int[] { hSash.computeSize(SWT.DEFAULT, SWT.DEFAULT).y, sashBottom.computeSize(SWT.DEFAULT, SWT.DEFAULT).y });
setControl(container);
}
private void createButtonBar() {
Composite buttonBar = new Composite(container, SWT.NONE);
GridLayout buttonBarLayout = new GridLayout(6, false);
buttonBarLayout.marginHeight = 0;
buttonBarLayout.marginWidth = 0;
buttonBar.setLayout(buttonBarLayout);
removeButton = new Button(buttonBar, SWT.PUSH);
removeButton.setImage(DELETE_IMAGE);
removeButton.setToolTipText(Messages.CustomXmlParserInputWizardPage_removeElement);
removeButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (treeViewer.getSelection().isEmpty() || selectedElement == null) {
return;
}
removeElement();
CustomXmlInputElement inputElement = (CustomXmlInputElement) ((IStructuredSelection) treeViewer.getSelection()).getFirstElement();
if (inputElement == definition.rootInputElement) {
definition.rootInputElement = null;
} else {
inputElement.getParentElement().getChildElements().remove(inputElement);
}
treeViewer.refresh();
validate();
updatePreviews();
removeButton.setEnabled(false);
if (definition.rootInputElement == null) {
addChildButton.setEnabled(true);
addChildButton.setToolTipText(Messages.CustomXmlParserInputWizardPage_addDocumentEleemnt);
} else {
addChildButton.setEnabled(false);
}
addNextButton.setEnabled(false);
moveUpButton.setEnabled(false);
moveDownButton.setEnabled(false);
}
});
addChildButton = new Button(buttonBar, SWT.PUSH);
addChildButton.setImage(ADD_CHILD_IMAGE);
addChildButton.setToolTipText(Messages.CustomXmlParserInputWizardPage_addChildElement);
addChildButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
CustomXmlInputElement inputElement = new CustomXmlInputElement("", false, Tag.IGNORE, Tag.IGNORE.toString(), 0, "", null); //$NON-NLS-1$ //$NON-NLS-2$
if (definition.rootInputElement == null) {
definition.rootInputElement = inputElement;
inputElement.setElementName(getChildNameSuggestion(null));
} else if (treeViewer.getSelection().isEmpty()) {
return;
} else {
CustomXmlInputElement parentInputElement = (CustomXmlInputElement) ((IStructuredSelection) treeViewer.getSelection()).getFirstElement();
parentInputElement.addChild(inputElement);
inputElement.setElementName(getChildNameSuggestion(parentInputElement));
}
treeViewer.refresh();
treeViewer.setSelection(new StructuredSelection(inputElement), true);
}
});
addNextButton = new Button(buttonBar, SWT.PUSH);
addNextButton.setImage(ADD_NEXT_IMAGE);
addNextButton.setToolTipText(Messages.CustomXmlParserInputWizardPage_addNextElement);
addNextButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
CustomXmlInputElement inputElement = new CustomXmlInputElement("", false, Tag.IGNORE, Tag.IGNORE.toString(), 0, "", null); //$NON-NLS-1$ //$NON-NLS-2$
if (definition.rootInputElement == null) {
definition.rootInputElement = inputElement;
inputElement.setElementName(getChildNameSuggestion(null));
} else if (treeViewer.getSelection().isEmpty()) {
return;
} else {
CustomXmlInputElement previousInputElement = (CustomXmlInputElement) ((IStructuredSelection) treeViewer.getSelection()).getFirstElement();
if (previousInputElement == definition.rootInputElement) {
return;
}
previousInputElement.addNext(inputElement);
inputElement.setElementName(getChildNameSuggestion(inputElement.getParentElement()));
}
treeViewer.refresh();
treeViewer.setSelection(new StructuredSelection(inputElement), true);
}
});
Button feelingLuckyButton = new Button(buttonBar, SWT.PUSH);
feelingLuckyButton.setImage(ADD_MANY_IMAGE);
feelingLuckyButton.setToolTipText(Messages.CustomXmlParserInputWizardPage_feelingLucky);
feelingLuckyButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
CustomXmlInputElement inputElement = null;
if (definition.rootInputElement == null) {
if (getChildNameSuggestion(null).length() != 0) {
inputElement = new CustomXmlInputElement(getChildNameSuggestion(null), false, Tag.IGNORE, Tag.IGNORE.toString(), 0, "", null); //$NON-NLS-1$
definition.rootInputElement = inputElement;
feelingLucky(inputElement);
} else {
return;
}
} else if (treeViewer.getSelection().isEmpty()) {
return;
} else {
inputElement = (CustomXmlInputElement) ((IStructuredSelection) treeViewer.getSelection()).getFirstElement();
feelingLucky(inputElement);
}
treeViewer.refresh();
treeViewer.setSelection(new StructuredSelection(inputElement), true);
treeViewer.expandToLevel(inputElement, AbstractTreeViewer.ALL_LEVELS);
}
});
moveUpButton = new Button(buttonBar, SWT.PUSH);
moveUpButton.setImage(MOVE_UP_IMAGE);
moveUpButton.setToolTipText(Messages.CustomXmlParserInputWizardPage_moveUp);
moveUpButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (treeViewer.getSelection().isEmpty()) {
return;
}
CustomXmlInputElement inputElement = (CustomXmlInputElement) ((IStructuredSelection) treeViewer.getSelection()).getFirstElement();
if (inputElement == definition.rootInputElement) {
return;
}
inputElement.moveUp();
treeViewer.refresh();
validate();
updatePreviews();
}
});
moveDownButton = new Button(buttonBar, SWT.PUSH);
moveDownButton.setImage(MOVE_DOWN_IMAGE);
moveDownButton.setToolTipText(Messages.CustomXmlParserInputWizardPage_moveDown);
moveDownButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (treeViewer.getSelection().isEmpty()) {
return;
}
CustomXmlInputElement inputElement = (CustomXmlInputElement) ((IStructuredSelection) treeViewer.getSelection()).getFirstElement();
if (inputElement == definition.rootInputElement) {
return;
}
inputElement.moveDown();
treeViewer.refresh();
validate();
updatePreviews();
}
});
}
private void feelingLucky(CustomXmlInputElement inputElement) {
while (true) {
String attributeName = getAttributeNameSuggestion(inputElement);
if (attributeName.length() == 0) {
break;
}
CustomXmlInputAttribute attribute = new CustomXmlInputAttribute(attributeName, Tag.OTHER, attributeName, 0, ""); //$NON-NLS-1$
inputElement.addAttribute(attribute);
}
while (true) {
String childName = getChildNameSuggestion(inputElement);
if (childName.length() == 0) {
break;
}
CustomXmlInputElement childElement = new CustomXmlInputElement(childName, false, Tag.IGNORE, Tag.IGNORE.toString(), 0, "", null); //$NON-NLS-1$
inputElement.addChild(childElement);
feelingLucky(childElement);
}
}
private static class InputElementTreeNodeContentProvider implements ITreeContentProvider {
@Override
public Object[] getElements(Object inputElement) {
CustomXmlTraceDefinition def = (CustomXmlTraceDefinition) inputElement;
if (def.rootInputElement != null) {
return new Object[] { def.rootInputElement };
}
return new Object[0];
}
@Override
public Object[] getChildren(Object parentElement) {
CustomXmlInputElement inputElement = (CustomXmlInputElement) parentElement;
if (inputElement.getChildElements() == null) {
return new CustomXmlInputElement[0];
}
return inputElement.getChildElements().toArray();
}
@Override
public boolean hasChildren(Object element) {
CustomXmlInputElement inputElement = (CustomXmlInputElement) element;
return (inputElement.getChildElements() != null && !inputElement.getChildElements().isEmpty());
}
@Override
public void dispose() {
// Do nothing
}
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
// Do nothing
}
@Override
public Object getParent(Object element) {
CustomXmlInputElement inputElement = (CustomXmlInputElement) element;
return inputElement.getParentElement();
}
}
private static class InputElementTreeLabelProvider extends ColumnLabelProvider {
@Override
public Image getImage(Object element) {
return ELEMENT_IMAGE;
}
@Override
public String getText(Object element) {
CustomXmlInputElement inputElement = (CustomXmlInputElement) element;
return (inputElement.getElementName().trim().length() == 0) ? "?" : inputElement.getElementName(); //$NON-NLS-1$
}
}
private class InputElementTreeSelectionChangedListener implements ISelectionChangedListener {
@Override
public void selectionChanged(SelectionChangedEvent event) {
if (selectedElement != null) {
selectedElement.dispose();
}
if (!(event.getSelection().isEmpty()) && event.getSelection() instanceof IStructuredSelection) {
IStructuredSelection sel = (IStructuredSelection) event.getSelection();
CustomXmlInputElement inputElement = (CustomXmlInputElement) sel.getFirstElement();
selectedElement = new ElementNode(elementContainer, inputElement);
elementContainer.layout();
elementScrolledComposite.setMinSize(elementContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x,
elementContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y - 1);
container.layout();
validate();
updatePreviews();
removeButton.setEnabled(true);
addChildButton.setEnabled(true);
addChildButton.setToolTipText(Messages.CustomXmlParserInputWizardPage_addChildElement);
if (definition.rootInputElement == inputElement) {
addNextButton.setEnabled(false);
} else {
addNextButton.setEnabled(true);
}
moveUpButton.setEnabled(true);
moveDownButton.setEnabled(true);
} else {
removeButton.setEnabled(false);
if (definition.rootInputElement == null) {
addChildButton.setEnabled(true);
addChildButton.setToolTipText(Messages.CustomXmlParserInputWizardPage_addDocumentElement);
} else {
addChildButton.setEnabled(false);
}
addNextButton.setEnabled(false);
moveUpButton.setEnabled(false);
moveDownButton.setEnabled(false);
}
}
}
@Override
public void dispose() {
if (fixedFont != null) {
fixedFont.dispose();
fixedFont = null;
}
super.dispose();
}
private void loadDefinition(CustomXmlTraceDefinition def) {
categoryText.setText(def.categoryName);
logtypeText.setText(def.definitionName);
if (def.timeStampOutputFormat != null) {
timeStampOutputFormatText.setText(def.timeStampOutputFormat);
} else {
timeStampOutputFormatText.setText(""); //$NON-NLS-1$
}
treeViewer.setInput(def);
if (def.rootInputElement != null) {
treeViewer.setSelection(new StructuredSelection(def.rootInputElement));
}
}
private String getName(CustomXmlInputElement inputElement) {
String name = (inputElement.getElementName().trim().length() == 0) ? "?" : inputElement.getElementName().trim(); //$NON-NLS-1$
if (inputElement.getParentElement() == null) {
return name;
}
return getName(inputElement.getParentElement()) + " : " + name; //$NON-NLS-1$
}
private String getName(CustomXmlInputAttribute inputAttribute, CustomXmlInputElement inputElement) {
String name = (inputAttribute.getAttributeName().trim().length() == 0) ? "?" : inputAttribute.getAttributeName().trim(); //$NON-NLS-1$
return getName(inputElement) + " : " + name; //$NON-NLS-1$
}
@Override
public void setVisible(boolean visible) {
if (visible) {
validate();
updatePreviews();
}
super.setVisible(visible);
}
/**
* Get the global list of inputs.
*
* @return The list of inputs
*/
public List<Entry<Tag, String>> getInputs() {
return getInputs(definition.rootInputElement);
}
/**
* Get the list of inputs for a given element, recursively.
*
* @param inputElement
* The element
* @return The list of inputs
*/
public List<Entry<Tag, String>> getInputs(CustomXmlInputElement inputElement) {
List<Entry<Tag, String>> inputs = new ArrayList<>();
if (inputElement.getInputTag() != null && !inputElement.getInputTag().equals(Tag.IGNORE)) {
Entry<Tag, String> input = new SimpleEntry<>(inputElement.getInputTag(), inputElement.getInputName());
if (!inputs.contains(input)) {
inputs.add(input);
}
}
if (inputElement.getAttributes() != null) {
for (CustomXmlInputAttribute attribute : inputElement.getAttributes()) {
Entry<Tag, String> input = new SimpleEntry<>(attribute.getInputTag(), attribute.getInputName());
if (!inputs.contains(input)) {
inputs.add(input);
}
}
}
if (inputElement.getChildElements() != null) {
for (CustomXmlInputElement childInputElement : inputElement.getChildElements()) {
for (Entry<Tag, String> input : getInputs(childInputElement)) {
if (!inputs.contains(input)) {
inputs.add(input);
}
}
}
}
return inputs;
}
private void removeElement() {
selectedElement.dispose();
selectedElement = null;
elementContainer.layout();
elementScrolledComposite.setMinSize(elementContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x,
elementContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y - 1);
container.layout();
}
private String getSelectionText() {
InputStream inputStream = null;
if (this.selection instanceof IStructuredSelection) {
Object sel = ((IStructuredSelection) this.selection).getFirstElement();
if (sel instanceof IFile) {
IFile file = (IFile) sel;
try {
inputStream = file.getContents();
} catch (CoreException e) {
return ""; //$NON-NLS-1$
}
}
}
if (inputStream != null) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));) {
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line);
sb.append('\n');
}
parseXmlInput(sb.toString());
return sb.toString();
} catch (IOException e) {
return ""; //$NON-NLS-1$
}
}
return ""; //$NON-NLS-1$
}
private void parseXmlInput(final String string) {
try {
DocumentBuilder db = XmlUtils.newSafeDocumentBuilderFactory().newDocumentBuilder();
// The following allows xml parsing without access to the dtd
EntityResolver resolver = (publicId, systemId) -> {
String empty = ""; //$NON-NLS-1$
ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes());
return new InputSource(bais);
};
db.setEntityResolver(resolver);
// The following catches xml parsing exceptions
db.setErrorHandler(new ErrorHandler() {
@Override
public void error(SAXParseException saxparseexception) throws SAXException {
// Do nothing
}
@Override
public void warning(SAXParseException saxparseexception) throws SAXException {
// Do nothing
}
@Override
public void fatalError(SAXParseException saxparseexception) throws SAXException {
if (string.trim().length() != 0) {
errorText.setText(saxparseexception.getMessage());
errorText.setBackground(COLOR_LIGHT_RED);
errorText.setVisible(true);
}
throw saxparseexception;
}
});
errorText.setVisible(false);
Document doc = null;
doc = db.parse(new ByteArrayInputStream(string.getBytes()));
documentElement = doc.getDocumentElement();
} catch (ParserConfigurationException e) {
Activator.getDefault().logError("Error pasing XML input string: " + string, e); //$NON-NLS-1$
documentElement = null;
} catch (SAXException e) {
documentElement = null;
} catch (IOException e) {
Activator.getDefault().logError("Error pasing XML input string: " + string, e); //$NON-NLS-1$
documentElement = null;
}
}
private void initValues() {
timeStampValue = null;
timeStampFormat = null;
logEntriesCount = 0;
logEntryFound = false;
}
private void updatePreviews() {
if (inputText == null) {
// early update during construction
return;
}
inputText.setStyleRanges(new StyleRange[] {});
if (selectedElement == null) {
return;
}
initValues();
selectedElement.updatePreview();
if (timeStampValue != null && timeStampFormat != null) {
try {
TmfTimestampFormat timestampFormat = new TmfTimestampFormat(timeStampFormat);
long timestamp = timestampFormat.parseValue(timeStampValue);
if (timeStampOutputFormatText.getText().trim().isEmpty()) {
timestampFormat = new TmfTimestampFormat();
} else {
timestampFormat = new TmfTimestampFormat(timeStampOutputFormatText.getText().trim());
}
timeStampPreviewText.setText(timestampFormat.format(timestamp));
} catch (ParseException e) {
timeStampPreviewText.setText("*parse exception* [" + timeStampValue + "] <> [" + timeStampFormat + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
} catch (IllegalArgumentException e) {
timeStampPreviewText.setText("*parse exception* [Illegal Argument]"); //$NON-NLS-1$
}
} else {
timeStampPreviewText.setText("*no matching time stamp*"); //$NON-NLS-1$
}
}
private void openHelpShell(String url) {
if (helpBrowser != null && !helpBrowser.isDisposed()) {
helpBrowser.getShell().setActive();
if (!helpBrowser.getUrl().equals(url)) {
helpBrowser.setUrl(url);
}
return;
}
final Shell helpShell = new Shell(getShell(), SWT.SHELL_TRIM);
helpShell.setLayout(new FillLayout());
helpBrowser = new Browser(helpShell, SWT.NONE);
helpBrowser.addTitleListener(event -> helpShell.setText(event.title));
Rectangle r = container.getBounds();
Point p = container.toDisplay(r.x, r.y);
Rectangle trim = helpShell.computeTrim(p.x + (r.width - 750) / 2, p.y + (r.height - 400) / 2, 750, 400);
helpShell.setBounds(trim);
helpShell.open();
helpBrowser.setUrl(url);
}
private class UpdateListener implements ModifyListener, SelectionListener {
@Override
public void modifyText(ModifyEvent e) {
validate();
updatePreviews();
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
validate();
updatePreviews();
}
@Override
public void widgetSelected(SelectionEvent e) {
validate();
updatePreviews();
}
}
private class ElementNode {
private final CustomXmlInputElement inputElement;
private final Group group;
private List<Attribute> attributes = new ArrayList<>();
private List<ElementNode> childElements = new ArrayList<>();
private Text elementNameText;
private Composite tagComposite;
private Combo tagCombo;
private Label tagLabel;
private Text tagText;
private Combo actionCombo;
private Label previewLabel;
private Text previewText;
private Button logEntryButton;
private Button eventTypeButton;
private Text eventTypeText;
private Label fillerLabel;
private Composite addAttributeComposite;
private Button addAttributeButton;
private Label addAttributeLabel;
public ElementNode(Composite parent, CustomXmlInputElement inputElement) {
this.inputElement = inputElement;
group = new Group(parent, SWT.NONE);
GridLayout gl = new GridLayout(2, false);
gl.marginHeight = 0;
group.setLayout(gl);
group.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
group.setText(getName(inputElement));
Label label = new Label(group, SWT.NULL);
label.setText(Messages.CustomXmlParserInputWizardPage_elementName);
label.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
elementNameText = new Text(group, SWT.BORDER | SWT.SINGLE);
GridData gd = new GridData(SWT.FILL, SWT.CENTER, true, false);
gd.widthHint = 0;
elementNameText.setLayoutData(gd);
elementNameText.addModifyListener(e -> {
ElementNode.this.inputElement.setElementName(elementNameText.getText().trim());
group.setText(getName(ElementNode.this.inputElement));
});
elementNameText.setText(inputElement.getElementName());
elementNameText.addModifyListener(updateListener);
if (inputElement.getParentElement() != null) {
previewLabel = new Label(group, SWT.NULL);
previewLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
previewLabel.setText(Messages.CustomXmlParserInputWizardPage_preview);
previewText = new Text(group, SWT.BORDER | SWT.SINGLE | SWT.READ_ONLY);
gd = new GridData(SWT.FILL, SWT.CENTER, true, false);
gd.widthHint = 0;
previewText.setLayoutData(gd);
previewText.setText(Messages.CustomXmlParserInputWizardPage_noMatchingElement);
previewText.setBackground(COLOR_WIDGET_BACKGROUND);
logEntryButton = new Button(group, SWT.CHECK);
logEntryButton.setText(Messages.CustomXmlParserInputWizardPage_logEntry);
logEntryButton.setSelection(inputElement.isLogEntry());
logEntryButton.addSelectionListener(new SelectionListener() {
@Override
public void widgetDefaultSelected(SelectionEvent e) {
// Do nothing
}
@Override
public void widgetSelected(SelectionEvent e) {
CustomXmlInputElement parentElem = ElementNode.this.inputElement.getParentElement();
while (parentElem != null) {
parentElem.setLogEntry(false);
parentElem = parentElem.getParentElement();
}
}
});
logEntryButton.addSelectionListener(updateListener);
tagComposite = new Composite(group, SWT.FILL);
GridLayout tagLayout = new GridLayout(4, false);
tagLayout.marginWidth = 0;
tagLayout.marginHeight = 0;
tagComposite.setLayout(tagLayout);
tagComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
tagCombo = new Combo(tagComposite, SWT.DROP_DOWN | SWT.READ_ONLY);
tagCombo.setItems(new String[] {
Tag.IGNORE.toString(),
Tag.TIMESTAMP.toString(),
Tag.EVENT_TYPE.toString(),
Tag.MESSAGE.toString(),
Tag.EXTRA_FIELD_NAME.toString(),
Tag.EXTRA_FIELD_VALUE.toString(),
Tag.OTHER.toString() });
tagCombo.setVisibleItemCount(tagCombo.getItemCount());
tagCombo.addSelectionListener(new SelectionListener() {
@Override
public void widgetDefaultSelected(SelectionEvent e) {
// Do nothing
}
@Override
public void widgetSelected(SelectionEvent e) {
tagText.removeModifyListener(updateListener);
switch (tagCombo.getSelectionIndex()) {
case 0: // Ignore
tagLabel.setVisible(false);
tagText.setVisible(false);
actionCombo.setVisible(false);
break;
case 1: // Time Stamp
tagLabel.setText(Messages.CustomXmlParserInputWizardPage_format);
tagLabel.setVisible(true);
tagText.setVisible(true);
tagText.addModifyListener(updateListener);
actionCombo.setVisible(true);
break;
case 2: // Event type
tagLabel.setVisible(false);
tagText.setVisible(false);
actionCombo.setVisible(true);
break;
case 3: // Message
tagLabel.setVisible(false);
tagText.setVisible(false);
actionCombo.setVisible(true);
break;
case 4: // Field names
tagLabel.setVisible(false);
tagText.setVisible(false);
actionCombo.setVisible(false);
break;
case 5: // Field values
tagLabel.setVisible(false);
tagText.setVisible(false);
actionCombo.setVisible(true);
break;
case 6: // Other
tagLabel.setText(Messages.CustomXmlParserInputWizardPage_name);
tagLabel.setVisible(true);
if (tagText.getText().trim().length() == 0) {
tagText.setText(elementNameText.getText().trim());
}
tagText.setVisible(true);
tagText.addModifyListener(updateListener);
actionCombo.setVisible(true);
break;
default:
break;
}
tagComposite.layout();
validate();
updatePreviews();
}
});
tagLabel = new Label(tagComposite, SWT.NULL);
tagLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
tagText = new Text(tagComposite, SWT.BORDER | SWT.SINGLE);
gd = new GridData(SWT.FILL, SWT.CENTER, true, false);
gd.widthHint = 0;
tagText.setLayoutData(gd);
actionCombo = new Combo(tagComposite, SWT.DROP_DOWN | SWT.READ_ONLY);
actionCombo.setItems(new String[] { Messages.CustomXmlParserInputWizardPage_set, Messages.CustomXmlParserInputWizardPage_append,
Messages.CustomXmlParserInputWizardPage_appendWith });
actionCombo.select(inputElement.getInputAction());
actionCombo.addSelectionListener(updateListener);
if (inputElement.getInputTag().equals(Tag.IGNORE)) {
tagCombo.select(0);
tagLabel.setVisible(false);
tagText.setVisible(false);
actionCombo.setVisible(false);
} else if (inputElement.getInputTag().equals(Tag.TIMESTAMP)) {
tagCombo.select(1);
tagLabel.setText(Messages.CustomXmlParserInputWizardPage_format);
tagText.setText(inputElement.getInputFormat());
tagText.addModifyListener(updateListener);
actionCombo.setVisible(true);
} else if (inputElement.getInputTag().equals(Tag.EVENT_TYPE)) {
tagCombo.select(2);
tagLabel.setVisible(false);
tagText.setVisible(false);
actionCombo.setVisible(true);
} else if (inputElement.getInputTag().equals(Tag.MESSAGE)) {
tagCombo.select(3);
tagLabel.setVisible(false);
tagText.setVisible(false);
actionCombo.setVisible(true);
} else if (inputElement.getInputTag().equals(Tag.EXTRA_FIELD_NAME)) {
tagCombo.select(4);
tagLabel.setVisible(false);
tagText.setVisible(false);
actionCombo.setVisible(false);
} else if (inputElement.getInputTag().equals(Tag.EXTRA_FIELD_VALUE)) {
tagCombo.select(5);
tagLabel.setVisible(false);
tagText.setVisible(false);
actionCombo.setVisible(true);
} else {
tagCombo.select(6);
tagLabel.setText(Messages.CustomXmlParserInputWizardPage_name);
tagText.setText(inputElement.getInputName());
tagText.addModifyListener(updateListener);
actionCombo.setVisible(true);
}
eventTypeButton = new Button(group, SWT.CHECK);
eventTypeButton.setText(Messages.CustomTxtParserInputWizardPage_eventType);
eventTypeButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
eventTypeButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (eventTypeButton.getSelection()) {
eventTypeText.setEnabled(true);
} else {
eventTypeText.setEnabled(false);
}
}
});
eventTypeButton.addSelectionListener(updateListener);
eventTypeText = new Text(group, SWT.BORDER | SWT.SINGLE);
gd = new GridData(SWT.FILL, SWT.CENTER, true, false);
gd.widthHint = 0;
eventTypeText.setLayoutData(gd);
if (inputElement.getEventType() != null) {
eventTypeText.setText(inputElement.getEventType());
eventTypeButton.setSelection(true);
} else {
eventTypeText.setEnabled(false);
eventTypeButton.setSelection(false);
}
eventTypeText.addModifyListener(updateListener);
}
if (inputElement.getAttributes() != null) {
for (CustomXmlInputAttribute inputAttribute : inputElement.getAttributes()) {
Attribute attribute = new Attribute(group, this, inputAttribute, attributes.size() + 1);
attributes.add(attribute);
}
}
createAddButton();
}
private void updatePreview() {
Element element = getPreviewElement(inputElement);
// no preview text for document element
if (inputElement.getParentElement() != null) {
previewText.setText(Messages.CustomXmlParserInputWizardPage_noMatchingElement);
if (element != null) {
previewText.setText(CustomXmlTrace.parseElement(element, new StringBuffer()).toString());
if (logEntryButton.getSelection()) {
if (!logEntryFound) {
logEntryFound = true;
logEntriesCount++;
} else {
// remove nested log entry
logEntryButton.setSelection(false);
}
}
if (tagCombo.getText().equals(Tag.TIMESTAMP.toString()) && logEntriesCount <= 1) {
String value = previewText.getText().trim();
if (value.length() != 0) {
if (actionCombo.getSelectionIndex() == CustomTraceDefinition.ACTION_SET) {
timeStampValue = value;
timeStampFormat = tagText.getText().trim();
} else if (actionCombo.getSelectionIndex() == CustomTraceDefinition.ACTION_APPEND) {
if (timeStampValue != null) {
timeStampValue += value;
timeStampFormat += tagText.getText().trim();
} else {
timeStampValue = value;
timeStampFormat = tagText.getText().trim();
}
} else if (actionCombo.getSelectionIndex() == CustomTraceDefinition.ACTION_APPEND_WITH_SEPARATOR) {
if (timeStampValue != null) {
timeStampValue += CustomTraceDefinition.SEPARATOR + value;
timeStampFormat += CustomTraceDefinition.SEPARATOR + tagText.getText().trim();
} else {
timeStampValue = value;
timeStampFormat = tagText.getText().trim();
}
}
}
}
}
}
for (Attribute attribute : attributes) {
if (element != null) {
String value = element.getAttribute(attribute.attributeNameText.getText().trim());
if (value.length() != 0) {
attribute.previewText.setText(value);
if (attribute.tagCombo.getText().equals(Tag.TIMESTAMP.toString()) && logEntriesCount <= 1) {
if (attribute.actionCombo.getSelectionIndex() == CustomTraceDefinition.ACTION_SET) {
timeStampValue = value;
timeStampFormat = attribute.tagText.getText().trim();
} else if (attribute.actionCombo.getSelectionIndex() == CustomTraceDefinition.ACTION_APPEND) {
if (timeStampValue != null) {
timeStampValue += value;
timeStampFormat += attribute.tagText.getText().trim();
} else {
timeStampValue = value;
timeStampFormat = attribute.tagText.getText().trim();
}
} else if (attribute.actionCombo.getSelectionIndex() == CustomTraceDefinition.ACTION_APPEND_WITH_SEPARATOR) {
if (timeStampValue != null) {
timeStampValue += " | " + value; //$NON-NLS-1$
timeStampFormat += " | " + attribute.tagText.getText().trim(); //$NON-NLS-1$
} else {
timeStampValue = value;
timeStampFormat = attribute.tagText.getText().trim();
}
}
}
} else {
attribute.previewText.setText(Messages.CustomXmlParserInputWizardPage_noMatchingAttribute);
}
} else {
attribute.previewText.setText(Messages.CustomXmlParserInputWizardPage_noMatchingElement);
}
}
for (ElementNode child : childElements) {
child.updatePreview();
}
if (logEntryButton != null && logEntryButton.getSelection()) {
logEntryFound = false;
}
}
private void createAddButton() {
fillerLabel = new Label(group, SWT.NONE);
addAttributeComposite = new Composite(group, SWT.NONE);
addAttributeComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
GridLayout addAttributeLayout = new GridLayout(2, false);
addAttributeLayout.marginHeight = 0;
addAttributeLayout.marginWidth = 0;
addAttributeComposite.setLayout(addAttributeLayout);
addAttributeButton = new Button(addAttributeComposite, SWT.PUSH);
addAttributeButton.setImage(ADD_IMAGE);
addAttributeButton.setToolTipText(Messages.CustomXmlParserInputWizardPage_addAttribute);
addAttributeButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
removeAddButton();
String attributeName = getAttributeNameSuggestion(inputElement);
CustomXmlInputAttribute inputAttribute = new CustomXmlInputAttribute(attributeName, Tag.OTHER, attributeName, 0, ""); //$NON-NLS-1$
attributes.add(new Attribute(group, ElementNode.this, inputAttribute, attributes.size() + 1));
createAddButton();
elementContainer.layout();
elementScrolledComposite.setMinSize(elementContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x,
elementContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y - 1);
group.getParent().layout();
validate();
updatePreviews();
}
});
addAttributeLabel = new Label(addAttributeComposite, SWT.NULL);
addAttributeLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
addAttributeLabel.setText(Messages.CustomXmlParserInputWizardPage_newAttibute);
}
private void removeAddButton() {
fillerLabel.dispose();
addAttributeComposite.dispose();
}
private void removeAttribute(int attributeNumber) {
int nb = attributeNumber;
if (--nb < attributes.size()) {
attributes.remove(nb).dispose();
for (int i = nb; i < attributes.size(); i++) {
attributes.get(i).setAttributeNumber(i + 1);
}
elementContainer.layout();
elementScrolledComposite.setMinSize(elementContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x,
elementContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y - 1);
group.getParent().layout();
}
}
private void dispose() {
group.dispose();
}
private void extractInputs() {
inputElement.setElementName(elementNameText.getText().trim());
if (inputElement.getParentElement() != null) {
inputElement.setLogEntry(logEntryButton.getSelection());
inputElement.setEventType(eventTypeButton.getSelection() ? eventTypeText.getText().trim() : null);
Tag inputTag = Tag.fromLabel(tagCombo.getText());
inputElement.setInputTag(inputTag);
if (inputTag.equals(Tag.OTHER)) {
inputElement.setInputName(tagText.getText().trim());
} else {
inputElement.setInputName(inputTag.toString());
if (inputTag.equals(Tag.TIMESTAMP)) {
inputElement.setInputFormat(tagText.getText().trim());
}
}
inputElement.setInputAction(actionCombo.getSelectionIndex());
}
inputElement.setAttributes(new ArrayList<CustomXmlInputAttribute>(attributes.size()));
for (int i = 0; i < attributes.size(); i++) {
String inputName = null;
String inputFormat = null;
Attribute attribute = attributes.get(i);
String attributeName = attribute.attributeNameText.getText().trim();
Tag inputTag = Tag.fromLabel(attribute.tagCombo.getText());
if (inputTag.equals(Tag.OTHER)) {
inputName = attribute.tagText.getText().trim();
} else {
inputName = inputTag.toString();
if (inputTag.equals(Tag.TIMESTAMP)) {
inputFormat = attribute.tagText.getText().trim();
}
}
int inputAction = attribute.actionCombo.getSelectionIndex();
inputElement.addAttribute(new CustomXmlInputAttribute(attributeName, inputTag, inputName, inputAction, inputFormat));
}
}
}
private class Attribute {
private ElementNode element;
private int attributeNumber;
// children of parent (must be disposed)
private Composite labelComposite;
private Composite attributeComposite;
private Label filler;
private Composite tagComposite;
// children of labelComposite
private Label attributeLabel;
// children of attributeComposite
private Text attributeNameText;
private Text previewText;
// children of tagComposite
private Combo tagCombo;
private Label tagLabel;
private Text tagText;
private Combo actionCombo;
public Attribute(Composite parent, ElementNode element, CustomXmlInputAttribute inputAttribute, int attributeNumber) {
this.element = element;
this.attributeNumber = attributeNumber;
labelComposite = new Composite(parent, SWT.FILL);
GridLayout labelLayout = new GridLayout(2, false);
labelLayout.marginWidth = 0;
labelLayout.marginHeight = 0;
labelComposite.setLayout(labelLayout);
labelComposite.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
Button deleteButton = new Button(labelComposite, SWT.PUSH);
deleteButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
deleteButton.setImage(DELETE_IMAGE);
deleteButton.setToolTipText(Messages.CustomXmlParserInputWizardPage_removeAttribute);
deleteButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
Attribute.this.element.removeAttribute(Attribute.this.attributeNumber);
validate();
updatePreviews();
}
});
attributeLabel = new Label(labelComposite, SWT.NULL);
attributeLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
attributeLabel.setText(Messages.CustomXmlParserInputWizardPage_attibute);
attributeComposite = new Composite(parent, SWT.FILL);
GridLayout attributeLayout = new GridLayout(4, false);
attributeLayout.marginWidth = 0;
attributeLayout.marginHeight = 0;
attributeComposite.setLayout(attributeLayout);
attributeComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
Label nameLabel = new Label(attributeComposite, SWT.NONE);
nameLabel.setText(Messages.CustomXmlParserInputWizardPage_name);
attributeNameText = new Text(attributeComposite, SWT.BORDER | SWT.SINGLE);
attributeNameText.setLayoutData(new GridData(120, SWT.DEFAULT));
attributeNameText.setText(inputAttribute.getAttributeName());
attributeNameText.addModifyListener(updateListener);
Label previewLabel = new Label(attributeComposite, SWT.NONE);
previewLabel.setText(Messages.CustomXmlParserInputWizardPage_preview);
previewText = new Text(attributeComposite, SWT.BORDER | SWT.SINGLE | SWT.READ_ONLY);
GridData gd = new GridData(SWT.FILL, SWT.CENTER, true, false);
gd.widthHint = 0;
previewText.setLayoutData(gd);
previewText.setText(Messages.CustomXmlParserInputWizardPage_noMatch);
previewText.setBackground(COLOR_WIDGET_BACKGROUND);
filler = new Label(parent, SWT.NULL);
tagComposite = new Composite(parent, SWT.FILL);
GridLayout tagLayout = new GridLayout(4, false);
tagLayout.marginWidth = 0;
tagLayout.marginHeight = 0;
tagComposite.setLayout(tagLayout);
tagComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
tagCombo = new Combo(tagComposite, SWT.DROP_DOWN | SWT.READ_ONLY);
tagCombo.setItems(new String[] {
Tag.TIMESTAMP.toString(),
Tag.EVENT_TYPE.toString(),
Tag.MESSAGE.toString(),
Tag.EXTRA_FIELD_NAME.toString(),
Tag.EXTRA_FIELD_VALUE.toString(),
Tag.OTHER.toString() });
tagCombo.select(3); // Other
tagCombo.addSelectionListener(new SelectionListener() {
@Override
public void widgetDefaultSelected(SelectionEvent e) {
// Do nothing
}
@Override
public void widgetSelected(SelectionEvent e) {
tagText.removeModifyListener(updateListener);
switch (tagCombo.getSelectionIndex()) {
case 0: // Time Stamp
tagLabel.setText(Messages.CustomXmlParserInputWizardPage_format);
tagLabel.setVisible(true);
tagText.setVisible(true);
tagText.addModifyListener(updateListener);
actionCombo.setVisible(true);
break;
case 1: // Event type
tagLabel.setVisible(false);
tagText.setVisible(false);
actionCombo.setVisible(true);
break;
case 2: // Message
tagLabel.setVisible(false);
tagText.setVisible(false);
actionCombo.setVisible(true);
break;
case 3: // Field names
tagLabel.setVisible(false);
tagText.setVisible(false);
actionCombo.setVisible(false);
break;
case 4: // Field values
tagLabel.setVisible(false);
tagText.setVisible(false);
actionCombo.setVisible(true);
break;
case 5: // Other
tagLabel.setText(Messages.CustomXmlParserInputWizardPage_name);
tagLabel.setVisible(true);
if (tagText.getText().trim().length() == 0) {
tagText.setText(attributeNameText.getText().trim());
}
tagText.setVisible(true);
tagText.addModifyListener(updateListener);
actionCombo.setVisible(true);
break;
default:
break;
}
tagComposite.layout();
validate();
updatePreviews();
}
});
tagLabel = new Label(tagComposite, SWT.NULL);
tagLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
tagText = new Text(tagComposite, SWT.BORDER | SWT.SINGLE);
gd = new GridData(SWT.FILL, SWT.CENTER, true, false);
gd.widthHint = 0;
tagText.setLayoutData(gd);
tagText.setText(attributeNameText.getText());
actionCombo = new Combo(tagComposite, SWT.DROP_DOWN | SWT.READ_ONLY);
actionCombo.setItems(new String[] { Messages.CustomXmlParserInputWizardPage_set, Messages.CustomXmlParserInputWizardPage_append,
Messages.CustomXmlParserInputWizardPage_appendWith });
actionCombo.select(inputAttribute.getInputAction());
actionCombo.addSelectionListener(updateListener);
if (inputAttribute.getInputTag().equals(Tag.TIMESTAMP)) {
tagCombo.select(0);
tagLabel.setText(Messages.CustomXmlParserInputWizardPage_format);
tagText.setText(inputAttribute.getInputFormat());
tagText.addModifyListener(updateListener);
actionCombo.setVisible(true);
} else if (inputAttribute.getInputTag().equals(Tag.EVENT_TYPE)) {
tagCombo.select(1);
tagLabel.setVisible(false);
tagText.setVisible(false);
actionCombo.setVisible(true);
} else if (inputAttribute.getInputTag().equals(Tag.MESSAGE)) {
tagCombo.select(2);
tagLabel.setVisible(false);
tagText.setVisible(false);
actionCombo.setVisible(true);
} else if (inputAttribute.getInputTag().equals(Tag.EXTRA_FIELD_NAME)) {
tagCombo.select(3);
tagLabel.setVisible(false);
tagText.setVisible(false);
actionCombo.setVisible(false);
} else if (inputAttribute.getInputTag().equals(Tag.EXTRA_FIELD_VALUE)) {
tagCombo.select(4);
tagLabel.setVisible(false);
tagText.setVisible(false);
actionCombo.setVisible(true);
} else {
tagCombo.select(5);
tagLabel.setText(Messages.CustomXmlParserInputWizardPage_name);
tagText.setText(inputAttribute.getInputName());
tagText.addModifyListener(updateListener);
actionCombo.setVisible(true);
}
}
private void dispose() {
labelComposite.dispose();
attributeComposite.dispose();
filler.dispose();
tagComposite.dispose();
}
private void setAttributeNumber(int attributeNumber) {
this.attributeNumber = attributeNumber;
labelComposite.layout();
}
}
private Element getPreviewElement(CustomXmlInputElement inputElement) {
CustomXmlInputElement currentElement = inputElement;
Element element = documentElement;
if (element != null) {
if (!documentElement.getNodeName().equals(definition.rootInputElement.getElementName())) {
return null;
}
ArrayList<String> elementNames = new ArrayList<>();
while (currentElement != null) {
elementNames.add(currentElement.getElementName());
currentElement = currentElement.getParentElement();
}
for (int i = elementNames.size() - 1; --i >= 0;) {
NodeList childList = element.getChildNodes();
element = null;
for (int j = 0; j < childList.getLength(); j++) {
Node child = childList.item(j);
if (child instanceof Element && child.getNodeName().equals(elementNames.get(i))) {
element = (Element) child;
break;
}
}
if (element == null) {
break;
}
}
if (element != null) {
return element;
}
}
return null;
}
private String getChildNameSuggestion(CustomXmlInputElement inputElement) {
if (inputElement == null) {
if (documentElement != null) {
return documentElement.getNodeName();
}
} else {
Element element = getPreviewElement(inputElement);
if (element != null) {
NodeList childNodes = element.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node node = childNodes.item(i);
if (node instanceof Element) {
boolean unused = true;
if (inputElement.getChildElements() != null) {
for (CustomXmlInputElement child : inputElement.getChildElements()) {
if (child.getElementName().equals(node.getNodeName())) {
unused = false;
break;
}
}
}
if (unused) {
return node.getNodeName();
}
}
}
}
}
return ""; //$NON-NLS-1$
}
private String getAttributeNameSuggestion(CustomXmlInputElement inputElement) {
Element element = getPreviewElement(inputElement);
if (element != null) {
NamedNodeMap attributeMap = element.getAttributes();
for (int i = 0; i < attributeMap.getLength(); i++) {
Node node = attributeMap.item(i);
boolean unused = true;
if (inputElement.getAttributes() != null) {
for (CustomXmlInputAttribute attribute : inputElement.getAttributes()) {
if (attribute.getAttributeName().equals(node.getNodeName())) {
unused = false;
break;
}
}
}
if (unused) {
return node.getNodeName();
}
}
}
return ""; //$NON-NLS-1$
}
private void validate() {
definition.categoryName = categoryText.getText().trim();
definition.definitionName = logtypeText.getText().trim();
definition.timeStampOutputFormat = timeStampOutputFormatText.getText().trim();
if (selectedElement != null) {
selectedElement.extractInputs();
treeViewer.refresh();
}
List<String> errors = new ArrayList<>();
if (definition.categoryName.length() == 0) {
errors.add(Messages.CustomXmlParserInputWizardPage_emptyCategoryError);
categoryText.setBackground(COLOR_LIGHT_RED);
} else if (definition.definitionName.length() == 0) {
errors.add(Messages.CustomXmlParserInputWizardPage_emptyLogTypeError);
logtypeText.setBackground(COLOR_LIGHT_RED);
} else {
categoryText.setBackground(COLOR_TEXT_BACKGROUND);
logtypeText.setBackground(COLOR_TEXT_BACKGROUND);
if (definition.categoryName.indexOf(':') != -1) {
errors.add(Messages.CustomXmlParserInputWizardPage_invalidCategoryError);
categoryText.setBackground(COLOR_LIGHT_RED);
}
if (definition.definitionName.indexOf(':') != -1) {
errors.add(Messages.CustomXmlParserInputWizardPage_invalidLogTypeError);
logtypeText.setBackground(COLOR_LIGHT_RED);
}
for (TraceTypeHelper helper : TmfTraceType.getTraceTypeHelpers()) {
if (definition.categoryName.equals(helper.getCategoryName()) &&
definition.definitionName.equals(helper.getName()) &&
(editDefinitionName == null || !editDefinitionName.equals(definition.definitionName)) &&
(editCategoryName == null || !editCategoryName.equals(definition.categoryName))) {
errors.add(Messages.CustomXmlParserInputWizardPage_duplicatelogTypeError);
logtypeText.setBackground(COLOR_LIGHT_RED);
break;
}
}
}
if (definition.rootInputElement == null) {
errors.add(Messages.CustomXmlParserInputWizardPage_noDocumentError);
}
if (definition.rootInputElement != null) {
logEntryFound = false;
timeStampFound = false;
errors.addAll(validateElement(definition.rootInputElement));
if ((definition.rootInputElement.getAttributes() != null && !definition.rootInputElement.getAttributes().isEmpty())
|| (definition.rootInputElement.getChildElements() != null && !definition.rootInputElement.getChildElements().isEmpty())
|| errors.isEmpty()) {
if (!logEntryFound) {
errors.add(Messages.CustomXmlParserInputWizardPage_missingLogEntryError);
}
if (timeStampFound && !definition.timeStampOutputFormat.isEmpty()) {
try {
new TmfTimestampFormat(timeStampOutputFormatText.getText().trim());
timeStampOutputFormatText.setBackground(COLOR_TEXT_BACKGROUND);
} catch (IllegalArgumentException e) {
errors.add(Messages.CustomXmlParserInputWizardPage_elementInvalidTimestampFmtError);
timeStampOutputFormatText.setBackground(COLOR_LIGHT_RED);
}
} else {
timeStampOutputFormatText.setBackground(COLOR_TEXT_BACKGROUND);
if (!timeStampFound) {
timeStampPreviewText.setText(Messages.CustomXmlParserInputWizardPage_noTimestampElementOrAttribute);
}
}
}
} else {
timeStampPreviewText.setText(Messages.CustomXmlParserInputWizardPage_noTimestampElementOrAttribute);
}
if (errors.isEmpty()) {
setDescription(defaultDescription);
setPageComplete(true);
} else {
setDescription(Joiner.on(' ').join(errors));
setPageComplete(false);
}
}
/**
* Clean up the specified XML element.
*
* @param inputElement
* The element to clean up
* @return The validated element
*/
public List<String> validateElement(CustomXmlInputElement inputElement) {
List<String> errors = new ArrayList<>();
ElementNode elementNode = null;
if (selectedElement != null && selectedElement.inputElement.equals(inputElement)) {
elementNode = selectedElement;
}
if (inputElement == definition.rootInputElement) {
if (inputElement.getElementName().length() == 0) {
errors.add(Messages.CustomXmlParserInputWizardPage_missingDocumentElementError);
if (elementNode != null) {
elementNode.elementNameText.setBackground(COLOR_LIGHT_RED);
}
} else {
if (elementNode != null) {
elementNode.elementNameText.setBackground(COLOR_TEXT_BACKGROUND);
}
}
}
if (inputElement != definition.rootInputElement) {
if (inputElement.isLogEntry()) {
logEntryFound = true;
}
if (inputElement.getInputTag().equals(Tag.TIMESTAMP)) {
timeStampFound = true;
if (inputElement.getInputFormat().length() == 0) {
errors.add(NLS.bind(Messages.CustomXmlParserInputWizardPage_elementMissingTimestampFmtError, getName(inputElement)));
if (elementNode != null) {
elementNode.tagText.setBackground(COLOR_LIGHT_RED);
}
} else {
try {
new TmfTimestampFormat(inputElement.getInputFormat());
if (elementNode != null) {
elementNode.tagText.setBackground(COLOR_TEXT_BACKGROUND);
}
} catch (IllegalArgumentException e) {
errors.add(NLS.bind(Messages.CustomXmlParserInputWizardPage_elementInvalidTimestampFmtError, getName(inputElement)));
if (elementNode != null) {
elementNode.tagText.setBackground(COLOR_LIGHT_RED);
}
}
}
} else if (inputElement.getInputName().length() == 0) {
errors.add(NLS.bind(Messages.CustomXmlParserInputWizardPage_elementMissingInputNameError, getName(inputElement)));
if (elementNode != null) {
elementNode.tagText.setBackground(COLOR_LIGHT_RED);
}
} else if (inputElement.getInputTag().equals(Tag.OTHER) && Tag.fromLabel(inputElement.getInputName()) != null) {
errors.add(NLS.bind(Messages.CustomXmlParserInputWizardPage_elementReservedInputNameError, getName(inputElement)));
if (elementNode != null) {
elementNode.tagText.setBackground(COLOR_LIGHT_RED);
}
} else {
if (elementNode != null) {
elementNode.tagText.setBackground(COLOR_TEXT_BACKGROUND);
}
}
if (inputElement.getEventType() != null && inputElement.getEventType().trim().isEmpty()) {
errors.add(NLS.bind(Messages.CustomXmlParserInputWizardPage_emptyEventTypeError, getName(inputElement)));
if (elementNode != null) {
elementNode.eventTypeText.setBackground(COLOR_LIGHT_RED);
}
} else {
if (elementNode != null) {
elementNode.eventTypeText.setBackground(COLOR_TEXT_BACKGROUND);
}
}
}
if (inputElement.getAttributes() != null) {
if (elementNode != null) {
for (Attribute attribute : elementNode.attributes) {
attribute.attributeNameText.setBackground(COLOR_TEXT_BACKGROUND);
}
}
for (int i = 0; i < inputElement.getAttributes().size(); i++) {
CustomXmlInputAttribute attribute = inputElement.getAttributes().get(i);
boolean duplicate = false;
for (int j = i + 1; j < inputElement.getAttributes().size(); j++) {
CustomXmlInputAttribute otherAttribute = inputElement.getAttributes().get(j);
if (otherAttribute.getAttributeName().equals(attribute.getAttributeName())) {
duplicate = true;
if (elementNode != null) {
elementNode.attributes.get(j).attributeNameText.setBackground(COLOR_LIGHT_RED);
}
}
}
if (attribute.getAttributeName().length() == 0) {
errors.add(NLS.bind(Messages.CustomXmlParserInputWizardPage_attributeMissingNameError, getName(inputElement)));
if (elementNode != null) {
elementNode.attributes.get(i).attributeNameText.setBackground(COLOR_LIGHT_RED);
}
} else if (duplicate) {
errors.add(NLS.bind(Messages.CustomXmlParserInputWizardPage_attributeDuplicateNameError, getName(attribute, inputElement)));
if (elementNode != null) {
elementNode.attributes.get(i).attributeNameText.setBackground(COLOR_LIGHT_RED);
}
}
if (attribute.getInputTag().equals(Tag.TIMESTAMP)) {
timeStampFound = true;
if (attribute.getInputFormat().length() == 0) {
errors.add(NLS.bind(Messages.CustomXmlParserInputWizardPage_attributeMissingTimestampFmtError, getName(attribute, inputElement)));
if (elementNode != null) {
elementNode.attributes.get(i).tagText.setBackground(COLOR_LIGHT_RED);
}
} else {
try {
new TmfTimestampFormat(attribute.getInputFormat());
if (elementNode != null) {
elementNode.attributes.get(i).tagText.setBackground(COLOR_TEXT_BACKGROUND);
}
} catch (IllegalArgumentException e) {
errors.add(NLS.bind(Messages.CustomXmlParserInputWizardPage_attributeInvalidTimestampFmtError, getName(attribute, inputElement)));
if (elementNode != null) {
elementNode.attributes.get(i).tagText.setBackground(COLOR_LIGHT_RED);
}
}
}
} else if (attribute.getInputName().length() == 0) {
errors.add(NLS.bind(Messages.CustomXmlParserInputWizardPage_attributeMissingInputNameError, getName(attribute, inputElement)));
if (elementNode != null) {
elementNode.attributes.get(i).tagText.setBackground(COLOR_LIGHT_RED);
}
} else if (attribute.getInputTag().equals(Tag.OTHER) && Tag.fromLabel(attribute.getInputName()) != null) {
errors.add(NLS.bind(Messages.CustomXmlParserInputWizardPage_attributeReservedInputNameError, getName(attribute, inputElement)));
if (elementNode != null) {
elementNode.attributes.get(i).tagText.setBackground(COLOR_LIGHT_RED);
}
} else {
if (elementNode != null) {
elementNode.attributes.get(i).tagText.setBackground(COLOR_TEXT_BACKGROUND);
}
}
}
}
if (inputElement.getChildElements() != null) {
for (CustomXmlInputElement child : inputElement.getChildElements()) {
ElementNode childElementNode = null;
if (selectedElement != null && selectedElement.inputElement.equals(child)) {
childElementNode = selectedElement;
}
if (childElementNode != null) {
childElementNode.elementNameText.setBackground(COLOR_TEXT_BACKGROUND);
}
}
for (int i = 0; i < inputElement.getChildElements().size(); i++) {
CustomXmlInputElement child = inputElement.getChildElements().get(i);
ElementNode childElementNode = null;
if (selectedElement != null && selectedElement.inputElement.equals(child)) {
childElementNode = selectedElement;
}
if (child.getElementName().length() == 0) {
errors.add(NLS.bind(Messages.CustomXmlParserInputWizardPage_elementMissingNameError, getName(child)));
if (childElementNode != null) {
childElementNode.elementNameText.setBackground(COLOR_LIGHT_RED);
}
} else {
boolean duplicate = false;
for (int j = i + 1; j < inputElement.getChildElements().size(); j++) {
CustomXmlInputElement otherChild = inputElement.getChildElements().get(j);
if (otherChild.getElementName().equals(child.getElementName())) {
duplicate = true;
ElementNode otherChildElementNode = null;
if (selectedElement != null && selectedElement.inputElement.equals(otherChild)) {
otherChildElementNode = selectedElement;
}
if (otherChildElementNode != null) {
otherChildElementNode.elementNameText.setBackground(COLOR_LIGHT_RED);
}
}
}
if (duplicate) {
errors.add(NLS.bind(Messages.CustomXmlParserInputWizardPage_elementDuplicateNameError, getName(child)));
if (childElementNode != null) {
childElementNode.elementNameText.setBackground(COLOR_LIGHT_RED);
}
}
}
errors.addAll(validateElement(child));
}
}
return errors;
}
/**
* Get the trace definition.
*
* @return The trace definition
*/
public CustomXmlTraceDefinition getDefinition() {
return definition;
}
/**
* Get the raw text input.
*
* @return The raw text input.
*/
public char[] getInputText() {
return inputText.getText().toCharArray();
}
}