sernet.verinice.samt.audit.rcp.ElementView.java Source code

Java tutorial

Introduction

Here is the source code for sernet.verinice.samt.audit.rcp.ElementView.java

Source

/*******************************************************************************
 * Copyright (c) 2010 Daniel Murygin.
 *
 * This program 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.
 * This program 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 this program. 
 * If not, see <http://www.gnu.org/licenses/>.
 * 
 * Contributors:
 *     Daniel Murygin <dm[at]sernet[dot]de> - initial API and implementation
 ******************************************************************************/
package sernet.verinice.samt.audit.rcp;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;
import org.eclipse.core.resources.WorkspaceJob;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.viewers.DecoratingLabelProvider;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.part.ViewPart;

import sernet.gs.service.RetrieveInfo;
import sernet.gs.ui.rcp.main.Activator;
import sernet.gs.ui.rcp.main.ExceptionUtil;
import sernet.gs.ui.rcp.main.bsi.editors.EditorFactory;
import sernet.gs.ui.rcp.main.bsi.views.TreeViewerCache;
import sernet.gs.ui.rcp.main.common.model.CnAElementFactory;
import sernet.gs.ui.rcp.main.common.model.IModelLoadListener;
import sernet.gs.ui.rcp.main.service.ServiceFactory;
import sernet.hui.common.connect.Entity;
import sernet.verinice.interfaces.CommandException;
import sernet.verinice.interfaces.ICommandService;
import sernet.verinice.iso27k.rcp.ISMViewContentProvider;
import sernet.verinice.iso27k.rcp.ISMViewLabelProvider;
import sernet.verinice.iso27k.rcp.ISO27KModelViewUpdate;
import sernet.verinice.iso27k.rcp.JobScheduler;
import sernet.verinice.iso27k.service.Retriever;
import sernet.verinice.model.bsi.BSIModel;
import sernet.verinice.model.common.CnALink;
import sernet.verinice.model.common.CnATreeElement;
import sernet.verinice.model.iso27k.Audit;
import sernet.verinice.model.iso27k.Group;
import sernet.verinice.model.iso27k.ISO27KModel;
import sernet.verinice.model.iso27k.Organization;

/**
 * Abstract view with tree viewer to show {@link CnATreeElement}s of specific types
 * and of {@link Group}s which contains these types.
 * 
 * Subclasses implements methods to load the desired elements.
 * 
 * @author Daniel Murygin <dm[at]sernet[dot]de>
 */
@SuppressWarnings("restriction")
public abstract class ElementView extends ViewPart {

    private static final Logger LOG = Logger.getLogger(ElementView.class);

    private static volatile ISO27KModel dummy = null;

    protected static synchronized ISO27KModel getDummy() {
        if (dummy == null) {
            dummy = new ISO27KModel();
            dummy.setEntity(new Entity(ISO27KModel.TYPE_ID));
        }
        return dummy;
    }

    protected TreeViewer viewer;

    protected TreeViewerCache cache = new TreeViewerCache();

    protected ISMViewContentProvider contentProvider;

    private ISO27KModelViewUpdate modelUpdateListener;

    private IModelLoadListener modelLoadListener;

    private ISelectionListener selectionListener;

    private Action doubleClickAction;

    private ICommandService commandService;

    private Integer selectedId;

    private Object selection;

    protected CnATreeElement selectedGroup;

    private CnATreeElement elementToLink;

    private Audit selectedAudit;

    private Organization selectedOrganization;

    private Label textLink, textGroup;

    /**
     * @return {@link CnATreeElement}s to show in this view
     * @throws CommandException
     */
    protected abstract List<? extends CnATreeElement> getElementList() throws CommandException;

    /**
     * Loads {@link CnATreeElement}s which are linked to the element with primary key
     * selectedId. After loading elements are shown in the view
     * 
     * @param selectedId primary key of a {@link CnATreeElement}
     * @return Elements linked to primary key selectedId
     * @throws CommandException
     */
    protected abstract List<? extends CnATreeElement> getLinkedElements(int selectedId) throws CommandException;

    /* (non-Javadoc)
     * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
     */
    @Override
    public void createPartControl(final Composite parent) {
        try {
            initView(parent);
            startInitDataJob();
        } catch (Exception e) {
            LOG.error("Error while creating view", e); //$NON-NLS-1$
            ExceptionUtil.log(e, Messages.ElementView_1);
        }

    }

    protected void initView(Composite parent) {
        GridLayout gridLayoutParent = new GridLayout(1, true);
        parent.setLayout(gridLayoutParent);

        Composite compositeInfo = new Composite(parent, SWT.NONE);
        compositeInfo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        GridLayout gridLayoutInfo = new GridLayout(2, false);
        compositeInfo.setLayout(gridLayoutInfo);

        Label labelLink = new Label(compositeInfo, SWT.NONE);
        labelLink.setText(Messages.ElementView_2);
        labelLink.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
        textLink = new Label(compositeInfo, SWT.NONE);
        textLink.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

        viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
        viewer.getTree().setLayoutData(new GridData(GridData.FILL_BOTH));
        contentProvider = new ISMViewContentProvider(cache, new ElementViewTreeCommandFactory(),
                new ElementViewParentLoader());

        viewer.setContentProvider(contentProvider);

        IWorkbench workbench = getSite().getWorkbenchWindow().getWorkbench();
        viewer.setLabelProvider(
                new DecoratingLabelProvider(new ISMViewLabelProvider(cache), workbench.getDecoratorManager()));

        // make the viewer a selection provider
        getSite().setSelectionProvider(viewer);
        // listen to other selection provider
        addSelectionListener();

        hookContextMenu();
        makeActions();
        addActions();
        fillToolBar();
        hookDndListeners();
    }

    /**
     * 
     */
    protected void startInitDataJob() {
        WorkspaceJob initDataJob = new WorkspaceJob(Messages.ElementView_4) {
            public IStatus runInWorkspace(final IProgressMonitor monitor) {
                IStatus status = Status.OK_STATUS;
                try {
                    monitor.beginTask(Messages.ElementView_5, IProgressMonitor.UNKNOWN);
                    initData();
                } catch (Exception e) {
                    LOG.error("Error while loading data.", e); //$NON-NLS-1$
                    status = new Status(Status.ERROR, "sernet.verinice.samt.audit.rcp", Messages.ElementView_8, e); //$NON-NLS-1$
                } finally {
                    monitor.done();
                }
                return status;
            }
        };
        JobScheduler.scheduleInitJob(initDataJob);
    }

    protected void initData() throws CommandException {
        if (CnAElementFactory.isIsoModelLoaded()) {
            if (modelUpdateListener == null) {
                // modellistener should only be created once!
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Creating modelUpdateListener for ISMView."); //$NON-NLS-1$
                }
                Activator.inheritVeriniceContextState();
                modelUpdateListener = createISO27KModelViewUpdate();
                CnAElementFactory.getInstance().getISO27kModel().addISO27KModelListener(modelUpdateListener);
                final List<? extends CnATreeElement> elementList = getElementList();
                Display.getDefault().syncExec(new Runnable() {
                    public void run() {
                        setInput(elementList);
                    }
                });
            }
        } else if (modelLoadListener == null) {
            // model is not loaded yet: add a listener to load data when it's laoded
            modelLoadListener = new IModelLoadListener() {
                public void closed(BSIModel model) {
                    // nothing to do
                }

                public void loaded(BSIModel model) {
                    // nothing to do
                }

                @Override
                public void loaded(ISO27KModel model) {
                    synchronized (modelLoadListener) {
                        startInitDataJob();
                    }
                }
            };
            CnAElementFactory.getInstance().addLoadListener(modelLoadListener);
        }
    }

    private Set<CnATreeElement> editElementSet = new HashSet<CnATreeElement>();

    /**
     * @param newElement
     */
    public void registerforEdit(CnATreeElement newElement) {
        synchronized (editElementSet) {
            editElementSet.add(newElement);
        }
    }

    protected ISO27KModelViewUpdate createISO27KModelViewUpdate() {
        return new ISO27KModelViewUpdate(viewer, cache) {
            public void linkAdded(CnALink link) {
                reload();
                // Open the editors registered before in AddAction
                synchronized (editElementSet) {
                    openEqualLinkEditors(link);
                }
            }

            @Override
            public void databaseChildRemoved(CnATreeElement child) {
                super.databaseChildRemoved(child);
                reload();
            }

            @Override
            public void databaseChildAdded(CnATreeElement child) {
                child = reloadParent(child);
                super.databaseChildAdded(child);
            }
        };
    }

    private void addSelectionListener() {
        selectionListener = new ISelectionListener() {
            /* (non-Javadoc)
             * @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection)
             */
            public void selectionChanged(IWorkbenchPart sourcePart, ISelection selection) {
                pageSelectionChanged(sourcePart, selection);
            }
        };
        getSite().getPage().addPostSelectionListener(selectionListener);
    }

    /**
     * @param part
     * @param selection
     */
    protected void pageSelectionChanged(IWorkbenchPart sourcePart, ISelection selection) {
        if (selection instanceof IStructuredSelection && sourcePart instanceof ElementView) {
            Object element = ((IStructuredSelection) selection).getFirstElement();
            if (element instanceof CnATreeElement) {
                CnATreeElement treeElement = (CnATreeElement) element;
                boolean sourceIsThisView = this.equals(sourcePart);
                setPageSelection(element, treeElement, sourceIsThisView);
            }
        }
    }

    private void setPageSelection(Object element, CnATreeElement treeElement, boolean sourceIsThisView) {
        if (!sourceIsThisView) {
            // check if treeElement has a relation to elements in this view
            if (checkRelations(treeElement)) {
                loadElements(treeElement);
                setElementToLink(treeElement);
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Selected link element, Type: " + treeElement.getObjectType() + ", name: " //$NON-NLS-1$//$NON-NLS-2$
                            + treeElement.getTitle());
                }
            }
            if (treeElement != null && treeElement.getTypeId().equals(Audit.TYPE_ID)) {
                setSelectedAudit((Audit) treeElement);
            }
            if (treeElement != null && treeElement.getTypeId().equals(Organization.TYPE_ID)) {
                setSelectedOrganization((Organization) treeElement);
            }
        } else {
            if (element instanceof Group) {
                CnATreeElement selectedElement = (CnATreeElement) element;
                setSelectedGroup(selectedElement);
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Selected group, Type: " + selectedGroup.getObjectType() + ", name: " //$NON-NLS-1$//$NON-NLS-2$
                            + selectedGroup.getTitle());
                }
            } else {
                setSelectedGroup(null);
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Removing selected group, Type: " + selectedGroup.getObjectType() + ", name: " //$NON-NLS-1$//$NON-NLS-2$
                            + selectedGroup.getTitle());
                }
            }
        }
    }

    private void loadElements(Object element) {
        this.selection = element;
        try {
            if (element == null) {
                final List<? extends CnATreeElement> elementList = getElementList();
                Display.getDefault().syncExec(new Runnable() {
                    public void run() {
                        setInput(elementList);
                    }
                });
            } else if (element instanceof CnATreeElement) {
                CnATreeElement treeElement = (CnATreeElement) element;

                // check if treeElement has a relation to elements in this view
                if (checkRelations(treeElement)) {
                    selectedId = treeElement.getDbId();
                    final List<? extends CnATreeElement> elementList = getLinkedElements(selectedId);
                    Display.getDefault().syncExec(new Runnable() {
                        public void run() {
                            setInput(elementList);
                        }
                    });
                }
            } else {
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Unknown element selected: " + element); //$NON-NLS-1$
                }
            }
        } catch (Exception e) {
            LOG.error("Error while loading linked elements", e); //$NON-NLS-1$
        }
    }

    /**
     * Checks if selectedGroup is in elementList. 
     * If not selectedGroup is set to null.
     * 
     * @param elementList list of {@link CnATreeElement}s
     */
    protected void checkSelectedGroup(List elementList) {
        if (selectedGroup != null && (elementList == null || !elementList.contains(getSelectedGroup()))) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Removing selected group, Type: " + getSelectedGroup().getObjectType() + ", name: " //$NON-NLS-1$//$NON-NLS-2$
                        + getSelectedGroup().getTitle());
            }
            setSelectedGroup(null);
        }
    }

    /**
     * Returns true if treeElement has a relation to elements in this view.
     * Implement this in classes extending this view.
     * 
     * @param treeElement 
     * @return true if treeElement has a relation to elements in this view
     */
    protected boolean checkRelations(CnATreeElement treeElement) {
        return true;
    }

    public void reload() {
        loadElements(this.selection);
        Display.getDefault().asyncExec(new Runnable() {
            public void run() {
                viewer.refresh();
            }
        });
    }

    public void setInput(List list) {
        if (list != null && !list.isEmpty()) {
            viewer.setInput(list);
        } else {
            viewer.setInput(getDummy());
        }
    }

    public void setIcon(Image icon) {
        this.setTitleImage(icon);
    }

    public void setViewTitle(String title) {
        setPartName(title);
    }

    private void hookContextMenu() {
        MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$
        menuMgr.setRemoveAllWhenShown(true);
        menuMgr.addMenuListener(new IMenuListener() {
            public void menuAboutToShow(IMenuManager manager) {
                fillContextMenu(manager);
            }
        });
        Menu menu = menuMgr.createContextMenu(viewer.getControl());

        viewer.getControl().setMenu(menu);
        getSite().registerContextMenu(menuMgr, viewer);
    }

    /**
     * @param manager
     */
    protected void fillContextMenu(IMenuManager manager) {
        // TODO Auto-generated method stub

    }

    /**
     * 
     */
    protected void makeActions() {
        doubleClickAction = new Action() {
            public void run() {
                if (viewer.getSelection() instanceof IStructuredSelection) {
                    Object sel = ((IStructuredSelection) viewer.getSelection()).getFirstElement();
                    EditorFactory.getInstance().updateAndOpenObject(sel);
                }
            }
        };

    }

    private void addActions() {
        viewer.addDoubleClickListener(new IDoubleClickListener() {
            public void doubleClick(DoubleClickEvent event) {
                doubleClickAction.run();
            }
        });
    }

    /**
     * 
     */
    protected void fillToolBar() {
        //IActionBars bars = getViewSite().getActionBars();
        //IToolBarManager manager = bars.getToolBarManager();
        //manager.add(someAction);
    }

    protected void hookDndListeners() {
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.part.WorkbenchPart#dispose()
     */
    @Override
    public void dispose() {
        CnAElementFactory.getInstance().getISO27kModel().removeISO27KModelListener(modelUpdateListener);
        CnAElementFactory.getInstance().removeLoadListener(modelLoadListener);
        getSite().getPage().removePostSelectionListener(selectionListener);
        super.dispose();
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
     */
    @Override
    public void setFocus() {
        // TODO Auto-generated method stub

    }

    protected CnATreeElement getSelectedGroup() {
        return selectedGroup;
    }

    protected void setSelectedGroup(CnATreeElement selectedGroup) {
        this.selectedGroup = selectedGroup;
        if (textGroup != null) {
            textGroup.setText((selectedGroup != null) ? selectedGroup.getTitle() : ""); //$NON-NLS-1$
        }
    }

    public void setElementToLink(CnATreeElement element) {
        this.elementToLink = element;
        textLink.setText((element != null) ? element.getTitle() : ""); //$NON-NLS-1$
    }

    public CnATreeElement getElementToLink() {
        return elementToLink;
    }

    public void setSelectedAudit(Audit selectedAudit) {
        this.selectedAudit = selectedAudit;
    }

    public Audit getSelectedAudit() {
        return selectedAudit;
    }

    protected Organization getSelectedOrganization() {
        return selectedOrganization;
    }

    protected void setSelectedOrganization(Organization selectedOrganization) {
        this.selectedOrganization = selectedOrganization;
    }

    public ICommandService getCommandService() {
        if (commandService == null) {
            commandService = createCommandServive();
        }
        return commandService;
    }

    private ICommandService createCommandServive() {
        return ServiceFactory.lookupCommandService();
    }

    private CnATreeElement reloadParent(CnATreeElement child) {
        // reload the parent, put is to the cache
        RetrieveInfo ri = RetrieveInfo.getPropertyChildrenInstance().setParent(true);
        CnATreeElement parent = Retriever.retrieveElement(child.getParent(), ri);
        cache.clear(parent);
        cache.addObject(parent);
        child.setParentAndScope(parent);
        return child;
    }

    private void openEqualLinkEditors(CnALink link) {
        Set<CnATreeElement> workSet = new HashSet<CnATreeElement>(editElementSet);
        for (CnATreeElement element : workSet) {
            if (element.equals(link.getDependant())) {
                EditorFactory.getInstance().openEditor(link.getDependant());
                editElementSet.remove(element);
            }
            if (element.equals(link.getDependency())) {
                EditorFactory.getInstance().openEditor(link.getDependency());
                editElementSet.remove(element);
            }
        }
        if (editElementSet.size() > 0) {
            LOG.warn("Two links added at the same time");
        }
    }

}