org.openlegacy.ide.eclipse.preview.AbstractEntityPreview.java Source code

Java tutorial

Introduction

Here is the source code for org.openlegacy.ide.eclipse.preview.AbstractEntityPreview.java

Source

/*******************************************************************************
 * Copyright (c) 2014 OpenLegacy Inc.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     OpenLegacy Inc. - initial API and implementation
 *******************************************************************************/
package org.openlegacy.ide.eclipse.preview;

import org.eclipse.core.filebuffers.FileBuffers;
import org.eclipse.core.filebuffers.IFileBuffer;
import org.eclipse.core.filebuffers.ITextFileBuffer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.NormalAnnotation;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.custom.CaretEvent;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.texteditor.AbstractTextEditor;
import org.eclipse.ui.texteditor.ITextEditor;
import org.openlegacy.ide.eclipse.components.ImageComposite;
import org.openlegacy.ide.eclipse.editors.graphical.IOpenLegacyEditor;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

public abstract class AbstractEntityPreview extends ViewPart {

    private Map<String, CompilationUnit> cacheCompilationUnitContainer = new HashMap<String, CompilationUnit>();

    private Map<String, JavaClassProperties> cacheJavaClassPropertiesContainer = new HashMap<String, JavaClassProperties>();

    private Map<String, StyledText> cacheStyledTextContainer = new HashMap<String, StyledText>();

    private EditorListener editorListener;

    private boolean isVisible;

    protected IEditorPart lastActiveEditor;

    protected static CompilationUnit createParser(ICompilationUnit javaInput) {
        ASTParser parser = ASTParser.newParser(AST.JLS4);
        parser.setSource(javaInput);
        parser.setKind(ASTParser.K_COMPILATION_UNIT);
        parser.setResolveBindings(true);

        return (CompilationUnit) parser.createAST(null);
    }

    private static CompilationUnit createParser(String input) {
        ASTParser parser = ASTParser.newParser(AST.JLS4);
        parser.setSource(input.toCharArray());
        parser.setKind(ASTParser.K_COMPILATION_UNIT);
        parser.setResolveBindings(true);

        return (CompilationUnit) parser.createAST(null);
    }

    protected static IEditorPart getActiveEditor() {
        IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
        if (window != null) {
            IWorkbenchPage page = window.getActivePage();
            if (page != null) {
                return page.getActiveEditor();
            }
        }
        return null;
    }

    protected static IFile getFile(String path) {
        IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
        return root.getFile(new Path(path));
    }

    /**
     * Extract IJavaElement if current document is a java file
     * 
     * @return IJavaElement or null
     */
    protected static IJavaElement getJavaInput() {
        IEditorPart activeEditor = getActiveEditor();
        if (activeEditor != null) {
            if (!(activeEditor instanceof ITextEditor) && !(activeEditor instanceof IOpenLegacyEditor)) {
                return null;
            }
            final IJavaElement javaInput = getJavaInput(activeEditor);
            if (javaInput != null && javaInput.getPath().getFileExtension().equals("java")) {
                return javaInput;
            }
        }
        return null;
    }

    private static IJavaElement getJavaInput(IEditorPart part) {
        IEditorInput editorInput = part.getEditorInput();
        if (editorInput != null) {
            IJavaElement input = (IJavaElement) editorInput.getAdapter(IJavaElement.class);
            return input;
        }
        return null;
    }

    private boolean inspectAnnotationNode(NormalAnnotation node, List<String> imports) {
        Name typeName = node.getTypeName();
        ITypeBinding binding = typeName.resolveTypeBinding();
        if (binding != null) {
            String qualifiedName = binding.getQualifiedName();
            if (qualifiedName != null) {
                if (qualifiedName.equals(getEntityAnnotation())) {
                    return true;
                }
            }
        } else {
            // in case if binding is not resolved
            String fullyQualifiedName = typeName.getFullyQualifiedName();
            if (fullyQualifiedName.equals(getEntityAnnotation())
                    || fullyQualifiedName.equals(getEntityAnnotationShort())) {
                if (imports.contains(getEntityAnnotation())
                        || imports.contains(getEntityAnnotation().replace(getEntityAnnotationShort(), "*"))) {
                    return true;
                }
            }
        }
        return false;
    }

    protected abstract String getEntityAnnotation();

    protected abstract String getEntityAnnotationShort();

    private static List<String> prepareImports(Object[] imports) {
        List<String> importList = new ArrayList<String>();
        for (Object importItem : imports) {
            String string = importItem.toString();
            importList.add(
                    string.substring(string.indexOf("import") + "import".length(), string.lastIndexOf(";")).trim());
        }
        return importList;
    }

    /**
     * Extract JavaClassProperties if current source annotated with <b>@ScreenEntity</b>
     * 
     * @return JavaClassProperties instance or null
     */
    private JavaClassProperties getJavaClassProperties(String key, Object source) {
        final AtomicBoolean isAccepted = new AtomicBoolean(false);
        IFile sourceFile = null;

        CompilationUnit cu = getCacheCompilationUnitContainer().get(key);
        if (cu == null) {
            // create parser
            if (source instanceof ITextFileBuffer) {
                cu = createParser(((ITextFileBuffer) source).getDocument().get());
            } else {
                cu = createParser((ICompilationUnit) source);
            }
        }

        getCacheCompilationUnitContainer().put(key, cu);

        if (cu == null) {
            return null;
        }

        final List<String> imports = prepareImports(cu.imports().toArray());

        // run through the code and visit Annotation nodes
        cu.accept(new ASTVisitor() {

            @Override
            public boolean visit(NormalAnnotation node) {
                if (node != null && !isAccepted.get()) {
                    isAccepted.set(inspectAnnotationNode(node, imports));
                }
                return true;
            }
        });
        if (isAccepted.get()) {
            sourceFile = getSourceFile(cu.getJavaElement().getPath());
        }
        return new JavaClassProperties(sourceFile, isAccepted.get());
    }

    @Override
    public void dispose() {
        super.dispose();

        if (editorListener != null) {
            // remove Part listener
            getSite().getWorkbenchWindow().getPartService().removePartListener(editorListener);
            // remove FileBuffer listener
            FileBuffers.getTextFileBufferManager().removeFileBufferListener(editorListener);

            // remove Caret & Modify listeners
            for (StyledText styledText : getCacheStyledTextContainer().values()) {
                if (!styledText.isDisposed()) {
                    styledText.removeCaretListener(editorListener);
                    styledText.removeModifyListener(editorListener);
                }
            }
            editorListener.dispose();
            editorListener = null;
        }
    }

    public void handleBufferIsDirty(IFileBuffer buffer) {
        // parse annotation(buffer) to update in cache
        String key = buffer.getLocation().toOSString();
        if (cacheJavaClassPropertiesContainer.containsKey(key)) {
            JavaClassProperties properties = getJavaClassProperties(key, buffer);
            cacheJavaClassPropertiesContainer.put(key, properties);
        }
        doPartActivated();
    }

    public void handlePartActivated(IWorkbenchPart part) {
        doPartActivated();
    }

    public void handlePartClosed(IWorkbenchPart part) {
        // hide image if editor with annotation closed
        if (part == lastActiveEditor) {
            getImageComposite().setVisible(false);
            lastActiveEditor = null;
        }
    }

    public void handlePartHidden(IWorkbenchPart part) {
        if (this == part) {
            isVisible = false;
        }
    }

    public void handlePartVisible(IWorkbenchPart part) {
        if (this == part) {
            if (isVisible) {
                return;
            }
            isVisible = true;
        }
    }

    private void doPartActivated() {
        if (isVisible) {
            IJavaElement javaInput = getJavaInput();
            if (javaInput != null) {
                final AtomicBoolean isAccepted = new AtomicBoolean(false);

                String key = javaInput.getPath().toOSString();
                if (!cacheJavaClassPropertiesContainer.containsKey(key)) {
                    JavaClassProperties properties = getJavaClassProperties(key, javaInput);
                    cacheJavaClassPropertiesContainer.put(key, properties);
                    isAccepted.set(properties != null);
                } else {
                    JavaClassProperties properties = cacheJavaClassPropertiesContainer.get(key);
                    // if cached class is annotated then check if there is the latest version of image
                    if (properties.isAnnotated()) {
                        isAccepted.set(true);
                        IFile sourceFile = null;
                        sourceFile = properties.getSourceFile();
                        IFile newSourceFile = getSourceFile(javaInput.getPath());
                        if (sourceFile.getModificationStamp() != newSourceFile.getModificationStamp()) {
                            sourceFile = newSourceFile;
                            properties.setSourceFile(newSourceFile);
                        }
                    }
                }

                if (isAccepted.get()) {
                    // add caret listener
                    if (!getCacheStyledTextContainer().containsKey(key)
                            || getCacheStyledTextContainer().get(key).isDisposed()) {
                        IEditorPart activeEditor = getActiveEditor();
                        if (!(activeEditor instanceof IOpenLegacyEditor)) {
                            AbstractTextEditor editor = (AbstractTextEditor) activeEditor;
                            StyledText styledText = ((StyledText) editor.getAdapter(Control.class));
                            styledText.addCaretListener(editorListener);
                            styledText.addModifyListener(editorListener);
                            getCacheStyledTextContainer().put(key, styledText);
                        }
                    }
                    // show image if it exists
                    showPreviewImage(javaInput, cacheJavaClassPropertiesContainer.get(key).getSourceFile());
                    lastActiveEditor = getActiveEditor();
                    return;
                }
            }
        }
        // keep last shown image - comfort during dev.
        // getImageComposite().setVisible(false);
    }

    protected abstract void showPreviewImage(IJavaElement javaInput, IFile sourceFile);

    protected abstract ImageComposite getImageComposite();

    protected abstract IFile getSourceFile(IPath path);

    @Override
    public void init(IViewSite site) throws PartInitException {
        super.init(site);
        if (editorListener == null) {
            editorListener = new EditorListener(this);
            // set Part listener
            getSite().getWorkbenchWindow().getPartService().addPartListener(editorListener);
            // set FileBuffer listener
            FileBuffers.getTextFileBufferManager().addFileBufferListener(editorListener);
        }

    }

    /**
     * Passing the focus request to the viewer's control.
     */
    @Override
    public void setFocus() {
        getImageComposite().setFocus();
    }

    public void showEnlargedImage() {
        getImageComposite().showEnlargedImage();
    }

    public void showMessage(String message) {
        MessageDialog.openInformation(getImageComposite().getShell(), "Screen Preview", message);
    }

    public Map<String, CompilationUnit> getCacheCompilationUnitContainer() {
        return cacheCompilationUnitContainer;
    }

    public Map<String, StyledText> getCacheStyledTextContainer() {
        return cacheStyledTextContainer;
    }

    public void handleCaretMoved(CaretEvent caretEvent) {
        // allow override

    }

    public void handleModifyText(ModifyEvent event) {
        // allow override
    }
}