View Javadoc
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.djutils.exceptions.Throw;
8   
9   /**
10   * A category is a set of objects who's class belongs to a certain categorization. One {@code Category} object can specify to
11   * which subset of traffic between on origin and destination certain demand data belongs.
12   * <p>
13   * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
14   * BSD-style license. See <a href="http://opentrafficsim.org/docs/current/license.html">OpenTrafficSim License</a>.
15   * <p>
16   * @version $Revision$, $LastChangedDate$, by $Author$, initial version Sep 15, 2016 <br>
17   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
18   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
19   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
20   */
21  public class Category implements Serializable
22  {
23  
24      /** Empty category. */
25      public static final Category UNCATEGORIZED = new Category(Categorization.UNCATEGORIZED);
26  
27      /** */
28      private static final long serialVersionUID = 20160921L;
29  
30      /** Categorization. */
31      private final Categorization categorization;
32  
33      /** List of objects defining the category. */
34      private final List<Object> objects = new ArrayList<>();
35  
36      /**
37       * @param categorization Categorization; categorization
38       */
39      private Category(final Categorization categorization)
40      {
41          Throw.whenNull(categorization, "Categorization may not be null.");
42          this.categorization = categorization;
43      }
44  
45      /**
46       * @param categorization Categorization; categorization
47       * @param object1 Object; 1st object
48       * @param objects Object...; other objects
49       * @throws IllegalArgumentException if the objects do not comply with the categorization
50       * @throws NullPointerException if any input is null
51       */
52      public Category(final Categorization categorization, final Object object1, final Object... objects)
53      {
54          this(categorization);
55          Throw.when(categorization.size() != objects.length + 1, IllegalArgumentException.class,
56                  "Objects do not comply with the categorization; bad number of objects.");
57          Throw.whenNull(object1, "Objects may not be null.");
58          Throw.when(!categorization.get(0).isAssignableFrom(object1.getClass()), IllegalArgumentException.class,
59                  "Objects do not comply with the categorization; object 1 is of type %s, should be %s.", object1.getClass(),
60                  categorization.get(0));
61          for (int i = 1; i < categorization.size(); i++)
62          {
63              Throw.whenNull(objects[i - 1], "Objects may not be null.");
64              Throw.when(!categorization.get(i).isAssignableFrom(objects[i - 1].getClass()), IllegalArgumentException.class,
65                      "Objects do not comply with the categorization; object %d is of type %s, should be %s.", i + 1,
66                      objects[i - 1].getClass(), categorization.get(i));
67          }
68          this.objects.add(object1);
69          for (Object object : objects)
70          {
71              this.objects.add(object);
72          }
73      }
74  
75      /**
76       * Returns the i'th object.
77       * @param i int; index of the object
78       * @return the i'th object
79       * @throws IndexOutOfBoundsException if index i is out of bounds
80       */
81      public final Object get(final int i)
82      {
83          Throw.when(i < 0 || i >= this.objects.size(), IndexOutOfBoundsException.class,
84                  "Index %d is out of range for categorization of size %d", i, this.objects.size());
85          return this.objects.get(i);
86      }
87  
88      /**
89       * @return categorization.
90       */
91      public final Categorization getCategorization()
92      {
93          return this.categorization;
94      }
95  
96      /**
97       * Returns the object of this category pertaining to the specified class from the category.
98       * @param clazz Class&lt;T&gt;; class from categorization to get the category object for
99       * @param <T> type of the object
100      * @return Object; object of this category pertaining to the specified class from the category
101      */
102     @SuppressWarnings("unchecked")
103     public final <T> T get(final Class<T> clazz)
104     {
105         Throw.when(!this.categorization.entails(clazz), RuntimeException.class,
106                 "Trying to get a categorization object by class, with the class not belonging to the categorization.");
107         for (Object obj : this.objects)
108         {
109             if (clazz.isAssignableFrom(obj.getClass()))
110             {
111                 return (T) obj; // assignable so safe
112             }
113         }
114         throw new RuntimeException(
115                 "Categorization contains no object assignable to given class, even though the categorization entails the class.");
116     }
117 
118     /** {@inheritDoc} */
119     @Override
120     public final int hashCode()
121     {
122         final int prime = 31;
123         int result = 1;
124         result = prime * result + ((this.categorization == null) ? 0 : this.categorization.hashCode());
125         result = prime * result + ((this.objects == null) ? 0 : this.objects.hashCode());
126         return result;
127     }
128 
129     /** {@inheritDoc} */
130     @Override
131     public final boolean equals(final Object obj)
132     {
133         if (this == obj)
134         {
135             return true;
136         }
137         if (obj == null)
138         {
139             return false;
140         }
141         if (getClass() != obj.getClass())
142         {
143             return false;
144         }
145         Category other = (Category) obj;
146         if (this.categorization == null)
147         {
148             if (other.categorization != null)
149             {
150                 return false;
151             }
152         }
153         else if (!this.categorization.equals(other.categorization))
154         {
155             return false;
156         }
157         if (this.objects == null)
158         {
159             if (other.objects != null)
160             {
161                 return false;
162             }
163         }
164         else if (!this.objects.equals(other.objects))
165         {
166             return false;
167         }
168         return true;
169     }
170 
171     /** {@inheritDoc} */
172     @Override
173     public final String toString()
174     {
175         return "Category [" + this.objects + "]";
176     }
177 
178 }