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