/******************************************************************************* * 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 v1.0 which * accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Patrick Tasse - Initial API and implementation *******************************************************************************/ package org.eclipse.tracecompass.internal.tmf.ui.parsers.wizards; import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; import java.text.ParseException; import java.util.AbstractMap.SimpleEntry; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; 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.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.browser.TitleEvent; import org.eclipse.swt.browser.TitleListener; 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.events.VerifyEvent; import org.eclipse.swt.events.VerifyListener; 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.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.CustomTxtTraceDefinition; import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomTxtTraceDefinition.Cardinality; import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomTxtTraceDefinition.InputData; import org.eclipse.tracecompass.tmf.core.parsers.custom.CustomTxtTraceDefinition.InputLine; 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; /** * Input wizard page for custom text parsers. * * @author Patrick Tasse */ public class CustomTxtParserInputWizardPage extends WizardPage { private static final String DEFAULT_REGEX = "\\s*(.*\\S)"; //$NON-NLS-1$ 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 String PATTERN_URL = "http://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html#sum"; //$NON-NLS-1$ private static final Image LINE_IMAGE = Activator.getDefault().getImageFromPath("/icons/elcl16/line_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 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_BLACK = Display.getDefault().getSystemColor(SWT.COLOR_BLACK); private static final Color COLOR_LIGHT_GREEN = new Color(Display.getDefault(), 192, 255, 192); private static final Color COLOR_GREEN = Display.getDefault().getSystemColor(SWT.COLOR_GREEN); private static final Color COLOR_LIGHT_YELLOW = new Color(Display.getDefault(), 255, 255, 192); private static final Color COLOR_YELLOW = Display.getDefault().getSystemColor(SWT.COLOR_YELLOW); private static final Color COLOR_LIGHT_MAGENTA = new Color(Display.getDefault(), 255, 192, 255); private static final Color COLOR_MAGENTA = Display.getDefault().getSystemColor(SWT.COLOR_MAGENTA); 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 CustomTxtTraceDefinition definition; private String editCategoryName; private String editDefinitionName; private String defaultDescription; private Line selectedLine; private Composite container; private Text categoryText; private Text logtypeText; private Text timestampOutputFormatText; private Text timestampPreviewText; private ScrolledComposite lineScrolledComposite; private TreeViewer treeViewer; private Composite lineContainer; private StyledText inputText; private Font fixedFont; private UpdateListener updateListener; private Browser helpBrowser; // variables used recursively through line traversal private String timeStampFormat; private boolean timestampFound; /** * Constructor * * @param selection * The Selection object * @param definition * The trace definition */ protected CustomTxtParserInputWizardPage(ISelection selection, CustomTxtTraceDefinition definition) { super("CustomParserWizardPage"); //$NON-NLS-1$ if (definition == null) { setTitle(Messages.CustomTxtParserInputWizardPage_titleNew); defaultDescription = Messages.CustomTxtParserInputWizardPage_descriptionNew; } else { setTitle(Messages.CustomTxtParserInputWizardPage_titleEdit); defaultDescription = Messages.CustomTxtParserInputWizardPage_desccriptionEdit; } 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.CustomTxtParserInputWizardPage_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.CustomTxtParserInputWizardPage_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.CustomTxtParserInputWizardPage_default, borderWidth, borderWidth); } }); Button timeStampFormatHelpButton = new Button(headerComposite, SWT.PUSH); timeStampFormatHelpButton.setImage(HELP_IMAGE); timeStampFormatHelpButton.setToolTipText(Messages.CustomTxtParserInputWizardPage_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.CustomTxtParserInputWizardPage_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.CustomTxtParserInputWizardPage_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(Messages.CustomTxtParserInputWizardPage_noMatchingTimestamp); Composite buttonBar = new Composite(container, SWT.NONE); GridLayout buttonBarLayout = new GridLayout(5, false); buttonBarLayout.marginHeight = 0; buttonBarLayout.marginWidth = 0; buttonBar.setLayout(buttonBarLayout); Button removeButton = new Button(buttonBar, SWT.PUSH); removeButton.setImage(DELETE_IMAGE); removeButton.setToolTipText(Messages.CustomTxtParserInputWizardPage_removeLine); removeButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (treeViewer.getSelection().isEmpty() || selectedLine == null) { return; } removeLine(); InputLine inputLine = (InputLine) ((IStructuredSelection) treeViewer.getSelection()).getFirstElement(); if (inputLine.parentInput == null) { definition.inputs.remove(inputLine); } else { int index = inputLine.parentInput.childrenInputs.indexOf(inputLine); if (index > 0) { inputLine.parentInput.childrenInputs.get(index - 1).nextInput = inputLine.nextInput; } inputLine.parentInput.childrenInputs.remove(inputLine); } treeViewer.refresh(); validate(); updatePreviews(); } }); Button addNextButton = new Button(buttonBar, SWT.PUSH); addNextButton.setImage(ADD_NEXT_IMAGE); addNextButton.setToolTipText(Messages.CustomTxtParserInputWizardPage_addNextLine); addNextButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { InputLine inputLine = new InputLine(Cardinality.ZERO_OR_MORE, "", null); //$NON-NLS-1$ if (((List<?>) treeViewer.getInput()).isEmpty()) { definition.inputs.add(inputLine); } else if (treeViewer.getSelection().isEmpty()) { return; } else { InputLine previousInputLine = (InputLine) ((IStructuredSelection) treeViewer.getSelection()).getFirstElement(); if (previousInputLine.parentInput == null) { for (int i = 0; i < definition.inputs.size(); i++) { if (definition.inputs.get(i).equals(previousInputLine)) { definition.inputs.add(i + 1, inputLine); } } } else { previousInputLine.addNext(inputLine); } } treeViewer.refresh(); treeViewer.setSelection(new StructuredSelection(inputLine), true); } }); Button addChildButton = new Button(buttonBar, SWT.PUSH); addChildButton.setImage(ADD_CHILD_IMAGE); addChildButton.setToolTipText(Messages.CustomTxtParserInputWizardPage_addChildLine); addChildButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { InputLine inputLine = new InputLine(Cardinality.ZERO_OR_MORE, "", null); //$NON-NLS-1$ if (((List<?>) treeViewer.getInput()).isEmpty()) { definition.inputs.add(inputLine); } else if (treeViewer.getSelection().isEmpty()) { return; } else { InputLine parentInputLine = (InputLine) ((IStructuredSelection) treeViewer.getSelection()).getFirstElement(); parentInputLine.addChild(inputLine); } treeViewer.refresh(); treeViewer.setSelection(new StructuredSelection(inputLine), true); } }); Button moveUpButton = new Button(buttonBar, SWT.PUSH); moveUpButton.setImage(MOVE_UP_IMAGE); moveUpButton.setToolTipText(Messages.CustomTxtParserInputWizardPage_moveUp); moveUpButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (treeViewer.getSelection().isEmpty()) { return; } InputLine inputLine = (InputLine) ((IStructuredSelection) treeViewer.getSelection()).getFirstElement(); if (inputLine.parentInput == null) { for (int i = 1; i < definition.inputs.size(); i++) { if (definition.inputs.get(i).equals(inputLine)) { definition.inputs.add(i - 1, definition.inputs.remove(i)); break; } } } else { inputLine.moveUp(); } treeViewer.refresh(); validate(); updatePreviews(); } }); Button moveDownButton = new Button(buttonBar, SWT.PUSH); moveDownButton.setImage(MOVE_DOWN_IMAGE); moveDownButton.setToolTipText(Messages.CustomTxtParserInputWizardPage_moveDown); moveDownButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (treeViewer.getSelection().isEmpty()) { return; } InputLine inputLine = (InputLine) ((IStructuredSelection) treeViewer.getSelection()).getFirstElement(); if (inputLine.parentInput == null) { for (int i = 0; i < definition.inputs.size() - 1; i++) { if (definition.inputs.get(i).equals(inputLine)) { definition.inputs.add(i + 1, definition.inputs.remove(i)); break; } } } else { inputLine.moveDown(); } treeViewer.refresh(); validate(); updatePreviews(); } }); 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); GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); gd.heightHint = 200; gd.widthHint = 200; treeScrolledComposite.setLayoutData(gd); 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 InputLineTreeNodeContentProvider()); treeViewer.setLabelProvider(new InputLineTreeLabelProvider()); treeViewer.addSelectionChangedListener(new InputLineTreeSelectionChangedListener()); treeContainer.layout(); treeScrolledComposite.setMinSize(treeContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x, treeContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y); lineScrolledComposite = new ScrolledComposite(hSash, SWT.V_SCROLL); lineScrolledComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); lineContainer = new Composite(lineScrolledComposite, SWT.NONE); GridLayout linesLayout = new GridLayout(); linesLayout.marginHeight = 1; linesLayout.marginWidth = 0; lineContainer.setLayout(linesLayout); lineScrolledComposite.setContent(lineContainer); lineScrolledComposite.setExpandHorizontal(true); lineScrolledComposite.setExpandVertical(true); if (definition == null) { definition = new CustomTxtTraceDefinition(); definition.inputs.add(new InputLine(Cardinality.ZERO_OR_MORE, DEFAULT_REGEX, Arrays.asList(new InputData(Tag.MESSAGE, CustomTraceDefinition.ACTION_SET)))); } loadDefinition(definition); treeViewer.expandAll(); lineContainer.layout(); categoryText.addModifyListener(updateListener); logtypeText.addModifyListener(updateListener); timestampOutputFormatText.addModifyListener(updateListener); lineScrolledComposite.setMinSize(lineContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x, lineContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y - 1); hSash.setWeights(new int[] { 1, 2 }); Composite sashBottom = new Composite(vSash, SWT.NONE); GridLayout sashBottomLayout = new GridLayout(3, false); sashBottomLayout.marginHeight = 0; sashBottomLayout.marginWidth = 0; sashBottom.setLayout(sashBottomLayout); Label previewLabel = new Label(sashBottom, SWT.NULL); previewLabel.setText(Messages.CustomTxtParserInputWizardPage_previewInput); previewLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); Button highlightAllButton = new Button(sashBottom, SWT.PUSH); highlightAllButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false)); highlightAllButton.setText(Messages.CustomTxtParserInputWizardPage_highlightAll); highlightAllButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { updatePreviews(true); } }); Button legendButton = new Button(sashBottom, SWT.PUSH); legendButton.setImage(HELP_IMAGE); legendButton.setToolTipText(Messages.CustomTxtParserInputWizardPage_previewLegend); legendButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false)); legendButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { openLegend(); } }); 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); gd = new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1); gd.heightHint = inputText.computeSize(SWT.DEFAULT, inputText.getLineHeight() * 4).y; gd.widthHint = 800; inputText.setLayoutData(gd); inputText.setText(getSelectionText()); inputText.addModifyListener(updateListener); vSash.setWeights(new int[] { hSash.computeSize(SWT.DEFAULT, SWT.DEFAULT).y, sashBottom.computeSize(SWT.DEFAULT, SWT.DEFAULT).y }); setControl(container); validate(); updatePreviews(); } private static class InputLineTreeNodeContentProvider implements ITreeContentProvider { @Override public Object[] getElements(Object inputElement) { return ((List<?>) inputElement).toArray(); } @Override public Object[] getChildren(Object parentElement) { InputLine inputLine = (InputLine) parentElement; if (inputLine.childrenInputs == null) { return new InputLine[0]; } return inputLine.childrenInputs.toArray(); } @Override public boolean hasChildren(Object element) { InputLine inputLine = (InputLine) element; return (inputLine.childrenInputs != null && !inputLine.childrenInputs.isEmpty()); } @Override public void dispose() { } @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } @Override public Object getParent(Object element) { InputLine inputLine = (InputLine) element; return inputLine.parentInput; } } private class InputLineTreeLabelProvider extends ColumnLabelProvider { @Override public Image getImage(Object element) { return LINE_IMAGE; } @Override public String getText(Object element) { InputLine inputLine = (InputLine) element; if (inputLine.parentInput == null) { return "Root Line " + getName(inputLine) + " " + inputLine.cardinality.toString() + " : " + inputLine.getRegex(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } return "Line " + getName(inputLine) + " " + inputLine.cardinality.toString() + " : " + inputLine.getRegex(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } } private class InputLineTreeSelectionChangedListener implements ISelectionChangedListener { @Override public void selectionChanged(SelectionChangedEvent event) { if (selectedLine != null) { selectedLine.dispose(); } if (!(event.getSelection().isEmpty()) && event.getSelection() instanceof IStructuredSelection) { IStructuredSelection sel = (IStructuredSelection) event.getSelection(); InputLine inputLine = (InputLine) sel.getFirstElement(); selectedLine = new Line(lineContainer, getName(inputLine), inputLine); lineContainer.layout(); lineScrolledComposite.setMinSize(lineContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x, lineContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y - 1); container.layout(); validate(); updatePreviews(); } } } @Override public void dispose() { if (fixedFont != null) { fixedFont.dispose(); fixedFont = null; } super.dispose(); } private void loadDefinition(CustomTxtTraceDefinition 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.inputs); if (!def.inputs.isEmpty()) { InputLine inputLine = def.inputs.get(0); treeViewer.setSelection(new StructuredSelection(inputLine)); } } private String getName(InputLine inputLine) { if (inputLine.parentInput == null) { return Integer.toString(definition.inputs.indexOf(inputLine) + 1); } return getName(inputLine.parentInput) + "." + Integer.toString(inputLine.parentInput.childrenInputs.indexOf(inputLine) + 1); //$NON-NLS-1$ } /** * Get the global list of inputs. * * @return The list of inputs */ public List<Entry<Tag, String>> getInputs() { List<Entry<Tag, String>> inputs = new ArrayList<>(); for (InputLine inputLine : definition.inputs) { for (Entry<Tag, String> input : getInputs(inputLine)) { if (!inputs.contains(input)) { inputs.add(input); } } } return inputs; } /** * Get the list of inputs for the given input line, recursively. * * @param inputLine * The input line * @return The list of inputs */ private List<Entry<Tag, String>> getInputs(InputLine inputLine) { List<Entry<Tag, String>> inputs = new ArrayList<>(); if (inputLine.columns != null) { for (InputData inputData : inputLine.columns) { Entry<Tag, String> input = new SimpleEntry<>(inputData.tag, inputData.name); if (!inputs.contains(input)) { inputs.add(input); } } } if (inputLine.childrenInputs != null) { for (InputLine childInputLine : inputLine.childrenInputs) { for (Entry<Tag, String> input : getInputs(childInputLine)) { if (!inputs.contains(input)) { inputs.add(input); } } } } return inputs; } private void removeLine() { selectedLine.dispose(); selectedLine = null; lineContainer.layout(); lineScrolledComposite.setMinSize(lineContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x, lineContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y - 1); container.layout(); } private String getSelectionText() { if (this.selection instanceof IStructuredSelection) { Object sel = ((IStructuredSelection) this.selection).getFirstElement(); if (sel instanceof IFile) { IFile file = (IFile) sel; BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(file.getContents())); StringBuilder sb = new StringBuilder(); String line = null; while ((line = reader.readLine()) != null) { sb.append(line); sb.append('\n'); } return sb.toString(); } catch (CoreException e) { return ""; //$NON-NLS-1$ } catch (IOException e) { return ""; //$NON-NLS-1$ } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { } } } } } return ""; //$NON-NLS-1$ } private void updatePreviews() { updatePreviews(false); } private void updatePreviews(boolean updateAll) { if (inputText == null) { // early update during construction return; } inputText.setStyleRanges(new StyleRange[] {}); try (Scanner scanner = new Scanner(inputText.getText());) { scanner.useDelimiter("\n"); //$NON-NLS-1$ int rawPos = 0; // skip starting delimiters String skip = scanner.findWithinHorizon("\\A\n+", 0); //$NON-NLS-1$ if (skip != null) { rawPos += skip.length(); } timeStampFormat = null; if (selectedLine != null) { for (InputGroup input : selectedLine.inputs) { input.previewText.setText(Messages.CustomTxtParserInputWizardPage_noMathcingLine); } } Map<Object, String> data = new HashMap<>(); int rootLineMatches = 0; String firstEntryTimeStamp = null; String firstEntryTimeStampInputFormat = null; String line = null; boolean lineIsNull = true; // needed because of JDT bug with continue at label event: while (scanner.hasNext() || !lineIsNull) { if (rootLineMatches > 0 && !updateAll) { break; } if (line == null) { line = scanner.next(); lineIsNull = false; } int length = line.length(); String log = line.replaceAll("\r", ""); //$NON-NLS-1$ //$NON-NLS-2$ for (InputLine rootInputLine : definition.inputs) { Pattern pattern; try { pattern = rootInputLine.getPattern(); } catch (PatternSyntaxException e) { continue; } Matcher matcher = pattern.matcher(log); if (matcher.matches()) { rootLineMatches++; inputText.setStyleRange(new StyleRange(rawPos, length, COLOR_BLACK, COLOR_YELLOW, SWT.ITALIC)); data = new HashMap<>(); timeStampFormat = null; updatePreviewLine(rootInputLine, matcher, data, rawPos, rootLineMatches); if (rootLineMatches == 1) { firstEntryTimeStamp = data.get(Tag.TIMESTAMP); firstEntryTimeStampInputFormat = timeStampFormat; } HashMap<InputLine, Integer> countMap = new HashMap<>(); InputLine currentInput = null; if (rootInputLine.childrenInputs != null && !rootInputLine.childrenInputs.isEmpty()) { currentInput = rootInputLine.childrenInputs.get(0); countMap.put(currentInput, 0); } rawPos += length + 1; // +1 for \n while (scanner.hasNext()) { line = scanner.next(); length = line.length(); log = line.replaceAll("\r", ""); //$NON-NLS-1$ //$NON-NLS-2$ boolean processed = false; if (currentInput == null) { for (InputLine input : definition.inputs) { try { matcher = input.getPattern().matcher(log); } catch (PatternSyntaxException e) { continue; } if (matcher.matches()) { continue event; } } } else { if (checkNotNull(countMap.get(currentInput)) >= currentInput.getMinCount()) { List<InputLine> nextInputs = currentInput.getNextInputs(countMap); if (nextInputs.isEmpty() || nextInputs.get(nextInputs.size() - 1).getMinCount() == 0) { for (InputLine input : definition.inputs) { try { matcher = input.getPattern().matcher(log); } catch (PatternSyntaxException e) { continue; } if (matcher.matches()) { continue event; } } } for (InputLine input : nextInputs) { try { matcher = input.getPattern().matcher(log); } catch (PatternSyntaxException e) { continue; } if (matcher.matches()) { inputText.setStyleRange(new StyleRange(rawPos, length, COLOR_BLACK, COLOR_LIGHT_YELLOW, SWT.ITALIC)); currentInput = input; updatePreviewLine(currentInput, matcher, data, rawPos, rootLineMatches); if (countMap.get(currentInput) == null) { countMap.put(currentInput, 1); } else { countMap.put(currentInput, checkNotNull(countMap.get(currentInput)) + 1); } Iterator<InputLine> iter = countMap.keySet().iterator(); while (iter.hasNext()) { InputLine inputLine = iter.next(); if (inputLine.level > currentInput.level) { iter.remove(); } } if (currentInput.childrenInputs != null && !currentInput.childrenInputs.isEmpty()) { currentInput = currentInput.childrenInputs.get(0); countMap.put(currentInput, 0); } else { if (checkNotNull(countMap.get(currentInput)) >= currentInput.getMaxCount()) { if (!currentInput.getNextInputs(countMap).isEmpty()) { currentInput = currentInput.getNextInputs(countMap).get(0); if (countMap.get(currentInput) == null) { countMap.put(currentInput, 0); } iter = countMap.keySet().iterator(); while (iter.hasNext()) { InputLine inputLine = iter.next(); if (inputLine.level > currentInput.level) { iter.remove(); } } } else { currentInput = null; } } } processed = true; break; } } } if (!processed && currentInput != null) { matcher = null; try { matcher = currentInput.getPattern().matcher(log); } catch (PatternSyntaxException e) { } if (matcher != null && matcher.matches()) { inputText.setStyleRange(new StyleRange(rawPos, length, COLOR_BLACK, COLOR_LIGHT_YELLOW, SWT.ITALIC)); updatePreviewLine(currentInput, matcher, data, rawPos, rootLineMatches); countMap.put(currentInput, checkNotNull(countMap.get(currentInput)) + 1); if (currentInput.childrenInputs != null && !currentInput.childrenInputs.isEmpty()) { currentInput = currentInput.childrenInputs.get(0); countMap.put(currentInput, 0); } else { if (checkNotNull(countMap.get(currentInput)) >= currentInput.getMaxCount()) { if (!currentInput.getNextInputs(countMap).isEmpty()) { currentInput = currentInput.getNextInputs(countMap).get(0); if (countMap.get(currentInput) == null) { countMap.put(currentInput, 0); } Iterator<InputLine> iter = countMap.keySet().iterator(); while (iter.hasNext()) { InputLine inputLine = iter.next(); if (inputLine.level > currentInput.level) { iter.remove(); } } } else { currentInput = null; } } } } } } rawPos += length + 1; // +1 for \n } break; } } rawPos += length + 1; // +1 for \n line = null; lineIsNull = true; } if (rootLineMatches == 1) { firstEntryTimeStamp = data.get(Tag.TIMESTAMP); firstEntryTimeStampInputFormat = timeStampFormat; } if (firstEntryTimeStamp == null) { timestampPreviewText.setText(Messages.CustomTxtParserInputWizardPage_noTimestampGroup); if (selectedLine != null) { for (InputGroup group : selectedLine.inputs) { if (group.tagCombo.getText().equals(Tag.TIMESTAMP.toString())) { timestampPreviewText.setText(Messages.CustomTxtParserInputWizardPage_noMatchingTimestamp); break; } } } } else { try { TmfTimestampFormat timestampFormat = new TmfTimestampFormat(firstEntryTimeStampInputFormat); long timestamp = timestampFormat.parseValue(firstEntryTimeStamp); 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* [" + firstEntryTimeStamp + "] <> [" + firstEntryTimeStampInputFormat + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } catch (IllegalArgumentException e) { timestampPreviewText.setText("*parse exception* [Illegal Argument: " + e.getMessage() + "]"); //$NON-NLS-1$ //$NON-NLS-2$ } } } } private void updatePreviewLine(InputLine line, Matcher matcher, Map<Object, String> data, int rawPos, int rootLineMatches) { for (int i = 0; i < line.columns.size(); i++) { InputData input = line.columns.get(i); if (i < matcher.groupCount() && matcher.group(i + 1) != null) { if (line.parentInput == null) { inputText.setStyleRange(new StyleRange(rawPos + matcher.start(i + 1), matcher.end(i + 1) - matcher.start(i + 1), COLOR_BLACK, COLOR_GREEN, SWT.BOLD)); } else { inputText.setStyleRange(new StyleRange(rawPos + matcher.start(i + 1), matcher.end(i + 1) - matcher.start(i + 1), COLOR_BLACK, COLOR_LIGHT_GREEN, SWT.BOLD)); } String value = matcher.group(i + 1).trim(); if (selectedLine != null && selectedLine.inputLine.equals(line) && rootLineMatches == 1 && selectedLine.inputs.get(i).previewText.getText().equals(Messages.CustomTxtParserInputWizardPage_noMatchingLine)) { selectedLine.inputs.get(i).previewText.setText(value); } if (value.length() == 0) { continue; } Object key = (input.tag.equals(Tag.OTHER) ? input.name : input.tag); if (input.action == CustomTraceDefinition.ACTION_SET) { data.put(key, value); if (input.tag.equals(Tag.TIMESTAMP)) { timeStampFormat = input.format; } } else if (input.action == CustomTraceDefinition.ACTION_APPEND) { String s = data.get(key); if (s != null) { data.put(key, s + value); } else { data.put(key, value); } if (input.tag.equals(Tag.TIMESTAMP)) { if (timeStampFormat != null) { timeStampFormat += input.format; } else { timeStampFormat = input.format; } } } else if (input.action == CustomTraceDefinition.ACTION_APPEND_WITH_SEPARATOR) { String s = data.get(key); if (s != null) { data.put(key, s + CustomTraceDefinition.SEPARATOR + value); } else { data.put(key, value); } if (input.tag.equals(Tag.TIMESTAMP)) { if (timeStampFormat != null) { timeStampFormat += CustomTraceDefinition.SEPARATOR + input.format; } else { timeStampFormat = input.format; } } } } else { if (selectedLine != null && selectedLine.inputLine.equals(line) && rootLineMatches == 1) { if (selectedLine.inputs.get(i).previewText.getText().equals(Messages.CustomTxtParserInputWizardPage_noMatchingLine)) { selectedLine.inputs.get(i).previewText.setText(Messages.CustomTxtParserInputWizardPage_noMatchingGroup); } } } } // highlight the matching groups that have no corresponponding input for (int i = line.columns.size(); i < matcher.groupCount(); i++) { if (matcher.group(i + 1) != null) { if (line.parentInput == null) { inputText.setStyleRange(new StyleRange(rawPos + matcher.start(i + 1), matcher.end(i + 1) - matcher.start(i + 1), COLOR_BLACK, COLOR_MAGENTA)); } else { inputText.setStyleRange(new StyleRange(rawPos + matcher.start(i + 1), matcher.end(i + 1) - matcher.start(i + 1), COLOR_BLACK, COLOR_LIGHT_MAGENTA)); } } } } 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(new TitleListener() { @Override public void changed(TitleEvent 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 void openLegend() { final String cg = Messages.CustomTxtParserInputWizardPage_capturedGroup; final String ucg = Messages.CustomTxtParserInputWizardPage_unidentifiedCaptureGroup; final String ut = Messages.CustomTxtParserInputWizardPage_uncapturedText; int line1start = 0; String line1 = Messages.CustomTxtParserInputWizardPage_nonMatchingLine; int line2start = line1start + line1.length(); String line2 = Messages.CustomTxtParserInputWizardPage_matchingRootLine + ' ' + cg + ' ' + ucg + ' ' + ut + " \n"; //$NON-NLS-1$ int line3start = line2start + line2.length(); String line3 = Messages.CustomTxtParserInputWizardPage_matchingOtherLine + ' ' + cg + ' ' + ucg + ' ' + ut + " \n"; //$NON-NLS-1$ int line4start = line3start + line3.length(); String line4 = Messages.CustomTxtParserInputWizardPage_matchingOtherLine + ' ' + cg + ' ' + ucg + ' ' + ut + " \n"; //$NON-NLS-1$ int line5start = line4start + line4.length(); String line5 = Messages.CustomTxtParserInputWizardPage_nonMatchingLine; int line6start = line5start + line5.length(); String line6 = Messages.CustomTxtParserInputWizardPage_matchingRootLine + cg + ' ' + ucg + ' ' + ut + " \n"; //$NON-NLS-1$ final Shell legendShell = new Shell(getShell(), SWT.DIALOG_TRIM); legendShell.setLayout(new FillLayout()); StyledText legendText = new StyledText(legendShell, SWT.MULTI); legendText.setFont(fixedFont); legendText.setText(line1 + line2 + line3 + line4 + line5 + line6); legendText.setStyleRange(new StyleRange(line2start, line2.length(), COLOR_BLACK, COLOR_YELLOW, SWT.ITALIC)); legendText.setStyleRange(new StyleRange(line3start, line3.length(), COLOR_BLACK, COLOR_LIGHT_YELLOW, SWT.ITALIC)); legendText.setStyleRange(new StyleRange(line4start, line4.length(), COLOR_BLACK, COLOR_LIGHT_YELLOW, SWT.ITALIC)); legendText.setStyleRange(new StyleRange(line6start, line6.length(), COLOR_BLACK, COLOR_YELLOW, SWT.ITALIC)); legendText.setStyleRange(new StyleRange(line2start + line2.indexOf(cg), cg.length(), COLOR_BLACK, COLOR_GREEN, SWT.BOLD)); legendText.setStyleRange(new StyleRange(line2start + line2.indexOf(ucg), ucg.length(), COLOR_BLACK, COLOR_MAGENTA)); legendText.setStyleRange(new StyleRange(line3start + line3.indexOf(cg), cg.length(), COLOR_BLACK, COLOR_LIGHT_GREEN, SWT.BOLD)); legendText.setStyleRange(new StyleRange(line3start + line3.indexOf(ucg), ucg.length(), COLOR_BLACK, COLOR_LIGHT_MAGENTA)); legendText.setStyleRange(new StyleRange(line4start + line4.indexOf(cg), cg.length(), COLOR_BLACK, COLOR_LIGHT_GREEN, SWT.BOLD)); legendText.setStyleRange(new StyleRange(line4start + line4.indexOf(ucg), ucg.length(), COLOR_BLACK, COLOR_LIGHT_MAGENTA)); legendText.setStyleRange(new StyleRange(line6start + line6.indexOf(cg), cg.length(), COLOR_BLACK, COLOR_GREEN, SWT.BOLD)); legendText.setStyleRange(new StyleRange(line6start + line6.indexOf(ucg), ucg.length(), COLOR_BLACK, COLOR_MAGENTA)); legendShell.setText(Messages.CustomTxtParserInputWizardPage_previewLegend); legendShell.pack(); legendShell.open(); } 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 Line { private static final String INFINITY_STRING = "\u221E"; //$NON-NLS-1$ private InputLine inputLine; private Group group; private Composite labelComposite; private Text regexText; private Composite cardinalityContainer; private Combo cardinalityCombo; private Label cardinalityMinLabel; private Text cardinalityMinText; private Label cardinalityMaxLabel; private Text cardinalityMaxText; private Button infiniteButton; private Button eventTypeButton; private Text eventTypeText; private List<InputGroup> inputs = new ArrayList<>(); private Button addGroupButton; private Label addGroupLabel; public Line(Composite parent, String name, InputLine inputLine) { this.inputLine = inputLine; group = new Group(parent, SWT.NONE); group.setText(name); group.setLayout(new GridLayout(2, false)); group.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); labelComposite = new Composite(group, SWT.FILL); GridLayout labelLayout = new GridLayout(1, false); labelLayout.marginWidth = 0; labelLayout.marginHeight = 0; labelComposite.setLayout(labelLayout); labelComposite.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false)); Label label = new Label(labelComposite, SWT.NULL); label.setText(Messages.CustomTxtParserInputWizardPage_regularExpression); Composite regexContainer = new Composite(group, SWT.NONE); GridLayout regexLayout = new GridLayout(2, false); regexLayout.marginHeight = 0; regexLayout.marginWidth = 0; regexContainer.setLayout(regexLayout); regexContainer.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); regexText = new Text(regexContainer, SWT.BORDER | SWT.SINGLE); GridData gd = new GridData(SWT.FILL, SWT.CENTER, true, false); gd.widthHint = 0; regexText.setLayoutData(gd); regexText.setText(inputLine.getRegex()); regexText.addModifyListener(updateListener); Button regexHelpButton = new Button(regexContainer, SWT.PUSH); regexHelpButton.setImage(HELP_IMAGE); regexHelpButton.setToolTipText(Messages.CustomTxtParserInputWizardPage_regularExpressionHelp); regexHelpButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { openHelpShell(PATTERN_URL); } }); label = new Label(group, SWT.NONE); label.setText(Messages.CustomTxtParserInputWizardPage_cardinality); label.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false)); cardinalityContainer = new Composite(group, SWT.NONE); GridLayout cardinalityLayout = new GridLayout(6, false); cardinalityLayout.marginHeight = 0; cardinalityLayout.marginWidth = 0; cardinalityContainer.setLayout(cardinalityLayout); cardinalityContainer.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); cardinalityCombo = new Combo(cardinalityContainer, SWT.DROP_DOWN | SWT.READ_ONLY); cardinalityCombo.setItems(new String[] { Cardinality.ZERO_OR_MORE.toString(), Cardinality.ONE_OR_MORE.toString(), Cardinality.ZERO_OR_ONE.toString(), Cardinality.ONE.toString(), "(?,?)" }); //$NON-NLS-1$ cardinalityCombo.addSelectionListener(new SelectionListener() { @Override public void widgetDefaultSelected(SelectionEvent e) { } @Override public void widgetSelected(SelectionEvent e) { switch (cardinalityCombo.getSelectionIndex()) { case 4: // (?,?) cardinalityMinLabel.setVisible(true); cardinalityMinText.setVisible(true); cardinalityMaxLabel.setVisible(true); cardinalityMaxText.setVisible(true); infiniteButton.setVisible(true); break; default: cardinalityMinLabel.setVisible(false); cardinalityMinText.setVisible(false); cardinalityMaxLabel.setVisible(false); cardinalityMaxText.setVisible(false); infiniteButton.setVisible(false); break; } cardinalityContainer.layout(); validate(); updatePreviews(); } }); cardinalityMinLabel = new Label(cardinalityContainer, SWT.NONE); cardinalityMinLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false)); cardinalityMinLabel.setText(Messages.CustomTxtParserInputWizardPage_min); cardinalityMinLabel.setVisible(false); cardinalityMinText = new Text(cardinalityContainer, SWT.BORDER | SWT.SINGLE); gd = new GridData(SWT.CENTER, SWT.CENTER, false, false); gd.widthHint = 20; cardinalityMinText.setLayoutData(gd); cardinalityMinText.setVisible(false); cardinalityMaxLabel = new Label(cardinalityContainer, SWT.NONE); cardinalityMaxLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false)); cardinalityMaxLabel.setText(Messages.CustomTxtParserInputWizardPage_max); cardinalityMaxLabel.setVisible(false); cardinalityMaxText = new Text(cardinalityContainer, SWT.BORDER | SWT.SINGLE); gd = new GridData(SWT.CENTER, SWT.CENTER, false, false); gd.widthHint = 20; cardinalityMaxText.setLayoutData(gd); cardinalityMaxText.setVisible(false); infiniteButton = new Button(cardinalityContainer, SWT.PUSH); infiniteButton.setText(INFINITY_STRING); infiniteButton.setVisible(false); infiniteButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { cardinalityMaxText.setText(INFINITY_STRING); } }); if (inputLine.cardinality.equals(Cardinality.ZERO_OR_MORE)) { cardinalityCombo.select(0); } else if (inputLine.cardinality.equals(Cardinality.ONE_OR_MORE)) { cardinalityCombo.select(1); } else if (inputLine.cardinality.equals(Cardinality.ZERO_OR_ONE)) { cardinalityCombo.select(2); } else if (inputLine.cardinality.equals(Cardinality.ONE)) { cardinalityCombo.select(3); } else { cardinalityCombo.select(4); cardinalityMinLabel.setVisible(true); cardinalityMinText.setVisible(true); if (inputLine.getMinCount() >= 0) { cardinalityMinText.setText(Integer.toString(inputLine.getMinCount())); } cardinalityMaxLabel.setVisible(true); cardinalityMaxText.setVisible(true); if (inputLine.getMaxCount() == Cardinality.INF) { cardinalityMaxText.setText(INFINITY_STRING); } else if (inputLine.getMaxCount() >= 0) { cardinalityMaxText.setText(Integer.toString(inputLine.getMaxCount())); } infiniteButton.setVisible(true); } VerifyListener digitsListener = new VerifyListener() { @Override public void verifyText(VerifyEvent e) { if (e.text.equals(INFINITY_STRING)) { e.doit = e.widget == cardinalityMaxText && e.start == 0 && e.end == ((Text) e.widget).getText().length(); } else { if (((Text) e.widget).getText().equals(INFINITY_STRING)) { e.doit = e.start == 0 && e.end == ((Text) e.widget).getText().length(); } for (int i = 0; i < e.text.length(); i++) { if (!Character.isDigit(e.text.charAt(i))) { e.doit = false; break; } } } } }; cardinalityMinText.addModifyListener(updateListener); cardinalityMaxText.addModifyListener(updateListener); cardinalityMinText.addVerifyListener(digitsListener); cardinalityMaxText.addVerifyListener(digitsListener); 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 (inputLine.eventType != null) { eventTypeText.setText(inputLine.eventType); eventTypeButton.setSelection(true); } else { eventTypeText.setEnabled(false); eventTypeButton.setSelection(false); } eventTypeText.addModifyListener(updateListener); if (inputLine.columns != null) { for (InputData inputData : inputLine.columns) { InputGroup inputGroup = new InputGroup(group, this, inputs.size() + 1); if (inputData.tag.equals(Tag.TIMESTAMP)) { inputGroup.tagCombo.select(0); inputGroup.tagText.setText(inputData.format); inputGroup.tagLabel.setText(Messages.CustomTxtParserInputWizardPage_format); inputGroup.tagLabel.setVisible(true); inputGroup.tagText.setVisible(true); inputGroup.tagText.addModifyListener(updateListener); inputGroup.actionCombo.setVisible(true); } else if (inputData.tag.equals(Tag.EVENT_TYPE)) { inputGroup.tagCombo.select(1); inputGroup.actionCombo.setVisible(true); } else if (inputData.tag.equals(Tag.MESSAGE)) { inputGroup.tagCombo.select(2); inputGroup.actionCombo.setVisible(true); } else if (inputData.tag.equals(Tag.EXTRA_FIELD_NAME)) { inputGroup.tagCombo.select(3); inputGroup.actionCombo.setVisible(false); } else if (inputData.tag.equals(Tag.EXTRA_FIELD_VALUE)) { inputGroup.tagCombo.select(4); inputGroup.actionCombo.setVisible(true); } else { inputGroup.tagCombo.select(5); inputGroup.tagText.setText(inputData.name); inputGroup.tagLabel.setText(Messages.CustomTxtParserInputWizardPage_name); inputGroup.tagLabel.setVisible(true); inputGroup.tagText.setVisible(true); inputGroup.tagText.addModifyListener(updateListener); inputGroup.actionCombo.setVisible(true); } inputGroup.actionCombo.select(inputData.action); inputs.add(inputGroup); } } createAddGroupButton(); } private void createAddGroupButton() { addGroupButton = new Button(group, SWT.PUSH); addGroupButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false)); addGroupButton.setImage(ADD_IMAGE); addGroupButton.setToolTipText(Messages.CustomTxtParserInputWizardPage_addGroup); addGroupButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { removeAddGroupButton(); inputs.add(new InputGroup(group, Line.this, inputs.size() + 1)); createAddGroupButton(); lineContainer.layout(); lineScrolledComposite.setMinSize(lineContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x, lineContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y - 1); group.getParent().layout(); validate(); updatePreviews(); } }); addGroupLabel = new Label(group, SWT.NULL); addGroupLabel.setText(Messages.CustomTxtParserInputWizardPage_newGroup); } private void removeAddGroupButton() { addGroupButton.dispose(); addGroupLabel.dispose(); } private void removeInput(int inputNumber) { int nb = inputNumber; if (--nb < inputs.size()) { inputs.remove(nb).dispose(); for (int i = nb; i < inputs.size(); i++) { inputs.get(i).setInputNumber(i + 1); } lineContainer.layout(); lineScrolledComposite.setMinSize(lineContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x, lineContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y - 1); group.getParent().layout(); } } private void dispose() { group.dispose(); } private void extractInputs() { inputLine.setRegex(selectedLine.regexText.getText()); inputLine.eventType = selectedLine.eventTypeButton.getSelection() ? selectedLine.eventTypeText.getText().trim() : null; switch (cardinalityCombo.getSelectionIndex()) { case 0: inputLine.cardinality = Cardinality.ZERO_OR_MORE; break; case 1: inputLine.cardinality = Cardinality.ONE_OR_MORE; break; case 2: inputLine.cardinality = Cardinality.ZERO_OR_ONE; break; case 3: inputLine.cardinality = Cardinality.ONE; break; case 4: // (?,?) int min, max; try { min = Integer.parseInt(cardinalityMinText.getText()); } catch (NumberFormatException e) { min = -1; } try { if (cardinalityMaxText.getText().equals(INFINITY_STRING)) { max = Cardinality.INF; } else { max = Integer.parseInt(cardinalityMaxText.getText()); } } catch (NumberFormatException e) { max = -1; } inputLine.cardinality = new Cardinality(min, max); break; default: inputLine.cardinality = Cardinality.ZERO_OR_MORE; break; } inputLine.columns = new ArrayList<>(inputs.size()); for (int i = 0; i < inputs.size(); i++) { InputGroup grp = inputs.get(i); InputData inputData = new InputData(); inputData.tag = Tag.fromLabel(grp.tagCombo.getText()); if (inputData.tag.equals(Tag.OTHER)) { inputData.name = grp.tagText.getText().trim(); } else { inputData.name = inputData.tag.toString(); if (inputData.tag.equals(Tag.TIMESTAMP)) { inputData.format = grp.tagText.getText().trim(); } } inputData.action = grp.actionCombo.getSelectionIndex(); inputLine.columns.add(inputData); } } } private class InputGroup { private Line line; private int inputNumber; // children of parent (must be disposed) private Composite labelComposite; private Composite tagComposite; private Label previewLabel; private Text previewText; // children of labelComposite private Label inputLabel; // children of tagComposite private Combo tagCombo; private Label tagLabel; private Text tagText; private Combo actionCombo; public InputGroup(Composite parent, Line line, int inputNumber) { this.line = line; this.inputNumber = inputNumber; 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.CustomTxtParserInputWizardPage_removeGroup); deleteButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { InputGroup.this.line.removeInput(InputGroup.this.inputNumber); validate(); updatePreviews(); } }); inputLabel = new Label(labelComposite, SWT.NULL); inputLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false)); inputLabel.setText(NLS.bind(Messages.CustomTxtParserInputWizardPage_group, inputNumber)); 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(2); tagCombo.addSelectionListener(new SelectionListener() { @Override public void widgetDefaultSelected(SelectionEvent e) { } @Override public void widgetSelected(SelectionEvent e) { tagText.removeModifyListener(updateListener); switch (tagCombo.getSelectionIndex()) { case 0: // Time Stamp tagLabel.setText(Messages.CustomTxtParserInputWizardPage_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 name tagLabel.setVisible(false); tagText.setVisible(false); actionCombo.setVisible(false); break; case 4: // Field type tagLabel.setVisible(false); tagText.setVisible(false); actionCombo.setVisible(true); break; case 5: // Other tagLabel.setText(Messages.CustomTxtParserInputWizardPage_name); tagLabel.setVisible(true); 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)); tagLabel.setVisible(false); tagText = new Text(tagComposite, SWT.BORDER | SWT.SINGLE); GridData gd = new GridData(SWT.FILL, SWT.CENTER, true, false); gd.widthHint = 0; tagText.setLayoutData(gd); tagText.setVisible(false); actionCombo = new Combo(tagComposite, SWT.DROP_DOWN | SWT.READ_ONLY); actionCombo.setItems(new String[] { Messages.CustomTxtParserInputWizardPage_set, Messages.CustomTxtParserInputWizardPage_append, Messages.CustomTxtParserInputWizardPage_appendWith }); actionCombo.select(0); actionCombo.addSelectionListener(updateListener); previewLabel = new Label(parent, SWT.NULL); previewLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false)); previewLabel.setText(Messages.CustomTxtParserInputWizardPage_preview); previewText = new Text(parent, 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.CustomTxtParserInputWizardPage_noMatch); previewText.setBackground(COLOR_WIDGET_BACKGROUND); } private void dispose() { labelComposite.dispose(); tagComposite.dispose(); previewLabel.dispose(); previewText.dispose(); } private void setInputNumber(int inputNumber) { this.inputNumber = inputNumber; inputLabel.setText(NLS.bind(Messages.CustomTxtParserInputWizardPage_group, inputNumber)); labelComposite.layout(); } } private void validate() { definition.categoryName = categoryText.getText().trim(); definition.definitionName = logtypeText.getText().trim(); definition.timeStampOutputFormat = timestampOutputFormatText.getText().trim(); if (selectedLine != null) { selectedLine.extractInputs(); treeViewer.refresh(); } StringBuffer errors = new StringBuffer(); if (definition.categoryName.length() == 0) { errors.append("Enter a category for the new trace type. "); //$NON-NLS-1$ categoryText.setBackground(COLOR_LIGHT_RED); } else if (definition.definitionName.length() == 0) { errors.append("Enter a name for the new trace type. "); //$NON-NLS-1$ logtypeText.setBackground(COLOR_LIGHT_RED); } else { categoryText.setBackground(COLOR_TEXT_BACKGROUND); logtypeText.setBackground(COLOR_TEXT_BACKGROUND); if (definition.categoryName.indexOf(':') != -1) { errors.append("Invalid character ':' in category. "); //$NON-NLS-1$ categoryText.setBackground(COLOR_LIGHT_RED); } if (definition.definitionName.indexOf(':') != -1) { errors.append("Invalid character ':' in trace type. "); //$NON-NLS-1$ 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.append("The trace type name already exists. "); //$NON-NLS-1$ logtypeText.setBackground(COLOR_LIGHT_RED); break; } } } timestampFound = false; for (int i = 0; i < definition.inputs.size(); i++) { InputLine inputLine = definition.inputs.get(i); String name = Integer.toString(i + 1); errors.append(validateLine(inputLine, name)); } if (timestampFound && !definition.timeStampOutputFormat.isEmpty()) { try { new TmfTimestampFormat(definition.timeStampOutputFormat); timestampOutputFormatText.setBackground(COLOR_TEXT_BACKGROUND); } catch (IllegalArgumentException e) { errors.append("Enter a valid output format for the Time Stamp field [" + e.getMessage() + "]."); //$NON-NLS-1$ //$NON-NLS-2$ timestampOutputFormatText.setBackground(COLOR_LIGHT_RED); } } else { timestampOutputFormatText.setBackground(COLOR_TEXT_BACKGROUND); } if (errors.length() == 0) { setDescription(defaultDescription); setPageComplete(true); } else { setDescription(errors.toString()); setPageComplete(false); } } /** * Validate an input line. * * @param inputLine * The line to clean up * @param name * The name of the line * @return The cleaned up line */ public StringBuffer validateLine(InputLine inputLine, String name) { StringBuffer errors = new StringBuffer(); Line line = null; if (selectedLine != null && selectedLine.inputLine.equals(inputLine)) { line = selectedLine; } try { Pattern.compile(inputLine.getRegex()); if (line != null) { line.regexText.setBackground(COLOR_TEXT_BACKGROUND); } } catch (PatternSyntaxException e) { errors.append("Enter a valid regular expression (Line " + name + "). "); //$NON-NLS-1$ //$NON-NLS-2$ if (line != null) { line.regexText.setBackground(COLOR_LIGHT_RED); } } if (inputLine.getMinCount() == -1) { errors.append("Enter a minimum value for cardinality (Line " + name + "). "); //$NON-NLS-1$ //$NON-NLS-2$ if (line != null) { line.cardinalityMinText.setBackground(COLOR_LIGHT_RED); } } else { if (line != null) { line.cardinalityMinText.setBackground(COLOR_TEXT_BACKGROUND); } } if (inputLine.getMaxCount() == -1) { errors.append("Enter a maximum value for cardinality (Line " + name + "). "); //$NON-NLS-1$ //$NON-NLS-2$ if (line != null) { line.cardinalityMaxText.setBackground(COLOR_LIGHT_RED); } } else if (inputLine.getMinCount() > inputLine.getMaxCount()) { errors.append("Enter correct (min <= max) values for cardinality (Line " + name + "). "); //$NON-NLS-1$ //$NON-NLS-2$ if (line != null) { line.cardinalityMinText.setBackground(COLOR_LIGHT_RED); } if (line != null) { line.cardinalityMaxText.setBackground(COLOR_LIGHT_RED); } } else { if (line != null) { line.cardinalityMaxText.setBackground(COLOR_TEXT_BACKGROUND); } } if (inputLine.eventType != null && inputLine.eventType.trim().isEmpty()) { errors.append("Enter the event type (Line " + name + "). "); //$NON-NLS-1$ //$NON-NLS-2$ if (line != null) { line.eventTypeText.setBackground(COLOR_LIGHT_RED); } } else { if (line != null) { line.eventTypeText.setBackground(COLOR_TEXT_BACKGROUND); } } for (int i = 0; inputLine.columns != null && i < inputLine.columns.size(); i++) { InputData inputData = inputLine.columns.get(i); InputGroup group = null; if (line != null) { group = line.inputs.get(i); } if (inputData.tag.equals(Tag.TIMESTAMP)) { timestampFound = true; if (inputData.format.length() == 0) { errors.append("Enter the input format for the Time Stamp (Line " + name + " Group " + (i + 1) + "). "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ if (group != null) { group.tagText.setBackground(COLOR_LIGHT_RED); } } else { try { new TmfTimestampFormat(inputData.format); if (group != null) { group.tagText.setBackground(COLOR_TEXT_BACKGROUND); } } catch (IllegalArgumentException e) { errors.append("Enter a valid input format for the Time Stamp (Line " + name + " Group " + (i + 1) + ") [" + e.getMessage() + "]. "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ if (group != null) { group.tagText.setBackground(COLOR_LIGHT_RED); } } } } else if (inputData.tag.equals(Tag.OTHER)) { if (inputData.name.isEmpty()) { errors.append("Enter a name for the data group (Line " + name + " Group " + (i + 1) + "). "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ if (group != null) { group.tagText.setBackground(COLOR_LIGHT_RED); } } else if (Tag.fromLabel(inputData.name) != null) { errors.append("Cannot use reserved name for the data group (Line " + name + " Group " + (i + 1) + "). "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ if (group != null) { group.tagText.setBackground(COLOR_LIGHT_RED); } } else { if (group != null) { group.tagText.setBackground(COLOR_TEXT_BACKGROUND); } } } else { if (group != null) { group.tagText.setBackground(COLOR_TEXT_BACKGROUND); } } } for (int i = 0; inputLine.childrenInputs != null && i < inputLine.childrenInputs.size(); i++) { errors.append(validateLine(inputLine.childrenInputs.get(i), name + "." + (i + 1))); //$NON-NLS-1$ } return errors; } /** * Get the trace definition. * * @return The trace definition */ public CustomTxtTraceDefinition getDefinition() { return definition; } /** * Get the raw text of the input. * * @return The raw input text */ public char[] getInputText() { return inputText.getText().toCharArray(); } }