Skip to content

Commit ba9bfeb

Browse files
authored
Default column name to pojo field name, and add allFields mode to Measurement annotation (#972)
1 parent d3a7bbc commit ba9bfeb

File tree

8 files changed

+309
-67
lines changed

8 files changed

+309
-67
lines changed

MANUAL.md

+24-5
Original file line numberDiff line numberDiff line change
@@ -323,21 +323,40 @@ public class Cpu {
323323
}
324324
```
325325

326-
2. Add @Measurement,@TimeColumn and @Column annotations:
326+
2. Add @Measurement,@TimeColumn and @Column annotations (column names default to field names unless otherwise specified):
327327

328328
```Java
329329
@Measurement(name = "cpu")
330330
public class Cpu {
331331
@TimeColumn
332-
@Column(name = "time")
332+
@Column
333333
private Instant time;
334334
@Column(name = "host", tag = true)
335335
private String hostname;
336-
@Column(name = "region", tag = true)
336+
@Column(tag = true)
337+
private String region;
338+
@Column
339+
private Double idle;
340+
@Column
341+
private Boolean happydevop;
342+
@Column(name = "uptimesecs")
343+
private Long uptimeSecs;
344+
// getters (and setters if you need)
345+
}
346+
```
347+
348+
Alternatively, you can use:
349+
350+
```Java
351+
@Measurement(name = "cpu", allFields = true)
352+
public class Cpu {
353+
@TimeColumn
354+
private Instant time;
355+
@Column(name = "host", tag = true)
356+
private String hostname;
357+
@Column(tag = true)
337358
private String region;
338-
@Column(name = "idle")
339359
private Double idle;
340-
@Column(name = "happydevop")
341360
private Boolean happydevop;
342361
@Column(name = "uptimesecs")
343362
private Long uptimeSecs;

src/main/java/org/influxdb/annotation/Column.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@
3232
@Target(ElementType.FIELD)
3333
public @interface Column {
3434

35-
String name();
35+
/**
36+
* If unset, the annotated field's name will be used as the column name.
37+
*/
38+
String name() default "";
3639

3740
boolean tag() default false;
3841
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* The MIT License (MIT)
3+
*
4+
* Copyright (c) 2017 azeti Networks AG (<[email protected]>)
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
7+
* associated documentation files (the "Software"), to deal in the Software without restriction,
8+
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
9+
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in all copies or
13+
* substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
16+
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18+
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20+
*/
21+
package org.influxdb.annotation;
22+
23+
import java.lang.annotation.ElementType;
24+
import java.lang.annotation.Retention;
25+
import java.lang.annotation.RetentionPolicy;
26+
import java.lang.annotation.Target;
27+
28+
/**
29+
* When a POJO annotated with {@code @Measurement(allFields = true)} is loaded or saved,
30+
* this annotation can be used to exclude some of its fields.
31+
* @see Measurement#allFields()
32+
*
33+
* @author Eran Leshem
34+
*/
35+
@Retention(RetentionPolicy.RUNTIME)
36+
@Target(ElementType.FIELD)
37+
public @interface Exclude {
38+
}

src/main/java/org/influxdb/annotation/Measurement.java

+7
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,11 @@
4040
String retentionPolicy() default "autogen";
4141

4242
TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
43+
44+
/**
45+
* If {@code true}, then all non-static fields of this measurement will be loaded or saved,
46+
* regardless of any {@code @Column} annotations.
47+
* @see Exclude
48+
*/
49+
boolean allFields() default false;
4350
}

src/main/java/org/influxdb/dto/Point.java

+29-15
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
package org.influxdb.dto;
22

3+
import org.influxdb.BuilderException;
4+
import org.influxdb.annotation.Column;
5+
import org.influxdb.annotation.Exclude;
6+
import org.influxdb.annotation.Measurement;
7+
import org.influxdb.annotation.TimeColumn;
8+
import org.influxdb.impl.Preconditions;
9+
310
import java.lang.annotation.Annotation;
411
import java.lang.reflect.Field;
12+
import java.lang.reflect.Modifier;
513
import java.math.BigDecimal;
614
import java.math.BigInteger;
715
import java.math.RoundingMode;
@@ -11,14 +19,9 @@
1119
import java.util.Map;
1220
import java.util.Map.Entry;
1321
import java.util.Objects;
14-
import java.util.TreeMap;
1522
import java.util.Optional;
23+
import java.util.TreeMap;
1624
import java.util.concurrent.TimeUnit;
17-
import org.influxdb.BuilderException;
18-
import org.influxdb.annotation.Column;
19-
import org.influxdb.annotation.Measurement;
20-
import org.influxdb.annotation.TimeColumn;
21-
import org.influxdb.impl.Preconditions;
2225

2326
/**
2427
* Representation of a InfluxDB database Point.
@@ -276,23 +279,34 @@ public boolean hasFields() {
276279
*/
277280
public Builder addFieldsFromPOJO(final Object pojo) {
278281

279-
Class<? extends Object> clazz = pojo.getClass();
282+
Class<?> clazz = pojo.getClass();
283+
Measurement measurement = clazz.getAnnotation(Measurement.class);
284+
boolean allFields = measurement != null && measurement.allFields();
285+
280286
while (clazz != null) {
281287

282288
for (Field field : clazz.getDeclaredFields()) {
283289

284290
Column column = field.getAnnotation(Column.class);
285291

286-
if (column == null) {
292+
if (column == null && !(allFields
293+
&& !field.isAnnotationPresent(Exclude.class) && !Modifier.isStatic(field.getModifiers()))) {
287294
continue;
288295
}
289296

290297
field.setAccessible(true);
291-
String fieldName = column.name();
292-
addFieldByAttribute(pojo, field, column, fieldName);
298+
299+
String fieldName;
300+
if (column != null && !column.name().isEmpty()) {
301+
fieldName = column.name();
302+
} else {
303+
fieldName = field.getName();
304+
}
305+
306+
addFieldByAttribute(pojo, field, column != null && column.tag(), fieldName);
293307
}
294-
clazz = clazz.getSuperclass();
295-
}
308+
clazz = clazz.getSuperclass();
309+
}
296310

297311
if (this.fields.isEmpty()) {
298312
throw new BuilderException("Class " + pojo.getClass().getName()
@@ -302,8 +316,8 @@ public Builder addFieldsFromPOJO(final Object pojo) {
302316
return this;
303317
}
304318

305-
private void addFieldByAttribute(final Object pojo, final Field field, final Column column,
306-
final String fieldName) {
319+
private void addFieldByAttribute(final Object pojo, final Field field, final boolean tag,
320+
final String fieldName) {
307321
try {
308322
Object fieldValue = field.get(pojo);
309323

@@ -325,7 +339,7 @@ private void addFieldByAttribute(final Object pojo, final Field field, final Col
325339
return;
326340
}
327341

328-
if (column.tag()) {
342+
if (tag) {
329343
if (fieldValue != null) {
330344
this.tags.put(fieldName, (String) fieldValue);
331345
}

src/main/java/org/influxdb/impl/InfluxDBResultMapper.java

+34-22
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,14 @@
2020
*/
2121
package org.influxdb.impl;
2222

23+
import org.influxdb.InfluxDBMapperException;
24+
import org.influxdb.annotation.Column;
25+
import org.influxdb.annotation.Exclude;
26+
import org.influxdb.annotation.Measurement;
27+
import org.influxdb.dto.QueryResult;
28+
2329
import java.lang.reflect.Field;
30+
import java.lang.reflect.Modifier;
2431
import java.time.Instant;
2532
import java.time.format.DateTimeFormatter;
2633
import java.time.format.DateTimeFormatterBuilder;
@@ -33,11 +40,6 @@
3340
import java.util.concurrent.ConcurrentMap;
3441
import java.util.concurrent.TimeUnit;
3542

36-
import org.influxdb.InfluxDBMapperException;
37-
import org.influxdb.annotation.Column;
38-
import org.influxdb.annotation.Measurement;
39-
import org.influxdb.dto.QueryResult;
40-
4143
/**
4244
* Main class responsible for mapping a QueryResult to a POJO.
4345
*
@@ -213,20 +215,34 @@ void cacheMeasurementClass(final Class<?>... classVarAgrs) {
213215
}
214216
ConcurrentMap<String, Field> influxColumnAndFieldMap = new ConcurrentHashMap<>();
215217

218+
Measurement measurement = clazz.getAnnotation(Measurement.class);
219+
boolean allFields = measurement != null && measurement.allFields();
220+
216221
Class<?> c = clazz;
217222
while (c != null) {
218223
for (Field field : c.getDeclaredFields()) {
219224
Column colAnnotation = field.getAnnotation(Column.class);
220-
if (colAnnotation != null) {
221-
influxColumnAndFieldMap.put(colAnnotation.name(), field);
225+
if (colAnnotation == null && !(allFields
226+
&& !field.isAnnotationPresent(Exclude.class) && !Modifier.isStatic(field.getModifiers()))) {
227+
continue;
222228
}
229+
230+
influxColumnAndFieldMap.put(getFieldName(field, colAnnotation), field);
223231
}
224232
c = c.getSuperclass();
225233
}
226234
CLASS_FIELD_CACHE.putIfAbsent(clazz.getName(), influxColumnAndFieldMap);
227235
}
228236
}
229237

238+
private static String getFieldName(final Field field, final Column colAnnotation) {
239+
if (colAnnotation != null && !colAnnotation.name().isEmpty()) {
240+
return colAnnotation.name();
241+
}
242+
243+
return field.getName();
244+
}
245+
230246
String getMeasurementName(final Class<?> clazz) {
231247
return ((Measurement) clazz.getAnnotation(Measurement.class)).name();
232248
}
@@ -289,17 +305,11 @@ <T> List<T> parseSeriesAs(final QueryResult.Series series, final Class<T> clazz,
289305

290306
/**
291307
* InfluxDB client returns any number as Double.
292-
* See https://github.com/influxdata/influxdb-java/issues/153#issuecomment-259681987
308+
* See <a href="https://github.com/influxdata/influxdb-java/issues/153#issuecomment-259681987">...</a>
293309
* for more information.
294310
*
295-
* @param object
296-
* @param field
297-
* @param value
298-
* @param precision
299-
* @throws IllegalArgumentException
300-
* @throws IllegalAccessException
301311
*/
302-
<T> void setFieldValue(final T object, final Field field, final Object value, final TimeUnit precision)
312+
private static <T> void setFieldValue(final T object, final Field field, final Object value, final TimeUnit precision)
303313
throws IllegalArgumentException, IllegalAccessException {
304314
if (value == null) {
305315
return;
@@ -325,8 +335,8 @@ <T> void setFieldValue(final T object, final Field field, final Object value, fi
325335
}
326336
}
327337

328-
<T> boolean fieldValueModified(final Class<?> fieldType, final Field field, final T object, final Object value,
329-
final TimeUnit precision)
338+
static <T> boolean fieldValueModified(final Class<?> fieldType, final Field field, final T object, final Object value,
339+
final TimeUnit precision)
330340
throws IllegalArgumentException, IllegalAccessException {
331341
if (String.class.isAssignableFrom(fieldType)) {
332342
field.set(object, String.valueOf(value));
@@ -351,8 +361,9 @@ <T> boolean fieldValueModified(final Class<?> fieldType, final Field field, fina
351361
return false;
352362
}
353363

354-
<T> boolean fieldValueForPrimitivesModified(final Class<?> fieldType, final Field field, final T object,
355-
final Object value) throws IllegalArgumentException, IllegalAccessException {
364+
static <T> boolean fieldValueForPrimitivesModified(final Class<?> fieldType, final Field field, final T object,
365+
final Object value)
366+
throws IllegalArgumentException, IllegalAccessException {
356367
if (double.class.isAssignableFrom(fieldType)) {
357368
field.setDouble(object, ((Double) value).doubleValue());
358369
return true;
@@ -372,8 +383,9 @@ <T> boolean fieldValueForPrimitivesModified(final Class<?> fieldType, final Fiel
372383
return false;
373384
}
374385

375-
<T> boolean fieldValueForPrimitiveWrappersModified(final Class<?> fieldType, final Field field, final T object,
376-
final Object value) throws IllegalArgumentException, IllegalAccessException {
386+
static <T> boolean fieldValueForPrimitiveWrappersModified(final Class<?> fieldType, final Field field, final T object,
387+
final Object value)
388+
throws IllegalArgumentException, IllegalAccessException {
377389
if (Double.class.isAssignableFrom(fieldType)) {
378390
field.set(object, value);
379391
return true;
@@ -393,7 +405,7 @@ <T> boolean fieldValueForPrimitiveWrappersModified(final Class<?> fieldType, fin
393405
return false;
394406
}
395407

396-
private Long toMillis(final long value, final TimeUnit precision) {
408+
private static Long toMillis(final long value, final TimeUnit precision) {
397409

398410
return TimeUnit.MILLISECONDS.convert(value, precision);
399411
}

0 commit comments

Comments
 (0)