X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.db.procore%2Fsrc%2Forg%2Fsimantics%2Fdb%2Fprocore%2Fcluster%2FCCSParser.java;fp=bundles%2Forg.simantics.db.procore%2Fsrc%2Forg%2Fsimantics%2Fdb%2Fprocore%2Fcluster%2FCCSParser.java;h=3e42d59303cc14494c97dd065799cb4b590b3207;hp=0000000000000000000000000000000000000000;hb=969bd23cab98a79ca9101af33334000879fb60c5;hpb=866dba5cd5a3929bbeae85991796acb212338a08 diff --git a/bundles/org.simantics.db.procore/src/org/simantics/db/procore/cluster/CCSParser.java b/bundles/org.simantics.db.procore/src/org/simantics/db/procore/cluster/CCSParser.java new file mode 100644 index 000000000..3e42d5930 --- /dev/null +++ b/bundles/org.simantics.db.procore/src/org/simantics/db/procore/cluster/CCSParser.java @@ -0,0 +1,237 @@ +package org.simantics.db.procore.cluster; + +import org.simantics.db.exception.RuntimeDatabaseException; +import org.simantics.db.procore.cluster.ClusterChangeSetI.Operation; +import org.simantics.db.procore.cluster.ClusterChangeSetI.OperationEnum; +import org.simantics.db.service.ClusterUID; + +class CCSParser { + private static boolean DEBUG = false; + enum StmEnum { + Add, + Remove + }; + enum ReferenceType { + Local, + ForeignShort, + ForeignLong + }; + static class Args { + ClusterUID clusterUID; + ForeignTable rft; + Operation rop; + Args(ClusterUID clusterUID, ForeignTable rft, Operation rop) { + this.clusterUID = clusterUID; + this.rft = rft; + this.rop = rop; + } + void createResource(short aRI) { + rop.type = OperationEnum.CreateResource; + rop.count = 1; + rop.resourceIndex = aRI; + } + void addRelation(short aRI, short aPI, ClusterUID aPC, short aOI, ClusterUID aOC) { + rop.type = OperationEnum.AddRelation; + rop.count = 5; + rop.resourceIndex = aRI; + rop.predicateIndex = aPI; + rop.predicateCluster = aPC; + rop.objectIndex = aOI; + rop.objectCluster = aOC; + } + void removeRelation(short aRI, short aPI, ClusterUID aPC, short aOI, ClusterUID aOC) { + rop.type = OperationEnum.RemoveRelation; + rop.count = 5; + rop.resourceIndex = aRI; + rop.predicateIndex = aPI; + rop.predicateCluster = aPC; + rop.objectIndex = aOI; + rop.objectCluster = aOC; + } + void setValue(short aRI, byte[] apValueData, int valueStart, int aValueSize) { + rop.type = OperationEnum.SetValue; + rop.count = 4; + rop.resourceIndex = aRI; + rop.valueSize = aValueSize; + rop.valueData = apValueData; + rop.valueStart = valueStart; + } + void deleteValue(short aRI) { + rop.type = OperationEnum.DeleteValue; + rop.count = 1; + rop.resourceIndex = aRI; + } + void modifyValue(short aRI, long aOffset, int aSize, byte[] apValue, int valueStart) { + rop.type = OperationEnum.ModifyValue; + rop.count = 5; + rop.resourceIndex = aRI; + rop.valueOffset = aOffset; + rop.valueSize = aSize; + rop.valueData = apValue; + rop.valueStart = valueStart; + } + } + private static class Data { + short resource; + ClusterUID clusterUID; + boolean left; + Data() { + resource = 0; + clusterUID = ClusterUID.Null; + left = false; + } + } + static class ForeignTable { + ForeignTable() { + init(); + } + void init() { + mSize = 0; + } + boolean get(short key, Data data) { + if (key < mSize) { + data.resource = mTable[key].resource; + data.clusterUID = mTable[key].clusterUID; + data.left = mTable[key].left; + return true; + } + return false; + } + void getOrThrow(short key, Data data) { + if (key < mSize) { + data.resource = mTable[key].resource; + data.clusterUID = mTable[key].clusterUID; + data.left = mTable[key].left; + } else + new IllegalArgumentException("Missing foreign table entry for key=" + key + "."); + } + // cid is just for debugging + void put(ClusterUID clusterUID, final Data data) { + if (mSize <256) { + if (DEBUG) + System.out.println("ft put c=" + clusterUID + " i=" + mSize + " r=" + data.resource + + " rc=" + data.clusterUID); + if (data.resource == 0) + throw new RuntimeDatabaseException("Resource can not be zero."); + if (data.clusterUID.equals(ClusterUID.Null)) + throw new RuntimeDatabaseException("Cluster can not be zero."); + mTable[mSize++] = data; + } + } + private Data[] mTable = new Data[256]; + private int mSize; + } + static int parseStm(StmEnum stmEnum, Args args, byte[] bytes, int ap, + int aBits, // number of bits used from operation code + ReferenceType aPredicate, ReferenceType aObject) { + assert(aBits <= 6); + byte left = (byte)(6 - aBits); + short ri = (short)((bytes[ap] & (1< 0) { // middle index bits + b = (short)(bytes[ap++] & 0xFF); + l = 8; + byte t = (byte)b; + t &= (1<>= left; // skip used + } + GetLeftArgs a = new GetLeftArgs(ap, b, l); + getLeft(args.clusterUID, args.rft, bytes, pdata, a); + getLeft(args.clusterUID, args.rft, bytes, odata, a); + ap = a.p; + if (DEBUG) + System.out.println("" + stmEnum + " r=" + ri + " rc=" + args.clusterUID + + " p=" + pdata.resource + " pc=" + pdata.clusterUID + + " o=" + odata.resource + " oc=" + odata.clusterUID); + if (ClusterUID.Null.equals(args.clusterUID) || ClusterUID.Null.equals(pdata.clusterUID) || ClusterUID.Null.equals(odata.clusterUID)) + throw new RuntimeDatabaseException("Illegal cluster uid. args=" + args); + switch (stmEnum) { + case Add: + args.addRelation(ri, + pdata.resource, pdata.clusterUID, + odata.resource, odata.clusterUID); + break; + case Remove: + args.removeRelation(ri, pdata.resource, pdata.clusterUID, odata.resource, odata.clusterUID); + break; + default: + new RuntimeException("Internal error. Contact application support."); + } + return ap; + } + private static class GetLeftArgs { + GetLeftArgs(int p, short b, byte l) { + this.p = p; + this.b = b; + this.l = l; + } + int p; + short b; + byte l; + } + private static void getLeft(ClusterUID aClusterUID, ForeignTable rft, byte[] bytes, + Data rdata, GetLeftArgs a) { + if (rdata.left) { + if (a.l < 6) { + a.b |= ((bytes[a.p] & 0xFF) << a.l); // next 8 bits + ++a.p; + a.l += 8; + } + byte t = (byte)a.b; + t &= 0x3F; + rdata.resource |= t << 8; // top bits + rdata.left = false; // just for debugging + if (rdata.clusterUID != aClusterUID) + rft.put(aClusterUID, rdata); + a.b >>>= 6; // skip used bits + a.l -= 6; + } else // ForeignShort + rft.getOrThrow(rdata.resource, rdata); + } + private static int getData(ClusterUID aClusterUID, ForeignTable ft, byte[] bytes, int rp, ReferenceType a, Data rdata) { + switch (a) { + default: + throw new IllegalArgumentException("Illegal enumeration value=" + a + "."); + case Local: + rdata.resource = (short)(bytes[rp] & 0xFF); // low byte + rdata.clusterUID = aClusterUID; + rdata.left = true; + rp += 1; + break; + case ForeignShort: + rdata.resource = (short)(bytes[rp] & 0xFF); // index to foreign table + rdata.left = false; + rp += 1; + break; + case ForeignLong: + rdata.clusterUID = ClusterUID.make(bytes, rp); + rp += ClusterUID.getLongLength() * 8; + rdata.resource = (short)(bytes[rp] & 0xFF); // low byte + rdata.left = true; + rp += 1; + break; + } + return rp; + } + static long getLongN(byte[] bytes, int offset, int size) { + long l = 0; + for (int i=0, shift=0; i