@Override
    public boolean shouldKeepLeft(ServiceUnitStateData from, ServiceUnitStateData to) {
        if (to == null) {
            return false;
        }

        if (from != null) {
            if (from.versionId() == Long.MAX_VALUE && to.versionId() == Long.MIN_VALUE) { // overflow
            } else if (from.versionId() >= to.versionId()) {
                return true;
            } else if (from.versionId() < to.versionId() - 1) { // Compacted
                return false;
            } // else from.versionId() == to.versionId() - 1 // continue to check further
        }

        if (to.force()) {
            return false;
        }

        ServiceUnitState prevState = state(from);
        ServiceUnitState state = state(to);
        if (!ServiceUnitState.isValidTransition(prevState, state)) {
            return true;
        }

        if (checkBrokers) {
            switch (prevState) {
                case Owned:
                    switch (state) {
                        case Splitting:
                            return isNotBlank(to.dstBroker())
                                    || !from.dstBroker().equals(to.sourceBroker());
                        case Releasing:
                            return invalidUnload(from, to);
                    }
                case Assigning:
                    switch (state) {
                        case Owned:
                            return notEquals(from, to);
                    }
                case Releasing:
                    switch (state) {
                        case Assigning:
                            return isBlank(to.dstBroker()) || notEquals(from, to);
                        case Free:
                            return notEquals(from, to);
                    }
                case Splitting:
                    switch (state) {
                        case Deleted:
                            return notEquals(from, to);
                    }
                case Free:
                    switch (state) {
                        case Assigning:
                            return isNotBlank(to.sourceBroker()) || isBlank(to.dstBroker());
                    }
            }
        }
        return false;
    }
@Test
    public void testTransitionsAndBrokers() {

        assertTrue(strategy.shouldKeepLeft(data(Init), data2(Init)));
        assertFalse(strategy.shouldKeepLeft(data(Init), data2(Free)));
        assertFalse(strategy.shouldKeepLeft(data(Init), data2(Assigning)));
        assertFalse(strategy.shouldKeepLeft(data(Init), data2(Owned)));
        assertFalse(strategy.shouldKeepLeft(data(Init), data2(Releasing)));
        assertFalse(strategy.shouldKeepLeft(data(Init), data2(Splitting)));
        assertFalse(strategy.shouldKeepLeft(data(Init), data2(Deleted)));

        assertTrue(strategy.shouldKeepLeft(data(Assigning), data2(Init)));
        assertTrue(strategy.shouldKeepLeft(data(Assigning), data2(Free)));
        assertTrue(strategy.shouldKeepLeft(data(Assigning), data2(Assigning)));
        assertTrue(strategy.shouldKeepLeft(data(Assigning, "dst1"), data2(Owned, "dst2")));
        assertTrue(strategy.shouldKeepLeft(data(Assigning, dst), data2(Owned, src, dst)));
        assertFalse(strategy.shouldKeepLeft(data(Assigning, dst), data2(Owned, dst)));
        assertFalse(strategy.shouldKeepLeft(data(Assigning, src, dst), data2(Owned, src, dst)));
        assertTrue(strategy.shouldKeepLeft(data(Assigning, src, dst), data2(Releasing, dst)));
        assertTrue(strategy.shouldKeepLeft(data(Assigning, src, dst), data2(Releasing, src, dst)));
        assertTrue(strategy.shouldKeepLeft(data(Assigning), data2(Splitting, dst)));
        assertTrue(strategy.shouldKeepLeft(data(Assigning), data2(Deleted, dst)));

        assertTrue(strategy.shouldKeepLeft(data(Owned), data2(Init)));
        assertTrue(strategy.shouldKeepLeft(data(Owned), data2(Free)));
        assertTrue(strategy.shouldKeepLeft(data(Owned), data2(Assigning)));
        assertTrue(strategy.shouldKeepLeft(data(Owned), data2(Owned)));
        assertTrue(strategy.shouldKeepLeft(data(Owned), data2(Releasing, dst)));
        assertTrue(strategy.shouldKeepLeft(data(Owned, src, "dst1"), data2(Releasing, src, "dst2")));
        assertTrue(strategy.shouldKeepLeft(data(Owned, "dst1"), data2(Releasing, "dst2")));
        assertTrue(strategy.shouldKeepLeft(data(Owned, dst), data2(Releasing, dst)));
        assertTrue(strategy.shouldKeepLeft(data(Owned, src, dst), data2(Releasing, null, dst)));
        assertTrue(strategy.shouldKeepLeft(data(Owned, src, dst), data2(Releasing, src, null)));
        assertFalse(strategy.shouldKeepLeft(data(Owned, src, dst), data2(Releasing, dst, null)));
        assertTrue(strategy.shouldKeepLeft(data(Owned, src, "dst1"), data2(Releasing, src, "dst2")));
        assertTrue(strategy.shouldKeepLeft(data(Owned, "src1", dst), data2(Releasing, "src2", dst)));
        assertTrue(strategy.shouldKeepLeft(data(Owned, src, dst), data2(Releasing, src, dst)));
        assertFalse(strategy.shouldKeepLeft(data(Owned, src, dst), data2(Releasing, dst, "dst2")));
        assertTrue(strategy.shouldKeepLeft(data(Owned, src, "dst1"), data2(Splitting, src, "dst2")));
        assertTrue(strategy.shouldKeepLeft(data(Owned, "dst1"), data2(Splitting, "dst2")));
        assertFalse(strategy.shouldKeepLeft(data(Owned, dst), data2(Splitting, dst, null)));
        assertFalse(strategy.shouldKeepLeft(data(Owned, src, dst), data2(Splitting, dst, null)));
        assertTrue(strategy.shouldKeepLeft(data(Owned), data2(Deleted, dst)));

        assertTrue(strategy.shouldKeepLeft(data(Releasing), data2(Init)));
        assertFalse(strategy.shouldKeepLeft(data(Releasing), data2(Free)));
        assertTrue(strategy.shouldKeepLeft(data(Releasing, "dst1"), data2(Free, "dst2")));
        assertTrue(strategy.shouldKeepLeft(data(Releasing, "src1", dst), data2(Free, "src2", dst)));
        assertTrue(strategy.shouldKeepLeft(data(Releasing, src, "dst1"), data2(Assigning, src, "dst2")));
        assertTrue(strategy.shouldKeepLeft(data(Releasing, src, "dst1"), data2(Assigning, src, "dst2")));
        assertTrue(strategy.shouldKeepLeft(data(Releasing, "src1", dst), data2(Assigning, "src2", dst)));
        assertFalse(strategy.shouldKeepLeft(data(Releasing, src, dst), data2(Assigning, src, dst)));
        assertTrue(strategy.shouldKeepLeft(data(Releasing), data2(Owned)));
        assertTrue(strategy.shouldKeepLeft(data(Releasing), data2(Releasing)));
        assertTrue(strategy.shouldKeepLeft(data(Releasing), data2(Splitting)));
        assertTrue(strategy.shouldKeepLeft(data(Releasing), data2(Deleted, dst)));

        assertTrue(strategy.shouldKeepLeft(data(Splitting), data2(Init)));
        assertTrue(strategy.shouldKeepLeft(data(Splitting), data2(Free)));
        assertTrue(strategy.shouldKeepLeft(data(Splitting), data2(Assigning)));
        assertTrue(strategy.shouldKeepLeft(data(Splitting), data2(Owned)));
        assertTrue(strategy.shouldKeepLeft(data(Splitting), data2(Releasing)));
        assertTrue(strategy.shouldKeepLeft(data(Splitting), data2(Splitting)));
        assertTrue(strategy.shouldKeepLeft(data(Splitting, src, "dst1"), data2(Deleted, src, "dst2")));
        assertTrue(strategy.shouldKeepLeft(data(Splitting, "dst1"), data2(Deleted, "dst2")));
        assertTrue(strategy.shouldKeepLeft(data(Splitting, "src1", dst), data2(Deleted, "src2", dst)));
        assertFalse(strategy.shouldKeepLeft(data(Splitting, dst), data2(Deleted, dst)));
        assertFalse(strategy.shouldKeepLeft(data(Splitting, src, dst), data2(Deleted, src, dst)));

        assertFalse(strategy.shouldKeepLeft(data(Deleted), data2(Init)));
        assertTrue(strategy.shouldKeepLeft(data(Deleted), data2(Free)));
        assertTrue(strategy.shouldKeepLeft(data(Deleted), data2(Assigning)));
        assertTrue(strategy.shouldKeepLeft(data(Deleted), data2(Owned)));
        assertTrue(strategy.shouldKeepLeft(data(Deleted), data2(Releasing)));
        assertTrue(strategy.shouldKeepLeft(data(Deleted), data2(Splitting)));
        assertTrue(strategy.shouldKeepLeft(data(Deleted), data2(Deleted)));

        assertFalse(strategy.shouldKeepLeft(data(Free), data2(Init)));
        assertTrue(strategy.shouldKeepLeft(data(Free), data2(Free)));
        assertFalse(strategy.shouldKeepLeft(data(Free), data2(Assigning)));
        assertTrue(strategy.shouldKeepLeft(data(Free), data2(Assigning, src, dst)));
        assertTrue(strategy.shouldKeepLeft(data(Free), data2(Owned)));
        assertTrue(strategy.shouldKeepLeft(data(Free), data2(Releasing)));
        assertTrue(strategy.shouldKeepLeft(data(Free), data2(Splitting)));
        assertTrue(strategy.shouldKeepLeft(data(Free), data2(Deleted)));
    }