MergeConflictType (@NotNull Predicate<? super ThreeSide> emptiness, @NotNull BiPredicate<? super ThreeSide, ? super ThreeSide> equality, @Nullable BiPredicate<? super ThreeSide, ? super ThreeSide> trueEquality, @NotNull BooleanSupplier conflictResolver) { boolean isLeftEmpty = emptiness.test(ThreeSide.LEFT); boolean isBaseEmpty = emptiness.test(ThreeSide.BASE); boolean isRightEmpty = emptiness.test(ThreeSide.RIGHT); assert !isLeftEmpty || !isBaseEmpty || !isRightEmpty; if (isBaseEmpty) { if (isLeftEmpty) { // --= return new MergeConflictType(MergeConflictType.Type.INSERTED, false, true); } else if (isRightEmpty) { // =-- return new MergeConflictType(MergeConflictType.Type.INSERTED, true, false); } else { // =-= boolean equalModifications = equality.test(ThreeSide.LEFT, ThreeSide.RIGHT); if (equalModifications) { return new MergeConflictType(MergeConflictType.Type.INSERTED, true, true); } else { return new MergeConflictType(MergeConflictType.Type.CONFLICT, true, true, false); } } } else { if (isLeftEmpty && isRightEmpty) { // -=- return new MergeConflictType(MergeConflictType.Type.DELETED, true, true); } else { // -==, ==-, === boolean unchangedLeft = equality.test(ThreeSide.BASE, ThreeSide.LEFT); boolean unchangedRight = equality.test(ThreeSide.BASE, ThreeSide.RIGHT); if (unchangedLeft && unchangedRight) { assert trueEquality != null; boolean trueUnchangedLeft = trueEquality.test(ThreeSide.BASE, ThreeSide.LEFT); boolean trueUnchangedRight = trueEquality.test(ThreeSide.BASE, ThreeSide.RIGHT); assert !trueUnchangedLeft || !trueUnchangedRight; return new MergeConflictType(MergeConflictType.Type.MODIFIED, !trueUnchangedLeft, !trueUnchangedRight); } if (unchangedLeft) return new MergeConflictType(isRightEmpty ? MergeConflictType.Type.DELETED : MergeConflictType.Type.MODIFIED, false, true); if (unchangedRight) return new MergeConflictType(isLeftEmpty ? MergeConflictType.Type.DELETED : MergeConflictType.Type.MODIFIED, true, false); boolean equalModifications = equality.test(ThreeSide.LEFT, ThreeSide.RIGHT); if (equalModifications) { return new MergeConflictType(MergeConflictType.Type.MODIFIED, true, true); } else { boolean canBeResolved = !isLeftEmpty && !isRightEmpty && conflictResolver.getAsBoolean(); return new MergeConflictType(MergeConflictType.Type.CONFLICT, true, true, canBeResolved); } } } }