/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.plugin.ij.structure;
import com.google.common.collect.Sets;
import com.intellij.ide.structureView.StructureViewTreeElement;
import com.intellij.ide.structureView.TextEditorBasedStructureViewModel;
import com.intellij.ide.structureView.impl.java.FieldsFilter;
import com.intellij.ide.structureView.impl.java.JavaClassTreeElement;
import com.intellij.ide.structureView.impl.java.JavaInheritedMembersNodeProvider;
import com.intellij.ide.structureView.impl.java.KindSorter;
import com.intellij.ide.structureView.impl.java.PropertiesGrouper;
import com.intellij.ide.structureView.impl.java.PublicElementsFilter;
import com.intellij.ide.structureView.impl.java.SuperTypesGrouper;
import com.intellij.ide.structureView.impl.java.VisibilitySorter;
import com.intellij.ide.util.treeView.smartTree.Filter;
import com.intellij.ide.util.treeView.smartTree.Grouper;
import com.intellij.ide.util.treeView.smartTree.NodeProvider;
import com.intellij.ide.util.treeView.smartTree.Sorter;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import gw.plugin.ij.lang.psi.IGosuFileBase;
import gw.plugin.ij.lang.psi.api.statements.IGosuVariable;
import gw.plugin.ij.lang.psi.api.statements.typedef.IGosuMethod;
import gw.plugin.ij.lang.psi.api.statements.typedef.IGosuTypeDefinition;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Collection;
public class GosuStructureViewModel extends TextEditorBasedStructureViewModel {
@NotNull
private final IGosuFileBase rootElement;
private static final Collection<NodeProvider> NODE_PROVIDERS = Arrays.<NodeProvider>asList(new JavaInheritedMembersNodeProvider());
private static final Class[] SUITABLE_CLASSES = new Class[]{
IGosuFileBase.class,
IGosuTypeDefinition.class,
IGosuMethod.class,
IGosuVariable.class};
public GosuStructureViewModel(@NotNull IGosuFileBase rootElement) {
super(rootElement);
this.rootElement = rootElement;
}
@Override
public Collection<NodeProvider> getNodeProviders() {
return NODE_PROVIDERS;
}
@NotNull
protected PsiFile getPsiFile() {
return rootElement;
}
@NotNull
public StructureViewTreeElement getRoot() {
PsiClass psiClass = rootElement.getPsiClass();
if(psiClass == null) {
psiClass = new FakePsiClass();
}
return new JavaClassTreeElement(psiClass, false, Sets.<PsiClass>newHashSet());
}
@NotNull
public Filter[] getFilters() {
return new Filter[]{new FieldsFilter(),
new PublicElementsFilter()};
}
@NotNull
public Grouper[] getGroupers() {
return new Grouper[]{new SuperTypesGrouper(),
new PropertiesGrouper()};
}
@Override
public boolean shouldEnterElement(Object element) {
return element instanceof IGosuTypeDefinition;
}
@NotNull
public Sorter[] getSorters() {
return new Sorter[]{KindSorter.INSTANCE,
VisibilitySorter.INSTANCE,
Sorter.ALPHA_SORTER};
}
@NotNull
protected Class[] getSuitableClasses() {
return SUITABLE_CLASSES;
}
@Nullable
protected Object findAcceptableElement(@Nullable PsiElement element) {
while (element != null && !(element instanceof PsiDirectory)) {
if (isSuitable(element)) {
if (element instanceof IGosuFileBase) {
return ((IGosuFileBase) element).getPsiClass();
}
return element;
}
element = element.getParent();
}
return null;
}
@Override
protected boolean isSuitable(@NotNull final PsiElement element) {
if (super.isSuitable(element)) {
if (element instanceof IGosuMethod) {
IGosuMethod method = (IGosuMethod) element;
PsiElement parent = method.getParent().getParent();
if (parent instanceof IGosuTypeDefinition) {
return ((IGosuTypeDefinition) parent).getQualifiedName() != null;
}
} else if (element instanceof IGosuVariable) {
IGosuVariable field = (IGosuVariable) element;
PsiElement parent = field.getParent().getParent().getParent();
if (parent instanceof IGosuTypeDefinition) {
return ((IGosuTypeDefinition) parent).getQualifiedName() != null;
}
} else if (element instanceof IGosuTypeDefinition) {
return ((IGosuTypeDefinition) element).getQualifiedName() != null;
} else if (element instanceof IGosuFileBase) {
return true;
}
}
return false;
}
}