aboutsummaryrefslogtreecommitdiffstats
path: root/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/internal/MapDiffCursor.java
blob: 3e0a823efd523afab64a56bd85d5612b7696e28e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package org.eclipse.viatra.solver.data.map.internal;

import org.eclipse.viatra.solver.data.map.Cursor;
import org.eclipse.viatra.solver.data.map.DiffCursor;

/**
 * A cursor representing the difference between two states of a map.
 * @author Oszkar Semerath
 *
 */
public class MapDiffCursor<KEY,VALUE> implements DiffCursor<KEY, VALUE> {
	/**
	 * Default value representing missing elements.
	 */
	VALUE defaultValue;
	MapCursor<KEY,VALUE> cursor1;
	MapCursor<KEY,VALUE> cursor2;
	
	// Values
	KEY key;
	VALUE value1;
	VALUE value2;
	
	// State
	/**
	 * Positive number if cursor 1 is behind, negative number if cursor 2 is behind, and 0 if they are at the same position.
	 */
	int cursorRelation;
	
	public MapDiffCursor(VALUE defaultValue, Cursor<KEY, VALUE> cursor1, Cursor<KEY, VALUE> cursor2) {
		super();
		this.defaultValue = defaultValue;
		this.cursor1 = (MapCursor<KEY, VALUE>) cursor1;
		this.cursor2 = (MapCursor<KEY, VALUE>) cursor2;
		
		this.updateState();
		this.moveToConsistentState();
	}

	public KEY getKey() {
		return key;
	}
	public VALUE getValue1() {
		return value1;
	}
	public VALUE getValue2() {
		return value2;
	}
	public boolean isTerminated() {
		return cursor1.isTerminated() && cursor2.isTerminated();
	}
	
	protected void updateState() {
		this.cursorRelation = MapCursor.compare(cursor1, cursor2);
		if(cursorRelation > 0 || cursor2.isTerminated()) {
			this.key = cursor1.getKey();
			this.value1 = cursor1.getValue();
			this.value2 = defaultValue;
		} else if(cursorRelation < 0|| cursor1.isTerminated()){
			this.key = cursor2.getKey();
			this.value1 = defaultValue;
			this.value2 = cursor1.getValue();
		} else {
			// cursor1 = cursor2
			if(!cursor1.getKey().equals(cursor2.getKey())) {
				throw new IllegalStateException(
					"Cursor comarison tells that they are in the same state, but keys are different. " + cursor1.getKey() + " - " + cursor2.getKey());
			}
			this.key = cursor1.getKey();
			this.value1 = cursor1.getValue();
			this.value2 = defaultValue;
		}
	}
	
	protected boolean canStop() {
		return this.value1 != this.value2;
	}
	protected void moveOne() {
		if(isTerminated()) {
			throw new IllegalStateException("DiffCursor tries to move when terminated!");
		}
		if(this.cursorRelation > 0 || cursor2.isTerminated()) {
			cursor1.move();
		} else if(this.cursorRelation < 0 || cursor1.isTerminated()) {
			cursor2.move();
		} else {
			cursor1.move();
			cursor2.move();
		}
		updateState();
	}
	protected void moveToConsistentState() {
		while(!canStop() && !isTerminated()) {
			moveOne();
		}
	}
	
	public void move() {
		if(!isTerminated()) {
			moveOne();
			moveToConsistentState();
		}
	}
}