package org.archstudio.archlight.core;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.archstudio.archlight.ArchlightDocTest;
import org.archstudio.archlight.ArchlightTest;
import org.archstudio.eclipse.ui.views.AbstractArchStudioOutlinePage;
import org.archstudio.resources.IResources;
import org.archstudio.testadt.IArchlightTestADT;
import org.archstudio.xarchadt.IXArchADT;
import org.archstudio.xarchadt.ObjRef;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchSite;
public class ArchlightOutlinePage extends AbstractArchStudioOutlinePage {
protected IArchlightTestADT testadt = null;
protected List<? extends ArchlightTest> tests = null;
protected List<? extends ArchlightDocTest> doctests = null;
public ArchlightOutlinePage(IArchlightTestADT testadt, IXArchADT xarch, ObjRef xArchRef, IResources resources) {
super(xarch, xArchRef, resources, false, true);
this.testadt = testadt;
updateTests();
updateDocTests();
}
@Override
public void createControl(Composite parent) {
super.createControl(parent);
getTreeViewer().expandToLevel(4);
}
@Override
protected ITreeContentProvider createViewContentProvider() {
return new ViewContentProvider();
}
@Override
protected ILabelProvider createViewLabelProvider() {
return new ViewLabelProvider();
}
public void updateTests() {
tests = testadt.getAllTests();
}
public void updateDocTests() {
doctests = ArchlightUtils.loadDocTests(xarch, documentRootRef);
}
@Override
public void updateOutlinePage() {
updateTests();
updateDocTests();
super.updateOutlinePage();
}
protected int getTestState(ArchlightTest test) {
String uid = test.getUID();
for (ArchlightDocTest doctest : doctests) {
if (doctest.getTestUID().equals(uid)) {
if (doctest.isEnabled()) {
return ArchlightUtils.APPLIED;
}
else {
return ArchlightUtils.DISABLED;
}
}
}
return ArchlightUtils.NOT_APPLIED;
}
/*
* We do an interesting thing here; namely that the tree itself is fake and not structured like a tree. Instead, we
* just have the list of current tests. The view content provider iterates through those and responds to getChildren
* based on the contents of that list. Intermediate FolderNodes are created as necessary as placeholders.
*/
class ViewContentProvider implements ITreeContentProvider {
private Object[] EMPTY_ARRAY = new Object[0];
@Override
public Object[] getElements(Object inputElement) {
return getChildren(inputElement);
}
@Override
public Object[] getChildren(Object parentElement) {
if (parentElement instanceof IWorkbenchSite) {
ObjRef xADLRef = (ObjRef) xarch.get(documentRootRef, "xADL");
return new Object[] { xADLRef };
}
else if (parentElement instanceof ObjRef || parentElement instanceof FolderNode) {
//Figure out where we are
String[] currentLocation = null;
if (parentElement instanceof ObjRef) {
currentLocation = new String[0];
}
else if (parentElement instanceof FolderNode) {
currentLocation = ((FolderNode) parentElement).getPathSegments();
}
else {
throw new RuntimeException("Unknown node in tree: " + parentElement);
}
//Find all the children of where we are
List<Object> children = new ArrayList<Object>();
List<? extends ArchlightTest> ts = tests;
for (ArchlightTest test : ts) {
String[] testLocation = ArchlightTest.getCategoryPathComponents(test.getCategory());
if (testLocation.length <= currentLocation.length) {
continue;
}
boolean matches = true;
for (int j = 0; j < currentLocation.length; j++) {
if (!currentLocation[j].equals(testLocation[j])) {
matches = false;
break;
}
}
if (matches) {
//Okay, this is at least a descendant of our current location
if (testLocation.length == currentLocation.length + 1) {
//It's a direct child
children.add(test);
}
else {
//It's a descendant and we need to put in a foldernode
String[] folderNodeLocation = new String[currentLocation.length + 1];
System.arraycopy(currentLocation, 0, folderNodeLocation, 0, currentLocation.length);
folderNodeLocation[currentLocation.length] = testLocation[currentLocation.length];
FolderNode fn = new FolderNode(folderNodeLocation);
if (!children.contains(fn)) {
children.add(fn);
}
}
}
}
//Sort the list of children
Collections.sort(children, new Comparator<Object>() {
@Override
public int compare(Object o1, Object o2) {
if (o1 instanceof FolderNode && o2 instanceof ArchlightTest) {
return -1; //folders always before tests
}
else if (o1 instanceof ArchlightTest && o2 instanceof FolderNode) {
return 1; //Tests always after folders
}
else if (o1 instanceof FolderNode && o2 instanceof FolderNode) {
return ((FolderNode) o1).getLastSegment().compareToIgnoreCase(
((FolderNode) o2).getLastSegment());
}
else if (o1 instanceof ArchlightTest && o2 instanceof ArchlightTest) {
return ArchlightTest.getLastCategoryPathComponent(((ArchlightTest) o1).getCategory())
.compareTo(
ArchlightTest.getLastCategoryPathComponent(((ArchlightTest) o2)
.getCategory()));
}
return 0;
};
});
return children.toArray();
}
return EMPTY_ARRAY;
}
@Override
public Object getParent(Object element) {
return null;
}
@Override
public boolean hasChildren(Object element) {
if (element instanceof IWorkbenchSite) {
return true;
}
else if (element instanceof ObjRef) {
return true;
}
else if (element instanceof FolderNode) {
return true;
}
else if (element instanceof ArchlightTest) {
return false;
}
return false;
}
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
@Override
public void dispose() {
}
}
class ViewLabelProvider extends LabelProvider implements ILabelProvider {
@Override
public Image getImage(Object element) {
if (element instanceof ObjRef) {
return resources.getPlatformImage(ISharedImages.IMG_OBJ_FOLDER);
}
else if (element instanceof FolderNode) {
return resources.getPlatformImage(ISharedImages.IMG_OBJ_FOLDER);
}
else if (element instanceof ArchlightTest) {
switch (getTestState((ArchlightTest) element)) {
case ArchlightUtils.APPLIED:
return resources.getImage(ArchlightUtils.IMAGE_TEST_APPLIED);
case ArchlightUtils.DISABLED:
return resources.getImage(ArchlightUtils.IMAGE_TEST_DISABLED);
case ArchlightUtils.NOT_APPLIED:
return resources.getImage(ArchlightUtils.IMAGE_TEST_NOTAPPLIED);
}
return resources.getPlatformImage(ISharedImages.IMG_OBJ_FILE);
}
return null;
}
@Override
public String getText(Object element) {
if (element instanceof ObjRef) {
String uri = xarch.getURI(xarch.getDocumentRootRef((ObjRef) element)).toString();
if (uri == null) {
return "Document";
}
else {
return uri;
}
}
else if (element instanceof FolderNode) {
return ((FolderNode) element).getLastSegment();
}
else if (element instanceof ArchlightTest) {
return ArchlightTest.getLastCategoryPathComponent(((ArchlightTest) element).getCategory());
}
return super.getText(element);
}
}
public Object[] getSelectedNodes() {
ISelection selection = getSelection();
if (selection instanceof IStructuredSelection) {
IStructuredSelection ss = (IStructuredSelection) selection;
Object[] nodes = ss.toArray();
return nodes;
}
else {
return new Object[0];
}
}
@Override
protected void fillContextMenu(IMenuManager menuMgr) {
Object[] selectedNodes = getSelectedNodes();
if (selectedNodes.length == 0) {
Action noAction = new Action("[No Selection]") {
@Override
public void run() {
}
};
noAction.setEnabled(false);
menuMgr.add(noAction);
}
else if (selectedNodes.length > 1) {
Action noAction = new Action("[Select One Node for Menu]") {
@Override
public void run() {
}
};
noAction.setEnabled(false);
menuMgr.add(noAction);
}
else {
Object node = selectedNodes[0];
List<? extends IAction> actions = ArchlightUtils.createTestMenuActions(xarch, documentRootRef, tests,
resources, node);
if (actions.isEmpty()) {
Action noAction = new Action("[No Actions]") {
@Override
public void run() {
}
};
noAction.setEnabled(false);
menuMgr.add(noAction);
}
for (IAction action : actions) {
menuMgr.add(action);
}
}
menuMgr.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
}
@Override
public void focusEditor(ObjRef[] refs) {
}
}