From 93f69979baf0db5e80d389dc0dadf7b81d3a2b22 Mon Sep 17 00:00:00 2001 From: ikalyvas Date: Thu, 23 May 2019 18:03:44 +0300 Subject: [PATCH] Updates Queryablelist to support Queries and Criteria --- .../main/java/eu/eudat/data/entities/DMP.java | 6 +- .../java/eu/eudat/data/entities/Project.java | 9 +- .../main/java/eu/eudat/query/DMPQuery.java | 40 ++++++- .../java/eu/eudat/query/DatasetQuery.java | 47 +++++++- .../java/eu/eudat/query/ProjectQuery.java | 7 ++ .../src/main/java/eu/eudat/query/Query.java | 16 ++- .../main/java/eu/eudat/query/UserQuery.java | 5 + dmp-backend/pom.xml | 2 +- .../eu/eudat/queryable/QueryableList.java | 3 + .../eudat/queryable/collector/Collector.java | 29 +++++ .../queryable/collector/ProjectionField.java | 107 ++++++++++++++++++ .../QueryableHibernateList.java | 44 ++++--- .../configurations/JacksonConfiguration.java | 16 +++ .../main/java/eu/eudat/controllers/DMPs.java | 17 ++- .../java/eu/eudat/criteria/DMPCriteria.java | 44 ++++++- .../eu/eudat/criteria/DatasetCriteria.java | 77 +++++++++++++ .../eu/eudat/criteria/ProjectCriteria.java | 35 ++++-- .../java/eu/eudat/criteria/UserCriteria.java | 40 ++++++- 18 files changed, 488 insertions(+), 56 deletions(-) create mode 100644 dmp-backend/queryable/src/main/java/eu/eudat/queryable/collector/Collector.java create mode 100644 dmp-backend/queryable/src/main/java/eu/eudat/queryable/collector/ProjectionField.java create mode 100644 dmp-backend/web/src/main/java/eu/eudat/configurations/JacksonConfiguration.java create mode 100644 dmp-backend/web/src/main/java/eu/eudat/criteria/DatasetCriteria.java diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/entities/DMP.java b/dmp-backend/data/src/main/java/eu/eudat/data/entities/DMP.java index 8e665f027..e4f4dbfd4 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/entities/DMP.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/entities/DMP.java @@ -323,9 +323,9 @@ public class DMP implements DataEntity { public DMP buildFromTuple(List tuple, List fields, String base) { String currentBase = base.isEmpty() ? "" : base + "."; if (fields.contains(currentBase + "id")) this.id = EntityBinder.fromTuple(tuple, currentBase + "id"); - this.dataset = tuple.stream().map(x -> new Dataset().buildFromTuple(tuple, fields, currentBase + "dataset")).collect(Collectors.toSet()); - this.creator = tuple.stream().map(x -> new UserInfo().buildFromTuple(tuple, fields, currentBase + "creator")).collect(Collectors.toList()).get(0); - this.project = tuple.stream().map(x -> new Project().buildFromTuple(tuple, fields, currentBase + "project")).collect(Collectors.toList()).get(0); + this.dataset = tuple.stream().map(x -> new Dataset().buildFromTuple(Arrays.asList(x), fields, currentBase + "dataset")).collect(Collectors.toSet()); + this.creator = tuple.stream().map(x -> new UserInfo().buildFromTuple(Arrays.asList(x), fields, currentBase + "creator")).collect(Collectors.toList()).get(0); + this.project = tuple.stream().map(x -> new Project().buildFromTuple(Arrays.asList(x), fields, currentBase + "project")).collect(Collectors.toList()).get(0); return this; } } diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/entities/Project.java b/dmp-backend/data/src/main/java/eu/eudat/data/entities/Project.java index 4977bc1ed..ed03e3622 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/entities/Project.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/entities/Project.java @@ -8,10 +8,7 @@ import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.Type; import javax.persistence.*; -import java.util.Date; -import java.util.List; -import java.util.Set; -import java.util.UUID; +import java.util.*; import java.util.stream.Collectors; @@ -312,9 +309,9 @@ public class Project implements DataEntity { String currentBase = base.isEmpty() ? "" : base + "."; if (fields.contains(currentBase + "id")) this.id = EntityBinder.fromTuple(tuple, currentBase + "id"); if (fields.contains(currentBase + "dmps")) - this.dmps = tuple.stream().map(x -> new DMP().buildFromTuple(tuple, fields, currentBase + "dmps")).collect(Collectors.toSet()); + this.dmps = tuple.stream().map(x -> new DMP().buildFromTuple(Arrays.asList(x), fields, currentBase + "dmps")).collect(Collectors.toSet()); if (fields.contains(currentBase + "creationUser")) - this.creationUser = tuple.stream().map(x -> new UserInfo().buildFromTuple(tuple, fields, currentBase + "creationUser")).collect(Collectors.toList()).get(0); + this.creationUser = tuple.stream().map(x -> new UserInfo().buildFromTuple(Arrays.asList(x), fields, currentBase + "creationUser")).collect(Collectors.toList()).get(0); return this; } } diff --git a/dmp-backend/data/src/main/java/eu/eudat/query/DMPQuery.java b/dmp-backend/data/src/main/java/eu/eudat/query/DMPQuery.java index 0108a2447..5100d2e88 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/query/DMPQuery.java +++ b/dmp-backend/data/src/main/java/eu/eudat/query/DMPQuery.java @@ -2,12 +2,13 @@ package eu.eudat.query; import eu.eudat.data.dao.DatabaseAccessLayer; import eu.eudat.data.entities.DMP; +import eu.eudat.data.entities.Dataset; import eu.eudat.data.entities.Project; +import eu.eudat.data.entities.UserInfo; import eu.eudat.queryable.QueryableList; import eu.eudat.queryable.types.FieldSelectionType; import eu.eudat.queryable.types.SelectionField; -import javax.persistence.TypedQuery; import javax.persistence.criteria.Subquery; import java.util.Arrays; import java.util.Date; @@ -20,6 +21,8 @@ public class DMPQuery extends Query { private String label; private int version; private ProjectQuery projectQuery; + private UserQuery userQuery; + private DatasetQuery datasetQuery; private List statuses; private Date created; private Date modified; @@ -28,6 +31,10 @@ public class DMPQuery extends Query { super(databaseAccessLayer); } + public DMPQuery(DatabaseAccessLayer databaseAccessLayer, List selectionFields) { + super(databaseAccessLayer, selectionFields); + } + public UUID getId() { return id; } @@ -92,18 +99,45 @@ public class DMPQuery extends Query { this.modified = modified; } + public UserQuery getUserQuery() { + return userQuery; + } + + public void setUserQuery(UserQuery userQuery) { + this.userQuery = userQuery; + } + + public DatasetQuery getDatasetQuery() { + return datasetQuery; + } + + public void setDatasetQuery(DatasetQuery datasetQuery) { + this.datasetQuery = datasetQuery; + } + public QueryableList getQuery() { QueryableList query = this.databaseAccessLayer.asQueryable(); if (this.id != null) { query.where((builder, root) -> builder.equal(root.get("id"), this.id)); } - if(this.projectQuery != null){ + if (this.projectQuery != null) { Subquery projectQuery = this.projectQuery.getQuery().query(Arrays.asList(new SelectionField(FieldSelectionType.FIELD, "id"))); query.where((builder, root) -> root.get("project").get("id").in(projectQuery)); } - if(this.getStatuses() != null && !this.getStatuses().isEmpty()){ + if (this.getStatuses() != null && !this.getStatuses().isEmpty()) { query.where((builder, root) -> root.get("status").in(this.getStatuses())); } + if (this.userQuery != null) { + Subquery userInfoSubQuery = this.userQuery.getQuery().query(Arrays.asList(new SelectionField(FieldSelectionType.FIELD, "id"))); + query.where((builder, root) -> root.get("creator").get("id").in(userInfoSubQuery)); + } + if(this.datasetQuery != null){ + Subquery datasetSubQuery = this.datasetQuery.getQuery().query(Arrays.asList(new SelectionField(FieldSelectionType.COMPOSITE_FIELD, "dmp:id"))); + query.where((builder, root) -> root.get("id").in(datasetSubQuery )); + } + if (!this.getSelectionFields().isEmpty() && this.getSelectionFields() != null) { + query.withFields(this.getSelectionFields()); + } return query; } } diff --git a/dmp-backend/data/src/main/java/eu/eudat/query/DatasetQuery.java b/dmp-backend/data/src/main/java/eu/eudat/query/DatasetQuery.java index 677a81a93..7dce8d313 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/query/DatasetQuery.java +++ b/dmp-backend/data/src/main/java/eu/eudat/query/DatasetQuery.java @@ -1,20 +1,65 @@ package eu.eudat.query; import eu.eudat.data.dao.DatabaseAccessLayer; +import eu.eudat.data.entities.DMP; import eu.eudat.data.entities.Dataset; import eu.eudat.queryable.QueryableList; +import eu.eudat.queryable.types.FieldSelectionType; +import eu.eudat.queryable.types.SelectionField; +import javax.persistence.criteria.Subquery; +import java.util.Arrays; +import java.util.List; import java.util.UUID; public class DatasetQuery extends Query { + private UUID id; + private String label; + private DMPQuery dmpQuery; public DatasetQuery(DatabaseAccessLayer databaseAccessLayer) { super(databaseAccessLayer); } + public DatasetQuery(DatabaseAccessLayer databaseAccessLayer, List selectionFields) { + super(databaseAccessLayer, selectionFields); + } + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + public DMPQuery getDmpQuery() { + return dmpQuery; + } + + public void setDmpQuery(DMPQuery dmpQuery) { + this.dmpQuery = dmpQuery; + } + @Override public QueryableList getQuery() { - return null; + QueryableList query = this.databaseAccessLayer.asQueryable(); + if (this.id != null) { + query.where((builder, root) -> builder.equal(root.get("id"), this.id)); + } + if (this.dmpQuery != null) { + Subquery dmpSubQuery = this.dmpQuery.getQuery().query(Arrays.asList(new SelectionField(FieldSelectionType.FIELD, "id"))); + query.where((builder, root) -> root.get("dmp").get("id").in(dmpSubQuery)); + } + return query; } } diff --git a/dmp-backend/data/src/main/java/eu/eudat/query/ProjectQuery.java b/dmp-backend/data/src/main/java/eu/eudat/query/ProjectQuery.java index ba4d3e88c..e23665e2d 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/query/ProjectQuery.java +++ b/dmp-backend/data/src/main/java/eu/eudat/query/ProjectQuery.java @@ -27,6 +27,10 @@ public class ProjectQuery extends Query { super(databaseAccessLayer); } + public ProjectQuery(DatabaseAccessLayer databaseAccessLayer, List selectionFields) { + super(databaseAccessLayer, selectionFields); + } + public UUID getId() { return id; } @@ -96,6 +100,9 @@ public class ProjectQuery extends Query { Subquery userInfoSubquery = this.userQuery.getQuery().query(Arrays.asList(new SelectionField(FieldSelectionType.FIELD, "id"))); query.where((builder, root) -> root.get("creationUser").get("id").in(userInfoSubquery)); } + if (!this.getSelectionFields().isEmpty() && this.getSelectionFields() != null) { + query.withFields(this.getSelectionFields()); + } return query; } } diff --git a/dmp-backend/data/src/main/java/eu/eudat/query/Query.java b/dmp-backend/data/src/main/java/eu/eudat/query/Query.java index d5e908ef4..effc6a1be 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/query/Query.java +++ b/dmp-backend/data/src/main/java/eu/eudat/query/Query.java @@ -4,12 +4,26 @@ import eu.eudat.data.dao.DatabaseAccessLayer; import eu.eudat.queryable.QueryableList; import eu.eudat.queryable.queryableentity.DataEntity; +import java.util.LinkedList; +import java.util.List; + public abstract class Query { - protected DatabaseAccessLayer databaseAccessLayer; + protected DatabaseAccessLayer databaseAccessLayer; + + private List selectionFields = new LinkedList<>(); + + public Query(DatabaseAccessLayer databaseAccessLayer, List selectionFields) { + this.databaseAccessLayer = databaseAccessLayer; + this.selectionFields = selectionFields; + } public Query(DatabaseAccessLayer databaseAccessLayer) { this.databaseAccessLayer = databaseAccessLayer; } public abstract QueryableList getQuery(); + + protected List getSelectionFields() { + return selectionFields; + } } diff --git a/dmp-backend/data/src/main/java/eu/eudat/query/UserQuery.java b/dmp-backend/data/src/main/java/eu/eudat/query/UserQuery.java index 2b3b9c10d..f6240b7c3 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/query/UserQuery.java +++ b/dmp-backend/data/src/main/java/eu/eudat/query/UserQuery.java @@ -4,6 +4,7 @@ import eu.eudat.data.dao.DatabaseAccessLayer; import eu.eudat.data.entities.UserInfo; import eu.eudat.queryable.QueryableList; +import java.util.List; import java.util.UUID; public class UserQuery extends Query { @@ -22,6 +23,10 @@ public class UserQuery extends Query { super(databaseAccessLayer); } + public UserQuery(DatabaseAccessLayer databaseAccessLayer, List selectionFields) { + super(databaseAccessLayer, selectionFields); + } + @Override public QueryableList getQuery() { QueryableList query = this.databaseAccessLayer.asQueryable(); diff --git a/dmp-backend/pom.xml b/dmp-backend/pom.xml index deaaf8885..cb515c253 100644 --- a/dmp-backend/pom.xml +++ b/dmp-backend/pom.xml @@ -35,7 +35,7 @@ 7.0.35 2.8.4 - 5.2.11.Final + 5.4.2.Final 1.9 4.11 diff --git a/dmp-backend/queryable/src/main/java/eu/eudat/queryable/QueryableList.java b/dmp-backend/queryable/src/main/java/eu/eudat/queryable/QueryableList.java index 5a8da6770..f11c15876 100644 --- a/dmp-backend/queryable/src/main/java/eu/eudat/queryable/QueryableList.java +++ b/dmp-backend/queryable/src/main/java/eu/eudat/queryable/QueryableList.java @@ -8,6 +8,7 @@ import javax.persistence.TypedQuery; import javax.persistence.criteria.Expression; import javax.persistence.criteria.Subquery; import java.util.List; +import java.util.Map; import java.util.concurrent.CompletableFuture; public interface QueryableList { @@ -23,6 +24,8 @@ public interface QueryableList { QueryableList withFields(List fields); + List toListWithFields(); + CompletableFuture> toListAsync(); T getSingle(); diff --git a/dmp-backend/queryable/src/main/java/eu/eudat/queryable/collector/Collector.java b/dmp-backend/queryable/src/main/java/eu/eudat/queryable/collector/Collector.java new file mode 100644 index 000000000..5de816bab --- /dev/null +++ b/dmp-backend/queryable/src/main/java/eu/eudat/queryable/collector/Collector.java @@ -0,0 +1,29 @@ +package eu.eudat.queryable.collector; + +import javax.persistence.Tuple; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class Collector { + + public List buildFromTuple(List results, Map> groupedResults, List fields, String key) { + return groupedResults.keySet().stream() + .map(x -> buildOne(groupedResults.get(x), fields, key)) + .collect(Collectors.toList()); + } + + private Map buildOne(List tuples, List fields, String key) { + Map tupleValues = new LinkedHashMap(); + List projectionFields = fields.stream() + .map(x -> x.split("\\.")) + .collect(Collectors.groupingBy(x -> x[0])) + .values() + .stream() + .map(field -> new ProjectionField(field.stream().map(x -> String.join(".", x)).collect(Collectors.toList()), null)) + .collect(Collectors.toList()); + projectionFields.forEach(x -> x.collect(tupleValues, tuples)); + return tupleValues; + } +} diff --git a/dmp-backend/queryable/src/main/java/eu/eudat/queryable/collector/ProjectionField.java b/dmp-backend/queryable/src/main/java/eu/eudat/queryable/collector/ProjectionField.java new file mode 100644 index 000000000..d76e33c0c --- /dev/null +++ b/dmp-backend/queryable/src/main/java/eu/eudat/queryable/collector/ProjectionField.java @@ -0,0 +1,107 @@ +package eu.eudat.queryable.collector; + +import com.google.common.collect.Lists; + +import javax.persistence.Tuple; +import java.util.*; +import java.util.stream.Collectors; + +public class ProjectionField { + private String key; + private List fields; + private ProjectionField parent; + + public ProjectionField(List field, ProjectionField parent) { + this.parse(field); + this.parent = parent; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public List getFields() { + return fields; + } + + public void setFields(List fields) { + this.fields = fields; + } + + private void parse(List fields) { + String[] fieldsArr = fields.get(0).split("\\."); + this.key = fieldsArr[0]; + this.fields = fields.stream() + .map(x -> x.replace(x.contains(".") ? this.key + "." : this.key, "")) + .filter(x -> !x.isEmpty()) + .map(x -> x.split("\\.")) + .collect(Collectors.groupingBy(x -> x[0])) + .values() + .stream() + .map(field -> new ProjectionField(field.stream().map(x -> String.join(".", x)).collect(Collectors.toList()), this)) + .collect(Collectors.toList()); + } + + public Map collect(Map map, List tuples) { + if (fields != null && !fields.isEmpty()) { + this.collect(map, this.fields, tuples); + } else { + map.put(key, this.createObject(tuples, this.generatePath())); + } + return map; + } + + public Map collect(Map map, List projectionGroup, List tuples) { + map.put(key, this.createObject(tuples, projectionGroup)); + return map; + } + + private String generatePath() { + List list = new LinkedList<>(); + ProjectionField current = this; + list.add(current.key); + while (current.parent != null) { + list.add(current.parent.key); + current = current.parent; + } + return String.join(".", Lists.reverse(list)); + } + + private Object createObject(List tuples, String field) { + List values = tuples.stream() + .map(x -> x.get(field)) + .distinct() + .collect(Collectors.toList()); + + if (values.size() > 1) { + return values.stream().map(x -> { + Map map = new LinkedHashMap(); + map.put(field, x); + return map; + }).collect(Collectors.toList()); + } else if (values.size() == 1) { + return values.get(0); + } else return null; + } + + private Object createObject(List tuples, List group) { + Collection values = tuples.stream() + .map(x -> getValuesFrom(tuples, x, group)) + .collect(Collectors.toMap(x -> x.get("id"), x -> x, (x, y) -> x)).values(); + return values; + } + + private Map getValuesFrom(List tuples, Tuple tuple, List group) { + Map map = new LinkedHashMap(); + group.forEach(x -> { + if (x.fields != null && !x.fields.isEmpty()) + map.put(x.key, this.createObject(tuples, x.fields)); + else map.put(x.key, tuple.get(x.generatePath())); + }); + return map; + } +} diff --git a/dmp-backend/queryable/src/main/java/eu/eudat/queryable/jpa/hibernatequeryablelist/QueryableHibernateList.java b/dmp-backend/queryable/src/main/java/eu/eudat/queryable/jpa/hibernatequeryablelist/QueryableHibernateList.java index 6b93907d0..e51a9a4d2 100644 --- a/dmp-backend/queryable/src/main/java/eu/eudat/queryable/jpa/hibernatequeryablelist/QueryableHibernateList.java +++ b/dmp-backend/queryable/src/main/java/eu/eudat/queryable/jpa/hibernatequeryablelist/QueryableHibernateList.java @@ -1,6 +1,7 @@ package eu.eudat.queryable.jpa.hibernatequeryablelist; import eu.eudat.queryable.QueryableList; +import eu.eudat.queryable.collector.Collector; import eu.eudat.queryable.exceptions.NotSingleResultException; import eu.eudat.queryable.jpa.predicates.*; import eu.eudat.queryable.queryableentity.DataEntity; @@ -18,6 +19,7 @@ import java.util.stream.Collectors; public class QueryableHibernateList implements QueryableList { + private Collector collector = new Collector(); private EntityManager manager; private CriteriaQuery query; private Class tClass; @@ -33,6 +35,7 @@ public class QueryableHibernateList implements QueryableLi private Integer offset; private Set hints; private String hint; + private Map joinsMap = new HashMap<>(); public QueryableHibernateList(EntityManager manager, Class tClass) { this.manager = manager; @@ -56,7 +59,7 @@ public class QueryableHibernateList implements QueryableLi } private QueryableList selectFields() { - List rootFields = fields.stream().map(field -> this.convertFieldToPath(field)).collect(Collectors.toList()); + List rootFields = fields.stream().map(field -> this.convertFieldToPath(field)).filter(x -> x != null).collect(Collectors.toList()); this.query.select(this.manager.getCriteriaBuilder().tuple(rootFields.toArray(new Selection[rootFields.size()]))); return this; } @@ -72,7 +75,7 @@ public class QueryableHibernateList implements QueryableLi Join join = null; path.alias(fields[0]); for (int i = 1; i < fields.length; i++) { - join = join != null ? join.join(fields[i - 1], JoinType.LEFT) : this.root.join(fields[i - 1], JoinType.LEFT); + join = join != null ? join.join(fields[i - 1], JoinType.LEFT) : this.getJoin(fields[i - 1], JoinType.LEFT); path = join.get(fields[i]); path.alias(String.join(".", Arrays.asList(fields).subList(0, i + 1))); } @@ -80,6 +83,20 @@ public class QueryableHibernateList implements QueryableLi } } + private Join getJoin(String field, String path, Join joined, JoinType type) { + if (this.joinsMap.containsKey(path)) return this.joinsMap.get(path); + Join join = joined.join(path, type); + this.joinsMap.put(path, join); + return join; + } + + private Join getJoin(String field, JoinType type) { + if (this.joinsMap.containsKey(field)) return this.joinsMap.get(field); + Join join = this.root.join(field, type); + this.joinsMap.put(field, join); + return join; + } + public QueryableHibernateList setEntity(Class type) { return this; @@ -194,22 +211,23 @@ public class QueryableHibernateList implements QueryableLi if (!this.orderings.isEmpty()) this.query.orderBy(this.generateOrderPredicates(this.orderings, this.root)); if (!this.fields.isEmpty()) this.selectFields(); if (distinct) this.query.distinct(true); - if (!this.fields.isEmpty()) return this.toListWithFields(); - else return this.toListWithOutFields(); + //if (!this.fields.isEmpty()) return this.toListWithFields(); + return this.toListWithOutFields(); } - private List toListWithFields() { + public List toListWithFields() { + CriteriaBuilder builder = this.manager.getCriteriaBuilder(); + if (!this.fields.isEmpty()) this.query = builder.createTupleQuery(); + else this.query = builder.createQuery(this.tClass); + this.root = this.query.from(this.tClass); + this.query.where(this.generateWherePredicates(this.singlePredicates, this.root, this.nestedPredicates, this.nestedQueryRoot)); + if (!this.orderings.isEmpty()) this.query.orderBy(this.generateOrderPredicates(this.orderings, this.root)); + if (!this.fields.isEmpty()) this.selectFields(); + if (distinct) this.query.distinct(true); List results = this.manager.createQuery(query).getResultList(); Map> groupedResults = results.stream() .collect(Collectors.groupingBy(x -> x.get("id"))); - return results.stream().map(x -> { - try { - return (T) this.tClass.newInstance().buildFromTuple(groupedResults.get(x.get("id")), this.fields, ""); - } catch (InstantiationException | IllegalAccessException e) { - e.printStackTrace(); - } - return null; - }).collect(Collectors.toList()); + return this.collector.buildFromTuple(results, groupedResults, this.fields, "id"); } private List toListWithOutFields() { diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/JacksonConfiguration.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/JacksonConfiguration.java new file mode 100644 index 000000000..806b2f0fe --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/configurations/JacksonConfiguration.java @@ -0,0 +1,16 @@ +package eu.eudat.configurations; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class JacksonConfiguration { + @Bean + public ObjectMapper buildObjectMapper() { + return new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL) + .setSerializationInclusion(JsonInclude.Include.NON_ABSENT) + .setSerializationInclusion(JsonInclude.Include.NON_EMPTY); + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/DMPs.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/DMPs.java index da067b26e..0a5488575 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/DMPs.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/DMPs.java @@ -48,6 +48,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.UUID; @@ -201,18 +202,16 @@ public class DMPs extends BaseController { @RequestMapping(method = RequestMethod.POST, value = {"/test"}, consumes = "application/json", produces = "application/json") public @ResponseBody - ResponseEntity>> test(@RequestBody DMPCriteria criteria, @ClaimedAuthorities(claims = {Authorities.ANONYMOUS}) Principal principal) throws Exception { + ResponseEntity>> test(@RequestBody DMPCriteria criteria, @ClaimedAuthorities(claims = {Authorities.ANONYMOUS}) Principal principal) throws Exception { DatabaseRepository dbRepo = this.getApiContext().getOperationsContext().getDatabaseRepository(); - DMPQuery query = criteria.getQuery(dbRepo.getDmpDao()); - ProjectQuery projectQuery = criteria.getProject().getQuery(dbRepo.getProjectDao()); - UserQuery userQuery = criteria.getProject().getCreator().getQuery(dbRepo.getUserInfoDao()); - projectQuery.setUserQuery(userQuery); - query.setProjectQuery(projectQuery); - List models = query.getQuery().withFields(Arrays.asList("id", "project.id", "dataset.id", "project.creationUser.id")).select(x -> new DataManagementPlanListingModel().fromDataModel(x)); - DataTableData dmp = new DataTableData<>(); + + DMPQuery query = criteria.buildQuery(dbRepo); + + List models = query.getQuery().toListWithFields(); + DataTableData dmp = new DataTableData<>(); dmp.setData(models); dmp.setTotalCount(query.getQuery().count()); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().status(ApiMessageCode.NO_MESSAGE).payload(dmp)); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().status(ApiMessageCode.NO_MESSAGE).payload(dmp)); } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/criteria/DMPCriteria.java b/dmp-backend/web/src/main/java/eu/eudat/criteria/DMPCriteria.java index d1bb1074d..1bdadcd4d 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/criteria/DMPCriteria.java +++ b/dmp-backend/web/src/main/java/eu/eudat/criteria/DMPCriteria.java @@ -2,10 +2,10 @@ package eu.eudat.criteria; import eu.eudat.criteria.entities.Criteria; import eu.eudat.criteria.entities.DateCriteria; -import eu.eudat.data.dao.entities.DMPDao; +import eu.eudat.logic.services.operations.DatabaseRepository; import eu.eudat.query.DMPQuery; -import java.util.UUID; +import java.util.*; public class DMPCriteria { private Criteria id; @@ -15,6 +15,8 @@ public class DMPCriteria { private ProjectCriteria project; private DateCriteria created; private DateCriteria modified; + private UserCriteria creator; + private DatasetCriteria dataset; public Criteria getId() { return id; @@ -108,9 +110,41 @@ public class DMPCriteria { this.modified = criteria; } - public DMPQuery getQuery(DMPDao dao) { - DMPQuery dmpQuery = new DMPQuery(dao); - dmpQuery.setId(this.id.getValue()); + public UserCriteria getCreator() { + return creator; + } + + public void setCreator(UserCriteria creator) { + this.creator = creator; + } + + public DatasetCriteria getDataset() { + return dataset; + } + + public void setDataset(DatasetCriteria dataset) { + this.dataset = dataset; + } + + protected List buildFields(String path) { + Set fields = new HashSet<>(); + path = path != null && !path.isEmpty() ? path + "." : ""; + if (this.id != null) fields.add(path + this.id.getAs()); + if (this.project != null) fields.addAll(this.project.buildFields(path + "project")); + if (this.creator != null) fields.addAll(this.creator.buildFields(path + "creator")); + if (this.dataset != null) fields.addAll(this.dataset.buildFields(path + "dataset")); + if (this.label != null) fields.add(path + this.label.getAs()); + if (!fields.contains(path + "id")) fields.add(path + "id"); + return new LinkedList<>(fields); + } + + public DMPQuery buildQuery(DatabaseRepository dao) { + List fields = this.buildFields(""); + DMPQuery dmpQuery = new DMPQuery(dao.getDmpDao(), fields); + if (this.id != null) dmpQuery.setId(this.id.getValue()); + if (this.project != null) dmpQuery.setProjectQuery(this.project.buildQuery(dao)); + if (this.creator != null) dmpQuery.setUserQuery(this.creator.buildQuery(dao)); + if (this.dataset != null) dmpQuery.setDatasetQuery(this.dataset.buildQuery(dao)); return dmpQuery; } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/criteria/DatasetCriteria.java b/dmp-backend/web/src/main/java/eu/eudat/criteria/DatasetCriteria.java new file mode 100644 index 000000000..f65f69028 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/criteria/DatasetCriteria.java @@ -0,0 +1,77 @@ +package eu.eudat.criteria; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; +import com.fasterxml.jackson.databind.node.JsonNodeType; +import eu.eudat.criteria.entities.Criteria; +import eu.eudat.logic.services.operations.DatabaseRepository; +import eu.eudat.query.DatasetQuery; + +import java.io.IOException; +import java.util.*; + +public class DatasetCriteria { + private Criteria id; + private Criteria label; + private DMPCriteria dmp; + + public Criteria getId() { + return id; + } + + public void setId(JsonNode jsonNode) throws IOException { + if (jsonNode.getNodeType().equals(JsonNodeType.STRING)) { + Criteria criteria = new Criteria<>(); + criteria.setAs(jsonNode.asText()); + this.id = criteria; + } else if (jsonNode.getNodeType().equals(JsonNodeType.OBJECT)) { + ObjectReader reader = new ObjectMapper().readerFor(new TypeReference>() { + }); + this.id = reader.readValue(jsonNode); + } + } + + public Criteria getLabel() { + return label; + } + + public void setLabel(JsonNode jsonNode) throws IOException { + if (jsonNode.getNodeType().equals(JsonNodeType.STRING)) { + Criteria criteria = new Criteria<>(); + criteria.setAs(jsonNode.asText()); + this.label = criteria; + } else if (jsonNode.getNodeType().equals(JsonNodeType.OBJECT)) { + ObjectReader reader = new ObjectMapper().readerFor(new TypeReference>() { + }); + this.label = reader.readValue(jsonNode); + } + } + + public DMPCriteria getDmp() { + return dmp; + } + + public void setDmp(DMPCriteria dmp) { + this.dmp = dmp; + } + + protected List buildFields(String path) { + Set fields = new HashSet<>(); + path = path != null && !path.isEmpty() ? path + "." : ""; + if (this.id != null) fields.add(path + this.id.getAs()); + if (this.label != null) fields.add(path + this.label.getAs()); + if (this.dmp != null) fields.addAll(this.dmp.buildFields(path + "dmp")); + if (!fields.contains(path + "id")) fields.add(path + "id"); + return new LinkedList<>(fields); + } + + public DatasetQuery buildQuery(DatabaseRepository dao) { + List fields = this.buildFields(""); + DatasetQuery datasetQuery = new DatasetQuery(dao.getDatasetDao(), fields); + if (this.id != null) datasetQuery.setId(this.id.getValue()); + if (this.dmp != null) datasetQuery.setDmpQuery(this.dmp.buildQuery(dao)); + return datasetQuery; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/criteria/ProjectCriteria.java b/dmp-backend/web/src/main/java/eu/eudat/criteria/ProjectCriteria.java index b6cdff56f..873f6bbdd 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/criteria/ProjectCriteria.java +++ b/dmp-backend/web/src/main/java/eu/eudat/criteria/ProjectCriteria.java @@ -7,12 +7,11 @@ import com.fasterxml.jackson.databind.ObjectReader; import com.fasterxml.jackson.databind.node.JsonNodeType; import eu.eudat.criteria.entities.Criteria; import eu.eudat.criteria.entities.DateCriteria; -import eu.eudat.data.dao.entities.ProjectDao; +import eu.eudat.logic.services.operations.DatabaseRepository; import eu.eudat.query.ProjectQuery; import java.io.IOException; -import java.util.List; -import java.util.UUID; +import java.util.*; public class ProjectCriteria { private Criteria id; @@ -33,7 +32,8 @@ public class ProjectCriteria { criteria.setAs(jsonNode.asText()); this.id = criteria; } else if (jsonNode.getNodeType().equals(JsonNodeType.OBJECT)) { - ObjectReader reader = new ObjectMapper().readerFor(new TypeReference>() {}); + ObjectReader reader = new ObjectMapper().readerFor(new TypeReference>() { + }); this.id = reader.readValue(jsonNode); } } @@ -50,8 +50,15 @@ public class ProjectCriteria { return label; } - public void setLabel(Criteria label) { - this.label = label; + public void setLabel(JsonNode jsonNode) throws IOException { + if (jsonNode.getNodeType().equals(JsonNodeType.STRING)) { + Criteria criteria = new Criteria<>(); + criteria.setAs(jsonNode.asText()); + this.label = criteria; + } else if (jsonNode.getNodeType().equals(JsonNodeType.OBJECT)) { + ObjectReader reader = new ObjectMapper().readerFor(new TypeReference>() {}); + this.label = reader.readValue(jsonNode); + } } public void setLabel(String label) { @@ -104,9 +111,21 @@ public class ProjectCriteria { this.creator = creator; } - public ProjectQuery getQuery(ProjectDao dao) { - ProjectQuery query = new ProjectQuery(dao); + protected List buildFields(String path) { + Set fields = new HashSet<>(); + path = path != null && !path.isEmpty() ? path + "." : ""; + if (this.creator != null) fields.addAll(this.creator.buildFields(path + "creationUser")); + if (this.id != null) fields.add(path + this.id.getAs()); + if (this.label != null) fields.add(path + this.label.getAs()); + if (!fields.contains(path + "id")) fields.add(path + "id"); + return new LinkedList<>(fields); + } + + public ProjectQuery buildQuery(DatabaseRepository dao) { + List fields = this.buildFields(""); + ProjectQuery query = new ProjectQuery(dao.getProjectDao(), fields); query.setId(this.id.getValue()); + if (this.creator != null) query.setUserQuery(this.creator.buildQuery(dao)); return query; } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/criteria/UserCriteria.java b/dmp-backend/web/src/main/java/eu/eudat/criteria/UserCriteria.java index 5d5498155..4293a271c 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/criteria/UserCriteria.java +++ b/dmp-backend/web/src/main/java/eu/eudat/criteria/UserCriteria.java @@ -6,14 +6,15 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; import com.fasterxml.jackson.databind.node.JsonNodeType; import eu.eudat.criteria.entities.Criteria; -import eu.eudat.data.dao.entities.UserInfoDao; +import eu.eudat.logic.services.operations.DatabaseRepository; import eu.eudat.query.UserQuery; import java.io.IOException; -import java.util.UUID; +import java.util.*; public class UserCriteria { private Criteria id; + private Criteria email; public Criteria getId() { return id; @@ -25,14 +26,41 @@ public class UserCriteria { criteria.setAs(jsonNode.asText()); this.id = criteria; } else if (jsonNode.getNodeType().equals(JsonNodeType.OBJECT)) { - ObjectReader reader = new ObjectMapper().readerFor(new TypeReference>() {}); + ObjectReader reader = new ObjectMapper().readerFor(new TypeReference>() { + }); this.id = reader.readValue(jsonNode); } } - public UserQuery getQuery(UserInfoDao dao) { - UserQuery query = new UserQuery(dao); - query.setId(this.id.getValue()); + public Criteria getEmail() { + return email; + } + + public void setEmail(JsonNode jsonNode) throws IOException { + if (jsonNode.getNodeType().equals(JsonNodeType.STRING)) { + Criteria criteria = new Criteria<>(); + criteria.setAs(jsonNode.asText()); + this.email = criteria; + } else if (jsonNode.getNodeType().equals(JsonNodeType.OBJECT)) { + ObjectReader reader = new ObjectMapper().readerFor(new TypeReference>() { + }); + this.email = reader.readValue(jsonNode); + } + } + + protected List buildFields(String path) { + Set fields = new HashSet<>(); + path = path != null && !path.isEmpty() ? path + "." : ""; + if (this.id != null) fields.add(path + this.id.getAs()); + if (this.email != null) fields.add(path + this.email.getAs()); + if (!fields.contains(path + "id")) fields.add(path + "id"); + return new LinkedList<>(fields); + } + + public UserQuery buildQuery(DatabaseRepository dao) { + List fields = this.buildFields(""); + UserQuery query = new UserQuery(dao.getUserInfoDao(), fields); + if (this.id != null) query.setId(this.id.getValue()); return query; } }