1 package org.simantics.db.procore.cluster;
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;
9 private static boolean DEBUG = false;
20 ClusterUID clusterUID;
23 Args(ClusterUID clusterUID, ForeignTable rft, Operation rop) {
24 this.clusterUID = clusterUID;
28 void createResource(short aRI) {
29 rop.type = OperationEnum.CreateResource;
31 rop.resourceIndex = aRI;
33 void addRelation(short aRI, short aPI, ClusterUID aPC, short aOI, ClusterUID aOC) {
34 rop.type = OperationEnum.AddRelation;
36 rop.resourceIndex = aRI;
37 rop.predicateIndex = aPI;
38 rop.predicateCluster = aPC;
39 rop.objectIndex = aOI;
40 rop.objectCluster = aOC;
42 void removeRelation(short aRI, short aPI, ClusterUID aPC, short aOI, ClusterUID aOC) {
43 rop.type = OperationEnum.RemoveRelation;
45 rop.resourceIndex = aRI;
46 rop.predicateIndex = aPI;
47 rop.predicateCluster = aPC;
48 rop.objectIndex = aOI;
49 rop.objectCluster = aOC;
51 void setValue(short aRI, byte[] apValueData, int valueStart, int aValueSize) {
52 rop.type = OperationEnum.SetValue;
54 rop.resourceIndex = aRI;
55 rop.valueSize = aValueSize;
56 rop.valueData = apValueData;
57 rop.valueStart = valueStart;
59 void deleteValue(short aRI) {
60 rop.type = OperationEnum.DeleteValue;
62 rop.resourceIndex = aRI;
64 void modifyValue(short aRI, long aOffset, int aSize, byte[] apValue, int valueStart) {
65 rop.type = OperationEnum.ModifyValue;
67 rop.resourceIndex = aRI;
68 rop.valueOffset = aOffset;
69 rop.valueSize = aSize;
70 rop.valueData = apValue;
71 rop.valueStart = valueStart;
74 private static class Data {
76 ClusterUID clusterUID;
80 clusterUID = ClusterUID.Null;
84 static class ForeignTable {
91 boolean get(short key, Data data) {
93 data.resource = mTable[key].resource;
94 data.clusterUID = mTable[key].clusterUID;
95 data.left = mTable[key].left;
100 void getOrThrow(short key, Data data) {
102 data.resource = mTable[key].resource;
103 data.clusterUID = mTable[key].clusterUID;
104 data.left = mTable[key].left;
106 new IllegalArgumentException("Missing foreign table entry for key=" + key + ".");
108 // cid is just for debugging
109 void put(ClusterUID clusterUID, final Data data) {
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;
121 private Data[] mTable = new Data[256];
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) {
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;
137 if (left > 0) { // middle index bits
138 b = (short)(bytes[ap++] & 0xFF);
144 b >>= left; // skip used
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);
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);
159 pdata.resource, pdata.clusterUID,
160 odata.resource, odata.clusterUID);
163 args.removeRelation(ri, pdata.resource, pdata.clusterUID, odata.resource, odata.clusterUID);
166 new RuntimeException("Internal error. Contact application support.");
170 private static class GetLeftArgs {
171 GetLeftArgs(int p, short b, byte l) {
180 private static void getLeft(ClusterUID aClusterUID, ForeignTable rft, byte[] bytes,
181 Data rdata, GetLeftArgs a) {
184 a.b |= ((bytes[a.p] & 0xFF) << a.l); // next 8 bits
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
196 } else // ForeignShort
197 rft.getOrThrow(rdata.resource, rdata);
199 private static int getData(ClusterUID aClusterUID, ForeignTable ft, byte[] bytes, int rp, ReferenceType a, Data rdata) {
202 throw new IllegalArgumentException("Illegal enumeration value=" + a + ".");
204 rdata.resource = (short)(bytes[rp] & 0xFF); // low byte
205 rdata.clusterUID = aClusterUID;
210 rdata.resource = (short)(bytes[rp] & 0xFF); // index to foreign table
215 rdata.clusterUID = ClusterUID.make(bytes, rp);
216 rp += ClusterUID.getLongLength() * 8;
217 rdata.resource = (short)(bytes[rp] & 0xFF); // low byte
224 static long getLongN(byte[] bytes, int offset, int size) {
226 for (int i=0, shift=0; i<size; ++i, ++offset, shift+=8) {
227 l |= (bytes[offset] & 0xFF) << shift;
231 static short getShort(byte[] bytes, int offset) {
232 return (short)getLongN(bytes, offset, 2);
234 static int getInt(byte[] bytes, int offset) {
235 return (int)getLongN(bytes, offset, 4);