Skip to content

Commit bceb1d6

Browse files
committed
Always assert the correctness of graph operations
1 parent 9091fb6 commit bceb1d6

7 files changed

Lines changed: 54 additions & 70 deletions

File tree

src/main/java/org/variantsync/diffdetective/util/Assert.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,14 @@ public static void assertFalse(boolean condition) {
6868
assertTrue(!condition);
6969
}
7070

71+
public static void assertFalse(boolean condition, final Supplier<String> errorMessage) {
72+
assertTrue(!condition, errorMessage);
73+
}
74+
75+
public static void assertFalse(boolean condition, String errorMessage) {
76+
assertTrue(!condition, errorMessage);
77+
}
78+
7179
/** Throws {@link AssertionError} with {@code errorMessage} as error message. */
7280
public static void fail(String errorMessage) {
7381
throw new AssertionError(errorMessage);

src/main/java/org/variantsync/diffdetective/variation/diff/DiffNode.java

Lines changed: 33 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -231,30 +231,20 @@ public int getChangeAmount(Time time) {
231231
return getParent(time).getChangeAmount(time);
232232
}
233233

234-
/**
235-
* Sets the parent at {@code time} checking that this node doesn't currently have a parent.
236-
*/
237-
private void setParent(final DiffNode newParent, Time time) {
238-
Assert.assertTrue(getParent(time) == null);
239-
parents[time.ordinal()] = newParent;
240-
}
241-
242234
/**
243235
* Adds this subtree below the given parents.
244236
* Inverse of drop.
245237
* @param newBeforeParent Node that should be this node's before parent. May be null.
246238
* @param newAfterParent Node that should be this node's after parent. May be null.
247239
* @return True iff this node could be added as child to at least one of the given non-null parents.
248240
*/
249-
public boolean addBelow(final DiffNode newBeforeParent, final DiffNode newAfterParent) {
250-
boolean success = false;
251-
if (newBeforeParent != null) {
252-
success |= newBeforeParent.addChild(this, BEFORE);
241+
public void addBelow(final DiffNode newBeforeParent, final DiffNode newAfterParent) {
242+
if (getDiffType().existsAtTime(BEFORE) && newBeforeParent != null) {
243+
newBeforeParent.addChild(this, BEFORE);
253244
}
254-
if (newAfterParent != null) {
255-
success |= newAfterParent.addChild(this, AFTER);
245+
if (getDiffType().existsAtTime(AFTER) && newAfterParent != null) {
246+
newAfterParent.addChild(this, AFTER);
256247
}
257-
return success;
258248
}
259249

260250
/**
@@ -263,25 +253,19 @@ public boolean addBelow(final DiffNode newBeforeParent, final DiffNode newAfterP
263253
*/
264254
public void drop() {
265255
Time.forAll(time -> {
266-
drop(time);
256+
if (getParent(time) != null) {
257+
drop(time);
258+
}
267259
});
268260
}
269261

270262
/**
271263
* Removes this subtree from its parents at the time {@code time}.
272264
*/
273265
public void drop(Time time) {
274-
if (getParent(time) != null) {
275-
getParent(time).removeChild(this, time);
276-
}
277-
}
266+
Assert.assertTrue(getParent(time) != null);
278267

279-
/**
280-
* Remove this node as the parent of {@code child} but it doesn't change {@link children}.
281-
*/
282-
private void dropChild(final DiffNode child, Time time) {
283-
Assert.assertTrue(child.getParent(time) == this);
284-
child.parents[time.ordinal()] = null;
268+
getParent(time).removeChild(this, time);
285269
}
286270

287271
/**
@@ -295,34 +279,26 @@ public int indexOfChild(final DiffNode child, Time time) {
295279
/**
296280
* Insert {@code child} as child at the time {@code time} at the position {@code index}.
297281
*/
298-
public boolean insertChild(final DiffNode child, int index, Time time) {
299-
if (child.getDiffType().existsAtTime(time)) {
300-
if (child.getParent(time) != null) {
301-
throw new IllegalArgumentException("Given child " + child + " already has a " + time + " parent (" + child.getParent(time) + ")!");
302-
}
282+
public void insertChild(final DiffNode child, int index, Time time) {
283+
Assert.assertTrue(child.getDiffType().existsAtTime(time));
284+
Assert.assertFalse(isChild(child, time), () ->
285+
"Given child " + child + " already has a " + time + " parent (" + child.getParent(time) + ")!");
303286

304-
children[time.ordinal()].add(index, child);
305-
child.setParent(this, time);
306-
return true;
307-
}
308-
return false;
287+
children[time.ordinal()].add(index, child);
288+
child.parents[time.ordinal()] = this;
309289
}
310290

311291
/**
312292
* The same as {@link DiffNode#insertChild} but puts the node at the end of the children
313293
* list instead of inserting it at a specific index.
314294
*/
315-
public boolean addChild(final DiffNode child, Time time) {
316-
if (child.getDiffType().existsAtTime(time)) {
317-
if (child.getParent(time) != null) {
318-
throw new IllegalArgumentException("Given child " + child + " already has a " + time + " parent (" + child.getParent(time) + ")!");
319-
}
295+
public void addChild(final DiffNode child, Time time) {
296+
Assert.assertTrue(child.getDiffType().existsAtTime(time));
297+
Assert.assertFalse(isChild(child, time), () ->
298+
"Given child " + child + " already has a " + time + " parent (" + child.getParent(time) + ")!");
320299

321-
children[time.ordinal()].add(child);
322-
child.setParent(this, time);
323-
return true;
324-
}
325-
return false;
300+
children[time.ordinal()].add(child);
301+
child.parents[time.ordinal()] = this;
326302
}
327303

328304
/**
@@ -343,13 +319,11 @@ public void addChildren(final Collection<DiffNode> children, Time time) {
343319
* @param time whether {@code child} should be removed before or after the edit
344320
* @return True iff the child was removed, false iff it's not a child at {@code time}.
345321
*/
346-
public boolean removeChild(final DiffNode child, Time time) {
347-
if (isChild(child, time)) {
348-
dropChild(child, time);
349-
children[time.ordinal()].remove(child);
350-
return true;
351-
}
352-
return false;
322+
public void removeChild(final DiffNode child, Time time) {
323+
Assert.assertTrue(isChild(child, time));
324+
325+
child.parents[time.ordinal()] = null;
326+
children[time.ordinal()].remove(child);
353327
}
354328

355329
/**
@@ -359,7 +333,11 @@ public boolean removeChild(final DiffNode child, Time time) {
359333
*/
360334
public void removeChildren(final Collection<DiffNode> childrenToRemove) {
361335
for (final DiffNode childToRemove : childrenToRemove) {
362-
Time.forAll(time -> removeChild(childToRemove, time));
336+
Time.forAll(time -> {
337+
if (isChild(childToRemove, time)) {
338+
removeChild(childToRemove, time);
339+
}
340+
});
363341
}
364342
}
365343

@@ -371,7 +349,7 @@ public void removeChildren(final Collection<DiffNode> childrenToRemove) {
371349
*/
372350
public List<DiffNode> removeChildren(Time time) {
373351
for (var child : children[time.ordinal()]) {
374-
dropChild(child, time);
352+
child.parents[time.ordinal()] = null;
375353
}
376354

377355
final List<DiffNode> orphans = children[time.ordinal()];

src/main/java/org/variantsync/diffdetective/variation/diff/DiffTree.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,9 @@ private static void addUnmapped(MappingStore mappings, DiffNode parent, WrappedV
607607
);
608608
} else {
609609
diffNode = ((WrappedDiffTree)src).getDiffNode();
610-
diffNode.drop(AFTER);
610+
if (diffNode.getParent(AFTER) != null) {
611+
diffNode.drop(AFTER);
612+
}
611613
}
612614
parent.addChild(diffNode, AFTER);
613615

src/main/java/org/variantsync/diffdetective/variation/diff/Projection.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ public void insertChild(final Projection child, int index) {
102102
}
103103

104104
@Override
105-
public boolean removeChild(final Projection child) {
106-
return getBackingNode().removeChild(child.getBackingNode(), time);
105+
public void removeChild(final Projection child) {
106+
getBackingNode().removeChild(child.getBackingNode(), time);
107107
}
108108

109109
@Override

src/main/java/org/variantsync/diffdetective/variation/diff/serialize/edgeformat/EdgeLabelFormat.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package org.variantsync.diffdetective.variation.diff.serialize.edgeformat;
22

3-
import org.variantsync.diffdetective.util.Assert;
43
import org.variantsync.diffdetective.variation.diff.DiffNode;
54
import org.variantsync.diffdetective.variation.diff.Time;
65
import org.variantsync.diffdetective.variation.diff.serialize.LineGraphConstants;
@@ -99,13 +98,13 @@ public Direction getEdgeDirection() {
9998
protected void connectAccordingToLabel(final DiffNode child, final DiffNode parent, final String edgeLabel) {
10099
if (edgeLabel.startsWith(LineGraphConstants.BEFORE_AND_AFTER_PARENT)) {
101100
// Nothing has been changed. The child-parent relationship remains the same
102-
Time.forAll(time -> Assert.assertTrue(parent.addChild(child, time)));
101+
Time.forAll(time -> parent.addChild(child, time));
103102
} else if (edgeLabel.startsWith(LineGraphConstants.BEFORE_PARENT)) {
104103
// The child DiffNode lost its parent DiffNode (an orphan DiffNode)
105-
Assert.assertTrue(parent.addChild(child, BEFORE));
104+
parent.addChild(child, BEFORE);
106105
} else if (edgeLabel.startsWith(LineGraphConstants.AFTER_PARENT)) {
107106
// The parent DiffNode has a new child DiffNode
108-
Assert.assertTrue(parent.addChild(child, AFTER));
107+
parent.addChild(child, AFTER);
109108
} else {
110109
throw new IllegalArgumentException("Syntax error. Invalid name in edge label " + edgeLabel);
111110
}

src/main/java/org/variantsync/diffdetective/variation/tree/VariationNode.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ public void addChildren(final Collection<T> children) {
228228
* @see removeChildren
229229
* @see getChildren
230230
*/
231-
public abstract boolean removeChild(final T child);
231+
public abstract void removeChild(final T child);
232232

233233
/**
234234
* Removes the given nodes from the children list using {@link removeChild}.

src/main/java/org/variantsync/diffdetective/variation/tree/VariationTreeNode.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -228,13 +228,10 @@ public void insertChild(final VariationTreeNode child, int index) {
228228
}
229229

230230
@Override
231-
public boolean removeChild(final VariationTreeNode child) {
232-
if (isChild(child)) {
233-
child.parent = null;
234-
childOrder.remove(child);
235-
return true;
236-
}
237-
return false;
231+
public void removeChild(final VariationTreeNode child) {
232+
Assert.assertTrue(isChild(child));
233+
child.parent = null;
234+
childOrder.remove(child);
238235
}
239236

240237
@Override

0 commit comments

Comments
 (0)