package org.archstudio.archedit.core;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.xml.xpath.XPathException;
import org.archstudio.eclipse.ui.views.AbstractArchStudioOutlinePage;
import org.archstudio.resources.IResources;
import org.archstudio.resources.ResourceCache;
import org.archstudio.swtutils.SWTWidgetUtils;
import org.archstudio.sysutils.SystemUtils;
import org.archstudio.sysutils.UIDGenerator;
import org.archstudio.xadl.XadlUtils;
import org.archstudio.xadl.bna.utils.XArchADTOperations;
import org.archstudio.xadl3.xadlcore_3_0.Xadlcore_3_0Package;
import org.archstudio.xarchadt.IXArchADT;
import org.archstudio.xarchadt.IXArchADTFeature;
import org.archstudio.xarchadt.IXArchADTFeature.FeatureType;
import org.archstudio.xarchadt.IXArchADTPackageMetadata;
import org.archstudio.xarchadt.IXArchADTSubstitutionHint;
import org.archstudio.xarchadt.IXArchADTTypeMetadata;
import org.archstudio.xarchadt.ObjRef;
import org.archstudio.xarchadt.variability.IXArchADTVariability;
import org.archstudio.xarchadt.variability.IXArchADTVariability.ChangeStatus;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.DropTargetListener;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchSite;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
public class ArchEditOutlinePage extends AbstractArchStudioOutlinePage {
protected boolean showIDs = false;
protected boolean showDescriptions = true;
protected boolean showObjRefs = false;
protected static int nextId = 100;
public ArchEditOutlinePage(IXArchADT xarch, ObjRef xArchRef, IResources resources) {
super(xarch, xArchRef, resources, true, true);
}
@Override
public void createControl(Composite parent) {
super.createControl(parent);
if (documentRootRef == null) {
return;
}
setupDoubleClick();
setupDragAndDrop();
}
@Override
protected ITreeContentProvider createViewContentProvider() {
return new ViewContentProvider();
}
@Override
protected ILabelProvider createViewLabelProvider() {
return new ViewLabelProvider();
}
protected void setupDoubleClick() {
getTreeViewer().addDoubleClickListener(new IDoubleClickListener() {
@Override
public void doubleClick(DoubleClickEvent event) {
List<INodeInfo> selectedNodeInfos = getSelectedNodeInfos();
if (selectedNodeInfos.size() == 1) {
INodeInfo selectedNodeInfo = selectedNodeInfos.get(0);
if (selectedNodeInfo instanceof IReferenceNodeInfo) {
IReferenceNodeInfo referenceNodeInfo = (IReferenceNodeInfo) selectedNodeInfo;
ObjRef parentRef = referenceNodeInfo.getParentRef();
String featureName = referenceNodeInfo.getFeatureName();
if (referenceNodeInfo.isMultiple()) {
List<ObjRef> referenceTargetObjects = Lists.newArrayList(Iterables.filter(
xarch.getAll(parentRef, featureName), ObjRef.class));
if (referenceNodeInfo.getIndex() < referenceTargetObjects.size()) {
ObjRef referenceTargetRef = referenceTargetObjects.get(referenceNodeInfo.getIndex());
if (referenceTargetRef != null) {
focusEditor(ArchEditMyxComponent.EDITOR_NAME, new ObjRef[] { referenceTargetRef });
}
}
}
else {
Object referenceTargetObject = xarch.get(parentRef, featureName);
if (referenceTargetObject != null && referenceTargetObject instanceof ObjRef) {
ObjRef referenceTargetRef = (ObjRef) referenceTargetObject;
focusEditor(ArchEditMyxComponent.EDITOR_NAME, new ObjRef[] { referenceTargetRef });
}
}
}
}
}
});
}
protected void setupDragAndDrop() {
DropTarget target = new DropTarget(getTreeViewer().getTree(), DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_DEFAULT);
final TextTransfer textTransfer = TextTransfer.getInstance();
target.setTransfer(new Transfer[] { textTransfer });
target.addDropListener(new DropTargetListener() {
@Override
public void dragEnter(DropTargetEvent event) {
if (event.detail == DND.DROP_DEFAULT) {
if ((event.operations & DND.DROP_COPY) != 0) {
event.detail = DND.DROP_COPY;
}
else {
event.detail = DND.DROP_NONE;
}
}
}
@Override
public void dragOver(DropTargetEvent event) {
if (textTransfer.isSupportedType(event.currentDataType)) {
Object o = textTransfer.nativeToJava(event.currentDataType);
if (o instanceof String) {
String t = (String) o;
if (t.startsWith("$LINK$")) {
event.feedback = DND.FEEDBACK_SCROLL;
}
}
}
event.feedback = DND.FEEDBACK_NONE;
}
@Override
public void dragOperationChanged(DropTargetEvent event) {
if (event.detail == DND.DROP_DEFAULT) {
if ((event.operations & DND.DROP_COPY) != 0) {
event.detail = DND.DROP_COPY;
}
else {
event.detail = DND.DROP_NONE;
}
}
}
@Override
public void dragLeave(DropTargetEvent event) {
}
@Override
public void dropAccept(DropTargetEvent event) {
}
@Override
public void drop(DropTargetEvent event) {
if (textTransfer.isSupportedType(event.currentDataType)) {
String text = (String) event.data;
if (text.startsWith("$LINK$")) {
String[] parts = text.split("\\$", 4);
String xPath = parts[3];
String featureName = parts[2];
ObjRef parentRef;
try {
parentRef = SystemUtils.firstOrNull(xarch.resolveObjRefs(documentRootRef, xPath));
}
catch (XPathException e) {
e.printStackTrace();
return;
}
if (parentRef == null) {
return;
}
if (event.item != null && event.item instanceof TreeItem) {
Object data = ((TreeItem) event.item).getData();
if (data != null && data instanceof ArchEditElementNode) {
ObjRef targetRef = ((ArchEditElementNode) data).getRef();
IXArchADTFeature feature = XadlUtils.getFeatureByName(xarch, parentRef, featureName);
if (feature != null) {
if (!XadlUtils.isAssignableTo(xarch, feature, xarch.getTypeMetadata(targetRef))) {
MessageBox messageBox = new MessageBox(getControl().getShell(), SWT.OK
| SWT.ICON_ERROR);
messageBox.setMessage("Can't link that kind of element to this link.");
messageBox.setText("Error");
messageBox.open();
}
else {
XArchADTOperations xarch = new XArchADTOperations(
ArchEditOutlinePage.this.xarch);
xarch.set(parentRef, featureName, targetRef);
xarch.done("Link");
}
}
}
}
}
}
}
});
}
class ViewContentProvider implements ITreeContentProvider {
private final Object[] EMPTY_ARRAY = new Object[0];
IArchEditNode rootNode = null;
@Override
public Object[] getElements(Object inputElement) {
return getChildren(inputElement);
}
@Override
public Object[] getChildren(Object parentElement) {
if (parentElement instanceof IWorkbenchSite) {
if (rootNode == null) {
rootNode = new ArchEditElementNode((ObjRef) xarch.get(documentRootRef, "xADL"));
}
return new Object[] { rootNode };
}
else if (parentElement instanceof IArchEditNode) {
return ((IArchEditNode) parentElement).getChildren().toArray(new IArchEditNode[0]);
}
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 IArchEditNode) {
return ((IArchEditNode) element).hasChildren();
}
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 IArchEditNode) {
return ((IArchEditNode) element).getImage();
}
return null;
}
@Override
public String getText(Object element) {
String text = super.getText(element);
if (element instanceof ArchEditElementNode) {
ObjRef objRef = ((ArchEditElementNode) element).ref;
if (xarch instanceof IXArchADTVariability) {
ChangeStatus changeStatus = ((IXArchADTVariability) xarch).getChangeStatus(objRef);
if (changeStatus != ChangeStatus.ATTACHED && changeStatus != ChangeStatus.NOT_ENABLED) {
text += " (" + changeStatus + ")";
}
}
}
return text;
}
}
public List<INodeInfo> getSelectedNodeInfos() {
List<INodeInfo> nodeInfoList = new ArrayList<INodeInfo>();
for (Object selectedObject : getSelectedObjects()) {
if (selectedObject instanceof INodeInfo) {
nodeInfoList.add((INodeInfo) selectedObject);
}
}
return nodeInfoList;
}
protected interface IArchEditNode {
public boolean hasChildren();
public List<IArchEditNode> getChildren();
public Image getImage();
}
protected class ArchEditReferenceNode implements IArchEditNode, IReferenceNodeInfo {
protected final ObjRef parentRef;
protected final String featureName;
protected final int index;
protected final boolean isMultiple;
public ArchEditReferenceNode(ObjRef parentRef, String featureName, boolean isMultiple, int index) {
super();
this.parentRef = parentRef;
this.featureName = featureName;
this.isMultiple = isMultiple;
this.index = index;
}
@Override
public ObjRef getParentRef() {
return parentRef;
}
@Override
public String getFeatureName() {
return featureName;
}
@Override
public Image getImage() {
return resources.getPlatformImage(ISharedImages.IMG_TOOL_FORWARD);
}
@Override
public boolean hasChildren() {
return false;
}
@Override
public List<IArchEditNode> getChildren() {
return Collections.emptyList();
}
@Override
public boolean isMultiple() {
return isMultiple;
}
@Override
public int getIndex() {
return index;
}
@Override
public String toString() {
return getFeatureName();
}
}
protected class ArchEditElementNode implements IArchEditNode, IElementNodeInfo {
protected final ObjRef ref;
protected final IXArchADTTypeMetadata typeMetadata;
public ArchEditElementNode(ObjRef ref) {
this.ref = ref;
typeMetadata = xarch.getTypeMetadata(ref);
}
@Override
public ObjRef getRef() {
return ref;
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (o instanceof ArchEditElementNode) {
if (((ArchEditElementNode) o).ref.equals(ref)) {
return true;
}
}
return false;
}
@Override
public int hashCode() {
return ref.hashCode();
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(XadlUtils.getDisplayName(xarch, ref));
if (showIDs && !showDescriptions) {
String id = XadlUtils.getID(xarch, ref);
if (id != null) {
sb.append(" [");
sb.append(id);
sb.append("]");
}
}
else if (showDescriptions && !showIDs) {
String desc = XadlUtils.getName(xarch, ref);
if (desc != null) {
sb.append(" [");
sb.append(desc);
sb.append("]");
}
}
else if (showDescriptions && showIDs) {
String id = XadlUtils.getID(xarch, ref);
String desc = XadlUtils.getName(xarch, ref);
if (id != null || desc != null) {
if (id == null) {
id = "(No ID)";
}
if (desc == null) {
desc = "(No Description)";
}
sb.append(" [");
sb.append(id);
sb.append("; ");
sb.append(desc);
sb.append("]");
}
}
if (showObjRefs) {
sb.append(" <" + ref + ">");
}
return sb.toString();
}
@Override
public List<IArchEditNode> getChildren() {
List<IArchEditNode> l = new ArrayList<IArchEditNode>();
for (IXArchADTFeature feature : typeMetadata.getFeatures().values()) {
String eltName = feature.getName();
if (feature.isReference()) {
switch (feature.getType()) {
case ELEMENT_SINGLE:
l.add(new ArchEditReferenceNode(ref, eltName, false, 0));
break;
case ELEMENT_MULTIPLE:
int size = Iterables.size(Iterables.filter(xarch.getAll(ref, eltName), ObjRef.class));
for (int i = 0; i < size; i++) {
l.add(new ArchEditReferenceNode(ref, eltName, true, i++));
}
break;
case ATTRIBUTE:
// do nothing
}
}
else {
switch (feature.getType()) {
case ELEMENT_SINGLE:
ObjRef childRef = (ObjRef) xarch.get(ref, eltName);
if (childRef != null) {
l.add(new ArchEditElementNode(childRef));
}
break;
case ELEMENT_MULTIPLE:
for (ObjRef childRef2 : Iterables.filter(xarch.getAll(ref, eltName), ObjRef.class)) {
l.add(new ArchEditElementNode(childRef2));
}
case ATTRIBUTE:
// do nothing
}
}
}
return l;
}
@Override
public boolean hasChildren() {
for (IXArchADTFeature feature : typeMetadata.getFeatures().values()) {
switch (feature.getType()) {
case ELEMENT_MULTIPLE:
return true;
case ELEMENT_SINGLE:
return true;
case ATTRIBUTE:
// do nothing, keep searching
}
}
return false;
}
@Override
public Image getImage() {
Image image = ResourceCache.getIcon(xarch, ref);
if (image != null) {
return image;
}
if (hasChildren()) {
return resources.getPlatformImage(ISharedImages.IMG_OBJ_FOLDER);
}
else {
return resources.getPlatformImage(ISharedImages.IMG_OBJ_ELEMENT);
}
}
}
@Override
protected IAction[] createPulldownMenuItems() {
Action showIDAction = new Action("Show IDs", IAction.AS_CHECK_BOX) {
@Override
public void run() {
Object[] expandedElements = getTreeViewer().getExpandedElements();
showIDs = isChecked();
getTreeViewer().refresh(true);
getTreeViewer().setExpandedElements(expandedElements);
}
};
showIDAction.setChecked(showIDs);
showIDAction.setText("Show IDs");
showIDAction.setToolTipText("Show IDs with elements");
Action showDescAction = new Action("Show Descriptions", IAction.AS_CHECK_BOX) {
@Override
public void run() {
Object[] expandedElements = getTreeViewer().getExpandedElements();
showDescriptions = isChecked();
getTreeViewer().refresh(true);
getTreeViewer().setExpandedElements(expandedElements);
}
};
showDescAction.setChecked(showDescriptions);
showDescAction.setText("Show Descriptions");
showDescAction.setToolTipText("Show Descriptions with elements");
Action showObjRefAction = new Action("Show ObjRefs", IAction.AS_CHECK_BOX) {
@Override
public void run() {
Object[] expandedElements = getTreeViewer().getExpandedElements();
showObjRefs = isChecked();
getTreeViewer().refresh(true);
getTreeViewer().setExpandedElements(expandedElements);
}
};
showObjRefAction.setChecked(showObjRefs);
showObjRefAction.setText("Show ObjRefs");
showObjRefAction.setToolTipText("Show ObjRefs with elements");
return new Action[] { showIDAction, showDescAction, showObjRefAction };
}
@Override
protected void fillContextMenu(IMenuManager menuMgr) {
List<INodeInfo> selectedNodeInfos = getSelectedNodeInfos();
if (selectedNodeInfos.size() == 0) {
Action noAction = new Action("[No Selection]") {
@Override
public void run() {
}
};
noAction.setEnabled(false);
menuMgr.add(noAction);
}
else if (selectedNodeInfos.size() > 1) {
Action noAction = new Action("[Select One Node for Menu]") {
@Override
public void run() {
}
};
noAction.setEnabled(false);
menuMgr.add(noAction);
}
else {
INodeInfo selectedNodeInfo = selectedNodeInfos.get(0);
if (selectedNodeInfo instanceof IElementNodeInfo) {
ObjRef ref = ((IElementNodeInfo) selectedNodeInfo).getRef();
if (!XadlUtils.isRootElement(xarch, ref)) {
// It's not the root node so we can remove it.
menuMgr.add(createContextMenuRemoveAction(ref));
menuMgr.add(new Separator());
}
IAction generateIdAction = createContextMenuGenerateIDAction(ref);
if (generateIdAction != null) {
menuMgr.add(generateIdAction);
menuMgr.add(new Separator());
}
else {
menuMgr.add(createContextMenuGenerateAllIDsAction(ref));
menuMgr.add(new Separator());
}
List<Object> items = createAddContextMenuItems(ref);
if (items.isEmpty()) {
menuMgr.add(SWTWidgetUtils.createNoAction("[No Actions]"));
}
else {
for (Object item : items) {
if (item instanceof IContributionItem) {
menuMgr.add((IContributionItem) item);
}
else if (item instanceof IAction) {
menuMgr.add((IAction) item);
}
}
}
}
}
menuMgr.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
}
public IAction createContextMenuRemoveAction(ObjRef ref) {
final ObjRef fref = ref;
Action removeAction = new Action("Remove") {
@Override
public void run() {
XadlUtils.remove(xarch, fref);
Object[] expandedElements = getTreeViewer().getExpandedElements();
getTreeViewer().refresh(true);
getTreeViewer().setExpandedElements(expandedElements);
}
};
return removeAction;
}
protected IAction createContextMenuGenerateIDAction(ObjRef ref) {
final ObjRef fref = ref;
final IXArchADTTypeMetadata typeMetadata = xarch.getTypeMetadata(ref);
final IXArchADTFeature idFeature = typeMetadata.getFeatures().get("id");
if (idFeature == null) {
return null;
}
Action generateIdAction = new Action("Generate ID") {
@Override
public void run() {
XArchADTOperations.set("Generate ID", xarch, fref, "id", UIDGenerator.generateUID());
}
};
String existingId = (String) xarch.get(ref, "id");
generateIdAction.setEnabled(existingId == null || existingId.trim().length() == 0);
return generateIdAction;
}
protected IAction createContextMenuGenerateAllIDsAction(ObjRef ref) {
final ObjRef fref = ref;
Action generateIdAction = new Action("Generate All IDs") {
@Override
public void run() {
XArchADTOperations xarch = new XArchADTOperations(ArchEditOutlinePage.this.xarch);
List<Serializable> objRefs = Lists.<Serializable> newArrayList(fref);
while (objRefs.size() > 0) {
Serializable s = objRefs.remove(0);
if (s instanceof ObjRef) {
ObjRef ref = (ObjRef) s;
IXArchADTTypeMetadata typeMetadata = xarch.getTypeMetadata(ref);
IXArchADTFeature idFeature = typeMetadata.getFeatures().get("id");
if (idFeature != null) {
if (xarch.get(ref, idFeature.getName()) == null) {
xarch.set(ref, idFeature.getName(), UIDGenerator.generateUID());
}
}
for (IXArchADTFeature feature : typeMetadata.getFeatures().values()) {
if (feature.isReference()) {
continue;
}
switch (feature.getType()) {
case ATTRIBUTE:
continue;
case ELEMENT_SINGLE:
objRefs.add(xarch.get(ref, feature.getName()));
continue;
case ELEMENT_MULTIPLE:
objRefs.addAll(xarch.getAll(ref, feature.getName()));
continue;
}
}
}
}
xarch.done("Generate All IDs");
}
};
return generateIdAction;
}
private List<IXArchADTFeature> sort(Collection<IXArchADTFeature> features) {
List<IXArchADTFeature> f = Lists.newArrayList(features);
Collections.sort(f, new Comparator<IXArchADTFeature>() {
@Override
public int compare(IXArchADTFeature arg0, IXArchADTFeature arg1) {
return arg0.getTypeName().compareTo(arg1.getTypeName());
}
});
return f;
}
protected List<Object> createAddContextMenuItems(final ObjRef ref) {
List<Object> items = new ArrayList<Object>();
final IXArchADTTypeMetadata typeMetadata = xarch.getTypeMetadata(ref);
for (final IXArchADTFeature feature : sort(typeMetadata.getFeatures().values())) {
if (feature.getType().equals(FeatureType.ELEMENT_SINGLE)
|| feature.getType().equals(FeatureType.ELEMENT_MULTIPLE)) {
boolean disabled = false;
if (feature.getType().equals(FeatureType.ELEMENT_SINGLE)) {
Object existingElement = xarch.get(ref, feature.getName());
if (existingElement != null) {
//We can't add a new one because we already have one.
items.add(SWTWidgetUtils.createNoAction("Add " + SystemUtils.capFirst(feature.getName())));
disabled = true;
}
}
if (!disabled) {
final MenuManager submenuManager = new MenuManager("Add " + SystemUtils.capFirst(feature.getName()));
// Find all the candidates
boolean foundOne = false;
if (XadlUtils.isInstanceOf(xarch, feature, Xadlcore_3_0Package.Literals.EXTENSION)) {
String typeName = typeMetadata.getTypeName().substring(
typeMetadata.getTypeName().lastIndexOf('.') + 1);
for (IXArchADTSubstitutionHint hint : xarch.getSubstitutionHintsForTarget(
typeMetadata.getNsURI(), typeName)) {
foundOne = true;
Action addEltAction = new AddElementAction(ref, feature, hint.getSourceNsURI(),
hint.getSourceTypeName());
submenuManager.add(addEltAction);
}
}
else {
// This handles substitution groups and the like
for (IXArchADTSubstitutionHint hint : xarch.getSubstitutionHintsForSource(
typeMetadata.getNsURI(), feature.getName())) {
foundOne = true;
Action addEltAction = new AddElementAction(ref, feature, hint.getTargetNsURI(),
hint.getTargetTypeName());
submenuManager.add(addEltAction);
}
}
if (foundOne) {
submenuManager.add(new Separator());
}
List<AddElementAction> addElementActions = Lists.newArrayList();
for (final IXArchADTPackageMetadata packageMetadata : xarch.getAvailablePackageMetadata()) {
for (Map.Entry<String, IXArchADTTypeMetadata> e : packageMetadata.getTypeMetadata().entrySet()) {
final String elementName = e.getKey();
if (XadlUtils.isAssignableTo(xarch, feature, e.getValue()) && !e.getValue().isAbstract()) {
foundOne = true;
addElementActions.add(new AddElementAction(ref, feature, packageMetadata.getNsURI(),
elementName));
}
}
}
Collections.sort(addElementActions, new Comparator<AddElementAction>() {
@Override
public int compare(AddElementAction o1, AddElementAction o2) {
return o1.getText().compareTo(o2.getText());
}
});
if (addElementActions.size() > 15) {
Multimap<String, AddElementAction> addElementActionsByPackage = Multimaps.index(
addElementActions, new Function<AddElementAction, String>() {
@Override
@Nullable
public String apply(@Nullable AddElementAction input) {
return input.getPackageNsURI();
}
});
for (Entry<String, Collection<AddElementAction>> entry : SystemUtils
.sortedByKey(addElementActionsByPackage.asMap().entrySet())) {
MenuManager p = new MenuManager("Package " + entry.getKey());
submenuManager.add(p);
for (AddElementAction addElementAction : entry.getValue()) {
p.add(addElementAction);
}
}
}
else if (addElementActions.size() > 0) {
for (AddElementAction addElementAction : addElementActions) {
submenuManager.add(addElementAction);
}
}
if (!foundOne) {
submenuManager.add(SWTWidgetUtils.createNoAction("[No Candidates]"));
}
items.add(submenuManager);
}
}
}
return items;
}
private class AddElementAction extends Action {
private final ObjRef ref;
private final IXArchADTFeature feature;
private final String packageNsURI;
private final String elementName;
public AddElementAction(ObjRef ref, IXArchADTFeature feature, String packageNsURI, String elementName) {
super(SystemUtils.capFirst(elementName));
this.ref = ref;
this.feature = feature;
this.packageNsURI = packageNsURI;
this.elementName = elementName;
setToolTipText(packageNsURI);
setDescription(packageNsURI);
}
@Override
public void run() {
ObjRef newRef = xarch.create(packageNsURI, elementName);
switch (feature.getType()) {
case ELEMENT_SINGLE:
XArchADTOperations.set("Add", xarch, ref, feature.getName(), newRef);
break;
case ELEMENT_MULTIPLE:
XArchADTOperations.add("Add", xarch, ref, feature.getName(), newRef);
break;
case ATTRIBUTE:
throw new IllegalArgumentException();
}
Object[] expandedElements = getTreeViewer().getExpandedElements();
getTreeViewer().refresh(true);
getTreeViewer().setExpandedElements(expandedElements);
}
public String getPackageNsURI() {
return packageNsURI;
}
}
@Override
public void focusEditor(ObjRef[] refs) {
// FIXME: getTreeViewer() can be null if the editor has not yet been focused
if (refs.length > 0 && getTreeViewer() != null) {
List<ArchEditElementNode> nodes = new ArrayList<ArchEditElementNode>(refs.length);
for (ObjRef ref : refs) {
nodes.add(new ArchEditElementNode(ref));
}
//Expand the ancestors of the selected items
for (ArchEditElementNode node : nodes) {
List<ObjRef> ancestors = xarch.getAllAncestors(node.ref);
for (int j = ancestors.size() - 1; j >= 1; j--) {
ArchEditElementNode ancestorNode = new ArchEditElementNode(ancestors.get(j));
getTreeViewer().expandToLevel(ancestorNode, 1);
}
}
IStructuredSelection ss = new StructuredSelection(nodes);
getTreeViewer().setSelection(ss, true);
}
}
}