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