com.archimatetool.editor.views.tree.TreeModelViewerFindReplaceProvider.java Source code

Java tutorial

Introduction

Here is the source code for com.archimatetool.editor.views.tree.TreeModelViewerFindReplaceProvider.java

Source

/**
 * This program and the accompanying materials
 * are made available under the terms of the License
 * which accompanies this distribution in the file LICENSE.txt
 */
package com.archimatetool.editor.views.tree;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;

import com.archimatetool.editor.ui.findreplace.AbstractFindReplaceProvider;
import com.archimatetool.editor.utils.StringUtils;
import com.archimatetool.editor.views.tree.commands.RenameCommandHandler;
import com.archimatetool.model.IArchimateModel;
import com.archimatetool.model.IArchimateModelObject;
import com.archimatetool.model.IArchimateRelationship;
import com.archimatetool.model.IFolder;
import com.archimatetool.model.INameable;

/**
 * Find/Replace Provider for Model Tree Viewer
 * 
 * @author Phillip Beauvoir
 */
public class TreeModelViewerFindReplaceProvider extends AbstractFindReplaceProvider {

    private TreeModelViewer fTreeModelViewer;

    /**
     * If this is true then when user has selected items in the tree and chooses "Replace", these elements
     * are the ones for the replace operation (if they match the criteria).
     * If this is false then the classic "Replace" behaviour is used selecting the next/previous match and then replacing that one.
     */
    boolean replaceSelection = false;

    public TreeModelViewerFindReplaceProvider(TreeModelViewer viewer) {
        fTreeModelViewer = viewer;
    }

    public boolean find(String toFind) {
        // Find All
        if (isAll()) {
            List<INameable> elements = getAllMatchingElements(toFind);
            fTreeModelViewer.setSelection(new StructuredSelection(elements), true);
            return !elements.isEmpty();
        }
        // Find Next/Previous
        else {
            INameable element = findNextElement(getFirstSelectedObject(), toFind);
            if (element != null) {
                fTreeModelViewer.setSelection(new StructuredSelection(element), true);
            }
            return (element != null);
        }
    }

    public boolean replace(String toFind, String toReplaceWith) {
        // Replace All
        if (isAll()) {
            List<INameable> elements = getAllMatchingElements(toFind);
            if (!elements.isEmpty()) {
                List<String> newNames = new ArrayList<String>();

                for (INameable nameable : elements) {
                    String newName = getNewName(nameable.getName(), toFind, toReplaceWith);
                    newNames.add(newName);
                }

                RenameCommandHandler.doRenameCommands(elements, newNames);
                fTreeModelViewer.setSelection(new StructuredSelection(elements), true);
            }
            return !elements.isEmpty();
        }
        // Replace Next/Previous
        else {
            // Replace on selected elements
            if (replaceSelection) {
                List<Object> selected = getSelectedObjects();
                if (!selected.isEmpty()) {
                    List<INameable> elements = new ArrayList<INameable>();
                    List<String> newNames = new ArrayList<String>();

                    for (Object object : selected) {
                        if (matches(object, toFind)) {
                            INameable nameable = (INameable) object;
                            elements.add(nameable);

                            String newName = getNewName(nameable.getName(), toFind, toReplaceWith);
                            newNames.add(newName);
                        }
                    }

                    if (!elements.isEmpty()) {
                        RenameCommandHandler.doRenameCommands(elements, newNames);
                        return true;
                    }
                }
            }
            // Replace on next single selection
            else {
                Object object = getFirstSelectedObject();
                if (matches(object, toFind)) {
                    RenameCommandHandler.doRenameCommand((INameable) object,
                            getNewName(((INameable) object).getName(), toFind, toReplaceWith));
                    return true;
                }
            }

            // Else move forward
            return find(toFind);
        }
    }

    /**
     * Find the next/previous element in the tree that matches the find criteria
     * @param startElement The element to start the search from for next/previous
     * @param toFind The string to find
     * @return The next/previous element if found, or null
     */
    INameable findNextElement(Object startElement, String toFind) {
        // Get *all* elements in the viewer
        List<INameable> elements = getAllNameableElements();

        if (elements.isEmpty()) {
            return null;
        }

        // Increment for forward/backward
        int increment = isForward() ? 1 : -1;

        // Starting index (defaults for a null startElement)
        int startIndex = isForward() ? 0 : elements.size() - 1;

        // Find starting point from startElement, if we have one
        if (startElement != null) {
            startIndex = elements.indexOf(startElement) + increment;
        }

        // Iterate through all elements forwards or backwards until we find the next matching element
        for (int i = startIndex; isForward() ? (i < elements.size()) : (i >= 0); i += increment) {
            Object element = elements.get(i);
            if (matches(element, toFind)) {
                return (INameable) element;
            }
        }

        return null;
    }

    /**
     * @param toFind The string to find a match on. If this is null, then collect all elements in the tree viewer.
     * @return All elements in the TreeViewer that match the string, in sorted and filtered order
     *          If a model is in scope use that as the starting/end point
     */
    List<INameable> getAllMatchingElements(String toFind) {
        if (isAllModels()) {
            return getMatchingElements(fTreeModelViewer.getInput(), toFind);
        } else {
            return getMatchingElements(getModelInScope(), toFind);
        }
    }

    /**
     * @param element The element to start searching from.
     * @param toFind The string to find a match on. If this is null, then collect all elements in the tree viewer.
     * @return A list of all matching elements in the viewer model as sorted and filtered by the TreeViewer model
     */
    private List<INameable> getMatchingElements(Object element, String toFind) {
        List<INameable> list = new ArrayList<INameable>();

        if (element != null) {
            if (toFind == null && element instanceof INameable) { // collect all
                list.add((INameable) element);
            } else if (matches(element, toFind)) { // collect on match
                list.add((INameable) element);
            }

            for (Object object : fTreeModelViewer.getSortedChildren(element)) {
                list.addAll(getMatchingElements(object, toFind));
            }
        }

        return list;
    }

    /**
     * @return *all* elements in the TreeViewer of type INameable, in sorted and filtered order
     */
    private List<INameable> getAllNameableElements() {
        return getAllMatchingElements(null);
    }

    /**
     * @return True if object is a matching type and toFind is found in the object's name
     */
    private boolean matches(Object object, String toFind) {
        if (object instanceof IFolder && !isIncludeFolders()) { // folders not included
            return false;
        }

        if (object instanceof IArchimateRelationship && !isIncludeRelations()) { // relations not included
            return false;
        }

        return (object instanceof INameable) && RenameCommandHandler.canRename(object) && StringUtils.isSet(toFind)
                && ((INameable) object).getName() != null
                && ((INameable) object).getName().matches(getSearchStringPattern(toFind));
    }

    /**
     * @return The first selected object in the tree, or null
     */
    private Object getFirstSelectedObject() {
        IStructuredSelection selection = (IStructuredSelection) fTreeModelViewer.getSelection();
        return selection.getFirstElement();
    }

    @SuppressWarnings("unchecked")
    private List<Object> getSelectedObjects() {
        IStructuredSelection selection = (IStructuredSelection) fTreeModelViewer.getSelection();
        return selection.toList();
    }

    /**
     * @return The model in scope of the selected element
     */
    private IArchimateModel getModelInScope() {
        IStructuredSelection selection = (IStructuredSelection) fTreeModelViewer.getSelection();
        Object o = selection.getFirstElement();
        if (o instanceof IArchimateModelObject) {
            return ((IArchimateModelObject) o).getArchimateModel();
        }

        return null;
    }
}