From 1c73bae2e23242673e0a07cdbc2493700f134ceb Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 13 Feb 2022 23:34:25 -0800 Subject: New storage implementation --- .../java/org/traccar/storage/DatabaseStorage.java | 71 +++++++++++++++------- .../java/org/traccar/storage/QueryBuilder.java | 6 +- src/main/java/org/traccar/storage/Storage.java | 15 ++--- .../java/org/traccar/storage/query/Columns.java | 22 ++++--- .../java/org/traccar/storage/query/Condition.java | 42 +++++++++++-- src/main/java/org/traccar/storage/query/Limit.java | 15 +++++ .../java/org/traccar/storage/query/Request.java | 22 +++++++ 7 files changed, 145 insertions(+), 48 deletions(-) create mode 100644 src/main/java/org/traccar/storage/query/Limit.java (limited to 'src/main/java/org/traccar/storage') diff --git a/src/main/java/org/traccar/storage/DatabaseStorage.java b/src/main/java/org/traccar/storage/DatabaseStorage.java index 0bcab7d20..2c893ebbc 100644 --- a/src/main/java/org/traccar/storage/DatabaseStorage.java +++ b/src/main/java/org/traccar/storage/DatabaseStorage.java @@ -2,6 +2,7 @@ package org.traccar.storage; import org.traccar.storage.query.Columns; import org.traccar.storage.query.Condition; +import org.traccar.storage.query.Limit; import org.traccar.storage.query.Order; import org.traccar.storage.query.Request; @@ -24,7 +25,7 @@ public class DatabaseStorage extends Storage { @Override public List getObjects(Class clazz, Request request) throws StorageException { StringBuilder query = new StringBuilder("SELECT "); - query.append(formatColumns(request.getColumns(), clazz, c -> c)); + query.append(formatColumns(request.getColumns(), clazz, "get", c -> c)); query.append(" FROM ").append(getTableName(clazz)); query.append(formatCondition(request.getCondition())); query.append(formatOrder(request.getOrder())); @@ -44,9 +45,9 @@ public class DatabaseStorage extends Storage { StringBuilder query = new StringBuilder("INSERT INTO "); query.append(getTableName(entity.getClass())); query.append("("); - query.append(formatColumns(request.getColumns(), entity.getClass(), c -> c)); + query.append(formatColumns(request.getColumns(), entity.getClass(), "set", c -> c)); query.append(") VALUES ("); - query.append(formatColumns(request.getColumns(), entity.getClass(), c -> ':' + c)); + query.append(formatColumns(request.getColumns(), entity.getClass(), "set", c -> ':' + c)); query.append(")"); try { QueryBuilder builder = QueryBuilder.create(dataSource, query.toString(), true); @@ -62,7 +63,7 @@ public class DatabaseStorage extends Storage { StringBuilder query = new StringBuilder("UPDATE "); query.append(getTableName(entity.getClass())); query.append(" SET "); - query.append(formatColumns(request.getColumns(), entity.getClass(), c -> c + " = :" + c)); + query.append(formatColumns(request.getColumns(), entity.getClass(), "set", c -> c + " = :" + c)); query.append(formatCondition(request.getCondition())); try { QueryBuilder builder = QueryBuilder.create(dataSource, query.toString()); @@ -101,31 +102,46 @@ public class DatabaseStorage extends Storage { } private Map getConditionVariables(Condition genericCondition) { - Map result = new HashMap<>(); - if (genericCondition instanceof Condition.Equals) { - Condition.Equals condition = (Condition.Equals) genericCondition; - result.put(condition.getVariable(), condition.getValue()); + Map results = new HashMap<>(); + if (genericCondition instanceof Condition.Compare) { + Condition.Compare condition = (Condition.Compare) genericCondition; + if (condition.getValue() != null) { + results.put(condition.getVariable(), condition.getValue()); + } } else if (genericCondition instanceof Condition.Between) { Condition.Between condition = (Condition.Between) genericCondition; - result.put(condition.getFromVariable(), condition.getFromValue()); - result.put(condition.getToVariable(), condition.getToValue()); + results.put(condition.getFromVariable(), condition.getFromValue()); + results.put(condition.getToVariable(), condition.getToValue()); + } else if (genericCondition instanceof Condition.Binary) { + Condition.Binary condition = (Condition.Binary) genericCondition; + results.putAll(getConditionVariables(condition.getFirst())); + results.putAll(getConditionVariables(condition.getSecond())); } - return result; + return results; } - private String formatColumns(Columns columns, Class clazz, Function mapper) { - return columns.getColumns(clazz).stream().map(mapper).collect(Collectors.joining(", ")); + private String formatColumns( + Columns columns, Class clazz, String type, Function mapper) { + return columns.getColumns(clazz, type).stream().map(mapper).collect(Collectors.joining(", ")); } private String formatCondition(Condition genericCondition) { + return formatCondition(genericCondition, true); + } + + private String formatCondition(Condition genericCondition, boolean appendWhere) { StringBuilder result = new StringBuilder(); if (genericCondition != null) { - result.append(" WHERE "); - if (genericCondition instanceof Condition.Equals) { + if (appendWhere) { + result.append(" WHERE "); + } + if (genericCondition instanceof Condition.Compare) { - Condition.Equals condition = (Condition.Equals) genericCondition; + Condition.Compare condition = (Condition.Compare) genericCondition; result.append(condition.getColumn()); - result.append(" == :"); + result.append(" "); + result.append(condition.getOperator()); + result.append(" :"); result.append(condition.getVariable()); } else if (genericCondition instanceof Condition.Between) { @@ -137,12 +153,14 @@ public class DatabaseStorage extends Storage { result.append(" AND :"); result.append(condition.getToVariable()); - } else if (genericCondition instanceof Condition.And) { + } else if (genericCondition instanceof Condition.Binary) { - Condition.And condition = (Condition.And) genericCondition; - result.append(formatCondition(condition.getFirst())); - result.append(" AND "); - result.append(formatCondition(condition.getSecond())); + Condition.Binary condition = (Condition.Binary) genericCondition; + result.append(formatCondition(condition.getFirst(), false)); + result.append(" "); + result.append(condition.getOperator()); + result.append(" "); + result.append(formatCondition(condition.getSecond(), false)); } } @@ -161,4 +179,13 @@ public class DatabaseStorage extends Storage { return result.toString(); } + private String formatLimit(Limit limit) { + StringBuilder result = new StringBuilder(); + if (limit != null) { + result.append(" LIMIT "); + result.append(limit.getValue()); + } + return result.toString(); + } + } diff --git a/src/main/java/org/traccar/storage/QueryBuilder.java b/src/main/java/org/traccar/storage/QueryBuilder.java index 838472c8b..edaacb74d 100644 --- a/src/main/java/org/traccar/storage/QueryBuilder.java +++ b/src/main/java/org/traccar/storage/QueryBuilder.java @@ -276,8 +276,7 @@ public final class QueryBuilder { Method[] methods = object.getClass().getMethods(); for (Method method : methods) { - if (method.getName().startsWith("get") && method.getParameterTypes().length == 0 - && !method.isAnnotationPresent(QueryIgnore.class)) { + if (method.getName().startsWith("get") && method.getParameterTypes().length == 0) { String name = method.getName().substring(3); try { if (method.getReturnType().equals(boolean.class)) { @@ -412,8 +411,7 @@ public final class QueryBuilder { Method[] methods = clazz.getMethods(); for (final Method method : methods) { - if (method.getName().startsWith("set") && method.getParameterTypes().length == 1 - && !method.isAnnotationPresent(QueryIgnore.class)) { + if (method.getName().startsWith("set") && method.getParameterTypes().length == 1) { final String name = method.getName().substring(3); diff --git a/src/main/java/org/traccar/storage/Storage.java b/src/main/java/org/traccar/storage/Storage.java index b95ce9505..3726fbf50 100644 --- a/src/main/java/org/traccar/storage/Storage.java +++ b/src/main/java/org/traccar/storage/Storage.java @@ -6,20 +6,17 @@ import java.util.List; public abstract class Storage { - abstract List getObjects(Class clazz, Request request) throws StorageException; + public abstract List getObjects(Class clazz, Request request) throws StorageException; - abstract long addObject(T entity, Request request) throws StorageException; + public abstract long addObject(T entity, Request request) throws StorageException; - abstract void updateObject(T entity, Request request) throws StorageException; + public abstract void updateObject(T entity, Request request) throws StorageException; - abstract void removeObject(Class clazz, Request request) throws StorageException; + public abstract void removeObject(Class clazz, Request request) throws StorageException; - T getObject(Class clazz, Request request) throws StorageException { + public T getObject(Class clazz, Request request) throws StorageException { var objects = getObjects(clazz, request); - if (objects.isEmpty()) { - throw new StorageException("No objects found"); - } - return objects.get(0); + return objects.isEmpty() ? null : objects.get(0); } } diff --git a/src/main/java/org/traccar/storage/query/Columns.java b/src/main/java/org/traccar/storage/query/Columns.java index 1a13665ee..196d2281c 100644 --- a/src/main/java/org/traccar/storage/query/Columns.java +++ b/src/main/java/org/traccar/storage/query/Columns.java @@ -1,5 +1,6 @@ package org.traccar.storage.query; +import org.traccar.storage.QueryExtended; import org.traccar.storage.QueryIgnore; import java.lang.reflect.Method; @@ -11,14 +12,17 @@ import java.util.stream.Collectors; public abstract class Columns { - public abstract List getColumns(Class clazz); + public abstract List getColumns(Class clazz, String type); - protected List getAllColumns(Class clazz) { + protected List getAllColumns(Class clazz, String type) { List columns = new LinkedList<>(); Method[] methods = clazz.getMethods(); for (Method method : methods) { - if (method.getName().startsWith("set") && method.getParameterTypes().length == 1 - && !method.isAnnotationPresent(QueryIgnore.class)) { + int parameterCount = type.equals("set") ? 1 : 0; + if (method.getName().startsWith(type) && method.getParameterTypes().length == parameterCount + && !method.isAnnotationPresent(QueryIgnore.class) + && !method.isAnnotationPresent(QueryExtended.class) + && !method.getName().equals("getClass")) { columns.add(method.getName().substring(3).toLowerCase()); } } @@ -27,8 +31,8 @@ public abstract class Columns { public static class All extends Columns { @Override - public List getColumns(Class clazz) { - return getAllColumns(clazz); + public List getColumns(Class clazz, String type) { + return getAllColumns(clazz, type); } } @@ -40,7 +44,7 @@ public abstract class Columns { } @Override - public List getColumns(Class clazz) { + public List getColumns(Class clazz, String type) { return columns; } } @@ -53,8 +57,8 @@ public abstract class Columns { } @Override - public List getColumns(Class clazz) { - return getAllColumns(clazz).stream() + public List getColumns(Class clazz, String type) { + return getAllColumns(clazz, type).stream() .filter(column -> !columns.contains(column)) .collect(Collectors.toList()); } diff --git a/src/main/java/org/traccar/storage/query/Condition.java b/src/main/java/org/traccar/storage/query/Condition.java index 50d520bc7..82c8e8479 100644 --- a/src/main/java/org/traccar/storage/query/Condition.java +++ b/src/main/java/org/traccar/storage/query/Condition.java @@ -2,13 +2,25 @@ package org.traccar.storage.query; public interface Condition { - class Equals implements Condition { + class Equals extends Compare { + public Equals(String column, String variable) { + this(column, variable, null); + } + + public Equals(String column, String variable, Object value) { + super(column, "=", variable, value); + } + } + + class Compare implements Condition { private final String column; + private final String operator; private final String variable; private final Object value; - public Equals(String column, String variable, Object value) { + public Compare(String column, String operator, String variable, Object value) { this.column = column; + this.operator = operator; this.variable = variable; this.value = value; } @@ -17,6 +29,10 @@ public interface Condition { return column; } + public String getOperator() { + return operator; + } + public String getVariable() { return variable; } @@ -62,13 +78,27 @@ public interface Condition { } } - class And implements Condition { + class Or extends Binary { + public Or(Condition first, Condition second) { + super(first, second, "OR"); + } + } + + class And extends Binary { + public And(Condition first, Condition second) { + super(first, second, "AND"); + } + } + + class Binary implements Condition { private final Condition first; private final Condition second; + private final String operator; - public And(Condition first, Condition second) { + public Binary(Condition first, Condition second, String operator) { this.first = first; this.second = second; + this.operator = operator; } public Condition getFirst() { @@ -78,6 +108,10 @@ public interface Condition { public Condition getSecond() { return second; } + + public String getOperator() { + return operator; + } } } diff --git a/src/main/java/org/traccar/storage/query/Limit.java b/src/main/java/org/traccar/storage/query/Limit.java new file mode 100644 index 000000000..4a20f0ce2 --- /dev/null +++ b/src/main/java/org/traccar/storage/query/Limit.java @@ -0,0 +1,15 @@ +package org.traccar.storage.query; + +public class Limit { + + private final int value; + + public Limit(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + +} diff --git a/src/main/java/org/traccar/storage/query/Request.java b/src/main/java/org/traccar/storage/query/Request.java index 8536cafd0..a98dd48f7 100644 --- a/src/main/java/org/traccar/storage/query/Request.java +++ b/src/main/java/org/traccar/storage/query/Request.java @@ -5,11 +5,29 @@ public class Request { private final Columns columns; private final Condition condition; private final Order order; + private final Limit limit; + + public Request(Columns columns) { + this(columns, null, null); + } + + public Request(Condition condition) { + this(null, condition, null); + } + + public Request(Columns columns, Condition condition) { + this(columns, condition, null); + } public Request(Columns columns, Condition condition, Order order) { + this(columns, condition, order, null); + } + + public Request(Columns columns, Condition condition, Order order, Limit limit) { this.columns = columns; this.condition = condition; this.order = order; + this.limit = limit; } public Columns getColumns() { @@ -24,4 +42,8 @@ public class Request { return order; } + public Limit getLimit() { + return limit; + } + } -- cgit v1.2.3