2010-07-12 Francois Chouinard <fchouinar@gmail.com> Contributions for Bug319429...
authorFrancois Chouinard <fchouinard@gmail.com>
Mon, 12 Jul 2010 19:47:04 +0000 (19:47 +0000)
committerFrancois Chouinard <fchouinard@gmail.com>
Mon, 12 Jul 2010 19:47:04 +0000 (19:47 +0000)
* icons/add_button.gif: New file.
* icons/addchild_button.gif: New file.
* icons/addmany_button.gif: New file.
* icons/addnext_button.gif: New file.
* icons/customparser_wizard.gif: New file.
* icons/delete_button.gif: New file.
* icons/down_button.gif: New file.
* icons/element_icon.gif: New file.
* icons/help_button.gif: New file.
* icons/line_icon.gif: New file.
* icons/movedown_button.gif: New file.
* icons/moveup_button.gif: New file.
* icons/up_button.gif: New file.
* src/org/eclipse/linuxtools/tmf/ui/commands/ManageCustomParsersCommandHandler.java: New file.
* src/org/eclipse/linuxtools/tmf/ui/dialogs/ManageCustomParsersDialog.java: New file.
* src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomEvent.java: New file.
* src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomEventsTable.java: New file.
* src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomParserProvider.java: New file.
* src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomTraceDefinition.java: New file.
* src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomTxtEvent.java: New file.
* src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomTxtTrace.java: New file.
* src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomTxtTraceContext.java: New file.
* src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomTxtTraceDefinition.java: New file.
* src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomXmlEvent.java: New file.
* src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomXmlTrace.java: New file.
* src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomXmlTraceContext.java: New file.
* src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomXmlTraceDefinition.java: New file.
* src/org/eclipse/linuxtools/tmf/ui/wizards/CustomTxtParserInputWizardPage.java: New file.
* src/org/eclipse/linuxtools/tmf/ui/wizards/CustomTxtParserOutputWizardPage.java: New file.
* src/org/eclipse/linuxtools/tmf/ui/wizards/CustomTxtParserWizard.java: New file.
* src/org/eclipse/linuxtools/tmf/ui/wizards/CustomXmlParserInputWizardPage.java: New file.
* src/org/eclipse/linuxtools/tmf/ui/wizards/CustomXmlParserOutputWizardPage.java: New file.
* src/org/eclipse/linuxtools/tmf/ui/wizards/CustomXmlParserWizard.java: New file.

34 files changed:
org.eclipse.linuxtools.tmf.ui/ChangeLog
org.eclipse.linuxtools.tmf.ui/icons/add_button.gif [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/icons/addchild_button.gif [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/icons/addmany_button.gif [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/icons/addnext_button.gif [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/icons/customparser_wizard.gif [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/icons/delete_button.gif [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/icons/down_button.gif [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/icons/element_icon.gif [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/icons/help_button.gif [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/icons/line_icon.gif [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/icons/movedown_button.gif [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/icons/moveup_button.gif [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/icons/up_button.gif [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/commands/ManageCustomParsersCommandHandler.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/dialogs/ManageCustomParsersDialog.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomEvent.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomEventsTable.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomParserProvider.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomTraceDefinition.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomTxtEvent.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomTxtTrace.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomTxtTraceContext.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomTxtTraceDefinition.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomXmlEvent.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomXmlTrace.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomXmlTraceContext.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomXmlTraceDefinition.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/wizards/CustomTxtParserInputWizardPage.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/wizards/CustomTxtParserOutputWizardPage.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/wizards/CustomTxtParserWizard.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/wizards/CustomXmlParserInputWizardPage.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/wizards/CustomXmlParserOutputWizardPage.java [new file with mode: 0644]
org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/wizards/CustomXmlParserWizard.java [new file with mode: 0644]

index ad147d0f0691ef7d6ee5720880ee4829fbcdc74e..6fe14fd587f2021e0af88302a09fa2b22c05cf1b 100644 (file)
@@ -1,5 +1,39 @@
 2010-07-12  Francois Chouinard  <fchouinar@gmail.com>
 
+       * icons/add_button.gif: New file.
+       * icons/addchild_button.gif: New file.
+       * icons/addmany_button.gif: New file.
+       * icons/addnext_button.gif: New file.
+       * icons/customparser_wizard.gif: New file.
+       * icons/delete_button.gif: New file.
+       * icons/down_button.gif: New file.
+       * icons/element_icon.gif: New file.
+       * icons/help_button.gif: New file.
+       * icons/line_icon.gif: New file.
+       * icons/movedown_button.gif: New file.
+       * icons/moveup_button.gif: New file.
+       * icons/up_button.gif: New file.
+       * src/org/eclipse/linuxtools/tmf/ui/commands/ManageCustomParsersCommandHandler.java: New file.
+       * src/org/eclipse/linuxtools/tmf/ui/dialogs/ManageCustomParsersDialog.java: New file.
+       * src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomEvent.java: New file.
+       * src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomEventsTable.java: New file.
+       * src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomParserProvider.java: New file.
+       * src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomTraceDefinition.java: New file.
+       * src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomTxtEvent.java: New file.
+       * src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomTxtTrace.java: New file.
+       * src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomTxtTraceContext.java: New file.
+       * src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomTxtTraceDefinition.java: New file.
+       * src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomXmlEvent.java: New file.
+       * src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomXmlTrace.java: New file.
+       * src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomXmlTraceContext.java: New file.
+       * src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomXmlTraceDefinition.java: New file.
+       * src/org/eclipse/linuxtools/tmf/ui/wizards/CustomTxtParserInputWizardPage.java: New file.
+       * src/org/eclipse/linuxtools/tmf/ui/wizards/CustomTxtParserOutputWizardPage.java: New file.
+       * src/org/eclipse/linuxtools/tmf/ui/wizards/CustomTxtParserWizard.java: New file.
+       * src/org/eclipse/linuxtools/tmf/ui/wizards/CustomXmlParserInputWizardPage.java: New file.
+       * src/org/eclipse/linuxtools/tmf/ui/wizards/CustomXmlParserOutputWizardPage.java: New file.
+       * src/org/eclipse/linuxtools/tmf/ui/wizards/CustomXmlParserWizard.java: New file.
+
        * src/org/eclipse/linuxtools/tmf/ui/TmfUiPlugin.java: 
                - Initialized ParserProviderManager
                - Added getImageFromPath() 
diff --git a/org.eclipse.linuxtools.tmf.ui/icons/add_button.gif b/org.eclipse.linuxtools.tmf.ui/icons/add_button.gif
new file mode 100644 (file)
index 0000000..ae9543c
Binary files /dev/null and b/org.eclipse.linuxtools.tmf.ui/icons/add_button.gif differ
diff --git a/org.eclipse.linuxtools.tmf.ui/icons/addchild_button.gif b/org.eclipse.linuxtools.tmf.ui/icons/addchild_button.gif
new file mode 100644 (file)
index 0000000..4219ea1
Binary files /dev/null and b/org.eclipse.linuxtools.tmf.ui/icons/addchild_button.gif differ
diff --git a/org.eclipse.linuxtools.tmf.ui/icons/addmany_button.gif b/org.eclipse.linuxtools.tmf.ui/icons/addmany_button.gif
new file mode 100644 (file)
index 0000000..576eb4f
Binary files /dev/null and b/org.eclipse.linuxtools.tmf.ui/icons/addmany_button.gif differ
diff --git a/org.eclipse.linuxtools.tmf.ui/icons/addnext_button.gif b/org.eclipse.linuxtools.tmf.ui/icons/addnext_button.gif
new file mode 100644 (file)
index 0000000..fb7c7f0
Binary files /dev/null and b/org.eclipse.linuxtools.tmf.ui/icons/addnext_button.gif differ
diff --git a/org.eclipse.linuxtools.tmf.ui/icons/customparser_wizard.gif b/org.eclipse.linuxtools.tmf.ui/icons/customparser_wizard.gif
new file mode 100644 (file)
index 0000000..d3667ed
Binary files /dev/null and b/org.eclipse.linuxtools.tmf.ui/icons/customparser_wizard.gif differ
diff --git a/org.eclipse.linuxtools.tmf.ui/icons/delete_button.gif b/org.eclipse.linuxtools.tmf.ui/icons/delete_button.gif
new file mode 100644 (file)
index 0000000..6bc0689
Binary files /dev/null and b/org.eclipse.linuxtools.tmf.ui/icons/delete_button.gif differ
diff --git a/org.eclipse.linuxtools.tmf.ui/icons/down_button.gif b/org.eclipse.linuxtools.tmf.ui/icons/down_button.gif
new file mode 100644 (file)
index 0000000..3f3a1ae
Binary files /dev/null and b/org.eclipse.linuxtools.tmf.ui/icons/down_button.gif differ
diff --git a/org.eclipse.linuxtools.tmf.ui/icons/element_icon.gif b/org.eclipse.linuxtools.tmf.ui/icons/element_icon.gif
new file mode 100644 (file)
index 0000000..246a8a0
Binary files /dev/null and b/org.eclipse.linuxtools.tmf.ui/icons/element_icon.gif differ
diff --git a/org.eclipse.linuxtools.tmf.ui/icons/help_button.gif b/org.eclipse.linuxtools.tmf.ui/icons/help_button.gif
new file mode 100644 (file)
index 0000000..9d70301
Binary files /dev/null and b/org.eclipse.linuxtools.tmf.ui/icons/help_button.gif differ
diff --git a/org.eclipse.linuxtools.tmf.ui/icons/line_icon.gif b/org.eclipse.linuxtools.tmf.ui/icons/line_icon.gif
new file mode 100644 (file)
index 0000000..af96ace
Binary files /dev/null and b/org.eclipse.linuxtools.tmf.ui/icons/line_icon.gif differ
diff --git a/org.eclipse.linuxtools.tmf.ui/icons/movedown_button.gif b/org.eclipse.linuxtools.tmf.ui/icons/movedown_button.gif
new file mode 100644 (file)
index 0000000..a603a53
Binary files /dev/null and b/org.eclipse.linuxtools.tmf.ui/icons/movedown_button.gif differ
diff --git a/org.eclipse.linuxtools.tmf.ui/icons/moveup_button.gif b/org.eclipse.linuxtools.tmf.ui/icons/moveup_button.gif
new file mode 100644 (file)
index 0000000..2cc2972
Binary files /dev/null and b/org.eclipse.linuxtools.tmf.ui/icons/moveup_button.gif differ
diff --git a/org.eclipse.linuxtools.tmf.ui/icons/up_button.gif b/org.eclipse.linuxtools.tmf.ui/icons/up_button.gif
new file mode 100644 (file)
index 0000000..7760d26
Binary files /dev/null and b/org.eclipse.linuxtools.tmf.ui/icons/up_button.gif differ
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/commands/ManageCustomParsersCommandHandler.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/commands/ManageCustomParsersCommandHandler.java
new file mode 100644 (file)
index 0000000..b1568f3
--- /dev/null
@@ -0,0 +1,29 @@
+/*******************************************************************************\r
+ * Copyright (c) 2010 Ericsson\r
+ * \r
+ * All rights reserved. This program and the accompanying materials are\r
+ * made available under the terms of the Eclipse Public License v1.0 which\r
+ * accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ * \r
+ * Contributors:\r
+ *   Patrick Tasse - Initial API and implementation\r
+ *******************************************************************************/\r
+\r
+package org.eclipse.linuxtools.tmf.ui.commands;\r
+\r
+import org.eclipse.core.commands.AbstractHandler;\r
+import org.eclipse.core.commands.ExecutionEvent;\r
+import org.eclipse.core.commands.ExecutionException;\r
+import org.eclipse.linuxtools.tmf.ui.dialogs.ManageCustomParsersDialog;\r
+import org.eclipse.swt.widgets.Display;\r
+\r
+public class ManageCustomParsersCommandHandler extends AbstractHandler {\r
+\r
+    public Object execute(ExecutionEvent event) throws ExecutionException {\r
+        ManageCustomParsersDialog dialog = new ManageCustomParsersDialog(Display.getDefault().getActiveShell());\r
+        dialog.open();\r
+        return null;\r
+    }\r
+\r
+}\r
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/dialogs/ManageCustomParsersDialog.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/dialogs/ManageCustomParsersDialog.java
new file mode 100644 (file)
index 0000000..5671876
--- /dev/null
@@ -0,0 +1,336 @@
+/*******************************************************************************\r
+ * Copyright (c) 2010 Ericsson\r
+ * \r
+ * All rights reserved. This program and the accompanying materials are\r
+ * made available under the terms of the Eclipse Public License v1.0 which\r
+ * accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ * \r
+ * Contributors:\r
+ *   Patrick Tasse - Initial API and implementation\r
+ *******************************************************************************/\r
+\r
+package org.eclipse.linuxtools.tmf.ui.dialogs;\r
+\r
+import java.io.File;\r
+\r
+import org.eclipse.core.resources.IFile;\r
+import org.eclipse.core.resources.IWorkspace;\r
+import org.eclipse.core.resources.ResourcesPlugin;\r
+import org.eclipse.core.runtime.CoreException;\r
+import org.eclipse.core.runtime.IPath;\r
+import org.eclipse.core.runtime.Path;\r
+import org.eclipse.jface.dialogs.Dialog;\r
+import org.eclipse.jface.dialogs.IDialogConstants;\r
+import org.eclipse.jface.dialogs.MessageDialog;\r
+import org.eclipse.jface.wizard.WizardDialog;\r
+import org.eclipse.linuxtools.tmf.ui.TmfUiPlugin;\r
+import org.eclipse.linuxtools.tmf.ui.editors.TmfEventsEditor;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.ParserProviderManager;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomTraceDefinition;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomTxtTrace;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomTxtTraceDefinition;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomXmlTrace;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomXmlTraceDefinition;\r
+import org.eclipse.linuxtools.tmf.ui.views.project.ProjectView;\r
+import org.eclipse.linuxtools.tmf.ui.wizards.CustomTxtParserWizard;\r
+import org.eclipse.linuxtools.tmf.ui.wizards.CustomXmlParserWizard;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.events.SelectionListener;\r
+import org.eclipse.swt.graphics.Image;\r
+import org.eclipse.swt.layout.GridData;\r
+import org.eclipse.swt.layout.GridLayout;\r
+import org.eclipse.swt.widgets.Button;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Control;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.swt.widgets.FileDialog;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.eclipse.swt.widgets.List;\r
+import org.eclipse.swt.widgets.Shell;\r
+import org.eclipse.ui.IEditorInput;\r
+import org.eclipse.ui.IEditorPart;\r
+import org.eclipse.ui.IReusableEditor;\r
+import org.eclipse.ui.IWorkbench;\r
+import org.eclipse.ui.IWorkbenchPage;\r
+import org.eclipse.ui.PlatformUI;\r
+import org.eclipse.ui.part.FileEditorInput;\r
+\r
+public class ManageCustomParsersDialog extends Dialog {\r
+\r
+    private static final Image image = TmfUiPlugin.getDefault().getImageFromPath("/icons/customparser_wizard.gif");\r
+\r
+    Button txtButton;\r
+    Button xmlButton;\r
+    List parserList;\r
+    Button newButton;\r
+    Button editButton;\r
+    Button deleteButton;\r
+    Button importButton;\r
+    Button exportButton;\r
+    Button parseButton;\r
+    \r
+    public ManageCustomParsersDialog(Shell parent) {\r
+        super(parent);\r
+        setShellStyle(SWT.RESIZE | SWT.MAX | getShellStyle());\r
+    }\r
+\r
+    /* (non-Javadoc)\r
+     * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)\r
+     */\r
+    @Override\r
+    protected Control createDialogArea(Composite parent) {\r
+        getShell().setText("Manage Custom Parsers");\r
+        getShell().setImage(image);\r
+        \r
+        Composite composite = (Composite) super.createDialogArea(parent);\r
+        composite.setLayout(new GridLayout(2, false));\r
+\r
+        Composite listContainer = new Composite(composite, SWT.NONE);\r
+        listContainer.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));\r
+        GridLayout lcgl = new GridLayout();\r
+        lcgl.marginHeight = 0;\r
+        lcgl.marginWidth = 0;\r
+        listContainer.setLayout(lcgl);\r
+        \r
+        Composite radioContainer = new Composite(listContainer, SWT.NONE);\r
+        GridLayout rcgl = new GridLayout(2, true);\r
+        rcgl.marginHeight = 0;\r
+        rcgl.marginWidth = 0;\r
+        radioContainer.setLayout(rcgl);\r
+        \r
+        txtButton = new Button(radioContainer, SWT.RADIO);\r
+        txtButton.setText("Text");\r
+        txtButton.setSelection(true);\r
+        txtButton.addSelectionListener(new SelectionListener(){\r
+            public void widgetDefaultSelected(SelectionEvent e) {}\r
+            public void widgetSelected(SelectionEvent e) {\r
+                fillParserList();\r
+            }});\r
+        \r
+        xmlButton = new Button(radioContainer, SWT.RADIO);\r
+        xmlButton.setText("XML");\r
+        xmlButton.addSelectionListener(new SelectionListener(){\r
+            public void widgetDefaultSelected(SelectionEvent e) {}\r
+            public void widgetSelected(SelectionEvent e) {\r
+                fillParserList();\r
+            }});\r
+        \r
+        parserList = new List(listContainer, SWT.SINGLE | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);\r
+        parserList.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));\r
+        parserList.addSelectionListener(new SelectionListener(){\r
+            public void widgetDefaultSelected(SelectionEvent e) {}\r
+            public void widgetSelected(SelectionEvent e) {\r
+                if (parserList.getSelectionCount() == 0) {\r
+                    editButton.setEnabled(false);\r
+                    deleteButton.setEnabled(false);\r
+                    exportButton.setEnabled(false);\r
+                    parseButton.setEnabled(false);\r
+                } else {\r
+                    editButton.setEnabled(true);\r
+                    deleteButton.setEnabled(true);\r
+                    exportButton.setEnabled(true);\r
+                    parseButton.setEnabled(true);\r
+                }\r
+            }});\r
+        \r
+        Composite buttonContainer = new Composite(composite, SWT.NULL);\r
+        buttonContainer.setLayout(new GridLayout());\r
+        buttonContainer.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, false, false));\r
+\r
+        newButton = new Button(buttonContainer, SWT.PUSH);\r
+        newButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));\r
+        newButton.setText("New...");\r
+        newButton.addSelectionListener(new SelectionListener(){\r
+            public void widgetDefaultSelected(SelectionEvent e) {}\r
+            public void widgetSelected(SelectionEvent e) {\r
+                WizardDialog dialog = null;\r
+                if (txtButton.getSelection()) {\r
+                    dialog = new WizardDialog(getShell(), new CustomTxtParserWizard());\r
+                } else if (xmlButton.getSelection()) {\r
+                    dialog = new WizardDialog(getShell(), new CustomXmlParserWizard());\r
+                }\r
+                dialog.open();\r
+                if (dialog.getReturnCode() == Dialog.OK) {\r
+                    fillParserList();\r
+                }\r
+            }});\r
+        \r
+        editButton = new Button(buttonContainer, SWT.PUSH);\r
+        editButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));\r
+        editButton.setText("Edit...");\r
+        editButton.setEnabled(false);\r
+        editButton.addSelectionListener(new SelectionListener(){\r
+            public void widgetDefaultSelected(SelectionEvent e) {}\r
+            public void widgetSelected(SelectionEvent e) {\r
+                WizardDialog dialog = null;\r
+                if (txtButton.getSelection()) {\r
+                    dialog = new WizardDialog(getShell(),\r
+                            new CustomTxtParserWizard(CustomTxtTraceDefinition.load(parserList.getSelection()[0])));\r
+                } else if (xmlButton.getSelection()) {\r
+                    dialog = new WizardDialog(getShell(),\r
+                            new CustomXmlParserWizard(CustomXmlTraceDefinition.load(parserList.getSelection()[0])));\r
+                }\r
+                dialog.open();\r
+                if (dialog.getReturnCode() == Dialog.OK) {\r
+                    fillParserList();\r
+                }\r
+            }});\r
+\r
+        deleteButton = new Button(buttonContainer, SWT.PUSH);\r
+        deleteButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));\r
+        deleteButton.setText("Delete");\r
+        deleteButton.setEnabled(false);\r
+        deleteButton.addSelectionListener(new SelectionListener(){\r
+            public void widgetDefaultSelected(SelectionEvent e) {}\r
+            public void widgetSelected(SelectionEvent e) {\r
+                boolean confirm = MessageDialog.openQuestion(\r
+                        getShell(),\r
+                        "Delete Custom Parser",\r
+                        "Are you sure you want to delete the " + parserList.getSelection()[0] + " custom parser?");\r
+                if (confirm) {\r
+                    if (txtButton.getSelection()) {\r
+                        CustomTxtTraceDefinition.delete(parserList.getSelection()[0]);\r
+                    } else if (xmlButton.getSelection()) {\r
+                        CustomXmlTraceDefinition.delete(parserList.getSelection()[0]);\r
+                    }\r
+                    fillParserList();\r
+                }\r
+            }});\r
+\r
+        new Label(buttonContainer, SWT.NONE); // filler\r
+        \r
+        importButton = new Button(buttonContainer, SWT.PUSH);\r
+        importButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));\r
+        importButton.setText("Import...");\r
+        importButton.addSelectionListener(new SelectionListener(){\r
+            public void widgetDefaultSelected(SelectionEvent e) {}\r
+            public void widgetSelected(SelectionEvent e) {\r
+                FileDialog dialog = new FileDialog(Display.getCurrent().getActiveShell(), SWT.OPEN);\r
+                dialog.setText("Select custom parser file to import");\r
+                dialog.setFilterExtensions(new String[] {"*.xml", "*"});\r
+                String path = dialog.open();\r
+                if (path != null) {\r
+                    CustomTraceDefinition[] defs = null;\r
+                    if (txtButton.getSelection()) {\r
+                        defs = CustomTxtTraceDefinition.loadAll(path);\r
+                    } else if (xmlButton.getSelection()) {\r
+                        defs = CustomXmlTraceDefinition.loadAll(path);\r
+                    }\r
+                    if (defs != null && defs.length > 0) {\r
+                        for (CustomTraceDefinition def : defs) {\r
+                            def.save();\r
+                        }\r
+                        fillParserList();\r
+                    }\r
+                }\r
+            }});\r
+\r
+        exportButton = new Button(buttonContainer, SWT.PUSH);\r
+        exportButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));\r
+        exportButton.setText("Export...");\r
+        exportButton.setEnabled(false);\r
+        exportButton.addSelectionListener(new SelectionListener(){\r
+            public void widgetDefaultSelected(SelectionEvent e) {}\r
+            public void widgetSelected(SelectionEvent e) {\r
+                FileDialog dialog = new FileDialog(Display.getCurrent().getActiveShell(), SWT.SAVE);\r
+                dialog.setText("Select file to export the " + parserList.getSelection()[0] + " custom parser");\r
+                dialog.setFilterExtensions(new String[] {"*.xml", "*"});\r
+                String path = dialog.open();\r
+                if (path != null) {\r
+                    CustomTraceDefinition def = null;\r
+                    if (txtButton.getSelection()) {\r
+                        def = CustomTxtTraceDefinition.load(parserList.getSelection()[0]);\r
+                    } else if (xmlButton.getSelection()) {\r
+                        def = CustomXmlTraceDefinition.load(parserList.getSelection()[0]);\r
+                    }\r
+                    if (def != null) {\r
+                        def.save(path);\r
+                    }\r
+                }\r
+            }});\r
+\r
+        parseButton = new Button(buttonContainer, SWT.PUSH);\r
+        parseButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));\r
+        parseButton.setText("Parse...");\r
+        parseButton.setEnabled(false);\r
+        parseButton.addSelectionListener(new SelectionListener(){\r
+            public void widgetDefaultSelected(SelectionEvent e) {}\r
+            public void widgetSelected(SelectionEvent e) {\r
+                FileDialog dialog = new FileDialog(Display.getCurrent().getActiveShell(), SWT.OPEN);\r
+                dialog.setText("Select log file to parse using the " + parserList.getSelection()[0] + " custom parser");\r
+                if (xmlButton.getSelection()) {\r
+                    dialog.setFilterExtensions(new String[] {"*.xml", "*"});\r
+                }\r
+                String path = dialog.open();\r
+                String parser = null;\r
+                if (path != null) {\r
+                    CustomTraceDefinition def = null;\r
+                    if (txtButton.getSelection()) {\r
+                        def = CustomTxtTraceDefinition.load(parserList.getSelection()[0]);\r
+                        parser = CustomTxtTrace.class.getCanonicalName() + "." + def.definitionName;\r
+                    } else if (xmlButton.getSelection()) {\r
+                        def = CustomXmlTraceDefinition.load(parserList.getSelection()[0]);\r
+                        parser = CustomXmlTrace.class.getCanonicalName() + "." + def.definitionName;\r
+                    }\r
+                    if (def != null) {\r
+                        try {\r
+                            IWorkspace workspace = ResourcesPlugin.getWorkspace();\r
+                            IPath location = Path.fromOSString(path);\r
+                            IFile file = workspace.getRoot().getFileForLocation(location);\r
+                            if (file == null) {\r
+                                file = ProjectView.createLink(new File(location.toPortableString()).toURI());\r
+                            }\r
+                            file.setPersistentProperty(ParserProviderManager.PARSER_PROPERTY, parser);\r
+                            IEditorInput editorInput = new FileEditorInput(file);\r
+                            IWorkbench wb = PlatformUI.getWorkbench();\r
+                            IWorkbenchPage activePage = wb.getActiveWorkbenchWindow().getActivePage();\r
+          \r
+                            String editorId = TmfEventsEditor.ID;\r
+                            IEditorPart editor = activePage.findEditor(editorInput);\r
+                            if (editor != null && editor instanceof IReusableEditor) {\r
+                                activePage.reuseEditor((IReusableEditor)editor, editorInput);\r
+                                activePage.activate(editor);\r
+                            } else {\r
+                                editor = activePage.openEditor(editorInput, editorId);\r
+                            }\r
+                        } catch (CoreException e1) {\r
+                            MessageDialog.openError(getShell(), "Parse Error", e1.getMessage());\r
+                        }\r
+                    }\r
+                }\r
+            }});\r
+\r
+        fillParserList();\r
+\r
+        getShell().setMinimumSize(300, 275);\r
+        return composite;\r
+    }\r
+\r
+    /* (non-Javadoc)\r
+     * @see org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite)\r
+     */\r
+    @Override\r
+    protected void createButtonsForButtonBar(Composite parent) {\r
+        createButton(parent, IDialogConstants.OK_ID, IDialogConstants.CLOSE_LABEL, false);\r
+    }\r
+\r
+    private void fillParserList() {\r
+        parserList.removeAll();\r
+        if (txtButton.getSelection()) {\r
+            for (CustomTxtTraceDefinition def : CustomTxtTraceDefinition.loadAll()) {\r
+                parserList.add(def.definitionName);\r
+            }\r
+        } else if (xmlButton.getSelection()) {\r
+            for (CustomXmlTraceDefinition def : CustomXmlTraceDefinition.loadAll()) {\r
+                parserList.add(def.definitionName);\r
+            }\r
+        }\r
+        editButton.setEnabled(false);\r
+        deleteButton.setEnabled(false);\r
+        exportButton.setEnabled(false);\r
+        parseButton.setEnabled(false);\r
+    }\r
+\r
+}\r
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomEvent.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomEvent.java
new file mode 100644 (file)
index 0000000..c910f3a
--- /dev/null
@@ -0,0 +1,111 @@
+/*******************************************************************************\r
+ * Copyright (c) 2010 Ericsson\r
+ * \r
+ * All rights reserved. This program and the accompanying materials are\r
+ * made available under the terms of the Eclipse Public License v1.0 which\r
+ * accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ * \r
+ * Contributors:\r
+ *   Patrick Tasse - Initial API and implementation\r
+ *******************************************************************************/\r
+\r
+package org.eclipse.linuxtools.tmf.ui.parsers.custom;\r
+\r
+import java.text.ParseException;\r
+import java.text.SimpleDateFormat;\r
+import java.util.Date;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import org.eclipse.linuxtools.tmf.event.TmfEvent;\r
+import org.eclipse.linuxtools.tmf.event.TmfEventContent;\r
+import org.eclipse.linuxtools.tmf.event.TmfEventReference;\r
+import org.eclipse.linuxtools.tmf.event.TmfEventSource;\r
+import org.eclipse.linuxtools.tmf.event.TmfEventType;\r
+import org.eclipse.linuxtools.tmf.event.TmfTimestamp;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomTraceDefinition.OutputColumn;\r
+\r
+public class CustomEvent extends TmfEvent {\r
+\r
+    protected static final String TIMESTAMP_INPUT_FORMAT_KEY = "CE_TS_I_F";\r
+    protected static final String NO_MESSAGE = "";\r
+    public static final byte TIMESTAMP_SCALE = -3;\r
+    \r
+    protected CustomTraceDefinition fDefinition;\r
+    protected Map<String, String> fData;\r
+    private String[] fColumnData;\r
+\r
+    public CustomEvent(CustomTraceDefinition definition, TmfEvent other) {\r
+        super(other);\r
+        fDefinition = definition;\r
+        fData = new HashMap<String, String>();\r
+    }\r
+\r
+    public CustomEvent(CustomTraceDefinition definition, TmfTimestamp timestamp, TmfEventSource source, TmfEventType type, TmfEventReference reference) {\r
+        super(timestamp, source, type, reference);\r
+        fDefinition = definition;\r
+        fData = new HashMap<String, String>();\r
+    }\r
+\r
+    public CustomEvent(CustomTraceDefinition definition, TmfTimestamp originalTS, TmfTimestamp effectiveTS, TmfEventSource source, TmfEventType type, TmfEventReference reference) {\r
+        super(originalTS, effectiveTS, source, type, reference);\r
+        fDefinition = definition;\r
+        fData = new HashMap<String, String>();\r
+    }\r
+    \r
+    @Override\r
+    public TmfTimestamp getTimestamp() {\r
+        if (fData != null) processData();\r
+        return super.getTimestamp();\r
+    }\r
+\r
+    @Override\r
+    public TmfTimestamp getOriginalTimestamp() {\r
+        if (fData != null) processData();\r
+        return super.getOriginalTimestamp();\r
+    }\r
+\r
+    @Override\r
+    public TmfEventContent getContent() {\r
+        if (fData != null) processData();\r
+        return super.getContent();\r
+    }\r
+\r
+    public String[] extractItemFields() {\r
+        if (fData != null) processData();\r
+        return fColumnData;\r
+    }\r
+\r
+    private void processData() {\r
+        String timeStampString = fData.get(CustomTraceDefinition.TAG_TIMESTAMP);\r
+        String timeStampInputFormat = fData.get(TIMESTAMP_INPUT_FORMAT_KEY);\r
+        Date date = null;\r
+        if (timeStampInputFormat != null && timeStampString != null) {\r
+            SimpleDateFormat dateFormat = new SimpleDateFormat(timeStampInputFormat);\r
+            try {\r
+                date = dateFormat.parse(timeStampString);\r
+                fOriginalTimestamp = fEffectiveTimestamp = new TmfTimestamp(date.getTime(), TIMESTAMP_SCALE);\r
+            } catch (ParseException e) {\r
+                fOriginalTimestamp = fEffectiveTimestamp = TmfTimestamp.Zero;\r
+            }\r
+        } else {\r
+            fOriginalTimestamp = fEffectiveTimestamp = TmfTimestamp.Zero;\r
+        }\r
+        \r
+        int i = 0;\r
+        fColumnData = new String[fDefinition.outputs.size()];\r
+        for (OutputColumn outputColumn : fDefinition.outputs) {\r
+            String value = fData.get(outputColumn.name);\r
+            if (outputColumn.name.equals(CustomTraceDefinition.TAG_TIMESTAMP) && date != null) {\r
+                SimpleDateFormat dateFormat = new SimpleDateFormat(fDefinition.timeStampOutputFormat);\r
+                fColumnData[i++] = dateFormat.format(date);\r
+            } else {\r
+                fColumnData[i++] = value;\r
+            }\r
+        }\r
+        String message = fData.get(CustomTraceDefinition.TAG_MESSAGE);;\r
+        setContent(new TmfEventContent(this, message));\r
+        fData = null;\r
+    }\r
+}\r
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomEventsTable.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomEventsTable.java
new file mode 100644 (file)
index 0000000..f8d4a7b
--- /dev/null
@@ -0,0 +1,59 @@
+/*******************************************************************************\r
+ * Copyright (c) 2010 Ericsson\r
+ * \r
+ * All rights reserved. This program and the accompanying materials are\r
+ * made available under the terms of the Eclipse Public License v1.0 which\r
+ * accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ * \r
+ * Contributors:\r
+ *   Patrick Tasse - Initial API and implementation\r
+ *******************************************************************************/\r
+\r
+package org.eclipse.linuxtools.tmf.ui.parsers.custom;\r
+\r
+import java.text.SimpleDateFormat;\r
+import java.util.TimeZone;\r
+\r
+import org.eclipse.linuxtools.tmf.event.TmfEvent;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomTraceDefinition.OutputColumn;\r
+import org.eclipse.linuxtools.tmf.ui.viewers.events.TmfEventsTable;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Table;\r
+import org.eclipse.swt.widgets.TableColumn;\r
+\r
+public class CustomEventsTable extends TmfEventsTable {\r
+\r
+    private CustomTraceDefinition fDefinition;\r
+    \r
+    public CustomEventsTable(CustomTraceDefinition definition, Composite parent, int cacheSize) {\r
+        super(parent, cacheSize);\r
+        fDefinition = definition;\r
+        createColumnHeaders(fTable);\r
+    }\r
+\r
+    public static final String TIMESTAMP_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS";\r
+    private static final SimpleDateFormat TIMESTAMP_SIMPLE_DATE_FORMAT = new SimpleDateFormat(TIMESTAMP_FORMAT); \r
+    static {\r
+        TIMESTAMP_SIMPLE_DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT"));\r
+    }\r
+\r
+    @Override\r
+    public void createColumnHeaders(final Table table) {\r
+        if (fDefinition == null) return; // ignore when called by the super constructor\r
+        for (OutputColumn outputColumn : fDefinition.outputs) {\r
+            TableColumn column = new TableColumn(table, SWT.LEFT);\r
+            column.setText(outputColumn.name);\r
+            column.pack();\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public String[] extractItemFields(TmfEvent event) {\r
+        if (event instanceof CustomEvent) {\r
+            return ((CustomEvent) event).extractItemFields();\r
+        }\r
+        return new String[0];\r
+    }\r
+}\r
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomParserProvider.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomParserProvider.java
new file mode 100644 (file)
index 0000000..aaf5fe7
--- /dev/null
@@ -0,0 +1,79 @@
+/*******************************************************************************\r
+ * Copyright (c) 2010 Ericsson\r
+ * \r
+ * All rights reserved. This program and the accompanying materials are\r
+ * made available under the terms of the Eclipse Public License v1.0 which\r
+ * accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ * \r
+ * Contributors:\r
+ *   Patrick Tasse - Initial API and implementation\r
+ *******************************************************************************/\r
+\r
+package org.eclipse.linuxtools.tmf.ui.parsers.custom;\r
+\r
+import java.io.FileNotFoundException;\r
+import java.util.LinkedHashMap;\r
+import java.util.Map;\r
+\r
+import org.eclipse.core.resources.IResource;\r
+import org.eclipse.linuxtools.tmf.trace.ITmfTrace;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.IParserProvider;\r
+import org.eclipse.linuxtools.tmf.ui.viewers.events.TmfEventsTable;\r
+import org.eclipse.swt.widgets.Composite;\r
+\r
+public class CustomParserProvider implements IParserProvider {\r
+\r
+    public String getCategory() {\r
+        return "Custom";\r
+    }\r
+\r
+    public ITmfTrace getTraceForParser(String parser, IResource resource) {\r
+        try {\r
+            String name = resource.getName();\r
+            String path = resource.getLocation().toOSString();\r
+            for (CustomTxtTraceDefinition def : CustomTxtTraceDefinition.loadAll()) {\r
+                if (parser.equals(CustomTxtTrace.class.getCanonicalName() + "." + def.definitionName)) {\r
+                    return new CustomTxtTrace(name, def, path, 100);\r
+                }\r
+            }\r
+            for (CustomXmlTraceDefinition def : CustomXmlTraceDefinition.loadAll()) {\r
+                if (parser.equals(CustomXmlTrace.class.getCanonicalName() + "." + def.definitionName)) {\r
+                    return new CustomXmlTrace(name, def, path, 100);\r
+                }\r
+            }\r
+        } catch (FileNotFoundException e) {\r
+            e.printStackTrace();\r
+        }\r
+        return null;\r
+    }\r
+\r
+    public ITmfTrace getTraceForContentType(String contentTypeId, IResource resource) {\r
+        return null;\r
+    }\r
+\r
+    public String getEditorIdForParser(String parser) {\r
+        return null;\r
+    }\r
+\r
+    public Map<String, String> getParserMap() {\r
+        Map<String, String> parserMap = new LinkedHashMap<String, String>();\r
+        for (CustomTxtTraceDefinition def : CustomTxtTraceDefinition.loadAll()) {\r
+            parserMap.put(def.definitionName, CustomTxtTrace.class.getCanonicalName() + "." + def.definitionName);\r
+        }\r
+        for (CustomXmlTraceDefinition def : CustomXmlTraceDefinition.loadAll()) {\r
+            parserMap.put(def.definitionName, CustomXmlTrace.class.getCanonicalName() + "." + def.definitionName);\r
+        }\r
+        return parserMap;\r
+    }\r
+\r
+    public TmfEventsTable getEventsTable(ITmfTrace trace, Composite parent, int cacheSize) {\r
+        if (trace instanceof CustomTxtTrace) {\r
+            return new CustomEventsTable(((CustomTxtTrace) trace).getDefinition(), parent, cacheSize);\r
+        } else if (trace instanceof CustomXmlTrace) {\r
+            return new CustomEventsTable(((CustomXmlTrace) trace).getDefinition(), parent, cacheSize);\r
+        }\r
+        return null;\r
+    }\r
+\r
+}\r
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomTraceDefinition.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomTraceDefinition.java
new file mode 100644 (file)
index 0000000..70c456e
--- /dev/null
@@ -0,0 +1,59 @@
+/*******************************************************************************\r
+ * Copyright (c) 2010 Ericsson\r
+ * \r
+ * All rights reserved. This program and the accompanying materials are\r
+ * made available under the terms of the Eclipse Public License v1.0 which\r
+ * accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ * \r
+ * Contributors:\r
+ *   Patrick Tasse - Initial API and implementation\r
+ *******************************************************************************/\r
+\r
+package org.eclipse.linuxtools.tmf.ui.parsers.custom;\r
+\r
+import java.text.SimpleDateFormat;\r
+import java.util.List;\r
+import java.util.TimeZone;\r
+\r
+import org.eclipse.linuxtools.tmf.event.TmfTimestamp;\r
+\r
+\r
+public abstract class CustomTraceDefinition {\r
+\r
+    public static final int ACTION_SET = 0;\r
+    public static final int ACTION_APPEND = 1;\r
+    public static final int ACTION_APPEND_WITH_SEPARATOR = 2;\r
+\r
+    public static final String TAG_TIMESTAMP = "Time Stamp";\r
+    public static final String TAG_MESSAGE = "Message";\r
+    public static final String TAG_OTHER = "Other";\r
+    \r
+    public String definitionName;\r
+    public List<OutputColumn> outputs;\r
+    public String timeStampOutputFormat;\r
+    \r
+    public static class OutputColumn {\r
+        public String name;\r
+\r
+        public OutputColumn() {};\r
+\r
+        public OutputColumn(String name) {\r
+            this.name = name;\r
+        }\r
+\r
+        @Override\r
+        public String toString() {\r
+            return name;\r
+        }\r
+    }\r
+\r
+    public String formatTimeStamp(TmfTimestamp timestamp) {\r
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(timeStampOutputFormat);\r
+        simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));\r
+        return simpleDateFormat.format(timestamp.getValue());\r
+    }\r
+    \r
+    public abstract void save();\r
+    public abstract void save(String path);\r
+}\r
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomTxtEvent.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomTxtEvent.java
new file mode 100644 (file)
index 0000000..0c7582f
--- /dev/null
@@ -0,0 +1,88 @@
+/*******************************************************************************\r
+ * Copyright (c) 2010 Ericsson\r
+ * \r
+ * All rights reserved. This program and the accompanying materials are\r
+ * made available under the terms of the Eclipse Public License v1.0 which\r
+ * accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ * \r
+ * Contributors:\r
+ *   Patrick Tasse - Initial API and implementation\r
+ *******************************************************************************/\r
+\r
+package org.eclipse.linuxtools.tmf.ui.parsers.custom;\r
+\r
+import java.util.regex.Matcher;\r
+\r
+import org.eclipse.linuxtools.tmf.event.TmfEvent;\r
+import org.eclipse.linuxtools.tmf.event.TmfEventReference;\r
+import org.eclipse.linuxtools.tmf.event.TmfEventSource;\r
+import org.eclipse.linuxtools.tmf.event.TmfEventType;\r
+import org.eclipse.linuxtools.tmf.event.TmfTimestamp;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomTxtTraceDefinition.InputData;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomTxtTraceDefinition.InputLine;\r
+\r
+public class CustomTxtEvent extends CustomEvent {\r
+\r
+    public CustomTxtEvent(CustomTxtTraceDefinition definition, TmfEvent other) {\r
+        super(definition, other);\r
+    }\r
+\r
+    public CustomTxtEvent(CustomTxtTraceDefinition definition, TmfTimestamp timestamp, TmfEventSource source, TmfEventType type, TmfEventReference reference) {\r
+        super(definition, timestamp, source, type, reference);\r
+    }\r
+\r
+    public CustomTxtEvent(CustomTxtTraceDefinition definition, TmfTimestamp originalTS, TmfTimestamp effectiveTS, TmfEventSource source, TmfEventType type, TmfEventReference reference) {\r
+        super(definition, originalTS, effectiveTS, source, type, reference);\r
+    }\r
+\r
+    public void processGroups(InputLine input, Matcher matcher) {\r
+        for (int i = 0; i < input.columns.size(); i++) {\r
+            InputData column = input.columns.get(i);\r
+            if (i < matcher.groupCount() && matcher.group(i + 1) != null) {\r
+                String value = matcher.group(i + 1).trim();\r
+                if (value.length() == 0) {\r
+                    continue;\r
+                }\r
+                String name = column.name;\r
+                if (column.action == CustomTxtTraceDefinition.ACTION_SET) {\r
+                    fData.put(name, value);\r
+                    if (name.equals(CustomTxtTraceDefinition.TAG_TIMESTAMP)) {\r
+                        fData.put(TIMESTAMP_INPUT_FORMAT_KEY, column.format);\r
+                    }\r
+                } else if (column.action == CustomTxtTraceDefinition.ACTION_APPEND) {\r
+                    String s = fData.get(name);\r
+                    if (s != null) {\r
+                        fData.put(name, s + value);\r
+                    } else {\r
+                        fData.put(name, value);\r
+                    }\r
+                    if (name.equals(CustomTxtTraceDefinition.TAG_TIMESTAMP)) {\r
+                        String timeStampInputFormat = fData.get(TIMESTAMP_INPUT_FORMAT_KEY);\r
+                        if (timeStampInputFormat != null) {\r
+                            fData.put(TIMESTAMP_INPUT_FORMAT_KEY, timeStampInputFormat + column.format);\r
+                        } else {\r
+                            fData.put(TIMESTAMP_INPUT_FORMAT_KEY, column.format);\r
+                        }\r
+                    }\r
+                } else if (column.action == CustomTxtTraceDefinition.ACTION_APPEND_WITH_SEPARATOR) {\r
+                    String s = fData.get(name);\r
+                    if (s != null) {\r
+                        fData.put(name, s + " | " + value);\r
+                    } else {\r
+                        fData.put(name, value);\r
+                    }\r
+                    if (name.equals(CustomTxtTraceDefinition.TAG_TIMESTAMP)) {\r
+                        String timeStampInputFormat = fData.get(TIMESTAMP_INPUT_FORMAT_KEY);\r
+                        if (timeStampInputFormat != null) {\r
+                            fData.put(TIMESTAMP_INPUT_FORMAT_KEY, timeStampInputFormat + " | " + column.format);\r
+                        } else {\r
+                            fData.put(TIMESTAMP_INPUT_FORMAT_KEY, column.format);\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+        }\r
+    }\r
+\r
+}\r
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomTxtTrace.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomTxtTrace.java
new file mode 100644 (file)
index 0000000..2cae30c
--- /dev/null
@@ -0,0 +1,277 @@
+/*******************************************************************************\r
+ * Copyright (c) 2010 Ericsson\r
+ * \r
+ * All rights reserved. This program and the accompanying materials are\r
+ * made available under the terms of the Eclipse Public License v1.0 which\r
+ * accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ * \r
+ * Contributors:\r
+ *   Patrick Tasse - Initial API and implementation\r
+ *******************************************************************************/\r
+\r
+package org.eclipse.linuxtools.tmf.ui.parsers.custom;\r
+\r
+import java.io.File;\r
+import java.io.FileNotFoundException;\r
+import java.io.IOException;\r
+import java.io.RandomAccessFile;\r
+import java.util.HashMap;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+import java.util.Map.Entry;\r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+\r
+import org.eclipse.linuxtools.tmf.event.TmfEvent;\r
+import org.eclipse.linuxtools.tmf.event.TmfEventReference;\r
+import org.eclipse.linuxtools.tmf.event.TmfEventSource;\r
+import org.eclipse.linuxtools.tmf.event.TmfEventType;\r
+import org.eclipse.linuxtools.tmf.event.TmfTimestamp;\r
+import org.eclipse.linuxtools.tmf.trace.ITmfContext;\r
+import org.eclipse.linuxtools.tmf.trace.ITmfLocation;\r
+import org.eclipse.linuxtools.tmf.trace.ITmfTrace;\r
+import org.eclipse.linuxtools.tmf.trace.TmfContext;\r
+import org.eclipse.linuxtools.tmf.trace.TmfLocation;\r
+import org.eclipse.linuxtools.tmf.trace.TmfTrace;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomTxtTraceDefinition.InputLine;\r
+\r
+public class CustomTxtTrace extends TmfTrace<CustomTxtEvent> {\r
+\r
+    private CustomTxtTraceDefinition fDefinition;\r
+    \r
+    public CustomTxtTrace(String name, CustomTxtTraceDefinition definition, String path, int cacheSize) throws FileNotFoundException {\r
+        super(name, CustomTxtEvent.class, path, cacheSize);\r
+        fDefinition = definition;\r
+    }\r
+\r
+    public ITmfTrace createTraceCopy() {\r
+        // TODO Auto-generated method stub\r
+        return null;\r
+    }\r
+\r
+    @Override\r
+    public TmfContext seekLocation(ITmfLocation<?> location) {\r
+        //System.out.println(Thread.currentThread().getName() + "::" + getName() + " seekLocation(" + ((location == null || location.getLocation() == null) ? "null" : location) + ")");\r
+        //new Throwable().printStackTrace();\r
+        CustomTxtTraceContext context = new CustomTxtTraceContext(new TmfLocation<Long>((Long)null), ITmfContext.INITIAL_RANK);\r
+        if (!new File(getPath()).isFile()) {\r
+            return context;\r
+        }\r
+        try {\r
+            RandomAccessFile raFile = new RandomAccessFile(getPath(), "r");\r
+            if (location != null && location.getLocation() instanceof Long) {\r
+                raFile.seek((Long)location.getLocation());\r
+            }\r
+            String line;\r
+            long rawPos = raFile.getFilePointer();\r
+            while ((line = raFile.readLine()) != null) {\r
+                for (InputLine input : getFirstLines()) {\r
+                    Matcher matcher = input.getPattern().matcher(line);\r
+                    if (matcher.find()) {\r
+                        context.setLocation(new TmfLocation<Long>(rawPos));\r
+                        context.raFile = raFile;\r
+                        context.firstLineMatcher = matcher;\r
+                        context.nextLineLocation = raFile.getFilePointer();\r
+                        context.inputLine = input;\r
+                        return context;\r
+                    }\r
+                }\r
+                rawPos = raFile.getFilePointer();\r
+            }\r
+            return context;\r
+        } catch (FileNotFoundException e) {\r
+            e.printStackTrace();\r
+            return context;\r
+        } catch (IOException e) {\r
+            e.printStackTrace();\r
+            return context;\r
+        }\r
+        \r
+    }\r
+\r
+    @Override\r
+    public ITmfLocation<?> getCurrentLocation() {\r
+        // TODO Auto-generated method stub\r
+        return null;\r
+    }\r
+\r
+    @Override\r
+    public synchronized TmfEvent getNextEvent(TmfContext context) {\r
+        ITmfContext savedContext = context.clone();\r
+        TmfEvent event = parseEvent(context);\r
+        if (event != null) {\r
+            updateIndex(savedContext, savedContext.getRank(), event.getTimestamp());\r
+            context.updateRank(1);\r
+        }\r
+        return event;\r
+    }\r
+\r
+    @Override\r
+    public TmfEvent parseEvent(TmfContext tmfContext) {\r
+        //System.out.println(Thread.currentThread().getName() + ":: " + getName() + " parseEvent(" + tmfContext.getRank() + " @ " + (tmfContext.getLocation().getLocation() == null ? "null" : tmfContext.getLocation()));\r
+        if (!(tmfContext instanceof CustomTxtTraceContext)) {\r
+            return null;\r
+        }\r
+        \r
+        CustomTxtTraceContext context = (CustomTxtTraceContext) tmfContext;\r
+        if (!(context.getLocation().getLocation() instanceof Long)) {\r
+            return null;\r
+        }\r
+\r
+        CustomTxtEvent event = parseFirstLine(context);\r
+\r
+        HashMap<InputLine, Integer> countMap = new HashMap<InputLine, Integer>();\r
+        InputLine currentInput = null;\r
+        if (context.inputLine.childrenInputs != null && context.inputLine.childrenInputs.size() > 0) {\r
+            currentInput = context.inputLine.childrenInputs.get(0);\r
+            countMap.put(currentInput, 0);\r
+        }\r
+        \r
+        synchronized (context.raFile) {\r
+            try {\r
+                if (context.raFile.getFilePointer() != context.nextLineLocation) {\r
+                    context.raFile.seek(context.nextLineLocation);\r
+                }\r
+                String line;\r
+                long rawPos = context.raFile.getFilePointer();\r
+                while ((line = context.raFile.readLine()) != null) {\r
+                    boolean processed = false;\r
+                    if (currentInput == null) {\r
+                        for (InputLine input : getFirstLines()) {\r
+                            Matcher matcher = input.getPattern().matcher(line);\r
+                            if (matcher.find()) {\r
+                                context.setLocation(new TmfLocation<Long>(rawPos));\r
+                                context.firstLineMatcher = matcher;\r
+                                context.nextLineLocation = context.raFile.getFilePointer();\r
+                                context.inputLine = input;\r
+                                return event;\r
+                            }\r
+                        }\r
+                    } else {\r
+                        if (countMap.get(currentInput) >= currentInput.getMinCount()) {\r
+                            List<InputLine> nextInputs = currentInput.getNextInputs(countMap);\r
+                            if (nextInputs.size() == 0 || nextInputs.get(nextInputs.size() - 1).getMinCount() == 0) {\r
+                                for (InputLine input : getFirstLines()) {\r
+                                    Matcher matcher = input.getPattern().matcher(line);\r
+                                    if (matcher.find()) {\r
+                                        context.setLocation(new TmfLocation<Long>(rawPos));\r
+                                        context.firstLineMatcher = matcher;\r
+                                        context.nextLineLocation = context.raFile.getFilePointer();\r
+                                        context.inputLine = input;\r
+                                        return event;\r
+                                    }\r
+                                }\r
+                            }\r
+                            for (InputLine input : nextInputs) {\r
+                                Matcher matcher = input.getPattern().matcher(line);\r
+                                if (matcher.find()) {\r
+                                    event.processGroups(input, matcher);\r
+                                    currentInput = input;\r
+                                    if (countMap.get(currentInput) == null) {\r
+                                        countMap.put(currentInput, 1);\r
+                                    } else {\r
+                                        countMap.put(currentInput, countMap.get(currentInput) + 1);\r
+                                    }\r
+                                    Iterator<InputLine> iter = countMap.keySet().iterator();\r
+                                    while (iter.hasNext()) {\r
+                                        InputLine inputLine = iter.next();\r
+                                        if (inputLine.level > currentInput.level) {\r
+                                            iter.remove();\r
+                                        }\r
+                                    }\r
+                                    if (currentInput.childrenInputs != null && currentInput.childrenInputs.size() > 0) {\r
+                                        currentInput = currentInput.childrenInputs.get(0);\r
+                                        countMap.put(currentInput, 0);\r
+                                    } else {\r
+                                        if (countMap.get(currentInput) >= currentInput.getMaxCount()) {\r
+                                            if (currentInput.getNextInputs(countMap).size() > 0) {\r
+                                                currentInput = currentInput.getNextInputs(countMap).get(0);\r
+                                                if (countMap.get(currentInput) == null) {\r
+                                                    countMap.put(currentInput, 0);\r
+                                                }\r
+                                                iter = countMap.keySet().iterator();\r
+                                                while (iter.hasNext()) {\r
+                                                    InputLine inputLine = iter.next();\r
+                                                    if (inputLine.level > currentInput.level) {\r
+                                                        iter.remove();\r
+                                                    }\r
+                                                }\r
+                                            } else {\r
+                                                currentInput = null;\r
+                                            }\r
+                                        }\r
+                                    }\r
+                                    processed = true;\r
+                                    break;\r
+                                }\r
+                            }\r
+                        }\r
+                        if (! processed) {\r
+                            Matcher matcher = currentInput.getPattern().matcher(line);\r
+                            if (matcher.find()) {\r
+                                event.processGroups(currentInput, matcher);\r
+                                countMap.put(currentInput, countMap.get(currentInput) + 1);\r
+                                if (currentInput.childrenInputs != null && currentInput.childrenInputs.size() > 0) {\r
+                                    currentInput = currentInput.childrenInputs.get(0);\r
+                                    countMap.put(currentInput, 0);\r
+                                } else {\r
+                                    if (countMap.get(currentInput) >= currentInput.getMaxCount()) {\r
+                                        if (currentInput.getNextInputs(countMap).size() > 0) {\r
+                                            currentInput = currentInput.getNextInputs(countMap).get(0);\r
+                                            if (countMap.get(currentInput) == null) {\r
+                                                countMap.put(currentInput, 0);\r
+                                            }\r
+                                            Iterator<InputLine> iter = countMap.keySet().iterator();\r
+                                            while (iter.hasNext()) {\r
+                                                InputLine inputLine = iter.next();\r
+                                                if (inputLine.level > currentInput.level) {\r
+                                                    iter.remove();\r
+                                                }\r
+                                            }\r
+                                        } else {\r
+                                            currentInput = null;\r
+                                        }\r
+                                    }\r
+                                }\r
+                            }\r
+                        }\r
+                    }\r
+                    rawPos = context.raFile.getFilePointer();\r
+                }\r
+            } catch (IOException e) {\r
+                e.printStackTrace();\r
+            }\r
+        }\r
+        for(Entry<InputLine, Integer> entry : countMap.entrySet()) {\r
+            if (entry.getValue() < entry.getKey().getMinCount()) {\r
+                event = null;\r
+            }\r
+        }\r
+        context.setLocation(new TmfLocation<Long>((Long)null));\r
+        return event;\r
+    }\r
+\r
+    public List<InputLine> getFirstLines() {\r
+        return fDefinition.inputs;\r
+    }\r
+    \r
+    public CustomTxtEvent parseFirstLine(CustomTxtTraceContext context) {\r
+        CustomTxtEvent event = new CustomTxtEvent(fDefinition, TmfTimestamp.Zero, new TmfEventSource(""), new TmfEventType(fDefinition.definitionName, new String[0]), new TmfEventReference(""));\r
+        event.processGroups(context.inputLine, context.firstLineMatcher);\r
+        return event;\r
+    }\r
+    \r
+    public void parseNextLine(CustomTxtEvent event, String line, InputLine input) {\r
+        Pattern pattern = input.getPattern();\r
+        Matcher matcher = pattern.matcher(line);\r
+        if (matcher.find()) {\r
+            event.processGroups(input, matcher);\r
+            return;\r
+        }\r
+    }\r
+\r
+    public CustomTraceDefinition getDefinition() {\r
+        return fDefinition;\r
+    }\r
+}\r
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomTxtTraceContext.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomTxtTraceContext.java
new file mode 100644 (file)
index 0000000..38e142d
--- /dev/null
@@ -0,0 +1,31 @@
+/*******************************************************************************\r
+ * Copyright (c) 2010 Ericsson\r
+ * \r
+ * All rights reserved. This program and the accompanying materials are\r
+ * made available under the terms of the Eclipse Public License v1.0 which\r
+ * accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ * \r
+ * Contributors:\r
+ *   Patrick Tasse - Initial API and implementation\r
+ *******************************************************************************/\r
+\r
+package org.eclipse.linuxtools.tmf.ui.parsers.custom;\r
+\r
+import java.io.RandomAccessFile;\r
+import java.util.regex.Matcher;\r
+\r
+import org.eclipse.linuxtools.tmf.trace.ITmfLocation;\r
+import org.eclipse.linuxtools.tmf.trace.TmfContext;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomTxtTraceDefinition.InputLine;\r
+\r
+public class CustomTxtTraceContext extends TmfContext {\r
+    public RandomAccessFile raFile;\r
+    public Matcher firstLineMatcher;\r
+    public long nextLineLocation;\r
+    public InputLine inputLine;\r
+\r
+    public CustomTxtTraceContext(ITmfLocation<?> location, long rank) {\r
+        super(location, rank);\r
+    }\r
+}
\ No newline at end of file
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomTxtTraceDefinition.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomTxtTraceDefinition.java
new file mode 100644 (file)
index 0000000..0e18903
--- /dev/null
@@ -0,0 +1,628 @@
+/*******************************************************************************\r
+ * Copyright (c) 2010 Ericsson\r
+ * \r
+ * All rights reserved. This program and the accompanying materials are\r
+ * made available under the terms of the Eclipse Public License v1.0 which\r
+ * accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ * \r
+ * Contributors:\r
+ *   Patrick Tasse - Initial API and implementation\r
+ *******************************************************************************/\r
+\r
+package org.eclipse.linuxtools.tmf.ui.parsers.custom;\r
+\r
+import java.io.ByteArrayInputStream;\r
+import java.io.File;\r
+import java.io.FileWriter;\r
+import java.io.IOException;\r
+import java.io.StringWriter;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.regex.Pattern;\r
+import java.util.regex.PatternSyntaxException;\r
+\r
+import javax.xml.parsers.DocumentBuilder;\r
+import javax.xml.parsers.DocumentBuilderFactory;\r
+import javax.xml.parsers.ParserConfigurationException;\r
+import javax.xml.transform.OutputKeys;\r
+import javax.xml.transform.Transformer;\r
+import javax.xml.transform.TransformerConfigurationException;\r
+import javax.xml.transform.TransformerException;\r
+import javax.xml.transform.TransformerFactory;\r
+import javax.xml.transform.TransformerFactoryConfigurationError;\r
+import javax.xml.transform.dom.DOMSource;\r
+import javax.xml.transform.stream.StreamResult;\r
+\r
+import org.eclipse.linuxtools.tmf.ui.TmfUiPlugin;\r
+import org.w3c.dom.Document;\r
+import org.w3c.dom.Element;\r
+import org.w3c.dom.Node;\r
+import org.w3c.dom.NodeList;\r
+import org.xml.sax.EntityResolver;\r
+import org.xml.sax.ErrorHandler;\r
+import org.xml.sax.InputSource;\r
+import org.xml.sax.SAXException;\r
+import org.xml.sax.SAXParseException;\r
+\r
+public class CustomTxtTraceDefinition extends CustomTraceDefinition {\r
+\r
+    protected static final String CUSTOM_TXT_TRACE_DEFINITIONS_FILE_NAME = "custom_txt_parsers.xml";\r
+    protected static final String CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME =\r
+        TmfUiPlugin.getDefault().getStateLocation().addTrailingSeparator().append(CUSTOM_TXT_TRACE_DEFINITIONS_FILE_NAME).toString();\r
+\r
+    private static final String CUSTOM_TXT_TRACE_DEFINITION_ROOT_ELEMENT = "CustomTxtTraceDefinitionList";\r
+    private static final String DEFINITION_ELEMENT = "Definition";\r
+    private static final String NAME_ATTRIBUTE = "name";\r
+    private static final String TIME_STAMP_OUTPUT_FORMAT_ELEMENT = "TimeStampOutputFormat";\r
+    private static final String INPUT_LINE_ELEMENT = "InputLine";\r
+    private static final String CARDINALITY_ELEMENT = "Cardinality";\r
+    private static final String MIN_ATTRIBUTE = "min";\r
+    private static final String MAX_ATTRIBUTE = "max";\r
+    private static final String REGEX_ELEMENT = "RegEx";\r
+    private static final String INPUT_DATA_ELEMENT = "InputData";\r
+    private static final String ACTION_ATTRIBUTE = "action";\r
+    private static final String FORMAT_ATTRIBUTE = "format";\r
+    private static final String OUTPUT_COLUMN_ELEMENT = "OutputColumn";\r
+    \r
+    public List<InputLine> inputs;\r
+\r
+    public CustomTxtTraceDefinition() {\r
+        this("", new ArrayList<InputLine>(0), new ArrayList<OutputColumn>(0), "");\r
+    };\r
+    \r
+    public CustomTxtTraceDefinition(String logtype, List<InputLine> inputs, List<OutputColumn> outputs, String timeStampOutputFormat) {\r
+        this.definitionName = logtype;\r
+        this.inputs = inputs;\r
+        this.outputs = outputs;\r
+        this.timeStampOutputFormat = timeStampOutputFormat;\r
+    }\r
+    \r
+    public static class InputLine {\r
+        public List<InputData> columns;\r
+        public Cardinality cardinality;\r
+        private String regex;\r
+        private Pattern pattern;\r
+        public InputLine parentInput;\r
+        public int level;\r
+        public InputLine nextInput;\r
+        public List<InputLine> childrenInputs;\r
+        \r
+        public InputLine() {};\r
+        \r
+        public InputLine(Cardinality cardinality, String regex, List<InputData> columns) {\r
+            this.cardinality = cardinality;\r
+            this.regex = regex;\r
+            this.columns = columns;\r
+        }\r
+        \r
+        public void setRegex(String regex) {\r
+            this.regex = regex;\r
+            this.pattern = null;\r
+        }\r
+        \r
+        public String getRegex() {\r
+            return regex;\r
+        }\r
+        \r
+        public Pattern getPattern() throws PatternSyntaxException {\r
+            if (pattern == null) {\r
+                pattern = Pattern.compile(regex);\r
+            }\r
+            return pattern;\r
+        }\r
+        \r
+        public void addChild(InputLine input) {\r
+            if (childrenInputs == null) {\r
+                childrenInputs = new ArrayList<InputLine>(1);\r
+            } else if (childrenInputs.size() > 0) {\r
+                InputLine last = childrenInputs.get(childrenInputs.size() - 1);\r
+                last.nextInput = input;\r
+            }\r
+            childrenInputs.add(input);\r
+            input.parentInput = this;\r
+            input.level = this.level + 1;\r
+        }\r
+\r
+        public void addNext(InputLine input) {\r
+            if (parentInput != null) {\r
+                int index = parentInput.childrenInputs.indexOf(this);\r
+                parentInput.childrenInputs.add(index + 1, input);\r
+                InputLine next = nextInput;\r
+                nextInput = input;\r
+                input.nextInput = next;\r
+            }\r
+            input.parentInput = this.parentInput;\r
+            input.level = this.level;\r
+        }\r
+\r
+        public void moveUp() {\r
+            if (parentInput != null) {\r
+                int index = parentInput.childrenInputs.indexOf(this);\r
+                if (index > 0) {\r
+                    parentInput.childrenInputs.add(index - 1 , parentInput.childrenInputs.remove(index));\r
+                    parentInput.childrenInputs.get(index).nextInput = nextInput;\r
+                    nextInput = parentInput.childrenInputs.get(index);\r
+                }\r
+            }\r
+        }\r
+\r
+        public void moveDown() {\r
+            if (parentInput != null) {\r
+                int index = parentInput.childrenInputs.indexOf(this);\r
+                if (index < parentInput.childrenInputs.size() - 1) {\r
+                    parentInput.childrenInputs.add(index + 1 , parentInput.childrenInputs.remove(index));\r
+                    nextInput = parentInput.childrenInputs.get(index).nextInput;\r
+                    parentInput.childrenInputs.get(index).nextInput = this;\r
+                }\r
+            }\r
+        }\r
+\r
+        public void addColumn(InputData column) {\r
+            if (columns == null) {\r
+                columns = new ArrayList<InputData>(1);\r
+            }\r
+            columns.add(column);\r
+        }\r
+        \r
+        public List<InputLine> getNextInputs(Map<InputLine, Integer> countMap) {\r
+            List<InputLine> nextInputs = new ArrayList<InputLine>();\r
+            InputLine next = nextInput;\r
+            while (next != null) {\r
+                nextInputs.add(next);\r
+                if (next.cardinality.min > 0) {\r
+                    return nextInputs;\r
+                }\r
+                next = next.nextInput;\r
+            }\r
+            if (parentInput != null && parentInput.level > 0) {\r
+                int parentCount = countMap.get(parentInput);\r
+                if (parentCount < parentInput.getMaxCount()) {\r
+                    nextInputs.add(parentInput);\r
+                }\r
+                if (parentCount < parentInput.getMinCount()) {\r
+                    return nextInputs;\r
+                }\r
+                nextInputs.addAll(parentInput.getNextInputs(countMap));\r
+            }\r
+            return nextInputs;\r
+        }\r
+        \r
+        public int getMinCount() {\r
+            return cardinality.min;\r
+        }\r
+        \r
+        public int getMaxCount() {\r
+            return cardinality.max;\r
+        }\r
+\r
+        @Override\r
+        public String toString() {\r
+            return regex + " " + cardinality;\r
+        }\r
+        \r
+    }\r
+\r
+    public static class InputData {\r
+        public String name;\r
+        public int action;\r
+        public String format;\r
+        \r
+        public InputData() {};\r
+        \r
+        public InputData(String name, int action, String format) {\r
+            this.name = name;\r
+            this.action = action;\r
+            this.format = format;\r
+        }\r
+        \r
+        public InputData(String name, int action) {\r
+            this.name = name;\r
+            this.action = action;\r
+        }\r
+    }\r
+\r
+    public static class Cardinality {\r
+        public final static int INF = Integer.MAX_VALUE;\r
+        public final static Cardinality ONE = new Cardinality(1, 1);\r
+        public final static Cardinality ONE_OR_MORE = new Cardinality(1, INF);\r
+        public final static Cardinality ZERO_OR_ONE = new Cardinality(0, 1);\r
+        public final static Cardinality ZERO_OR_MORE = new Cardinality(0, INF); \r
+        \r
+        private int min;\r
+        private int max;\r
+        \r
+        public Cardinality(int min, int max) {\r
+            this.min = min;\r
+            this.max = max;\r
+        }\r
+\r
+        @Override\r
+        public String toString() {\r
+            return "(" + (min >= 0 ? min : "?") + "," + (max == INF ? "\u221E" : (max >= 0 ? max : "?")) + ")";\r
+        }\r
+\r
+        @Override\r
+        public boolean equals(Object obj) {\r
+            if (!(obj instanceof Cardinality)) return false;\r
+            Cardinality other = (Cardinality) obj;\r
+            return (this.min == other.min && this.max == other.max);\r
+        }\r
+    }\r
+    \r
+    public void save() {\r
+        save(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME);\r
+    }\r
+    \r
+    public void save(String path) {\r
+        try {\r
+            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();\r
+            DocumentBuilder db = dbf.newDocumentBuilder();\r
+            \r
+            // The following allows xml parsing without access to the dtd\r
+            EntityResolver resolver = new EntityResolver () {\r
+                public InputSource resolveEntity (String publicId, String systemId) {\r
+                    String empty = "";\r
+                    ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes());\r
+                    return new InputSource(bais);\r
+                }\r
+            };\r
+            db.setEntityResolver(resolver);\r
+\r
+            // The following catches xml parsing exceptions\r
+            db.setErrorHandler(new ErrorHandler(){\r
+                public void error(SAXParseException saxparseexception) throws SAXException {}\r
+                public void warning(SAXParseException saxparseexception) throws SAXException {}\r
+                public void fatalError(SAXParseException saxparseexception) throws SAXException {\r
+                    throw saxparseexception;\r
+                }});\r
+            \r
+            Document doc = null;\r
+            File file = new File(path);\r
+            if (file.canRead()) {\r
+                doc = db.parse(file);\r
+                if (! doc.getDocumentElement().getNodeName().equals(CUSTOM_TXT_TRACE_DEFINITION_ROOT_ELEMENT)) {\r
+                    return;\r
+                }\r
+            } else {\r
+                doc = db.newDocument();\r
+                Node node = doc.createElement(CUSTOM_TXT_TRACE_DEFINITION_ROOT_ELEMENT);\r
+                doc.appendChild(node);\r
+            }\r
+\r
+            Element root = doc.getDocumentElement();\r
+            \r
+            NodeList nodeList = root.getChildNodes();\r
+            for (int i = 0; i < nodeList.getLength(); i++) {\r
+                Node node = nodeList.item(i);\r
+                if (node instanceof Element &&\r
+                        node.getNodeName().equals(DEFINITION_ELEMENT) &&\r
+                        definitionName.equals(((Element) node).getAttribute(NAME_ATTRIBUTE))) {\r
+                    root.removeChild(node);\r
+                }\r
+            }\r
+            Element definitionElement = doc.createElement(DEFINITION_ELEMENT);\r
+            root.appendChild(definitionElement);\r
+            definitionElement.setAttribute(NAME_ATTRIBUTE, definitionName);\r
+            \r
+            Element formatElement = doc.createElement(TIME_STAMP_OUTPUT_FORMAT_ELEMENT);\r
+            definitionElement.appendChild(formatElement);\r
+            formatElement.appendChild(doc.createTextNode(timeStampOutputFormat));\r
+\r
+            if (inputs != null) {\r
+                for (InputLine inputLine : inputs) {\r
+                    definitionElement.appendChild(createInputLineElement(inputLine, doc));\r
+                }\r
+            }\r
+\r
+            if (outputs != null) {\r
+                for (OutputColumn output : outputs) {\r
+                    Element outputColumnElement = doc.createElement(OUTPUT_COLUMN_ELEMENT);\r
+                    definitionElement.appendChild(outputColumnElement);\r
+                    outputColumnElement.setAttribute(NAME_ATTRIBUTE, output.name);\r
+                }\r
+            }\r
+            \r
+            Transformer transformer = TransformerFactory.newInstance().newTransformer();\r
+            transformer.setOutputProperty(OutputKeys.INDENT, "yes");\r
+\r
+            //initialize StreamResult with File object to save to file\r
+            StreamResult result = new StreamResult(new StringWriter());\r
+            DOMSource source = new DOMSource(doc);\r
+            transformer.transform(source, result);\r
+            String xmlString = result.getWriter().toString();\r
+            \r
+            FileWriter writer = new FileWriter(file);\r
+            writer.write(xmlString);\r
+            writer.close();\r
+        } catch (ParserConfigurationException e) {\r
+            e.printStackTrace();\r
+        } catch (TransformerConfigurationException e) {\r
+            e.printStackTrace();\r
+        } catch (TransformerFactoryConfigurationError e) {\r
+            e.printStackTrace();\r
+        } catch (TransformerException e) {\r
+            e.printStackTrace();\r
+        } catch (IOException e) {\r
+            e.printStackTrace();\r
+        } catch (SAXException e) {\r
+            e.printStackTrace();\r
+        }\r
+    }\r
+\r
+    private Element createInputLineElement(InputLine inputLine, Document doc) {\r
+        Element inputLineElement = doc.createElement(INPUT_LINE_ELEMENT);\r
+        \r
+        Element cardinalityElement = doc.createElement(CARDINALITY_ELEMENT);\r
+        inputLineElement.appendChild(cardinalityElement);\r
+        cardinalityElement.setAttribute(MIN_ATTRIBUTE, Integer.toString(inputLine.cardinality.min));\r
+        cardinalityElement.setAttribute(MAX_ATTRIBUTE, Integer.toString(inputLine.cardinality.max));\r
+        \r
+        Element regexElement = doc.createElement(REGEX_ELEMENT);\r
+        inputLineElement.appendChild(regexElement);\r
+        regexElement.appendChild(doc.createTextNode(inputLine.regex));\r
+\r
+        if (inputLine.columns != null) {\r
+            for (InputData inputData : inputLine.columns) {\r
+                Element inputDataElement = doc.createElement(INPUT_DATA_ELEMENT);\r
+                inputLineElement.appendChild(inputDataElement);\r
+                inputDataElement.setAttribute(NAME_ATTRIBUTE, inputData.name);\r
+                inputDataElement.setAttribute(ACTION_ATTRIBUTE, Integer.toString(inputData.action));\r
+                if (inputData.format != null) {\r
+                    inputDataElement.setAttribute(FORMAT_ATTRIBUTE, inputData.format);\r
+                }\r
+            }\r
+        }\r
+        \r
+        if (inputLine.childrenInputs != null) {\r
+            for (InputLine childInputLine : inputLine.childrenInputs) {\r
+                inputLineElement.appendChild(createInputLineElement(childInputLine, doc));\r
+            }\r
+        }\r
+        \r
+        return inputLineElement;\r
+    }\r
+    \r
+    public static CustomTxtTraceDefinition[] loadAll() {\r
+        return loadAll(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME);\r
+    }\r
+    \r
+    public static CustomTxtTraceDefinition[] loadAll(String path) {\r
+        try {\r
+            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();\r
+            DocumentBuilder db = dbf.newDocumentBuilder();\r
+\r
+            // The following allows xml parsing without access to the dtd\r
+            EntityResolver resolver = new EntityResolver () {\r
+                public InputSource resolveEntity (String publicId, String systemId) {\r
+                    String empty = "";\r
+                    ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes());\r
+                    return new InputSource(bais);\r
+                }\r
+            };\r
+            db.setEntityResolver(resolver);\r
+\r
+            // The following catches xml parsing exceptions\r
+            db.setErrorHandler(new ErrorHandler(){\r
+                public void error(SAXParseException saxparseexception) throws SAXException {}\r
+                public void warning(SAXParseException saxparseexception) throws SAXException {}\r
+                public void fatalError(SAXParseException saxparseexception) throws SAXException {\r
+                    throw saxparseexception;\r
+                }});\r
+\r
+            File file = new File(path);\r
+            if (!file.canRead()) {\r
+                return new CustomTxtTraceDefinition[0];\r
+            }\r
+            Document doc = db.parse(file);\r
+\r
+            Element root = doc.getDocumentElement();\r
+            if (! root.getNodeName().equals(CUSTOM_TXT_TRACE_DEFINITION_ROOT_ELEMENT)) {\r
+                return new CustomTxtTraceDefinition[0];\r
+            }\r
+\r
+            ArrayList<CustomTxtTraceDefinition> defList = new ArrayList<CustomTxtTraceDefinition>();\r
+            NodeList nodeList = root.getChildNodes();\r
+            for (int i = 0; i < nodeList.getLength(); i++) {\r
+                Node node = nodeList.item(i);\r
+                if (node instanceof Element && node.getNodeName().equals(DEFINITION_ELEMENT)) {\r
+                    CustomTxtTraceDefinition def = extractDefinition((Element) node);\r
+                    if (def != null) {\r
+                        defList.add(def);\r
+                    }\r
+                }\r
+            }\r
+            return defList.toArray(new CustomTxtTraceDefinition[0]);\r
+        } catch (ParserConfigurationException e) {\r
+            e.printStackTrace();\r
+        } catch (SAXException e) {\r
+            e.printStackTrace();\r
+        } catch (IOException e) {\r
+            e.printStackTrace();\r
+        }\r
+        return new CustomTxtTraceDefinition[0];\r
+    }\r
+\r
+    public static CustomTxtTraceDefinition load(String definitionName) {\r
+        try {\r
+            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();\r
+            DocumentBuilder db = dbf.newDocumentBuilder();\r
+\r
+            // The following allows xml parsing without access to the dtd\r
+            EntityResolver resolver = new EntityResolver () {\r
+                public InputSource resolveEntity (String publicId, String systemId) {\r
+                    String empty = "";\r
+                    ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes());\r
+                    return new InputSource(bais);\r
+                }\r
+            };\r
+            db.setEntityResolver(resolver);\r
+\r
+            // The following catches xml parsing exceptions\r
+            db.setErrorHandler(new ErrorHandler(){\r
+                public void error(SAXParseException saxparseexception) throws SAXException {}\r
+                public void warning(SAXParseException saxparseexception) throws SAXException {}\r
+                public void fatalError(SAXParseException saxparseexception) throws SAXException {\r
+                    throw saxparseexception;\r
+                }});\r
+\r
+            File file = new File(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME);\r
+            Document doc = db.parse(file);\r
+\r
+            Element root = doc.getDocumentElement();\r
+            if (! root.getNodeName().equals(CUSTOM_TXT_TRACE_DEFINITION_ROOT_ELEMENT)) {\r
+                return null;\r
+            }\r
+\r
+            NodeList nodeList = root.getChildNodes();\r
+            for (int i = 0; i < nodeList.getLength(); i++) {\r
+                Node node = nodeList.item(i);\r
+                if (node instanceof Element &&\r
+                        node.getNodeName().equals(DEFINITION_ELEMENT) &&\r
+                        definitionName.equals(((Element) node).getAttribute(NAME_ATTRIBUTE))) {\r
+                    return extractDefinition((Element) node);\r
+                }\r
+            }\r
+        } catch (ParserConfigurationException e) {\r
+            e.printStackTrace();\r
+        } catch (SAXException e) {\r
+            e.printStackTrace();\r
+        } catch (IOException e) {\r
+            e.printStackTrace();\r
+        }\r
+        return null;\r
+    }\r
+    \r
+    public static CustomTxtTraceDefinition extractDefinition(Element definitionElement) {\r
+        CustomTxtTraceDefinition def = new CustomTxtTraceDefinition();\r
+        \r
+        def.definitionName = definitionElement.getAttribute(NAME_ATTRIBUTE);\r
+        if (def.definitionName == null) return null;\r
+        \r
+        NodeList nodeList = definitionElement.getChildNodes();\r
+        for (int i = 0; i < nodeList.getLength(); i++) {\r
+            Node node = nodeList.item(i);\r
+            String nodeName = node.getNodeName();\r
+            if (nodeName.equals(TIME_STAMP_OUTPUT_FORMAT_ELEMENT)) {\r
+                Element formatElement = (Element) node;\r
+                def.timeStampOutputFormat = formatElement.getTextContent();\r
+            } else if (nodeName.equals(INPUT_LINE_ELEMENT)) {\r
+                InputLine inputLine = extractInputLine((Element) node);\r
+                if (inputLine != null) {\r
+                    def.inputs.add(inputLine);\r
+                }\r
+            } else if (nodeName.equals(OUTPUT_COLUMN_ELEMENT)) {\r
+                Element outputColumnElement = (Element) node;\r
+                OutputColumn outputColumn = new OutputColumn();\r
+                outputColumn.name = outputColumnElement.getAttribute(NAME_ATTRIBUTE);\r
+                def.outputs.add(outputColumn);\r
+            }\r
+        }\r
+        return def;\r
+    }\r
+\r
+    private static InputLine extractInputLine(Element inputLineElement) {\r
+        InputLine inputLine = new InputLine();\r
+        NodeList nodeList = inputLineElement.getChildNodes();\r
+        for (int i = 0; i < nodeList.getLength(); i++) {\r
+            Node node = nodeList.item(i);\r
+            String nodeName = node.getNodeName();\r
+            if (nodeName.equals(CARDINALITY_ELEMENT)) {\r
+                Element cardinalityElement = (Element) node;\r
+                try {\r
+                    int min = Integer.parseInt(cardinalityElement.getAttribute(MIN_ATTRIBUTE));\r
+                    int max = Integer.parseInt(cardinalityElement.getAttribute(MAX_ATTRIBUTE));\r
+                    inputLine.cardinality = new Cardinality(min, max);\r
+                } catch (NumberFormatException e) {\r
+                    return null;\r
+                }\r
+            } else if (nodeName.equals(REGEX_ELEMENT)) {\r
+                Element regexElement = (Element) node;\r
+                inputLine.regex = regexElement.getTextContent();\r
+            } else if (nodeName.equals(INPUT_DATA_ELEMENT)) {\r
+                Element inputDataElement = (Element) node;\r
+                InputData inputData = new InputData();\r
+                inputData.name = inputDataElement.getAttribute(NAME_ATTRIBUTE);\r
+                inputData.action = Integer.parseInt(inputDataElement.getAttribute(ACTION_ATTRIBUTE));\r
+                inputData.format = inputDataElement.getAttribute(FORMAT_ATTRIBUTE);\r
+                inputLine.addColumn(inputData);\r
+            } else if (nodeName.equals(INPUT_LINE_ELEMENT)) {\r
+                Element childInputLineElement = (Element) node;\r
+                InputLine childInputLine = extractInputLine(childInputLineElement);\r
+                if (childInputLine != null) {\r
+                    inputLine.addChild(childInputLine);\r
+                }\r
+            }\r
+        }\r
+        return inputLine;\r
+    }\r
+    \r
+    public static void delete(String definitionName) {\r
+        try {\r
+            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();\r
+            DocumentBuilder db = dbf.newDocumentBuilder();\r
+\r
+            // The following allows xml parsing without access to the dtd\r
+            EntityResolver resolver = new EntityResolver () {\r
+                public InputSource resolveEntity (String publicId, String systemId) {\r
+                    String empty = "";\r
+                    ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes());\r
+                    return new InputSource(bais);\r
+                }\r
+            };\r
+            db.setEntityResolver(resolver);\r
+\r
+            // The following catches xml parsing exceptions\r
+            db.setErrorHandler(new ErrorHandler(){\r
+                public void error(SAXParseException saxparseexception) throws SAXException {}\r
+                public void warning(SAXParseException saxparseexception) throws SAXException {}\r
+                public void fatalError(SAXParseException saxparseexception) throws SAXException {\r
+                    throw saxparseexception;\r
+                }});\r
+\r
+            File file = new File(CUSTOM_TXT_TRACE_DEFINITIONS_PATH_NAME);\r
+            Document doc = db.parse(file);\r
+\r
+            Element root = doc.getDocumentElement();\r
+            if (! root.getNodeName().equals(CUSTOM_TXT_TRACE_DEFINITION_ROOT_ELEMENT)) {\r
+                return;\r
+            }\r
+\r
+            NodeList nodeList = root.getChildNodes();\r
+            for (int i = 0; i < nodeList.getLength(); i++) {\r
+                Node node = nodeList.item(i);\r
+                if (node instanceof Element &&\r
+                        node.getNodeName().equals(DEFINITION_ELEMENT) &&\r
+                        definitionName.equals(((Element) node).getAttribute(NAME_ATTRIBUTE))) {\r
+                    root.removeChild(node);\r
+                }\r
+            }\r
+            \r
+            Transformer transformer = TransformerFactory.newInstance().newTransformer();\r
+            transformer.setOutputProperty(OutputKeys.INDENT, "yes");\r
+\r
+            //initialize StreamResult with File object to save to file\r
+            StreamResult result = new StreamResult(new StringWriter());\r
+            DOMSource source = new DOMSource(doc);\r
+            transformer.transform(source, result);\r
+            String xmlString = result.getWriter().toString();\r
+            \r
+            FileWriter writer = new FileWriter(file);\r
+            writer.write(xmlString);\r
+            writer.close();\r
+        } catch (ParserConfigurationException e) {\r
+            e.printStackTrace();\r
+        } catch (SAXException e) {\r
+            e.printStackTrace();\r
+        } catch (IOException e) {\r
+            e.printStackTrace();\r
+        } catch (TransformerConfigurationException e) {\r
+            e.printStackTrace();\r
+        } catch (TransformerFactoryConfigurationError e) {\r
+            e.printStackTrace();\r
+        } catch (TransformerException e) {\r
+            e.printStackTrace();\r
+        }\r
+    }\r
+}\r
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomXmlEvent.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomXmlEvent.java
new file mode 100644 (file)
index 0000000..bf2950a
--- /dev/null
@@ -0,0 +1,77 @@
+/*******************************************************************************\r
+ * Copyright (c) 2010 Ericsson\r
+ * \r
+ * All rights reserved. This program and the accompanying materials are\r
+ * made available under the terms of the Eclipse Public License v1.0 which\r
+ * accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ * \r
+ * Contributors:\r
+ *   Patrick Tasse - Initial API and implementation\r
+ *******************************************************************************/\r
+\r
+package org.eclipse.linuxtools.tmf.ui.parsers.custom;\r
+\r
+import org.eclipse.linuxtools.tmf.event.TmfEvent;\r
+import org.eclipse.linuxtools.tmf.event.TmfEventReference;\r
+import org.eclipse.linuxtools.tmf.event.TmfEventSource;\r
+import org.eclipse.linuxtools.tmf.event.TmfEventType;\r
+import org.eclipse.linuxtools.tmf.event.TmfTimestamp;\r
+\r
+public class CustomXmlEvent extends CustomEvent {\r
+\r
+    public CustomXmlEvent(CustomXmlTraceDefinition definition, TmfEvent other) {\r
+        super(definition, other);\r
+    }\r
+\r
+    public CustomXmlEvent(CustomXmlTraceDefinition definition, TmfTimestamp timestamp, TmfEventSource source, TmfEventType type, TmfEventReference reference) {\r
+        super(definition, timestamp, source, type, reference);\r
+    }\r
+\r
+    public CustomXmlEvent(CustomXmlTraceDefinition definition, TmfTimestamp originalTS, TmfTimestamp effectiveTS, TmfEventSource source, TmfEventType type, TmfEventReference reference) {\r
+        super(definition, originalTS, effectiveTS, source, type, reference);\r
+    }\r
+\r
+    public void parseInput(String value, String name, int inputAction, String inputFormat) {\r
+        if (value.length() == 0) {\r
+            return;\r
+        }\r
+        if (inputAction == CustomTraceDefinition.ACTION_SET) {\r
+            fData.put(name, value);\r
+            if (name.equals(CustomTraceDefinition.TAG_TIMESTAMP)) {\r
+                fData.put(TIMESTAMP_INPUT_FORMAT_KEY, inputFormat);\r
+            }\r
+        } else if (inputAction == CustomTraceDefinition.ACTION_APPEND) {\r
+            String s = fData.get(name);\r
+            if (s != null) {\r
+                fData.put(name, s + value);\r
+            } else {\r
+                fData.put(name, value);\r
+            }\r
+            if (name.equals(CustomTraceDefinition.TAG_TIMESTAMP)) {\r
+                String timeStampInputFormat = fData.get(TIMESTAMP_INPUT_FORMAT_KEY);\r
+                if (timeStampInputFormat != null) {\r
+                    fData.put(TIMESTAMP_INPUT_FORMAT_KEY, timeStampInputFormat + inputFormat);\r
+                } else {\r
+                    fData.put(TIMESTAMP_INPUT_FORMAT_KEY, inputFormat);\r
+                }\r
+            }\r
+        } else if (inputAction == CustomTraceDefinition.ACTION_APPEND_WITH_SEPARATOR) {\r
+            String s = fData.get(name);\r
+            if (s != null) {\r
+                fData.put(name, s + " | " + value);\r
+            } else {\r
+                fData.put(name, value);\r
+            }\r
+            if (name.equals(CustomTraceDefinition.TAG_TIMESTAMP)) {\r
+                String timeStampInputFormat = fData.get(TIMESTAMP_INPUT_FORMAT_KEY);\r
+                if (timeStampInputFormat != null) {\r
+                    fData.put(TIMESTAMP_INPUT_FORMAT_KEY, timeStampInputFormat + " | " + inputFormat);\r
+                } else {\r
+                    fData.put(TIMESTAMP_INPUT_FORMAT_KEY, inputFormat);\r
+                }\r
+            }\r
+        }\r
+    }\r
+\r
+}\r
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomXmlTrace.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomXmlTrace.java
new file mode 100644 (file)
index 0000000..ca4c593
--- /dev/null
@@ -0,0 +1,345 @@
+/*******************************************************************************\r
+ * Copyright (c) 2010 Ericsson\r
+ * \r
+ * All rights reserved. This program and the accompanying materials are\r
+ * made available under the terms of the Eclipse Public License v1.0 which\r
+ * accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ * \r
+ * Contributors:\r
+ *   Patrick Tasse - Initial API and implementation\r
+ *******************************************************************************/\r
+\r
+package org.eclipse.linuxtools.tmf.ui.parsers.custom;\r
+\r
+import java.io.ByteArrayInputStream;\r
+import java.io.File;\r
+import java.io.FileNotFoundException;\r
+import java.io.IOException;\r
+import java.io.RandomAccessFile;\r
+\r
+import javax.xml.parsers.DocumentBuilder;\r
+import javax.xml.parsers.DocumentBuilderFactory;\r
+import javax.xml.parsers.ParserConfigurationException;\r
+\r
+import org.eclipse.linuxtools.tmf.event.TmfEvent;\r
+import org.eclipse.linuxtools.tmf.event.TmfEventReference;\r
+import org.eclipse.linuxtools.tmf.event.TmfEventSource;\r
+import org.eclipse.linuxtools.tmf.event.TmfEventType;\r
+import org.eclipse.linuxtools.tmf.event.TmfTimestamp;\r
+import org.eclipse.linuxtools.tmf.trace.ITmfContext;\r
+import org.eclipse.linuxtools.tmf.trace.ITmfLocation;\r
+import org.eclipse.linuxtools.tmf.trace.ITmfTrace;\r
+import org.eclipse.linuxtools.tmf.trace.TmfContext;\r
+import org.eclipse.linuxtools.tmf.trace.TmfLocation;\r
+import org.eclipse.linuxtools.tmf.trace.TmfTrace;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomXmlTraceDefinition.InputAttribute;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomXmlTraceDefinition.InputElement;\r
+import org.w3c.dom.Document;\r
+import org.w3c.dom.Element;\r
+import org.w3c.dom.Node;\r
+import org.w3c.dom.NodeList;\r
+import org.xml.sax.EntityResolver;\r
+import org.xml.sax.ErrorHandler;\r
+import org.xml.sax.InputSource;\r
+import org.xml.sax.SAXException;\r
+import org.xml.sax.SAXParseException;\r
+\r
+public class CustomXmlTrace extends TmfTrace<CustomXmlEvent> {\r
+\r
+    private CustomXmlTraceDefinition fDefinition;\r
+    private InputElement fRecordInputElement;\r
+    \r
+    public CustomXmlTrace(String name, CustomXmlTraceDefinition definition, String path, int cacheSize) throws FileNotFoundException {\r
+        super(name, CustomXmlEvent.class, path, cacheSize);\r
+        fDefinition = definition;\r
+        fRecordInputElement = getRecordInputElement(fDefinition.rootInputElement);\r
+    }\r
+\r
+    @Override\r
+    public TmfContext seekLocation(ITmfLocation<?> location) {\r
+        //System.out.println(Thread.currentThread().getName() + "::" + getName() + " seekLocation(" + ((location == null || location.getLocation() == null) ? "null" : location) + ")");\r
+        //new Throwable().printStackTrace();\r
+        CustomXmlTraceContext context = new CustomXmlTraceContext(new TmfLocation<Long>((Long)null), ITmfContext.INITIAL_RANK);\r
+        if (!new File(getPath()).isFile()) {\r
+            return context;\r
+        }\r
+        try {\r
+            context.raFile = new RandomAccessFile(getPath(), "r");\r
+            if (location != null && location.getLocation() instanceof Long) {\r
+                context.raFile.seek((Long)location.getLocation());\r
+            }\r
+            \r
+            String line;\r
+            String recordElementStart = "<" + fRecordInputElement.elementName;\r
+            long rawPos = context.raFile.getFilePointer();\r
+            \r
+            while ((line = context.raFile.readLine()) != null) {\r
+                int idx = line.indexOf(recordElementStart); \r
+                if (idx != -1) {\r
+                    context.setLocation(new TmfLocation<Long>(rawPos + idx));\r
+                    return context;\r
+                }\r
+                rawPos = context.raFile.getFilePointer();\r
+            }\r
+            return context;\r
+        } catch (FileNotFoundException e) {\r
+            e.printStackTrace();\r
+            return context;\r
+        } catch (IOException e) {\r
+            e.printStackTrace();\r
+            return context;\r
+        }\r
+        \r
+    }\r
+\r
+    public ITmfTrace createTraceCopy() {\r
+        // TODO Auto-generated method stub\r
+        return null;\r
+    }\r
+    \r
+    @Override\r
+    public ITmfLocation<?> getCurrentLocation() {\r
+        return new TmfLocation<Object>(null);\r
+    }\r
+\r
+    @Override\r
+    public synchronized TmfEvent getNextEvent(TmfContext context) {\r
+        ITmfContext savedContext = context.clone();\r
+        TmfEvent event = parseEvent(context);\r
+        if (event != null) {\r
+            updateIndex(savedContext, savedContext.getRank(), event.getTimestamp());\r
+            context.updateRank(1);\r
+        }\r
+        return event;\r
+    }\r
+\r
+    @Override\r
+    public TmfEvent parseEvent(TmfContext tmfContext) {\r
+        //System.out.println(Thread.currentThread().getName() + ":: " + getName() + " parseEvent(" + tmfContext.getRank() + " @ " + (tmfContext.getLocation().getLocation() == null ? "null" : tmfContext.getLocation()));\r
+        if (!(tmfContext instanceof CustomXmlTraceContext)) {\r
+            return null;\r
+        }\r
+        \r
+        CustomXmlTraceContext context = (CustomXmlTraceContext) tmfContext;\r
+        if (!(context.getLocation().getLocation() instanceof Long)) {\r
+            return null;\r
+        }\r
+\r
+        synchronized (context.raFile) {\r
+            CustomXmlEvent event = null;\r
+            try {\r
+                if (context.raFile.getFilePointer() != (Long)context.getLocation().getLocation() + 1) {\r
+                    context.raFile.seek((Long)context.getLocation().getLocation() + 1); // +1 is for the <\r
+                }\r
+                StringBuffer elementBuffer = new StringBuffer("<");\r
+                readElement(elementBuffer, context.raFile);\r
+                Element element = parseElementBuffer(elementBuffer);\r
+                \r
+                event = extractEvent(element, fRecordInputElement);\r
+                \r
+                String line;\r
+                String recordElementStart = "<" + fRecordInputElement.elementName;\r
+                long rawPos = context.raFile.getFilePointer();\r
+                \r
+                while ((line = context.raFile.readLine()) != null) {\r
+                    int idx = line.indexOf(recordElementStart); \r
+                    if (idx != -1) {\r
+                        context.setLocation(new TmfLocation<Long>(rawPos + idx));\r
+                        return event;\r
+                    }\r
+                    rawPos = context.raFile.getFilePointer();\r
+                }\r
+            } catch (IOException e) {\r
+                e.printStackTrace();\r
+            }\r
+            context.setLocation(new TmfLocation<Long>((Long)null));\r
+            return event;\r
+        }\r
+    }\r
+\r
+    private Element parseElementBuffer(StringBuffer elementBuffer) {\r
+        try {\r
+            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();\r
+            DocumentBuilder db = dbf.newDocumentBuilder();\r
+\r
+            // The following allows xml parsing without access to the dtd\r
+            EntityResolver resolver = new EntityResolver () {\r
+                public InputSource resolveEntity (String publicId, String systemId) {\r
+                    String empty = "";\r
+                    ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes());\r
+                    return new InputSource(bais);\r
+                }\r
+            };\r
+            db.setEntityResolver(resolver);\r
+\r
+            // The following catches xml parsing exceptions\r
+            db.setErrorHandler(new ErrorHandler(){\r
+                public void error(SAXParseException saxparseexception) throws SAXException {}\r
+                public void warning(SAXParseException saxparseexception) throws SAXException {}\r
+                public void fatalError(SAXParseException saxparseexception) throws SAXException {\r
+                    throw saxparseexception;\r
+                }});\r
+            \r
+            Document doc = db.parse(new ByteArrayInputStream(elementBuffer.toString().getBytes()));\r
+            return doc.getDocumentElement();\r
+        } catch (ParserConfigurationException e) {\r
+            e.printStackTrace();\r
+        } catch (SAXException e) {\r
+            e.printStackTrace();\r
+        } catch (IOException e) {\r
+            e.printStackTrace();\r
+        }\r
+        return null;\r
+    }\r
+\r
+    private void readElement(StringBuffer buffer, RandomAccessFile raFile) {\r
+        try {\r
+            int numRead = 0;\r
+            boolean startTagClosed = false;\r
+            int i;\r
+            while ((i = raFile.read()) != -1) {\r
+                numRead++;\r
+                char c = (char)i;\r
+                buffer.append(c);\r
+                if (c == '"') {\r
+                    readQuote(buffer, raFile, '"');\r
+                } else if (c == '\'') {\r
+                    readQuote(buffer, raFile, '\'');\r
+                } else if (c == '<') {\r
+                    readElement(buffer, raFile);\r
+                } else if (c == '/' && numRead == 1) {\r
+                    break; // found "</"\r
+                } else if (c == '-' && numRead == 3 && buffer.substring(buffer.length() - 3, buffer.length() - 1).equals("!-")) {\r
+                    readComment(buffer, raFile); // found "<!--"\r
+                } else if (i == '>') {\r
+                    if (buffer.charAt(buffer.length() - 2) == '/') {\r
+                        break; // found "/>"\r
+                    } else if (startTagClosed) {\r
+                        break; // found "<...>...</...>"\r
+                    } else {\r
+                        startTagClosed = true; // found "<...>"\r
+                    }\r
+                }\r
+            }\r
+            return;\r
+        } catch (IOException e) {\r
+            return;\r
+        }\r
+    }\r
+\r
+    private void readQuote(StringBuffer buffer, RandomAccessFile raFile, char eq) {\r
+        try {\r
+            int i;\r
+            while ((i = raFile.read()) != -1) {\r
+                char c = (char)i;\r
+                buffer.append(c);\r
+                if (c == eq) {\r
+                    break; // found matching end-quote\r
+                }\r
+            }\r
+            return;\r
+        } catch (IOException e) {\r
+            return;\r
+        }\r
+    }\r
+\r
+    private void readComment(StringBuffer buffer, RandomAccessFile raFile) {\r
+        try {\r
+            int numRead = 0;\r
+            int i;\r
+            while ((i = raFile.read()) != -1) {\r
+                numRead++;\r
+                char c = (char)i;\r
+                buffer.append(c);\r
+                if (c == '>' && numRead >= 2 && buffer.substring(buffer.length() - 3, buffer.length() - 1).equals("--")) {\r
+                    break; // found "-->"\r
+                }\r
+            }\r
+            return;\r
+        } catch (IOException e) {\r
+            return;\r
+        }\r
+    }\r
+\r
+    public static StringBuffer parseElement(Element parentElement, StringBuffer buffer) {\r
+        NodeList nodeList = parentElement.getChildNodes();\r
+        String separator = null;\r
+        for (int i = 0; i < nodeList.getLength(); i++) {\r
+            Node node = nodeList.item(i);\r
+            if (node.getNodeType() == Node.ELEMENT_NODE) {\r
+                if (separator == null) {\r
+                    separator = " | ";\r
+                } else {\r
+                    buffer.append(separator);\r
+                }\r
+                Element element = (Element) node;\r
+                if (element.hasChildNodes() == false) {\r
+                    buffer.append(element.getNodeName());\r
+                } else if (element.getChildNodes().getLength() == 1 && element.getFirstChild().getNodeType() == Node.TEXT_NODE) {\r
+                    buffer.append(element.getNodeName() + ":" + element.getFirstChild().getNodeValue().trim());\r
+                } else {\r
+                    buffer.append(element.getNodeName());\r
+                    buffer.append(" [ ");\r
+                    parseElement(element, buffer);\r
+                    buffer.append(" ]");\r
+                }\r
+            } else if (node.getNodeType() == Node.TEXT_NODE) {\r
+                if (node.getNodeValue().trim().length() != 0) {\r
+                    buffer.append(node.getNodeValue().trim());\r
+                }\r
+            }\r
+        }\r
+        return buffer;\r
+    }\r
+\r
+    public InputElement getRecordInputElement(InputElement inputElement) {\r
+        if (inputElement.logEntry) {\r
+            return inputElement;\r
+        } else if (inputElement.childElements != null) {\r
+            for (InputElement childInputElement : inputElement.childElements) {\r
+                InputElement recordInputElement = getRecordInputElement(childInputElement);\r
+                if (recordInputElement != null) {\r
+                    return recordInputElement;\r
+                }\r
+            }\r
+        }\r
+        return null;\r
+    }\r
+    \r
+    public CustomXmlEvent extractEvent(Element element, InputElement inputElement) {\r
+        CustomXmlEvent event = new CustomXmlEvent(fDefinition, TmfTimestamp.Zero, new TmfEventSource(""), new TmfEventType(fDefinition.definitionName, new String[0]), new TmfEventReference(""));\r
+        parseElement(element, event, inputElement);\r
+        return event;\r
+    }\r
+    \r
+    private void parseElement(Element element, CustomXmlEvent event, InputElement inputElement) {\r
+        if (inputElement.inputName != null && !inputElement.inputName.equals(CustomXmlTraceDefinition.TAG_IGNORE)) {\r
+            event.parseInput(parseElement(element, new StringBuffer()).toString(), inputElement.inputName, inputElement.inputAction, inputElement.inputFormat);\r
+        }\r
+        if (inputElement.attributes != null) {\r
+            for (InputAttribute attribute : inputElement.attributes) {\r
+                event.parseInput(element.getAttribute(attribute.attributeName), attribute.inputName, attribute.inputAction, attribute.inputFormat);\r
+            }\r
+        }\r
+        NodeList childNodes = element.getChildNodes();\r
+        if (inputElement.childElements != null) {\r
+            for (int i = 0; i < childNodes.getLength(); i++) {\r
+                Node node = childNodes.item(i);\r
+                if (node instanceof Element) {\r
+                    for (InputElement child : inputElement.childElements) {\r
+                        if (node.getNodeName().equals(child.elementName)) {\r
+                            parseElement((Element) node, event, child);\r
+                            break;\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+        }\r
+        return;\r
+    }\r
+\r
+    public CustomTraceDefinition getDefinition() {\r
+        return fDefinition;\r
+    }\r
+}\r
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomXmlTraceContext.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomXmlTraceContext.java
new file mode 100644 (file)
index 0000000..0dd3df5
--- /dev/null
@@ -0,0 +1,26 @@
+/*******************************************************************************\r
+ * Copyright (c) 2010 Ericsson\r
+ * \r
+ * All rights reserved. This program and the accompanying materials are\r
+ * made available under the terms of the Eclipse Public License v1.0 which\r
+ * accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ * \r
+ * Contributors:\r
+ *   Patrick Tasse - Initial API and implementation\r
+ *******************************************************************************/\r
+\r
+package org.eclipse.linuxtools.tmf.ui.parsers.custom;\r
+\r
+import java.io.RandomAccessFile;\r
+\r
+import org.eclipse.linuxtools.tmf.trace.ITmfLocation;\r
+import org.eclipse.linuxtools.tmf.trace.TmfContext;\r
+\r
+public class CustomXmlTraceContext extends TmfContext {\r
+    public RandomAccessFile raFile;\r
+\r
+    public CustomXmlTraceContext(ITmfLocation<?> location, long rank) {\r
+        super(location, rank);\r
+    }\r
+}
\ No newline at end of file
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomXmlTraceDefinition.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/parsers/custom/CustomXmlTraceDefinition.java
new file mode 100644 (file)
index 0000000..fb9f036
--- /dev/null
@@ -0,0 +1,559 @@
+/*******************************************************************************\r
+ * Copyright (c) 2010 Ericsson\r
+ * \r
+ * All rights reserved. This program and the accompanying materials are\r
+ * made available under the terms of the Eclipse Public License v1.0 which\r
+ * accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ * \r
+ * Contributors:\r
+ *   Patrick Tasse - Initial API and implementation\r
+ *******************************************************************************/\r
+\r
+package org.eclipse.linuxtools.tmf.ui.parsers.custom;\r
+\r
+import java.io.ByteArrayInputStream;\r
+import java.io.File;\r
+import java.io.FileWriter;\r
+import java.io.IOException;\r
+import java.io.StringWriter;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import javax.xml.parsers.DocumentBuilder;\r
+import javax.xml.parsers.DocumentBuilderFactory;\r
+import javax.xml.parsers.ParserConfigurationException;\r
+import javax.xml.transform.OutputKeys;\r
+import javax.xml.transform.Transformer;\r
+import javax.xml.transform.TransformerConfigurationException;\r
+import javax.xml.transform.TransformerException;\r
+import javax.xml.transform.TransformerFactory;\r
+import javax.xml.transform.TransformerFactoryConfigurationError;\r
+import javax.xml.transform.dom.DOMSource;\r
+import javax.xml.transform.stream.StreamResult;\r
+\r
+import org.eclipse.linuxtools.tmf.ui.TmfUiPlugin;\r
+import org.w3c.dom.Document;\r
+import org.w3c.dom.Element;\r
+import org.w3c.dom.Node;\r
+import org.w3c.dom.NodeList;\r
+import org.xml.sax.EntityResolver;\r
+import org.xml.sax.ErrorHandler;\r
+import org.xml.sax.InputSource;\r
+import org.xml.sax.SAXException;\r
+import org.xml.sax.SAXParseException;\r
+\r
+public class CustomXmlTraceDefinition extends CustomTraceDefinition {\r
+\r
+    protected static final String CUSTOM_XML_TRACE_DEFINITIONS_FILE_NAME = "custom_xml_parsers.xml";\r
+    protected static final String CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME =\r
+        TmfUiPlugin.getDefault().getStateLocation().addTrailingSeparator().append(CUSTOM_XML_TRACE_DEFINITIONS_FILE_NAME).toString();\r
+\r
+    public static final String TAG_IGNORE = "Ignore";\r
+\r
+    private static final String CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT = "CustomXMLTraceDefinitionList";\r
+    private static final String DEFINITION_ELEMENT = "Definition";\r
+    private static final String NAME_ATTRIBUTE = "name";\r
+    private static final String LOG_ENTRY_ATTRIBUTE = "logentry";\r
+    private static final String TIME_STAMP_OUTPUT_FORMAT_ELEMENT = "TimeStampOutputFormat";\r
+    private static final String INPUT_ELEMENT_ELEMENT = "InputElement";\r
+    private static final String ATTRIBUTE_ELEMENT = "Attribute";\r
+    private static final String INPUT_DATA_ELEMENT = "InputData";\r
+    private static final String ACTION_ATTRIBUTE = "action";\r
+    private static final String FORMAT_ATTRIBUTE = "format";\r
+    private static final String OUTPUT_COLUMN_ELEMENT = "OutputColumn";\r
+    \r
+    public InputElement rootInputElement;\r
+\r
+    public CustomXmlTraceDefinition() {\r
+        this("", null, new ArrayList<OutputColumn>(), "");\r
+    };\r
+\r
+    public CustomXmlTraceDefinition(String logtype, InputElement rootElement, List<OutputColumn> outputs, String timeStampOutputFormat) {\r
+        this.definitionName = logtype;\r
+        this.rootInputElement = rootElement;\r
+        this.outputs = outputs;\r
+        this.timeStampOutputFormat = timeStampOutputFormat;\r
+    }\r
+\r
+    public static class InputElement {\r
+        public String elementName;\r
+        public boolean logEntry;\r
+        public String inputName;\r
+        public int inputAction;\r
+        public String inputFormat;\r
+        public List<InputAttribute> attributes;\r
+        public InputElement parentElement;\r
+        public InputElement nextElement;\r
+        public List<InputElement> childElements;\r
+        \r
+        public InputElement() {};\r
+        \r
+        public InputElement(String elementName, boolean logEntry, String inputName, int inputAction, String inputFormat, List<InputAttribute> attributes) {\r
+            this.elementName = elementName;\r
+            this.logEntry = logEntry;\r
+            this.inputName = inputName;\r
+            this.inputAction = inputAction;\r
+            this.inputFormat = inputFormat;\r
+            this.attributes = attributes;\r
+        }\r
+        \r
+        public void addAttribute(InputAttribute attribute) {\r
+            if (attributes == null) {\r
+                attributes = new ArrayList<InputAttribute>(1);\r
+            }\r
+            attributes.add(attribute);\r
+        }\r
+\r
+        public void addChild(InputElement input) {\r
+            if (childElements == null) {\r
+                childElements = new ArrayList<InputElement>(1);\r
+            } else if (childElements.size() > 0) {\r
+                InputElement last = childElements.get(childElements.size() - 1);\r
+                last.nextElement = input;\r
+            }\r
+            childElements.add(input);\r
+            input.parentElement = this;\r
+        }\r
+\r
+        public void addNext(InputElement input) {\r
+            if (parentElement != null) {\r
+                int index = parentElement.childElements.indexOf(this);\r
+                parentElement.childElements.add(index + 1, input);\r
+                InputElement next = nextElement;\r
+                nextElement = input;\r
+                input.nextElement = next;\r
+            }\r
+            input.parentElement = this.parentElement;\r
+        }\r
+\r
+        public void moveUp() {\r
+            if (parentElement != null) {\r
+                int index = parentElement.childElements.indexOf(this);\r
+                if (index > 0) {\r
+                    parentElement.childElements.add(index - 1 , parentElement.childElements.remove(index));\r
+                    parentElement.childElements.get(index).nextElement = nextElement;\r
+                    nextElement = parentElement.childElements.get(index);\r
+                }\r
+            }\r
+        }\r
+\r
+        public void moveDown() {\r
+            if (parentElement != null) {\r
+                int index = parentElement.childElements.indexOf(this);\r
+                if (index < parentElement.childElements.size() - 1) {\r
+                    parentElement.childElements.add(index + 1 , parentElement.childElements.remove(index));\r
+                    nextElement = parentElement.childElements.get(index).nextElement;\r
+                    parentElement.childElements.get(index).nextElement = this;\r
+                }\r
+            }\r
+        }\r
+\r
+    }\r
+\r
+    public static class InputAttribute {\r
+        public String attributeName;\r
+        public String inputName;\r
+        public int inputAction;\r
+        public String inputFormat;\r
+        \r
+        public InputAttribute() {};\r
+        \r
+        public InputAttribute(String attributeName, String inputName, int inputAction, String inputFormat) {\r
+            this.attributeName = attributeName;\r
+            this.inputName = inputName;\r
+            this.inputAction = inputAction;\r
+            this.inputFormat = inputFormat;\r
+        }\r
+    }\r
+\r
+    public void save() {\r
+        save(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME);\r
+    }\r
+    \r
+    public void save(String path) {\r
+        try {\r
+            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();\r
+            DocumentBuilder db = dbf.newDocumentBuilder();\r
+            \r
+            // The following allows xml parsing without access to the dtd\r
+            EntityResolver resolver = new EntityResolver () {\r
+                public InputSource resolveEntity (String publicId, String systemId) {\r
+                    String empty = "";\r
+                    ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes());\r
+                    return new InputSource(bais);\r
+                }\r
+            };\r
+            db.setEntityResolver(resolver);\r
+\r
+            // The following catches xml parsing exceptions\r
+            db.setErrorHandler(new ErrorHandler(){\r
+                public void error(SAXParseException saxparseexception) throws SAXException {}\r
+                public void warning(SAXParseException saxparseexception) throws SAXException {}\r
+                public void fatalError(SAXParseException saxparseexception) throws SAXException {\r
+                    throw saxparseexception;\r
+                }});\r
+            \r
+            Document doc = null;\r
+            File file = new File(path);\r
+            if (file.canRead()) {\r
+                doc = db.parse(file);\r
+                if (! doc.getDocumentElement().getNodeName().equals(CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT)) {\r
+                    return;\r
+                }\r
+            } else {\r
+                doc = db.newDocument();\r
+                Node node = doc.createElement(CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT);\r
+                doc.appendChild(node);\r
+            }\r
+\r
+            Element root = doc.getDocumentElement();\r
+            \r
+            NodeList nodeList = root.getChildNodes();\r
+            for (int i = 0; i < nodeList.getLength(); i++) {\r
+                Node node = nodeList.item(i);\r
+                if (node instanceof Element &&\r
+                        node.getNodeName().equals(DEFINITION_ELEMENT) &&\r
+                        definitionName.equals(((Element) node).getAttribute(NAME_ATTRIBUTE))) {\r
+                    root.removeChild(node);\r
+                }\r
+            }\r
+            Element definitionElement = doc.createElement(DEFINITION_ELEMENT);\r
+            root.appendChild(definitionElement);\r
+            definitionElement.setAttribute(NAME_ATTRIBUTE, definitionName);\r
+            \r
+            Element formatElement = doc.createElement(TIME_STAMP_OUTPUT_FORMAT_ELEMENT);\r
+            definitionElement.appendChild(formatElement);\r
+            formatElement.appendChild(doc.createTextNode(timeStampOutputFormat));\r
+\r
+            if (rootInputElement != null) {\r
+                definitionElement.appendChild(createInputElementElement(rootInputElement, doc));\r
+            }\r
+\r
+            if (outputs != null) {\r
+                for (OutputColumn output : outputs) {\r
+                    Element outputColumnElement = doc.createElement(OUTPUT_COLUMN_ELEMENT);\r
+                    definitionElement.appendChild(outputColumnElement);\r
+                    outputColumnElement.setAttribute(NAME_ATTRIBUTE, output.name);\r
+                }\r
+            }\r
+            \r
+            Transformer transformer = TransformerFactory.newInstance().newTransformer();\r
+            transformer.setOutputProperty(OutputKeys.INDENT, "yes");\r
+\r
+            //initialize StreamResult with File object to save to file\r
+            StreamResult result = new StreamResult(new StringWriter());\r
+            DOMSource source = new DOMSource(doc);\r
+            transformer.transform(source, result);\r
+            String xmlString = result.getWriter().toString();\r
+            \r
+            FileWriter writer = new FileWriter(file);\r
+            writer.write(xmlString);\r
+            writer.close();\r
+        } catch (ParserConfigurationException e) {\r
+            e.printStackTrace();\r
+        } catch (TransformerConfigurationException e) {\r
+            e.printStackTrace();\r
+        } catch (TransformerFactoryConfigurationError e) {\r
+            e.printStackTrace();\r
+        } catch (TransformerException e) {\r
+            e.printStackTrace();\r
+        } catch (IOException e) {\r
+            e.printStackTrace();\r
+        } catch (SAXException e) {\r
+            e.printStackTrace();\r
+        }\r
+    }\r
+    \r
+    private Element createInputElementElement(InputElement inputElement, Document doc) {\r
+        Element inputElementElement = doc.createElement(INPUT_ELEMENT_ELEMENT);\r
+        inputElementElement.setAttribute(NAME_ATTRIBUTE, inputElement.elementName);\r
+        \r
+        if (inputElement.logEntry) {\r
+            inputElementElement.setAttribute(LOG_ENTRY_ATTRIBUTE, Boolean.toString(inputElement.logEntry));\r
+        }\r
+\r
+        if (inputElement.parentElement != null) {\r
+            Element inputDataElement = doc.createElement(INPUT_DATA_ELEMENT);\r
+            inputElementElement.appendChild(inputDataElement);\r
+            inputDataElement.setAttribute(NAME_ATTRIBUTE, inputElement.inputName);\r
+            inputDataElement.setAttribute(ACTION_ATTRIBUTE, Integer.toString(inputElement.inputAction));\r
+            if (inputElement.inputFormat != null) {\r
+                inputDataElement.setAttribute(FORMAT_ATTRIBUTE, inputElement.inputFormat);\r
+            }\r
+        }\r
+\r
+        if (inputElement.attributes != null) {\r
+            for (InputAttribute attribute : inputElement.attributes) {\r
+                Element inputAttributeElement = doc.createElement(ATTRIBUTE_ELEMENT);\r
+                inputElementElement.appendChild(inputAttributeElement);\r
+                inputAttributeElement.setAttribute(NAME_ATTRIBUTE, attribute.attributeName);\r
+                Element inputDataElement = doc.createElement(INPUT_DATA_ELEMENT);\r
+                inputAttributeElement.appendChild(inputDataElement);\r
+                inputDataElement.setAttribute(NAME_ATTRIBUTE, attribute.inputName);\r
+                inputDataElement.setAttribute(ACTION_ATTRIBUTE, Integer.toString(attribute.inputAction));\r
+                if (attribute.inputFormat != null) {\r
+                    inputDataElement.setAttribute(FORMAT_ATTRIBUTE, attribute.inputFormat);\r
+                }\r
+            }\r
+        }\r
+        \r
+        if (inputElement.childElements != null) {\r
+            for (InputElement childInputElement : inputElement.childElements) {\r
+                inputElementElement.appendChild(createInputElementElement(childInputElement, doc));\r
+            }\r
+        }\r
+        \r
+        return inputElementElement;\r
+    }\r
+    \r
+    public static CustomXmlTraceDefinition[] loadAll() {\r
+        return loadAll(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME);\r
+    }\r
+    \r
+    public static CustomXmlTraceDefinition[] loadAll(String path) {\r
+        try {\r
+            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();\r
+            DocumentBuilder db = dbf.newDocumentBuilder();\r
+\r
+            // The following allows xml parsing without access to the dtd\r
+            EntityResolver resolver = new EntityResolver () {\r
+                public InputSource resolveEntity (String publicId, String systemId) {\r
+                    String empty = "";\r
+                    ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes());\r
+                    return new InputSource(bais);\r
+                }\r
+            };\r
+            db.setEntityResolver(resolver);\r
+\r
+            // The following catches xml parsing exceptions\r
+            db.setErrorHandler(new ErrorHandler(){\r
+                public void error(SAXParseException saxparseexception) throws SAXException {}\r
+                public void warning(SAXParseException saxparseexception) throws SAXException {}\r
+                public void fatalError(SAXParseException saxparseexception) throws SAXException {\r
+                    throw saxparseexception;\r
+                }});\r
+\r
+            File file = new File(path);\r
+            if (!file.canRead()) {\r
+                return new CustomXmlTraceDefinition[0];\r
+            }\r
+            Document doc = db.parse(file);\r
+\r
+            Element root = doc.getDocumentElement();\r
+            if (! root.getNodeName().equals(CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT)) {\r
+                return new CustomXmlTraceDefinition[0];\r
+            }\r
+\r
+            ArrayList<CustomXmlTraceDefinition> defList = new ArrayList<CustomXmlTraceDefinition>();\r
+            NodeList nodeList = root.getChildNodes();\r
+            for (int i = 0; i < nodeList.getLength(); i++) {\r
+                Node node = nodeList.item(i);\r
+                if (node instanceof Element && node.getNodeName().equals(DEFINITION_ELEMENT)) {\r
+                    CustomXmlTraceDefinition def = extractDefinition((Element) node);\r
+                    if (def != null) {\r
+                        defList.add(def);\r
+                    }\r
+                }\r
+            }\r
+            return defList.toArray(new CustomXmlTraceDefinition[0]);\r
+        } catch (ParserConfigurationException e) {\r
+            e.printStackTrace();\r
+        } catch (SAXException e) {\r
+            e.printStackTrace();\r
+        } catch (IOException e) {\r
+            e.printStackTrace();\r
+        }\r
+        return new CustomXmlTraceDefinition[0];\r
+    }\r
+\r
+    public static CustomXmlTraceDefinition load(String definitionName) {\r
+        try {\r
+            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();\r
+            DocumentBuilder db = dbf.newDocumentBuilder();\r
+\r
+            // The following allows xml parsing without access to the dtd\r
+            EntityResolver resolver = new EntityResolver () {\r
+                public InputSource resolveEntity (String publicId, String systemId) {\r
+                    String empty = "";\r
+                    ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes());\r
+                    return new InputSource(bais);\r
+                }\r
+            };\r
+            db.setEntityResolver(resolver);\r
+\r
+            // The following catches xml parsing exceptions\r
+            db.setErrorHandler(new ErrorHandler(){\r
+                public void error(SAXParseException saxparseexception) throws SAXException {}\r
+                public void warning(SAXParseException saxparseexception) throws SAXException {}\r
+                public void fatalError(SAXParseException saxparseexception) throws SAXException {\r
+                    throw saxparseexception;\r
+                }});\r
+\r
+            File file = new File(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME);\r
+            Document doc = db.parse(file);\r
+\r
+            Element root = doc.getDocumentElement();\r
+            if (! root.getNodeName().equals(CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT)) {\r
+                return null;\r
+            }\r
+\r
+            NodeList nodeList = root.getChildNodes();\r
+            for (int i = 0; i < nodeList.getLength(); i++) {\r
+                Node node = nodeList.item(i);\r
+                if (node instanceof Element &&\r
+                        node.getNodeName().equals(DEFINITION_ELEMENT) &&\r
+                        definitionName.equals(((Element) node).getAttribute(NAME_ATTRIBUTE))) {\r
+                    return extractDefinition((Element) node);\r
+                }\r
+            }\r
+        } catch (ParserConfigurationException e) {\r
+            e.printStackTrace();\r
+        } catch (SAXException e) {\r
+            e.printStackTrace();\r
+        } catch (IOException e) {\r
+            e.printStackTrace();\r
+        }\r
+        return null;\r
+    }\r
+    \r
+    public static CustomXmlTraceDefinition extractDefinition(Element definitionElement) {\r
+        CustomXmlTraceDefinition def = new CustomXmlTraceDefinition();\r
+        \r
+        def.definitionName = definitionElement.getAttribute(NAME_ATTRIBUTE);\r
+        if (def.definitionName == null) return null;\r
+        \r
+        NodeList nodeList = definitionElement.getChildNodes();\r
+        for (int i = 0; i < nodeList.getLength(); i++) {\r
+            Node node = nodeList.item(i);\r
+            String nodeName = node.getNodeName();\r
+            if (nodeName.equals(TIME_STAMP_OUTPUT_FORMAT_ELEMENT)) {\r
+                Element formatElement = (Element) node;\r
+                def.timeStampOutputFormat = formatElement.getTextContent();\r
+            } else if (nodeName.equals(INPUT_ELEMENT_ELEMENT)) {\r
+                InputElement inputElement = extractInputElement((Element) node);\r
+                if (inputElement != null) {\r
+                    if (def.rootInputElement == null) {\r
+                        def.rootInputElement = inputElement;\r
+                    } else {\r
+                        return null;\r
+                    }\r
+                }\r
+            } else if (nodeName.equals(OUTPUT_COLUMN_ELEMENT)) {\r
+                Element outputColumnElement = (Element) node;\r
+                OutputColumn outputColumn = new OutputColumn();\r
+                outputColumn.name = outputColumnElement.getAttribute(NAME_ATTRIBUTE);\r
+                def.outputs.add(outputColumn);\r
+            }\r
+        }\r
+        return def;\r
+    }\r
+\r
+    private static InputElement extractInputElement(Element inputElementElement) {\r
+        InputElement inputElement = new InputElement();\r
+        inputElement.elementName = inputElementElement.getAttribute(NAME_ATTRIBUTE);\r
+        inputElement.logEntry = (Boolean.toString(true).equals(inputElementElement.getAttribute(LOG_ENTRY_ATTRIBUTE))) ? true : false;\r
+        NodeList nodeList = inputElementElement.getChildNodes();\r
+        for (int i = 0; i < nodeList.getLength(); i++) {\r
+            Node node = nodeList.item(i);\r
+            String nodeName = node.getNodeName();\r
+            if (nodeName.equals(INPUT_DATA_ELEMENT)) {\r
+                Element inputDataElement = (Element) node;\r
+                inputElement.inputName = inputDataElement.getAttribute(NAME_ATTRIBUTE);\r
+                inputElement.inputAction = Integer.parseInt(inputDataElement.getAttribute(ACTION_ATTRIBUTE));\r
+                inputElement.inputFormat = inputDataElement.getAttribute(FORMAT_ATTRIBUTE);\r
+            } else if (nodeName.equals(ATTRIBUTE_ELEMENT)) {\r
+                Element attributeElement = (Element) node;\r
+                InputAttribute attribute = new InputAttribute();\r
+                attribute.attributeName = attributeElement.getAttribute(NAME_ATTRIBUTE);\r
+                NodeList attributeNodeList = attributeElement.getChildNodes();\r
+                for (int j = 0; j < attributeNodeList.getLength(); j++) {\r
+                    Node attributeNode = attributeNodeList.item(j);\r
+                    String attributeNodeName = attributeNode.getNodeName();\r
+                    if (attributeNodeName.equals(INPUT_DATA_ELEMENT)) {\r
+                        Element inputDataElement = (Element) attributeNode;\r
+                        attribute.inputName = inputDataElement.getAttribute(NAME_ATTRIBUTE);\r
+                        attribute.inputAction = Integer.parseInt(inputDataElement.getAttribute(ACTION_ATTRIBUTE));\r
+                        attribute.inputFormat = inputDataElement.getAttribute(FORMAT_ATTRIBUTE);\r
+                    }\r
+                }\r
+                inputElement.addAttribute(attribute);\r
+            } else if (nodeName.equals(INPUT_ELEMENT_ELEMENT)) {\r
+                Element childInputElementElement = (Element) node;\r
+                InputElement childInputElement = extractInputElement(childInputElementElement);\r
+                if (childInputElement != null) {\r
+                    inputElement.addChild(childInputElement);\r
+                }\r
+            }\r
+        }\r
+        return inputElement;\r
+    }\r
+    \r
+    public static void delete(String definitionName) {\r
+        try {\r
+            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();\r
+            DocumentBuilder db = dbf.newDocumentBuilder();\r
+\r
+            // The following allows xml parsing without access to the dtd\r
+            EntityResolver resolver = new EntityResolver () {\r
+                public InputSource resolveEntity (String publicId, String systemId) {\r
+                    String empty = "";\r
+                    ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes());\r
+                    return new InputSource(bais);\r
+                }\r
+            };\r
+            db.setEntityResolver(resolver);\r
+\r
+            // The following catches xml parsing exceptions\r
+            db.setErrorHandler(new ErrorHandler(){\r
+                public void error(SAXParseException saxparseexception) throws SAXException {}\r
+                public void warning(SAXParseException saxparseexception) throws SAXException {}\r
+                public void fatalError(SAXParseException saxparseexception) throws SAXException {\r
+                    throw saxparseexception;\r
+                }});\r
+\r
+            File file = new File(CUSTOM_XML_TRACE_DEFINITIONS_PATH_NAME);\r
+            Document doc = db.parse(file);\r
+\r
+            Element root = doc.getDocumentElement();\r
+            if (! root.getNodeName().equals(CUSTOM_XML_TRACE_DEFINITION_ROOT_ELEMENT)) {\r
+                return;\r
+            }\r
+\r
+            NodeList nodeList = root.getChildNodes();\r
+            for (int i = 0; i < nodeList.getLength(); i++) {\r
+                Node node = nodeList.item(i);\r
+                if (node instanceof Element &&\r
+                        node.getNodeName().equals(DEFINITION_ELEMENT) &&\r
+                        definitionName.equals(((Element) node).getAttribute(NAME_ATTRIBUTE))) {\r
+                    root.removeChild(node);\r
+                }\r
+            }\r
+            \r
+            Transformer transformer = TransformerFactory.newInstance().newTransformer();\r
+            transformer.setOutputProperty(OutputKeys.INDENT, "yes");\r
+\r
+            //initialize StreamResult with File object to save to file\r
+            StreamResult result = new StreamResult(new StringWriter());\r
+            DOMSource source = new DOMSource(doc);\r
+            transformer.transform(source, result);\r
+            String xmlString = result.getWriter().toString();\r
+            \r
+            FileWriter writer = new FileWriter(file);\r
+            writer.write(xmlString);\r
+            writer.close();\r
+        } catch (ParserConfigurationException e) {\r
+            e.printStackTrace();\r
+        } catch (SAXException e) {\r
+            e.printStackTrace();\r
+        } catch (IOException e) {\r
+            e.printStackTrace();\r
+        } catch (TransformerConfigurationException e) {\r
+            e.printStackTrace();\r
+        } catch (TransformerFactoryConfigurationError e) {\r
+            e.printStackTrace();\r
+        } catch (TransformerException e) {\r
+            e.printStackTrace();\r
+        }\r
+    }\r
+}\r
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/wizards/CustomTxtParserInputWizardPage.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/wizards/CustomTxtParserInputWizardPage.java
new file mode 100644 (file)
index 0000000..5bceafa
--- /dev/null
@@ -0,0 +1,1495 @@
+package org.eclipse.linuxtools.tmf.ui.wizards;\r
+\r
+import java.io.BufferedReader;\r
+import java.io.IOException;\r
+import java.io.InputStreamReader;\r
+import java.text.ParseException;\r
+import java.text.SimpleDateFormat;\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
+import java.util.Date;\r
+import java.util.HashMap;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Scanner;\r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+import java.util.regex.PatternSyntaxException;\r
+\r
+import org.eclipse.core.resources.IFile;\r
+import org.eclipse.core.runtime.CoreException;\r
+import org.eclipse.jface.viewers.ColumnLabelProvider;\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.eclipse.jface.viewers.ISelectionChangedListener;\r
+import org.eclipse.jface.viewers.IStructuredSelection;\r
+import org.eclipse.jface.viewers.ITreeContentProvider;\r
+import org.eclipse.jface.viewers.SelectionChangedEvent;\r
+import org.eclipse.jface.viewers.StructuredSelection;\r
+import org.eclipse.jface.viewers.TreeViewer;\r
+import org.eclipse.jface.viewers.Viewer;\r
+import org.eclipse.jface.wizard.WizardPage;\r
+import org.eclipse.linuxtools.tmf.ui.TmfUiPlugin;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomTxtTraceDefinition;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomTxtTraceDefinition.Cardinality;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomTxtTraceDefinition.InputData;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomTxtTraceDefinition.InputLine;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.browser.Browser;\r
+import org.eclipse.swt.browser.TitleEvent;\r
+import org.eclipse.swt.browser.TitleListener;\r
+import org.eclipse.swt.custom.SashForm;\r
+import org.eclipse.swt.custom.ScrolledComposite;\r
+import org.eclipse.swt.custom.StyleRange;\r
+import org.eclipse.swt.custom.StyledText;\r
+import org.eclipse.swt.events.ModifyEvent;\r
+import org.eclipse.swt.events.ModifyListener;\r
+import org.eclipse.swt.events.SelectionAdapter;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.events.SelectionListener;\r
+import org.eclipse.swt.events.VerifyEvent;\r
+import org.eclipse.swt.events.VerifyListener;\r
+import org.eclipse.swt.graphics.Color;\r
+import org.eclipse.swt.graphics.Font;\r
+import org.eclipse.swt.graphics.FontData;\r
+import org.eclipse.swt.graphics.Image;\r
+import org.eclipse.swt.layout.FillLayout;\r
+import org.eclipse.swt.layout.GridData;\r
+import org.eclipse.swt.layout.GridLayout;\r
+import org.eclipse.swt.widgets.Button;\r
+import org.eclipse.swt.widgets.Combo;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.swt.widgets.Group;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.eclipse.swt.widgets.Shell;\r
+import org.eclipse.swt.widgets.Text;\r
+\r
+public class CustomTxtParserInputWizardPage extends WizardPage {\r
+\r
+    private static final String DEFAULT_REGEX = "\\s*(.*\\S)";\r
+    private static final String DEFAULT_TIMESTAMP_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS";\r
+    private static final String SIMPLE_DATE_FORMAT_URL = "http://java.sun.com/javase/6/docs/api/java/text/SimpleDateFormat.html#skip-navbar_top";\r
+    private static final String PATTERN_URL = "http://java.sun.com/javase/6/docs/api/java/util/regex/Pattern.html#sum";\r
+    private static final Image lineImage = TmfUiPlugin.getDefault().getImageFromPath("/icons/line_icon.gif");\r
+    private static final Image addImage = TmfUiPlugin.getDefault().getImageFromPath("/icons/add_button.gif");\r
+    private static final Image addNextImage = TmfUiPlugin.getDefault().getImageFromPath("/icons/addnext_button.gif");\r
+    private static final Image addChildImage = TmfUiPlugin.getDefault().getImageFromPath("/icons/addchild_button.gif");\r
+    private static final Image deleteImage = TmfUiPlugin.getDefault().getImageFromPath("/icons/delete_button.gif");\r
+    private static final Image moveUpImage = TmfUiPlugin.getDefault().getImageFromPath("/icons/moveup_button.gif");\r
+    private static final Image moveDownImage = TmfUiPlugin.getDefault().getImageFromPath("/icons/movedown_button.gif");\r
+    private static final Image helpImage = TmfUiPlugin.getDefault().getImageFromPath("/icons/help_button.gif");\r
+    private static final Color COLOR_BLACK = Display.getCurrent().getSystemColor(SWT.COLOR_BLACK);\r
+    private static final Color COLOR_LIGHT_GREEN = new Color(Display.getDefault(), 192, 255, 192);\r
+    private static final Color COLOR_GREEN = Display.getCurrent().getSystemColor(SWT.COLOR_GREEN);\r
+    private static final Color COLOR_LIGHT_YELLOW = new Color(Display.getDefault(), 255, 255, 192);\r
+    private static final Color COLOR_YELLOW = Display.getCurrent().getSystemColor(SWT.COLOR_YELLOW);\r
+    private static final Color COLOR_LIGHT_MAGENTA = new Color(Display.getDefault(), 255, 192, 255);\r
+    private static final Color COLOR_MAGENTA = Display.getCurrent().getSystemColor(SWT.COLOR_MAGENTA);\r
+    private static final Color COLOR_LIGHT_RED = new Color(Display.getDefault(), 255, 192, 192);\r
+    private static final Color COLOR_TEXT_BACKGROUND = Display.getCurrent().getSystemColor(SWT.COLOR_WHITE);\r
+    private static final Color COLOR_WIDGET_BACKGROUND = Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);\r
+\r
+    private ISelection selection;\r
+    private CustomTxtTraceDefinition definition;\r
+    private String editDefinitionName;\r
+    private String defaultDescription;\r
+    private Line selectedLine;\r
+    private Composite container;\r
+    private Text logtypeText;\r
+    private Text timestampOutputFormatText;\r
+    private Text timestampPreviewText;\r
+    private ScrolledComposite treeScrolledComposite;\r
+    private ScrolledComposite lineScrolledComposite;\r
+    private TreeViewer treeViewer;\r
+    private Composite treeContainer;\r
+    private Composite lineContainer;\r
+    @SuppressWarnings("unused")\r
+       private Group addLineGroup;\r
+    private StyledText inputText;\r
+    private Font fixedFont;\r
+    private UpdateListener updateListener;\r
+    private Browser helpBrowser;\r
+\r
+    // variables used recursively through line traversal\r
+    @SuppressWarnings("unused")\r
+       private String timeStampValue;\r
+    private String timeStampFormat;\r
+    private boolean timestampFound;\r
+    \r
+    protected CustomTxtParserInputWizardPage(ISelection selection, CustomTxtTraceDefinition definition) {\r
+        super("CustomParserWizardPage");\r
+        if (definition == null) {\r
+            setTitle("New Custom Text Parser");\r
+            defaultDescription = "Create a new custom parser for text log files";\r
+        } else {\r
+            setTitle("Edit Custom Text Parser");\r
+            defaultDescription = "Edit an existing custom parser for text log files";\r
+        }\r
+        setDescription(defaultDescription);\r
+        this.selection = selection;\r
+        this.definition = definition;\r
+        if (definition != null) {\r
+            this.editDefinitionName = definition.definitionName;\r
+        }\r
+    }\r
+\r
+    public void createControl(Composite parent) {\r
+        container = new Composite(parent, SWT.NULL);\r
+        container.setLayout(new GridLayout());\r
+\r
+        updateListener = new UpdateListener();\r
+        \r
+        Composite headerComposite = new Composite(container, SWT.FILL);\r
+        GridLayout headerLayout = new GridLayout(5, false);\r
+        headerLayout.marginHeight = 0;\r
+        headerLayout.marginWidth = 0;\r
+        headerComposite.setLayout(headerLayout);\r
+        headerComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));\r
+        \r
+        Label logtypeLabel = new Label(headerComposite, SWT.NULL);\r
+        logtypeLabel.setText("Log type:");\r
+        \r
+        logtypeText = new Text(headerComposite, SWT.BORDER | SWT.SINGLE);\r
+        logtypeText.setLayoutData(new GridData(120, SWT.DEFAULT));\r
+        logtypeText.addModifyListener(updateListener);\r
+        \r
+        Label timestampFormatLabel = new Label(headerComposite, SWT.NULL);\r
+        timestampFormatLabel.setText("Time Stamp format:");\r
+        \r
+        timestampOutputFormatText = new Text(headerComposite, SWT.BORDER | SWT.SINGLE);\r
+        timestampOutputFormatText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));\r
+        timestampOutputFormatText.setText(DEFAULT_TIMESTAMP_FORMAT);\r
+        timestampOutputFormatText.addModifyListener(updateListener);\r
+\r
+        Button dateFormatHelpButton = new Button(headerComposite, SWT.PUSH);\r
+        dateFormatHelpButton.setImage(helpImage);\r
+        dateFormatHelpButton.setToolTipText("Date Format Help");\r
+        dateFormatHelpButton.addSelectionListener(new SelectionAdapter() {\r
+            public void widgetSelected(SelectionEvent e) {\r
+                openHelpShell(SIMPLE_DATE_FORMAT_URL);\r
+            }\r
+        });\r
+        \r
+        Label timestampPreviewLabel = new Label(headerComposite, SWT.NULL);\r
+        timestampPreviewLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 3, 1));\r
+        timestampPreviewLabel.setText("Preview:");\r
+        \r
+        timestampPreviewText = new Text(headerComposite, SWT.BORDER | SWT.SINGLE | SWT.READ_ONLY);\r
+        timestampPreviewText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));\r
+        timestampPreviewText.setText("*no matching timestamp*");\r
+\r
+        Composite buttonBar = new Composite(container, SWT.NONE);\r
+        GridLayout buttonBarLayout = new GridLayout(5, false);\r
+        buttonBarLayout.marginHeight = 0;\r
+        buttonBarLayout.marginWidth = 0;\r
+        buttonBar.setLayout(buttonBarLayout);\r
+        \r
+        Button removeButton = new Button(buttonBar, SWT.PUSH);\r
+        removeButton.setImage(deleteImage);\r
+        removeButton.setToolTipText("Remove line");\r
+        removeButton.addSelectionListener(new SelectionAdapter() {\r
+            public void widgetSelected(SelectionEvent e) {\r
+                if (treeViewer.getSelection().isEmpty() || selectedLine == null) return;\r
+                removeLine();\r
+                InputLine inputLine = (InputLine) ((IStructuredSelection) treeViewer.getSelection()).getFirstElement();\r
+                if (inputLine.parentInput == null) {\r
+                    definition.inputs.remove(inputLine);\r
+                } else {\r
+                    inputLine.parentInput.childrenInputs.remove(inputLine);\r
+                }\r
+                treeViewer.refresh();\r
+                validate();\r
+                updatePreviews();\r
+            }\r
+        });\r
+        Button addNextButton = new Button(buttonBar, SWT.PUSH);\r
+        addNextButton.setImage(addNextImage);\r
+        addNextButton.setToolTipText("Add next line");\r
+        addNextButton.addSelectionListener(new SelectionAdapter() {\r
+            public void widgetSelected(SelectionEvent e) {\r
+                InputLine inputLine = new InputLine(Cardinality.ZERO_OR_MORE, "", null);\r
+                if (((List<?>) treeViewer.getInput()).size() == 0) {\r
+                    definition.inputs.add(inputLine);\r
+                } else if (treeViewer.getSelection().isEmpty()) {\r
+                    return;\r
+                } else {\r
+                    InputLine previousInputLine = (InputLine) ((IStructuredSelection) treeViewer.getSelection()).getFirstElement();\r
+                    if (previousInputLine.parentInput == null) {\r
+                        for (int i = 0; i < definition.inputs.size(); i++) {\r
+                            if (definition.inputs.get(i).equals(previousInputLine)) {\r
+                                definition.inputs.add(i + 1, inputLine);\r
+                            }\r
+                        }\r
+                    } else {\r
+                        previousInputLine.addNext(inputLine);\r
+                    }\r
+                }\r
+                treeViewer.refresh();\r
+                treeViewer.setSelection(new StructuredSelection(inputLine), true);\r
+            }\r
+        });\r
+        Button addChildButton = new Button(buttonBar, SWT.PUSH);\r
+        addChildButton.setImage(addChildImage);\r
+        addChildButton.setToolTipText("Add child line");\r
+        addChildButton.addSelectionListener(new SelectionAdapter() {\r
+            public void widgetSelected(SelectionEvent e) {\r
+                InputLine inputLine = new InputLine(Cardinality.ZERO_OR_MORE, "", null);\r
+                if (((List<?>) treeViewer.getInput()).size() == 0) {\r
+                    definition.inputs.add(inputLine);\r
+                } else if (treeViewer.getSelection().isEmpty()) {\r
+                    return;\r
+                } else {\r
+                    InputLine parentInputLine = (InputLine) ((IStructuredSelection) treeViewer.getSelection()).getFirstElement();\r
+                    parentInputLine.addChild(inputLine);\r
+                }\r
+                treeViewer.refresh();\r
+                treeViewer.setSelection(new StructuredSelection(inputLine), true);\r
+            }\r
+        });\r
+        Button moveUpButton = new Button(buttonBar, SWT.PUSH);\r
+        moveUpButton.setImage(moveUpImage);\r
+        moveUpButton.setToolTipText("Move up");\r
+        moveUpButton.addSelectionListener(new SelectionAdapter() {\r
+            public void widgetSelected(SelectionEvent e) {\r
+                if (treeViewer.getSelection().isEmpty()) return;\r
+                InputLine inputLine = (InputLine) ((IStructuredSelection) treeViewer.getSelection()).getFirstElement();\r
+                if (inputLine.parentInput == null) {\r
+                    for (int i = 1; i < definition.inputs.size(); i++) {\r
+                        if (definition.inputs.get(i).equals(inputLine)) {\r
+                            definition.inputs.add(i - 1 , definition.inputs.remove(i));\r
+                            break;\r
+                        }\r
+                    }\r
+                } else {\r
+                    inputLine.moveUp();\r
+                }\r
+                treeViewer.refresh();\r
+                validate();\r
+                updatePreviews();\r
+            }\r
+        });\r
+        Button moveDownButton = new Button(buttonBar, SWT.PUSH);\r
+        moveDownButton.setImage(moveDownImage);\r
+        moveDownButton.setToolTipText("Move down");\r
+        moveDownButton.addSelectionListener(new SelectionAdapter() {\r
+            public void widgetSelected(SelectionEvent e) {\r
+                if (treeViewer.getSelection().isEmpty()) return;\r
+                InputLine inputLine = (InputLine) ((IStructuredSelection) treeViewer.getSelection()).getFirstElement();\r
+                if (inputLine.parentInput == null) {\r
+                    for (int i = 0; i < definition.inputs.size() - 1; i++) {\r
+                        if (definition.inputs.get(i).equals(inputLine)) {\r
+                            definition.inputs.add(i + 1 , definition.inputs.remove(i));\r
+                            break;\r
+                        }\r
+                    }\r
+                } else {\r
+                    inputLine.moveDown();\r
+                }\r
+                treeViewer.refresh();\r
+                validate();\r
+                updatePreviews();\r
+            }\r
+        });\r
+        \r
+        SashForm vSash = new SashForm(container, SWT.VERTICAL);\r
+        vSash.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));\r
+        vSash.setBackground(vSash.getDisplay().getSystemColor(SWT.COLOR_GRAY));\r
+\r
+        SashForm hSash = new SashForm(vSash, SWT.HORIZONTAL);\r
+        hSash.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));\r
+\r
+        treeScrolledComposite = new ScrolledComposite(hSash, SWT.V_SCROLL | SWT.H_SCROLL);\r
+        GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);\r
+        gd.heightHint = 200;\r
+        gd.widthHint = 200;\r
+        treeScrolledComposite.setLayoutData(gd);\r
+        treeContainer = new Composite(treeScrolledComposite, SWT.NONE);\r
+        treeContainer.setLayout(new FillLayout());\r
+        treeScrolledComposite.setContent(treeContainer);\r
+        treeScrolledComposite.setExpandHorizontal(true);\r
+        treeScrolledComposite.setExpandVertical(true);\r
+        \r
+        treeViewer = new TreeViewer(treeContainer, SWT.SINGLE | SWT.BORDER);\r
+        treeViewer.setContentProvider(new InputLineTreeNodeContentProvider());\r
+        treeViewer.setLabelProvider(new InputLineTreeLabelProvider());\r
+        treeViewer.addSelectionChangedListener(new InputLineTreeSelectionChangedListener());\r
+        treeContainer.layout();\r
+        \r
+        treeScrolledComposite.setMinSize(treeContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x, treeContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);\r
+        \r
+        lineScrolledComposite = new ScrolledComposite(hSash, SWT.V_SCROLL);\r
+        lineScrolledComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));\r
+        lineContainer = new Composite(lineScrolledComposite, SWT.NONE);\r
+        GridLayout linesLayout = new GridLayout();\r
+        linesLayout.marginHeight = 1;\r
+        linesLayout.marginWidth = 0;\r
+        lineContainer.setLayout(linesLayout);\r
+        lineScrolledComposite.setContent(lineContainer);\r
+        lineScrolledComposite.setExpandHorizontal(true);\r
+        lineScrolledComposite.setExpandVertical(true);\r
+\r
+        if (definition == null) {\r
+            definition = new CustomTxtTraceDefinition();\r
+            definition.inputs.add(new InputLine(Cardinality.ZERO_OR_MORE, DEFAULT_REGEX,\r
+                    Arrays.asList(new InputData(CustomTxtTraceDefinition.TAG_MESSAGE, CustomTxtTraceDefinition.ACTION_SET))));\r
+        }\r
+        loadDefinition(definition);\r
+        treeViewer.expandAll();\r
+        lineContainer.layout();\r
+        \r
+        lineScrolledComposite.setMinSize(lineContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x, lineContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y-1);\r
+\r
+        hSash.setWeights(new int[] {1, 2});\r
+        \r
+        Composite sashBottom = new Composite(vSash, SWT.NONE);\r
+        GridLayout sashBottomLayout = new GridLayout(3, false);\r
+        sashBottomLayout.marginHeight = 0;\r
+        sashBottomLayout.marginWidth = 0;\r
+        sashBottom.setLayout(sashBottomLayout);\r
+\r
+        Label previewLabel = new Label(sashBottom, SWT.NULL);\r
+        previewLabel.setText("Preview input");\r
+        previewLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));\r
+\r
+        Button highlightAllButton = new Button(sashBottom, SWT.PUSH);\r
+        highlightAllButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));\r
+        highlightAllButton.setText("Highlight All");\r
+        highlightAllButton.addSelectionListener(new SelectionAdapter() {\r
+            public void widgetSelected(SelectionEvent e) {\r
+                updatePreviews(true);\r
+            }\r
+        });\r
+        \r
+        Button legendButton = new Button(sashBottom, SWT.PUSH);\r
+        legendButton.setImage(helpImage);\r
+        legendButton.setToolTipText("Preview Legend");\r
+        legendButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));\r
+        legendButton.addSelectionListener(new SelectionAdapter() {\r
+            public void widgetSelected(SelectionEvent e) {\r
+                openLegend();\r
+            }\r
+        });\r
+        \r
+        inputText = new StyledText(sashBottom, SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL);\r
+        if (fixedFont == null) {\r
+            if (System.getProperty("os.name").contains("Windows")) {\r
+                fixedFont = new Font(Display.getCurrent(), new FontData("Courier New", 10, SWT.NORMAL));\r
+            } else {\r
+                fixedFont = new Font(Display.getCurrent(), new FontData("Monospace", 10, SWT.NORMAL));\r
+            }\r
+        }\r
+        inputText.setFont(fixedFont);\r
+        gd = new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1);\r
+        gd.heightHint = inputText.computeSize(SWT.DEFAULT, inputText.getLineHeight() * 4).y;\r
+        gd.widthHint = 800;\r
+        inputText.setLayoutData(gd);\r
+        inputText.setText(getSelectionText());\r
+        inputText.addModifyListener(updateListener);\r
+\r
+        vSash.setWeights(new int[] {hSash.computeSize(SWT.DEFAULT, SWT.DEFAULT).y, sashBottom.computeSize(SWT.DEFAULT, SWT.DEFAULT).y});\r
+        \r
+        setControl(container);\r
+        \r
+        validate();\r
+        updatePreviews();\r
+    }\r
+\r
+    private class InputLineTreeNodeContentProvider implements ITreeContentProvider {\r
+\r
+        public Object[] getElements(Object inputElement) {\r
+            return ((List<?>) inputElement).toArray();\r
+        }\r
+\r
+        public Object[] getChildren(Object parentElement) {\r
+            InputLine inputLine = (InputLine) parentElement;\r
+            if (inputLine.childrenInputs == null) return new InputLine[0];\r
+            return inputLine.childrenInputs.toArray();\r
+        }\r
+\r
+        public boolean hasChildren(Object element) {\r
+            InputLine inputLine = (InputLine) element;\r
+            return (inputLine.childrenInputs != null && inputLine.childrenInputs.size() > 0);\r
+        }\r
+\r
+        public void dispose() {\r
+        }\r
+\r
+        public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {\r
+        }\r
+\r
+        public Object getParent(Object element) {\r
+            InputLine inputLine = (InputLine) element;\r
+            return inputLine.parentInput;\r
+        }\r
+    }\r
+    \r
+    private class InputLineTreeLabelProvider extends ColumnLabelProvider {\r
+\r
+        @Override\r
+        public Image getImage(Object element) {\r
+            return lineImage;\r
+        }\r
+\r
+        @Override\r
+        public String getText(Object element) {\r
+            InputLine inputLine = (InputLine) element;\r
+            if (inputLine.parentInput == null) {\r
+                return "Root Line " + getName(inputLine) + " " + inputLine.cardinality.toString() + " : " + inputLine.getRegex();\r
+            } else {\r
+                return "Line " + getName(inputLine) + " " + inputLine.cardinality.toString() + " : " + inputLine.getRegex();\r
+            }\r
+        }\r
+    }\r
+\r
+    private class InputLineTreeSelectionChangedListener implements ISelectionChangedListener {\r
+        public void selectionChanged(SelectionChangedEvent event) {\r
+            if (selectedLine != null) {\r
+                selectedLine.dispose();\r
+            }\r
+            if (!(event.getSelection().isEmpty()) && event.getSelection() instanceof IStructuredSelection) {\r
+                IStructuredSelection selection = (IStructuredSelection) event.getSelection();\r
+                InputLine inputLine = (InputLine) selection.getFirstElement();\r
+                selectedLine = new Line(lineContainer, getName(inputLine), inputLine);\r
+                lineContainer.layout();\r
+                lineScrolledComposite.setMinSize(lineContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x, lineContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y-1);\r
+                container.layout();\r
+                validate();\r
+                updatePreviews();\r
+            }\r
+        }\r
+    }\r
+    \r
+    /* (non-Javadoc)\r
+     * @see org.eclipse.jface.dialogs.DialogPage#dispose()\r
+     */\r
+    @Override\r
+    public void dispose() {\r
+        if (fixedFont != null) {\r
+            fixedFont.dispose();\r
+            fixedFont = null;\r
+        }\r
+        super.dispose();\r
+    }\r
+\r
+    private void loadDefinition(CustomTxtTraceDefinition def) {\r
+        logtypeText.setText(def.definitionName);\r
+        timestampOutputFormatText.setText(def.timeStampOutputFormat);\r
+        treeViewer.setInput(def.inputs);\r
+        if (def.inputs.size() > 0) {\r
+            InputLine inputLine = def.inputs.get(0);\r
+            treeViewer.setSelection(new StructuredSelection(inputLine));\r
+        }\r
+    }\r
+\r
+    private String getName(InputLine inputLine) {\r
+        if (inputLine.parentInput == null) {\r
+            return Integer.toString(definition.inputs.indexOf(inputLine)+1);\r
+        }\r
+        return getName(inputLine.parentInput) + "." + Integer.toString(inputLine.parentInput.childrenInputs.indexOf(inputLine)+1);\r
+    }\r
+\r
+    public List<String> getInputNames() {\r
+        List<String> inputs = new ArrayList<String>();\r
+        for (InputLine inputLine : definition.inputs) {\r
+            for (String inputName : getInputNames(inputLine)) {\r
+                if (!inputs.contains(inputName)) {\r
+                    inputs.add(inputName);\r
+                }\r
+            }\r
+        }\r
+        return inputs;\r
+    }\r
+    \r
+    public List<String> getInputNames(InputLine inputLine) {\r
+        List<String> inputs = new ArrayList<String>();\r
+        if (inputLine.columns != null) {\r
+            for (InputData inputData : inputLine.columns) {\r
+                String inputName = inputData.name;\r
+                if (!inputs.contains(inputName)) {\r
+                    inputs.add(inputName);\r
+                }\r
+            }\r
+        }\r
+        if (inputLine.childrenInputs != null) {\r
+            for (InputLine childInputLine : inputLine.childrenInputs) {\r
+                for (String inputName : getInputNames(childInputLine)) {\r
+                    if (!inputs.contains(inputName)) {\r
+                        inputs.add(inputName);\r
+                    }\r
+                }\r
+            }\r
+        }\r
+        return inputs;\r
+    }\r
+    \r
+    private void removeLine() {\r
+        selectedLine.dispose();\r
+        selectedLine = null;\r
+        lineContainer.layout();\r
+        lineScrolledComposite.setMinSize(lineContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x, lineContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y-1);\r
+        container.layout();\r
+    }\r
+\r
+//    private void removeAddLineButton() {\r
+//        addLineGroup.dispose();\r
+//    }\r
+    \r
+    private String getSelectionText() {\r
+        if (this.selection instanceof IStructuredSelection) {\r
+            Object selection = ((IStructuredSelection)this.selection).getFirstElement();\r
+            if (selection instanceof IFile) {\r
+                IFile file = (IFile)selection;\r
+                try {\r
+                    BufferedReader reader = new BufferedReader(new InputStreamReader(file.getContents()));\r
+                    StringBuilder sb = new StringBuilder();\r
+                    String line = null;\r
+                    while ((line = reader.readLine()) != null) {\r
+                        sb.append(line + "\n");\r
+                    }\r
+                    return sb.toString();\r
+                } catch (CoreException e) {\r
+                    return "";\r
+                } catch (IOException e) {\r
+                    return "";\r
+                }\r
+            }\r
+        }\r
+        return "";\r
+    }\r
+    \r
+    private void updatePreviews() {\r
+        updatePreviews(false);\r
+    }\r
+\r
+    private void updatePreviews(boolean updateAll) {\r
+        if (inputText == null) {\r
+            // early update during construction\r
+            return;\r
+        }\r
+        inputText.setStyleRanges(new StyleRange[] {});\r
+        \r
+        Scanner scanner = new Scanner(inputText.getText());\r
+        scanner.useDelimiter("\n");\r
+        int rawPos = 0;\r
+        String skip; // skip starting delimiters\r
+        if ((skip = scanner.findWithinHorizon("\\A\n+", 0)) != null) {\r
+            rawPos += skip.length();\r
+        }\r
+        \r
+        timeStampFormat = null;\r
+        if (selectedLine != null) {\r
+            for (InputGroup input : selectedLine.inputs) {\r
+                input.previewText.setText("*no matching line*");\r
+            }\r
+        }\r
+        \r
+        Map<String, String> data = new HashMap<String, String>();\r
+        int rootLineMatches = 0;\r
+        String firstEntryTimeStamp = null;\r
+        String firstEntryTimeStampInputFormat = null;\r
+        String log = null;\r
+    event: \r
+        while (log != null || scanner.hasNext()) {\r
+            if (rootLineMatches > 0 && !updateAll) {\r
+                break;\r
+            }\r
+            if (log == null) {\r
+                log = scanner.next();\r
+            }\r
+            int length = log.length();\r
+            for (InputLine rootInputLine : definition.inputs) {\r
+                Pattern pattern;\r
+                try {\r
+                    pattern = rootInputLine.getPattern();\r
+                } catch (PatternSyntaxException e) {\r
+                    continue;\r
+                }\r
+                Matcher matcher = pattern.matcher(log);\r
+                if (matcher.find()) {\r
+                    rootLineMatches++;\r
+                    inputText.setStyleRange(new StyleRange(rawPos, length,\r
+                            COLOR_BLACK, COLOR_YELLOW, SWT.ITALIC));\r
+                    data = new HashMap<String, String>();\r
+                    timeStampFormat = null;\r
+                    updatePreviewLine(rootInputLine, matcher, data, rawPos, rootLineMatches);\r
+                    if (rootLineMatches == 1) {\r
+                        firstEntryTimeStamp = data.get(CustomTxtTraceDefinition.TAG_TIMESTAMP);\r
+                        firstEntryTimeStampInputFormat = timeStampFormat;\r
+                    }\r
+                    HashMap<InputLine, Integer> countMap = new HashMap<InputLine, Integer>();\r
+                    InputLine currentInput = null;\r
+                    if (rootInputLine.childrenInputs != null && rootInputLine.childrenInputs.size() > 0) {\r
+                        currentInput = rootInputLine.childrenInputs.get(0);\r
+                        countMap.put(currentInput, 0);\r
+                    }\r
+                    rawPos += length + 1; // +1 for \n\r
+                    while (scanner.hasNext()) {\r
+                        log = scanner.next();\r
+                        length = log.length();\r
+                        boolean processed = false;\r
+                        if (currentInput == null) {\r
+                            for (InputLine input : definition.inputs) {\r
+                                matcher = input.getPattern().matcher(log);\r
+                                if (matcher.find()) {\r
+                                    continue event;\r
+                                }\r
+                            }\r
+                        } else {\r
+                            if (countMap.get(currentInput) >= currentInput.getMinCount()) {\r
+                                List<InputLine> nextInputs = currentInput.getNextInputs(countMap);\r
+                                if (nextInputs.size() == 0 || nextInputs.get(nextInputs.size() - 1).getMinCount() == 0) {\r
+                                    for (InputLine input : definition.inputs) {\r
+                                        matcher = input.getPattern().matcher(log);\r
+                                        if (matcher.find()) {\r
+                                            continue event;\r
+                                        }\r
+                                    }\r
+                                }\r
+                                for (InputLine input : nextInputs) {\r
+                                    matcher = input.getPattern().matcher(log);\r
+                                    if (matcher.find()) {\r
+                                        inputText.setStyleRange(new StyleRange(rawPos, length,\r
+                                                COLOR_BLACK, COLOR_LIGHT_YELLOW, SWT.ITALIC));\r
+                                        currentInput = input;\r
+                                        updatePreviewLine(currentInput, matcher, data, rawPos, rootLineMatches);\r
+                                        if (countMap.get(currentInput) == null) {\r
+                                            countMap.put(currentInput, 1);\r
+                                        } else {\r
+                                            countMap.put(currentInput, countMap.get(currentInput) + 1);\r
+                                        }\r
+                                        Iterator<InputLine> iter = countMap.keySet().iterator();\r
+                                        while (iter.hasNext()) {\r
+                                            InputLine inputLine = iter.next();\r
+                                            if (inputLine.level > currentInput.level) {\r
+                                                iter.remove();\r
+                                            }\r
+                                        }\r
+                                        if (currentInput.childrenInputs != null && currentInput.childrenInputs.size() > 0) {\r
+                                            currentInput = currentInput.childrenInputs.get(0);\r
+                                            countMap.put(currentInput, 0);\r
+                                        } else {\r
+                                            if (countMap.get(currentInput) >= currentInput.getMaxCount()) {\r
+                                                if (currentInput.getNextInputs(countMap).size() > 0) {\r
+                                                    currentInput = currentInput.getNextInputs(countMap).get(0);\r
+                                                    if (countMap.get(currentInput) == null) {\r
+                                                        countMap.put(currentInput, 0);\r
+                                                    }\r
+                                                    iter = countMap.keySet().iterator();\r
+                                                    while (iter.hasNext()) {\r
+                                                        InputLine inputLine = iter.next();\r
+                                                        if (inputLine.level > currentInput.level) {\r
+                                                            iter.remove();\r
+                                                        }\r
+                                                    }\r
+                                                } else {\r
+                                                    currentInput = null;\r
+                                                }\r
+                                            }\r
+                                        }\r
+                                        processed = true;\r
+                                        break;\r
+                                    }\r
+                                }\r
+                            }\r
+                            if (! processed) {\r
+                                matcher = currentInput.getPattern().matcher(log);\r
+                                if (matcher.find()) {\r
+                                    inputText.setStyleRange(new StyleRange(rawPos, length,\r
+                                            COLOR_BLACK, COLOR_LIGHT_YELLOW, SWT.ITALIC));\r
+                                    updatePreviewLine(currentInput, matcher, data, rawPos, rootLineMatches);\r
+                                    countMap.put(currentInput, countMap.get(currentInput) + 1);\r
+                                    if (currentInput.childrenInputs != null && currentInput.childrenInputs.size() > 0) {\r
+                                        currentInput = currentInput.childrenInputs.get(0);\r
+                                        countMap.put(currentInput, 0);\r
+                                    } else {\r
+                                        if (countMap.get(currentInput) >= currentInput.getMaxCount()) {\r
+                                            if (currentInput.getNextInputs(countMap).size() > 0) {\r
+                                                currentInput = currentInput.getNextInputs(countMap).get(0);\r
+                                                if (countMap.get(currentInput) == null) {\r
+                                                    countMap.put(currentInput, 0);\r
+                                                }\r
+                                                Iterator<InputLine> iter = countMap.keySet().iterator();\r
+                                                while (iter.hasNext()) {\r
+                                                    InputLine inputLine = iter.next();\r
+                                                    if (inputLine.level > currentInput.level) {\r
+                                                        iter.remove();\r
+                                                    }\r
+                                                }\r
+                                            } else {\r
+                                                currentInput = null;\r
+                                            }\r
+                                        }\r
+                                    }\r
+                                }\r
+                            }\r
+                        }\r
+                        rawPos += length + 1; // +1 for \n\r
+                    }\r
+\r
+                    break;\r
+                }\r
+            }\r
+            rawPos += length + 1; // +1 for \n\r
+            log = null;\r
+        }\r
+        scanner.close();\r
+        if (rootLineMatches == 1) {\r
+            firstEntryTimeStamp = data.get(CustomTxtTraceDefinition.TAG_TIMESTAMP);\r
+            firstEntryTimeStampInputFormat = timeStampFormat;\r
+        }\r
+        if (firstEntryTimeStamp == null) {\r
+            timestampPreviewText.setText("*no timestamp group*");\r
+            if (selectedLine != null) {\r
+                for (InputGroup group : selectedLine.inputs) {\r
+                    if (group.tagCombo.getText().equals(CustomTxtTraceDefinition.TAG_TIMESTAMP)) {\r
+                        timestampPreviewText.setText("*no matching timestamp*");\r
+                        break;\r
+                    }\r
+                }\r
+            }\r
+        } else {\r
+            try {\r
+                SimpleDateFormat dateFormat = new SimpleDateFormat(firstEntryTimeStampInputFormat);\r
+                Date date = dateFormat.parse(firstEntryTimeStamp);\r
+                dateFormat = new SimpleDateFormat(timestampOutputFormatText.getText().trim());\r
+                timestampPreviewText.setText(dateFormat.format(date));\r
+            } catch (ParseException e) {\r
+                timestampPreviewText.setText("*parse exception* [" + firstEntryTimeStamp + "] <> [" + firstEntryTimeStampInputFormat + "]");\r
+            } catch (IllegalArgumentException e) {\r
+                timestampPreviewText.setText("*parse exception* [Illegal Argument]");\r
+            }\r
+\r
+        }\r
+    }\r
+\r
+    private void updatePreviewLine(InputLine line, Matcher matcher, Map<String, String> data, int rawPos, int rootLineMatches) {\r
+        for (int i = 0; i < line.columns.size(); i++) {\r
+            InputData input = line.columns.get(i);\r
+            if (i < matcher.groupCount() && matcher.group(i+1) != null) {\r
+                if (line.parentInput == null) {\r
+                    inputText.setStyleRange(new StyleRange(rawPos + matcher.start(i+1), matcher.end(i+1) - matcher.start(i+1),\r
+                            COLOR_BLACK, COLOR_GREEN, SWT.BOLD));\r
+                } else {\r
+                    inputText.setStyleRange(new StyleRange(rawPos + matcher.start(i+1), matcher.end(i+1) - matcher.start(i+1),\r
+                            COLOR_BLACK, COLOR_LIGHT_GREEN, SWT.BOLD));\r
+                }\r
+                String value = matcher.group(i+1).trim();\r
+                if (selectedLine != null && selectedLine.inputLine.equals(line) && rootLineMatches == 1) {\r
+                    if (selectedLine.inputs.get(i).previewText.getText().equals("*no matching line*")) {\r
+                        selectedLine.inputs.get(i).previewText.setText(value);\r
+                    }\r
+                }\r
+                if (value.length() == 0) {\r
+                    continue;\r
+                }\r
+                if (input.action == CustomTxtTraceDefinition.ACTION_SET) {\r
+                    data.put(input.name, value);\r
+                    if (input.name.equals(CustomTxtTraceDefinition.TAG_TIMESTAMP)) {\r
+                        timeStampFormat = input.format;\r
+                    }\r
+                } else if (input.action == CustomTxtTraceDefinition.ACTION_APPEND) {\r
+                    String s = data.get(input.name);\r
+                    if (s != null) {\r
+                        data.put(input.name, s + value);\r
+                    } else {\r
+                        data.put(input.name, value);\r
+                    }\r
+                    if (input.name.equals(CustomTxtTraceDefinition.TAG_TIMESTAMP)) {\r
+                        if (timeStampFormat != null) {\r
+                            timeStampFormat += input.format;\r
+                        } else {\r
+                            timeStampFormat = input.format;\r
+                        }\r
+                    }\r
+                } else if (input.action == CustomTxtTraceDefinition.ACTION_APPEND_WITH_SEPARATOR) {\r
+                    String s = data.get(input.name);\r
+                    if (s != null) {\r
+                        data.put(input.name, s + " | " + value);\r
+                    } else {\r
+                        data.put(input.name, value);\r
+                    }\r
+                    if (input.name.equals(CustomTxtTraceDefinition.TAG_TIMESTAMP)) {\r
+                        if (timeStampFormat != null) {\r
+                            timeStampFormat += " | " + input.format;\r
+                        } else {\r
+                            timeStampFormat = input.format;\r
+                        }\r
+                    }\r
+                }\r
+            } else {\r
+                if (selectedLine != null && selectedLine.inputLine.equals(line) && rootLineMatches == 1) {\r
+                    if (selectedLine.inputs.get(i).previewText.getText().equals("*no matching line*")) {\r
+                        selectedLine.inputs.get(i).previewText.setText("*no matching group*");\r
+                    }\r
+                }\r
+            }\r
+        }\r
+        // highlight the matching groups that have no corresponponding input\r
+        for (int i = line.columns.size(); i < matcher.groupCount(); i++) {\r
+            if (matcher.group(i+1) != null) {\r
+                if (line.parentInput == null) {\r
+                    inputText.setStyleRange(new StyleRange(rawPos + matcher.start(i+1), matcher.end(i+1) - matcher.start(i+1),\r
+                            COLOR_BLACK, COLOR_MAGENTA));\r
+                } else {\r
+                    inputText.setStyleRange(new StyleRange(rawPos + matcher.start(i+1), matcher.end(i+1) - matcher.start(i+1),\r
+                            COLOR_BLACK, COLOR_LIGHT_MAGENTA));\r
+                }\r
+            }\r
+        }\r
+    }\r
+    \r
+    private void openHelpShell(String url) {\r
+        if (helpBrowser != null && !helpBrowser.isDisposed()) {\r
+            helpBrowser.getShell().setActive();\r
+            if (!helpBrowser.getUrl().equals(url)) {\r
+                helpBrowser.setUrl(url);\r
+            }\r
+            return;\r
+        }\r
+        final Shell helpShell = new Shell(getShell(), SWT.SHELL_TRIM);\r
+        helpShell.setLayout(new FillLayout());\r
+        helpBrowser = new Browser(helpShell, SWT.NONE);\r
+        helpBrowser.addTitleListener(new TitleListener() {\r
+           public void changed(TitleEvent event) {\r
+               helpShell.setText(event.title);\r
+           }\r
+        });\r
+        helpBrowser.setBounds(0,0,600,400);\r
+        helpShell.pack();\r
+        helpShell.open();\r
+        helpBrowser.setUrl(url);\r
+    }\r
+\r
+    private void openLegend() {\r
+        final String CG = "Captured group";\r
+        final String UCG = "Unidentified captured group";\r
+        final String UT = "Uncaptured text";\r
+        int line1start = 0;\r
+        String line1 = "Non-matching line\n";\r
+        int line2start = line1start + line1.length();\r
+        String line2 = "Matching root line : "+CG+" "+UCG+" "+UT+" \n";\r
+        int line3start = line2start + line2.length();\r
+        String line3 = "Matching other line: "+CG+" "+UCG+" "+UT+" \n";\r
+        int line4start = line3start + line3.length();\r
+        String line4 = "Matching other line: "+CG+" "+UCG+" "+UT+" \n";\r
+        int line5start = line4start + line4.length();\r
+        String line5 = "Non-matching line\n";\r
+        int line6start = line5start + line5.length();\r
+        String line6 = "Matching root line : "+CG+" "+UCG+" "+UT+" \n";\r
\r
+        final Shell legendShell = new Shell(getShell(), SWT.DIALOG_TRIM);\r
+        legendShell.setLayout(new FillLayout());\r
+        StyledText legendText = new StyledText(legendShell, SWT.MULTI);\r
+        legendText.setFont(fixedFont);\r
+        legendText.setText(line1 + line2 + line3 + line4 + line5 + line6);\r
+        legendText.setStyleRange(new StyleRange(line2start, line2.length(), COLOR_BLACK, COLOR_YELLOW, SWT.ITALIC));\r
+        legendText.setStyleRange(new StyleRange(line3start, line3.length(), COLOR_BLACK, COLOR_LIGHT_YELLOW, SWT.ITALIC));\r
+        legendText.setStyleRange(new StyleRange(line4start, line4.length(), COLOR_BLACK, COLOR_LIGHT_YELLOW, SWT.ITALIC));\r
+        legendText.setStyleRange(new StyleRange(line6start, line6.length(), COLOR_BLACK, COLOR_YELLOW, SWT.ITALIC));\r
+        legendText.setStyleRange(new StyleRange(line2start + line2.indexOf(CG), CG.length(), COLOR_BLACK, COLOR_GREEN, SWT.BOLD));\r
+        legendText.setStyleRange(new StyleRange(line2start + line2.indexOf(UCG), UCG.length(), COLOR_BLACK, COLOR_MAGENTA));\r
+        legendText.setStyleRange(new StyleRange(line3start + line3.indexOf(CG), CG.length(), COLOR_BLACK, COLOR_LIGHT_GREEN, SWT.BOLD));\r
+        legendText.setStyleRange(new StyleRange(line3start + line3.indexOf(UCG), UCG.length(), COLOR_BLACK, COLOR_LIGHT_MAGENTA));\r
+        legendText.setStyleRange(new StyleRange(line4start + line4.indexOf(CG), CG.length(), COLOR_BLACK, COLOR_LIGHT_GREEN, SWT.BOLD));\r
+        legendText.setStyleRange(new StyleRange(line4start + line4.indexOf(UCG), UCG.length(), COLOR_BLACK, COLOR_LIGHT_MAGENTA));\r
+        legendText.setStyleRange(new StyleRange(line6start + line6.indexOf(CG), CG.length(), COLOR_BLACK, COLOR_GREEN, SWT.BOLD));\r
+        legendText.setStyleRange(new StyleRange(line6start + line6.indexOf(UCG), UCG.length(), COLOR_BLACK, COLOR_MAGENTA));\r
+        legendShell.setText("Preview Legend");\r
+        legendShell.pack();\r
+        legendShell.open();\r
+    }\r
+\r
+    private class UpdateListener implements ModifyListener, SelectionListener {\r
+\r
+        public void modifyText(ModifyEvent e) {\r
+            validate();\r
+            updatePreviews();\r
+        }\r
+\r
+        public void widgetDefaultSelected(SelectionEvent e) {\r
+            validate();\r
+            updatePreviews();\r
+        }\r
+\r
+        public void widgetSelected(SelectionEvent e) {\r
+            validate();\r
+            updatePreviews();\r
+        }\r
+\r
+    }\r
+    \r
+    private class Line {\r
+        private static final String INFINITY_STRING = "\u221E";\r
+        @SuppressWarnings("unused")\r
+               String name;\r
+        InputLine inputLine;\r
+        Group group;\r
+        Composite labelComposite;\r
+        Text regexText;\r
+        Composite cardinalityContainer;\r
+        Combo cardinalityCombo;\r
+        Label cardinalityMinLabel;\r
+        Text cardinalityMinText;\r
+        Label cardinalityMaxLabel;\r
+        Text cardinalityMaxText;\r
+        Button infiniteButton;\r
+        ArrayList<InputGroup> inputs = new ArrayList<InputGroup>();\r
+        Button addGroupButton;\r
+        Label addGroupLabel;\r
+        \r
+        public Line(Composite parent, String name, InputLine inputLine) {\r
+            this.name = name;\r
+            this.inputLine = inputLine;\r
+            \r
+            group = new Group(parent, SWT.NONE);\r
+            group.setText(name);\r
+            group.setLayout(new GridLayout(2, false));\r
+            group.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));\r
+            \r
+            labelComposite = new Composite(group, SWT.FILL);\r
+            GridLayout labelLayout = new GridLayout(1, false);\r
+            labelLayout.marginWidth = 0;\r
+            labelLayout.marginHeight = 0;\r
+            labelComposite.setLayout(labelLayout);\r
+            labelComposite.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));\r
+            \r
+            Label label = new Label(labelComposite, SWT.NULL);\r
+            label.setText("Regular expression:");\r
+            \r
+            Composite regexContainer = new Composite(group, SWT.NONE);\r
+            GridLayout regexLayout = new GridLayout(2, false);\r
+            regexLayout.marginHeight = 0;\r
+            regexLayout.marginWidth = 0;\r
+            regexContainer.setLayout(regexLayout);\r
+            regexContainer.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));\r
+            \r
+            regexText = new Text(regexContainer, SWT.BORDER | SWT.SINGLE);\r
+            GridData gd = new GridData(SWT.FILL, SWT.CENTER, true, false);\r
+            gd.widthHint = 0;\r
+            regexText.setLayoutData(gd);\r
+            regexText.setText(inputLine.getRegex());\r
+            regexText.addModifyListener(updateListener);\r
+            \r
+            Button regexHelpButton = new Button(regexContainer, SWT.PUSH);\r
+            regexHelpButton.setImage(helpImage);\r
+            regexHelpButton.setToolTipText("Regular Expression Help");\r
+            regexHelpButton.addSelectionListener(new SelectionAdapter() {\r
+                public void widgetSelected(SelectionEvent e) {\r
+                    openHelpShell(PATTERN_URL);\r
+                }\r
+            });\r
+            \r
+            label = new Label(group, SWT.NONE);\r
+            label.setText("Cardinality:");\r
+            label.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));\r
+            \r
+            cardinalityContainer = new Composite(group, SWT.NONE);\r
+            GridLayout cardinalityLayout = new GridLayout(6, false);\r
+            cardinalityLayout.marginHeight = 0;\r
+            cardinalityLayout.marginWidth = 0;\r
+            cardinalityContainer.setLayout(cardinalityLayout);\r
+            cardinalityContainer.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));\r
+\r
+            cardinalityCombo = new Combo(cardinalityContainer, SWT.DROP_DOWN | SWT.READ_ONLY);\r
+            cardinalityCombo.setItems(new String[] {\r
+                    Cardinality.ZERO_OR_MORE.toString(),\r
+                    Cardinality.ONE_OR_MORE.toString(),\r
+                    Cardinality.ZERO_OR_ONE.toString(),\r
+                    Cardinality.ONE.toString(),\r
+                    "(?,?)"});\r
+            cardinalityCombo.addSelectionListener(new SelectionListener(){\r
+                public void widgetDefaultSelected(SelectionEvent e) {}\r
+                public void widgetSelected(SelectionEvent e) {\r
+                    switch (cardinalityCombo.getSelectionIndex()) {\r
+                    case 4: //(?,?)\r
+                        cardinalityMinLabel.setVisible(true);\r
+                        cardinalityMinText.setVisible(true);\r
+                        cardinalityMaxLabel.setVisible(true);\r
+                        cardinalityMaxText.setVisible(true);\r
+                        infiniteButton.setVisible(true);\r
+                        break;\r
+                    default:\r
+                        cardinalityMinLabel.setVisible(false);\r
+                        cardinalityMinText.setVisible(false);\r
+                        cardinalityMaxLabel.setVisible(false);\r
+                        cardinalityMaxText.setVisible(false);\r
+                        infiniteButton.setVisible(false);\r
+                        break;\r
+                    }\r
+                    cardinalityContainer.layout();\r
+                    validate();\r
+                    updatePreviews();\r
+                }});\r
+            \r
+            cardinalityMinLabel = new Label(cardinalityContainer, SWT.NONE);\r
+            cardinalityMinLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));\r
+            cardinalityMinLabel.setText("min:");\r
+            cardinalityMinLabel.setVisible(false);\r
+            \r
+            cardinalityMinText = new Text(cardinalityContainer, SWT.BORDER | SWT.SINGLE);\r
+            gd = new GridData(SWT.CENTER, SWT.CENTER, false, false);\r
+            gd.widthHint = 20;\r
+            cardinalityMinText.setLayoutData(gd);\r
+            cardinalityMinText.setVisible(false);\r
+            \r
+            cardinalityMaxLabel = new Label(cardinalityContainer, SWT.NONE);\r
+            cardinalityMaxLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));\r
+            cardinalityMaxLabel.setText("max:");\r
+            cardinalityMaxLabel.setVisible(false);\r
+            \r
+            cardinalityMaxText = new Text(cardinalityContainer, SWT.BORDER | SWT.SINGLE);\r
+            gd = new GridData(SWT.CENTER, SWT.CENTER, false, false);\r
+            gd.widthHint = 20;\r
+            cardinalityMaxText.setLayoutData(gd);\r
+            cardinalityMaxText.setVisible(false);\r
+\r
+            infiniteButton = new Button(cardinalityContainer, SWT.PUSH);\r
+            infiniteButton.setText(INFINITY_STRING);\r
+            infiniteButton.setVisible(false);\r
+            infiniteButton.addSelectionListener(new SelectionAdapter(){\r
+                @Override\r
+                public void widgetSelected(SelectionEvent e) {\r
+                    cardinalityMaxText.setText(INFINITY_STRING);\r
+                }});\r
+\r
+            if (inputLine.cardinality.equals(Cardinality.ZERO_OR_MORE)) {\r
+                cardinalityCombo.select(0);\r
+            } else if (inputLine.cardinality.equals(Cardinality.ONE_OR_MORE)) {\r
+                cardinalityCombo.select(1);\r
+            } else if (inputLine.cardinality.equals(Cardinality.ZERO_OR_ONE)) {\r
+                cardinalityCombo.select(2);\r
+            } else if (inputLine.cardinality.equals(Cardinality.ONE)) {\r
+                cardinalityCombo.select(3);\r
+            } else {\r
+                cardinalityCombo.select(4);\r
+                cardinalityMinLabel.setVisible(true);\r
+                cardinalityMinText.setVisible(true);\r
+                if (inputLine.getMinCount() >= 0) {\r
+                    cardinalityMinText.setText(Integer.toString(inputLine.getMinCount()));\r
+                }\r
+                cardinalityMaxLabel.setVisible(true);\r
+                cardinalityMaxText.setVisible(true);\r
+                if (inputLine.getMaxCount() == Cardinality.INF) {\r
+                    cardinalityMaxText.setText(INFINITY_STRING);\r
+                } else if (inputLine.getMaxCount() >= 0) {\r
+                    cardinalityMaxText.setText(Integer.toString(inputLine.getMaxCount()));\r
+                }\r
+                infiniteButton.setVisible(true);\r
+            }\r
+            \r
+            VerifyListener digitsListener = new VerifyListener() {\r
+                public void verifyText(VerifyEvent e) {\r
+                    if (e.text.equals(INFINITY_STRING)) {\r
+                        e.doit = e.widget == cardinalityMaxText && e.start == 0 && e.end == ((Text) e.widget).getText().length();\r
+                    } else {\r
+                        if (((Text) e.widget).getText().equals(INFINITY_STRING)) {\r
+                            e.doit = e.start == 0 && e.end == ((Text) e.widget).getText().length();\r
+                        }\r
+                        for (int i = 0; i < e.text.length(); i++) {\r
+                            if (!Character.isDigit(e.text.charAt(i))) {\r
+                                e.doit = false;\r
+                                break;\r
+                            }\r
+                        }\r
+                    }\r
+                }};\r
+                \r
+            cardinalityMinText.addModifyListener(updateListener);\r
+            cardinalityMaxText.addModifyListener(updateListener);\r
+            cardinalityMinText.addVerifyListener(digitsListener);\r
+            cardinalityMaxText.addVerifyListener(digitsListener);\r
+\r
+            if (inputLine.columns != null) {\r
+                for (InputData inputData : inputLine.columns) {\r
+                    InputGroup inputGroup = new InputGroup(group, this, inputs.size()+1);\r
+                    if (inputData.name.equals(CustomTxtTraceDefinition.TAG_TIMESTAMP)) {\r
+                        inputGroup.tagCombo.select(0);\r
+                        inputGroup.tagText.setText(inputData.format);\r
+                        inputGroup.tagLabel.setText("format:");\r
+                        inputGroup.tagLabel.setVisible(true);\r
+                        inputGroup.tagText.setVisible(true);\r
+                        inputGroup.tagText.addModifyListener(updateListener);\r
+                    } else if (inputData.name.equals(CustomTxtTraceDefinition.TAG_MESSAGE)) {\r
+                        inputGroup.tagCombo.select(1);\r
+                    } else {\r
+                        inputGroup.tagCombo.select(2);\r
+                        inputGroup.tagText.setText(inputData.name);\r
+                        inputGroup.tagLabel.setText("name:");\r
+                        inputGroup.tagLabel.setVisible(true);\r
+                        inputGroup.tagText.setVisible(true);\r
+                        inputGroup.tagText.addModifyListener(updateListener);\r
+                    }\r
+                    inputGroup.actionCombo.select(inputData.action);\r
+                    inputs.add(inputGroup);\r
+                }\r
+            }\r
+            \r
+            createAddGroupButton();\r
+        }\r
+\r
+        private void createAddGroupButton() {\r
+            addGroupButton = new Button(group, SWT.PUSH);\r
+            addGroupButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));\r
+            addGroupButton.setImage(addImage);\r
+            addGroupButton.setToolTipText("Add group");\r
+            addGroupButton.addSelectionListener(new SelectionAdapter() {\r
+                public void widgetSelected(SelectionEvent e) {\r
+                    removeAddGroupButton();\r
+                    inputs.add(new InputGroup(group, Line.this, inputs.size()+1));\r
+                    createAddGroupButton();\r
+                    lineContainer.layout();\r
+                    lineScrolledComposite.setMinSize(lineContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x, lineContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y-1);\r
+                    group.getParent().layout();\r
+                    validate();\r
+                    updatePreviews();\r
+                }\r
+            });\r
+            \r
+            addGroupLabel = new Label(group, SWT.NULL);\r
+            addGroupLabel.setText("New group");\r
+        }\r
+\r
+        private void removeAddGroupButton() {\r
+            addGroupButton.dispose();\r
+            addGroupLabel.dispose();\r
+        }\r
+        \r
+        private void removeInput(int inputNumber) {\r
+            if (--inputNumber < inputs.size()) {\r
+                inputs.remove(inputNumber).dispose();\r
+                for (int i = inputNumber; i < inputs.size(); i++) {\r
+                    inputs.get(i).setInputNumber(i+1);\r
+                }\r
+                lineContainer.layout();\r
+                lineScrolledComposite.setMinSize(lineContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x, lineContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y-1);\r
+                group.getParent().layout();\r
+            }\r
+        }\r
+        \r
+//        private void setName(String name) {\r
+//            this.name = name;\r
+//            group.setText("Line " + name);\r
+//        }\r
+        \r
+        private void dispose() {\r
+            group.dispose();\r
+        }\r
+        \r
+        private void extractInputs() {\r
+            inputLine.setRegex(selectedLine.regexText.getText());\r
+            switch (cardinalityCombo.getSelectionIndex()) {\r
+            case 0:\r
+                inputLine.cardinality = Cardinality.ZERO_OR_MORE;\r
+                break;\r
+            case 1:\r
+                inputLine.cardinality = Cardinality.ONE_OR_MORE;\r
+                break;\r
+            case 2:\r
+                inputLine.cardinality = Cardinality.ZERO_OR_ONE;\r
+                break;\r
+            case 3:\r
+                inputLine.cardinality = Cardinality.ONE;\r
+                break;\r
+            case 4: //(?,?)\r
+                int min, max;\r
+                try {\r
+                    min = Integer.parseInt(cardinalityMinText.getText());\r
+                } catch (NumberFormatException e) {\r
+                    min = -1;\r
+                }\r
+                try {\r
+                    if (cardinalityMaxText.getText().equals(INFINITY_STRING)) {\r
+                        max = Cardinality.INF;\r
+                    } else {\r
+                        max = Integer.parseInt(cardinalityMaxText.getText());\r
+                    }\r
+                } catch (NumberFormatException e) {\r
+                    max = -1;\r
+                }\r
+                inputLine.cardinality = new Cardinality(min, max);\r
+                break;\r
+            default:\r
+                inputLine.cardinality = Cardinality.ZERO_OR_MORE;\r
+                break;\r
+            }\r
+            inputLine.columns = new ArrayList<InputData>(inputs.size());\r
+            for (int i = 0; i < inputs.size(); i++) {\r
+                InputGroup group = inputs.get(i);\r
+                InputData inputData = new InputData();\r
+                if (group.tagCombo.getText().equals(CustomTxtTraceDefinition.TAG_OTHER)) {\r
+                    inputData.name = group.tagText.getText().trim();\r
+                } else {\r
+                    inputData.name = group.tagCombo.getText();\r
+                    if (group.tagCombo.getText().equals(CustomTxtTraceDefinition.TAG_TIMESTAMP)) {\r
+                        inputData.format = group.tagText.getText().trim();\r
+                    }\r
+                }\r
+                inputData.action = group.actionCombo.getSelectionIndex();\r
+                inputLine.columns.add(inputData);\r
+            }\r
+        }\r
+    }\r
+\r
+    private class InputGroup {\r
+        Line line;\r
+        int inputNumber;\r
+        \r
+        // children of parent (must be disposed)\r
+        Composite labelComposite;\r
+        Composite tagComposite;\r
+        Label previewLabel;\r
+        Text previewText;\r
+\r
+        // children of labelComposite\r
+        Label inputLabel;\r
+        \r
+        // children of tagComposite\r
+        Combo tagCombo;\r
+        Label tagLabel;\r
+        Text tagText;\r
+        Combo actionCombo;\r
+        \r
+        public InputGroup(Composite parent, Line line, int inputNumber) {\r
+            this.line = line;\r
+            this.inputNumber = inputNumber;\r
+            \r
+            labelComposite = new Composite(parent, SWT.FILL);\r
+            GridLayout labelLayout = new GridLayout(2, false);\r
+            labelLayout.marginWidth = 0;\r
+            labelLayout.marginHeight = 0;\r
+            labelComposite.setLayout(labelLayout);\r
+            labelComposite.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));\r
+            \r
+            Button deleteButton = new Button(labelComposite, SWT.PUSH);\r
+            deleteButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));\r
+            deleteButton.setImage(deleteImage);\r
+            deleteButton.setToolTipText("Remove group");\r
+            deleteButton.addSelectionListener(new SelectionAdapter() {\r
+                public void widgetSelected(SelectionEvent e) {\r
+                    InputGroup.this.line.removeInput(InputGroup.this.inputNumber);\r
+                    validate();\r
+                    updatePreviews();\r
+                }\r
+            });\r
+            \r
+            inputLabel = new Label(labelComposite, SWT.NULL);\r
+            inputLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));\r
+            inputLabel.setText("Group " + inputNumber + ":");\r
+\r
+            tagComposite = new Composite(parent, SWT.FILL);\r
+            GridLayout tagLayout = new GridLayout(4, false);\r
+            tagLayout.marginWidth = 0;\r
+            tagLayout.marginHeight = 0;\r
+            tagComposite.setLayout(tagLayout);\r
+            tagComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));\r
+            \r
+            tagCombo = new Combo(tagComposite, SWT.DROP_DOWN | SWT.READ_ONLY);\r
+            tagCombo.setItems(new String[] {CustomTxtTraceDefinition.TAG_TIMESTAMP,\r
+                                            CustomTxtTraceDefinition.TAG_MESSAGE,\r
+                                            CustomTxtTraceDefinition.TAG_OTHER});\r
+            tagCombo.select(1);\r
+            tagCombo.addSelectionListener(new SelectionListener(){\r
+                public void widgetDefaultSelected(SelectionEvent e) {}\r
+                public void widgetSelected(SelectionEvent e) {\r
+                    tagText.removeModifyListener(updateListener);\r
+                    switch (tagCombo.getSelectionIndex()) {\r
+                    case 0: //Time Stamp\r
+                        tagLabel.setText("format:");\r
+                        tagLabel.setVisible(true);\r
+                        tagText.setVisible(true);\r
+                        tagText.addModifyListener(updateListener);\r
+                        break;\r
+                    case 1: //Message\r
+                        tagLabel.setVisible(false);\r
+                        tagText.setVisible(false);\r
+                        break;\r
+                    case 2: //Other\r
+                        tagLabel.setText("name:");\r
+                        tagLabel.setVisible(true);\r
+                        tagText.setVisible(true);\r
+                        tagText.addModifyListener(updateListener);\r
+                        break;\r
+                    case 3: //Continue\r
+                        tagLabel.setVisible(false);\r
+                        tagText.setVisible(false);\r
+                        break;\r
+                    }\r
+                    tagComposite.layout();\r
+                    validate();\r
+                    updatePreviews();\r
+                }});\r
+            \r
+            tagLabel = new Label(tagComposite, SWT.NULL);\r
+            tagLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));\r
+            tagLabel.setVisible(false);\r
+            \r
+            tagText = new Text(tagComposite, SWT.BORDER | SWT.SINGLE);\r
+            GridData gd = new GridData(SWT.FILL, SWT.CENTER, true, false);\r
+            gd.widthHint = 0;\r
+            tagText.setLayoutData(gd);\r
+            tagText.setVisible(false);\r
+            \r
+            actionCombo = new Combo(tagComposite, SWT.DROP_DOWN | SWT.READ_ONLY);\r
+            actionCombo.setItems(new String[] {"Set", "Append", "Append with |"});\r
+            actionCombo.select(0);\r
+            actionCombo.addSelectionListener(updateListener);\r
+            \r
+            previewLabel = new Label(parent, SWT.NULL);\r
+            previewLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));\r
+            previewLabel.setText("Preview:");\r
+            \r
+            previewText = new Text(parent, SWT.BORDER | SWT.SINGLE | SWT.READ_ONLY);\r
+            gd = new GridData(SWT.FILL, SWT.CENTER, true, false);\r
+            gd.widthHint = 0;\r
+            previewText.setLayoutData(gd);\r
+            previewText.setText("*no match*");\r
+            previewText.setBackground(COLOR_WIDGET_BACKGROUND);\r
+        }\r
+        \r
+        private void dispose() {\r
+            labelComposite.dispose();\r
+            tagComposite.dispose();\r
+            previewLabel.dispose();\r
+            previewText.dispose();\r
+        }\r
+        \r
+        private void setInputNumber(int inputNumber) {\r
+            this.inputNumber = inputNumber;\r
+            inputLabel.setText("Group " + inputNumber + ":");\r
+            labelComposite.layout();\r
+        }\r
+    }\r
+\r
+    private void validate() {\r
+\r
+        definition.definitionName = logtypeText.getText().trim();\r
+        definition.timeStampOutputFormat = timestampOutputFormatText.getText().trim();\r
+        \r
+        if (selectedLine != null) {\r
+            selectedLine.extractInputs();\r
+            treeViewer.refresh();\r
+        }\r
+        \r
+        StringBuffer errors = new StringBuffer();\r
+        \r
+        if (definition.definitionName.length() == 0) {\r
+            errors.append("Enter a name for the new log type. ");\r
+            logtypeText.setBackground(COLOR_LIGHT_RED);\r
+        } else {\r
+            logtypeText.setBackground(COLOR_TEXT_BACKGROUND);\r
+            for (CustomTxtTraceDefinition def : CustomTxtTraceDefinition.loadAll()) {\r
+                if (definition.definitionName.equals(def.definitionName)) {\r
+                    if (editDefinitionName == null || ! editDefinitionName.equals(definition.definitionName)) {\r
+                        errors.append("The log type name already exists. ");\r
+                        logtypeText.setBackground(COLOR_LIGHT_RED);\r
+                        break;\r
+                    }\r
+                }\r
+            }\r
+        }\r
+        \r
+        timestampFound = false;\r
+        for (int i = 0; i < definition.inputs.size(); i++) {\r
+            \r
+            InputLine inputLine = definition.inputs.get(i);\r
+            String name = Integer.toString(i+1);\r
+            errors.append(validateLine(inputLine, name));\r
+        }\r
+        if (timestampFound) {\r
+            if (definition.timeStampOutputFormat.length() == 0) {\r
+                errors.append("Enter the output format for the Time Stamp field. ");\r
+                timestampOutputFormatText.setBackground(COLOR_LIGHT_RED);\r
+            } else {\r
+                try {\r
+                    new SimpleDateFormat(definition.timeStampOutputFormat);\r
+                    timestampOutputFormatText.setBackground(COLOR_TEXT_BACKGROUND);\r
+                } catch (IllegalArgumentException e) {\r
+                    errors.append("Enter a valid output format for the Time Stamp field. ");\r
+                    timestampOutputFormatText.setBackground(COLOR_LIGHT_RED);\r
+                }\r
+            }\r
+            \r
+        } else {\r
+            timestampOutputFormatText.setBackground(COLOR_TEXT_BACKGROUND);\r
+//            timestampPreviewText.setBackground(COLOR_WIDGET_BACKGROUND);\r
+//            errors.append("Identify a Time Stamp group (Line "+name+"). ");\r
+//            timestampPreviewText.setText("*no timestamp group*");\r
+//            timestampPreviewText.setBackground(COLOR_LIGHT_RED);\r
+        }\r
+\r
+        if (errors.length() == 0) {\r
+            setDescription(defaultDescription);\r
+            setPageComplete(true);\r
+        } else {\r
+            setDescription(errors.toString());\r
+            setPageComplete(false);\r
+        }\r
+    }\r
+\r
+    public StringBuffer validateLine(InputLine inputLine, String name) {\r
+        StringBuffer errors = new StringBuffer();\r
+        Line line = null;\r
+        if (selectedLine != null && selectedLine.inputLine.equals(inputLine)) line = selectedLine;\r
+        try {\r
+            Pattern.compile(inputLine.getRegex());\r
+            if (line != null) line.regexText.setBackground(COLOR_TEXT_BACKGROUND);\r
+        } catch (PatternSyntaxException e) {\r
+            errors.append("Enter a valid regular expression (Line "+name+"). ");\r
+            if (line != null) line.regexText.setBackground(COLOR_LIGHT_RED);\r
+        }\r
+        if (inputLine.getMinCount() == -1) {\r
+            errors.append("Enter a minimum value for cardinality (Line "+name+"). ");\r
+            if (line != null) line.cardinalityMinText.setBackground(COLOR_LIGHT_RED);\r
+        } else {\r
+            if (line != null) line.cardinalityMinText.setBackground(COLOR_TEXT_BACKGROUND);\r
+        }\r
+        if (inputLine.getMaxCount() == -1) {\r
+            errors.append("Enter a maximum value for cardinality (Line "+name+"). ");\r
+            if (line != null) line.cardinalityMaxText.setBackground(COLOR_LIGHT_RED);\r
+        } else if (inputLine.getMinCount() > inputLine.getMaxCount()) {\r
+            errors.append("Enter correct (min <= max) values for cardinality (Line "+name+"). ");\r
+            if (line != null) line.cardinalityMinText.setBackground(COLOR_LIGHT_RED);\r
+            if (line != null) line.cardinalityMaxText.setBackground(COLOR_LIGHT_RED);\r
+        } else {\r
+            if (line != null) line.cardinalityMaxText.setBackground(COLOR_TEXT_BACKGROUND);\r
+        }\r
+        for (int i = 0; inputLine.columns != null && i < inputLine.columns.size(); i++) {\r
+            InputData inputData = inputLine.columns.get(i);\r
+            InputGroup group = null;\r
+            if (line != null) group = line.inputs.get(i);\r
+            if (inputData.name.equals(CustomTxtTraceDefinition.TAG_TIMESTAMP)) {\r
+                timestampFound = true;\r
+                if (inputData.format.length() == 0) {\r
+                    errors.append("Enter the input format for the Time Stamp (Line "+name+" Group "+(i+1)+"). ");\r
+                    if (group != null) group.tagText.setBackground(COLOR_LIGHT_RED);\r
+                } else {\r
+                    try {\r
+                        new SimpleDateFormat(inputData.format);\r
+                        if (group != null) group.tagText.setBackground(COLOR_TEXT_BACKGROUND);\r
+                    } catch (IllegalArgumentException e) {\r
+                        errors.append("Enter a valid input format for the Time Stamp (Line "+name+" Group "+(i+1)+"). ");\r
+                        if (group != null) group.tagText.setBackground(COLOR_LIGHT_RED);\r
+                    }\r
+                }\r
+            } else if (inputData.name.length() == 0) {\r
+                errors.append("Enter a name for the data group (Line "+name+" Group "+(i+1)+"). ");\r
+                if (group != null) group.tagText.setBackground(COLOR_LIGHT_RED);\r
+            } else {\r
+                if (group != null) group.tagText.setBackground(COLOR_TEXT_BACKGROUND);\r
+            }\r
+        }\r
+        for (int i = 0; inputLine.childrenInputs != null && i < inputLine.childrenInputs.size(); i++) {\r
+            errors.append(validateLine(inputLine.childrenInputs.get(i), name+"."+(i+1)));\r
+        }\r
+        return errors;\r
+    }\r
+    \r
+    public CustomTxtTraceDefinition getDefinition() {\r
+        return definition;\r
+    }\r
+\r
+    public char[] getInputText() {\r
+        return inputText.getText().toCharArray();\r
+    }\r
+}\r
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/wizards/CustomTxtParserOutputWizardPage.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/wizards/CustomTxtParserOutputWizardPage.java
new file mode 100644 (file)
index 0000000..f50c85d
--- /dev/null
@@ -0,0 +1,299 @@
+package org.eclipse.linuxtools.tmf.ui.wizards;\r
+\r
+import java.io.File;\r
+import java.io.FileNotFoundException;\r
+import java.io.FileWriter;\r
+import java.io.IOException;\r
+import java.util.ArrayList;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+\r
+import org.eclipse.jface.wizard.WizardPage;\r
+import org.eclipse.linuxtools.tmf.trace.ITmfTrace;\r
+import org.eclipse.linuxtools.tmf.ui.TmfUiPlugin;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomEventsTable;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomTxtTrace;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomTxtTraceDefinition;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomTraceDefinition.OutputColumn;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.custom.SashForm;\r
+import org.eclipse.swt.custom.ScrolledComposite;\r
+import org.eclipse.swt.events.SelectionAdapter;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.graphics.Image;\r
+import org.eclipse.swt.layout.GridData;\r
+import org.eclipse.swt.layout.GridLayout;\r
+import org.eclipse.swt.widgets.Button;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Text;\r
+\r
+public class CustomTxtParserOutputWizardPage extends WizardPage {\r
+\r
+    private static final Image upImage = TmfUiPlugin.getDefault().getImageFromPath("/icons/up_button.gif");\r
+    private static final Image downImage = TmfUiPlugin.getDefault().getImageFromPath("/icons/down_button.gif");\r
+    private CustomTxtParserWizard wizard;\r
+    private CustomTxtTraceDefinition definition;\r
+    ArrayList<Output> outputs = new ArrayList<Output>();\r
+    Output messageOutput;\r
+    Composite container;\r
+    SashForm sash;\r
+    Text timestampFormatText;\r
+    Text timestampPreviewText;\r
+    ScrolledComposite outputsScrolledComposite;\r
+    Composite outputsContainer;\r
+    ScrolledComposite inputScrolledComposite;\r
+    Composite tableContainer;\r
+    CustomEventsTable previewTable;\r
+    File tmpFile;\r
+    \r
+    protected CustomTxtParserOutputWizardPage(CustomTxtParserWizard wizard) {\r
+        super("CustomParserOutputWizardPage");\r
+        setTitle(wizard.inputPage.getTitle());\r
+        setDescription("Customize the output of the parser");\r
+        this.wizard = wizard;\r
+        setPageComplete(false);\r
+    }\r
+\r
+    public void createControl(Composite parent) {\r
+        container = new Composite(parent, SWT.NULL);\r
+        container.setLayout(new GridLayout());\r
+\r
+        sash = new SashForm(container, SWT.VERTICAL);\r
+        sash.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));\r
+        sash.setBackground(sash.getDisplay().getSystemColor(SWT.COLOR_GRAY));\r
+        \r
+        outputsScrolledComposite = new ScrolledComposite(sash, SWT.V_SCROLL);\r
+        outputsScrolledComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));\r
+        outputsContainer = new Composite(outputsScrolledComposite, SWT.NONE);\r
+        GridLayout outputsLayout = new GridLayout(4, false);\r
+        outputsLayout.marginHeight = 10;\r
+        outputsLayout.marginWidth = 0;\r
+        outputsContainer.setLayout(outputsLayout);\r
+        outputsScrolledComposite.setContent(outputsContainer);\r
+        outputsScrolledComposite.setExpandHorizontal(true);\r
+        outputsScrolledComposite.setExpandVertical(true);\r
+\r
+        outputsContainer.layout();\r
+        \r
+        outputsScrolledComposite.setMinSize(outputsContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x, outputsContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y-5);\r
+\r
+        tableContainer = new Composite(sash, SWT.NONE);\r
+        GridLayout tableLayout = new GridLayout();\r
+        tableLayout.marginHeight = 0;\r
+        tableLayout.marginWidth = 0;\r
+        tableContainer.setLayout(tableLayout);\r
+        previewTable = new CustomEventsTable(new CustomTxtTraceDefinition(), tableContainer, 0);\r
+        \r
+        if (wizard.definition != null) {\r
+            loadDefinition(wizard.definition);\r
+        }\r
+        setControl(container);\r
+        \r
+    }\r
+\r
+    @Override\r
+    public void dispose() {\r
+        previewTable.dispose();\r
+        super.dispose();\r
+    }\r
+\r
+    private void loadDefinition(CustomTxtTraceDefinition definition) {\r
+        for (OutputColumn outputColumn : definition.outputs) {\r
+            Output output = new Output(outputsContainer, outputColumn.name);\r
+            outputs.add(output);\r
+        }\r
+    }\r
+\r
+    /* (non-Javadoc)\r
+     * @see org.eclipse.jface.dialogs.DialogPage#setVisible(boolean)\r
+     */\r
+    @Override\r
+    public void setVisible(boolean visible) {\r
+        if (visible) {\r
+            this.definition = wizard.inputPage.getDefinition();\r
+            List<String> outputNames = wizard.inputPage.getInputNames();\r
+            \r
+            // dispose outputs that have been removed in the input page\r
+            Iterator<Output> iter = outputs.iterator();\r
+            while (iter.hasNext()) {\r
+                Output output = iter.next();\r
+                boolean found = false;\r
+                for (String name : outputNames) {\r
+                    if (output.name.equals(name)) {\r
+                        found = true;\r
+                        break;\r
+                    }\r
+                }\r
+                if (!found) {\r
+                    output.dispose();\r
+                    iter.remove();\r
+                }\r
+            }\r
+            \r
+            // create outputs that have been added in the input page\r
+            for (String name : outputNames) {\r
+                boolean found = false;\r
+                for (Output output : outputs) {\r
+                    if (output.name.equals(name)) {\r
+                        found = true;\r
+                        break;\r
+                    }\r
+                }\r
+                if (!found) {\r
+                    outputs.add(new Output(outputsContainer, name));\r
+                }\r
+            }\r
+            \r
+            outputsContainer.layout();\r
+            outputsScrolledComposite.setMinSize(outputsContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x, outputsContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y-5);\r
+            updatePreviewTable();\r
+            if (sash.getSize().y > outputsContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y + previewTable.getTable().getItemHeight()) {\r
+                sash.setWeights(new int[] {outputsContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y, sash.getSize().y - outputsContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y});\r
+            } else {\r
+                sash.setWeights(new int[] {outputsContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y, previewTable.getTable().getItemHeight()});\r
+            }\r
+            setPageComplete(true);\r
+        } else {\r
+            setPageComplete(false);\r
+        }\r
+        super.setVisible(visible);\r
+    }\r
+\r
+    private void moveBefore(Output moved) {\r
+        int i = outputs.indexOf(moved);\r
+        if (i > 0) {\r
+            Output previous = outputs.get(i-1);\r
+            moved.enabledButton.moveAbove(previous.enabledButton);\r
+            moved.nameLabel.moveBelow(moved.enabledButton);\r
+            moved.upButton.moveBelow(moved.nameLabel);\r
+            moved.downButton.moveBelow(moved.upButton);\r
+            outputs.add(i-1, outputs.remove(i));\r
+            outputsContainer.layout();\r
+            outputsScrolledComposite.setMinSize(outputsContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x, outputsContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y-5);\r
+            container.layout();\r
+            updatePreviewTable();\r
+        }\r
+    }\r
+    \r
+    private void moveAfter(Output moved) {\r
+        int i = outputs.indexOf(moved);\r
+        if (i+1 < outputs.size()) {\r
+            Output next = outputs.get(i+1);\r
+            moved.enabledButton.moveBelow(next.downButton);\r
+            moved.nameLabel.moveBelow(moved.enabledButton);\r
+            moved.upButton.moveBelow(moved.nameLabel);\r
+            moved.downButton.moveBelow(moved.upButton);\r
+            outputs.add(i+1, outputs.remove(i));\r
+            outputsContainer.layout();\r
+            outputsScrolledComposite.setMinSize(outputsContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x, outputsContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y-5);\r
+            container.layout();\r
+            updatePreviewTable();\r
+        }\r
+    }\r
+    \r
+    private void updatePreviewTable() {\r
+        final int MAX_NUM_ENTRIES = 50;\r
+        definition.outputs = extractOutputs();\r
+\r
+        try {\r
+            tmpFile = TmfUiPlugin.getDefault().getStateLocation().addTrailingSeparator().append("customwizard.tmp").toFile();\r
+            FileWriter writer = new FileWriter(tmpFile);\r
+            writer.write(wizard.inputPage.getInputText());\r
+            writer.close();\r
+            \r
+            ITmfTrace trace = new CustomTxtTrace(tmpFile.getName(), definition, tmpFile.getAbsolutePath(), MAX_NUM_ENTRIES);\r
+            previewTable.dispose();\r
+            previewTable = new CustomEventsTable(definition, tableContainer, MAX_NUM_ENTRIES);\r
+            previewTable.setTrace(trace);\r
+            previewTable.getTable().setItemCount(MAX_NUM_ENTRIES); // Trigger parsing\r
+        } catch (FileNotFoundException e) {\r
+            e.printStackTrace();\r
+        } catch (IOException e) {\r
+            e.printStackTrace();\r
+        }\r
+        \r
+        tableContainer.layout();\r
+        container.layout();\r
+    }\r
+\r
+    public List<OutputColumn> extractOutputs() {\r
+        int numColumns = 0;\r
+        for (int i = 0; i < outputs.size(); i++) {\r
+            if (outputs.get(i).enabledButton.getSelection()) {\r
+                numColumns++;\r
+            }\r
+        }\r
+        List<OutputColumn> outputColumns = new ArrayList<OutputColumn>(numColumns);\r
+        numColumns = 0;\r
+        for (int i = 0; i < outputs.size(); i++) {\r
+            Output output = outputs.get(i);\r
+            if (output.enabledButton.getSelection()) {\r
+                OutputColumn column = new OutputColumn();\r
+                column.name = output.nameLabel.getText();\r
+                outputColumns.add(column); \r
+            }\r
+        }\r
+        return outputColumns;\r
+    }\r
+\r
+    private class Output {\r
+        String name;\r
+        Button enabledButton;\r
+        Text nameLabel;\r
+        Button upButton;\r
+        Button downButton;\r
+        \r
+        public Output(Composite parent, String name) {\r
+            this.name = name;\r
+            \r
+            enabledButton = new Button(parent, SWT.CHECK);\r
+            enabledButton.setToolTipText("Visible");\r
+            enabledButton.setSelection(true);\r
+            enabledButton.addSelectionListener(new SelectionAdapter() {\r
+                public void widgetSelected(SelectionEvent e) {\r
+                    updatePreviewTable();\r
+                }\r
+            });\r
+            if (messageOutput != null) {\r
+                enabledButton.moveAbove(messageOutput.enabledButton);\r
+            }\r
+            \r
+            nameLabel = new Text(parent, SWT.BORDER | SWT.READ_ONLY | SWT.SINGLE);\r
+            nameLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));\r
+            nameLabel.setText(name);\r
+            nameLabel.moveBelow(enabledButton);\r
+\r
+            upButton = new Button(parent, SWT.PUSH);\r
+            upButton.setImage(upImage);\r
+            upButton.setToolTipText("Move Before");\r
+            upButton.addSelectionListener(new SelectionAdapter() {\r
+                public void widgetSelected(SelectionEvent e) {\r
+                    moveBefore(Output.this);\r
+                }\r
+            });\r
+            upButton.moveBelow(nameLabel);\r
+            \r
+            downButton = new Button(parent, SWT.PUSH);\r
+            downButton.setImage(downImage);\r
+            downButton.setToolTipText("Move After");\r
+            downButton.addSelectionListener(new SelectionAdapter() {\r
+                public void widgetSelected(SelectionEvent e) {\r
+                    moveAfter(Output.this);\r
+                }\r
+            });\r
+            downButton.moveBelow(upButton);\r
+        }\r
+\r
+        private void dispose() {\r
+            enabledButton.dispose();\r
+            nameLabel.dispose();\r
+            upButton.dispose();\r
+            downButton.dispose();\r
+        }\r
+    }\r
+\r
+    public CustomTxtTraceDefinition getDefinition() {\r
+        return definition;\r
+    }\r
+    \r
+}\r
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/wizards/CustomTxtParserWizard.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/wizards/CustomTxtParserWizard.java
new file mode 100644 (file)
index 0000000..e6ae71f
--- /dev/null
@@ -0,0 +1,75 @@
+package org.eclipse.linuxtools.tmf.ui.wizards;\r
+\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.eclipse.jface.viewers.IStructuredSelection;\r
+import org.eclipse.jface.wizard.Wizard;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomTxtTraceDefinition;\r
+import org.eclipse.ui.INewWizard;\r
+import org.eclipse.ui.IWorkbench;\r
+\r
+public class CustomTxtParserWizard extends Wizard implements INewWizard {\r
+\r
+    CustomTxtParserInputWizardPage inputPage;\r
+    CustomTxtParserOutputWizardPage outputPage;\r
+    private ISelection selection;\r
+    CustomTxtTraceDefinition definition;\r
+\r
+    public CustomTxtParserWizard() {\r
+        super();\r
+    }\r
+\r
+    public CustomTxtParserWizard(CustomTxtTraceDefinition definition) {\r
+        super();\r
+        this.definition = definition;\r
+    }\r
+\r
+    @Override\r
+    public boolean performFinish() {\r
+        CustomTxtTraceDefinition def = outputPage.getDefinition();\r
+        if (definition != null && !definition.definitionName.equals(def.definitionName)) {\r
+            CustomTxtTraceDefinition.delete(definition.definitionName);\r
+        }\r
+        def.save();\r
+        /*\r
+        if (this.selection instanceof IStructuredSelection) {\r
+            Object selection = ((IStructuredSelection)this.selection).getFirstElement();\r
+            if (selection instanceof IFile) {\r
+                IFile file = (IFile)selection;\r
+                IEditorInput editorInput = new FileEditorInput(file);\r
+                IWorkbench wb = PlatformUI.getWorkbench();\r
+                IWorkbenchPage activePage = wb.getActiveWorkbenchWindow().getActivePage();\r
+        \r
+                IEditorPart editor = activePage.findEditor(editorInput);\r
+                if (editor != null && editor instanceof GenericTableEditor) {\r
+                    activePage.reuseEditor((IReusableEditor)editor, editorInput);\r
+                    activePage.activate(editor);\r
+                } else {\r
+                    try {\r
+                        editor = activePage.openEditor(editorInput, GenericTableEditor.ID);\r
+                    } catch (PartInitException e) {\r
+                        // TODO Auto-generated catch block\r
+                        e.printStackTrace();\r
+                    }\r
+                }\r
+            }\r
+        }\r
+        */\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Adding the page to the wizard.\r
+     */\r
+\r
+    public void addPages() {\r
+        inputPage = new CustomTxtParserInputWizardPage(selection, definition);\r
+        addPage(inputPage);\r
+        outputPage = new CustomTxtParserOutputWizardPage(this);\r
+        addPage(outputPage);\r
+    }\r
+\r
+    public void init(IWorkbench workbench, IStructuredSelection selection) {\r
+        this.selection = selection;\r
+    }\r
+\r
+}\r
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/wizards/CustomXmlParserInputWizardPage.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/wizards/CustomXmlParserInputWizardPage.java
new file mode 100644 (file)
index 0000000..fea8527
--- /dev/null
@@ -0,0 +1,1565 @@
+package org.eclipse.linuxtools.tmf.ui.wizards;\r
+\r
+import java.io.BufferedReader;\r
+import java.io.ByteArrayInputStream;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.io.InputStreamReader;\r
+import java.text.ParseException;\r
+import java.text.SimpleDateFormat;\r
+import java.util.ArrayList;\r
+import java.util.Date;\r
+import java.util.List;\r
+\r
+import javax.xml.parsers.DocumentBuilder;\r
+import javax.xml.parsers.DocumentBuilderFactory;\r
+import javax.xml.parsers.ParserConfigurationException;\r
+\r
+import org.eclipse.core.resources.IFile;\r
+import org.eclipse.core.runtime.CoreException;\r
+import org.eclipse.jface.viewers.ColumnLabelProvider;\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.eclipse.jface.viewers.ISelectionChangedListener;\r
+import org.eclipse.jface.viewers.IStructuredSelection;\r
+import org.eclipse.jface.viewers.ITreeContentProvider;\r
+import org.eclipse.jface.viewers.SelectionChangedEvent;\r
+import org.eclipse.jface.viewers.StructuredSelection;\r
+import org.eclipse.jface.viewers.TreeViewer;\r
+import org.eclipse.jface.viewers.Viewer;\r
+import org.eclipse.jface.wizard.WizardPage;\r
+import org.eclipse.linuxtools.tmf.ui.TmfUiPlugin;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomXmlTrace;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomXmlTraceDefinition;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomXmlTraceDefinition.InputAttribute;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomXmlTraceDefinition.InputElement;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.browser.Browser;\r
+import org.eclipse.swt.browser.TitleEvent;\r
+import org.eclipse.swt.browser.TitleListener;\r
+import org.eclipse.swt.custom.SashForm;\r
+import org.eclipse.swt.custom.ScrolledComposite;\r
+import org.eclipse.swt.custom.StyleRange;\r
+import org.eclipse.swt.custom.StyledText;\r
+import org.eclipse.swt.events.ModifyEvent;\r
+import org.eclipse.swt.events.ModifyListener;\r
+import org.eclipse.swt.events.SelectionAdapter;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.events.SelectionListener;\r
+import org.eclipse.swt.graphics.Color;\r
+import org.eclipse.swt.graphics.Font;\r
+import org.eclipse.swt.graphics.FontData;\r
+import org.eclipse.swt.graphics.Image;\r
+import org.eclipse.swt.layout.FillLayout;\r
+import org.eclipse.swt.layout.GridData;\r
+import org.eclipse.swt.layout.GridLayout;\r
+import org.eclipse.swt.widgets.Button;\r
+import org.eclipse.swt.widgets.Combo;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.swt.widgets.Group;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.eclipse.swt.widgets.Shell;\r
+import org.eclipse.swt.widgets.Text;\r
+import org.w3c.dom.Document;\r
+import org.w3c.dom.Element;\r
+import org.w3c.dom.NamedNodeMap;\r
+import org.w3c.dom.Node;\r
+import org.w3c.dom.NodeList;\r
+import org.xml.sax.EntityResolver;\r
+import org.xml.sax.ErrorHandler;\r
+import org.xml.sax.InputSource;\r
+import org.xml.sax.SAXException;\r
+import org.xml.sax.SAXParseException;\r
+\r
+public class CustomXmlParserInputWizardPage extends WizardPage {\r
+\r
+    private static final String DEFAULT_TIMESTAMP_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS";\r
+    private static final String SIMPLE_DATE_FORMAT_URL = "http://java.sun.com/javase/6/docs/api/java/text/SimpleDateFormat.html#skip-navbar_top";\r
+    private static final Image elementImage = TmfUiPlugin.getDefault().getImageFromPath("/icons/element_icon.gif");\r
+    private static final Image addImage = TmfUiPlugin.getDefault().getImageFromPath("/icons/add_button.gif");\r
+    private static final Image addNextImage = TmfUiPlugin.getDefault().getImageFromPath("/icons/addnext_button.gif");\r
+    private static final Image addChildImage = TmfUiPlugin.getDefault().getImageFromPath("/icons/addchild_button.gif");\r
+    private static final Image addManyImage = TmfUiPlugin.getDefault().getImageFromPath("/icons/addmany_button.gif");\r
+    private static final Image deleteImage = TmfUiPlugin.getDefault().getImageFromPath("/icons/delete_button.gif");\r
+    private static final Image moveUpImage = TmfUiPlugin.getDefault().getImageFromPath("/icons/moveup_button.gif");\r
+    private static final Image moveDownImage = TmfUiPlugin.getDefault().getImageFromPath("/icons/movedown_button.gif");\r
+    private static final Image helpImage = TmfUiPlugin.getDefault().getImageFromPath("/icons/help_button.gif");\r
+    private static final Color COLOR_LIGHT_RED = new Color(Display.getDefault(), 255, 192, 192);\r
+    private static final Color COLOR_TEXT_BACKGROUND = Display.getCurrent().getSystemColor(SWT.COLOR_WHITE);\r
+    private static final Color COLOR_WIDGET_BACKGROUND = Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);\r
+\r
+    private ISelection selection;\r
+    private CustomXmlTraceDefinition definition;\r
+    private String editDefinitionName;\r
+    private String defaultDescription;\r
+    private ElementNode selectedElement;\r
+    private Composite container;\r
+    private Text logtypeText;\r
+    private Text timeStampOutputFormatText;\r
+    private Text timeStampPreviewText;\r
+    private Button removeButton;\r
+    private Button addChildButton;\r
+    private Button addNextButton;\r
+    private Button moveUpButton;\r
+    private Button moveDownButton;\r
+    private Button feelingLuckyButton;\r
+    private ScrolledComposite treeScrolledComposite;\r
+    private ScrolledComposite elementScrolledComposite;\r
+    private TreeViewer treeViewer;\r
+    private Composite treeContainer;\r
+    private Composite elementContainer;\r
+    private Text errorText;\r
+    private StyledText inputText;\r
+    private Font fixedFont;\r
+    private UpdateListener updateListener;\r
+    private Browser helpBrowser;\r
+    private Element documentElement;\r
+\r
+    // variables used recursively through element traversal\r
+    private String timeStampValue;\r
+    private String timeStampFormat;\r
+    private boolean timeStampFound;\r
+    private int logEntriesCount;\r
+    private boolean logEntryFound;\r
+    private int logEntryNestedCount;\r
+\r
+    protected CustomXmlParserInputWizardPage(ISelection selection, CustomXmlTraceDefinition definition) {\r
+        super("CustomXmlParserWizardPage");\r
+        if (definition == null) {\r
+            setTitle("New Custom XML Parser");\r
+            defaultDescription = "Create a new custom parser for XML log files";\r
+        } else {\r
+            setTitle("Edit Custom XML Parser");\r
+            defaultDescription = "Edit an existing custom parser for XML log files";\r
+        }\r
+        setDescription(defaultDescription);\r
+        this.selection = selection;\r
+        this.definition = definition;\r
+        if (definition != null) {\r
+            this.editDefinitionName = definition.definitionName;\r
+        }\r
+    }\r
+\r
+    public void createControl(Composite parent) {\r
+        container = new Composite(parent, SWT.NULL);\r
+        container.setLayout(new GridLayout());\r
+\r
+        updateListener = new UpdateListener();\r
+        \r
+        Composite headerComposite = new Composite(container, SWT.FILL);\r
+        GridLayout headerLayout = new GridLayout(5, false);\r
+        headerLayout.marginHeight = 0;\r
+        headerLayout.marginWidth = 0;\r
+        headerComposite.setLayout(headerLayout);\r
+        headerComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));\r
+        \r
+        Label logtypeLabel = new Label(headerComposite, SWT.NULL);\r
+        logtypeLabel.setText("Log type:");\r
+        \r
+        logtypeText = new Text(headerComposite, SWT.BORDER | SWT.SINGLE);\r
+        logtypeText.setLayoutData(new GridData(120, SWT.DEFAULT));\r
+        logtypeText.addModifyListener(updateListener);\r
+        \r
+        Label timeStampFormatLabel = new Label(headerComposite, SWT.NULL);\r
+        timeStampFormatLabel.setText("Time Stamp format:");\r
+        \r
+        timeStampOutputFormatText = new Text(headerComposite, SWT.BORDER | SWT.SINGLE);\r
+        timeStampOutputFormatText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));\r
+        timeStampOutputFormatText.setText(DEFAULT_TIMESTAMP_FORMAT);\r
+        timeStampOutputFormatText.addModifyListener(updateListener);\r
+\r
+        Button dateFormatHelpButton = new Button(headerComposite, SWT.PUSH);\r
+        dateFormatHelpButton.setImage(helpImage);\r
+        dateFormatHelpButton.setToolTipText("Date Format Help");\r
+        dateFormatHelpButton.addSelectionListener(new SelectionAdapter() {\r
+            public void widgetSelected(SelectionEvent e) {\r
+                openHelpShell(SIMPLE_DATE_FORMAT_URL);\r
+            }\r
+        });\r
+        \r
+        Label timeStampPreviewLabel = new Label(headerComposite, SWT.NULL);\r
+        timeStampPreviewLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 3, 1));\r
+        timeStampPreviewLabel.setText("Preview:");\r
+        \r
+        timeStampPreviewText = new Text(headerComposite, SWT.BORDER | SWT.SINGLE | SWT.READ_ONLY);\r
+        timeStampPreviewText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));\r
+        timeStampPreviewText.setText("*no time stamp element or attribute*");\r
+\r
+        createButtonBar();\r
+        \r
+        SashForm vSash = new SashForm(container, SWT.VERTICAL);\r
+        vSash.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));\r
+        vSash.setBackground(vSash.getDisplay().getSystemColor(SWT.COLOR_GRAY));\r
+\r
+        SashForm hSash = new SashForm(vSash, SWT.HORIZONTAL);\r
+        hSash.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));\r
+\r
+        treeScrolledComposite = new ScrolledComposite(hSash, SWT.V_SCROLL | SWT.H_SCROLL);\r
+        treeScrolledComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));\r
+        treeContainer = new Composite(treeScrolledComposite, SWT.NONE);\r
+        treeContainer.setLayout(new FillLayout());\r
+        treeScrolledComposite.setContent(treeContainer);\r
+        treeScrolledComposite.setExpandHorizontal(true);\r
+        treeScrolledComposite.setExpandVertical(true);\r
+        \r
+        treeViewer = new TreeViewer(treeContainer, SWT.SINGLE | SWT.BORDER);\r
+        treeViewer.setContentProvider(new InputElementTreeNodeContentProvider());\r
+        treeViewer.setLabelProvider(new InputElementTreeLabelProvider());\r
+        treeViewer.addSelectionChangedListener(new InputElementTreeSelectionChangedListener());\r
+        treeContainer.layout();\r
+        \r
+        treeScrolledComposite.setMinSize(treeContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x, treeContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);\r
+        \r
+        elementScrolledComposite = new ScrolledComposite(hSash, SWT.V_SCROLL);\r
+        elementScrolledComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));\r
+        elementContainer = new Composite(elementScrolledComposite, SWT.NONE);\r
+        GridLayout gl = new GridLayout();\r
+        gl.marginHeight = 1;\r
+        gl.marginWidth = 0;\r
+        elementContainer.setLayout(gl);\r
+        elementScrolledComposite.setContent(elementContainer);\r
+        elementScrolledComposite.setExpandHorizontal(true);\r
+        elementScrolledComposite.setExpandVertical(true);\r
+\r
+        if (definition == null) {\r
+            definition = new CustomXmlTraceDefinition();\r
+        }\r
+        loadDefinition(definition);\r
+        treeViewer.expandAll();\r
+        elementContainer.layout();\r
+        \r
+        elementScrolledComposite.setMinSize(elementContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x, elementContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y-1);\r
+        \r
+        hSash.setWeights(new int[] {1, 2});\r
+        \r
+        if (definition.rootInputElement == null) {\r
+            removeButton.setEnabled(false);\r
+            addChildButton.setToolTipText("Add document element");\r
+            addNextButton.setEnabled(false);\r
+            moveUpButton.setEnabled(false);\r
+            moveDownButton.setEnabled(false);\r
+        } else { // root is selected\r
+            addNextButton.setEnabled(false);\r
+        }\r
+        \r
+        Composite sashBottom = new Composite(vSash, SWT.NONE);\r
+        GridLayout sashBottomLayout = new GridLayout(2, false);\r
+        sashBottomLayout.marginHeight = 0;\r
+        sashBottomLayout.marginWidth = 0;\r
+        sashBottom.setLayout(sashBottomLayout);\r
+\r
+        Label previewLabel = new Label(sashBottom, SWT.NULL);\r
+        previewLabel.setText("Preview input");\r
+\r
+        errorText = new Text(sashBottom, SWT.SINGLE | SWT.READ_ONLY);\r
+        errorText.setBackground(COLOR_WIDGET_BACKGROUND);\r
+        errorText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));\r
+        errorText.setVisible(false);\r
+        \r
+        inputText = new StyledText(sashBottom, SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL);\r
+        if (fixedFont == null) {\r
+            if (System.getProperty("os.name").contains("Windows")) {\r
+                fixedFont = new Font(Display.getCurrent(), new FontData("Courier New", 10, SWT.NORMAL));\r
+            } else {\r
+                fixedFont = new Font(Display.getCurrent(), new FontData("Monospace", 10, SWT.NORMAL));\r
+            }\r
+        }\r
+        inputText.setFont(fixedFont);\r
+        GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1);\r
+        gd.heightHint = inputText.computeSize(SWT.DEFAULT, inputText.getLineHeight() * 4).y;\r
+        gd.widthHint = 800;\r
+        inputText.setLayoutData(gd);\r
+        inputText.setText(getSelectionText());\r
+        inputText.addModifyListener(new ModifyListener(){\r
+            public void modifyText(ModifyEvent e) {\r
+                parseXmlInput(inputText.getText());\r
+            }});\r
+        inputText.addModifyListener(updateListener);\r
+\r
+        vSash.setWeights(new int[] {hSash.computeSize(SWT.DEFAULT, SWT.DEFAULT).y, sashBottom.computeSize(SWT.DEFAULT, SWT.DEFAULT).y});\r
+        \r
+        setControl(container);\r
+    }\r
+\r
+    private void createButtonBar() {\r
+        Composite buttonBar = new Composite(container, SWT.NONE);\r
+        GridLayout buttonBarLayout = new GridLayout(6, false);\r
+        buttonBarLayout.marginHeight = 0;\r
+        buttonBarLayout.marginWidth = 0;\r
+        buttonBar.setLayout(buttonBarLayout);\r
+        \r
+        removeButton = new Button(buttonBar, SWT.PUSH);\r
+        removeButton.setImage(deleteImage);\r
+        removeButton.setToolTipText("Remove element");\r
+        removeButton.addSelectionListener(new SelectionAdapter() {\r
+            public void widgetSelected(SelectionEvent e) {\r
+                if (treeViewer.getSelection().isEmpty() || selectedElement == null) return;\r
+                removeElement();\r
+                InputElement inputElement = (InputElement) ((IStructuredSelection) treeViewer.getSelection()).getFirstElement();\r
+                if (inputElement == definition.rootInputElement) {\r
+                    definition.rootInputElement = null;\r
+                } else {\r
+                    inputElement.parentElement.childElements.remove(inputElement);\r
+                }\r
+                treeViewer.refresh();\r
+                validate();\r
+                updatePreviews();\r
+                removeButton.setEnabled(false);\r
+                if (definition.rootInputElement == null) {\r
+                    addChildButton.setEnabled(true);\r
+                    addChildButton.setToolTipText("Add document element");\r
+                } else {\r
+                    addChildButton.setEnabled(false);\r
+                }\r
+                addNextButton.setEnabled(false);\r
+                moveUpButton.setEnabled(false);\r
+                moveDownButton.setEnabled(false);\r
+            }\r
+        });\r
+        \r
+        addChildButton = new Button(buttonBar, SWT.PUSH);\r
+        addChildButton.setImage(addChildImage);\r
+        addChildButton.setToolTipText("Add child element");\r
+        addChildButton.addSelectionListener(new SelectionAdapter() {\r
+            public void widgetSelected(SelectionEvent e) {\r
+                InputElement inputElement = new InputElement("", false, CustomXmlTraceDefinition.TAG_IGNORE, 0, "", null);\r
+                if (definition.rootInputElement == null) {\r
+                    definition.rootInputElement = inputElement;\r
+                    inputElement.elementName = getChildNameSuggestion(null);\r
+                } else if (treeViewer.getSelection().isEmpty()) {\r
+                    return;\r
+                } else {\r
+                    InputElement parentInputElement = (InputElement) ((IStructuredSelection) treeViewer.getSelection()).getFirstElement();\r
+                    parentInputElement.addChild(inputElement);\r
+                    inputElement.elementName = getChildNameSuggestion(parentInputElement);\r
+                }\r
+                treeViewer.refresh();\r
+                treeViewer.setSelection(new StructuredSelection(inputElement), true);\r
+            }\r
+        });\r
+        \r
+        addNextButton = new Button(buttonBar, SWT.PUSH);\r
+        addNextButton.setImage(addNextImage);\r
+        addNextButton.setToolTipText("Add next element");\r
+        addNextButton.addSelectionListener(new SelectionAdapter() {\r
+            public void widgetSelected(SelectionEvent e) {\r
+                InputElement inputElement = new InputElement("", false, CustomXmlTraceDefinition.TAG_IGNORE, 0, "", null);\r
+                if (definition.rootInputElement == null) {\r
+                    definition.rootInputElement = inputElement;\r
+                    inputElement.elementName = getChildNameSuggestion(null);\r
+                } else if (treeViewer.getSelection().isEmpty()) {\r
+                    return;\r
+                } else {\r
+                    InputElement previousInputElement = (InputElement) ((IStructuredSelection) treeViewer.getSelection()).getFirstElement();\r
+                    if (previousInputElement == definition.rootInputElement) {\r
+                        return;\r
+                    } else {\r
+                        previousInputElement.addNext(inputElement);\r
+                        inputElement.elementName = getChildNameSuggestion(inputElement.parentElement);\r
+                    }\r
+                }\r
+                treeViewer.refresh();\r
+                treeViewer.setSelection(new StructuredSelection(inputElement), true);\r
+            }\r
+        });\r
+        \r
+        feelingLuckyButton = new Button(buttonBar, SWT.PUSH);\r
+        feelingLuckyButton.setImage(addManyImage);\r
+        feelingLuckyButton.setToolTipText("Feeling lucky");\r
+        feelingLuckyButton.addSelectionListener(new SelectionAdapter() {\r
+            public void widgetSelected(SelectionEvent e) {\r
+                InputElement inputElement = null;\r
+                if (definition.rootInputElement == null) {\r
+                    if (getChildNameSuggestion(null).length() != 0) {\r
+                        inputElement = new InputElement(getChildNameSuggestion(null), false, CustomXmlTraceDefinition.TAG_IGNORE, 0, "", null);\r
+                        definition.rootInputElement = inputElement;\r
+                        feelingLucky(inputElement);\r
+                    }\r
+                } else if (treeViewer.getSelection().isEmpty()) {\r
+                    return;\r
+                } else {\r
+                    inputElement = (InputElement) ((IStructuredSelection) treeViewer.getSelection()).getFirstElement();\r
+                    feelingLucky(inputElement);\r
+                }\r
+                treeViewer.refresh();\r
+                treeViewer.setSelection(new StructuredSelection(inputElement), true);\r
+                treeViewer.expandToLevel(inputElement, TreeViewer.ALL_LEVELS);\r
+            }\r
+        });\r
+        \r
+        moveUpButton = new Button(buttonBar, SWT.PUSH);\r
+        moveUpButton.setImage(moveUpImage);\r
+        moveUpButton.setToolTipText("Move up");\r
+        moveUpButton.addSelectionListener(new SelectionAdapter() {\r
+            public void widgetSelected(SelectionEvent e) {\r
+                if (treeViewer.getSelection().isEmpty()) return;\r
+                InputElement inputElement = (InputElement) ((IStructuredSelection) treeViewer.getSelection()).getFirstElement();\r
+                if (inputElement == definition.rootInputElement) {\r
+                    return;\r
+                } else {\r
+                    inputElement.moveUp();\r
+                }\r
+                treeViewer.refresh();\r
+                validate();\r
+                updatePreviews();\r
+            }\r
+        });\r
+        \r
+        moveDownButton = new Button(buttonBar, SWT.PUSH);\r
+        moveDownButton.setImage(moveDownImage);\r
+        moveDownButton.setToolTipText("Move down");\r
+        moveDownButton.addSelectionListener(new SelectionAdapter() {\r
+            public void widgetSelected(SelectionEvent e) {\r
+                if (treeViewer.getSelection().isEmpty()) return;\r
+                InputElement inputElement = (InputElement) ((IStructuredSelection) treeViewer.getSelection()).getFirstElement();\r
+                if (inputElement == definition.rootInputElement) {\r
+                    return;\r
+                } else {\r
+                    inputElement.moveDown();\r
+                }\r
+                treeViewer.refresh();\r
+                validate();\r
+                updatePreviews();\r
+            }\r
+        });\r
+    }\r
+\r
+    private void feelingLucky(InputElement inputElement) {\r
+        while (true) {\r
+            String attributeName = getAttributeNameSuggestion(inputElement);\r
+            if (attributeName.length() == 0) {\r
+                break;\r
+            } else {\r
+                InputAttribute attribute = new InputAttribute(attributeName, attributeName, 0, "");\r
+                inputElement.addAttribute(attribute);\r
+            }\r
+        }\r
+        while (true) {\r
+            String childName = getChildNameSuggestion(inputElement);\r
+            if (childName.length() == 0) {\r
+                break;\r
+            } else {\r
+                InputElement childElement = new InputElement(childName, false, CustomXmlTraceDefinition.TAG_IGNORE, 0, "", null);\r
+                inputElement.addChild(childElement);\r
+                feelingLucky(childElement);\r
+            }\r
+        }\r
+    }\r
+    \r
+    private class InputElementTreeNodeContentProvider implements ITreeContentProvider {\r
+\r
+        public Object[] getElements(Object inputElement) {\r
+            CustomXmlTraceDefinition def = (CustomXmlTraceDefinition) inputElement;\r
+            if (def.rootInputElement != null) {\r
+                return new Object[] {def.rootInputElement};\r
+            } else {\r
+                return new Object[0];\r
+            }\r
+        }\r
+\r
+        public Object[] getChildren(Object parentElement) {\r
+            InputElement inputElement = (InputElement) parentElement;\r
+            if (inputElement.childElements == null) return new InputElement[0];\r
+            return inputElement.childElements.toArray();\r
+        }\r
+\r
+        public boolean hasChildren(Object element) {\r
+            InputElement inputElement = (InputElement) element;\r
+            return (inputElement.childElements != null && inputElement.childElements.size() > 0);\r
+        }\r
+\r
+        public void dispose() {\r
+        }\r
+\r
+        public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {\r
+        }\r
+\r
+        public Object getParent(Object element) {\r
+            InputElement inputElement = (InputElement) element;\r
+            return inputElement.parentElement;\r
+        }\r
+    }\r
+    \r
+    private class InputElementTreeLabelProvider extends ColumnLabelProvider {\r
+\r
+        @Override\r
+        public Image getImage(Object element) {\r
+            return elementImage;\r
+        }\r
+\r
+        @Override\r
+        public String getText(Object element) {\r
+            InputElement inputElement = (InputElement) element;\r
+            return (inputElement.elementName.trim().length() == 0) ? "?" : inputElement.elementName;\r
+        }\r
+    }\r
+\r
+    private class InputElementTreeSelectionChangedListener implements ISelectionChangedListener {\r
+        public void selectionChanged(SelectionChangedEvent event) {\r
+            if (selectedElement != null) {\r
+                selectedElement.dispose();\r
+            }\r
+            if (!(event.getSelection().isEmpty()) && event.getSelection() instanceof IStructuredSelection) {\r
+                IStructuredSelection selection = (IStructuredSelection) event.getSelection();\r
+                InputElement inputElement = (InputElement) selection.getFirstElement();\r
+                selectedElement = new ElementNode(elementContainer, inputElement);\r
+                elementContainer.layout();\r
+                elementScrolledComposite.setMinSize(elementContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x, elementContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y-1);\r
+                container.layout();\r
+                validate();\r
+                updatePreviews();\r
+                removeButton.setEnabled(true);\r
+                addChildButton.setEnabled(true);\r
+                addChildButton.setToolTipText("Add child element");\r
+                if (definition.rootInputElement == inputElement) {\r
+                    addNextButton.setEnabled(false);\r
+                } else {\r
+                    addNextButton.setEnabled(true);\r
+                }\r
+                moveUpButton.setEnabled(true);\r
+                moveDownButton.setEnabled(true);\r
+            } else {\r
+                removeButton.setEnabled(false);\r
+                if (definition.rootInputElement == null) {\r
+                    addChildButton.setEnabled(true);\r
+                    addChildButton.setToolTipText("Add document element");\r
+                } else {\r
+                    addChildButton.setEnabled(false);\r
+                }\r
+                addNextButton.setEnabled(false);\r
+                moveUpButton.setEnabled(false);\r
+                moveDownButton.setEnabled(false);\r
+            }\r
+        }\r
+    }\r
+    \r
+    /* (non-Javadoc)\r
+     * @see org.eclipse.jface.dialogs.DialogPage#dispose()\r
+     */\r
+    @Override\r
+    public void dispose() {\r
+        if (fixedFont != null) {\r
+            fixedFont.dispose();\r
+            fixedFont = null;\r
+        }\r
+        super.dispose();\r
+    }\r
+\r
+    private void loadDefinition(CustomXmlTraceDefinition def) {\r
+        logtypeText.setText(def.definitionName);\r
+        timeStampOutputFormatText.setText(def.timeStampOutputFormat);\r
+        treeViewer.setInput(def);\r
+        \r
+        if (def.rootInputElement != null) {\r
+            treeViewer.setSelection(new StructuredSelection(def.rootInputElement));\r
+        }\r
+    }\r
+    \r
+    private String getName(InputElement inputElement) {\r
+        String name = (inputElement.elementName.trim().length() == 0) ? "?" : inputElement.elementName.trim();\r
+        if (inputElement.parentElement == null) {\r
+            return name;\r
+        }\r
+        return getName(inputElement.parentElement) + " : " + name;\r
+    }\r
+\r
+    private String getName(InputAttribute inputAttribute, InputElement inputElement) {\r
+        String name = (inputAttribute.attributeName.trim().length() == 0) ? "?" : inputAttribute.attributeName.trim();\r
+        return getName(inputElement) + " : " + name;\r
+    }\r
+\r
+    /* (non-Javadoc)\r
+     * @see org.eclipse.jface.dialogs.DialogPage#setVisible(boolean)\r
+     */\r
+    @Override\r
+    public void setVisible(boolean visible) {\r
+        if (visible) {\r
+            validate();\r
+            updatePreviews();\r
+        }\r
+        super.setVisible(visible);\r
+    }\r
+\r
+    public List<String> getInputNames() {\r
+        return getInputNames(definition.rootInputElement);\r
+    }\r
+    \r
+    public List<String> getInputNames(InputElement inputElement) {\r
+        List<String> inputs = new ArrayList<String>();\r
+        if (inputElement.inputName != null && !inputElement.inputName.equals(CustomXmlTraceDefinition.TAG_IGNORE)) {\r
+            String inputName = inputElement.inputName;\r
+            if (!inputs.contains(inputName)) {\r
+                inputs.add(inputName);\r
+            }\r
+        }\r
+        if (inputElement.attributes != null) {\r
+            for (InputAttribute attribute : inputElement.attributes) {\r
+                String inputName = attribute.inputName;\r
+                if (!inputs.contains(inputName)) {\r
+                    inputs.add(inputName);\r
+                }\r
+            }\r
+        }\r
+        if (inputElement.childElements != null) {\r
+            for (InputElement childInputElement : inputElement.childElements) {\r
+                for (String inputName : getInputNames(childInputElement)) {\r
+                    if (!inputs.contains(inputName)) {\r
+                        inputs.add(inputName);\r
+                    }\r
+                }\r
+            }\r
+        }\r
+        return inputs;\r
+    }\r
+    \r
+    private void removeElement() {\r
+        selectedElement.dispose();\r
+        selectedElement = null;\r
+        elementContainer.layout();\r
+        elementScrolledComposite.setMinSize(elementContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x, elementContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y-1);\r
+        container.layout();\r
+    }\r
+\r
+    private String getSelectionText() {\r
+        InputStream inputStream = null;\r
+        if (this.selection instanceof IStructuredSelection) {\r
+            Object selection = ((IStructuredSelection)this.selection).getFirstElement();\r
+            if (selection instanceof IFile) {\r
+                IFile file = (IFile)selection;\r
+                try {\r
+                    inputStream = file.getContents();\r
+                } catch (CoreException e) {\r
+                    return "";\r
+                }\r
+            }\r
+        }\r
+        if (inputStream != null) {\r
+            try {\r
+                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));\r
+                StringBuilder sb = new StringBuilder();\r
+                String line = null;\r
+                while ((line = reader.readLine()) != null) {\r
+                    sb.append(line + "\n");\r
+                }\r
+                parseXmlInput(sb.toString());\r
+                return sb.toString();\r
+            } catch (IOException e) {\r
+                return "";\r
+            }\r
+        }\r
+        return "";\r
+    }\r
+    \r
+    private void parseXmlInput(final String string) {\r
+        try {\r
+            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();\r
+            DocumentBuilder db = dbf.newDocumentBuilder();\r
+\r
+            // The following allows xml parsing without access to the dtd\r
+            EntityResolver resolver = new EntityResolver () {\r
+                public InputSource resolveEntity (String publicId, String systemId) {\r
+                    String empty = "";\r
+                    ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes());\r
+                    return new InputSource(bais);\r
+                }\r
+            };\r
+            db.setEntityResolver(resolver);\r
+\r
+            // The following catches xml parsing exceptions\r
+            db.setErrorHandler(new ErrorHandler(){\r
+                public void error(SAXParseException saxparseexception) throws SAXException {}\r
+                public void warning(SAXParseException saxparseexception) throws SAXException {}\r
+                public void fatalError(SAXParseException saxparseexception) throws SAXException {\r
+                    if (string.trim().length() != 0) {\r
+                        errorText.setText(saxparseexception.getMessage());\r
+                        errorText.setBackground(COLOR_LIGHT_RED);\r
+                        errorText.setVisible(true);\r
+                    }\r
+                    throw saxparseexception;\r
+                }});\r
+            \r
+            errorText.setVisible(false);\r
+            Document doc = null;\r
+            doc = db.parse(new ByteArrayInputStream(string.getBytes()));\r
+            documentElement = doc.getDocumentElement();\r
+        } catch (ParserConfigurationException e) {\r
+            e.printStackTrace();\r
+            documentElement = null;\r
+        } catch (SAXException e) {\r
+            documentElement = null;\r
+        } catch (IOException e) {\r
+            e.printStackTrace();\r
+            documentElement = null;\r
+        }\r
+    }\r
+\r
+    private void updatePreviews() {\r
+        updatePreviews(false);\r
+    }\r
+\r
+    private void updatePreviews(boolean updateAll) {\r
+        if (inputText == null) {\r
+            // early update during construction\r
+            return;\r
+        }\r
+        inputText.setStyleRanges(new StyleRange[] {});\r
+        if (selectedElement == null) {\r
+            return;\r
+        }\r
+        \r
+        timeStampValue = null;\r
+        timeStampFormat = null;\r
+        logEntriesCount = 0;\r
+        logEntryFound = false;\r
+        \r
+        selectedElement.updatePreview();\r
+\r
+        if (timeStampValue != null && timeStampFormat != null) {\r
+            try {\r
+                SimpleDateFormat dateFormat = new SimpleDateFormat(timeStampFormat);\r
+                Date date = dateFormat.parse(timeStampValue);\r
+                dateFormat = new SimpleDateFormat(timeStampOutputFormatText.getText().trim());\r
+                timeStampPreviewText.setText(dateFormat.format(date));\r
+            } catch (ParseException e) {\r
+                timeStampPreviewText.setText("*parse exception* [" + timeStampValue + "] <> [" + timeStampFormat + "]");\r
+            } catch (IllegalArgumentException e) {\r
+                timeStampPreviewText.setText("*parse exception* [Illegal Argument]");\r
+            }\r
+        } else {\r
+            timeStampPreviewText.setText("*no matching time stamp*");\r
+        }\r
+    }\r
+\r
+    private void openHelpShell(String url) {\r
+        if (helpBrowser != null && !helpBrowser.isDisposed()) {\r
+            helpBrowser.getShell().setActive();\r
+            if (!helpBrowser.getUrl().equals(url)) {\r
+                helpBrowser.setUrl(url);\r
+            }\r
+            return;\r
+        }\r
+        final Shell helpShell = new Shell(getShell(), SWT.SHELL_TRIM);\r
+        helpShell.setLayout(new FillLayout());\r
+        helpBrowser = new Browser(helpShell, SWT.NONE);\r
+        helpBrowser.addTitleListener(new TitleListener() {\r
+           public void changed(TitleEvent event) {\r
+               helpShell.setText(event.title);\r
+           }\r
+        });\r
+        helpBrowser.setBounds(0,0,600,400);\r
+        helpShell.pack();\r
+        helpShell.open();\r
+        helpBrowser.setUrl(url);\r
+    }\r
+\r
+    private class UpdateListener implements ModifyListener, SelectionListener {\r
+\r
+        public void modifyText(ModifyEvent e) {\r
+            validate();\r
+            updatePreviews();\r
+        }\r
+\r
+        public void widgetDefaultSelected(SelectionEvent e) {\r
+            validate();\r
+            updatePreviews();\r
+        }\r
+\r
+        public void widgetSelected(SelectionEvent e) {\r
+            validate();\r
+            updatePreviews();\r
+        }\r
+\r
+    }\r
+    \r
+    private class ElementNode {\r
+        final InputElement inputElement;\r
+        final Group group;\r
+        ArrayList<Attribute> attributes = new ArrayList<Attribute>();\r
+        ArrayList<ElementNode> childElements = new ArrayList<ElementNode>();\r
+        Text elementNameText;\r
+        Composite tagComposite;\r
+        Combo tagCombo;\r
+        Label tagLabel;\r
+        Text tagText;\r
+        Combo actionCombo;\r
+        Label previewLabel;\r
+        Text previewText;\r
+        Button logEntryButton;\r
+        Label fillerLabel;\r
+        Composite addAttributeComposite;\r
+        Button addAttributeButton;\r
+        Label addAttributeLabel;\r
+        \r
+        public ElementNode(Composite parent, InputElement inputElement) {\r
+            this.inputElement = inputElement;\r
+            \r
+            group = new Group(parent, SWT.NONE);\r
+            GridLayout gl = new GridLayout(2, false);\r
+            gl.marginHeight = 0;\r
+            group.setLayout(gl);\r
+            group.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));\r
+            group.setText(getName(inputElement));\r
+            \r
+            Label label = new Label(group, SWT.NULL);\r
+            label.setText("Element name:");\r
+            label.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));\r
+            \r
+            elementNameText = new Text(group, SWT.BORDER | SWT.SINGLE);\r
+            GridData gd = new GridData(SWT.FILL, SWT.CENTER, true, false);\r
+            gd.widthHint = 0;\r
+            elementNameText.setLayoutData(gd);\r
+            elementNameText.addModifyListener(new ModifyListener(){\r
+                public void modifyText(ModifyEvent e) {\r
+                    ElementNode.this.inputElement.elementName = elementNameText.getText().trim();\r
+                    group.setText(getName(ElementNode.this.inputElement));\r
+                }});\r
+            elementNameText.setText(inputElement.elementName);\r
+            elementNameText.addModifyListener(updateListener);\r
+\r
+            if (inputElement.parentElement != null) {\r
+                previewLabel = new Label(group, SWT.NULL);\r
+                previewLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));\r
+                previewLabel.setText("Preview:");\r
+                \r
+                previewText = new Text(group, SWT.BORDER | SWT.SINGLE | SWT.READ_ONLY);\r
+                gd = new GridData(SWT.FILL, SWT.CENTER, true, false);\r
+                gd.widthHint = 0;\r
+                previewText.setLayoutData(gd);\r
+                previewText.setText("*no matching element*");\r
+                previewText.setBackground(COLOR_WIDGET_BACKGROUND);\r
+                \r
+                logEntryButton = new Button(group, SWT.CHECK);\r
+                logEntryButton.setText("Log Entry");\r
+                logEntryButton.setSelection(inputElement.logEntry);\r
+                logEntryButton.addSelectionListener(new SelectionListener(){\r
+                    public void widgetDefaultSelected(SelectionEvent e) {}\r
+                    public void widgetSelected(SelectionEvent e) {\r
+                        InputElement parent = ElementNode.this.inputElement.parentElement;\r
+                        while (parent != null) {\r
+                            parent.logEntry = false;\r
+                            parent = parent.parentElement;\r
+                        }\r
+                    }});\r
+                logEntryButton.addSelectionListener(updateListener);\r
+    \r
+                tagComposite = new Composite(group, SWT.FILL);\r
+                GridLayout tagLayout = new GridLayout(4, false);\r
+                tagLayout.marginWidth = 0;\r
+                tagLayout.marginHeight = 0;\r
+                tagComposite.setLayout(tagLayout);\r
+                tagComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));\r
+                \r
+                tagCombo = new Combo(tagComposite, SWT.DROP_DOWN | SWT.READ_ONLY);\r
+                tagCombo.setItems(new String[] {CustomXmlTraceDefinition.TAG_IGNORE,\r
+                                                CustomXmlTraceDefinition.TAG_TIMESTAMP,\r
+                                                CustomXmlTraceDefinition.TAG_MESSAGE,\r
+                                                CustomXmlTraceDefinition.TAG_OTHER});\r
+                tagCombo.setVisibleItemCount(tagCombo.getItemCount());\r
+                tagCombo.addSelectionListener(new SelectionListener(){\r
+                    public void widgetDefaultSelected(SelectionEvent e) {}\r
+                    public void widgetSelected(SelectionEvent e) {\r
+                        tagText.removeModifyListener(updateListener);\r
+                        switch (tagCombo.getSelectionIndex()) {\r
+                        case 0: //Ignore\r
+                            tagLabel.setVisible(false);\r
+                            tagText.setVisible(false);\r
+                            actionCombo.setVisible(false);\r
+                            break;\r
+                        case 1: //Time Stamp\r
+                            tagLabel.setText("format:");\r
+                            tagLabel.setVisible(true);\r
+                            tagText.setVisible(true);\r
+                            tagText.addModifyListener(updateListener);\r
+                            actionCombo.setVisible(true);\r
+                            break;\r
+                        case 2: //Message\r
+                            tagLabel.setVisible(false);\r
+                            tagText.setVisible(false);\r
+                            actionCombo.setVisible(true);\r
+                            break;\r
+                        case 3: //Other\r
+                            tagLabel.setText("tag name:");\r
+                            tagLabel.setVisible(true);\r
+                            if (tagText.getText().trim().length() == 0) {\r
+                                tagText.setText(elementNameText.getText().trim());\r
+                            }\r
+                            tagText.setVisible(true);\r
+                            tagText.addModifyListener(updateListener);\r
+                            actionCombo.setVisible(true);\r
+                            break;\r
+                        }\r
+                        tagComposite.layout();\r
+                        validate();\r
+                        updatePreviews();\r
+                    }});\r
+                \r
+                tagLabel = new Label(tagComposite, SWT.NULL);\r
+                tagLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));\r
+                \r
+                tagText = new Text(tagComposite, SWT.BORDER | SWT.SINGLE);\r
+                gd = new GridData(SWT.FILL, SWT.CENTER, true, false);\r
+                gd.widthHint = 0;\r
+                tagText.setLayoutData(gd);\r
+                \r
+                actionCombo = new Combo(tagComposite, SWT.DROP_DOWN | SWT.READ_ONLY);\r
+                actionCombo.setItems(new String[] {"Set", "Append", "Append with |"});\r
+                actionCombo.select(inputElement.inputAction);\r
+                actionCombo.addSelectionListener(updateListener);\r
+                \r
+                if (inputElement.inputName.equals(CustomXmlTraceDefinition.TAG_IGNORE)) {\r
+                    tagCombo.select(0);\r
+                    tagLabel.setVisible(false);\r
+                    tagText.setVisible(false);\r
+                    actionCombo.setVisible(false);\r
+                } else if (inputElement.inputName.equals(CustomXmlTraceDefinition.TAG_TIMESTAMP)) {\r
+                    tagCombo.select(1);\r
+                    tagLabel.setText("format:");\r
+                    tagText.setText(inputElement.inputFormat);\r
+                    tagText.addModifyListener(updateListener);\r
+                } else if (inputElement.inputName.equals(CustomXmlTraceDefinition.TAG_MESSAGE)) {\r
+                    tagCombo.select(2);\r
+                    tagLabel.setVisible(false);\r
+                    tagText.setVisible(false);\r
+                } else {\r
+                    tagCombo.select(3);\r
+                    tagLabel.setText("tag name:");\r
+                    tagText.setText(inputElement.inputName);\r
+                    tagText.addModifyListener(updateListener);\r
+                }\r
+            }\r
+\r
+            if (inputElement.attributes != null) {\r
+                for (InputAttribute inputAttribute : inputElement.attributes) {\r
+                    Attribute attribute = new Attribute(group, this, inputAttribute, attributes.size()+1);\r
+                    attributes.add(attribute);\r
+                }\r
+            }\r
+            \r
+            createAddButton();\r
+        }\r
+        \r
+        private void updatePreview() {\r
+            Element element = getPreviewElement(inputElement);\r
+            if (inputElement.parentElement != null) { // no preview text for document element\r
+                previewText.setText("*no matching element*");\r
+                if (element != null) {\r
+                    previewText.setText(CustomXmlTrace.parseElement(element, new StringBuffer()).toString());\r
+                    if (logEntryButton.getSelection()) {\r
+                        if (logEntryFound == false) {\r
+                            logEntryFound = true;\r
+                            logEntriesCount++;\r
+                        } else {\r
+                            logEntryButton.setSelection(false); // remove nested log entry\r
+                        }\r
+                    }\r
+                    if (tagCombo.getText().equals(CustomXmlTraceDefinition.TAG_TIMESTAMP) && logEntriesCount <= 1) {\r
+                        String value = previewText.getText().trim();\r
+                        if (value.length() != 0) {\r
+                            if (actionCombo.getSelectionIndex() == CustomXmlTraceDefinition.ACTION_SET) {\r
+                                timeStampValue = value;\r
+                                timeStampFormat = tagText.getText().trim();\r
+                            } else if (actionCombo.getSelectionIndex() == CustomXmlTraceDefinition.ACTION_APPEND) {\r
+                                if (timeStampValue != null) {\r
+                                    timeStampValue += value;\r
+                                    timeStampFormat += tagText.getText().trim();\r
+                                } else {\r
+                                    timeStampValue = value;\r
+                                    timeStampFormat = tagText.getText().trim();\r
+                                }\r
+                            } else if (actionCombo.getSelectionIndex() == CustomXmlTraceDefinition.ACTION_APPEND_WITH_SEPARATOR) {\r
+                                if (timeStampValue != null) {\r
+                                    timeStampValue += " | " + value;\r
+                                    timeStampFormat += " | " + tagText.getText().trim();\r
+                                } else {\r
+                                    timeStampValue = value;\r
+                                    timeStampFormat = tagText.getText().trim();\r
+                                }\r
+                            }\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+            for (Attribute attribute : attributes) {\r
+                if (element != null) {\r
+                    String value = element.getAttribute(attribute.attributeNameText.getText().trim());\r
+                    if (value.length() != 0) {\r
+                        attribute.previewText.setText(value);\r
+                        if (attribute.tagCombo.getText().equals(CustomXmlTraceDefinition.TAG_TIMESTAMP) && logEntriesCount <= 1) {\r
+                            if (attribute.actionCombo.getSelectionIndex() == CustomXmlTraceDefinition.ACTION_SET) {\r
+                                timeStampValue = value;\r
+                                timeStampFormat = attribute.tagText.getText().trim();\r
+                            } else if (attribute.actionCombo.getSelectionIndex() == CustomXmlTraceDefinition.ACTION_APPEND) {\r
+                                if (timeStampValue != null) {\r
+                                    timeStampValue += value;\r
+                                    timeStampFormat += attribute.tagText.getText().trim();\r
+                                } else {\r
+                                    timeStampValue = value;\r
+                                    timeStampFormat = attribute.tagText.getText().trim();\r
+                                }\r
+                            } else if (attribute.actionCombo.getSelectionIndex() == CustomXmlTraceDefinition.ACTION_APPEND_WITH_SEPARATOR) {\r
+                                if (timeStampValue != null) {\r
+                                    timeStampValue += " | " + value;\r
+                                    timeStampFormat += " | " + attribute.tagText.getText().trim();\r
+                                } else {\r
+                                    timeStampValue = value;\r
+                                    timeStampFormat = attribute.tagText.getText().trim();\r
+                                }\r
+                            }\r
+                        }\r
+                    } else {\r
+                        attribute.previewText.setText("*no matching attribute*");\r
+                    }\r
+                } else {\r
+                    attribute.previewText.setText("*no matching element*");\r
+                }\r
+            }\r
+            for (ElementNode child : childElements) {\r
+                child.updatePreview();\r
+            }\r
+            if (logEntryButton != null && logEntryButton.getSelection()) {\r
+                logEntryFound = false;\r
+            }\r
+        }\r
+\r
+        private void createAddButton() {\r
+            fillerLabel = new Label(group, SWT.NONE);\r
+            \r
+            addAttributeComposite = new Composite(group, SWT.NONE);\r
+            addAttributeComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));\r
+            GridLayout addAttributeLayout = new GridLayout(2, false);\r
+            addAttributeLayout.marginHeight = 0;\r
+            addAttributeLayout.marginWidth = 0;\r
+            addAttributeComposite.setLayout(addAttributeLayout);\r
+            \r
+            addAttributeButton = new Button(addAttributeComposite, SWT.PUSH);\r
+            addAttributeButton.setImage(addImage);\r
+            addAttributeButton.setToolTipText("Add attribute");\r
+            addAttributeButton.addSelectionListener(new SelectionAdapter() {\r
+                public void widgetSelected(SelectionEvent e) {\r
+                    removeAddButton();\r
+                    String attributeName = getAttributeNameSuggestion(inputElement);\r
+                    InputAttribute inputAttribute = new InputAttribute(attributeName, attributeName, 0, "");\r
+                    attributes.add(new Attribute(group, ElementNode.this, inputAttribute, attributes.size()+1));\r
+                    createAddButton();\r
+                    elementContainer.layout();\r
+                    elementScrolledComposite.setMinSize(elementContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x, elementContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y-1);\r
+                    group.getParent().layout();\r
+                    validate();\r
+                    updatePreviews();\r
+                }\r
+            });\r
+            \r
+            addAttributeLabel = new Label(addAttributeComposite, SWT.NULL);\r
+            addAttributeLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));\r
+            addAttributeLabel.setText("New attribute");\r
+        }\r
+\r
+        private void removeAddButton() {\r
+            fillerLabel.dispose();\r
+            addAttributeComposite.dispose();\r
+        }\r
+        \r
+        private void removeAttribute(int attributeNumber) {\r
+            if (--attributeNumber < attributes.size()) {\r
+                attributes.remove(attributeNumber).dispose();\r
+                for (int i = attributeNumber; i < attributes.size(); i++) {\r
+                    attributes.get(i).setAttributeNumber(i+1);\r
+                }\r
+                elementContainer.layout();\r
+                elementScrolledComposite.setMinSize(elementContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x, elementContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y-1);\r
+                group.getParent().layout();\r
+            }\r
+        }\r
+        \r
+        private void dispose() {\r
+            group.dispose();\r
+        }\r
+\r
+        private void extractInputs() {\r
+            inputElement.elementName = elementNameText.getText().trim();\r
+            if (inputElement.parentElement != null) {\r
+                inputElement.logEntry = logEntryButton.getSelection();\r
+                if (tagCombo.getText().equals(CustomXmlTraceDefinition.TAG_OTHER)) {\r
+                    inputElement.inputName = tagText.getText().trim();\r
+                } else {\r
+                    inputElement.inputName = tagCombo.getText();\r
+                    if (tagCombo.getText().equals(CustomXmlTraceDefinition.TAG_TIMESTAMP)) {\r
+                        inputElement.inputFormat = tagText.getText().trim();\r
+                    }\r
+                }\r
+                inputElement.inputAction = actionCombo.getSelectionIndex();\r
+            }\r
+            inputElement.attributes = new ArrayList<InputAttribute>(attributes.size());\r
+            for (int i = 0; i < attributes.size(); i++) {\r
+                Attribute attribute = attributes.get(i);\r
+                InputAttribute inputAttribute = new InputAttribute();\r
+                inputAttribute.attributeName = attribute.attributeNameText.getText().trim();\r
+                if (attribute.tagCombo.getText().equals(CustomXmlTraceDefinition.TAG_OTHER)) {\r
+                    inputAttribute.inputName = attribute.tagText.getText().trim();\r
+                } else {\r
+                    inputAttribute.inputName = attribute.tagCombo.getText();\r
+                    if (attribute.tagCombo.getText().equals(CustomXmlTraceDefinition.TAG_TIMESTAMP)) {\r
+                        inputAttribute.inputFormat = attribute.tagText.getText().trim();\r
+                    }\r
+                }\r
+                inputAttribute.inputAction = attribute.actionCombo.getSelectionIndex();\r
+                inputElement.addAttribute(inputAttribute);\r
+            }\r
+        }\r
+    }\r
+\r
+    private class Attribute {\r
+        ElementNode element;\r
+        int attributeNumber;\r
+        \r
+        // children of parent (must be disposed)\r
+        Composite labelComposite;\r
+        Composite attributeComposite;\r
+        Label filler;\r
+        Composite tagComposite;\r
+\r
+        // children of labelComposite\r
+        Label attributeLabel;\r
+        \r
+        // children of attributeComposite\r
+        Text attributeNameText;\r
+        Text previewText;\r
+        \r
+        // children of tagComposite\r
+        Combo tagCombo;\r
+        Label tagLabel;\r
+        Text tagText;\r
+        Combo actionCombo;\r
+        \r
+        public Attribute(Composite parent, ElementNode element, InputAttribute inputAttribute, int attributeNumber) {\r
+            this.element = element;\r
+            this.attributeNumber = attributeNumber;\r
+            \r
+            labelComposite = new Composite(parent, SWT.FILL);\r
+            GridLayout labelLayout = new GridLayout(2, false);\r
+            labelLayout.marginWidth = 0;\r
+            labelLayout.marginHeight = 0;\r
+            labelComposite.setLayout(labelLayout);\r
+            labelComposite.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));\r
+            \r
+            Button deleteButton = new Button(labelComposite, SWT.PUSH);\r
+            deleteButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));\r
+            deleteButton.setImage(deleteImage);\r
+            deleteButton.setToolTipText("Remove attribute");\r
+            deleteButton.addSelectionListener(new SelectionAdapter() {\r
+                public void widgetSelected(SelectionEvent e) {\r
+                    Attribute.this.element.removeAttribute(Attribute.this.attributeNumber);\r
+                    validate();\r
+                    updatePreviews();\r
+                }\r
+            });\r
+            \r
+            attributeLabel = new Label(labelComposite, SWT.NULL);\r
+            attributeLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));\r
+            attributeLabel.setText("Attribute");\r
+            \r
+            attributeComposite = new Composite(parent, SWT.FILL);\r
+            GridLayout attributeLayout = new GridLayout(4, false);\r
+            attributeLayout.marginWidth = 0;\r
+            attributeLayout.marginHeight = 0;\r
+            attributeComposite.setLayout(attributeLayout);\r
+            attributeComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));\r
+\r
+            Label nameLabel = new Label(attributeComposite, SWT.NONE);\r
+            nameLabel.setText("name:");\r
+            \r
+            attributeNameText = new Text(attributeComposite, SWT.BORDER | SWT.SINGLE);\r
+            attributeNameText.setLayoutData(new GridData(120, SWT.DEFAULT));\r
+            attributeNameText.setText(inputAttribute.attributeName);\r
+            attributeNameText.addModifyListener(updateListener);\r
+            \r
+            Label previewLabel = new Label(attributeComposite, SWT.NONE);\r
+            previewLabel.setText("Preview:");\r
+            \r
+            previewText = new Text(attributeComposite, SWT.BORDER | SWT.SINGLE | SWT.READ_ONLY);\r
+            GridData gd = new GridData(SWT.FILL, SWT.CENTER, true, false);\r
+            gd.widthHint = 0;\r
+            previewText.setLayoutData(gd);\r
+            previewText.setText("*no match*");\r
+            previewText.setBackground(COLOR_WIDGET_BACKGROUND);\r
+\r
+            filler = new Label(parent, SWT.NULL);\r
+            \r
+            tagComposite = new Composite(parent, SWT.FILL);\r
+            GridLayout tagLayout = new GridLayout(4, false);\r
+            tagLayout.marginWidth = 0;\r
+            tagLayout.marginHeight = 0;\r
+            tagComposite.setLayout(tagLayout);\r
+            tagComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));\r
+            \r
+            tagCombo = new Combo(tagComposite, SWT.DROP_DOWN | SWT.READ_ONLY);\r
+            tagCombo.setItems(new String[] {CustomXmlTraceDefinition.TAG_TIMESTAMP,\r
+                                            CustomXmlTraceDefinition.TAG_MESSAGE,\r
+                                            CustomXmlTraceDefinition.TAG_OTHER});\r
+            tagCombo.select(2); //Other\r
+            tagCombo.addSelectionListener(new SelectionListener(){\r
+                public void widgetDefaultSelected(SelectionEvent e) {}\r
+                public void widgetSelected(SelectionEvent e) {\r
+                    tagText.removeModifyListener(updateListener);\r
+                    switch (tagCombo.getSelectionIndex()) {\r
+                    case 0: //Time Stamp\r
+                        tagLabel.setText("format:");\r
+                        tagLabel.setVisible(true);\r
+                        tagText.setVisible(true);\r
+                        tagText.addModifyListener(updateListener);\r
+                        break;\r
+                    case 1: //Message\r
+                        tagLabel.setVisible(false);\r
+                        tagText.setVisible(false);\r
+                        break;\r
+                    case 2: //Other\r
+                        tagLabel.setText("tag name:");\r
+                        tagLabel.setVisible(true);\r
+                        if (tagText.getText().trim().length() == 0) {\r
+                            tagText.setText(attributeNameText.getText().trim());\r
+                        }\r
+                        tagText.setVisible(true);\r
+                        tagText.addModifyListener(updateListener);\r
+                        break;\r
+                    }\r
+                    tagComposite.layout();\r
+                    validate();\r
+                    updatePreviews();\r
+                }});\r
+            \r
+            tagLabel = new Label(tagComposite, SWT.NULL);\r
+            tagLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));\r
+            \r
+            tagText = new Text(tagComposite, SWT.BORDER | SWT.SINGLE);\r
+            gd = new GridData(SWT.FILL, SWT.CENTER, true, false);\r
+            gd.widthHint = 0;\r
+            tagText.setLayoutData(gd);\r
+            tagText.setText(attributeNameText.getText());\r
+            \r
+            actionCombo = new Combo(tagComposite, SWT.DROP_DOWN | SWT.READ_ONLY);\r
+            actionCombo.setItems(new String[] {"Set", "Append", "Append with |"});\r
+            actionCombo.select(inputAttribute.inputAction);\r
+            actionCombo.addSelectionListener(updateListener);\r
+            \r
+            if (inputAttribute.inputName.equals(CustomXmlTraceDefinition.TAG_TIMESTAMP)) {\r
+                tagCombo.select(0);\r
+                tagLabel.setText("format:");\r
+                tagText.setText(inputAttribute.inputFormat);\r
+                tagText.addModifyListener(updateListener);\r
+            } else if (inputAttribute.inputName.equals(CustomXmlTraceDefinition.TAG_MESSAGE)) {\r
+                tagCombo.select(1);\r
+                tagLabel.setVisible(false);\r
+                tagText.setVisible(false);\r
+            } else {\r
+                tagCombo.select(2);\r
+                tagLabel.setText("tag name:");\r
+                tagText.setText(inputAttribute.inputName);\r
+                tagText.addModifyListener(updateListener);\r
+            }\r
+        }\r
+        \r
+        private void dispose() {\r
+            labelComposite.dispose();\r
+            attributeComposite.dispose();\r
+            filler.dispose();\r
+            tagComposite.dispose();\r
+        }\r
+        \r
+        private void setAttributeNumber(int attributeNumber) {\r
+            this.attributeNumber = attributeNumber;\r
+            labelComposite.layout();\r
+        }\r
+    }\r
+\r
+    private Element getPreviewElement(InputElement inputElement) {\r
+        Element element = documentElement;\r
+        if (element != null) {\r
+            if (!documentElement.getNodeName().equals(definition.rootInputElement.elementName)) {\r
+                return null;\r
+            }\r
+            ArrayList<String> elementNames = new ArrayList<String>();\r
+            while (inputElement != null) {\r
+                elementNames.add(inputElement.elementName);\r
+                inputElement = inputElement.parentElement;\r
+            }\r
+            for (int i = elementNames.size() - 1; --i >= 0;) {\r
+                NodeList childList = element.getChildNodes();\r
+                element = null;\r
+                for (int j = 0; j < childList.getLength(); j++) {\r
+                    Node child = childList.item(j);\r
+                    if (child instanceof Element && child.getNodeName().equals(elementNames.get(i))) {\r
+                        element = (Element)child;\r
+                        break;\r
+                    }\r
+                }\r
+                if (element == null) {\r
+                    break;\r
+                }\r
+            }\r
+            if (element != null) {\r
+                return element;\r
+            }\r
+        }\r
+        return null;\r
+    }\r
+    \r
+    private String getChildNameSuggestion(InputElement inputElement) {\r
+        if (inputElement == null) {\r
+            if (documentElement != null) {\r
+                return documentElement.getNodeName();\r
+            }\r
+        } else {\r
+            Element element = getPreviewElement(inputElement);\r
+            if (element != null) {\r
+                NodeList childNodes = element.getChildNodes();\r
+                for (int i = 0; i < childNodes.getLength(); i++) {\r
+                    Node node = childNodes.item(i);\r
+                    if (node instanceof Element) {\r
+                        boolean unused = true;\r
+                        if (inputElement.childElements != null) {\r
+                            for (InputElement child : inputElement.childElements) {\r
+                                if (child.elementName.equals(node.getNodeName())) {\r
+                                    unused = false;\r
+                                    break;\r
+                                }\r
+                            }\r
+                        }\r
+                        if (unused) {\r
+                            return node.getNodeName();\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+        }\r
+        return ("");\r
+    }\r
+    \r
+    private String getAttributeNameSuggestion(InputElement inputElement) {\r
+        Element element = getPreviewElement(inputElement);\r
+        if (element != null) {\r
+            NamedNodeMap attributeMap = element.getAttributes();\r
+            for (int i = 0; i < attributeMap.getLength(); i++) {\r
+                Node node = attributeMap.item(i);\r
+                boolean unused = true;\r
+                if (inputElement.attributes != null) {\r
+                    for (InputAttribute attribute : inputElement.attributes) {\r
+                        if (attribute.attributeName.equals(node.getNodeName())) {\r
+                            unused = false;\r
+                            break;\r
+                        }\r
+                    }\r
+                }\r
+                if (unused) {\r
+                    return node.getNodeName();\r
+                }\r
+            }\r
+        }\r
+        return ("");\r
+    }\r
+\r
+    private void validate() {\r
+        definition.definitionName = logtypeText.getText().trim();\r
+        definition.timeStampOutputFormat = timeStampOutputFormatText.getText().trim();\r
+        \r
+        if (selectedElement != null) {\r
+            selectedElement.extractInputs();\r
+            treeViewer.refresh();\r
+        }\r
+        \r
+        StringBuffer errors = new StringBuffer();\r
+\r
+        if (definition.definitionName.length() == 0) {\r
+            errors.append("Enter a name for the new log type. ");\r
+            logtypeText.setBackground(COLOR_LIGHT_RED);\r
+        } else {\r
+            logtypeText.setBackground(COLOR_TEXT_BACKGROUND);\r
+            for (CustomXmlTraceDefinition def : CustomXmlTraceDefinition.loadAll()) {\r
+                if (definition.definitionName.equals(def.definitionName)) {\r
+                    if (editDefinitionName == null || ! editDefinitionName.equals(definition.definitionName)) {\r
+                        errors.append("The log type name already exists. ");\r
+                        logtypeText.setBackground(COLOR_LIGHT_RED);\r
+                        break;\r
+                    }\r
+                }\r
+            }\r
+        }\r
+        \r
+        if (definition.rootInputElement == null) {\r
+            errors.append("Add a document element. ");\r
+        }\r
+        \r
+        if (definition.rootInputElement != null) {\r
+            logEntryFound = false;\r
+            logEntryNestedCount = 0;\r
+            timeStampFound = false;\r
+            \r
+            errors.append(validateElement(definition.rootInputElement));\r
+\r
+            if ((definition.rootInputElement.attributes != null && definition.rootInputElement.attributes.size() != 0) ||\r
+                    (definition.rootInputElement.childElements != null && definition.rootInputElement.childElements.size() != 0) || errors.length() == 0) {\r
+                if (!logEntryFound) {\r
+                    errors.append("Identify a Log Entry element. ");\r
+                }\r
+\r
+                if (timeStampFound) {\r
+                    if (timeStampOutputFormatText.getText().trim().length() == 0) {\r
+                        errors.append("Enter the output format for the Time Stamp field. ");\r
+                        timeStampOutputFormatText.setBackground(COLOR_LIGHT_RED);\r
+                    } else {\r
+                        try {\r
+                            new SimpleDateFormat(timeStampOutputFormatText.getText().trim());\r
+                            timeStampOutputFormatText.setBackground(COLOR_TEXT_BACKGROUND);\r
+                        } catch (IllegalArgumentException e) {\r
+                            errors.append("Enter a valid output format for the Time Stamp field. ");\r
+                            timeStampOutputFormatText.setBackground(COLOR_LIGHT_RED);\r
+                        }\r
+                    }\r
+                } else {\r
+                    timeStampPreviewText.setText("*no time stamp element or attribute*");\r
+                }\r
+            }\r
+        } else {\r
+            timeStampPreviewText.setText("*no time stamp element or attribute*");\r
+        }\r
+    \r
+        if (errors.length() == 0) {\r
+            setDescription(defaultDescription);\r
+            setPageComplete(true);\r
+        } else {\r
+            setDescription(errors.toString());\r
+            setPageComplete(false);\r
+        }\r
+    }\r
+    \r
+    public StringBuffer validateElement(InputElement inputElement) {\r
+        StringBuffer errors = new StringBuffer();\r
+        ElementNode elementNode = null;\r
+        if (selectedElement != null && selectedElement.inputElement.equals(inputElement)) elementNode = selectedElement;\r
+        if (inputElement == definition.rootInputElement) {\r
+            if (inputElement.elementName.length() == 0) {\r
+                errors.append("Enter a name for the document element. ");\r
+                if (elementNode != null) elementNode.elementNameText.setBackground(COLOR_LIGHT_RED);\r
+            } else {\r
+                if (elementNode != null) elementNode.elementNameText.setBackground(COLOR_TEXT_BACKGROUND);\r
+            }\r
+        }\r
+        if (inputElement != definition.rootInputElement) {\r
+            if (inputElement.logEntry) {\r
+                logEntryFound = true;\r
+                logEntryNestedCount++;\r
+            }\r
+            if (inputElement.inputName.equals(CustomXmlTraceDefinition.TAG_TIMESTAMP)) {\r
+                timeStampFound = true;\r
+                if (inputElement.inputFormat.length() == 0) {\r
+                    errors.append("Enter the input format for the Time Stamp (Element " + getName(inputElement) + "). ");\r
+                    if (elementNode != null) elementNode.tagText.setBackground(COLOR_LIGHT_RED);\r
+                } else {\r
+                    try {\r
+                        new SimpleDateFormat(inputElement.inputFormat);\r
+                        if (elementNode != null) elementNode.tagText.setBackground(COLOR_TEXT_BACKGROUND);\r
+                    } catch (IllegalArgumentException e) {\r
+                        errors.append("Enter a valid input format for the Time Stamp (Element " + getName(inputElement) + "). ");\r
+                        if (elementNode != null) elementNode.tagText.setBackground(COLOR_LIGHT_RED);\r
+                    }\r
+                }\r
+            } else if (inputElement.inputName.length() == 0) {\r
+                errors.append("Enter a name for the input . ");\r
+                if (elementNode != null) elementNode.tagText.setBackground(COLOR_LIGHT_RED);\r
+            } else {\r
+                if (elementNode != null) elementNode.tagText.setBackground(COLOR_TEXT_BACKGROUND);\r
+            }\r
+        }\r
+        if (inputElement.attributes != null) {\r
+            if (elementNode != null) {\r
+                for (Attribute attribute : elementNode.attributes) {\r
+                    attribute.attributeNameText.setBackground(COLOR_TEXT_BACKGROUND);\r
+                }\r
+            }\r
+            for (int i = 0; i < inputElement.attributes.size(); i++) {\r
+                InputAttribute attribute = inputElement.attributes.get(i);\r
+                boolean duplicate = false;\r
+                for (int j = i + 1; j < inputElement.attributes.size(); j++) {\r
+                    InputAttribute otherAttribute = inputElement.attributes.get(j);\r
+                    if (otherAttribute.attributeName.equals(attribute.attributeName)) {\r
+                        duplicate = true;\r
+                        if (elementNode != null) {\r
+                            elementNode.attributes.get(j).attributeNameText.setBackground(COLOR_LIGHT_RED);\r
+                        }\r
+                    }\r
+                }\r
+                if (attribute.attributeName.length() == 0) {\r
+                    errors.append("Enter a name for the attribute (Attribute " + getName(inputElement) + ": ?). ");\r
+                    if (elementNode != null) elementNode.attributes.get(i).attributeNameText.setBackground(COLOR_LIGHT_RED);\r
+                } else if (duplicate) {\r
+                    errors.append("Duplicate attribute names (Attribute " + getName(attribute, inputElement) +"). ");\r
+                    if (elementNode != null) elementNode.attributes.get(i).attributeNameText.setBackground(COLOR_LIGHT_RED);\r
+                }\r
+                if (attribute.inputName.equals(CustomXmlTraceDefinition.TAG_TIMESTAMP)) {\r
+                    timeStampFound = true;\r
+                    if (attribute.inputFormat.length() == 0) {\r
+                        errors.append("Enter the input format for the Time Stamp (Attribute " + getName(attribute, inputElement) +"). ");\r
+                        if (elementNode != null) elementNode.attributes.get(i).tagText.setBackground(COLOR_LIGHT_RED);\r
+                    } else {\r
+                        try {\r
+                            new SimpleDateFormat(attribute.inputFormat);\r
+                            if (elementNode != null) elementNode.attributes.get(i).tagText.setBackground(COLOR_TEXT_BACKGROUND);\r
+                        } catch (IllegalArgumentException e) {\r
+                            errors.append("Enter a valid input format for the Time Stamp (Attribute " + getName(attribute, inputElement) +"). ");\r
+                            if (elementNode != null) elementNode.attributes.get(i).tagText.setBackground(COLOR_LIGHT_RED);\r
+                        }\r
+                    }\r
+                } else if (attribute.inputName.length() == 0) {\r
+                    errors.append("Enter a name for the data group (Attribute " + getName(attribute, inputElement) +"). ");\r
+                    if (elementNode != null) elementNode.attributes.get(i).tagText.setBackground(COLOR_LIGHT_RED);\r
+                } else {\r
+                    if (elementNode != null) elementNode.attributes.get(i).tagText.setBackground(COLOR_TEXT_BACKGROUND);\r
+                }\r
+            }\r
+        }\r
+        if (inputElement.childElements != null) {\r
+            for (InputElement child : inputElement.childElements) {\r
+                ElementNode childElementNode = null;\r
+                if (selectedElement != null && selectedElement.inputElement.equals(child)) childElementNode = selectedElement;\r
+                if (childElementNode != null) childElementNode.elementNameText.setBackground(COLOR_TEXT_BACKGROUND);\r
+            }\r
+            for (int i = 0; i < inputElement.childElements.size(); i++) {\r
+                InputElement child = inputElement.childElements.get(i);\r
+                ElementNode childElementNode = null;\r
+                if (selectedElement != null && selectedElement.inputElement.equals(child)) childElementNode = selectedElement;\r
+                if (child.elementName.length() == 0) {\r
+                    errors.append("Enter a name for the element (Element " + getName(child) + "). ");\r
+                    if (childElementNode != null) childElementNode.elementNameText.setBackground(COLOR_LIGHT_RED);\r
+                } else {\r
+                    boolean duplicate = false;\r
+                    for (int j = i + 1; j < inputElement.childElements.size(); j++) {\r
+                        InputElement otherChild = inputElement.childElements.get(j);\r
+                        if (otherChild.elementName.equals(child.elementName)) {\r
+                            duplicate = true;\r
+                            ElementNode otherChildElementNode = null;\r
+                            if (selectedElement != null && selectedElement.inputElement.equals(otherChild)) otherChildElementNode = selectedElement;\r
+                            if (otherChildElementNode != null) otherChildElementNode.elementNameText.setBackground(COLOR_LIGHT_RED);\r
+                        }\r
+                    }\r
+                    if (duplicate) {\r
+                        errors.append("Duplicate element names (Element " + getName(child) + "). ");\r
+                        if (childElementNode != null) childElementNode.elementNameText.setBackground(COLOR_LIGHT_RED);\r
+                    }\r
+                }\r
+                \r
+                errors.append(validateElement(child));\r
+            }\r
+        }\r
+        if (inputElement.logEntry) {\r
+            logEntryNestedCount--;\r
+        }\r
+        return errors;\r
+    }\r
+    \r
+    public CustomXmlTraceDefinition getDefinition() {\r
+        return definition;\r
+    }\r
+\r
+    public char[] getInputText() {\r
+        return inputText.getText().toCharArray();\r
+    }\r
+}\r
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/wizards/CustomXmlParserOutputWizardPage.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/wizards/CustomXmlParserOutputWizardPage.java
new file mode 100644 (file)
index 0000000..573e5ec
--- /dev/null
@@ -0,0 +1,300 @@
+package org.eclipse.linuxtools.tmf.ui.wizards;\r
+\r
+import java.io.File;\r
+import java.io.FileNotFoundException;\r
+import java.io.FileWriter;\r
+import java.io.IOException;\r
+import java.util.ArrayList;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+\r
+import org.eclipse.jface.wizard.WizardPage;\r
+import org.eclipse.linuxtools.tmf.trace.ITmfTrace;\r
+import org.eclipse.linuxtools.tmf.ui.TmfUiPlugin;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomEventsTable;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomTraceDefinition;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomXmlTrace;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomXmlTraceDefinition;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomTraceDefinition.OutputColumn;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.custom.SashForm;\r
+import org.eclipse.swt.custom.ScrolledComposite;\r
+import org.eclipse.swt.events.SelectionAdapter;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.graphics.Image;\r
+import org.eclipse.swt.layout.GridData;\r
+import org.eclipse.swt.layout.GridLayout;\r
+import org.eclipse.swt.widgets.Button;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Text;\r
+\r
+public class CustomXmlParserOutputWizardPage extends WizardPage {\r
+\r
+    private static final Image upImage = TmfUiPlugin.getDefault().getImageFromPath("/icons/up_button.gif");\r
+    private static final Image downImage = TmfUiPlugin.getDefault().getImageFromPath("/icons/down_button.gif");\r
+    private CustomXmlParserWizard wizard;\r
+    private CustomXmlTraceDefinition definition;\r
+    ArrayList<Output> outputs = new ArrayList<Output>();\r
+    Output messageOutput;\r
+    Composite container;\r
+    SashForm sash;\r
+    Text timestampFormatText;\r
+    Text timestampPreviewText;\r
+    ScrolledComposite outputsScrolledComposite;\r
+    Composite outputsContainer;\r
+    ScrolledComposite inputScrolledComposite;\r
+    Composite tableContainer;\r
+    CustomEventsTable previewTable;\r
+    File tmpFile;\r
+    \r
+    protected CustomXmlParserOutputWizardPage(CustomXmlParserWizard wizard) {\r
+        super("CustomParserOutputWizardPage");\r
+        setTitle(wizard.inputPage.getTitle());\r
+        setDescription("Customize the output of the parser");\r
+        this.wizard = wizard;\r
+        setPageComplete(false);\r
+    }\r
+\r
+    public void createControl(Composite parent) {\r
+        container = new Composite(parent, SWT.NULL);\r
+        container.setLayout(new GridLayout());\r
+\r
+        sash = new SashForm(container, SWT.VERTICAL);\r
+        sash.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));\r
+        sash.setBackground(sash.getDisplay().getSystemColor(SWT.COLOR_GRAY));\r
+        \r
+        outputsScrolledComposite = new ScrolledComposite(sash, SWT.V_SCROLL);\r
+        outputsScrolledComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));\r
+        outputsContainer = new Composite(outputsScrolledComposite, SWT.NONE);\r
+        GridLayout outputsLayout = new GridLayout(4, false);\r
+        outputsLayout.marginHeight = 10;\r
+        outputsLayout.marginWidth = 0;\r
+        outputsContainer.setLayout(outputsLayout);\r
+        outputsScrolledComposite.setContent(outputsContainer);\r
+        outputsScrolledComposite.setExpandHorizontal(true);\r
+        outputsScrolledComposite.setExpandVertical(true);\r
+\r
+        outputsContainer.layout();\r
+        \r
+        outputsScrolledComposite.setMinSize(outputsContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x, outputsContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y-5);\r
+\r
+        tableContainer = new Composite(sash, SWT.NONE);\r
+        GridLayout tableLayout = new GridLayout();\r
+        tableLayout.marginHeight = 0;\r
+        tableLayout.marginWidth = 0;\r
+        tableContainer.setLayout(tableLayout);\r
+        previewTable = new CustomEventsTable(new CustomXmlTraceDefinition(), tableContainer, 0);\r
+\r
+        if (wizard.definition != null) {\r
+            loadDefinition(wizard.definition);\r
+        }\r
+        setControl(container);\r
+        \r
+    }\r
+\r
+    @Override\r
+    public void dispose() {\r
+        previewTable.dispose();\r
+        super.dispose();\r
+    }\r
+\r
+    private void loadDefinition(CustomTraceDefinition definition) {\r
+        for (OutputColumn outputColumn : definition.outputs) {\r
+            Output output = new Output(outputsContainer, outputColumn.name);\r
+            outputs.add(output);\r
+        }\r
+    }\r
+\r
+    /* (non-Javadoc)\r
+     * @see org.eclipse.jface.dialogs.DialogPage#setVisible(boolean)\r
+     */\r
+    @Override\r
+    public void setVisible(boolean visible) {\r
+        if (visible) {\r
+            this.definition = wizard.inputPage.getDefinition();\r
+            List<String> outputNames = wizard.inputPage.getInputNames();\r
+            \r
+            // dispose outputs that have been removed in the input page\r
+            Iterator<Output> iter = outputs.iterator();\r
+            while (iter.hasNext()) {\r
+                Output output = iter.next();\r
+                boolean found = false;\r
+                for (String name : outputNames) {\r
+                    if (output.name.equals(name)) {\r
+                        found = true;\r
+                        break;\r
+                    }\r
+                }\r
+                if (!found) {\r
+                    output.dispose();\r
+                    iter.remove();\r
+                }\r
+            }\r
+            \r
+            // create outputs that have been added in the input page\r
+            for (String name : outputNames) {\r
+                boolean found = false;\r
+                for (Output output : outputs) {\r
+                    if (output.name.equals(name)) {\r
+                        found = true;\r
+                        break;\r
+                    }\r
+                }\r
+                if (!found) {\r
+                    outputs.add(new Output(outputsContainer, name));\r
+                }\r
+            }\r
+            \r
+            outputsContainer.layout();\r
+            outputsScrolledComposite.setMinSize(outputsContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x, outputsContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y-5);\r
+            updatePreviewTable();\r
+            if (sash.getSize().y > outputsContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y + previewTable.getTable().getItemHeight()) {\r
+                sash.setWeights(new int[] {outputsContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y, sash.getSize().y - outputsContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y});\r
+            } else {\r
+                sash.setWeights(new int[] {outputsContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y, previewTable.getTable().getItemHeight()});\r
+            }\r
+            setPageComplete(true);\r
+        } else {\r
+            setPageComplete(false);\r
+        }\r
+        super.setVisible(visible);\r
+    }\r
+\r
+    private void moveBefore(Output moved) {\r
+        int i = outputs.indexOf(moved);\r
+        if (i > 0) {\r
+            Output previous = outputs.get(i-1);\r
+            moved.enabledButton.moveAbove(previous.enabledButton);\r
+            moved.nameLabel.moveBelow(moved.enabledButton);\r
+            moved.upButton.moveBelow(moved.nameLabel);\r
+            moved.downButton.moveBelow(moved.upButton);\r
+            outputs.add(i-1, outputs.remove(i));\r
+            outputsContainer.layout();\r
+            outputsScrolledComposite.setMinSize(outputsContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x, outputsContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y-5);\r
+            container.layout();\r
+            updatePreviewTable();\r
+        }\r
+    }\r
+    \r
+    private void moveAfter(Output moved) {\r
+        int i = outputs.indexOf(moved);\r
+        if (i+1 < outputs.size()) {\r
+            Output next = outputs.get(i+1);\r
+            moved.enabledButton.moveBelow(next.downButton);\r
+            moved.nameLabel.moveBelow(moved.enabledButton);\r
+            moved.upButton.moveBelow(moved.nameLabel);\r
+            moved.downButton.moveBelow(moved.upButton);\r
+            outputs.add(i+1, outputs.remove(i));\r
+            outputsContainer.layout();\r
+            outputsScrolledComposite.setMinSize(outputsContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).x, outputsContainer.computeSize(SWT.DEFAULT, SWT.DEFAULT).y-5);\r
+            container.layout();\r
+            updatePreviewTable();\r
+        }\r
+    }\r
+    \r
+    private void updatePreviewTable() {\r
+        final int MAX_NUM_ENTRIES = 50;\r
+        definition.outputs = extractOutputs();\r
+\r
+        try {\r
+            tmpFile = TmfUiPlugin.getDefault().getStateLocation().addTrailingSeparator().append("customwizard.tmp").toFile();\r
+            FileWriter writer = new FileWriter(tmpFile);\r
+            writer.write(wizard.inputPage.getInputText());\r
+            writer.close();\r
+            \r
+            ITmfTrace trace = new CustomXmlTrace(tmpFile.getName(), definition, tmpFile.getAbsolutePath(), MAX_NUM_ENTRIES);\r
+            previewTable.dispose();\r
+            previewTable = new CustomEventsTable(definition, tableContainer, MAX_NUM_ENTRIES);\r
+            previewTable.setTrace(trace);\r
+            previewTable.getTable().setItemCount(MAX_NUM_ENTRIES); // Trigger parsing\r
+        } catch (FileNotFoundException e) {\r
+            e.printStackTrace();\r
+        } catch (IOException e) {\r
+            e.printStackTrace();\r
+        }\r
+        \r
+        tableContainer.layout();\r
+        container.layout();\r
+    }\r
+\r
+    public List<OutputColumn> extractOutputs() {\r
+        int numColumns = 0;\r
+        for (int i = 0; i < outputs.size(); i++) {\r
+            if (outputs.get(i).enabledButton.getSelection()) {\r
+                numColumns++;\r
+            }\r
+        }\r
+        List<OutputColumn> outputColumns = new ArrayList<OutputColumn>(numColumns);\r
+        numColumns = 0;\r
+        for (int i = 0; i < outputs.size(); i++) {\r
+            Output output = outputs.get(i);\r
+            if (output.enabledButton.getSelection()) {\r
+                OutputColumn column = new OutputColumn();\r
+                column.name = output.nameLabel.getText();\r
+                outputColumns.add(column); \r
+            }\r
+        }\r
+        return outputColumns;\r
+    }\r
+\r
+    private class Output {\r
+        String name;\r
+        Button enabledButton;\r
+        Text nameLabel;\r
+        Button upButton;\r
+        Button downButton;\r
+        \r
+        public Output(Composite parent, String name) {\r
+            this.name = name;\r
+            \r
+            enabledButton = new Button(parent, SWT.CHECK);\r
+            enabledButton.setToolTipText("Visible");\r
+            enabledButton.setSelection(true);\r
+            enabledButton.addSelectionListener(new SelectionAdapter() {\r
+                public void widgetSelected(SelectionEvent e) {\r
+                    updatePreviewTable();\r
+                }\r
+            });\r
+            if (messageOutput != null) {\r
+                enabledButton.moveAbove(messageOutput.enabledButton);\r
+            }\r
+            \r
+            nameLabel = new Text(parent, SWT.BORDER | SWT.READ_ONLY | SWT.SINGLE);\r
+            nameLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));\r
+            nameLabel.setText(name);\r
+            nameLabel.moveBelow(enabledButton);\r
+\r
+            upButton = new Button(parent, SWT.PUSH);\r
+            upButton.setImage(upImage);\r
+            upButton.setToolTipText("Move Before");\r
+            upButton.addSelectionListener(new SelectionAdapter() {\r
+                public void widgetSelected(SelectionEvent e) {\r
+                    moveBefore(Output.this);\r
+                }\r
+            });\r
+            upButton.moveBelow(nameLabel);\r
+            \r
+            downButton = new Button(parent, SWT.PUSH);\r
+            downButton.setImage(downImage);\r
+            downButton.setToolTipText("Move After");\r
+            downButton.addSelectionListener(new SelectionAdapter() {\r
+                public void widgetSelected(SelectionEvent e) {\r
+                    moveAfter(Output.this);\r
+                }\r
+            });\r
+            downButton.moveBelow(upButton);\r
+        }\r
+\r
+        private void dispose() {\r
+            enabledButton.dispose();\r
+            nameLabel.dispose();\r
+            upButton.dispose();\r
+            downButton.dispose();\r
+        }\r
+    }\r
+    \r
+    public CustomXmlTraceDefinition getDefinition() {\r
+        return definition;\r
+    }\r
+    \r
+}\r
diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/wizards/CustomXmlParserWizard.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/wizards/CustomXmlParserWizard.java
new file mode 100644 (file)
index 0000000..bd74068
--- /dev/null
@@ -0,0 +1,75 @@
+package org.eclipse.linuxtools.tmf.ui.wizards;\r
+\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.eclipse.jface.viewers.IStructuredSelection;\r
+import org.eclipse.jface.wizard.Wizard;\r
+import org.eclipse.linuxtools.tmf.ui.parsers.custom.CustomXmlTraceDefinition;\r
+import org.eclipse.ui.INewWizard;\r
+import org.eclipse.ui.IWorkbench;\r
+\r
+public class CustomXmlParserWizard extends Wizard implements INewWizard {\r
+\r
+    CustomXmlParserInputWizardPage inputPage;\r
+    CustomXmlParserOutputWizardPage outputPage;\r
+    private ISelection selection;\r
+    CustomXmlTraceDefinition definition;\r
+\r
+    public CustomXmlParserWizard() {\r
+        super();\r
+    }\r
+\r
+    public CustomXmlParserWizard(CustomXmlTraceDefinition definition) {\r
+        super();\r
+        this.definition = definition;\r
+    }\r
+\r
+    @Override\r
+    public boolean performFinish() {\r
+        CustomXmlTraceDefinition def = outputPage.getDefinition();\r
+        if (definition != null && !definition.definitionName.equals(def.definitionName)) {\r
+            CustomXmlTraceDefinition.delete(definition.definitionName);\r
+        }\r
+        def.save();\r
+        /*\r
+        if (this.selection instanceof IStructuredSelection) {\r
+            Object selection = ((IStructuredSelection)this.selection).getFirstElement();\r
+            if (selection instanceof IFile) {\r
+                IFile file = (IFile)selection;\r
+                IEditorInput editorInput = new FileEditorInput(file);\r
+                IWorkbench wb = PlatformUI.getWorkbench();\r
+                IWorkbenchPage activePage = wb.getActiveWorkbenchWindow().getActivePage();\r
+        \r
+                IEditorPart editor = activePage.findEditor(editorInput);\r
+                if (editor != null && editor instanceof GenericTableEditor) {\r
+                    activePage.reuseEditor((IReusableEditor)editor, editorInput);\r
+                    activePage.activate(editor);\r
+                } else {\r
+                    try {\r
+                        editor = activePage.openEditor(editorInput, GenericTableEditor.ID);\r
+                    } catch (PartInitException e) {\r
+                        // TODO Auto-generated catch block\r
+                        e.printStackTrace();\r
+                    }\r
+                }\r
+            }\r
+        }\r
+        */\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Adding the page to the wizard.\r
+     */\r
+\r
+    public void addPages() {\r
+        inputPage = new CustomXmlParserInputWizardPage(selection, definition);\r
+        addPage(inputPage);\r
+        outputPage = new CustomXmlParserOutputWizardPage(this);\r
+        addPage(outputPage);\r
+    }\r
+\r
+    public void init(IWorkbench workbench, IStructuredSelection selection) {\r
+        this.selection = selection;\r
+    }\r
+\r
+}\r
This page took 0.154277 seconds and 5 git commands to generate.