1 package org.djutils.metadata;
2
3 import java.io.Serializable;
4 import java.util.Arrays;
5
6 import org.djutils.exceptions.Throw;
7
8
9
10
11
12
13
14
15
16
17 public class MetaData implements Serializable
18 {
19
20 private static final long serialVersionUID = 20200417L;
21
22
23 private final String name;
24
25
26 private final String description;
27
28
29 private final ObjectDescriptor[] objectDescriptors;
30
31
32 public static final MetaData EMPTY = new MetaData("No data", "No data", new ObjectDescriptor[0]);
33
34
35 public static final MetaData NO_META_DATA = new MetaData("No descriptive meta data provided", "Any payload is accepted",
36 new ObjectDescriptor("No descriptive meta data provided", "Any payload is accepted", Object.class));
37
38
39
40
41
42
43
44
45
46 public MetaData(final String name, final String description, final ObjectDescriptor... objectDescriptors)
47 {
48 Throw.whenNull(name, "name may not be null");
49 Throw.when(name.length() == 0, IllegalArgumentException.class, "name cannot be the empty string");
50 Throw.whenNull(description, "description may not be null");
51 for (int i = 0; i < objectDescriptors.length; i++)
52 {
53 ObjectDescriptor objectDescriptor = objectDescriptors[i];
54 Throw.whenNull(objectDescriptor, "objectDescriptor %d may not be null", i);
55 }
56 this.name = name;
57 this.description = description;
58 this.objectDescriptors = objectDescriptors;
59 }
60
61
62
63
64
65 public String getName()
66 {
67 return this.name;
68 }
69
70
71
72
73
74 public String getDescription()
75 {
76 return this.description;
77 }
78
79
80
81
82
83
84 public int size()
85 {
86 return this.objectDescriptors.length;
87 }
88
89
90
91
92
93 public ObjectDescriptor[] getObjectDescriptors()
94 {
95 return this.objectDescriptors.clone();
96 }
97
98
99
100
101
102
103
104 public String getFieldName(final int index)
105 {
106 return getObjectDescriptor(index).getName();
107 }
108
109
110
111
112
113
114
115 public String getObjectDescription(final int index)
116 {
117 return getObjectDescriptor(index).getDescription();
118 }
119
120
121
122
123
124
125
126 public Class<?> getObjectClass(final int index)
127 {
128 return getObjectDescriptor(index).getObjectClass();
129 }
130
131
132
133
134
135
136
137 public ObjectDescriptor getObjectDescriptor(final int index)
138 {
139 Throw.when(index < 0 || index >= this.objectDescriptors.length, IndexOutOfBoundsException.class,
140 "Index < 0 or index >= number of object descriptors");
141 return this.objectDescriptors[index];
142 }
143
144
145
146
147
148
149
150
151
152 public final void verifyComposition(final Object[] objectArray)
153 {
154 if ((size() == 0 || size() == 1) && objectArray == null)
155 {
156 return;
157 }
158 if (this.equals(NO_META_DATA))
159 {
160 return;
161 }
162 Throw.whenNull(objectArray, "objectArray may not be null");
163 Throw.when(objectArray.length != size(), IndexOutOfBoundsException.class,
164 "objectArray for \"%s\" has wrong length (expected %d, got %d)", this.name, size(), objectArray.length);
165 for (int index = 0; index < objectArray.length; index++)
166 {
167 Object object = objectArray[index];
168 if ((null != object) && (!(getObjectClass(index).isAssignableFrom(object.getClass()))))
169 {
170 throw new ClassCastException(String.format("objectArray[%d] (%s) cannot be used for %s", index,
171 objectArray[index], getObjectClass(index).getName()));
172 }
173 }
174 }
175
176
177
178
179
180
181
182
183 public final void verifyComposition(final Object object)
184 {
185 Throw.when(this.objectDescriptors.length != 1, IndexOutOfBoundsException.class,
186 "Testing single object, but length of the object descriptors array is %d", this.objectDescriptors.length);
187 if (this.equals(NO_META_DATA))
188 {
189 return;
190 }
191 Class<?> objectClass = getObjectClass(0);
192 if (!(objectClass.isAssignableFrom(object.getClass())))
193 {
194 throw new ClassCastException(String.format("object (%s) cannot be used for %s", object, objectClass.getName()));
195 }
196 }
197
198 @Override
199 public int hashCode()
200 {
201 final int prime = 31;
202 int result = 1;
203 result = prime * result + this.description.hashCode();
204 result = prime * result + this.name.hashCode();
205 result = prime * result + Arrays.hashCode(this.objectDescriptors);
206 return result;
207 }
208
209 @Override
210 @SuppressWarnings("checkstyle:needbraces")
211 public boolean equals(final Object obj)
212 {
213 if (this == obj)
214 return true;
215 if (obj == null)
216 return false;
217 if (getClass() != obj.getClass())
218 return false;
219 MetaData other = (MetaData) obj;
220 if (!this.name.equals(other.name))
221 return false;
222 if (!this.description.equals(other.description))
223 return false;
224 if (!Arrays.equals(this.objectDescriptors, other.objectDescriptors))
225 return false;
226 return true;
227 }
228
229 @Override
230 public String toString()
231 {
232 return "MetaData [name=" + this.name + ", description=" + this.description + ", objectDescriptors="
233 + Arrays.toString(this.objectDescriptors) + "]";
234 }
235
236 }