Skip to content

Commit 1dafcc1

Browse files
mirza99fmachado
authored andcommitted
Features/add fields by pojo (#519)
* Map Object to Point * Adding fields to builder by passing a POJO * Removing annotation support on accessors * Removing unused private method * Adding documentation
1 parent d9c9e49 commit 1dafcc1

File tree

4 files changed

+394
-5
lines changed

4 files changed

+394
-5
lines changed

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,22 @@ InfluxDBResultMapper resultMapper = new InfluxDBResultMapper(); // thread-safe -
263263
List<Cpu> cpuList = resultMapper.toPOJO(queryResult, Cpu.class);
264264
```
265265

266+
#### Writing using POJO
267+
The same way we use `annotations` to transform data to POJO, we can write data as POJO.
268+
Having the same POJO class Cpu
269+
270+
```java
271+
String dbName = "myTimeseries";
272+
String rpName = "aRetentionPolicy";
273+
// Cpu has annotations @Measurement and @Column
274+
Cpu cpu = new Cpu();
275+
// ... setting data
276+
277+
Point point = Point.measurementByPOJO(cpu.getClass()).addFieldsFromPOJO(cpu).build();
278+
279+
influxDB.write(dbName, rpName, point);
280+
```
281+
266282
#### QueryResult mapper limitations
267283

268284
* If your InfluxDB query contains multiple SELECT clauses, you will have to call InfluxResultMapper#toPOJO() multiple times to map every measurement returned by QueryResult to the respective POJO;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package org.influxdb;
2+
3+
/**
4+
* Class for exceptions when using Point Builder.
5+
*
6+
* @author mirza99
7+
*/
8+
public class BuilderException extends RuntimeException {
9+
10+
/**
11+
* Generated serial version UID.
12+
*/
13+
private static final long serialVersionUID = 4178882805281378918L;
14+
15+
public BuilderException(final String message) {
16+
super(message);
17+
}
18+
}

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

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.influxdb.dto;
22

3+
import java.lang.annotation.Annotation;
4+
import java.lang.reflect.Field;
35
import java.math.BigDecimal;
46
import java.math.BigInteger;
57
import java.text.NumberFormat;
@@ -9,6 +11,9 @@
911
import java.util.Objects;
1012
import java.util.TreeMap;
1113
import java.util.concurrent.TimeUnit;
14+
import org.influxdb.BuilderException;
15+
import org.influxdb.annotation.Column;
16+
import org.influxdb.annotation.Measurement;
1217
import org.influxdb.impl.Preconditions;
1318

1419
/**
@@ -52,6 +57,28 @@ public static Builder measurement(final String measurement) {
5257
return new Builder(measurement);
5358
}
5459

60+
/**
61+
* Create a new Point Build build to create a new Point in a fluent manner from a POJO.
62+
*
63+
* @param clazz Class of the POJO
64+
* @return the Builder instance
65+
*/
66+
67+
public static Builder measurementByPOJO(final Class<?> clazz) {
68+
Objects.requireNonNull(clazz, "clazz");
69+
throwExceptionIfMissingAnnotation(clazz, Measurement.class);
70+
String measurementName = findMeasurementName(clazz);
71+
return new Builder(measurementName);
72+
}
73+
74+
private static void throwExceptionIfMissingAnnotation(final Class<?> clazz,
75+
final Class<? extends Annotation> expectedClass) {
76+
if (!clazz.isAnnotationPresent(expectedClass)) {
77+
throw new IllegalArgumentException("Class " + clazz.getName() + " is not annotated with @"
78+
+ Measurement.class.getSimpleName());
79+
}
80+
}
81+
5582
/**
5683
* Builder for a new Point.
5784
*
@@ -195,6 +222,56 @@ public boolean hasFields() {
195222
return !fields.isEmpty();
196223
}
197224

225+
/**
226+
* Adds field map from object by reflection using {@link org.influxdb.annotation.Column}
227+
* annotation.
228+
*
229+
* @param pojo POJO Object with annotation {@link org.influxdb.annotation.Column} on fields
230+
* @return the Builder instance
231+
*/
232+
public Builder addFieldsFromPOJO(final Object pojo) {
233+
234+
Class<? extends Object> clazz = pojo.getClass();
235+
236+
for (Field field : clazz.getDeclaredFields()) {
237+
238+
Column column = field.getAnnotation(Column.class);
239+
240+
if (column == null) {
241+
continue;
242+
}
243+
244+
field.setAccessible(true);
245+
String fieldName = column.name();
246+
addFieldByAttribute(pojo, field, column, fieldName);
247+
}
248+
249+
if (this.fields.isEmpty()) {
250+
throw new BuilderException("Class " + pojo.getClass().getName()
251+
+ " has no @" + Column.class.getSimpleName() + " annotation");
252+
}
253+
254+
return this;
255+
}
256+
257+
private void addFieldByAttribute(final Object pojo, final Field field, final Column column,
258+
final String fieldName) {
259+
try {
260+
Object fieldValue = field.get(pojo);
261+
262+
if (column.tag()) {
263+
this.tags.put(fieldName, (String) fieldValue);
264+
} else {
265+
this.fields.put(fieldName, fieldValue);
266+
}
267+
268+
} catch (IllegalArgumentException | IllegalAccessException e) {
269+
// Can not happen since we use metadata got from the object
270+
throw new BuilderException(
271+
"Field " + fieldName + " could not found on class " + pojo.getClass().getSimpleName());
272+
}
273+
}
274+
198275
/**
199276
* Create a new Point.
200277
*
@@ -254,6 +331,13 @@ void setPrecision(final TimeUnit precision) {
254331
this.precision = precision;
255332
}
256333

334+
/**
335+
* @return the fields
336+
*/
337+
Map<String, Object> getFields() {
338+
return this.fields;
339+
}
340+
257341
/**
258342
* @param fields
259343
* the fields to set
@@ -418,4 +502,8 @@ private void formatedTime(final StringBuilder sb, final TimeUnit precision) {
418502
}
419503
sb.append(" ").append(precision.convert(this.time, this.precision));
420504
}
505+
506+
private static String findMeasurementName(final Class<?> clazz) {
507+
return clazz.getAnnotation(Measurement.class).name();
508+
}
421509
}

0 commit comments

Comments
 (0)