]> gerrit.simantics Code Review - simantics/platform.git/blob - 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
1 /*******************************************************************************
2  * Copyright (c) 2007, 2013, 2019 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *     Semantum oy - linked list utilities
12  *******************************************************************************/
13 package org.simantics.objmap.graph.rules.domain;
14
15 import java.util.Arrays;
16 import java.util.Collection;
17 import java.util.List;
18
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
21 import org.simantics.db.Resource;
22 import org.simantics.db.WriteGraph;
23 import org.simantics.db.common.utils.ListUtils;
24 import org.simantics.db.exception.DatabaseException;
25 import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;
26 import org.simantics.db.exception.NoSingleResultException;
27 import org.simantics.db.exception.ServiceException;
28 import org.simantics.layer0.Layer0;
29
30 /**
31  * Static utility methods for rule implementations.
32  * @author Hannu Niemistö
33  */
34 public class MappingUtils {
35
36     static final Logger LOGGER = LoggerFactory.getLogger(MappingUtils.class);
37     
38     /**
39      * Adds and removes statements to/from the database so that <code>objects</code>
40      * will be exactly the objects connected to <code>subject</code> by <code>predicate</code>.
41      * Returns true if the method made modifications to the database.
42      */
43         public static boolean synchronizeStatements(WriteGraph g, Resource subject, Resource predicate, Resource[] objects,
44                 boolean deleteExtraObjects) 
45                 throws DatabaseException {
46                 Collection<Resource> currentObjects0 = g.getObjects(subject, predicate);
47                 Resource[] currentObjects = currentObjects0.toArray(new Resource[currentObjects0.size()]);
48                 
49                 Arrays.sort(objects);
50                 Arrays.sort(currentObjects);
51                 
52                 boolean modified = false;
53                 int i=0, j=0;   
54                 if(currentObjects.length > 0 && objects.length > 0)
55                 while(true) {
56                         int cmp = currentObjects[i].compareTo(objects[j]);
57                         if(cmp < 0) {
58                             LOGGER.info("            remove statement");
59                             if(deleteExtraObjects)
60                                 g.deny(currentObjects[i]);
61                             else
62                                 g.denyStatement(subject, predicate, currentObjects[i]);                                 
63                                 modified = true;
64                                 ++i;
65                                 if(i >= currentObjects.length)
66                                         break;
67                         }
68                         else if(cmp > 0) {
69                             LOGGER.info("            add statement");
70                                 g.claim(subject, predicate, objects[j]);
71                                 modified = true;
72                                 ++j;
73                                 if(j >= objects.length)
74                                         break;
75                         }
76                         else {
77                                 ++i; ++j;
78                                 if(i >= currentObjects.length)
79                                         break;
80                                 if(j >= objects.length)
81                                         break;
82                         }
83                 }
84                 while(i < currentObjects.length) {
85                     if(deleteExtraObjects)
86                 g.deny(currentObjects[i]);
87             else
88                 g.denyStatement(subject, predicate, currentObjects[i]);
89                         modified = true;
90                         ++i;
91                 }
92                 while(j < objects.length) {
93                         g.claim(subject, predicate, objects[j]);
94                         modified = true;
95                         ++j;
96                 }
97                 return modified;
98         }
99
100         public static boolean synchronizeList(WriteGraph g, Resource element, Resource relation, Resource listType, List<Resource> value, boolean deleteExtraObjects) throws DatabaseException {
101                 final Layer0 L0 = Layer0.getInstance(g);
102                 
103                 // Return value
104                 boolean modified = false;
105                 
106                 // Get the list - create a new one, if necessary
107                 Resource currentList = g.getPossibleObject(element, relation);
108                 if (currentList == null) {
109                         currentList = ListUtils.create(g, listType);
110                         g.claim(element, relation, currentList);
111                         modified = true;
112                 }
113
114                 // Synchronize elements
115                 List<Resource> currentNodes = ListUtils.getListNodes(g, currentList);
116                 int i = 0, j = 0;
117                 while (i < currentNodes.size()) {
118                         Resource node = currentNodes.get(i);
119                         Resource v = g.getSingleObject(node, L0.List_Element);
120                         if (j < value.size() && v.equals(value.get(j))) {
121                                 i++;
122                                 j++;
123                         }
124                         else if (value.indexOf(v) > j) {
125                                 // Insert new element in the middle
126                                 insertElementBefore(g, L0, node, value.get(j));
127                                 modified = true;
128                                 j++;
129                         }
130                         else {
131                                 // Remove deleted element
132                                 if (deleteExtraObjects) g.deny(v);
133                                 removeNode(g, L0, node);
134                                 modified = true;
135                                 i++;
136                         }
137                 }
138
139                 // Add new elements at end
140                 while (j < value.size()) {
141                         // Add tailing elements
142                         insertElementBefore(g, L0, currentList, value.get(j));
143                         modified = true;
144                         j++;
145                 }
146                 
147                 return modified;
148         }
149
150         private static Resource insertElementBefore(WriteGraph g, final Layer0 L0, Resource node, final Resource val)
151                         throws NoSingleResultException, ManyObjectsForFunctionalRelationException, ServiceException {
152                 Resource prev = g.getSingleObject(node, L0.List_Previous);
153                 g.deny(prev, L0.List_Next, L0.List_Previous, node);
154                 
155                 Resource newNode = g.newResource();
156                 g.claim(newNode, L0.InstanceOf, L0.List_Entry);
157                 g.claim(prev, L0.List_Next, L0.List_Previous, newNode);
158                 g.claim(newNode, L0.List_Next, L0.List_Previous, node);
159                 g.claim(newNode, L0.List_Element, val);
160                 return newNode;
161         }
162
163         private static void removeNode(WriteGraph g, final Layer0 L0, Resource node)
164                         throws NoSingleResultException, ManyObjectsForFunctionalRelationException, ServiceException {
165                 Resource prev = g.getSingleObject(node, L0.List_Previous);
166                 Resource next = g.getSingleObject(node, L0.List_Next);
167                 g.claim(prev, L0.List_Next, L0.List_Previous, next);
168                 g.deny(node);
169         }
170
171 }