Skip to content

Commit 07ab5eb

Browse files
committed
Make graph datastructure hold values
1 parent 8b7985a commit 07ab5eb

11 files changed

Lines changed: 443 additions & 168 deletions

File tree

Lines changed: 148 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.kneelawk.graphlib.v3.api.datastructure;
22

3-
import java.util.Objects;
3+
import com.kneelawk.graphlib.v3.api.pos.NodePos;
44

55
// Translated from 2xsaiko's HCTM-Base Graph code:
66
// https://github.com/2xsaiko/hctm-base/blob/119df440743543b8b4979b450452d73f2c3c4c47/src/main/kotlin/common/graph/Graph.kt
@@ -12,23 +12,73 @@
1212
* upheld in this type's {@link #equals(Object)} and {@link #hashCode()}.
1313
* <p>
1414
* If a link needs to be directional, then its data should reference one of the nodes, making it asymmetrical.
15-
* Referencing a node can be done with a {@link com.kneelawk.graphlib.v3.api.pos.NodePos}.
15+
* Referencing a node can be done with a {@link NodePos}.
1616
*
17-
* @param first the first node in this link.
18-
* @param second the second node in this link.
19-
* @param key the key that makes this link unique out of all the links between the same two nodes.
20-
* @param <K> the type of key used to index each node.
21-
* @param <L> the type of link data contained in this link.
17+
* @param <K> the type of key used to index each node.
18+
* @param <V> the type of data contained in each node.
19+
* @param <LK> the type of link key that determines whether two links between the same nodes are unique.
20+
* @param <LV> the type of data contained in each link.
2221
*/
23-
public record KeyedLink<K, L>(KeyedNode<K, L> first, KeyedNode<K, L> second, L key) {
22+
public final class KeyedLink<K, V, LK, LV> {
23+
private final KeyedNode<K, V, LK, LV> first;
24+
private final KeyedNode<K, V, LK, LV> second;
25+
private final Key<K, LK> key;
26+
private final LV value;
27+
28+
/**
29+
* Creates a new keyed link.
30+
*
31+
* @param first the first node in this link.
32+
* @param second the second node in this link.
33+
* @param key the key that describes this link uniquely.
34+
* @param value the value held within this link.
35+
*/
36+
public KeyedLink(KeyedNode<K, V, LK, LV> first, KeyedNode<K, V, LK, LV> second, Key<K, LK> key, LV value) {
37+
this.first = first;
38+
this.second = second;
39+
this.key = key;
40+
this.value = value;
41+
42+
if (!key.contains(first.key()) || !key.contains(second.key()))
43+
throw new IllegalArgumentException("The link key must contain the keys of the link's two nodes");
44+
}
45+
46+
/**
47+
* {@return the first node in this link}
48+
*/
49+
public KeyedNode<K, V, LK, LV> first() {
50+
return first;
51+
}
52+
53+
/**
54+
* {@return the second node in this link}
55+
*/
56+
public KeyedNode<K, V, LK, LV> second() {
57+
return second;
58+
}
59+
60+
/**
61+
* {@return this link's key}
62+
*/
63+
public Key<K, LK> key() {
64+
return key;
65+
}
66+
67+
/**
68+
* {@return this link's value}
69+
*/
70+
public LV value() {
71+
return value;
72+
}
73+
2474
/**
2575
* Checks to see if the given node is either of the two nodes in this link.
2676
*
2777
* @param node the node to check.
2878
* @return <code>true</code> if the given node is either of the nodes in this link.
2979
*/
30-
public boolean contains(KeyedNode<K, L> node) {
31-
return Objects.equals(first, node) || Objects.equals(second, node);
80+
public boolean contains(KeyedNode<K, V, LK, LV> node) {
81+
return first.key().equals(node.key()) || second.key().equals(node.key());
3282
}
3383

3484
/**
@@ -38,7 +88,7 @@ public boolean contains(KeyedNode<K, L> node) {
3888
* @return <code>true</code> if a node with the given key is wither of the nodes in this link.
3989
*/
4090
public boolean contains(K key) {
41-
return Objects.equals(first.key(), key) || Objects.equals(second.key(), key);
91+
return first.key().equals(key) || second.key().equals(key);
4292
}
4393

4494
/**
@@ -47,8 +97,8 @@ public boolean contains(K key) {
4797
* @param node the node to get the other end of the link from.
4898
* @return the node at the other end of the link from the given node.
4999
*/
50-
public KeyedNode<K, L> other(KeyedNode<K, L> node) {
51-
if (Objects.equals(first, node)) {
100+
public KeyedNode<K, V, LK, LV> other(KeyedNode<K, V, LK, LV> node) {
101+
if (first.key().equals(node.key())) {
52102
return second;
53103
} else {
54104
return first;
@@ -61,44 +111,104 @@ public KeyedNode<K, L> other(KeyedNode<K, L> node) {
61111
* @param key the key of the node to get the other end of hte link from.
62112
* @return the node at the other end of the link from the node with the given key.
63113
*/
64-
public KeyedNode<K, L> other(K key) {
65-
if (Objects.equals(first.key(), key)) {
114+
public KeyedNode<K, V, LK, LV> other(K key) {
115+
if (first.key().equals(key)) {
66116
return second;
67117
} else {
68118
return first;
69119
}
70120
}
71121

72-
@Override
73-
public boolean equals(Object o) {
74-
if (this == o) return true;
75-
if (o == null || getClass() != o.getClass()) return false;
76-
77-
KeyedLink<?, ?> linkKey = (KeyedLink<?, ?>) o;
78-
79-
if (!key.equals(linkKey.key)) return false;
80-
81-
// note: hashCode and equals are symmetrical regardless of node order
82-
if (first.equals(linkKey.first)) {
83-
return second.equals(linkKey.second);
84-
} else if (second.equals(linkKey.first)) {
85-
return first.equals(linkKey.second);
86-
}
122+
/**
123+
* Establishes this link between this link's two nodes.
124+
*
125+
* @return {@code true} if a link was successfully established, {@code} false if a link already existed with this link's key.
126+
*/
127+
public boolean link() {
128+
return first.onLink(this) == null & second.onLink(this) == null;
129+
}
87130

88-
return false;
131+
/**
132+
* Removes this link from the two nodes it is attached between.
133+
*
134+
* @return {@code true} if this link was connecting the two nodes to begin with.
135+
*/
136+
public boolean unlink() {
137+
return first.onUnlink(key) == this & second.onUnlink(key) == this;
89138
}
90139

91-
@Override
92-
public int hashCode() {
93-
// note: hashCode and equals are symmetrical regardless of node order
94-
int result = first.hashCode();
95-
result = result ^ second.hashCode();
96-
result = 31 * result + key.hashCode();
97-
return result;
140+
/**
141+
* {@return whether this link is connecting its two nodes}
142+
*/
143+
public boolean isLinked() {
144+
return first.connections().get(key) == this && second.connections().get(key) == this;
98145
}
99146

100147
@Override
101148
public String toString() {
102149
return "link(" + first + " <-> " + second + ", " + key + ')';
103150
}
151+
152+
/**
153+
* Key used to index links.
154+
*
155+
* @param first the unique key of the first node.
156+
* @param second the unique key of the second node.
157+
* @param key the key that makes this link unique out of all the links between the same two nodes.
158+
* @param <N> the type of node key.
159+
* @param <L> the type of link key.
160+
*/
161+
public record Key<N, L>(N first, N second, L key) {
162+
/**
163+
* Gets whether this link key contains the given node key.
164+
*
165+
* @param nodeKey the node key to find.
166+
* @return {@code true} if this link key contains the given node key.
167+
*/
168+
public boolean contains(N nodeKey) {
169+
return first.equals(nodeKey) || second.equals(nodeKey);
170+
}
171+
172+
/**
173+
* Gets the node key opposite the given node key.
174+
*
175+
* @param nodeKey the node key to get the opposite end of the link from.
176+
* @return the node key at the other end of the link.
177+
*/
178+
public N other(N nodeKey) {
179+
if (first.equals(nodeKey)) {
180+
return second;
181+
} else {
182+
return first;
183+
}
184+
}
185+
186+
@Override
187+
public boolean equals(Object o) {
188+
if (this == o) return true;
189+
if (o == null || getClass() != o.getClass()) return false;
190+
191+
Key<?, ?> linkKey = (Key<?, ?>) o;
192+
193+
if (!key.equals(linkKey.key)) return false;
194+
195+
// note: hashCode and equals are symmetrical regardless of node order
196+
if (first.equals(linkKey.first)) {
197+
return second.equals(linkKey.second);
198+
} else if (second.equals(linkKey.first)) {
199+
return first.equals(linkKey.second);
200+
}
201+
202+
return false;
203+
}
204+
205+
@Override
206+
public int hashCode() {
207+
// note: hashCode and equals are symmetrical regardless of node order
208+
int result = first.hashCode();
209+
result = result ^ second.hashCode();
210+
result = 31 * result + key.hashCode();
211+
return result;
212+
}
213+
}
104214
}

0 commit comments

Comments
 (0)