nz.co.senanque.madura.workfloweditor.editor.WorkflowOutlinePage.java Source code

Java tutorial

Introduction

Here is the source code for nz.co.senanque.madura.workfloweditor.editor.WorkflowOutlinePage.java

Source

/*******************************************************************************
 * Copyright (c)2014 Prometheus Consulting
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/
package nz.co.senanque.madura.workfloweditor.editor;

import java.io.ByteArrayInputStream;

import nz.co.senanque.madura.MaduraPlugin;
import nz.co.senanque.madura.ProjectPropertyPage;
import nz.co.senanque.madura.Utils;
import nz.co.senanque.parser.InputStreamParserSource;
import nz.co.senanque.parser.ParserException;
import nz.co.senanque.parser.ParserSource;
import nz.co.senanque.parser.TOCInterface;
import nz.co.senanque.process.parser.ParsePackage;
import nz.co.senanque.process.parser.ProcessTextProvider;
import nz.co.senanque.schemaparser.SchemaParser;
import nz.co.senanque.workflow.WorkflowManagerMock;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.editors.text.TextEditor;
import org.eclipse.ui.model.WorkbenchContentProvider;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.views.contentoutline.ContentOutlinePage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 
 * This handles the outline control for the rule editor
 * It generates the table of contents by parsing the rule file
 * and sets up markers to indicate any errors.
 * 
 * @author Roger Parkinson
 */
public class WorkflowOutlinePage extends ContentOutlinePage implements TOCInterface {
    private static final Logger log = LoggerFactory.getLogger(WorkflowOutlinePage.class);

    private boolean m_timerStarted;
    private long m_parserOffset = 0;
    private IFile m_input;
    private final AdaptableList m_toc = new AdaptableList();
    private final TextEditor m_textEditor;

    public WorkflowOutlinePage(IFile input, TextEditor textEditor) {
        super();
        m_input = input;
        m_textEditor = textEditor;
        MaduraPlugin.registerBuilder(m_input.getProject(), WorkflowBuilder.getId());
    }

    public void createControl(Composite parent) {
        super.createControl(parent);
        // Configure the context menu.
        MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$
        menuMgr.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
        menuMgr.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS + "-end")); //$NON-NLS-1$
        final TreeViewer viewer = getTreeViewer();
        IDocumentProvider d = m_textEditor.getDocumentProvider();
        IDocument dd = d.getDocument(m_textEditor.getEditorInput());
        viewer.setContentProvider(new WorkbenchContentProvider());
        viewer.setLabelProvider(new WorkflowLabelProvider());
        String s = dd.get();
        SchemaParser schemaParser = Utils.getXSDFile(m_input);
        if (schemaParser == null) {
            return;
        }

        try {
            ITypedRegion r[] = dd.computePartitioning(0, s.length());
            viewer.setInput(
                    getContentOutline(r, s, m_input.getName(), m_input.getLocation().toOSString(), schemaParser));
        } catch (BadLocationException e) {
            e.printStackTrace();
        }

        Menu menu = menuMgr.createContextMenu(viewer.getTree());
        viewer.getTree().setMenu(menu);
        // Be sure to register it so that other plug-ins can add actions.
        getSite().registerContextMenu("nz.co.senanque.madura.workflow.outline", menuMgr, viewer); //$NON-NLS-1$
        dd.addDocumentListener(new IDocumentListener() {
            public void documentAboutToBeChanged(DocumentEvent event) {
            }

            public void documentChanged(DocumentEvent event) {
                Document doc = (Document) event.getDocument();
                processChange(doc);
            }
        });
    }

    public void processChange(final Document doc) {
        if (doc == null) {
            WorkflowBuilder.buildFile(m_input, this);
            log.debug("Just invoked full build");
            return;
        }
        final Tree tree = (Tree) getControl();
        final TreeViewer treeView = getTreeViewer();
        try {
            Runnable runnable = new Runnable() {
                public void run() {
                    getControl().setRedraw(false);
                    try {
                        String s = doc.get();
                        Object expanded[] = treeView.getExpandedElements();
                        tree.removeAll();
                        SchemaParser schemaParser = Utils.getXSDFile(m_input);
                        if (schemaParser == null) {
                            return;
                        }

                        ITypedRegion r[] = doc.computePartitioning(0, s.length());
                        AdaptableList o = ((AdaptableList) getContentOutline(r, s, m_input.getName(),
                                m_input.getLocation().toOSString(), schemaParser));
                        treeView.setInput(o);
                        for (int i = 0; i < expanded.length; i++) {
                            int j = o.children.indexOf(expanded[i]);
                            if (j > -1)
                                treeView.setExpandedState(o.children.get(j), true);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    getControl().setRedraw(true);
                    getControl().redraw();
                    m_timerStarted = false;
                }
            };
            if (!m_timerStarted) {
                m_timerStarted = true;
                Display.getDefault().timerExec(1000, runnable);
            } else {
                getControl().setRedraw(true);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Build the table of contents for the package
     * To do this we call the rules parser and pass it this class
     * which implements the TOCInterface. The TOCInterface is passed the
     * table of contents by the parser.
     * 
     * @param input
     * @return
     */
    private Object getContentOutline(ITypedRegion r[], String input, String name, String path,
            SchemaParser schemaParser) {
        try {
            m_input.deleteMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE);
        } catch (CoreException e1) {
        }
        m_toc.clear();
        int lineCount = 0;
        m_parserOffset = 0;
        String messageNames = ProjectPropertyPage.getMessageNames(m_input.getProject());
        String computeNames = ProjectPropertyPage.getComputeNames(m_input.getProject());
        for (int i = 0; i < r.length; i++) {
            ITypedRegion t = r[i];
            String section = input.substring(t.getOffset(), t.getOffset() + t.getLength());
            int sectionLineCount = 0;
            for (int i1 = 0; i1 < section.length(); i1++) {
                if (section.charAt(i1) == '\n') {
                    sectionLineCount++;
                }
            }
            log.debug("sectionLineCount {}", sectionLineCount);
            try {
                ParserSource parserSource = new InputStreamParserSource(
                        new ByteArrayInputStream(section.getBytes()), m_input.getName(), Utils.getBufferSize());
                ProcessTextProvider textProvider = new ProcessTextProvider(parserSource, schemaParser,
                        new WorkflowManagerMock(messageNames, computeNames));
                textProvider.setToc(this);
                ParsePackage parsePackage = new ParsePackage();
                parsePackage.parse(textProvider);
                //            log.debug("Parser for {} {}",m_parserOffset,section);

                m_parserOffset += parserSource.getPos();
            } catch (ParserException f) {
                Utils.addErrorElement(Utils.cleanupMessage(f.getMessage()), lineCount + f.getLineCount() + 1,
                        m_input);
            } catch (Exception e) {
                e.printStackTrace();
            }
            lineCount += sectionLineCount;
            log.debug("lineCount {}", lineCount);
        }
        return m_toc;
    }

    public Object addTOCElement(Object parent, String name, long start, long end, int type) {
        long adjustedStart = start + m_parserOffset;
        MarkElement element = new MarkElement((IAdaptable) parent, name, (int) adjustedStart, (int) (end - start),
                type);
        //      if (parent == m_input)
        m_toc.add(element);
        log.debug("Adding TOC name {} start {} end {} type {}", name, adjustedStart, end - start, type);
        return element;
    }

    public void addErrorElement(String name, int line) {
        final String n = name;
        final int l = line;
        try {
            MaduraPlugin.getWorkspace().run(new IWorkspaceRunnable() {
                public void run(IProgressMonitor monitor) {
                    try {
                        IEditorInput input = m_textEditor.getEditorInput();
                        if (input instanceof IFileEditorInput) {
                            IResource resource = ((IFileEditorInput) input).getFile();
                            IMarker marker = resource.createMarker(IMarker.PROBLEM);
                            if (marker.exists()) {
                                marker.setAttribute(IMarker.LOCATION, l);
                                marker.setAttribute(IMarker.LINE_NUMBER, l);
                                marker.setAttribute(IMarker.MESSAGE, n);
                                marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
                            }
                        }
                    } catch (CoreException e) {
                        e.printStackTrace();
                    }
                }
            }, null);
        } catch (CoreException e) {
            e.printStackTrace();
        }
    }

    public Object getTOCElement() {
        return m_input;
    }

    public void selectionChanged(SelectionChangedEvent event) {
        super.selectionChanged(event);
        ISelection selection = event.getSelection();
        if (selection.isEmpty())
            m_textEditor.resetHighlightRange();
        else {
            MarkElement segment = (MarkElement) ((IStructuredSelection) selection).getFirstElement();
            int start = segment.getStart();
            int length = segment.getLength();
            try {
                m_textEditor.setHighlightRange(start, length, true);
            } catch (IllegalArgumentException x) {
                m_textEditor.resetHighlightRange();
            }
        }
    }

    /**
     * @param file
     */
    public void setInput(IFile file) {
        m_input = file;
    }
}