/******************************************************************************* * Copyright (c) 2019 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 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation * Semantum Oy - Reorganization *******************************************************************************/ package org.simantics.issues.common; import java.util.Map; import java.util.Set; import org.eclipse.core.runtime.IProgressMonitor; import org.simantics.Simantics; import org.simantics.db.Issue; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.Session; import org.simantics.db.Statement; import org.simantics.db.VirtualGraph; import org.simantics.db.WriteGraph; import org.simantics.db.common.request.WriteRequest; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.util.RemoverUtil; import org.simantics.db.service.VirtualGraphSupport; import org.simantics.issues.ontology.IssueResource; import org.simantics.layer0.Layer0; import gnu.trove.set.hash.THashSet; public class BatchValidations { private static final boolean PERF = false; public static Map> validate(IProgressMonitor monitor, BatchIssueSource source, BatchIssueValidationContext context) throws DatabaseException { Session session = Simantics.getSession(); return session.syncRequest(new ComposedValidation(monitor, source, context)); } /** * @param monitor * @param source * @param issues * @return * @throws DatabaseException */ public static int store(final IProgressMonitor monitor, final Resource source, final Map> issues) throws DatabaseException { return store(monitor, source, issues, Integer.MAX_VALUE); } /** * @param monitor * @param source * @param issues * @param maxIssuesToWrite * @return number of issues written (added) * @throws DatabaseException */ public static int store(final IProgressMonitor monitor, final Resource source, final Map> issues, final int maxIssuesToWrite) throws DatabaseException { if (issues.isEmpty() || maxIssuesToWrite <= 0) return 0; Session session = Simantics.getSession(); VirtualGraphSupport support = session.getService(VirtualGraphSupport.class); VirtualGraph vg = support.getWorkspacePersistent(IssueConstants.ISSUE_VG); final int[] writtenIssues = { 0 }; session.syncRequest(new WriteRequest(vg) { @Override public void perform(WriteGraph graph) throws DatabaseException { for(Map.Entry> entry : issues.entrySet()) { if (monitor.isCanceled()) return; Resource context = entry.getKey(); Set current = entry.getValue(); Set existing = graph.sync(new BatchIssueDescriptions(source, context)); if(!existing.equals(current)) { Set added = new THashSet(current); Set removed = new THashSet(existing); added.removeAll(existing); removed.removeAll(current); for(Issue add : added) { add.write(graph, source); // Stop if write limit is reached. if (++writtenIssues[0] >= maxIssuesToWrite) return; } for(Issue remove : removed) { Resource issue = graph.sync(new IssueByList(source, remove)); if (issue == null) // FIXME: when can this happen and what should be done in this case? continue; graph.deny(issue, Layer0.getInstance(graph).PartOf); graph.deny(source, IssueResource.getInstance(graph).IssueSource_Manages, issue); RemoverUtil.remove(graph, issue); } } } } }); return writtenIssues[0]; } /** * @param map * @return */ @SuppressWarnings("rawtypes") private static int count(Map map) { int result = 0; for (Object obj : map.values()) { if (obj instanceof Set) { Set set = (Set) obj; result += set.size(); } } return result; } /** * Checks if the specified resourceToCheckForLinks is linked to * anything else besides itself and excludeLinksTo. * *

* This is used to if an issue context is still valid. We consider any issue * context that is not attached to something else besides its issue context to * be an invalid issue. Assertions and L0.InstanceOf do not count as external * links. * * @param graph database access handle * @param resourceToCheckForLinks the resource to check for "external" links * @param excludeLinksTo exclude links to this resource from evaluation * @return true if there are links, false otherwise * @throws DatabaseException */ public static boolean isLinkedToOtherThan(ReadGraph graph, Resource resourceToCheckForLinks, Resource excludeLinksTo) throws DatabaseException { Layer0 L0 = Layer0.getInstance(graph); for (Statement stm : graph.getStatements(resourceToCheckForLinks, L0.IsWeaklyRelatedTo)) { if (stm.isAsserted(resourceToCheckForLinks)) continue; if (stm.getPredicate().equals(L0.InstanceOf)) continue; Resource o = stm.getObject(); if (o.equals(excludeLinksTo) || o.equals(resourceToCheckForLinks)) continue; return true; } return false; } }