From a770d29c1cd08ec09aed5a988cb54c9aaf623f3f Mon Sep 17 00:00:00 2001 From: Tuukka Lehtonen Date: Thu, 2 Nov 2017 16:52:34 +0200 Subject: [PATCH] Allow overriding issue hidden-ness/hiding logic in inheriting ontologies Changed the way issues are modelled by adding two new function-properties: hider & hidden. hider is used to change the hidden-state of issues and hidden is used to query the state. This allows e.g. fully variable-based dynamic issue hierarchies to support hiding as well. refs #7594 Change-Id: Ieba88fb4ffd3142dc4371fa941fd5f31d6eaf93f --- .../simantics/db/common/utils/TagUtil.java | 10 +- .../src/org/simantics/issues/common/All.java | 27 ++++++ .../simantics/issues/common/HideFunction.java | 76 +++++++++++++++ .../graph/Issue.pgraph | 8 ++ .../graph/IssueUI.pgraph | 13 ++- .../IssueLabelDecorationRule.java | 95 +++++++++++++------ .../issues/ui/handler/FunctionHandler.java | 78 +++++++++++++++ .../org/simantics/issues/ui/handler/Hide.java | 10 +- .../issues/ui/handler/PreferenceHandler.java | 3 +- .../simantics/issues/ui/handler/Unhide.java | 8 +- 10 files changed, 273 insertions(+), 55 deletions(-) create mode 100644 bundles/org.simantics.issues.common/src/org/simantics/issues/common/HideFunction.java create mode 100644 bundles/org.simantics.issues.ui/src/org/simantics/issues/ui/handler/FunctionHandler.java diff --git a/bundles/org.simantics.db.common/src/org/simantics/db/common/utils/TagUtil.java b/bundles/org.simantics.db.common/src/org/simantics/db/common/utils/TagUtil.java index 81457b408..5cdeebc9f 100644 --- a/bundles/org.simantics.db.common/src/org/simantics/db/common/utils/TagUtil.java +++ b/bundles/org.simantics.db.common/src/org/simantics/db/common/utils/TagUtil.java @@ -23,7 +23,6 @@ import org.simantics.db.common.CommentMetadata; import org.simantics.db.common.request.WriteRequest; import org.simantics.db.exception.DatabaseException; import org.simantics.db.service.VirtualGraphSupport; -import org.simantics.utils.datastructures.Callback; /** * @author Tuukka Lehtonen @@ -62,12 +61,9 @@ public class TagUtil { graph.markUndoPoint(); processSelection(graph, resources); } - }, new Callback() { - @Override - public void run(DatabaseException e) { - if (e != null) - handleError(e); - } + }, e -> { + if (e != null) + handleError(e); }); } diff --git a/bundles/org.simantics.issues.common/src/org/simantics/issues/common/All.java b/bundles/org.simantics.issues.common/src/org/simantics/issues/common/All.java index 6eccb1755..d39ee9837 100644 --- a/bundles/org.simantics.issues.common/src/org/simantics/issues/common/All.java +++ b/bundles/org.simantics.issues.common/src/org/simantics/issues/common/All.java @@ -14,6 +14,7 @@ import org.simantics.db.layer0.variable.Variables; import org.simantics.issues.ontology.IssueResource; import org.simantics.layer0.Layer0; import org.simantics.scl.reflection.annotations.SCLValue; +import org.simantics.scl.runtime.function.Function1; public class All { @@ -96,4 +97,30 @@ public class All { throw new IllegalArgumentException("Unsupported property type: " + property); } + @SCLValue(type = "ReadGraph -> Resource -> a -> b") + public static Function1 standardIssueHider(ReadGraph graph, Resource converter, Object property) throws DatabaseException { + if (property instanceof Variable) { + Variable hider = (Variable) property; + Variable issue = hider.getParent(graph); + Resource r = issue.getPossibleRepresents(graph); + if (r != null) + return new HideFunction(r); + } + return null; + } + + @SCLValue(type = "ReadGraph -> Resource -> a -> Boolean") + public static Boolean standardIssueHidden(ReadGraph graph, Resource converter, Object property) throws DatabaseException { + if (property instanceof Variable) { + Variable hidden = (Variable) property; + Variable issue = hidden.getParent(graph); + Resource r = issue.getPossibleRepresents(graph); + if (r != null) { + IssueResource ISSUE = IssueResource.getInstance(graph); + return graph.hasStatement(r, ISSUE.Hidden); + } + } + return false; + } + } diff --git a/bundles/org.simantics.issues.common/src/org/simantics/issues/common/HideFunction.java b/bundles/org.simantics.issues.common/src/org/simantics/issues/common/HideFunction.java new file mode 100644 index 000000000..d72c36381 --- /dev/null +++ b/bundles/org.simantics.issues.common/src/org/simantics/issues/common/HideFunction.java @@ -0,0 +1,76 @@ +package org.simantics.issues.common; + +import java.util.Objects; + +import org.simantics.databoard.util.ObjectUtils; +import org.simantics.db.Resource; +import org.simantics.db.VirtualGraph; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.CommentMetadata; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.common.utils.NameUtils; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.exception.RuntimeDatabaseException; +import org.simantics.db.service.VirtualGraphSupport; +import org.simantics.issues.ontology.IssueResource; +import org.simantics.scl.runtime.SCLContext; +import org.simantics.scl.runtime.function.FunctionImpl1; + +/** + * @author Tuukka Lehtonen + * @since 1.31.0 + */ +class HideFunction extends FunctionImpl1 { + + private Resource[] issues; + + public HideFunction(Resource... issues) { + this.issues = issues; + } + + @Override + public Boolean apply(Boolean hide) { + try { + WriteGraph graph = Objects.requireNonNull((WriteGraph) SCLContext.getCurrent().get("graph")); + IssueResource ISSUE = IssueResource.getInstance(graph); + boolean changed = false; + for (Resource issue : issues) + changed |= tag(graph, issue, ISSUE.Hidden, hide); + return changed; + } catch (DatabaseException e) { + throw new RuntimeDatabaseException(e); + } + } + + private static boolean tag(WriteGraph graph, Resource r, Resource tagRel, boolean tag) throws DatabaseException { + boolean isTagged = graph.hasStatement(r, tagRel); + if (tag && !isTagged) { + // If r is virtual, we perform tagging in the same vg + VirtualGraphSupport vgs = graph.getService(VirtualGraphSupport.class); + VirtualGraph vg = vgs.getGraph(graph, r); + if (vg != null) { + graph.sync(new WriteRequest(vg) { + @Override + public void perform(WriteGraph graph) throws DatabaseException { + graph.claim(r, tagRel, tagRel, r); + CommentMetadata cm = graph.getMetadata(CommentMetadata.class); + graph.addMetadata(cm.add(ObjectUtils.toString("Marking " + NameUtils.getSafeLabel(graph, r) + " to " + NameUtils.getSafeName(graph, tagRel)))); + } + }); + } else { + graph.claim(r, tagRel, tagRel, r); + CommentMetadata cm = graph.getMetadata(CommentMetadata.class); + graph.addMetadata(cm.add(ObjectUtils.toString("Marking " + NameUtils.getSafeLabel(graph, r) + " to " + NameUtils.getSafeName(graph, tagRel)))); + } + return true; + } else if (!tag && isTagged) { + graph.deny(r, tagRel, tagRel, r); + CommentMetadata cm = graph.getMetadata(CommentMetadata.class); + graph.addMetadata(cm.add(ObjectUtils.toString("Denying " + NameUtils.getSafeLabel(graph, r) + " to " + NameUtils.getSafeName(graph, tagRel)))); + return true; + } + + return false; + } + +} \ No newline at end of file diff --git a/bundles/org.simantics.issues.ontology/graph/Issue.pgraph b/bundles/org.simantics.issues.ontology/graph/Issue.pgraph index c68e561f4..a819028de 100644 --- a/bundles/org.simantics.issues.ontology/graph/Issue.pgraph +++ b/bundles/org.simantics.issues.ontology/graph/Issue.pgraph @@ -42,6 +42,8 @@ ISSUE.Issue -- ISSUE.Issue.resource ==> "String" -- ISSUE.Issue.path ==> "String" -- ISSUE.Issue.creationTime --> L0.String -- ISSUE.Issue.hider ==> "Maybe (Boolean -> Boolean)" -- ISSUE.Issue.hidden ==> "Boolean" Boolean)" + @L0.assert ISSUE.Issue.hidden + ISSUE.Functions.standardIssueHidden : L0.Function + L0.HasValueType "Boolean" ISSUE.UserIssue L0.HasDescription "A tag for marking issues as manually added, i.e. so called user issues." diff --git a/bundles/org.simantics.issues.ui.ontology/graph/IssueUI.pgraph b/bundles/org.simantics.issues.ui.ontology/graph/IssueUI.pgraph index 281bec912..fa2099b9a 100644 --- a/bundles/org.simantics.issues.ui.ontology/graph/IssueUI.pgraph +++ b/bundles/org.simantics.issues.ui.ontology/graph/IssueUI.pgraph @@ -44,6 +44,8 @@ ACTIONS.SetSeverityAction -- ACTIONS.SetSeverityAction.HasSeverity --> ISSUE.Severity contentType) { - return contentType.equals(Resource.class); + return contentType.equals(Variable.class); } @Override public LabelDecorator getLabelDecorator(ReadGraph graph, Object content) throws DatabaseException { - Resource issue = (Resource) content; + Variable issue = (Variable) content; - final boolean hidden = graph.hasStatement(issue, IssueResource.getInstance(graph).Hidden); - final boolean user = graph.hasStatement(issue, IssueResource.getInstance(graph).UserIssue); - final boolean resolved = graph.hasStatement(issue, IssueResource.getInstance(graph).Resolved); - if (!hidden && !user && !resolved) - return null; + boolean hidden = false; + boolean user = false; + boolean resolved = false; - return new LabelDecorator.Stub() { - @SuppressWarnings("unchecked") - @Override - public F decorateFont(F font, String column, int itemIndex) { - int style = 0; - style |= resolved ? SWT.ITALIC : 0; - return style != 0 ? (F) ((FontDescriptor) font).setStyle(style) : font; - } - @SuppressWarnings("unchecked") - @Override - public C decorateForeground(C color, String column, int itemIndex) { - if (hidden) - return (C) Constants.HIDDEN_FG; - return color; - } - @SuppressWarnings("unchecked") - @Override - public C decorateBackground(C color, String column, int itemIndex) { - if (user) - return (C) Constants.USER_BG; - return color; - } - }; + Resource issueR = issue.getPossibleRepresents(graph); + if (issueR != null) { + IssueResource ISSUE = IssueResource.getInstance(graph); + hidden = graph.hasStatement(issueR, ISSUE.Hidden); + user = graph.hasStatement(issueR, ISSUE.UserIssue); + resolved = graph.hasStatement(issueR, ISSUE.Resolved); + } else { + hidden = Boolean.TRUE.equals(issue.getPossiblePropertyValue(graph, "hidden", Bindings.BOOLEAN)); + } + + int index = (hidden ? 1 : 0) + (user ? 2 : 0) + (resolved ? 4 : 0); + return DECORATORS[index]; } + private static final Decorator[] DECORATORS = { + null, + new Decorator(true, false, false), + new Decorator(false, true, false), + new Decorator(true, true, false), + new Decorator(false, false, true), + new Decorator(true, false, true), + new Decorator(false, true, true), + new Decorator(true, true, true), + }; + + private static class Decorator extends LabelDecorator.Stub { + private boolean hidden; + private boolean user; + private boolean resolved; + + public Decorator(boolean hidden, boolean user, boolean resolved) { + this.hidden = hidden; + this.user = user; + this.resolved = resolved; + } + + @SuppressWarnings("unchecked") + @Override + public F decorateFont(F font, String column, int itemIndex) { + int style = 0; + style |= resolved ? SWT.ITALIC : 0; + //style |= hidden ? SWT.BOLD : 0; + return style != 0 ? (F) ((FontDescriptor) font).setStyle(style) : font; + } + @SuppressWarnings("unchecked") + @Override + public C decorateForeground(C color, String column, int itemIndex) { + if (hidden) + return (C) Constants.HIDDEN_FG; + return color; + } + @SuppressWarnings("unchecked") + @Override + public C decorateBackground(C color, String column, int itemIndex) { + if (user) + return (C) Constants.USER_BG; + return color; + } + }; + } diff --git a/bundles/org.simantics.issues.ui/src/org/simantics/issues/ui/handler/FunctionHandler.java b/bundles/org.simantics.issues.ui/src/org/simantics/issues/ui/handler/FunctionHandler.java new file mode 100644 index 000000000..38b2c93e2 --- /dev/null +++ b/bundles/org.simantics.issues.ui/src/org/simantics/issues/ui/handler/FunctionHandler.java @@ -0,0 +1,78 @@ +package org.simantics.issues.ui.handler; + +import java.util.ArrayList; +import java.util.List; + +import org.simantics.Simantics; +import org.simantics.db.Resource; +import org.simantics.db.Session; +import org.simantics.db.VirtualGraph; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.common.utils.Logger; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.variable.Variable; +import org.simantics.db.service.VirtualGraphSupport; +import org.simantics.scl.runtime.SCLContext; +import org.simantics.scl.runtime.function.Function; + +/** + * @author Tuukka Lehtonen + * @since 1.31.0 + */ +class FunctionHandler extends PreferenceHandler { + + private String functionPropertyName; + private Object argument; + + public FunctionHandler(String virtualGraphId, String functionPropertyName, Object argument) { + super(virtualGraphId, null, false); + this.functionPropertyName = functionPropertyName; + this.argument = argument; + } + + public void execute(List vars, List resources) { + if (vars.isEmpty()) + return; + Session session = Simantics.peekSession(); + if (session == null) + return; + + VirtualGraph vg = virtualGraphId == null ? null : + session.getService(VirtualGraphSupport.class).getWorkspacePersistent(virtualGraphId); + + session.asyncRequest(new WriteRequest(vg) { + @Override + public void perform(WriteGraph graph) throws DatabaseException { + graph.markUndoPoint(); + execute(graph, vars, functionPropertyName); + } + }, e -> { + if (e != null) + Logger.defaultLogError(e); + }); + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + protected void execute(WriteGraph graph, List vars, String functionPropertyName) throws DatabaseException { + List hiders = new ArrayList<>(vars.size()); + for (Variable v : vars) { + Function f = v.getPossiblePropertyValue(graph, functionPropertyName); + if (f != null) + hiders.add(f); + } + if (!hiders.isEmpty()) { + SCLContext ctx = SCLContext.getCurrent(); + Object oldGraph = ctx.put("graph", graph); + try { + for (Function f : hiders) + f.apply(argument); + } catch (Throwable t) { + throw new DatabaseException(t); + } finally { + ctx.put("graph", oldGraph); + } + } + } + +} \ No newline at end of file diff --git a/bundles/org.simantics.issues.ui/src/org/simantics/issues/ui/handler/Hide.java b/bundles/org.simantics.issues.ui/src/org/simantics/issues/ui/handler/Hide.java index c6886c170..299b71346 100644 --- a/bundles/org.simantics.issues.ui/src/org/simantics/issues/ui/handler/Hide.java +++ b/bundles/org.simantics.issues.ui/src/org/simantics/issues/ui/handler/Hide.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2011 Association for Decentralized Information Management + * Copyright (c) 2007, 2017 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -8,19 +8,17 @@ * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation + * Semantum Oy - #7594 introduced FunctionHandler *******************************************************************************/ package org.simantics.issues.ui.handler; -import org.simantics.issues.ontology.IssueResource; - - /** * @author Tuukka Lehtonen */ -public class Hide extends PreferenceHandler { +public class Hide extends FunctionHandler { public Hide() { - super(null, IssueResource.URIs.Hidden, true); + super(null, "hider", Boolean.TRUE); } } diff --git a/bundles/org.simantics.issues.ui/src/org/simantics/issues/ui/handler/PreferenceHandler.java b/bundles/org.simantics.issues.ui/src/org/simantics/issues/ui/handler/PreferenceHandler.java index 7a8239598..20a343938 100644 --- a/bundles/org.simantics.issues.ui/src/org/simantics/issues/ui/handler/PreferenceHandler.java +++ b/bundles/org.simantics.issues.ui/src/org/simantics/issues/ui/handler/PreferenceHandler.java @@ -39,7 +39,6 @@ import org.simantics.db.layer0.adapter.ActionFactory2; import org.simantics.db.layer0.variable.Variable; import org.simantics.db.request.Read; import org.simantics.issues.ontology.IssueResource; -import org.simantics.utils.datastructures.SelectionUtils; import org.simantics.utils.ui.ErrorLogger; import org.simantics.utils.ui.ISelectionUtils; @@ -96,7 +95,7 @@ class PreferenceHandler extends AbstractHandler implements IElementUpdater, Acti return null; } - public void execute(final List vars, List resources) { + public void execute(List vars, List resources) { Session session = Simantics.peekSession(); if (session == null) return; diff --git a/bundles/org.simantics.issues.ui/src/org/simantics/issues/ui/handler/Unhide.java b/bundles/org.simantics.issues.ui/src/org/simantics/issues/ui/handler/Unhide.java index 72a9fb4c0..24918c1fb 100644 --- a/bundles/org.simantics.issues.ui/src/org/simantics/issues/ui/handler/Unhide.java +++ b/bundles/org.simantics.issues.ui/src/org/simantics/issues/ui/handler/Unhide.java @@ -8,19 +8,17 @@ * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation + * Semantum Oy - #7594 introduced FunctionHandler *******************************************************************************/ package org.simantics.issues.ui.handler; -import org.simantics.issues.ontology.IssueResource; - - /** * @author Tuukka Lehtonen */ -public class Unhide extends PreferenceHandler { +public class Unhide extends FunctionHandler { public Unhide() { - super(null, IssueResource.URIs.Hidden, false); + super(null, "hider", Boolean.FALSE); } } -- 2.47.1