de.hentschel.visualdbc.statistic.ui.control.ProofReferenceComposite.java Source code

Java tutorial

Introduction

Here is the source code for de.hentschel.visualdbc.statistic.ui.control.ProofReferenceComposite.java

Source

/*******************************************************************************
 * Copyright (c) 2014 Karlsruhe Institute of Technology, Germany
 *                    Technical University Darmstadt, Germany
 *                    Chalmers University of Technology, Sweden
 * 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:
 *    Technical University Darmstadt - initial API and implementation and/or initial documentation
 *******************************************************************************/

package de.hentschel.visualdbc.statistic.ui.control;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.runtime.Assert;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.provider.ReflectiveItemProviderAdapterFactory;
import org.eclipse.emf.edit.provider.resource.ResourceItemProviderAdapterFactory;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
import org.eclipse.jface.layout.TreeColumnLayout;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.LabelProviderChangedEvent;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorPart;
import org.key_project.util.eclipse.swt.SWTUtil;
import org.key_project.util.java.ObjectUtil;

import de.hentschel.visualdbc.dbcmodel.AbstractDbcOperation;
import de.hentschel.visualdbc.dbcmodel.AbstractDbcType;
import de.hentschel.visualdbc.dbcmodel.DbCAxiomContract;
import de.hentschel.visualdbc.dbcmodel.DbcAttribute;
import de.hentschel.visualdbc.dbcmodel.DbcAxiom;
import de.hentschel.visualdbc.dbcmodel.DbcEnumLiteral;
import de.hentschel.visualdbc.dbcmodel.DbcInvariant;
import de.hentschel.visualdbc.dbcmodel.DbcOperationContract;
import de.hentschel.visualdbc.dbcmodel.DbcProof;
import de.hentschel.visualdbc.dbcmodel.DbcProofReference;
import de.hentschel.visualdbc.dbcmodel.DbcmodelPackage;
import de.hentschel.visualdbc.dbcmodel.IDbCProofReferencable;
import de.hentschel.visualdbc.dbcmodel.IDbCProvable;
import de.hentschel.visualdbc.dbcmodel.provider.DbcmodelItemProviderAdapterFactory;

/**
 * Shows the proof references of selected elements provided by an {@link IProofReferenceProvider}.
 * @author Martin Hentschel
 */
public class ProofReferenceComposite extends Composite {
    /**
     * The {@link IEditorPart} which provides the content.
     */
    private IEditorPart editor;

    /**
     * The {@link IProofReferenceProvider} to use.
     */
    private IProofReferenceProvider proofReferenceProvider;

    /**
     * Shows the available proof references.
     */
    private TreeViewer viewer;

    /**
     * The used {@link ITreeContentProvider} in {@link #viewer}.
     */
    private ProofReferenceTreeContentProvider contentProvider;

    /**
     * The used {@link ITableLabelProvider} in {@link #viewer}.
     */
    private ProofReferenceLabelProvider labelProvider;

    /**
     * Listens for selection changes on {@link #editor}.
     */
    private ISelectionChangedListener selectionListener = new ISelectionChangedListener() {
        @Override
        public void selectionChanged(SelectionChangedEvent event) {
            handleSelectionChanged(event);
        }
    };

    /**
     * Constructor.
     * @param parent The parent {@link Composite}.
     * @param style The style to use.
     * @param editor The {@link IEditorPart} which provides the content.
     * @param proofReferenceProvider The {@link IProofReferenceProvider} to use.
     */
    public ProofReferenceComposite(Composite parent, int style, IEditorPart editor,
            IProofReferenceProvider proofReferenceProvider) {
        super(parent, style);
        Assert.isNotNull(editor);
        Assert.isNotNull(proofReferenceProvider);
        this.editor = editor;
        this.proofReferenceProvider = proofReferenceProvider;
        editor.getEditorSite().getSelectionProvider().addSelectionChangedListener(selectionListener);
        // Create viewer
        TreeColumnLayout viewerLayout = new TreeColumnLayout();
        setLayout(viewerLayout);
        viewer = new TreeViewer(this, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.FULL_SELECTION);
        viewer.getTree().setHeaderVisible(true);
        viewer.getTree().setLinesVisible(true);
        viewer.addDoubleClickListener(new IDoubleClickListener() {
            @Override
            public void doubleClick(DoubleClickEvent event) {
                handleDoubleClick(event);
            }
        });
        // Add main column
        TreeViewerColumn mainColumn = new TreeViewerColumn(viewer, SWT.NONE);
        mainColumn.getColumn().setText("Selected Element");
        mainColumn.getColumn().setMoveable(true);
        viewerLayout.setColumnData(mainColumn.getColumn(), new ColumnWeightData(40));
        // Add direction column
        TreeViewerColumn directionColumn = new TreeViewerColumn(viewer, SWT.NONE);
        directionColumn.getColumn().setText("Direction");
        directionColumn.getColumn().setMoveable(true);
        viewerLayout.setColumnData(directionColumn.getColumn(), new ColumnWeightData(10));
        // Add kind column
        TreeViewerColumn kindColumn = new TreeViewerColumn(viewer, SWT.NONE);
        kindColumn.getColumn().setText("Kind");
        kindColumn.getColumn().setMoveable(true);
        viewerLayout.setColumnData(kindColumn.getColumn(), new ColumnWeightData(20));
        // Add direction target column
        TreeViewerColumn directionTargetColumn = new TreeViewerColumn(viewer, SWT.NONE);
        directionTargetColumn.getColumn().setText("Direction Target");
        directionTargetColumn.getColumn().setMoveable(true);
        viewerLayout.setColumnData(directionTargetColumn.getColumn(), new ColumnWeightData(40));
        // Update content in viewer
        updateContent(editor.getEditorSite().getSelectionProvider().getSelection());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void dispose() {
        editor.getEditorSite().getSelectionProvider().removeSelectionChangedListener(selectionListener);
        if (contentProvider != null) {
            contentProvider.dispose();
        }
        if (labelProvider != null) {
            labelProvider.dispose();
        }
        super.dispose();
    }

    /**
     * Handles a double click in the viewer.
     * @param event The event.
     */
    protected void handleDoubleClick(DoubleClickEvent event) {
        if (proofReferenceProvider != null) {
            List<?> selectedElements = SWTUtil.toList(event.getSelection());
            List<Object> toSelect = new LinkedList<Object>();
            for (Object selected : selectedElements) {
                if (selected instanceof ProofReferenceEntry) {
                    toSelect.add(((ProofReferenceEntry) selected).getDirectionTarget());
                } else {
                    toSelect.add(selected);
                }
            }
            proofReferenceProvider.select(toSelect);
        }
    }

    /**
     * When the selection of {@link #editor} has changed.
     * @param event The event.
     */
    protected void handleSelectionChanged(SelectionChangedEvent event) {
        updateContent(event.getSelection());
    }

    /**
     * Sets the input of {@link #viewer}.
     * @param selection The {@link ISelection} to show in {@link #viewer}.
     */
    protected void updateContent(ISelection selection) {
        // Add new provider to remove no longer needed observed objects
        if (contentProvider != null) {
            contentProvider.dispose();
        }
        contentProvider = new ProofReferenceTreeContentProvider();
        viewer.setContentProvider(contentProvider);
        if (labelProvider != null) {
            labelProvider.dispose();
        }
        labelProvider = new ProofReferenceLabelProvider();
        viewer.setLabelProvider(labelProvider);
        // Set new input
        List<?> elements = SWTUtil.toList(selection);
        List<?> elementsToShow = proofReferenceProvider.extractElementsToShow(elements);
        if (elementsToShow == null) {
            elementsToShow = Collections.emptyList();
        }
        viewer.setInput(elementsToShow);
        viewer.expandToLevel(2);
    }

    /**
     * The {@link ITreeContentProvider} used in the viewer of {@link ProofReferenceComposite}.
     * @author Martin Hentschel
     */
    public static class ProofReferenceTreeContentProvider implements ITreeContentProvider {
        /**
         * The {@link TreeViewer} in which this {@link ITreeContentProvider} is used.
         */
        private TreeViewer viewer;

        /**
         * The current input of {@link #viewer}.
         */
        private Object input;

        /**
         * The filtered elements of {@link #input} which are shown in {@link #viewer}.
         */
        private Set<EObject> filteredInput;

        /**
         * Observed {@link EObject}s.
         */
        private Set<EObject> observedObjects = new HashSet<EObject>();

        /**
         * Listener on each instance in {@link #observedObjects}.
         */
        private Adapter changeListener = new AdapterImpl() {
            @Override
            public void notifyChanged(Notification msg) {
                handleNotifyChanged(msg);
            }
        };

        /**
         * Mapping of a parent element to its children.
         */
        private Map<Object, Object[]> childMapping = new HashMap<Object, Object[]>();

        /**
         * {@inheritDoc}
         */
        @Override
        public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
            clearObservedObjects();
            this.childMapping.clear();
            this.viewer = viewer instanceof TreeViewer ? (TreeViewer) viewer : null;
            this.input = newInput;
            this.filteredInput = filterInput(newInput);
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public void dispose() {
            clearObservedObjects();
            this.childMapping.clear();
        }

        /**
         * Removes the change listener from all objects in {@link #observedObjects}
         * and clears the list.
         */
        protected void clearObservedObjects() {
            for (EObject obj : observedObjects) {
                obj.eAdapters().remove(changeListener);
            }
            observedObjects.clear();
        }

        /**
         * Adds the change listener {@link #changeListener} to the given {@link EObject}
         * and registers the {@link EObject} in {@link #observedObjects}.
         * @param obj The {@link EObject} to observe.
         */
        protected void observeObject(EObject obj) {
            if (observedObjects.add(obj)) {
                obj.eAdapters().add(changeListener);
            }
        }

        /**
         * When something has changed on an observed {@link EObject} in {@link #observedObjects}.
         * @param msg The event.
         */
        protected void handleNotifyChanged(Notification msg) {
            if (DbcmodelPackage.Literals.DBC_PROOF_REFERENCE__SOURCE.equals(msg.getFeature())
                    || DbcmodelPackage.Literals.DBC_PROOF_REFERENCE__TARGET.equals(msg.getFeature())
                    || DbcmodelPackage.Literals.DBC_PROOF__PROOF_REFERENCES.equals(msg.getFeature())
                    || DbcmodelPackage.Literals.IDB_CPROOF_REFERENCABLE__ALL_REFERENCES.equals(msg.getFeature())) {
                updateChildren(msg.getNotifier());
                if (msg.getNewValue() instanceof DbcProofReference) {
                    DbcProofReference reference = (DbcProofReference) msg.getNewValue();
                    updateChildren(reference.getSource());
                    updateChildren(reference.getTarget());
                }
                if (msg.getOldValue() instanceof DbcProofReference) {
                    DbcProofReference reference = (DbcProofReference) msg.getOldValue();
                    updateChildren(reference.getSource());
                    updateChildren(reference.getTarget());
                }
            }
        }

        /**
         * Updates the children of the given parent element in {@link #viewer}.
         * @param parentElement The parent element to update its children.
         */
        protected void updateChildren(final Object parentElement) {
            if (parentElement != null && viewer != null && !viewer.getControl().isDisposed()) {
                viewer.getControl().getDisplay().syncExec(new Runnable() {
                    @Override
                    public void run() {
                        if (viewer.getControl().isDisposed()) {
                            Object[] children = childMapping.remove(parentElement);
                            if (children != null) {
                                viewer.remove(parentElement, children);
                            }
                            viewer.add(parentElement, getChildren(parentElement));
                        }
                    }
                });
            }
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public Object[] getChildren(Object parentElement) {
            Object[] children = childMapping.get(parentElement);
            if (children == null) {
                if (parentElement == input) {
                    children = filteredInput.toArray(new Object[filteredInput.size()]);
                } else if (parentElement instanceof DbcProof) {
                    DbcProof proof = (DbcProof) parentElement;
                    observeObject(proof);
                    List<DbcProofReference> references = proof.getProofReferences();
                    List<Object> result = new LinkedList<Object>();
                    for (DbcProofReference reference : references) {
                        result.add(new ProofReferenceEntry(proof, reference, "outgoing", reference.getTarget()));
                    }
                    children = result.toArray(new Object[result.size()]);
                } else if (parentElement instanceof IDbCProofReferencable) {
                    IDbCProofReferencable referencable = (IDbCProofReferencable) parentElement;
                    observeObject(referencable);
                    List<DbcProofReference> references = referencable.getAllReferences();
                    List<Object> result = new LinkedList<Object>();
                    for (DbcProofReference reference : references) {
                        result.add(new ProofReferenceEntry(referencable, reference, "incoming",
                                reference.getSource()));
                    }
                    children = result.toArray(new Object[result.size()]);
                } else if (parentElement instanceof DbcProofReference) {
                    DbcProofReference reference = (DbcProofReference) parentElement;
                    observeObject(reference);
                    children = new Object[] {
                            new ProofReferenceEntry(reference, reference, "refers from", reference.getSource()),
                            new ProofReferenceEntry(reference, reference, "refers to", reference.getTarget()) };
                } else if (parentElement instanceof ProofReferenceEntry) {
                    children = getChildren(((ProofReferenceEntry) parentElement).getDirectionTarget());
                } else {
                    children = new Object[0];
                }
                childMapping.put(parentElement, children);
            }
            return children;
        }

        /**
         * Filters out the element from the given {@link Object} which
         * have nothing to do with proof references or the elements
         * which provides currently no proof references.
         * @param input The input.
         * @return The elements which have something to do with proof references.
         */
        protected Set<EObject> filterInput(Object input) {
            Set<EObject> filteredInput = new LinkedHashSet<EObject>();
            if (input instanceof List<?>) {
                List<?> inputList = (List<?>) input;
                for (Object element : inputList) {
                    if (element instanceof DbcProof) {
                        DbcProof proof = (DbcProof) element;
                        if (!proof.getProofReferences().isEmpty()) {
                            filteredInput.add(proof);
                        }
                    } else if (element instanceof IDbCProofReferencable) {
                        IDbCProofReferencable referencable = (IDbCProofReferencable) element;
                        if (!referencable.getAllReferences().isEmpty()) {
                            filteredInput.add(referencable);
                        }
                    } else if (element instanceof DbcProofReference) {
                        filteredInput.add((EObject) element);
                    }
                }
            }
            return filteredInput;
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public Object getParent(Object element) {
            return null;
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public boolean hasChildren(Object element) {
            return getChildren(element).length >= 1;
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public Object[] getElements(Object inputElement) {
            return getChildren(inputElement);
        }
    }

    /**
     * A utility class which is instantiated from {@link ProofReferenceTreeContentProvider}
     * to represent a tree row entry with a direction.
     * @author Martin Hentschel
     */
    public static class ProofReferenceEntry {
        /**
         * The parent {@link Object} in the tree.
         */
        private Object parent;

        /**
         * The {@link DbcProofReference} which is the reason for this entry.
         */
        private DbcProofReference reference;

        /**
         * The direction.
         */
        private String direction;

        /**
         * The target of the direction.
         */
        private EObject directionTarget;

        /**
         * Constructor.
         * @param parent The parent {@link Object} in the tree.
         * @param reference The {@link DbcProofReference} which is the reason for this entry.
         * @param direction The direction.
         * @param directionTarget The target of the direction.
         */
        public ProofReferenceEntry(Object parent, DbcProofReference reference, String direction,
                EObject directionTarget) {
            this.parent = parent;
            this.reference = reference;
            this.direction = direction;
            this.directionTarget = directionTarget;
        }

        /**
         * Returns the parent {@link Object} in the tree.
         * @return The parent {@link Object} in the tree.
         */
        public Object getParent() {
            return parent;
        }

        /**
         * Returns the {@link DbcProofReference} which is the reason for this entry.
         * @return The {@link DbcProofReference} which is the reason for this entry.
         */
        public DbcProofReference getReference() {
            return reference;
        }

        /**
         * Returns the direction.
         * @return The direction.
         */
        public String getDirection() {
            return direction;
        }

        /**
         * Returns the target of the direction.
         * @return The target of the direction.
         */
        public EObject getDirectionTarget() {
            return directionTarget;
        }
    }

    /**
     * The {@link ITableLabelProvider} used in the viewer of {@link ProofReferenceComposite}.
     * @author Martin Hentschel
     */
    public static class ProofReferenceLabelProvider extends LabelProvider implements ITableLabelProvider {
        /**
         * Factory which has created {@link #childLabelProvider}.
         */
        private ComposedAdapterFactory adapterFactory;

        /**
         * A child {@link ILabelProvider} which is used to compute column images
         * and to detect when something has changed.
         */
        private AdapterFactoryLabelProvider childLabelProvider;

        /**
         * Listens for changes on {@link #childLabelProvider}.
         */
        private ILabelProviderListener childLabelProviderListener = new ILabelProviderListener() {
            @Override
            public void labelProviderChanged(LabelProviderChangedEvent event) {
                handleChildLabelProviderChanged(event);
            }
        };

        /**
         * Observed {@link EObject}s.
         */
        private Set<EObject> observedObjects = new HashSet<EObject>();

        /**
         * Listener on each instance in {@link #observedObjects}.
         */
        private Adapter changeListener = new AdapterImpl() {
            @Override
            public void notifyChanged(Notification msg) {
                handleNotifyChanged(msg);
            }
        };

        /**
         * Constructor.
         */
        public ProofReferenceLabelProvider() {
            adapterFactory = new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE);
            adapterFactory.addAdapterFactory(new ResourceItemProviderAdapterFactory());
            adapterFactory.addAdapterFactory(new DbcmodelItemProviderAdapterFactory());
            adapterFactory.addAdapterFactory(new ReflectiveItemProviderAdapterFactory());
            childLabelProvider = new AdapterFactoryLabelProvider(adapterFactory);
            childLabelProvider.setFireLabelUpdateNotifications(true);
            childLabelProvider.addListener(childLabelProviderListener);
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public void dispose() {
            clearObservedObjects();
            childLabelProvider.removeListener(childLabelProviderListener);
            childLabelProvider.dispose();
            adapterFactory.dispose();
            super.dispose();
        }

        /**
         * Removes the change listener from all objects in {@link #observedObjects}
         * and clears the list.
         */
        protected void clearObservedObjects() {
            for (EObject obj : observedObjects) {
                obj.eAdapters().remove(changeListener);
            }
            observedObjects.clear();
        }

        /**
         * Adds the change listener {@link #changeListener} to the given {@link EObject}
         * and registers the {@link EObject} in {@link #observedObjects}.
         * @param obj The {@link EObject} to observe.
         */
        protected void observeObject(EObject obj) {
            if (observedObjects.add(obj)) {
                obj.eAdapters().add(changeListener);
            }
        }

        /**
         * When something has changed on an observed {@link EObject} in {@link #observedObjects}.
         * @param msg The event.
         */
        protected void handleNotifyChanged(Notification msg) {
            if (DbcmodelPackage.Literals.DBC_PROOF_REFERENCE__KIND.equals(msg.getFeature())) {
                fireLabelProviderChangedThreadSave(new LabelProviderChangedEvent(this));
            }
        }

        /**
         * When something has changed on {@link #childLabelProvider}.
         * @param event The event.
         */
        protected void handleChildLabelProviderChanged(LabelProviderChangedEvent event) {
            fireLabelProviderChangedThreadSave(new LabelProviderChangedEvent(this));
        }

        /**
         * Fires the event to all listeners thread save.
         * @param event The event to fire.
         */
        protected void fireLabelProviderChangedThreadSave(final LabelProviderChangedEvent event) {
            Display.getDefault().syncExec(new Runnable() {
                @Override
                public void run() {
                    fireLabelProviderChanged(event);
                }
            });
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public Image getColumnImage(Object element, int columnIndex) {
            if (element instanceof ProofReferenceEntry) {
                if (columnIndex == 0) {
                    element = ((ProofReferenceEntry) element).getParent();
                    return childLabelProvider.getImage(element);
                } else if (columnIndex == 3) {
                    element = ((ProofReferenceEntry) element).getDirectionTarget();
                    return childLabelProvider.getImage(element);
                } else {
                    return null;
                }
            } else {
                if (columnIndex == 0) {
                    return childLabelProvider.getImage(element);
                } else {
                    return null;
                }
            }
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public String getColumnText(Object element, int columnIndex) {
            return getColumnText(element, columnIndex, true);
        }

        /**
         * Returns the column text to show.
         * @param element The element.
         * @param columnIndex The column index.
         * @param rootElement Is root element? 
         * @return The column text to show.
         */
        protected String getColumnText(Object element, int columnIndex, boolean rootElement) {
            if (element instanceof DbcProof) {
                if (columnIndex == 0 || columnIndex == 3 && !rootElement) {
                    DbcProof proof = ((DbcProof) element);
                    IDbCProvable target = proof.getTarget();
                    return target != null ? proof.getObligation() + " of " + getColumnText(target, 0)
                            : proof.getObligation();
                } else {
                    return null;
                }
            } else if (element instanceof DbcProofReference) {
                if (columnIndex == 0) {
                    DbcProofReference reference = ((DbcProofReference) element);
                    observeObject(reference);
                    return reference.getKind();
                } else {
                    return null;
                }
            } else if (element instanceof IDbCProofReferencable) {
                if (columnIndex == 0 || columnIndex == 3 && !rootElement) {
                    if (element instanceof DbcAttribute) {
                        return ((DbcAttribute) element).getName();
                    } else if (element instanceof DbcAxiom) {
                        return ((DbcAxiom) element).getName();
                    } else if (element instanceof DbcEnumLiteral) {
                        return ((DbcEnumLiteral) element).getName();
                    } else if (element instanceof DbcInvariant) {
                        return ((DbcInvariant) element).getName();
                    } else if (element instanceof AbstractDbcOperation) {
                        return ((AbstractDbcOperation) element).getSignature();
                    } else if (element instanceof AbstractDbcType) {
                        return ((AbstractDbcType) element).getName();
                    } else if (element instanceof DbCAxiomContract) {
                        return ((DbCAxiomContract) element).getName();
                    } else if (element instanceof DbcOperationContract) {
                        return ((DbcOperationContract) element).getName();
                    } else {
                        return ObjectUtil.toString(element);
                    }
                } else {
                    return null;
                }
            } else if (element instanceof ProofReferenceEntry) {
                ProofReferenceEntry refEntry = (ProofReferenceEntry) element;
                if (columnIndex == 0) {
                    return getColumnText(refEntry.getParent(), columnIndex, false);
                } else if (columnIndex == 1) {
                    return refEntry.getDirection();
                } else if (columnIndex == 2) {
                    observeObject(refEntry.getReference());
                    return refEntry.getReference().getKind();
                } else if (columnIndex == 3) {
                    return getColumnText(refEntry.getDirectionTarget(), columnIndex, false);
                } else {
                    return null;
                }
            } else {
                return ObjectUtil.toString(element);
            }
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public Image getImage(Object element) {
            return getColumnImage(element, 0);
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public String getText(Object element) {
            return getColumnText(element, 0);
        }
    }
}