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 @Override
105 public Boolean isCompatibleOnInfraLevel(final GtuType gtuType)
106 {
107 return this.levelCompatibilityMap.get(gtuType);
108 }
109
110
111
112
113
114
115
116
117 public final GtuCompatibility<T> addCompatibleGtuType(final GtuType gtuType) throws NullPointerException
118 {
119 Throw.whenNull(gtuType, "gtuType may not be null");
120 clearCompatibilityCache();
121 this.levelCompatibilityMap.put(gtuType, true);
122 return this;
123 }
124
125
126
127
128
129
130
131
132 public final GtuCompatibility<T> addIncompatibleGtuType(final GtuType gtuType) throws NullPointerException
133 {
134 Throw.whenNull(gtuType, "gtuType may not be null");
135 clearCompatibilityCache();
136 this.levelCompatibilityMap.put(gtuType, false);
137 return this;
138 }
139
140 @Override
141 public T getInfrastructure()
142 {
143 return this.infrastructure;
144 }
145
146 @Override
147 public void clearCompatibilityCache()
148 {
149 this.cachedCompatibilityMap.clear();
150 for (T infra : getInfrastructure().getChildren())
151 {
152 infra.clearCompatibilityCache();
153 }
154 }
155
156 @Override
157 public int hashCode()
158 {
159 return Objects.hash(this.infrastructure, this.levelCompatibilityMap);
160 }
161
162 @Override
163 @SuppressWarnings("checkstyle:needbraces")
164 public boolean equals(final Object obj)
165 {
166 if (this == obj)
167 return true;
168 if (obj == null)
169 return false;
170 if (getClass() != obj.getClass())
171 return false;
172 GtuCompatibility<?> other = (GtuCompatibility<?>) obj;
173 return Objects.equals(this.infrastructure, other.infrastructure)
174 && Objects.equals(this.levelCompatibilityMap, other.levelCompatibilityMap);
175 }
176
177 @Override
178 public final String toString()
179 {
180 return "GtuCompatibility [levelCompatibilityMap=" + this.levelCompatibilityMap + "]";
181 }
182
183 }