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