View Javadoc
1   package org.opentrafficsim.core.gtu.perception;
2   
3   import java.util.LinkedHashMap;
4   import java.util.Map;
5   
6   import org.opentrafficsim.base.parameters.ParameterException;
7   import org.opentrafficsim.core.gtu.GTU;
8   import org.opentrafficsim.core.gtu.GTUException;
9   import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
10  import org.opentrafficsim.core.network.NetworkException;
11  
12  /**
13   * <p>
14   * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
15   * BSD-style license. See <a href="http://opentrafficsim.org/docs/current/license.html">OpenTrafficSim License</a>.
16   * <p>
17   * @version $Revision$, $LastChangedDate$, by $Author$, initial version Jul 29, 2016 <br>
18   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
19   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
20   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
21   * @param <G> GTU type
22   */
23  public abstract class AbstractPerception<G extends GTU> implements Perception<G>
24  {
25  
26      /** */
27      private static final long serialVersionUID = 20160729L;
28  
29      /** Set of available perception categories. */
30      private final Map<Class<? extends PerceptionCategory<?, ?>>, PerceptionCategory<?, ?>> perceptionCategories =
31              new LinkedHashMap<>();
32  
33      /** Cache, avoiding loop and isAssignableFrom. */
34      private final Map<Class<? extends PerceptionCategory<?, ?>>, PerceptionCategory<?, ?>> cachedCategories =
35              new LinkedHashMap<>();
36  
37      /** GTU. */
38      private G gtu;
39  
40      /**
41       * Construct perception.
42       * @param gtu G; GTU
43       */
44      public AbstractPerception(final G gtu)
45      {
46          this.gtu = gtu;
47      }
48  
49      /** {@inheritDoc} */
50      @Override
51      @SuppressWarnings("checkstyle:designforextension")
52      public G getGtu()
53      {
54          return this.gtu;
55      }
56  
57      /** {@inheritDoc} */
58      @SuppressWarnings("unchecked")
59      @Override
60      public final <T extends PerceptionCategory<?, ?>> void addPerceptionCategory(final T perceptionCategory)
61      {
62          // guarantees correct combination of class and perception category
63          this.perceptionCategories.put((Class<T>) perceptionCategory.getClass(), perceptionCategory);
64          this.cachedCategories.clear();
65      }
66  
67      /** {@inheritDoc} */
68      @Override
69      public final <T extends PerceptionCategory<?, ?>> boolean contains(final Class<T> category)
70      {
71          if (this.cachedCategories.containsKey(category))
72          {
73              return true;
74          }
75          for (Class<?> clazz : this.perceptionCategories.keySet())
76          {
77              if (category.isAssignableFrom(clazz))
78              {
79                  // isAssignableFrom takes care of implementation of the category
80                  this.cachedCategories.put(category, this.perceptionCategories.get(clazz));
81                  return true;
82              }
83          }
84          return false;
85      }
86  
87      /** {@inheritDoc} */
88      @Override
89      public final <T extends PerceptionCategory<?, ?>> T getPerceptionCategory(final Class<T> category)
90              throws OperationalPlanException
91      {
92          T cat = getPerceptionCategoryOrNull(category);
93          if (cat != null)
94          {
95              return cat;
96          }
97          throw new OperationalPlanException("Perception category" + category + " is not present.");
98      }
99  
100     /** {@inheritDoc} */
101     @Override
102     @SuppressWarnings("unchecked")
103     public final <T extends PerceptionCategory<?, ?>> T getPerceptionCategoryOrNull(final Class<T> category)
104     {
105         T implementation = (T) this.cachedCategories.get(category);
106         if (implementation != null)
107         {
108             return implementation;
109         }
110         for (Class<?> clazz : this.perceptionCategories.keySet())
111         {
112             if (category.isAssignableFrom(clazz))
113             {
114                 // addPerceptionCategory guarantees correct combination of class and perception category
115                 // isAssignableFrom takes care of implementation of the category
116                 implementation = (T) this.perceptionCategories.get(clazz);
117                 this.cachedCategories.put(category, implementation);
118                 return implementation;
119             }
120         }
121         return null;
122     }
123 
124     /** {@inheritDoc} */
125     @Override
126     public final void removePerceptionCategory(final PerceptionCategory<?, ?> perceptionCategory)
127     {
128         for (Class<?> category : this.perceptionCategories.keySet())
129         {
130             if (perceptionCategory.getClass().isAssignableFrom(category))
131             {
132                 // addPerceptionCategory guarantees correct combination of class and perception category
133                 // isAssignableFrom takes care of implementation of the category
134                 this.perceptionCategories.remove(perceptionCategory.getClass());
135                 this.cachedCategories.clear();
136                 return;
137             }
138         }
139     }
140 
141     /** {@inheritDoc} */
142     @Override
143     @SuppressWarnings("checkstyle:designforextension")
144     public void perceive() throws GTUException, NetworkException, ParameterException
145     {
146         for (PerceptionCategory<?, ?> category : this.perceptionCategories.values())
147         {
148             category.updateAll();
149         }
150     }
151 
152     /** {@inheritDoc} */
153     @Override
154     @SuppressWarnings("checkstyle:designforextension")
155     public String toString()
156     {
157         StringBuilder s = new StringBuilder("Perception [");
158         String sep = "";
159         for (PerceptionCategory<?, ?> cat : this.perceptionCategories.values())
160         {
161             s.append(sep);
162             s.append(cat);
163             sep = ", ";
164         }
165         s.append("]");
166         return s.toString();
167     }
168 
169 }