org.eclipse.ui.views.markers.internal.MarkerAdapter.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.ui.views.markers.internal.MarkerAdapter.java

Source

/*******************************************************************************
 * Copyright (c) 2000, 2008 IBM Corporation and others.
 * 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.ui.views.markers.internal;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.osgi.util.NLS;
import org.eclipse.ui.internal.ide.Policy;

/**
 * The MarkerAdapter is the adapter for the deferred update of markers.
 * 
 * @since 3.1
 * 
 */
public class MarkerAdapter {

    class MarkerCategory extends MarkerNode {

        MarkerAdapter markerAdapter;

        int start;

        int end;

        private ConcreteMarker[] children;

        private String name;

        /**
         * Create a new instance of the receiver that has the markers between
         * startIndex and endIndex showing.
         * 
         * @param adapter
         * @param startIndex
         * @param endIndex
         */
        MarkerCategory(MarkerAdapter adapter, int startIndex, int endIndex, String categoryName) {
            markerAdapter = adapter;
            start = startIndex;
            end = endIndex;
            name = categoryName;
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.ui.views.markers.internal.MarkerNode#getChildren()
         */
        public MarkerNode[] getChildren() {

            if (children == null) {

                // Return nothing while a build is going on as this could be
                // stale
                if (building) {
                    return Util.EMPTY_MARKER_ARRAY;
                }

                ConcreteMarker[] allMarkers = markerAdapter.lastMarkers.toArray();

                int totalSize = getDisplayedSize();
                children = new ConcreteMarker[totalSize];

                System.arraycopy(allMarkers, start, children, 0, totalSize);
                // Sort them locally now
                view.getTableSorter().sort(view.getViewer(), children);

                for (int i = 0; i < children.length; i++) {
                    children[i].setCategory(this);
                }
            }
            return children;

        }

        /**
         * Return the number of errors being displayed.
         * 
         * @return int
         */
        int getDisplayedSize() {
            if (view.getMarkerLimit() > 0) {
                return Math.min(getTotalSize(), view.getMarkerLimit());
            }
            return getTotalSize();
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.ui.views.markers.internal.MarkerNode#getParent()
         */
        public MarkerNode getParent() {
            return null;
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.ui.views.markers.internal.MarkerNode#getDescription()
         */
        public String getDescription() {

            int size = end - start + 1;

            if (size <= view.getMarkerLimit()) {

                if (size == 1)
                    return NLS.bind(MarkerMessages.Category_One_Item_Label, new Object[] { name });

                return NLS.bind(MarkerMessages.Category_Label,
                        new Object[] { name, String.valueOf(getDisplayedSize()) });
            }
            return NLS.bind(MarkerMessages.Category_Limit_Label,
                    new Object[] { name, String.valueOf(getDisplayedSize()), String.valueOf(getTotalSize()) });
        }

        /**
         * Get the total size of the receiver.
         * 
         * @return int
         */
        private int getTotalSize() {
            return end - start + 1;
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.ui.views.markers.internal.MarkerNode#isConcrete()
         */
        public boolean isConcrete() {
            return false;
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.eclipse.ui.views.markers.internal.MarkerNode#getConcreteRepresentative()
         */
        public ConcreteMarker getConcreteRepresentative() {
            return markerAdapter.lastMarkers.getMarker(start);
        }

        /**
         * Return the name of the receiver.
         * 
         * @return String
         */
        public String getName() {
            return name;
        }
    }

    MarkerView view;

    private MarkerList lastMarkers;

    private MarkerCategory[] categories;

    private boolean building = true;// Start with nothing until we have

    // something

    /**
     * Create a new instance of the receiver.
     * 
     * @param markerView
     */
    MarkerAdapter(MarkerView markerView) {
        view = markerView;
    }

    /**
     * Return the category sorter for the receiver. This should only be called
     * in hierarchal mode or there will be a ClassCastException.
     * 
     * @return CategorySorter
     */
    public CategoryComparator getCategorySorter() {
        return (CategoryComparator) view.getViewer().getComparator();
    }

    /**
     * Build all of the markers in the receiver.
     * 
     * @param collector
     * @param monitor
     */
    public void buildAllMarkers(IProgressMonitor monitor) {
        building = true;
        MarkerList newMarkers;
        try {
            int markerLimit = view.getMarkerLimit();
            monitor.beginTask(MarkerMessages.MarkerView_19, markerLimit == -1 ? 60 : 100);
            try {
                monitor.subTask(MarkerMessages.MarkerView_waiting_on_changes);

                if (monitor.isCanceled())
                    return;

                monitor.subTask(MarkerMessages.MarkerView_searching_for_markers);
                SubProgressMonitor subMonitor = new SubProgressMonitor(monitor, 10);
                MarkerFilter[] filters = view.getEnabledFilters();
                if (filters.length > 0)
                    newMarkers = MarkerList.compute(filters, subMonitor, true);
                else
                    // Grab any filter as a disabled filter gives all of them
                    newMarkers = MarkerList.compute(new MarkerFilter[] { view.getAllFilters()[0] }, subMonitor,
                            true);

                if (monitor.isCanceled())
                    return;

                view.refreshMarkerCounts(monitor);

            } catch (CoreException e) {
                Policy.handle(e);
                newMarkers = new MarkerList();
                return;
            }

            if (monitor.isCanceled())
                return;

            ViewerComparator sorter = view.getViewer().getComparator();

            if (markerLimit == -1 || isShowingHierarchy()) {
                sorter.sort(view.getViewer(), newMarkers.toArray());
            } else {

                monitor.subTask(MarkerMessages.MarkerView_18);
                SubProgressMonitor mon = new SubProgressMonitor(monitor, 40);

                newMarkers = SortUtil.getFirst(newMarkers, (Comparator) sorter, markerLimit, mon);
                if (monitor.isCanceled())
                    return;

                sorter.sort(view.getViewer(), newMarkers.toArray());
            }

            if (newMarkers.getSize() == 0) {
                categories = new MarkerCategory[0];
                lastMarkers = newMarkers;
                monitor.done();
                return;
            }

            monitor.subTask(MarkerMessages.MarkerView_queueing_updates);

            if (monitor.isCanceled())
                return;

            if (isShowingHierarchy()) {
                MarkerCategory[] newCategories = buildHierarchy(newMarkers, 0, newMarkers.getSize() - 1, 0);
                if (monitor.isCanceled())
                    return;
                categories = newCategories;
            }

            lastMarkers = newMarkers;
            monitor.done();
        } finally {
            building = false;
        }

    }

    /**
     * Return whether or not a hierarchy is showing.
     * 
     * @return boolean
     */
    boolean isShowingHierarchy() {

        ViewerComparator sorter = view.getViewer().getComparator();
        if (sorter instanceof CategoryComparator) {
            return ((CategoryComparator) sorter).getCategoryField() != null;
        }
        return false;
    }

    /**
     * Break the marker up into categories
     * 
     * @param markers
     * @param start
     *            the start index in the markers
     * @param end
     *            the last index to check
     * @param sortIndex -
     *            the parent of the field
     * @param parent
     * @return MarkerCategory[] or <code>null</code> if we are at the bottom
     *         of the tree
     */
    MarkerCategory[] buildHierarchy(MarkerList markers, int start, int end, int sortIndex) {
        CategoryComparator sorter = getCategorySorter();

        if (sortIndex > 0) {
            return null;// Are we out of categories?
        }

        Collection categories = new ArrayList();

        Object previous = null;
        int categoryStart = start;

        Object[] elements = markers.getArray();

        for (int i = start; i <= end; i++) {

            if (previous != null) {
                // Are we at a category boundary?
                if (sorter.compare(previous, elements[i], sortIndex, false) != 0) {
                    categories.add(new MarkerCategory(this, categoryStart, i - 1,
                            getNameForIndex(markers, categoryStart)));
                    categoryStart = i;
                }
            }
            previous = elements[i];

        }

        if (end >= categoryStart) {
            categories.add(new MarkerCategory(this, categoryStart, end, getNameForIndex(markers, categoryStart)));
        }

        // Flatten single categories
        // if (categories.size() == 1) {
        // return buildHierarchy(markers, start, end, sortIndex + 1, parent);
        // }
        MarkerCategory[] nodes = new MarkerCategory[categories.size()];
        categories.toArray(nodes);
        return nodes;

    }

    /**
     * Get the name for the category from the marker at categoryStart in
     * markers.
     * 
     * @param markers
     * @param categoryStart
     * @return String
     */
    private String getNameForIndex(MarkerList markers, int categoryStart) {
        return getCategorySorter().getCategoryField().getValue(markers.toArray()[categoryStart]);
    }

    /**
     * Return the current list of markers.
     * 
     * @return MarkerList
     */
    public MarkerList getCurrentMarkers() {
        if (lastMarkers == null) {// First time?
            view.scheduleMarkerUpdate(Util.SHORT_DELAY);
            building = true;
        }
        if (building) {
            return new MarkerList();
        }
        return lastMarkers;
    }

    /**
     * Return the elements in the adapter.
     * 
     * @param root
     * @return Object[]
     */
    public Object[] getElements() {

        if (lastMarkers == null) {// First time?
            view.scheduleMarkerUpdate(Util.SHORT_DELAY);
            building = true;
        }
        if (building) {
            return Util.EMPTY_MARKER_ARRAY;
        }
        if (isShowingHierarchy() && categories != null) {
            return categories;
        }
        return lastMarkers.toArray();
    }

    /**
     * Return whether or not the receiver has markers without scheduling
     * anything if it doesn't.
     * 
     * @return boolean <code>true</code> if the markers have not been
     *         calculated.
     */
    public boolean hasNoMarkers() {
        return lastMarkers == null;
    }

    /**
     * Return the categories for the receiver.
     * 
     * @return MarkerCategory[] or <code>null</code> if there are no
     *         categories.
     */
    public MarkerCategory[] getCategories() {
        if (building) {
            return null;
        }
        return categories;
    }

    /**
     * Return whether or not the receiver is building.
     * @return boolean
     */
    boolean isBuilding() {
        return building;
    }

}