1 package org.opentrafficsim.road.gtu.strategical.od;
2
3 import java.io.Serializable;
4 import java.util.ArrayList;
5 import java.util.List;
6
7 import org.opentrafficsim.base.Identifiable;
8
9 import nl.tudelft.simulation.language.Throw;
10
11 /**
12 * A categorization determines for what part of traffic certain demand data is applicable. By default, this is always for a
13 * given origin-destination pair and time period. A categorization adds to this additional segregation. For example, per lane,
14 * per vehicle class, etc.
15 * <p>
16 * Copyright (c) 2013-2018 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
17 * BSD-style license. See <a href="http://opentrafficsim.org/docs/current/license.html">OpenTrafficSim License</a>.
18 * <p>
19 * @version $Revision$, $LastChangedDate$, by $Author$, initial version Sep 15, 2016 <br>
20 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
21 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
22 * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
23 */
24 public class Categorization implements Serializable, Identifiable
25 {
26
27 /** Empty categorization. */
28 public static final Categorization UNCATEGORIZED = new Categorization("Uncategorized");
29
30 /** */
31 private static final long serialVersionUID = 20160921L;
32
33 /** Id. */
34 private final String id;
35
36 /** Set of categorization classes. */
37 private final List<Class<?>> classes = new ArrayList<>();
38
39 /**
40 * @param id id
41 */
42 private Categorization(final String id)
43 {
44 Throw.whenNull(id, "Id may not be null.");
45 this.id = id;
46 }
47
48 /**
49 * @param id Id
50 * @param class1 1st class
51 * @param classes other classes
52 * @throws IllegalArgumentException if any class is given multiple times
53 * @throws NullPointerException if any input is null
54 */
55 public Categorization(final String id, final Class<?> class1, final Class<?>... classes)
56 {
57 this(id);
58 Throw.whenNull(class1, "Classes may not be null.");
59 this.classes.add(class1);
60 for (Class<?> clazz : classes)
61 {
62 Throw.whenNull(clazz, "Classes may not be null.");
63 Throw.when(this.classes.contains(clazz), IllegalArgumentException.class, "Class %s is given multiple times.",
64 clazz);
65 this.classes.add(clazz);
66 }
67 }
68
69 /**
70 * Returns the number of category classes defined.
71 * @return number of category classes defined
72 */
73 public final int size()
74 {
75 return this.classes.size();
76 }
77
78 /**
79 * Returns the i'th class.
80 * @param i index of the class
81 * @return the i'th class
82 * @throws IndexOutOfBoundsException if index i is out of bounds
83 */
84 public final Class<?> get(final int i)
85 {
86 Throw.when(i < 0 || i >= size(), IndexOutOfBoundsException.class,
87 "Index %d is out of range for categorization of size %d.", i, size());
88 return this.classes.get(i);
89 }
90
91 /**
92 * @return id.
93 */
94 @Override
95 public final String getId()
96 {
97 return this.id;
98 }
99
100 /**
101 * Returns whether the categorization contains a class that is, or is a sub type of, the given class.
102 * @param clazz Class; class to check
103 * @return whether the categorization contains a class that is, or is a sub type of, the given class
104 */
105 public final boolean entails(final Class<?> clazz)
106 {
107 for (Class<?> clazz2 : this.classes)
108 {
109 if (clazz.isAssignableFrom(clazz2))
110 {
111 return true;
112 }
113 }
114 return false;
115 }
116
117 /** {@inheritDoc} */
118 @Override
119 public final int hashCode()
120 {
121 final int prime = 31;
122 int result = 1;
123 result = prime * result + ((this.classes == null) ? 0 : this.classes.hashCode());
124 return result;
125 }
126
127 /** {@inheritDoc} */
128 @Override
129 public final boolean equals(final Object obj)
130 {
131 if (this == obj)
132 {
133 return true;
134 }
135 if (obj == null)
136 {
137 return false;
138 }
139 if (getClass() != obj.getClass())
140 {
141 return false;
142 }
143 Categorization other = (Categorization) obj;
144 if (this.classes == null)
145 {
146 if (other.classes != null)
147 {
148 return false;
149 }
150 }
151 else if (!this.classes.equals(other.classes))
152 {
153 return false;
154 }
155 return true;
156 }
157
158 /** {@inheritDoc} */
159 @Override
160 public final String toString()
161 {
162 return "Categorization [id=" + this.id + ", classes=" + this.classes + "]";
163 }
164
165 }