Skip to content

Commit 0a4b318

Browse files
committed
starfold + node order + time
1 parent 0154f23 commit 0a4b318

11 files changed

Lines changed: 358 additions & 33 deletions

File tree

src/main/java/org/variantsync/diffdetective/diff/difftree/CodeType.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,8 @@ public static CodeType fromName(final String name) {
4848

4949
throw new IllegalArgumentException("Given string \"" + name + "\" is not the name of a CodeType.");
5050
}
51+
52+
public String asMacroText() {
53+
return "#" + this.name;
54+
}
5155
}

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

Lines changed: 132 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,10 @@
55
import org.variantsync.diffdetective.diff.DiffLineNumber;
66
import org.variantsync.diffdetective.diff.Lines;
77
import org.variantsync.diffdetective.util.Assert;
8+
import org.variantsync.diffdetective.util.StringUtils;
89
import org.variantsync.diffdetective.util.fide.FixTrueFalse;
910

10-
import java.util.ArrayList;
11-
import java.util.Collection;
12-
import java.util.List;
13-
import java.util.Objects;
11+
import java.util.*;
1412
import java.util.function.Function;
1513

1614
import static org.variantsync.diffdetective.util.fide.FormulaUtils.negate;
@@ -46,12 +44,14 @@ public class DiffNode {
4644
/**
4745
* We use a list for children to maintain order.
4846
*/
49-
private final List<DiffNode> allChildren;
47+
private final List<DiffNode> childOrder;
48+
49+
// These lists store the outgoing edges. These lists do not respect order.
5050
private List<DiffNode> beforeChildren;
5151
private List<DiffNode> afterChildren;
5252

5353
private DiffNode() {
54-
this.allChildren = new ArrayList<>();
54+
this.childOrder = new ArrayList<>();
5555
this.beforeChildren = new ArrayList<>();
5656
this.afterChildren = new ArrayList<>();
5757
}
@@ -196,7 +196,7 @@ public boolean beforePathEqualsAfterPath() {
196196
* @return The number of unique child nodes.
197197
*/
198198
public int getTotalNumberOfChildren() {
199-
return allChildren.size();
199+
return childOrder.size();
200200
}
201201

202202
/**
@@ -292,10 +292,51 @@ public void drop() {
292292
}
293293
}
294294

295+
private void dropBeforeChild(final DiffNode child) {
296+
assert child.beforeParent == this;
297+
child.beforeParent = null;
298+
}
299+
300+
private void dropAfterChild(final DiffNode child) {
301+
assert child.afterParent == this;
302+
child.afterParent = null;
303+
}
304+
305+
public int indexOfChild(final DiffNode child) {
306+
return childOrder.indexOf(child);
307+
}
308+
309+
public boolean insertChildAt(final DiffNode child, int index, Time time) {
310+
return switch (time) {
311+
case BEFORE -> insertBeforeChild(child, index);
312+
case AFTER -> insertAfterChild(child, index);
313+
};
314+
}
315+
316+
public boolean insertBeforeChild(final DiffNode child, int index) {
317+
if (!child.isAdd()) {
318+
addWithoutDuplicates(beforeChildren, child);
319+
insertWithoutDuplicates(childOrder, child, index);
320+
child.setBeforeParent(this);
321+
return true;
322+
}
323+
return false;
324+
}
325+
326+
public boolean insertAfterChild(final DiffNode child, int index) {
327+
if (!child.isRem()) {
328+
addWithoutDuplicates(afterChildren, child);
329+
insertWithoutDuplicates(childOrder, child, index);
330+
child.setAfterParent(this);
331+
return true;
332+
}
333+
return false;
334+
}
335+
295336
public boolean addBeforeChild(final DiffNode child) {
296337
if (!child.isAdd()) {
297-
addToList(beforeChildren, child);
298-
addToList(allChildren, child);
338+
addWithoutDuplicates(beforeChildren, child);
339+
addWithoutDuplicates(childOrder, child);
299340
child.setBeforeParent(this);
300341
return true;
301342
}
@@ -304,8 +345,8 @@ public boolean addBeforeChild(final DiffNode child) {
304345

305346
public boolean addAfterChild(final DiffNode child) {
306347
if (!child.isRem()) {
307-
addToList(afterChildren, child);
308-
addToList(allChildren, child);
348+
addWithoutDuplicates(afterChildren, child);
349+
addWithoutDuplicates(childOrder, child);
309350
child.setAfterParent(this);
310351
return true;
311352
}
@@ -324,15 +365,21 @@ public void addAfterChildren(final Collection<DiffNode> afterChildren) {
324365
}
325366
}
326367

327-
private static void addToList(final List<DiffNode> childrenlist, final DiffNode child) {
368+
private static void addWithoutDuplicates(final List<DiffNode> childrenlist, final DiffNode child) {
328369
if (!childrenlist.contains(child)) {
329370
childrenlist.add(child);
330371
}
331372
}
332373

374+
private static void insertWithoutDuplicates(final List<DiffNode> childrenlist, final DiffNode child, int index) {
375+
if (!childrenlist.contains(child)) {
376+
childrenlist.add(index, child);
377+
}
378+
}
379+
333380
public boolean removeBeforeChild(final DiffNode child) {
334381
if (this.beforeChildren.remove(child)) {
335-
removeFromCache(this.afterChildren, this.allChildren, child);
382+
removeFromCache(this.afterChildren, this.childOrder, child);
336383
dropBeforeChild(child);
337384
return true;
338385
}
@@ -341,7 +388,7 @@ public boolean removeBeforeChild(final DiffNode child) {
341388

342389
public boolean removeAfterChild(final DiffNode child) {
343390
if (this.afterChildren.remove(child)) {
344-
removeFromCache(this.beforeChildren, this.allChildren, child);
391+
removeFromCache(this.beforeChildren, this.childOrder, child);
345392
dropAfterChild(child);
346393
return true;
347394
}
@@ -357,7 +404,7 @@ public void removeChildren(final Collection<DiffNode> childrenToRemove) {
357404

358405
public List<DiffNode> removeBeforeChildren() {
359406
for (final DiffNode child : beforeChildren) {
360-
removeFromCache(this.afterChildren, this.allChildren, child);
407+
removeFromCache(this.afterChildren, this.childOrder, child);
361408
dropBeforeChild(child);
362409
}
363410

@@ -368,7 +415,7 @@ public List<DiffNode> removeBeforeChildren() {
368415

369416
public List<DiffNode> removeAfterChildren() {
370417
for (final DiffNode child : afterChildren) {
371-
removeFromCache(this.beforeChildren, this.allChildren, child);
418+
removeFromCache(this.beforeChildren, this.childOrder, child);
372419
dropAfterChild(child);
373420
}
374421

@@ -377,16 +424,6 @@ public List<DiffNode> removeAfterChildren() {
377424
return orphans;
378425
}
379426

380-
private void dropBeforeChild(final DiffNode child) {
381-
assert child.beforeParent == this;
382-
child.beforeParent = null;
383-
}
384-
385-
private void dropAfterChild(final DiffNode child) {
386-
assert child.afterParent == this;
387-
child.afterParent = null;
388-
}
389-
390427
private static void removeFromCache(
391428
final List<DiffNode> childrenTypeB,
392429
final List<DiffNode> allChildren,
@@ -440,8 +477,24 @@ public Node getDirectFeatureMapping() {
440477
return featureMapping;
441478
}
442479

443-
public Collection<DiffNode> getAllChildren() {
444-
return allChildren;
480+
public List<DiffNode> getChildOrder() {
481+
return Collections.unmodifiableList(childOrder);
482+
}
483+
484+
public List<DiffNode> getAllChildren() {
485+
return getChildOrder();
486+
}
487+
488+
public List<DiffNode> getBeforeChildren() {
489+
return Collections.unmodifiableList(beforeChildren);
490+
}
491+
492+
public List<DiffNode> getAfterChildren() {
493+
return Collections.unmodifiableList(afterChildren);
494+
}
495+
496+
public List<DiffNode> getChildren(Time time) {
497+
return time.match(getBeforeChildren(), getAfterChildren());
445498
}
446499

447500
public void setIsMultilineMacro(boolean isMultilineMacro) {
@@ -506,6 +559,13 @@ public Node getAfterFeatureMapping() {
506559
return getFeatureMapping(DiffNode::getAfterParent);
507560
}
508561

562+
public Node getFeatureMapping(Time time) {
563+
return time.match(
564+
this::getBeforeFeatureMapping,
565+
this::getAfterFeatureMapping
566+
);
567+
}
568+
509569
private List<Node> getPresenceCondition(Function<DiffNode, DiffNode> parentOf) {
510570
final DiffNode parent = parentOf.apply(this);
511571

@@ -556,6 +616,17 @@ public Node getAfterPresenceCondition() {
556616
}
557617
}
558618

619+
public Node getPresenceCondition(Time time) {
620+
return time.match(
621+
this::getBeforePresenceCondition,
622+
this::getAfterPresenceCondition
623+
);
624+
}
625+
626+
public boolean isLeaf() {
627+
return childOrder.isEmpty();
628+
}
629+
559630
public boolean isRem() {
560631
return this.diffType.equals(DiffType.REM);
561632
}
@@ -631,13 +702,13 @@ public void assertConsistency() {
631702
// check consistency of children lists and edges
632703
for (final DiffNode bc : beforeChildren) {
633704
Assert.assertTrue(bc.beforeParent == this, () -> "Before child " + bc + " of " + this + " has another parent " + bc.beforeParent + "!");
634-
Assert.assertTrue(allChildren.contains(bc), () -> "Before child " + bc + " of " + this + " is not in the list of all children!");
705+
Assert.assertTrue(childOrder.contains(bc), () -> "Before child " + bc + " of " + this + " is not in the list of all children!");
635706
}
636707
for (final DiffNode ac : afterChildren) {
637708
Assert.assertTrue(ac.afterParent == this, () -> "After child " + ac + " of " + this + " has another parent " + ac.afterParent + "!");
638-
Assert.assertTrue(allChildren.contains(ac), () -> "After child " + ac + " of " + this + " is not in the list of all children!");
709+
Assert.assertTrue(childOrder.contains(ac), () -> "After child " + ac + " of " + this + " is not in the list of all children!");
639710
}
640-
for (final DiffNode c : allChildren) {
711+
for (final DiffNode c : childOrder) {
641712
Assert.assertTrue(beforeChildren.contains(c) || afterChildren.contains(c), () -> "Child " + c + " of " + this + " is neither a before not an after child!");
642713
}
643714

@@ -666,6 +737,36 @@ public void assertSemanticConsistency() {
666737
}
667738
}
668739

740+
public static String toTextDiffLine(final DiffType diffType, final String text) {
741+
return diffType.symbol + text.replaceAll(StringUtils.LINEBREAK_REGEX, StringUtils.LINEBREAK + diffType.symbol);
742+
}
743+
744+
public String toTextDiffLine() {
745+
return toTextDiffLine(diffType, this.getLabel());
746+
}
747+
748+
public String toTextDiff() {
749+
final StringBuilder diff = new StringBuilder();
750+
751+
if (!this.isRoot()) {
752+
diff
753+
.append(this.toTextDiffLine())
754+
.append(StringUtils.LINEBREAK);
755+
}
756+
757+
for (final DiffNode child : childOrder) {
758+
diff.append(child.toTextDiff());
759+
}
760+
761+
if (isMacro()) {
762+
diff
763+
.append(toTextDiffLine(this.diffType, CodeType.ENDIF.asMacroText()))
764+
.append(StringUtils.LINEBREAK);
765+
}
766+
767+
return diff.toString();
768+
}
769+
669770
@Override
670771
public String toString() {
671772
String s;

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,10 @@ public void removeNode(DiffNode node) {
180180
}
181181
}
182182

183+
public String toTextDiff() {
184+
return root.toTextDiff();
185+
}
186+
183187
private static class AllPathsEndAtRoot {
184188
private enum VisitStatus {
185189
STRANGER,

src/main/java/org/variantsync/diffdetective/diff/difftree/DiffType.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ public enum DiffType {
1616
final static String addCharacter = "+";
1717
final static String remCharacter = "-";
1818

19+
public static DiffType thatExistsOnlyAt(Time time) {
20+
return switch (time) {
21+
case BEFORE -> REM;
22+
case AFTER -> ADD;
23+
};
24+
}
25+
1926
/**
2027
* Runs the first given procedure if the edited artefact existed before the edit (DiffType != ADD).
2128
* Runs the second given procedure if the edited artefact exists after the edit (DiffType != REM).
@@ -92,10 +99,14 @@ public static DiffType fromName(final String line) {
9299
}
93100

94101
public boolean existsBefore() {
95-
return this != ADD;
102+
return existsAtTime(Time.BEFORE);
96103
}
97104

98105
public boolean existsAfter() {
99-
return this != REM;
106+
return existsAtTime(Time.AFTER);
107+
}
108+
109+
public boolean existsAtTime(Time time) {
110+
return (time == Time.BEFORE && this != ADD) || (time == Time.AFTER && this != REM);
100111
}
101112
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package org.variantsync.diffdetective.diff.difftree;
2+
3+
import java.util.function.Consumer;
4+
import java.util.function.Supplier;
5+
6+
public enum Time {
7+
BEFORE, AFTER;
8+
9+
public static void forall(final Consumer<Time> f) {
10+
f.accept(BEFORE);
11+
f.accept(AFTER);
12+
}
13+
14+
public <T> T match(final Supplier<T> before, final Supplier<T> after) {
15+
return this.<Supplier<T>>match(before, after).get();
16+
}
17+
18+
public <T> T match(final T before, final T after) {
19+
return switch (this) {
20+
case BEFORE -> before;
21+
case AFTER -> after;
22+
};
23+
}
24+
}

0 commit comments

Comments
 (0)