X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.objmap2%2Fsrc%2Forg%2Fsimantics%2Fobjmap%2Fgraph%2Frules%2Fdomain%2FMappingUtils.java;h=0bb50ff5726c270d92e69cb1be1074a71e3030bd;hb=993f8fda339c833e182a540bd4c10d3a91624966;hp=5e97f852dea2a17f79596a90580b927074de5117;hpb=969bd23cab98a79ca9101af33334000879fb60c5;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.objmap2/src/org/simantics/objmap/graph/rules/domain/MappingUtils.java b/bundles/org.simantics.objmap2/src/org/simantics/objmap/graph/rules/domain/MappingUtils.java index 5e97f852d..0bb50ff57 100644 --- a/bundles/org.simantics.objmap2/src/org/simantics/objmap/graph/rules/domain/MappingUtils.java +++ b/bundles/org.simantics.objmap2/src/org/simantics/objmap/graph/rules/domain/MappingUtils.java @@ -1,92 +1,171 @@ -/******************************************************************************* - * Copyright (c) 2007, 2013 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 - *******************************************************************************/ -package org.simantics.objmap.graph.rules.domain; - -import java.util.Arrays; -import java.util.Collection; - -import org.apache.log4j.Logger; -import org.simantics.db.Resource; -import org.simantics.db.WriteGraph; -import org.simantics.db.exception.DatabaseException; - -/** - * Static utility methods for rule implementations. - * @author Hannu Niemistö - */ -public class MappingUtils { - - static Logger LOGGER = Logger.getLogger("org.simantics.objmap"); - - /** - * Adds and removes statements to/from the database so that objects - * will be exactly the objects connected to subject by predicate. - * Returns true if the method made modifications to the database. - */ - public static boolean synchronizeStatements(WriteGraph g, Resource subject, Resource predicate, Resource[] objects, - boolean deleteExtraObjects) - throws DatabaseException { - Collection currentObjects0 = g.getObjects(subject, predicate); - Resource[] currentObjects = currentObjects0.toArray(new Resource[currentObjects0.size()]); - - Arrays.sort(objects); - Arrays.sort(currentObjects); - - boolean modified = false; - int i=0, j=0; - if(currentObjects.length > 0 && objects.length > 0) - while(true) { - int cmp = currentObjects[i].compareTo(objects[j]); - if(cmp < 0) { - LOGGER.info(" remove statement"); - if(deleteExtraObjects) - g.deny(currentObjects[i]); - else - g.denyStatement(subject, predicate, currentObjects[i]); - modified = true; - ++i; - if(i >= currentObjects.length) - break; - } - else if(cmp > 0) { - LOGGER.info(" add statement"); - g.claim(subject, predicate, objects[j]); - modified = true; - ++j; - if(j >= objects.length) - break; - } - else { - ++i; ++j; - if(i >= currentObjects.length) - break; - if(j >= objects.length) - break; - } - } - while(i < currentObjects.length) { - if(deleteExtraObjects) - g.deny(currentObjects[i]); - else - g.denyStatement(subject, predicate, currentObjects[i]); - modified = true; - ++i; - } - while(j < objects.length) { - g.claim(subject, predicate, objects[j]); - modified = true; - ++j; - } - return modified; - } - -} +/******************************************************************************* + * Copyright (c) 2007, 2013, 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 - linked list utilities + *******************************************************************************/ +package org.simantics.objmap.graph.rules.domain; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.utils.ListUtils; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.exception.ManyObjectsForFunctionalRelationException; +import org.simantics.db.exception.NoSingleResultException; +import org.simantics.db.exception.ServiceException; +import org.simantics.layer0.Layer0; + +/** + * Static utility methods for rule implementations. + * @author Hannu Niemistö + */ +public class MappingUtils { + + static final Logger LOGGER = LoggerFactory.getLogger(MappingUtils.class); + + /** + * Adds and removes statements to/from the database so that objects + * will be exactly the objects connected to subject by predicate. + * Returns true if the method made modifications to the database. + */ + public static boolean synchronizeStatements(WriteGraph g, Resource subject, Resource predicate, Resource[] objects, + boolean deleteExtraObjects) + throws DatabaseException { + Collection currentObjects0 = g.getObjects(subject, predicate); + Resource[] currentObjects = currentObjects0.toArray(new Resource[currentObjects0.size()]); + + Arrays.sort(objects); + Arrays.sort(currentObjects); + + boolean modified = false; + int i=0, j=0; + if(currentObjects.length > 0 && objects.length > 0) + while(true) { + int cmp = currentObjects[i].compareTo(objects[j]); + if(cmp < 0) { + LOGGER.trace(" remove statement"); + if(deleteExtraObjects) + g.deny(currentObjects[i]); + else + g.denyStatement(subject, predicate, currentObjects[i]); + modified = true; + ++i; + if(i >= currentObjects.length) + break; + } + else if(cmp > 0) { + LOGGER.trace(" add statement"); + g.claim(subject, predicate, objects[j]); + modified = true; + ++j; + if(j >= objects.length) + break; + } + else { + ++i; ++j; + if(i >= currentObjects.length) + break; + if(j >= objects.length) + break; + } + } + while(i < currentObjects.length) { + if(deleteExtraObjects) + g.deny(currentObjects[i]); + else + g.denyStatement(subject, predicate, currentObjects[i]); + modified = true; + ++i; + } + while(j < objects.length) { + g.claim(subject, predicate, objects[j]); + modified = true; + ++j; + } + return modified; + } + + public static boolean synchronizeList(WriteGraph g, Resource element, Resource relation, Resource listType, List value, boolean deleteExtraObjects) throws DatabaseException { + final Layer0 L0 = Layer0.getInstance(g); + + // Return value + boolean modified = false; + + // Get the list - create a new one, if necessary + Resource currentList = g.getPossibleObject(element, relation); + if (currentList == null) { + currentList = ListUtils.create(g, listType); + g.claim(element, relation, currentList); + modified = true; + } + + // Synchronize elements + List currentNodes = ListUtils.getListNodes(g, currentList); + int i = 0, j = 0; + while (i < currentNodes.size()) { + Resource node = currentNodes.get(i); + Resource v = g.getSingleObject(node, L0.List_Element); + if (j < value.size() && v.equals(value.get(j))) { + i++; + j++; + } + else if (value.indexOf(v) > j) { + // Insert new element in the middle + insertElementBefore(g, L0, node, value.get(j)); + modified = true; + j++; + } + else { + // Remove deleted element + if (deleteExtraObjects) g.deny(v); + removeNode(g, L0, node); + modified = true; + i++; + } + } + + // Add new elements at end + while (j < value.size()) { + // Add tailing elements + insertElementBefore(g, L0, currentList, value.get(j)); + modified = true; + j++; + } + + return modified; + } + + private static Resource insertElementBefore(WriteGraph g, final Layer0 L0, Resource node, final Resource val) + throws NoSingleResultException, ManyObjectsForFunctionalRelationException, ServiceException { + Resource prev = g.getSingleObject(node, L0.List_Previous); + g.deny(prev, L0.List_Next, L0.List_Previous, node); + + Resource newNode = g.newResource(); + g.claim(newNode, L0.InstanceOf, L0.List_Entry); + g.claim(prev, L0.List_Next, L0.List_Previous, newNode); + g.claim(newNode, L0.List_Next, L0.List_Previous, node); + g.claim(newNode, L0.List_Element, val); + return newNode; + } + + private static void removeNode(WriteGraph g, final Layer0 L0, Resource node) + throws NoSingleResultException, ManyObjectsForFunctionalRelationException, ServiceException { + Resource prev = g.getSingleObject(node, L0.List_Previous); + Resource next = g.getSingleObject(node, L0.List_Next); + g.claim(prev, L0.List_Next, L0.List_Previous, next); + g.deny(node); + } + +}