1 package org.opentrafficsim.core.compatibility;
2
3 import java.util.LinkedHashMap;
4 import java.util.Map;
5 import java.util.Objects;
6
7 import org.djutils.exceptions.Throw;
8 import org.opentrafficsim.base.HierarchicalType;
9 import org.opentrafficsim.base.OtsRuntimeException;
10 import org.opentrafficsim.core.gtu.GtuType;
11
12
13
14
15
16
17
18
19
20
21
22
23
24 public class GtuCompatibility<T extends HierarchicalType<T, ?> & Compatibility<GtuType, T>> implements Compatibility<GtuType, T>
25 {
26
27 private final Map<GtuType, Boolean> levelCompatibilityMap = new LinkedHashMap<>();
28
29
30 private final Map<GtuType, Boolean> cachedCompatibilityMap = new LinkedHashMap<>();
31
32
33 private final T infrastructure;
34
35
36
37
38
39 public GtuCompatibility(final T infrastructure)
40 {
41 Throw.whenNull(infrastructure, "infrastructure cannot be null");
42 this.infrastructure = infrastructure;
43 }
44
45
46
47
48
49 public GtuCompatibility(final GtuCompatibility<T> original)
50 {
51 this.infrastructure = original.infrastructure;
52 this.levelCompatibilityMap.putAll(original.levelCompatibilityMap);
53 }
54
55
56
57
58
59
60 @Override
61 public boolean isCompatible(final GtuType gtuType)
62 {
63 if (!this.cachedCompatibilityMap.containsKey(gtuType))
64 {
65 boolean foundTrue = false;
66 boolean foundFalse = false;
67 T infra = this.infrastructure;
68 while (infra != null)
69 {
70 GtuType gType = gtuType;
71 while (gType != null)
72 {
73 if (infra.isCompatibleOnInfraLevel(gType) != null)
74 {
75 if (infra.isCompatibleOnInfraLevel(gType))
76 {
77 foundTrue = true;
78 }
79 else
80 {
81 foundFalse = true;
82 }
83 }
84 gType = gType.getParent();
85 }
86 infra = infra.getParent();
87 }
88 if (foundFalse)
89 {
90 this.cachedCompatibilityMap.put(gtuType, false);
91 }
92 else if (foundTrue)
93 {
94 this.cachedCompatibilityMap.put(gtuType, true);
95 }
96 else
97 {
98 this.cachedCompatibilityMap.put(gtuType, false);
99 }
100 }
101 return this.cachedCompatibilityMap.get(gtuType);
102 }
103
104
105 @Override
106 public Boolean isCompatibleOnInfraLevel(final GtuType gtuType)
107 {
108 return this.levelCompatibilityMap.get(gtuType);
109 }
110
111
112
113
114
115
116
117
118 public final GtuCompatibility<T> addCompatibleGtuType(final GtuType gtuType) throws NullPointerException
119 {
120 Throw.whenNull(gtuType, "gtuType may not be null");
121 clearCompatibilityCache();
122 this.levelCompatibilityMap.put(gtuType, true);
123 return this;
124 }
125
126
127
128
129
130
131
132
133 public final GtuCompatibility<T> addIncompatibleGtuType(final GtuType gtuType) throws NullPointerException
134 {
135 Throw.whenNull(gtuType, "gtuType may not be null");
136 clearCompatibilityCache();
137 this.levelCompatibilityMap.put(gtuType, false);
138 return this;
139 }
140
141
142 @Override
143 public T getInfrastructure()
144 {
145 return this.infrastructure;
146 }
147
148
149 @Override
150 public void clearCompatibilityCache()
151 {
152 this.cachedCompatibilityMap.clear();
153 for (T infra: getInfrastructure().getChildren())
154 {
155 infra.clearCompatibilityCache();
156 }
157 }
158
159
160 @Override
161 public int hashCode()
162 {
163 return Objects.hash(this.infrastructure, this.levelCompatibilityMap);
164 }
165
166
167 @Override
168 @SuppressWarnings("checkstyle:needbraces")
169 public boolean equals(final Object obj)
170 {
171 if (this == obj)
172 return true;
173 if (obj == null)
174 return false;
175 if (getClass() != obj.getClass())
176 return false;
177 GtuCompatibility<?> other = (GtuCompatibility<?>) obj;
178 return Objects.equals(this.infrastructure, other.infrastructure)
179 && Objects.equals(this.levelCompatibilityMap, other.levelCompatibilityMap);
180 }
181
182
183 @Override
184 public final String toString()
185 {
186 return "GtuCompatibility [levelCompatibilityMap=" + this.levelCompatibilityMap + "]";
187 }
188
189 }