1 /*******************************************************************************
2 * Copyright (c) 2010, 2011 Association for Decentralized Information Management in
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.browsing.ui.model.actions;
14 import gnu.trove.map.hash.THashMap;
15 import gnu.trove.set.hash.THashSet;
17 import java.util.ArrayList;
18 import java.util.Arrays;
19 import java.util.Collection;
20 import java.util.Collections;
21 import java.util.HashSet;
22 import java.util.List;
26 import org.eclipse.jface.action.Action;
27 import org.simantics.browsing.ui.BuiltinKeys;
28 import org.simantics.browsing.ui.NodeContext;
29 import org.simantics.browsing.ui.model.InvalidContribution;
30 import org.simantics.browsing.ui.model.browsecontexts.BrowseContexts;
31 import org.simantics.browsing.ui.model.browsecontexts.ResolveActionBrowseContext;
32 import org.simantics.browsing.ui.model.nodetypes.EntityNodeType;
33 import org.simantics.browsing.ui.model.nodetypes.NodeType;
34 import org.simantics.browsing.ui.model.nodetypes.NodeTypeMultiMap;
35 import org.simantics.browsing.ui.model.nodetypes.SpecialNodeType;
36 import org.simantics.db.ReadGraph;
37 import org.simantics.db.Resource;
38 import org.simantics.db.exception.DatabaseException;
39 import org.simantics.viewpoint.ontology.ViewpointResource;
42 * ActionBrowseContext holds all contributions related to given set of action browse contexts.
44 * @author Hannu Niemistö
46 public class ActionBrowseContext {
47 NodeTypeMultiMap<ActionContribution> actionContributions = new NodeTypeMultiMap<ActionContribution>();
48 // TODO: remove these two temporary mechanisms
49 THashSet<Resource> removableNodeTypes = new THashSet<Resource>();
50 THashSet<Resource> renameableNodeTypes = new THashSet<Resource>();
51 NodeTypeMultiMap<TestContribution> removalContributions = new NodeTypeMultiMap<TestContribution>();
52 NodeTypeMultiMap<TestContribution> renamingContributions = new NodeTypeMultiMap<TestContribution>();
54 private final String[] uris;
56 private ActionBrowseContext(String[] uris) {
58 throw new NullPointerException("null URIs");
62 public String[] getURIs() {
66 public static ActionBrowseContext get(ReadGraph graph,NodeContext context,ActionBrowseContext defaultContext) throws DatabaseException {
67 ActionBrowseContext mbc = graph.syncRequest(new ResolveActionBrowseContext(context));
68 if(mbc != null) return mbc;
69 ActionBrowseContext parentContext = (ActionBrowseContext)context.getConstant(BuiltinKeys.ACTION_BROWSE_CONTEXT);
70 if(parentContext != null) return parentContext;
71 return defaultContext;
74 public static ActionBrowseContext create(ReadGraph g, Collection<Resource> browseContextResources) throws DatabaseException, InvalidContribution {
75 ViewpointResource vr = ViewpointResource.getInstance(g);
76 ActionBrowseContext browseContext = new ActionBrowseContext( BrowseContexts.toSortedURIs(g, browseContextResources) );
77 for(Resource browseContextResource : findSubcontexts(g, browseContextResources)) {
78 for(Resource actionContributionResource :
79 g.getObjects(browseContextResource, vr.BrowseContext_HasActionContribution)) {
81 ActionContribution.load(g, actionContributionResource,
82 browseContext.actionContributions
84 } catch(DatabaseException e) {
88 for(Resource canRemove : g.getObjects(browseContextResource, vr.BrowseContext_SupportsRemovalOf))
89 browseContext.removableNodeTypes.add(canRemove);
90 for(Resource canRemove : g.getObjects(browseContextResource, vr.BrowseContext_SupportsRenamingOf))
91 browseContext.renameableNodeTypes.add(canRemove);
93 for (Resource testContribution : g.getObjects(browseContextResource, vr.BrowseContext_HasTestContribution)) {
95 Set<Resource> types = g.getTypes(testContribution);
96 if (types.contains(vr.RemovalTestContribution))
97 TestContribution.load(g, testContribution, browseContext.removalContributions);
98 if (types.contains(vr.RenamingTestContribution))
99 TestContribution.load(g, testContribution, browseContext.renamingContributions);
100 } catch (DatabaseException e) {
105 return browseContext;
108 private static Collection<Resource> findSubcontexts(ReadGraph g,
109 Collection<Resource> browseContexts) throws DatabaseException {
110 ViewpointResource vr = ViewpointResource.getInstance(g);
111 HashSet<Resource> result = new HashSet<Resource>(browseContexts);
112 ArrayList<Resource> stack = new ArrayList<Resource>(browseContexts);
113 while(!stack.isEmpty()) {
114 Resource cur = stack.remove(stack.size()-1);
115 for(Resource sc : g.getObjects(cur, vr.BrowseContext_Includes))
122 private static NodeType getNodeType(ReadGraph graph, NodeContext parent) throws DatabaseException {
123 NodeType nodeType = parent.getConstant(NodeType.TYPE);
124 if(nodeType == null) {
125 // TODO remove this code when root of model browser is fixed
126 Object input = parent.getConstant(BuiltinKeys.INPUT);
127 if(input instanceof Resource)
128 nodeType = EntityNodeType.getNodeTypeFor(graph, (Resource)input);
133 public Map<IActionCategory, List<Action>> getActions(ReadGraph graph, NodeContext parent, Collection<NodeContext> all) throws DatabaseException {
134 NodeType nodeType = getNodeType(graph, parent);
136 return Collections.emptyMap();
137 THashMap<IActionCategory, List<Action>> map = new THashMap<IActionCategory, List<Action>>();
138 for(ActionContribution contribution : actionContributions.get(graph, nodeType)) {
139 CategorizedAction action = contribution.getAction(graph, parent, all);
141 List<Action> actions = map.get(action.category);
142 if(actions == null) {
143 actions = new ArrayList<Action>();
144 map.put(action.category, actions);
146 actions.add(action.action);
153 public int hashCode() {
154 return Arrays.hashCode(uris);
158 public boolean equals(Object obj) {
163 if (getClass() != obj.getClass())
165 ActionBrowseContext other = (ActionBrowseContext) obj;
166 return Arrays.equals(uris, other.uris);
170 public String toString() {
171 return getClass().getSimpleName() + Arrays.toString(uris);
175 * This is an attempt to improve removal logic with SpecialNodeTypes. However it
176 * should not be considered as a final solution.
178 public boolean canRemove(ReadGraph graph, NodeContext parent) throws DatabaseException {
179 return testContributions(graph, parent, removalContributions, removableNodeTypes);
183 * This is an attempt to improve renaming logic with SpecialNodeTypes. However it
184 * should not be considered as a final solution.
186 public boolean canRename(ReadGraph graph, NodeContext parent) throws DatabaseException {
187 return testContributions(graph, parent, renamingContributions, renameableNodeTypes);
190 private boolean testContributions(
193 NodeTypeMultiMap<TestContribution> contributions,
194 Set<Resource> allowedSpecialTypes) throws DatabaseException {
195 NodeType nodeType = getNodeType(graph, parent);
196 if (nodeType == null)
197 // Return true for now if node type is not available
198 // to prevent older and more custom solutions such as
199 // property view tables from breaking up.
202 // TODO: this is a previous temporary solution that should probably be removed
203 if (nodeType instanceof SpecialNodeType
204 && allowedSpecialTypes.contains(((SpecialNodeType) nodeType).resource))
207 for (TestContribution contribution : contributions.get(graph, nodeType)) {
208 if (!contribution.test(graph, parent))