/*******************************************************************************
* Copyright (c) 2007 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.seam.ui.search;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.search.internal.ui.text.IFileSearchContentProvider;
import org.eclipse.search.ui.text.AbstractTextSearchResult;
import org.jboss.tools.seam.core.IRole;
import org.jboss.tools.seam.core.ISeamComponent;
import org.jboss.tools.seam.core.ISeamElement;
import org.jboss.tools.seam.core.ISeamProject;
/**
* Seam tree content provider used in seam search page
*
* @author Jeremy
*
*/
public class SeamTreeContentProvider implements ITreeContentProvider, IFileSearchContentProvider {
private final Object[] EMPTY_ARR= new Object[0];
private AbstractTextSearchResult fResult;
private SeamSearchResultPage fPage;
private AbstractTreeViewer fTreeViewer;
private Map fChildrenMap;
/**
* Constructs SeamTreeContentProvider object
*
* @param page
*/
SeamTreeContentProvider(SeamSearchResultPage page, AbstractTreeViewer viewer) {
fPage= page;
fTreeViewer= viewer;
}
/**
* (non-Javadoc)
* @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
*/
public Object[] getElements(Object inputElement) {
Object[] children= getChildren(inputElement);
int elementLimit= getElementLimit();
if (elementLimit != -1 && elementLimit < children.length) {
Object[] limitedChildren= new Object[elementLimit];
System.arraycopy(children, 0, limitedChildren, 0, elementLimit);
return limitedChildren;
}
return children;
}
private int getElementLimit() {
return fPage.getElementLimit().intValue();
}
/**
* (non-Javadoc)
* @see org.eclipse.jface.viewers.IContentProvider#dispose()
*/
public void dispose() {
// nothing to do
}
/**
* (non-Javadoc)
* @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
*/
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
if (newInput instanceof AbstractTextSearchResult) {
initialize((AbstractTextSearchResult) newInput);
}
}
private synchronized void initialize(AbstractTextSearchResult result) {
fResult= result;
fChildrenMap= new HashMap();
if (result != null) {
Object[] elements= result.getElements();
for (int i= 0; i < elements.length; i++) {
insert(elements[i], false);
}
}
}
private void insert(Object child, boolean refreshViewer) {
Object parent= getParent(child);
while (parent != null) {
if (insertChild(parent, child)) {
if (refreshViewer)
fTreeViewer.add(parent, child);
} else {
if (refreshViewer)
fTreeViewer.refresh(parent);
return;
}
child= parent;
parent= getParent(child);
}
if (insertChild(fResult, child)) {
if (refreshViewer)
fTreeViewer.add(fResult, child);
}
}
/**
* returns true if the child already was a child of parent.
*
* @param parent
* @param child
* @return Returns <code>trye</code> if the child was added
*/
private boolean insertChild(Object parent, Object child) {
Set children= (Set) fChildrenMap.get(parent);
if (children == null) {
children= new HashSet();
fChildrenMap.put(parent, children);
}
return children.add(child);
}
private void remove(Object element, boolean refreshViewer) {
// precondition here: fResult.getMatchCount(child) <= 0
if (hasChildren(element)) {
if (refreshViewer)
fTreeViewer.refresh(element);
} else {
if (fResult.getMatchCount(element) == 0) {
fChildrenMap.remove(element);
Object parent= getParent(element);
if (parent != null) {
removeFromSiblings(element, parent);
remove(parent, refreshViewer);
} else {
removeFromSiblings(element, fResult);
if (refreshViewer)
fTreeViewer.refresh();
}
} else {
if (refreshViewer) {
fTreeViewer.refresh(element);
}
}
}
}
private void removeFromSiblings(Object element, Object parent) {
Set siblings= (Set) fChildrenMap.get(parent);
if (siblings != null) {
siblings.remove(element);
}
}
/**
* (non-Javadoc)
* @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
*/
public Object[] getChildren(Object parentElement) {
Set children= (Set) fChildrenMap.get(parentElement);
if (children == null)
return EMPTY_ARR;
return children.toArray();
}
/**
* (non-Javadoc)
* @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object)
*/
public boolean hasChildren(Object element) {
return getChildren(element).length > 0;
}
/**
* (non-Javadoc)
* @see org.eclipse.search.internal.ui.text.IFileSearchContentProvider#elementsChanged(java.lang.Object[])
*/
public synchronized void elementsChanged(Object[] updatedElements) {
for (int i= 0; i < updatedElements.length; i++) {
if (fResult.getMatchCount(updatedElements[i]) > 0)
insert(updatedElements[i], true);
else
remove(updatedElements[i], true);
}
}
/**
* (non-Javadoc)
* @see org.eclipse.search.internal.ui.text.IFileSearchContentProvider#clear()
*/
public void clear() {
initialize(fResult);
fTreeViewer.refresh();
}
/**
* (non-Javadoc)
* @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)
*/
public Object getParent(Object element) {
if (element instanceof IProject || element instanceof IJavaProject || element instanceof ISeamProject)
return null;
if (element instanceof IResource) {
IResource resource = (IResource) element;
return resource.getParent();
}
if(element instanceof IRole) {
ISeamElement p = ((IRole)element).getParent();
return p == null ? p : p.getParent();
}
if(element instanceof ISeamElement) {
if(element instanceof ISeamComponent) {
ISeamComponent c = (ISeamComponent)element;
return c.getSeamProject().getPackage(c);
}
return ((ISeamElement)element).getParent();
}
if (element instanceof IJavaElement) {
return ((IJavaElement)element).getParent();
}
return null;
}
}