View Javadoc
1   package org.djutils.data;
2   
3   import java.io.Serializable;
4   import java.lang.reflect.InvocationTargetException;
5   import java.lang.reflect.Method;
6   import java.util.Objects;
7   
8   import org.djunits.value.Value;
9   import org.djunits.value.base.Scalar;
10  import org.djutils.base.Identifiable;
11  import org.djutils.exceptions.Throw;
12  import org.djutils.primitives.Primitive;
13  
14  /**
15   * Column identifier and descriptor.
16   * <p>
17   * Copyright (c) 2020-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
18   * BSD-style license. See <a href="https://djutils.org/docs/current/djutils/licenses.html">DJUTILS License</a>.
19   * </p>
20   * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
21   * @author <a href="https://tudelft.nl/staff/p.knoppers-1">Peter Knoppers</a>
22   * @author <a href="https://dittlab.tudelft.nl">Wouter Schakel</a>
23   * @param <T> value type
24   */
25  public class Column<T> implements Identifiable, Serializable
26  {
27  
28      /** */
29      private static final long serialVersionUID = 20230125L;
30  
31      /** Id. */
32      private final String id;
33  
34      /** Description. */
35      private final String description;
36  
37      /** Value type. */
38      private final Class<T> valueType;
39  
40      /** Unit. */
41      private final String unit;
42  
43      /**
44       * Make a new column for a table with an id, description, type, and unit.
45       * @param id String; id of the column
46       * @param description String; description of the column
47       * @param valueType Class&lt;T&gt;; value type of the column
48       * @param unit String; unit, may be {@code null}
49       */
50      @SuppressWarnings("unchecked")
51      public Column(final String id, final String description, final Class<T> valueType, final String unit)
52      {
53          Throw.whenNull(id, "id may not be null.");
54          Throw.when(id.length() == 0, IllegalArgumentException.class, "id cannot be empty");
55          Throw.whenNull(description, "description may not be null.");
56          Throw.whenNull(valueType, "valueType may not be null.");
57          this.id = id;
58          this.description = description;
59          this.valueType = valueType.isPrimitive() ? (Class<T>) Primitive.getWrapper(valueType) : valueType;
60          Throw.when(Value.class.isAssignableFrom(valueType) && (unit == null || unit.length() == 0),
61                  IllegalArgumentException.class, "For a DJUNITS value, unit cannot be null or the empty string");
62          if (Scalar.class.isAssignableFrom(valueType))
63          {
64              try
65              {
66                  Method valueOfMethod = valueType.getDeclaredMethod("valueOf", String.class);
67                  valueOfMethod.invoke(null, "1.0" + unit);
68              }
69              catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
70                      | SecurityException exception)
71              {
72                  throw new IllegalArgumentException(
73                          "unit of the Column does not belong to Scalar of type " + valueType.getSimpleName());
74              }
75          }
76          this.unit = unit;
77      }
78  
79      /**
80       * Make a new column for a table with an id, description, type. The unit is blank (null).
81       * @param id String; id of the column
82       * @param description String; description of the column
83       * @param valueType Class&lt;T&gt;; value type of the column
84       */
85      public Column(final String id, final String description, final Class<T> valueType)
86      {
87          this(id, description, valueType, null);
88      }
89  
90      @Override
91      public String getId()
92      {
93          return this.id;
94      }
95  
96      /**
97       * Returns the column description.
98       * @return String; column description
99       */
100     public String getDescription()
101     {
102         return this.description;
103     }
104 
105     /**
106      * Returns the type of the values in the column.
107      * @return Class&lt;?&gt;; type of the values in the column
108      */
109     public Class<T> getValueType()
110     {
111         return this.valueType;
112     }
113 
114     /**
115      * Returns the unit of the column. Data is written an read using this unit.
116      * @return String; unit of the column
117      */
118     public String getUnit()
119     {
120         return this.unit;
121     }
122 
123     @Override
124     public int hashCode()
125     {
126         return Objects.hash(this.id);
127     }
128 
129     @Override
130     public boolean equals(final Object obj)
131     {
132         if (this == obj)
133         {
134             return true;
135         }
136         if (obj == null)
137         {
138             return false;
139         }
140         if (getClass() != obj.getClass())
141         {
142             return false;
143         }
144         Column<?> other = (Column<?>) obj;
145         return Objects.equals(this.id, other.id);
146     }
147 
148     @Override
149     public String toString()
150     {
151         return "Column [id=" + this.id + ", description=" + this.description + ", valueType=" + this.valueType
152                 + (this.unit == null ? "]" : ", unit=" + this.unit + "]");
153     }
154 
155 }