--- /dev/null
+package org.simantics.acorn.lru;
+
+import java.util.ArrayList;
+
+import org.simantics.acorn.ClusterManager;
+import org.simantics.acorn.internal.Change;
+import org.simantics.acorn.internal.ClusterChange;
+import org.simantics.db.procore.cluster.ClusterTraits;
+import org.simantics.db.service.ClusterUID;
+
+import gnu.trove.list.array.TByteArrayList;
+
+public class ClusterChangeSet {
+
+ public enum Type {
+ ADD,REMOVE,VALUE
+ }
+
+ public static class Entry {
+
+ final Type type;
+ final short subject;
+ final short predicate;
+ final short object;
+ final ClusterUID predicateUID;
+ final ClusterUID objectUID;
+ final boolean oldValueEx;
+ final byte[] oldValue;
+ final byte[] newValue;
+
+ public Entry(Type type, int subject, ClusterUID predicateUID, int predicate, ClusterUID objectUID, int object) {
+ this.type = type;
+ this.subject = (short)(subject & 0xFFF);
+ this.predicate = (short)predicate;
+ this.object = (short)object;
+ this.predicateUID = predicateUID;
+ this.objectUID = objectUID;
+ this.oldValueEx = false;
+ this.oldValue = null;
+ this.newValue = null;
+ }
+
+ public Entry(int subject, boolean oldValueEx, byte[] oldValue, byte[] newValue) {
+ if(oldValue == null && newValue == null)
+ throw new IllegalStateException();
+ this.type = Type.VALUE;
+ this.subject = (short)(subject & 0xFFF);
+ this.predicate = 0;
+ this.object = 0;
+ this.predicateUID = null;
+ this.objectUID = null;
+ this.oldValueEx = oldValueEx;
+ this.oldValue = oldValue;
+ this.newValue = newValue;
+ }
+
+ public void process(ClusterManager clusters, ClusterChange cs, int clusterKey) {
+
+ Entry e = this;
+
+ if(e.type == Type.VALUE) {
+
+ if(e.oldValue != null) {
+ cs.setValue(e.subject, e.oldValue, e.oldValue.length);
+ } else {
+ Change change = new Change();
+ change.addStatementIndex(e.subject, null, ClusterChange.DELETE_OPERATION);
+ cs.addChange(change);
+ }
+
+ } else if(e.type == Type.ADD) {
+
+ int s = ClusterTraits.createResourceKeyNoThrow(clusterKey, e.subject);
+ int p = clusters.getResourceKey(e.predicateUID, e.predicate);
+ int o = clusters.getResourceKey(e.objectUID, e.object);
+ Change change = new Change();
+ change.addStatementIndex(s, null, ClusterChange.REMOVE_OPERATION);
+ change.addStatementIndex(p, e.predicateUID, (byte)0);
+ change.addStatementIndex(o, e.objectUID, (byte)0);
+ cs.addChange(change);
+
+ } else if(e.type == Type.REMOVE) {
+
+ int s = ClusterTraits.createResourceKeyNoThrow(clusterKey, e.subject);
+ int p = clusters.getResourceKey(e.predicateUID, e.predicate);
+ int o = clusters.getResourceKey(e.objectUID, e.object);
+ Change change = new Change();
+ change.addStatementIndex(s, null, ClusterChange.ADD_OPERATION);
+ change.addStatementIndex(p, e.predicateUID, (byte)0);
+ change.addStatementIndex(o, e.objectUID, (byte)0);
+ cs.addChange(change);
+
+ }
+
+ }
+
+ }
+
+ final public String id;
+ final public ClusterUID cuid;
+ public String chunkKey;
+ public int chunkOffset = -1;
+
+ public TByteArrayList statementMask = new TByteArrayList();
+ public TByteArrayList oldValueEx = new TByteArrayList();
+ public ArrayList<byte[]> oldValues = new ArrayList<byte[]>();
+
+ public ClusterChangeSet(String id ,ClusterUID cuid) {
+ this.id = id;
+ this.cuid = cuid;
+ String[] ss = id.split("\\.");
+ chunkKey = ss[0];
+ chunkOffset = Integer.parseInt(ss[1]);
+ }
+
+ public ClusterStreamChunk getChunk(ClusterManager manager) {
+ return manager.streamLRU.get(chunkKey);
+ }
+
+}