org.bbaw.pdr.ae.view.markup.web.MarkupEditorVex.java Source code

Java tutorial

Introduction

Here is the source code for org.bbaw.pdr.ae.view.markup.web.MarkupEditorVex.java

Source

/**
 * This file is part of Archiv-Editor.
 * 
 * The software Archiv-Editor serves as a client user interface for working with
 * the Person Data Repository. See: pdr.bbaw.de
 * 
 * The software Archiv-Editor was developed at the Berlin-Brandenburg Academy
 * of Sciences and Humanities, Jgerstr. 22/23, D-10117 Berlin.
 * www.bbaw.de
 * 
 * Copyright (C) 2010-2013  Berlin-Brandenburg Academy
 * of Sciences and Humanities
 * 
 * The software Archiv-Editor was developed by @author: Christoph Plutte.
 * 
 * Archiv-Editor is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Archiv-Editor is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with Archiv-Editor.  
 * If not, see <http://www.gnu.org/licenses/lgpl-3.0.html>.
 */
package org.bbaw.pdr.ae.view.markup.web;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.XMLStreamException;

import net.sf.vex.css.StyleSheet;
import net.sf.vex.css.StyleSheetReader;
import net.sf.vex.dom.Document;
import net.sf.vex.dom.DocumentReader;
import net.sf.vex.dom.DocumentWriter;
import net.sf.vex.dom.Element;
import net.sf.vex.dom.IWhitespacePolicy;
import net.sf.vex.dom.RootElement;
import net.sf.vex.swt.VexWidget;

import org.bbaw.pdr.ae.common.AEConstants;
import org.bbaw.pdr.ae.model.Aspect;
import org.bbaw.pdr.ae.model.TaggingRange;
import org.bbaw.pdr.ae.view.control.interfaces.IMarkupEditor;
import org.bbaw.pdr.ae.view.markup.web.internal.Activator;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.fieldassist.ControlDecoration;
import org.eclipse.jface.resource.FontDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.ui.PlatformUI;
import org.xml.sax.SAXException;

/**
 * The Class MarkupEditorStext.
 * @author Christoph Plutte
 */
public class MarkupEditorVex implements IMarkupEditor {
    private StyleSheet styleSheet;
    /** The _aspect. */
    private Aspect _aspect;

    /** The _composite. */
    private Composite _composite;

    /** The _title. */
    private String _title;

    /** The _selected tr. */
    private TaggingRange[] _selectedTRs;

    /** The _font descriptor. */
    // Rap auskommentieren SWT.ROMAN
    private FontDescriptor _fontDescriptor = FontDescriptor.createFrom("Tahoma", 10, 3); //$NON-NLS-1$

    /** Resource Manager for colors and fonts. */
    private LocalResourceManager _resources = new LocalResourceManager(JFaceResources.getResources());

    /** The _markup listeners. */
    private ArrayList<Listener> _markupListeners = new ArrayList<Listener>();

    /** The _modify listeners. */
    private ArrayList<Listener> _modifyListeners = new ArrayList<Listener>();

    /** The _focus listeners. */
    private ArrayList<Listener> _focusListeners = new ArrayList<Listener>();

    /** The _key listeners. */
    private ArrayList<Listener> _keyListeners = new ArrayList<Listener>();

    /** The _text selection listeners. */
    private ArrayList<Listener> _textSelectionListeners = new ArrayList<Listener>();

    private HashMap<Element, TaggingRange> _taggingRangeMap;

    private HashMap<TaggingRange, TaggingRange> _recentTaggingRangeMap;

    private VexWidget _vexWidget;

    @Override
    public final void addExtendedModifyListener(final Listener extendedModifyListener) {
        if (extendedModifyListener != null) {
            _modifyListeners.add(extendedModifyListener);
        }

    }

    @Override
    public final void addFocusListener(final Listener focusListener) {
        if (focusListener != null) {
            _focusListeners.add(focusListener);
        }

    }

    @Override
    public final void addKeyListener(final Listener keyListener) {
        if (keyListener != null) {
            _keyListeners.add(keyListener);
        }

    }

    @Override
    public final void addMarkupSelectionListener(final Listener listener) {
        if (listener != null) {
            _markupListeners.add(listener);
        }

    }

    @Override
    public final void addTextSelectionListener(final Listener listener) {
        if (listener != null) {
            _textSelectionListeners.add(listener);
        }

    }

    @Override
    public final void createEditor() {
        _vexWidget = new VexWidget(_composite, SWT.MULTI | SWT.WRAP | SWT.V_SCROLL | SWT.BORDER);
        GridData gd = new GridData();
        gd.grabExcessHorizontalSpace = true;
        gd.horizontalAlignment = SWT.FILL;
        gd.grabExcessVerticalSpace = true;
        gd.verticalAlignment = SWT.FILL;
        // gd.widthHint = 280;
        gd.heightHint = 50;

        _vexWidget.setLayoutData(gd);
        _vexWidget.setFont(_resources.createFont(_fontDescriptor)); //$NON-NLS-1$
        PlatformUI.getWorkbench().getHelpSystem().setHelp(_vexWidget, "org.bbaw.pdr.ae.help.notificationText"); //$NON-NLS-1$
        _vexWidget.addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                System.out.println("vexwidget selection changed");
                //            Integer n = null;
                //            System.out.println(n.toString());
                IStructuredSelection selection = (IStructuredSelection) event.getSelection();
                Object[] objs = selection.toArray();
                if (objs instanceof Object[]) {

                    ArrayList<TaggingRange> trs = new ArrayList<TaggingRange>(objs.length);
                    boolean textSelection = _vexWidget.getCurrentElement().getName().equals("notification");

                    for (int i = 0; i < objs.length; i++) {
                        if (objs[i] instanceof Element) {
                            Element el = (Element) objs[i];
                            if (!el.getName().equals("notification")) {
                                textSelection = false;
                                trs.add(_taggingRangeMap.get(el));
                            }
                        }
                    }
                    if (textSelection) {
                        _selectedTRs = null;
                        Event se = new Event();
                        se.data = _selectedTRs;
                        se.type = SWT.Selection;
                        for (Listener s : _markupListeners) {
                            s.handleEvent(se);
                        }
                        Event see = new Event();
                        see.data = _vexWidget.getSelectedText();
                        for (Listener s : _textSelectionListeners) {
                            s.handleEvent(see);
                        }
                    } else {
                        _selectedTRs = (TaggingRange[]) trs.toArray(new TaggingRange[trs.size()]);
                        Event se = new Event();
                        se.data = _selectedTRs;
                        se.type = SWT.Selection;
                        for (Listener s : _markupListeners) {
                            s.handleEvent(se);
                        }
                    }
                }
                _vexWidget.layout();
                _vexWidget.redraw();
                _vexWidget.update();

            }
        });
        final ControlDecoration decoNoti = new ControlDecoration(_vexWidget, SWT.LEFT | SWT.TOP);

        _vexWidget.addFocusListener(new FocusListener() {

            @Override
            public void focusLost(FocusEvent e) {
                saveChanges();
                Event se = new Event();
                se.doit = false;
                for (Listener l : _focusListeners) {
                    l.handleEvent(se);
                }

            }

            @Override
            public void focusGained(FocusEvent e) {
                Event se = new Event();
                se.doit = true;
                for (Listener l : _focusListeners) {
                    l.handleEvent(se);
                }

            }
        });

        _vexWidget.addKeyListener(new KeyListener() {

            @Override
            public void keyReleased(KeyEvent e) {
                Event se = new Event();
                se.data = e.character;
                for (Listener s : _modifyListeners) {
                    s.handleEvent(se);
                }

            }

            @Override
            public void keyPressed(KeyEvent e) {
                // TODO Auto-generated method stub

            }
        });

    }

    private boolean compareTaggingRangeAndElement(TaggingRange tr, Element el) {
        if (tr.getName().equals(el.getName())
                && (tr.getType() == null || tr.getType().trim().length() == 0
                        || tr.getType().equals(el.getAttribute("type")))
                && (tr.getSubtype() == null || tr.getSubtype().trim().length() == 0
                        || tr.getSubtype().equals(el.getAttribute("subtype")))
                && (tr.getRole() == null || tr.getRole().trim().length() == 0
                        || tr.getRole().equals(el.getAttribute("role")))
                && tr.getTextValue().equals(el.getText())) {
            System.out.println("tr equal el");
            return true;
        }
        return false;
    }

    private static StyleSheet createStyleSheet() {
        final URL styleSheetUrl = MarkupEditorVex.class.getResource("comment.css");
        final StyleSheetReader reader = new StyleSheetReader();
        try {
            return reader.read(styleSheetUrl);
        } catch (IOException e) {
            AEConstants.ILOGGER.log(new Status(IStatus.INFO, Activator.PLUGIN_ID,
                    "Error trying to read Stylesheet: " + styleSheetUrl.toString()));
            throw new AssertionError("Cannot read the stylesheet: " + e.getMessage());
        }
    }

    @Override
    public void saveChanges() {
        if (_aspect != null && _vexWidget != null && _vexWidget.getDocument() != null) {
            ByteArrayOutputStream output = new ByteArrayOutputStream();

            DocumentWriter docWriter = new DocumentWriter();
            IWhitespacePolicy wsp = new IWhitespacePolicy() {

                @Override
                public boolean isPre(Element element) {
                    System.out.println("isPre " + element.getName());

                    if (element.getName().equals("notification")) {
                        return true;
                    } else {
                        return true;
                    }
                }

                @Override
                public boolean isBlock(Element element) {
                    System.out.println("isBlock " + element.getName());
                    if (element.getName().equals("notification")) {
                        return true;
                    } else {
                        return true;
                    }
                }
            };
            docWriter.setWhitespacePolicy(wsp);
            System.out.println("document encoding " + _vexWidget.getDocument().getEncoding());
            try {
                docWriter.write(_vexWidget.getDocument(), output);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            String xml = null;

            try {
                xml = new String(output.toByteArray(), "UTF-8");
            } catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            Pattern p = Pattern.compile("<\\?xml version='1.0'\\?>");
            Matcher m = p.matcher(xml);
            xml = m.replaceAll("<\\?xml version=\"1.0\" encoding=\"UTF-8\"\\?>");
            System.out.println("saveChanges in vex " + xml);

            _aspect.setNotificationAsXML(xml);
        }
    }

    @Override
    public final void deleteMarkup(final TaggingRange[] taggingRanges) {
        if (taggingRanges != null) {
            if (_recentTaggingRangeMap != null) {
                for (TaggingRange tr : taggingRanges) {
                    _aspect.getRangeList().remove(_recentTaggingRangeMap.get(tr));
                }
            } else {
                for (TaggingRange tr : taggingRanges) {
                    _aspect.getRangeList().remove(tr);
                }
            }
            int caret = _vexWidget.getCaretOffset();

            try {
                loadValues();
            } catch (ParserConfigurationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (SAXException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (XMLStreamException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            _vexWidget.moveTo(caret);
        }

    }

    @Override
    public final Aspect getAspect() {
        return _aspect;
    }

    @Override
    public final Control getControl() {
        return _vexWidget;
    }

    @Override
    public final TaggingRange[] getSelectedMarkups() {
        return _selectedTRs;
    }

    @Override
    public final String getTitle() {
        return _title;
    }

    @Override
    public final void insertContentSetMarkup(final TaggingRange taggingRange) {
        if (taggingRange.getType() != null && taggingRange.getType().trim().length() > 0
                && taggingRange.getTextValue().trim().length() > 0) {

            Collections.sort(_aspect.getRangeList());
            int start = _vexWidget.getSelectionStart();

            String selectedText = taggingRange.getTextValue();

            taggingRange.setStart(start);
            taggingRange.setLength(selectedText.length());

            Element el = new Element(taggingRange.getName());
            if (taggingRange.getType() != null && taggingRange.getType().trim().length() > 0) {
                el.setAttribute("type", taggingRange.getType());
            }
            if (taggingRange.getSubtype() != null && taggingRange.getSubtype().trim().length() > 0) {
                el.setAttribute("subtype", taggingRange.getSubtype());
            }
            if (taggingRange.getRole() != null && taggingRange.getRole().trim().length() > 0) {
                el.setAttribute("role", taggingRange.getRole());
            }
            if (taggingRange.getFrom() != null) {
                el.setAttribute("from", taggingRange.getFrom().toString());
            }
            if (taggingRange.getTo() != null) {
                el.setAttribute("to", taggingRange.getTo().toString());
            }
            if (taggingRange.getWhen() != null) {
                el.setAttribute("when", taggingRange.getWhen().toString());
            }
            if (taggingRange.getNotBefore() != null) {
                el.setAttribute("notBefore", taggingRange.getNotBefore().toString());
            }
            if (taggingRange.getNotAfter() != null) {
                el.setAttribute("notAfter", taggingRange.getNotAfter().toString());
            }
            if (taggingRange.getKey() != null && taggingRange.getKey().trim().length() > 0) {
                el.setAttribute("key", taggingRange.getKey());
            }
            if (taggingRange.getAna() != null && taggingRange.getAna().trim().length() > 0) {
                el.setAttribute("ana", taggingRange.getAna());
            }
            _taggingRangeMap.put(el, taggingRange);

            _vexWidget.insertText(selectedText);
            _vexWidget.moveTo(start, false);
            _vexWidget.moveTo(start + selectedText.length(), true);
            _vexWidget.insertElement(el);
            saveChanges();
            loadTaggingMap();

        }

    }

    @Override
    public final boolean isValid() {
        return true;
    }

    /**
     * Load values.
     * @throws XMLStreamException
     * @throws IOException
     * @throws SAXException
     * @throws ParserConfigurationException
     */
    private void loadValues() throws ParserConfigurationException, SAXException, IOException, XMLStreamException {
        System.out.println("loadValues");
        styleSheet = createStyleSheet();
        _taggingRangeMap = new HashMap<Element, TaggingRange>();
        Document document = createNotificatinDoc();
        System.out.println("load values encoding " + document.getEncoding());
        //      document.setEncoding("UTF-8");
        //      _vexWidget.setForeground(AEVIEWConstants.VIEW_FOREGROUND_SELECTED_COLOR);

        _vexWidget.setDocument(document, styleSheet);
        loadTaggingMap();

        //      _vexWidget.setStyleSheet(styleSheet);
        //      _vexWidget.redraw();
        _vexWidget.layout();
        _vexWidget.redraw();
        _vexWidget.update();

    }

    private void loadTaggingMap() {
        // Tagging
        LinkedList<TaggingRange> rangeList;
        ArrayList<Element> processedElements = new ArrayList<Element>();
        if (_aspect.getRangeList() != null) {
            rangeList = (LinkedList<TaggingRange>) _aspect.getRangeList();

            for (int i = 1; i < _vexWidget.getDocument().getLength(); i++) {
                Element e = _vexWidget.getDocument().getElementAt(i);
                if (e != null && !processedElements.contains(e)) {
                    processedElements.add(e);
                    for (TaggingRange tr : rangeList) {
                        if (compareTaggingRangeAndElement(tr, e)) {
                            _taggingRangeMap.put(e, tr);
                        }
                    }
                }
            }
        }

    }

    private Document createNotificatinDoc()
            throws ParserConfigurationException, SAXException, IOException, XMLStreamException {
        Document document;
        if (_aspect.getNotification() != null) {
            document = new DocumentReader().read(replaceLB(_aspect.getNotificationAsXML()));

            // document.setValidator(createValidator());
            return document;

        } else {
            document = new Document(new RootElement("notification"));
            //         document.setValidator(createValidator());
        }
        return document;
    }

    private String replaceLB(String notificationAsXML) {
        notificationAsXML.replaceAll("<lb></lb>", "\n");
        Pattern p = Pattern.compile("<lb></lb>");
        Matcher m = p.matcher(notificationAsXML);
        String replaced = m.replaceAll("\n");
        return replaced;
    }

    @Override
    public final void setAspect(final Aspect aspect) {
        this._aspect = aspect;
        if (_aspect != null) {
            try {
                loadValues();
            } catch (ParserConfigurationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (SAXException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (XMLStreamException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }

    @Override
    public final void setComposite(final Composite composite) {
        this._composite = composite;
    }

    @Override
    public final void setEditable(final boolean editable) {
        _vexWidget.setEnabled(editable);

    }

    @Override
    public final void setFont(final FontDescriptor fontDescriptor) {
        this._fontDescriptor = fontDescriptor;

    }

    @Override
    public final void setMarkup(final TaggingRange taggingRange) {
        int start = _vexWidget.getSelectionStart();
        int end = _vexWidget.getSelectionEnd();

        String selectedText = _vexWidget.getSelectedText();
        while (selectedText.startsWith(" ")) {
            selectedText = selectedText.substring(1);
            start++;
        }
        while (selectedText.endsWith(" ")) {
            selectedText = selectedText.substring(0, selectedText.length() - 1);
            end--;
        }
        taggingRange.setStart(start);
        taggingRange.setLength(end - start + 1);
        taggingRange.setTextValue(_vexWidget.getSelectedText());

        Element el = new Element(taggingRange.getName());
        if (taggingRange.getType() != null && taggingRange.getType().trim().length() > 0) {
            el.setAttribute("type", taggingRange.getType());
        }
        if (taggingRange.getSubtype() != null && taggingRange.getSubtype().trim().length() > 0) {
            el.setAttribute("subtype", taggingRange.getSubtype());
        }
        if (taggingRange.getRole() != null && taggingRange.getRole().trim().length() > 0) {
            el.setAttribute("role", taggingRange.getRole());
        }
        if (taggingRange.getFrom() != null) {
            el.setAttribute("from", taggingRange.getFrom().toString());
        }
        if (taggingRange.getTo() != null) {
            el.setAttribute("to", taggingRange.getTo().toString());
        }
        if (taggingRange.getWhen() != null) {
            el.setAttribute("when", taggingRange.getWhen().toString());
        }
        if (taggingRange.getNotBefore() != null) {
            el.setAttribute("notBefore", taggingRange.getNotBefore().toString());
        }
        if (taggingRange.getNotAfter() != null) {
            el.setAttribute("notAfter", taggingRange.getNotAfter().toString());
        }
        if (taggingRange.getKey() != null && taggingRange.getKey().trim().length() > 0) {
            el.setAttribute("key", taggingRange.getKey());
        }
        if (taggingRange.getAna() != null && taggingRange.getAna().trim().length() > 0) {
            el.setAttribute("ana", taggingRange.getAna());
        }
        _taggingRangeMap.put(el, taggingRange);
        _vexWidget.insertElement(el);
        saveChanges();
        loadTaggingMap();

    }

    @Override
    public final void setTitle(final String title) {
        this._title = title;

    }

    @Override
    public void refresh() {
        if (_aspect != null && _vexWidget != null) {
            int offset = _vexWidget.getCaretOffset();
            int textLength = _vexWidget.getDocument().getLength();
            int rangeNum = _vexWidget.getDocument().getRootElement().getChildNodes().length;
            try {
                loadValues();
            } catch (ParserConfigurationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (SAXException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (XMLStreamException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            _vexWidget.moveTo(offset);

            if (textLength != _vexWidget.getDocument().getLength()
                    || rangeNum != _vexWidget.getDocument().getRootElement().getChildNodes().length) {
                Event se = new Event();
                for (Listener s : _modifyListeners) {
                    s.handleEvent(se);
                }
            }
        }
    }

    @Override
    public void insert(String string) {
        _vexWidget.insertText(string);
    }

    @Override
    public void setSelected(boolean selected) {
        //      if (selected)
        //      {
        //         _vexWidget.setForeground(AEVIEWConstants.VIEW_FOREGROUND_SELECTED_COLOR);
        //      }
        //      else
        //      {
        //         _vexWidget.setForeground(AEVIEWConstants.VIEW_FOREGROUND_DESELECTED_COLOR);
        //      }
        //      _vexWidget.setStyleSheet(styleSheet);

    }

    @Override
    public void setFocus() {
        _vexWidget.setFocus();

    }

    @Override
    public String getSelectionText() {
        return _vexWidget.getSelectedText();
    }

}