Skip to content

Commit

Permalink
Default column name to pojo field name, and add allFields mode to `…
Browse files Browse the repository at this point in the history
…Measurement` annotation (#972)
  • Loading branch information
eranl authored Dec 2, 2023
1 parent d3a7bbc commit ba9bfeb
Show file tree
Hide file tree
Showing 8 changed files with 309 additions and 67 deletions.
29 changes: 24 additions & 5 deletions MANUAL.md
Original file line number Diff line number Diff line change
Expand Up @@ -323,21 +323,40 @@ public class Cpu {
}
```

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

```Java
@Measurement(name = "cpu")
public class Cpu {
@TimeColumn
@Column(name = "time")
@Column
private Instant time;
@Column(name = "host", tag = true)
private String hostname;
@Column(name = "region", tag = true)
@Column(tag = true)
private String region;
@Column
private Double idle;
@Column
private Boolean happydevop;
@Column(name = "uptimesecs")
private Long uptimeSecs;
// getters (and setters if you need)
}
```

Alternatively, you can use:

```Java
@Measurement(name = "cpu", allFields = true)
public class Cpu {
@TimeColumn
private Instant time;
@Column(name = "host", tag = true)
private String hostname;
@Column(tag = true)
private String region;
@Column(name = "idle")
private Double idle;
@Column(name = "happydevop")
private Boolean happydevop;
@Column(name = "uptimesecs")
private Long uptimeSecs;
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/org/influxdb/annotation/Column.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@
@Target(ElementType.FIELD)
public @interface Column {

String name();
/**
* If unset, the annotated field's name will be used as the column name.
*/
String name() default "";

boolean tag() default false;
}
38 changes: 38 additions & 0 deletions src/main/java/org/influxdb/annotation/Exclude.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2017 azeti Networks AG (<[email protected]>)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package org.influxdb.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* When a POJO annotated with {@code @Measurement(allFields = true)} is loaded or saved,
* this annotation can be used to exclude some of its fields.
* @see Measurement#allFields()
*
* @author Eran Leshem
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Exclude {
}
7 changes: 7 additions & 0 deletions src/main/java/org/influxdb/annotation/Measurement.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,11 @@
String retentionPolicy() default "autogen";

TimeUnit timeUnit() default TimeUnit.MILLISECONDS;

/**
* If {@code true}, then all non-static fields of this measurement will be loaded or saved,
* regardless of any {@code @Column} annotations.
* @see Exclude
*/
boolean allFields() default false;
}
44 changes: 29 additions & 15 deletions src/main/java/org/influxdb/dto/Point.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
package org.influxdb.dto;

import org.influxdb.BuilderException;
import org.influxdb.annotation.Column;
import org.influxdb.annotation.Exclude;
import org.influxdb.annotation.Measurement;
import org.influxdb.annotation.TimeColumn;
import org.influxdb.impl.Preconditions;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
Expand All @@ -11,14 +19,9 @@
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.TreeMap;
import java.util.Optional;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;
import org.influxdb.BuilderException;
import org.influxdb.annotation.Column;
import org.influxdb.annotation.Measurement;
import org.influxdb.annotation.TimeColumn;
import org.influxdb.impl.Preconditions;

/**
* Representation of a InfluxDB database Point.
Expand Down Expand Up @@ -276,23 +279,34 @@ public boolean hasFields() {
*/
public Builder addFieldsFromPOJO(final Object pojo) {

Class<? extends Object> clazz = pojo.getClass();
Class<?> clazz = pojo.getClass();
Measurement measurement = clazz.getAnnotation(Measurement.class);
boolean allFields = measurement != null && measurement.allFields();

while (clazz != null) {

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

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

if (column == null) {
if (column == null && !(allFields
&& !field.isAnnotationPresent(Exclude.class) && !Modifier.isStatic(field.getModifiers()))) {
continue;
}

field.setAccessible(true);
String fieldName = column.name();
addFieldByAttribute(pojo, field, column, fieldName);

String fieldName;
if (column != null && !column.name().isEmpty()) {
fieldName = column.name();
} else {
fieldName = field.getName();
}

addFieldByAttribute(pojo, field, column != null && column.tag(), fieldName);
}
clazz = clazz.getSuperclass();
}
clazz = clazz.getSuperclass();
}

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

private void addFieldByAttribute(final Object pojo, final Field field, final Column column,
final String fieldName) {
private void addFieldByAttribute(final Object pojo, final Field field, final boolean tag,
final String fieldName) {
try {
Object fieldValue = field.get(pojo);

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

if (column.tag()) {
if (tag) {
if (fieldValue != null) {
this.tags.put(fieldName, (String) fieldValue);
}
Expand Down
56 changes: 34 additions & 22 deletions src/main/java/org/influxdb/impl/InfluxDBResultMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,14 @@
*/
package org.influxdb.impl;

import org.influxdb.InfluxDBMapperException;
import org.influxdb.annotation.Column;
import org.influxdb.annotation.Exclude;
import org.influxdb.annotation.Measurement;
import org.influxdb.dto.QueryResult;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
Expand All @@ -33,11 +40,6 @@
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;

import org.influxdb.InfluxDBMapperException;
import org.influxdb.annotation.Column;
import org.influxdb.annotation.Measurement;
import org.influxdb.dto.QueryResult;

/**
* Main class responsible for mapping a QueryResult to a POJO.
*
Expand Down Expand Up @@ -213,20 +215,34 @@ void cacheMeasurementClass(final Class<?>... classVarAgrs) {
}
ConcurrentMap<String, Field> influxColumnAndFieldMap = new ConcurrentHashMap<>();

Measurement measurement = clazz.getAnnotation(Measurement.class);
boolean allFields = measurement != null && measurement.allFields();

Class<?> c = clazz;
while (c != null) {
for (Field field : c.getDeclaredFields()) {
Column colAnnotation = field.getAnnotation(Column.class);
if (colAnnotation != null) {
influxColumnAndFieldMap.put(colAnnotation.name(), field);
if (colAnnotation == null && !(allFields
&& !field.isAnnotationPresent(Exclude.class) && !Modifier.isStatic(field.getModifiers()))) {
continue;
}

influxColumnAndFieldMap.put(getFieldName(field, colAnnotation), field);
}
c = c.getSuperclass();
}
CLASS_FIELD_CACHE.putIfAbsent(clazz.getName(), influxColumnAndFieldMap);
}
}

private static String getFieldName(final Field field, final Column colAnnotation) {
if (colAnnotation != null && !colAnnotation.name().isEmpty()) {
return colAnnotation.name();
}

return field.getName();
}

String getMeasurementName(final Class<?> clazz) {
return ((Measurement) clazz.getAnnotation(Measurement.class)).name();
}
Expand Down Expand Up @@ -289,17 +305,11 @@ <T> List<T> parseSeriesAs(final QueryResult.Series series, final Class<T> clazz,

/**
* InfluxDB client returns any number as Double.
* See https://github.com/influxdata/influxdb-java/issues/153#issuecomment-259681987
* See <a href="https://github.com/influxdata/influxdb-java/issues/153#issuecomment-259681987">...</a>
* for more information.
*
* @param object
* @param field
* @param value
* @param precision
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
<T> void setFieldValue(final T object, final Field field, final Object value, final TimeUnit precision)
private static <T> void setFieldValue(final T object, final Field field, final Object value, final TimeUnit precision)
throws IllegalArgumentException, IllegalAccessException {
if (value == null) {
return;
Expand All @@ -325,8 +335,8 @@ <T> void setFieldValue(final T object, final Field field, final Object value, fi
}
}

<T> boolean fieldValueModified(final Class<?> fieldType, final Field field, final T object, final Object value,
final TimeUnit precision)
static <T> boolean fieldValueModified(final Class<?> fieldType, final Field field, final T object, final Object value,
final TimeUnit precision)
throws IllegalArgumentException, IllegalAccessException {
if (String.class.isAssignableFrom(fieldType)) {
field.set(object, String.valueOf(value));
Expand All @@ -351,8 +361,9 @@ <T> boolean fieldValueModified(final Class<?> fieldType, final Field field, fina
return false;
}

<T> boolean fieldValueForPrimitivesModified(final Class<?> fieldType, final Field field, final T object,
final Object value) throws IllegalArgumentException, IllegalAccessException {
static <T> boolean fieldValueForPrimitivesModified(final Class<?> fieldType, final Field field, final T object,
final Object value)
throws IllegalArgumentException, IllegalAccessException {
if (double.class.isAssignableFrom(fieldType)) {
field.setDouble(object, ((Double) value).doubleValue());
return true;
Expand All @@ -372,8 +383,9 @@ <T> boolean fieldValueForPrimitivesModified(final Class<?> fieldType, final Fiel
return false;
}

<T> boolean fieldValueForPrimitiveWrappersModified(final Class<?> fieldType, final Field field, final T object,
final Object value) throws IllegalArgumentException, IllegalAccessException {
static <T> boolean fieldValueForPrimitiveWrappersModified(final Class<?> fieldType, final Field field, final T object,
final Object value)
throws IllegalArgumentException, IllegalAccessException {
if (Double.class.isAssignableFrom(fieldType)) {
field.set(object, value);
return true;
Expand All @@ -393,7 +405,7 @@ <T> boolean fieldValueForPrimitiveWrappersModified(final Class<?> fieldType, fin
return false;
}

private Long toMillis(final long value, final TimeUnit precision) {
private static Long toMillis(final long value, final TimeUnit precision) {

return TimeUnit.MILLISECONDS.convert(value, precision);
}
Expand Down
Loading

0 comments on commit ba9bfeb

Please sign in to comment.