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