]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.objmap2/src/org/simantics/objmap/graph/rules/domain/MappingUtils.java
Support for linked lists in objmap2.
[simantics/platform.git] / bundles / org.simantics.objmap2 / src / org / simantics / objmap / graph / rules / domain / MappingUtils.java
index 5e97f852dea2a17f79596a90580b927074de5117..6f7f9260fde774cd50b59be3b95ae4f5a834425b 100644 (file)
-/*******************************************************************************\r
- * Copyright (c) 2007, 2013 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- *     VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.objmap.graph.rules.domain;\r
-\r
-import java.util.Arrays;\r
-import java.util.Collection;\r
-\r
-import org.apache.log4j.Logger;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.WriteGraph;\r
-import org.simantics.db.exception.DatabaseException;\r
-\r
-/**\r
- * Static utility methods for rule implementations.\r
- * @author Hannu Niemistö\r
- */\r
-public class MappingUtils {\r
-\r
-    static Logger LOGGER = Logger.getLogger("org.simantics.objmap");\r
-    \r
-    /**\r
-     * Adds and removes statements to/from the database so that <code>objects</code>\r
-     * will be exactly the objects connected to <code>subject</code> by <code>predicate</code>.\r
-     * Returns true if the method made modifications to the database.\r
-     */\r
-       public static boolean synchronizeStatements(WriteGraph g, Resource subject, Resource predicate, Resource[] objects,\r
-               boolean deleteExtraObjects) \r
-               throws DatabaseException {\r
-               Collection<Resource> currentObjects0 = g.getObjects(subject, predicate);\r
-               Resource[] currentObjects = currentObjects0.toArray(new Resource[currentObjects0.size()]);\r
-               \r
-               Arrays.sort(objects);\r
-               Arrays.sort(currentObjects);\r
-               \r
-               boolean modified = false;\r
-               int i=0, j=0;   \r
-               if(currentObjects.length > 0 && objects.length > 0)\r
-               while(true) {\r
-                       int cmp = currentObjects[i].compareTo(objects[j]);\r
-                       if(cmp < 0) {\r
-                           LOGGER.info("            remove statement");\r
-                           if(deleteExtraObjects)\r
-                               g.deny(currentObjects[i]);\r
-                           else\r
-                               g.denyStatement(subject, predicate, currentObjects[i]);                                 \r
-                               modified = true;\r
-                               ++i;\r
-                               if(i >= currentObjects.length)\r
-                                       break;\r
-                       }\r
-                       else if(cmp > 0) {\r
-                           LOGGER.info("            add statement");\r
-                               g.claim(subject, predicate, objects[j]);\r
-                               modified = true;\r
-                               ++j;\r
-                               if(j >= objects.length)\r
-                                       break;\r
-                       }\r
-                       else {\r
-                               ++i; ++j;\r
-                               if(i >= currentObjects.length)\r
-                                       break;\r
-                               if(j >= objects.length)\r
-                                       break;\r
-                       }\r
-               }\r
-               while(i < currentObjects.length) {\r
-                   if(deleteExtraObjects)\r
-                g.deny(currentObjects[i]);\r
-            else\r
-                g.denyStatement(subject, predicate, currentObjects[i]);\r
-                       modified = true;\r
-                       ++i;\r
-               }\r
-               while(j < objects.length) {\r
-                       g.claim(subject, predicate, objects[j]);\r
-                       modified = true;\r
-                       ++j;\r
-               }\r
-               return modified;\r
-       }\r
-\r
-}\r
+/*******************************************************************************
+ * 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 <code>objects</code>
+     * will be exactly the objects connected to <code>subject</code> by <code>predicate</code>.
+     * 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<Resource> 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;
+       }
+
+       public static boolean synchronizeList(WriteGraph g, Resource element, Resource relation, Resource listType, List<Resource> 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<Resource> 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);
+       }
+
+}