summaryrefslogtreecommitdiff
path: root/src/main/java/ChannelNode.java
blob: 20a7ac0a34f40cde184341dc2366417be9fafbf4 (plain)
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import static java.util.Map.entry;

public class ChannelNode implements IChannelNode {
    private Map<IChannelNode, Integer> incoming;
    private Map<IChannelNode, Integer> outgoing;

    public ChannelNode() {
        incoming = new TreeMap<>();
        outgoing = new TreeMap<>();
    }

    @Override
    public void setConnections(Map<IChannelNode, Integer> conmap, Direction dir) throws IllegalArgumentException {
        if(conmap == null) throw new IllegalArgumentException("connection map is null");
        if(dir == null) throw new IllegalArgumentException("direction is null");
        if(conmap.containsKey(this)) throw new IllegalArgumentException("connection map contains this node");

        Direction.overVals(Map.ofEntries(
            entry(Direction.INCOMING, () -> incoming = conmap),
            entry(Direction.OUTGOING, () -> outgoing = conmap)
        ), dir);
    }

    @Override
    public void setNumConnections(IChannelNode node, Direction dir, int num) throws IllegalArgumentException {
        if(node == null) throw new IllegalArgumentException("node is null");
        if(node == this) throw new IllegalArgumentException("node is self");
        if(dir == null) throw new IllegalArgumentException("dir is null");
        if(num < 0) throw new IllegalArgumentException("num < 0");

        Direction.overVals(Map.ofEntries(
            entry(Direction.INCOMING, () -> incoming.put(node, num)),
            entry(Direction.OUTGOING, () -> outgoing.put(node, num))
        ), dir);
    }

    @Override
    public void addConnection(IChannelNode node, Direction dir) throws IllegalArgumentException {
        if(node == null) throw new IllegalArgumentException("node is null");
        if(node == this) throw new IllegalArgumentException("node is self");
        if(dir == null) throw new IllegalArgumentException("dir is null");

        Direction.overVals(Map.ofEntries(
            entry(Direction.INCOMING, () -> incoming.put(node, incoming.get(node) + 1)),
            entry(Direction.OUTGOING, () -> outgoing.put(node, outgoing.get(node) + 1))
        ), dir);
    }

    @Override
    public void addConnections(Iterable<IChannelNode> nodes, Direction dir) throws IllegalArgumentException {
        if(nodes == null) throw new IllegalArgumentException("node is null");
        if(dir == null) throw new IllegalArgumentException("dir is null");
        nodes.forEach((node) -> {if(node == this) throw new IllegalArgumentException("one of the included nodes is this node");});

        for(IChannelNode node: nodes) {
            Direction.overVals(Map.ofEntries(
                entry(Direction.INCOMING, () -> incoming.put(node, incoming.get(node) + 1)),
                entry(Direction.OUTGOING, () -> outgoing.put(node, outgoing.get(node) + 1))
            ), dir);
        }
    }

    @Override
    public void removeConnection(IChannelNode node, Direction dir) throws IllegalArgumentException {
        if(node == null) throw new IllegalArgumentException("node is null");
        if(node == this) throw new IllegalArgumentException("node is self");
        if(dir == null) throw new IllegalArgumentException("dir is null");

        Direction.overVals(Map.ofEntries(
            entry(Direction.INCOMING, () -> incoming.put(node, Math.max(incoming.get(node) - 1, 0))),
            entry(Direction.OUTGOING, () -> outgoing.put(node, Math.max(outgoing.get(node) - 1, 0)))
        ), dir);
    }

    @Override
    public void removeConnections(Iterable<IChannelNode> nodes, Direction dir) throws IllegalArgumentException {
        if(nodes == null) throw new IllegalArgumentException("node is null");
        if(dir == null) throw new IllegalArgumentException("dir is null");
        nodes.forEach((node) -> {if(node == this) throw new IllegalArgumentException("one of the included nodes is this node");});

        for(IChannelNode node: nodes) {
            Direction.overVals(Map.ofEntries(
                entry(Direction.INCOMING, () -> incoming.put(node, Math.max(incoming.get(node) - 1, 0))),
                entry(Direction.OUTGOING, () -> outgoing.put(node, Math.max(outgoing.get(node) - 1, 0)))
            ), dir);
        }
    }

    @Override
    public void clearConnections(Direction dir) throws IllegalArgumentException {
        if(dir == null) throw new IllegalArgumentException("dir is null");

        Direction.overVals(Map.ofEntries(
            entry(Direction.INCOMING, () -> incoming.clear()),
            entry(Direction.OUTGOING, () -> outgoing.clear())
        ), dir);
    }

    @Override
    public boolean connectionExists(IChannelNode node, Direction dir) throws IllegalArgumentException {
        if(node == null) throw new IllegalArgumentException("node is null");
        if(dir == null) throw new IllegalArgumentException("dir is null");

        switch (dir) {
            case INCOMING -> {return incoming.containsKey(node);}
            case OUTGOING -> {return outgoing.containsKey(node);}
            case BOTH -> {return (incoming.containsKey(node) && outgoing.containsKey(node));}
            default -> throw new IllegalStateException("got unknown direction");
        }
    }

    @Override
    public int getNumConnections(Direction dir) throws IllegalArgumentException {
        if(dir == null) throw new IllegalArgumentException("dir is null");

        AtomicInteger total = new AtomicInteger();
        Direction.overVals(Map.ofEntries(
            entry(Direction.INCOMING, () -> {for(int i: incoming.values()) total.addAndGet(i);}),
            entry(Direction.OUTGOING, () -> {for(int i: outgoing.values()) total.addAndGet(i);})
        ), dir);
        return total.get();
    }

    @Override
    public Map<IChannelNode, Integer> getIncomingConnections() {
        return incoming;
    }

    @Override
    public Map<IChannelNode, Integer> getOutgoingConnections() {
        return outgoing;
    }

    @Override
    public List<Map<IChannelNode, Integer>> getConnections(Direction dir) throws IllegalArgumentException {
        if(dir == null) throw new IllegalArgumentException("dir is null");

        ArrayList<Map<IChannelNode, Integer>> res = new ArrayList<>();
        Direction.overVals(Map.ofEntries(
            entry(Direction.INCOMING, () -> res.add(incoming)),
            entry(Direction.OUTGOING, () -> res.add(outgoing))
        ), dir);

        return res;
    }

    @Override
    public int compareTo(IChannelNode iChannelNode) throws IllegalArgumentException {
        if(iChannelNode == null) throw new IllegalArgumentException("comparison node is null");
        int selfTotal = getNumConnections(Direction.BOTH),
            theirTotal = iChannelNode.getNumConnections(Direction.BOTH);

        return selfTotal - theirTotal;
    }
}