Removed contact application support prints
[simantics/platform.git] / bundles / org.simantics.db.procore / src / org / simantics / db / procore / cluster / CCSParser.java
1 package org.simantics.db.procore.cluster;
2
3 import org.simantics.db.exception.RuntimeDatabaseException;
4 import org.simantics.db.procore.cluster.ClusterChangeSetI.Operation;
5 import org.simantics.db.procore.cluster.ClusterChangeSetI.OperationEnum;
6 import org.simantics.db.service.ClusterUID;
7
8 class CCSParser {
9     private static boolean DEBUG = false;
10     enum StmEnum {
11         Add,
12         Remove
13     };
14     enum ReferenceType {
15         Local,
16         ForeignShort,
17         ForeignLong
18     };
19     static class Args {
20         ClusterUID clusterUID;
21         ForeignTable rft;
22         Operation rop;
23         Args(ClusterUID clusterUID, ForeignTable rft, Operation rop) {
24             this.clusterUID = clusterUID;
25             this.rft = rft;
26             this.rop = rop;
27         }
28         void createResource(short aRI) {
29             rop.type = OperationEnum.CreateResource;
30             rop.count = 1;
31             rop.resourceIndex = aRI;
32         }
33         void addRelation(short aRI, short aPI, ClusterUID aPC, short aOI, ClusterUID aOC) {
34             rop.type = OperationEnum.AddRelation;
35             rop.count = 5;
36             rop.resourceIndex = aRI;
37             rop.predicateIndex = aPI;
38             rop.predicateCluster = aPC;
39             rop.objectIndex = aOI;
40             rop.objectCluster = aOC;
41         }
42         void removeRelation(short aRI, short aPI, ClusterUID aPC, short aOI, ClusterUID aOC) {
43             rop.type = OperationEnum.RemoveRelation;
44             rop.count = 5;
45             rop.resourceIndex = aRI;
46             rop.predicateIndex = aPI;
47             rop.predicateCluster = aPC;
48             rop.objectIndex = aOI;
49             rop.objectCluster = aOC;
50         }
51         void setValue(short aRI, byte[] apValueData, int valueStart, int aValueSize) {
52             rop.type = OperationEnum.SetValue;
53             rop.count = 4;
54             rop.resourceIndex = aRI;
55             rop.valueSize = aValueSize;
56             rop.valueData = apValueData;
57             rop.valueStart = valueStart;
58         }
59         void deleteValue(short aRI) {
60             rop.type = OperationEnum.DeleteValue;
61             rop.count = 1;
62             rop.resourceIndex = aRI;
63         }
64         void modifyValue(short aRI, long aOffset, int aSize, byte[] apValue, int valueStart) {
65             rop.type = OperationEnum.ModifyValue;
66             rop.count = 5;
67             rop.resourceIndex = aRI;
68             rop.valueOffset = aOffset;
69             rop.valueSize = aSize;
70             rop.valueData = apValue;
71             rop.valueStart = valueStart;
72         }
73     }
74     private static class Data {
75         short resource;
76         ClusterUID clusterUID;
77         boolean left;
78         Data() {
79             resource = 0;
80             clusterUID = ClusterUID.Null;
81             left = false;
82         }
83     }
84     static class ForeignTable {
85         ForeignTable() {
86             init();
87         }
88         void init() {
89             mSize = 0;
90         }
91         boolean get(short key, Data data) {
92             if (key < mSize) {
93                 data.resource = mTable[key].resource;
94                 data.clusterUID = mTable[key].clusterUID;
95                 data.left = mTable[key].left;
96                 return true;
97             }
98             return false;
99         }
100         void getOrThrow(short key, Data data) {
101             if (key < mSize) {
102                 data.resource = mTable[key].resource;
103                 data.clusterUID = mTable[key].clusterUID;
104                 data.left = mTable[key].left;
105             } else
106                 new IllegalArgumentException("Missing foreign table entry for key=" + key + ".");
107         }
108         // cid is just for debugging
109         void put(ClusterUID clusterUID, final Data data) {
110             if (mSize <256) {
111                 if (DEBUG)
112                     System.out.println("ft put c=" + clusterUID + " i=" + mSize + " r=" + data.resource
113                             + " rc=" + data.clusterUID);
114                 if (data.resource == 0)
115                     throw new RuntimeDatabaseException("Resource can not be zero.");
116                 if (data.clusterUID.equals(ClusterUID.Null))
117                     throw new RuntimeDatabaseException("Cluster can not be zero.");
118                 mTable[mSize++] = data;
119             }
120         }
121         private Data[] mTable = new Data[256];
122         private int mSize;
123     }
124     static int parseStm(StmEnum stmEnum, Args args, byte[] bytes, int ap,
125         int aBits, // number of bits used from operation code
126         ReferenceType aPredicate, ReferenceType aObject) {
127         assert(aBits <= 6);
128         byte left = (byte)(6 - aBits);
129         short ri = (short)((bytes[ap] & (1<<aBits)-1) << (8+left)); // top reference bits
130         Data pdata = new Data();
131         ap = getData(args.clusterUID, args.rft, bytes, ++ap, aPredicate, pdata);
132         Data odata = new Data();
133         ap = getData(args.clusterUID, args.rft, bytes, ap, aObject, odata);
134         ri |= bytes[ap++] & 0xFF;
135         short b = 0;
136         byte l = 0;
137         if (left > 0) { // middle index bits
138             b = (short)(bytes[ap++] & 0xFF);
139             l = 8;
140             byte t = (byte)b;
141             t &= (1<<left)-1;
142             ri |= t << 8;
143             l -= left;
144             b >>= left; // skip used
145         }
146         GetLeftArgs a = new GetLeftArgs(ap, b, l);
147         getLeft(args.clusterUID, args.rft, bytes, pdata, a);
148         getLeft(args.clusterUID, args.rft, bytes, odata, a);
149         ap = a.p;
150         if (DEBUG)
151             System.out.println("" + stmEnum + " r=" + ri + " rc=" + args.clusterUID +
152                     " p=" + pdata.resource + " pc=" + pdata.clusterUID +
153                     " o=" + odata.resource + " oc=" + odata.clusterUID);
154         if (ClusterUID.Null.equals(args.clusterUID) || ClusterUID.Null.equals(pdata.clusterUID) || ClusterUID.Null.equals(odata.clusterUID))
155             throw new RuntimeDatabaseException("Illegal cluster uid. args=" + args);
156         switch (stmEnum) {
157             case Add:
158                 args.addRelation(ri,
159                         pdata.resource, pdata.clusterUID,
160                         odata.resource, odata.clusterUID);
161                 break;
162             case Remove:
163                 args.removeRelation(ri, pdata.resource, pdata.clusterUID, odata.resource, odata.clusterUID);
164                 break;
165             default:
166                 new RuntimeException("Internal error, unrecognized StmEnum value encountered: " + stmEnum);
167         }
168         return ap;
169     }
170     private static class GetLeftArgs {
171         GetLeftArgs(int p, short b, byte l) {
172             this.p = p;
173             this.b = b;
174             this.l = l;
175         }
176         int p;
177         short b;
178         byte l;
179     }
180     private static void getLeft(ClusterUID aClusterUID, ForeignTable rft, byte[] bytes,
181         Data rdata, GetLeftArgs a) {
182         if (rdata.left) {
183             if (a.l < 6) {
184                 a.b |= ((bytes[a.p] & 0xFF) << a.l); // next 8 bits
185                 ++a.p;
186                 a.l += 8;
187             }
188             byte t = (byte)a.b;
189             t &= 0x3F;
190             rdata.resource |= t << 8; // top bits
191             rdata.left = false; // just for debugging
192             if (rdata.clusterUID != aClusterUID)
193                 rft.put(aClusterUID, rdata);
194             a.b >>>= 6; // skip used bits
195             a.l -= 6;
196         } else // ForeignShort
197             rft.getOrThrow(rdata.resource, rdata);
198     }
199     private static int getData(ClusterUID aClusterUID, ForeignTable ft, byte[] bytes, int rp, ReferenceType a, Data rdata) {
200         switch (a) {
201             default: 
202                 throw new IllegalArgumentException("Illegal enumeration value=" + a + ".");
203             case Local:
204                 rdata.resource = (short)(bytes[rp] & 0xFF); // low byte
205                 rdata.clusterUID = aClusterUID;
206                 rdata.left = true;
207                 rp += 1;
208                 break;
209             case ForeignShort:
210                 rdata.resource = (short)(bytes[rp] & 0xFF); // index to foreign table
211                 rdata.left = false;
212                 rp += 1;
213                 break;
214             case ForeignLong:
215                 rdata.clusterUID = ClusterUID.make(bytes, rp);
216                 rp += ClusterUID.getLongLength() * 8;
217                 rdata.resource = (short)(bytes[rp] & 0xFF); // low byte
218                 rdata.left = true;
219                 rp += 1;
220                 break;
221         }
222         return rp;
223     }
224     static long getLongN(byte[] bytes, int offset, int size) {
225         long l = 0;
226         for (int i=0, shift=0; i<size; ++i, ++offset, shift+=8) {
227             l |= (bytes[offset] & 0xFF) << shift;
228         }
229         return l;
230     }
231     static short getShort(byte[] bytes, int offset) {
232         return (short)getLongN(bytes, offset, 2);
233     }
234     static int getInt(byte[] bytes, int offset) {
235         return (int)getLongN(bytes, offset, 4);
236     }
237 }