]> gerrit.simantics Code Review - simantics/interop.git/blob - org.simantics.interop.update/src/org/simantics/interop/update/model/UpdateOperations.java
Process changes in smaller chunks
[simantics/interop.git] / org.simantics.interop.update / src / org / simantics / interop / update / model / UpdateOperations.java
1 package org.simantics.interop.update.model;
2
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 import java.util.List;
6 import java.util.Map;
7 import java.util.Stack;
8
9 import org.eclipse.core.runtime.IProgressMonitor;
10 import org.simantics.db.ReadGraph;
11 import org.simantics.db.Resource;
12 import org.simantics.db.Session;
13 import org.simantics.db.Statement;
14 import org.simantics.db.VirtualGraph;
15 import org.simantics.db.WriteGraph;
16 import org.simantics.db.common.request.ReadRequest;
17 import org.simantics.db.common.request.WriteRequest;
18 import org.simantics.db.exception.DatabaseException;
19 import org.simantics.interop.test.GraphChanges;
20
21 /**
22  * 
23  * @author Marko Luukkainen <marko.luukkainen@vtt.fi>
24  *
25  */
26 public abstract  class UpdateOperations {
27         
28         private List<UpdateOp> operations = new ArrayList<UpdateOp>();
29         private Map<Resource, UpdateOp> resourceMap = new HashMap<Resource, UpdateOp>();
30         private Map<Statement, UpdateOp> statementMap = new HashMap<Statement, UpdateOp>();
31         private GraphChanges changes;
32         private int chunkSize = -1;
33         
34         public UpdateOperations(GraphChanges changes) {
35                 this.changes = changes; 
36         }
37         
38         public UpdateOp getUpdateOp(Resource r) {
39                 return resourceMap.get(r);
40         }
41         
42         public UpdateOp getUpdateOp(Statement s) {
43                 return statementMap.get(s);
44         }
45         
46         public int getChunkSize() {
47                 return chunkSize;
48         }
49         
50         public void setChunkSize(int chunkSize) {
51                 this.chunkSize = chunkSize;
52         }
53         
54         /**
55          * Applies all changes.
56          * 
57          * @param graph
58          * @throws DatabaseException
59          */
60         public void applyAll(WriteGraph graph) throws DatabaseException {
61                 List<UpdateOp> list = operations;
62                 apply(graph, list);
63         }
64
65         /**
66          * Applies selected changes.
67          * @param graph
68          * @throws DatabaseException
69          */
70         public void applySelected(WriteGraph graph) throws DatabaseException {
71                 List<UpdateOp> list = new ArrayList<UpdateOp>();
72                 for (UpdateOp op : operations) {
73                         if (op.selected())
74                                 list.add(op);
75                 }
76                 apply(graph, list);
77         }
78         
79         /**
80          * Applies all changes with chunked DB writes.
81          * 
82          * @param session
83          * @throws DatabaseException
84          */
85         public void applyAll(Session session, VirtualGraph vg) throws DatabaseException {
86                 List<UpdateOp> list = operations;
87                 apply(session, list, vg);
88         }
89
90         /**
91          * Applies selected changes with chunked DB writes.
92          * 
93          * @param session
94          * @throws DatabaseException
95          */
96         public void applySelected(Session session, VirtualGraph vg) throws DatabaseException {
97                 List<UpdateOp> list = new ArrayList<UpdateOp>();
98                 for (UpdateOp op : operations) {
99                         if (op.selected())
100                                 list.add(op);
101                 }
102                 apply(session, list, vg);
103         }
104         
105         protected void apply(WriteGraph graph, List<UpdateOp> list) throws DatabaseException {
106                 for (UpdateOp op : list) {
107                         apply(graph, op);
108                 }
109         }
110         
111         protected void apply(Session session, List<UpdateOp> list, VirtualGraph vg) throws DatabaseException {
112                 if (getChunkSize() > 0) {
113                         for (int s = 0; s < list.size(); ) {
114                                 int e = s + getChunkSize();
115                                 if (e > list.size())
116                                         e = list.size();
117                                 List<UpdateOp> subList = list.subList(s, e);
118                                 session.syncRequest(new WriteRequest(vg) {
119                                         
120                                         @Override
121                                         public void perform(WriteGraph graph) throws DatabaseException {
122                                                 
123                                                 for (UpdateOp op : subList) {
124                                                         apply(graph, op);
125                                                 }
126                                         }
127                                 });
128                                 s = e;
129                         }
130                 } else {
131                         session.syncRequest(new WriteRequest(vg) {
132                                 
133                                 @Override
134                                 public void perform(WriteGraph graph) throws DatabaseException {
135                                         
136                                         for (UpdateOp op : list) {
137                                                 apply(graph, op);
138                                         }
139                                 }
140                         });
141                 }
142         }
143         
144         public List<UpdateOp> getOperations() {
145                 return operations;
146         }
147         
148         public GraphChanges getChanges() {
149                 return changes;
150         }
151         
152         public Map<Resource, UpdateOp> getResourceMap() {
153                 return resourceMap;
154         }
155         
156         public Map<Statement, UpdateOp> getStatementMap() {
157                 return statementMap;
158         }
159
160         private void apply(WriteGraph g, UpdateOp op) throws DatabaseException {
161                 Stack<UpdateOp> stack = new Stack<UpdateOp>();
162                 _apply(g, stack, op);
163         }
164         
165         private void _apply(WriteGraph g, Stack<UpdateOp> stack, UpdateOp op) throws DatabaseException {
166                 if (op.applied())
167                         return;
168                 if (stack.contains(op)) {
169                         op.apply(g);
170                         return;
171                 }
172                 stack.push(op);
173                 for (UpdateOp pop : op.getParentOps())
174                     if (op.requiresOp(pop)) {
175                 if (!pop.applied())
176                     _apply(g, stack, pop);
177         } 
178                 for (UpdateOp sop : op.getSubOps())
179                     if (op.requiresOp(sop)) {
180                 if (!sop.applied())
181                     _apply(g, stack, sop);
182         }
183                 stack.pop();
184                 op.apply(g);
185         }
186
187         protected List<UpdateOp> getOps() {
188                 List<UpdateOp> list = new ArrayList<UpdateOp>(operations.size());
189                 list.addAll(operations);
190                 return list;
191         }
192         
193         protected void addOp(Resource r, UpdateOp op) {
194                 resourceMap.put(r, op);
195                 operations.add(op);
196         }
197         
198         protected void addOp(Statement s, UpdateOp op) {
199                 statementMap.put(s, op);
200                 operations.add(op);
201         }
202         
203         protected void replaceOp(Resource r, UpdateOp op) {
204                 UpdateOp oldOp = resourceMap.remove(r);
205                 if (oldOp != null) {
206                         operations.remove(oldOp);
207                 }
208                 resourceMap.put(r, op);
209                 operations.add(op);
210         }
211         
212         protected UpdateOp getOP(Resource r) {
213                 return resourceMap.get(r);
214         }
215         
216         protected UpdateOp getOP(Statement r) {
217                 return statementMap.get(r);
218         }
219
220         public abstract void populate(ReadGraph g) throws DatabaseException;
221         
222         /**
223          * Secondary populate method. Override this for chunked DB operations.  
224          * @param session
225          * @throws DatabaseException
226          */
227         public void populate(Session session, IProgressMonitor monitor) throws DatabaseException {
228                 session.syncRequest(new ReadRequest() {
229                         
230                         @Override
231                         public void run(ReadGraph graph) throws DatabaseException {
232                                 populate(graph);
233                         }
234                 });
235         }
236         
237         protected boolean compares(Resource r1, Resource r2) {
238                 if (r1.equals(r2))
239                         return true;
240                 if (changes.getComparable().contains(r1, r2))
241                         return true;
242                 return false;
243         }
244
245 }