1 package org.opentrafficsim.core.compatibility;
2
3 import java.util.LinkedHashMap;
4 import java.util.Map;
5
6 import org.djutils.exceptions.Throw;
7 import org.djutils.logger.CategoryLogger;
8 import org.opentrafficsim.base.HierarchicalType;
9 import org.opentrafficsim.core.gtu.GTUDirectionality;
10 import org.opentrafficsim.core.gtu.GTUException;
11 import org.opentrafficsim.core.gtu.GTUType;
12 import org.opentrafficsim.core.network.LongitudinalDirectionality;
13
14
15
16
17
18
19
20
21
22
23
24
25
26 public class GTUCompatibility<I extends HierarchicalType<I> & Compatibility<GTUType, I>> implements Compatibility<GTUType, I>
27 {
28
29 private final Map<GTUType, LongitudinalDirectionality> allowanceMap = new LinkedHashMap<>();
30
31
32 private final I infrastructure;
33
34
35
36
37
38 public GTUCompatibility(final I infrastructure)
39 {
40 this.infrastructure = infrastructure;
41 }
42
43
44
45
46
47
48
49 public GTUCompatibility(final GTUCompatibility<I> original)
50 {
51 this.infrastructure = original.infrastructure;
52 this.allowanceMap.putAll(original.allowanceMap);
53 }
54
55
56
57
58
59
60
61
62 @Override
63 public final Boolean isCompatible(final GTUType gtuType, final GTUDirectionality directionality)
64 {
65 LongitudinalDirectionality allowedDirections = this.allowanceMap.get(gtuType);
66 if (null == allowedDirections)
67 {
68 return null;
69 }
70 switch (allowedDirections)
71 {
72 case DIR_BOTH:
73 return true;
74 case DIR_MINUS:
75 return GTUDirectionality.DIR_MINUS == directionality;
76 case DIR_NONE:
77 return false;
78 case DIR_PLUS:
79 return GTUDirectionality.DIR_PLUS == directionality;
80 default:
81 CategoryLogger.always().warn("Unknown type in isCompatible - Cannot happen");
82 return null;
83 }
84 }
85
86
87
88
89
90
91
92
93 public final GTUCompatibility<I> addAllowedGTUType(final GTUType gtuType, final LongitudinalDirectionality directionality)
94 throws NullPointerException
95 {
96 Throw.whenNull(directionality, "Directionality for GTUType %s may not be null", gtuType);
97 this.allowanceMap.put(gtuType, directionality);
98 return this;
99 }
100
101
102
103
104
105
106
107
108 public final GTUCompatibility<I> removeAllowedGTUType(final GTUType gtuType,
109 final LongitudinalDirectionality directionality)
110 {
111 this.allowanceMap.remove(gtuType);
112 return this;
113 }
114
115
116 @Override
117 public final String toString()
118 {
119 return "GTUCompatibility [allowanceMap=" + this.allowanceMap + "]";
120 }
121
122
123 @Override
124 public final int hashCode()
125 {
126 final int prime = 31;
127 int result = 1;
128 result = prime * result + ((this.allowanceMap == null) ? 0 : this.allowanceMap.hashCode());
129 return result;
130 }
131
132
133 @Override
134 public final boolean equals(final Object obj)
135 {
136 if (this == obj)
137 {
138 return true;
139 }
140 if (obj == null)
141 {
142 return false;
143 }
144 if (getClass() != obj.getClass())
145 {
146 return false;
147 }
148 GTUCompatibility<?> other = (GTUCompatibility<?>) obj;
149 if (this.allowanceMap == null)
150 {
151 if (other.allowanceMap != null)
152 {
153 return false;
154 }
155 }
156 else if (!this.allowanceMap.equals(other.allowanceMap))
157 {
158 return false;
159 }
160 return true;
161 }
162
163
164
165
166
167
168
169
170 public final void isCompatibleWith(final Compatibility<GTUType, ?> parentCompatibility, final boolean tryParentsOfGTUType)
171 throws GTUException
172 {
173 for (GTUType gtuType : this.allowanceMap.keySet())
174 {
175 LongitudinalDirectionality ourLD = this.allowanceMap.get(gtuType);
176 LongitudinalDirectionality parentLD = parentCompatibility.getDirectionality(gtuType, true);
177 if (!parentLD.contains(ourLD))
178 {
179 throw new GTUException(String.format("GTUType %s has LongitudinalDirectionality %s on child, but %s on parent",
180 ourLD, parentLD));
181 }
182 }
183
184 }
185
186
187 @Override
188 public final LongitudinalDirectionality getDirectionality(final GTUType gtuType, final boolean tryParentsOfGTUType)
189 {
190 for (GTUType testGTUType = gtuType; null != testGTUType; testGTUType = testGTUType.getParent())
191 {
192 LongitudinalDirectionality result = this.allowanceMap.get(testGTUType);
193 if (null != result)
194 {
195 return result;
196 }
197 if (null != this.infrastructure && null != this.infrastructure.getParent())
198 {
199 result = this.infrastructure.getParent().getDirectionality(testGTUType, false);
200 if (null != result)
201 {
202 return result;
203 }
204 }
205 if (!tryParentsOfGTUType)
206 {
207 break;
208 }
209 }
210 return tryParentsOfGTUType ? LongitudinalDirectionality.DIR_NONE : null;
211 }
212
213 }