From 8cb465e20688788e9d0e3c6afc2881f57f2463be Mon Sep 17 00:00:00 2001 From: 82177082315 <82177082315@serpro-1556258> Date: Mon, 8 Jul 2019 09:49:44 -0300 Subject: [PATCH 1/5] =?UTF-8?q?-=20Suporte=20a=20consulta=20por=20operador?= =?UTF-8?q?es=20relacionais=20(>,<,>=3D,<=3D)=20-=20Suporte=20a=20consulta?= =?UTF-8?q?=20por=20campos=20de=20data=20-=20Suporte=20a=20ordena=C3=A7?= =?UTF-8?q?=C3=A3o=20por=20campos=20de=20sugundo=20n=C3=ADvel=20(sort=3Dus?= =?UTF-8?q?uario(nome))?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/demoiselle/jee/crud/AbstractDAO.java | 95 ++++++++++++++++++- .../demoiselle/jee/crud/CrudUtilHelper.java | 4 +- .../demoiselle/jee/crud/sort/SortHelper.java | 21 ++-- 3 files changed, 109 insertions(+), 11 deletions(-) diff --git a/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/AbstractDAO.java b/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/AbstractDAO.java index 7a6976e99..9c5d09855 100644 --- a/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/AbstractDAO.java +++ b/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/AbstractDAO.java @@ -8,11 +8,15 @@ import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.TimeZone; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Logger; @@ -30,16 +34,19 @@ import javax.persistence.criteria.From; import javax.persistence.criteria.Join; import javax.persistence.criteria.Order; +import javax.persistence.criteria.Path; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import javax.ws.rs.core.MultivaluedMap; +import org.apache.commons.lang3.time.DateUtils; import org.demoiselle.jee.core.api.crud.Crud; import org.demoiselle.jee.core.api.crud.Result; import org.demoiselle.jee.crud.exception.DemoiselleCrudException; import org.demoiselle.jee.crud.pagination.PaginationHelperConfig; import org.demoiselle.jee.crud.pagination.ResultSet; import org.demoiselle.jee.crud.sort.CrudSort; +import org.demoiselle.jee.crud.sort.SortModel; @TransactionAttribute(TransactionAttributeType.MANDATORY) public abstract class AbstractDAO implements Crud { @@ -55,6 +62,12 @@ public abstract class AbstractDAO implements Crud { protected abstract EntityManager getEntityManager(); private Logger logger = Logger.getLogger(this.getClass().getName()); + + private static final String ISO8601_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS"; + + private static final String ISO8601_UTC_PATTERN = ISO8601_PATTERN + "'Z'"; + + private static final TimeZone timeZoneUTC = TimeZone.getTimeZone("UTC"); @SuppressWarnings("unchecked") public AbstractDAO() { @@ -204,9 +217,9 @@ protected void configureOrder(CriteriaBuilder criteriaBuilder, CriteriaQuery drc.getSorts().stream().forEachOrdered(sortModel -> { if (sortModel.getType().equals(CrudSort.ASC)) { - orders.add(criteriaBuilder.asc(root.get(sortModel.getField()))); + orders.add(criteriaBuilder.asc(buildSortPath(criteriaBuilder, criteriaQuery, root, sortModel))); } else { - orders.add(criteriaBuilder.desc(root.get(sortModel.getField()))); + orders.add(criteriaBuilder.desc(buildSortPath(criteriaBuilder, criteriaQuery, root, sortModel))); } }); @@ -214,6 +227,16 @@ protected void configureOrder(CriteriaBuilder criteriaBuilder, CriteriaQuery } } + + protected Path buildSortPath(CriteriaBuilder criteriaBuilder, CriteriaQuery criteriaQuery, Root root, SortModel model) { + if (CrudUtilHelper.hasSubField(model.getField())) { + String[] attrs = model.getField().split("[()]"); + // + return root.get(attrs[0]).get(attrs[1]); + } else { + return root.get(model.getField()); + } + } protected Predicate[] buildPredicates(CriteriaBuilder criteriaBuilder, CriteriaQuery criteriaQuery, Root root) { List predicates = new LinkedList<>(); @@ -268,12 +291,16 @@ private void fillPredicates(List predicates, From from, Criter predicates.add(criteriaBuilder.isEmpty(from.get(child.getKey()))); } else if (isLikeFilter(value)) { predicates.add(buildLikePredicate(criteriaBuilder, criteriaQuery, from, child.getKey(), value)); + } else if (isRelationalFilter(child.getKey(), value)) { + predicates.add(buildRelationalPredicate(criteriaBuilder, criteriaQuery, from, child.getKey(), value, parent)); } else if ("isTrue".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value)) { predicates.add(criteriaBuilder.isTrue(from.get(child.getKey()))); } else if ("isFalse".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value)) { predicates.add(criteriaBuilder.isFalse(from.get(child.getKey()))); } else if (isEnumFilter(child.getKey(), value, parent)) { predicates.add(criteriaBuilder.equal(from.get(child.getKey()), convertEnumToInt(child.getKey(), value, parent))); + } else if (isDateFilter(child.getKey(), value)) { + predicates.add(criteriaBuilder.equal(from.get(child.getKey()), convertStringToDate(child.getKey(), value))); } else if (isUUIDFilter(child.getKey(), value, parent)) { predicates.add(criteriaBuilder.equal(from.get(child.getKey()), UUID.fromString(value))); } else { @@ -399,10 +426,47 @@ private List getAllFields(Class clazz){ List fields = new ArrayList<>(); return CrudUtilHelper.getAllFields(fields, clazz); } + + protected Date convertStringToDate(String key, String value) { + final String pattern = getDatePattern(value); + final SimpleDateFormat formatter = new SimpleDateFormat(pattern); + // + if (ISO8601_UTC_PATTERN.equals(pattern)) { + formatter.setTimeZone(timeZoneUTC); + } + // + try { + return formatter.parse(value); + } catch (final ParseException e) { + throw new DemoiselleCrudException(String.format("Não foi possível converter a string (%s) para uma data", value), e); + } + } protected Boolean isLikeFilter(String value) { return value.startsWith("*") || value.endsWith("*"); } + + protected boolean isRelationalFilter(String key, String value) { + return value.startsWith(">") || value.startsWith("<"); + } + + protected boolean isDateFilter(String key, String value) { + try { + DateUtils.parseDate(value, getDatePattern(value)); + // + return true; + } catch (final ParseException e) { + return false; + } + } + + protected String getDatePattern(String date) { + if (date.endsWith("Z")) { + return ISO8601_UTC_PATTERN; + } else { + return ISO8601_PATTERN; + } + } protected Predicate buildLikePredicate(CriteriaBuilder criteriaBuilder, CriteriaQuery criteriaQuery, From root, String key, String value) { String pattern = value.trim(); @@ -416,6 +480,33 @@ protected Predicate buildLikePredicate(CriteriaBuilder criteriaBuilder, Criteria // return criteriaBuilder.like(criteriaBuilder.lower(root.get(key)), pattern.toLowerCase()); } + + @SuppressWarnings("unchecked") + protected Predicate buildRelationalPredicate(CriteriaBuilder criteriaBuilder, CriteriaQuery criteriaQuery, From root, String key, String value, TreeNodeField> tnf) { + final String pattern = value.trim(); + // + if (pattern.startsWith(">=")) { + return criteriaBuilder.greaterThanOrEqualTo(root.get(key), (Comparable)convertToAppropriateType(key, pattern.substring(2), tnf)); + } else if (pattern.startsWith("<=")) { + return criteriaBuilder.lessThanOrEqualTo(root.get(key), (Comparable)convertToAppropriateType(key, pattern.substring(2), tnf)); + } else if (pattern.startsWith(">")) { + return criteriaBuilder.greaterThan(root.get(key), (Comparable)convertToAppropriateType(key, pattern.substring(1), tnf)); + } else if (pattern.startsWith("<")) { + return criteriaBuilder.lessThan(root.get(key), (Comparable)convertToAppropriateType(key, pattern.substring(1), tnf)); + } else { + throw new DemoiselleCrudException("Operador relacional não encontrado no filtro"); + } + } + + protected Comparable convertToAppropriateType(String key, String value, TreeNodeField> tnf) { + if (isEnumFilter(key, value, tnf)) { + return convertEnumToInt(key, value, tnf); + } else if (isDateFilter(key, value)) { + return convertStringToDate(key, value); + } else { + return value; + } + } protected Integer getMaxResult() { if (drc.getLimit() == null || drc.getOffset() == null) { diff --git a/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/CrudUtilHelper.java b/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/CrudUtilHelper.java index 3d4b744c2..4c53b90f3 100644 --- a/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/CrudUtilHelper.java +++ b/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/CrudUtilHelper.java @@ -338,7 +338,7 @@ public static void validateFields(TreeNodeField> tnf, Resour } - private static Boolean hasSubField(String field) { + public static Boolean hasSubField(String field) { Pattern patternLevels = Pattern.compile("\\([^)]*\\)*"); Matcher matcher = patternLevels.matcher(field); @@ -358,4 +358,4 @@ public static String getMethodAnnotatedWithID(Class targetClass) { -} +} \ No newline at end of file diff --git a/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/sort/SortHelper.java b/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/sort/SortHelper.java index 6394abeb7..1cc66eb21 100644 --- a/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/sort/SortHelper.java +++ b/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/sort/SortHelper.java @@ -11,6 +11,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; @@ -24,6 +25,7 @@ import org.demoiselle.jee.crud.DemoiselleRequestContext; import org.demoiselle.jee.crud.ReservedKeyWords; import org.demoiselle.jee.crud.Search; +import org.demoiselle.jee.crud.TreeNodeField; /** * Class responsible for managing the 'sort' parameter comes from Url Query @@ -137,12 +139,17 @@ public void execute(ResourceInfo resourceInfo, UriInfo uriInfo) { }); } } - - // Validate if the fields are valid - drc.getSorts().stream().forEach(sortModel -> { - CrudUtilHelper.checkIfExistField(CrudUtilHelper.getTargetClass(this.resourceInfo.getResourceClass()), sortModel.getField()); - }); - + + TreeNodeField> tnf = new TreeNodeField<>(CrudUtilHelper.getTargetClass(this.resourceInfo.getResourceClass()).getName(), ConcurrentHashMap.newKeySet(1)); + + // Validate if the fields are valid, using same idea for filters validation + if (!drc.getSorts().isEmpty()) { + drc.getSorts().stream().forEach( v -> + CrudUtilHelper.fillLeafTreeNodeField(tnf, v.getField(), null) + ); + + CrudUtilHelper.validateFields(tnf, this.resourceInfo, this.crudMessage); + } } private List getValuesFromQueryString(String key) { @@ -158,4 +165,4 @@ private List getValuesFromQueryString(String key) { } return null; } -} +} \ No newline at end of file From 2edd833967081945ebda7ba570e3f4aebb0735e8 Mon Sep 17 00:00:00 2001 From: 82177082315 <82177082315@serpro-1556258> Date: Fri, 24 Jan 2020 10:16:22 -0300 Subject: [PATCH 2/5] =?UTF-8?q?Corre=C3=A7=C3=A3o=20do=20m=C3=A9todo=20de?= =?UTF-8?q?=20consulta=20que=20estava=20gerando=20uma=20cl=C3=A1sula=20"OR?= =?UTF-8?q?"=20para=20filtros=20de=20consulta=20de=20segundo=20n=C3=ADvel,?= =?UTF-8?q?=20mesmo=20os=20campos=20sendo=20diferentes.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Por exemplo: "chamada_servico?usuario(idade)=20&usuario(nome)=joao", estava gerando a query "(...) where usuario.idade = 20 OR usuario.nome = joao", quando o correto seria "usuario.idade = 20 AND usuario.nome = joao". A cláusula OR agora é gerada somente quando os campos de segundo nível forem iguais, por exemplo: "chamada_servico?usuario(idade)=20&usuario(idade)=21". --- .../main/java/org/demoiselle/jee/crud/AbstractDAO.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/AbstractDAO.java b/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/AbstractDAO.java index 9c5d09855..97b69da47 100644 --- a/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/AbstractDAO.java +++ b/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/AbstractDAO.java @@ -244,8 +244,6 @@ protected Predicate[] buildPredicates(CriteriaBuilder criteriaBuilder, CriteriaQ if (drc.getFilters() != null) { drc.getFilters().getChildren().stream().forEach(child -> { - List predicatesToBuild = new LinkedList<>(); - /* * If the child doesnt child the element is on fist level. * @@ -253,11 +251,13 @@ protected Predicate[] buildPredicates(CriteriaBuilder criteriaBuilder, CriteriaQ * */ if (child.getChildren().isEmpty()) { + List predicatesToBuild = new LinkedList<>(); child.getValue().stream().forEach(value -> { fillPredicates(predicatesToBuild, root, criteriaBuilder, criteriaQuery, child, value, null); }); + predicates.add(criteriaBuilder.or(predicatesToBuild.toArray(new Predicate[]{}))); } else{ @@ -269,14 +269,15 @@ protected Predicate[] buildPredicates(CriteriaBuilder criteriaBuilder, CriteriaQ Join join = root.join(child.getKey()); child.getChildren().stream().forEach( child2ndLevel -> { + List predicatesToBuild = new LinkedList<>(); child2ndLevel.getValue().stream().forEach(value -> { fillPredicates(predicatesToBuild, join, criteriaBuilder, criteriaQuery, child2ndLevel, value, child); }); + + predicates.add(criteriaBuilder.or(predicatesToBuild.toArray(new Predicate[]{}))); }); } - - predicates.add(criteriaBuilder.or(predicatesToBuild.toArray(new Predicate[]{}))); }); } From 68070266664d4aba0860b63cbaa3fbba36fe5c78 Mon Sep 17 00:00:00 2001 From: "Ernandes Jr." Date: Fri, 22 May 2020 16:34:32 -0300 Subject: [PATCH 3/5] Adicionado o suporte a filtros em relacionamentos do tipo ONE-TO-MANY. Exemplo: /autores?livros(nome)=Arroz --- .../org/demoiselle/jee/crud/AbstractDAO.java | 62 +++++++++++++++---- .../demoiselle/jee/crud/CrudUtilHelper.java | 9 ++- 2 files changed, 58 insertions(+), 13 deletions(-) mode change 100644 => 100755 demoiselle-crud/src/main/java/org/demoiselle/jee/crud/AbstractDAO.java mode change 100644 => 100755 demoiselle-crud/src/main/java/org/demoiselle/jee/crud/CrudUtilHelper.java diff --git a/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/AbstractDAO.java b/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/AbstractDAO.java old mode 100644 new mode 100755 index 97b69da47..6005a4631 --- a/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/AbstractDAO.java +++ b/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/AbstractDAO.java @@ -11,6 +11,7 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Collection; import java.util.Date; import java.util.LinkedList; import java.util.List; @@ -31,12 +32,14 @@ import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Expression; import javax.persistence.criteria.From; import javax.persistence.criteria.Join; import javax.persistence.criteria.Order; import javax.persistence.criteria.Path; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; +import javax.persistence.criteria.Subquery; import javax.ws.rs.core.MultivaluedMap; import org.apache.commons.lang3.time.DateUtils; @@ -266,17 +269,25 @@ protected Predicate[] buildPredicates(CriteriaBuilder criteriaBuilder, CriteriaQ * * ?category(description)=test */ - - Join join = root.join(child.getKey()); - child.getChildren().stream().forEach( child2ndLevel -> { - List predicatesToBuild = new LinkedList<>(); - - child2ndLevel.getValue().stream().forEach(value -> { - fillPredicates(predicatesToBuild, join, criteriaBuilder, criteriaQuery, child2ndLevel, value, child); - }); - - predicates.add(criteriaBuilder.or(predicatesToBuild.toArray(new Predicate[]{}))); - }); + + if (isCollectionField(child.getKey())) { + /* + * Builds an Exists predicate for filters on entity collections fields. + */ + predicates.add(buildExistsPredicate(criteriaBuilder, criteriaQuery, root, child)); + } else { + Join join = root.join(child.getKey()); + + child.getChildren().stream().forEach( child2ndLevel -> { + List predicatesToBuild = new LinkedList<>(); + + child2ndLevel.getValue().stream().forEach(value -> { + fillPredicates(predicatesToBuild, join, criteriaBuilder, criteriaQuery, child2ndLevel, value, child); + }); + + predicates.add(criteriaBuilder.or(predicatesToBuild.toArray(new Predicate[]{}))); + }); + } } }); } @@ -284,6 +295,29 @@ protected Predicate[] buildPredicates(CriteriaBuilder criteriaBuilder, CriteriaQ return predicates.toArray(new Predicate[]{}); } + @SuppressWarnings({"rawtypes", "unchecked"}) + private Predicate buildExistsPredicate(CriteriaBuilder criteriaBuilder, CriteriaQuery criteriaQuery, Root root, TreeNodeField> parent) { + Subquery subquery = criteriaQuery.subquery(Integer.class); + Root subqueryRoot = subquery.correlate(root); + Join join = subqueryRoot.join(parent.getKey()); + + List subqueryPredicates = new LinkedList<>(); + + parent.getChildren().stream().forEach(child2ndLevel -> { + List predicatesToBuild = new LinkedList<>(); + + child2ndLevel.getValue().stream().forEach(value -> { + fillPredicates(predicatesToBuild, join, criteriaBuilder, criteriaQuery, child2ndLevel, value, parent); + }); + + subqueryPredicates.add(criteriaBuilder.or(predicatesToBuild.toArray(new Predicate[] {}))); + }); + + subquery.select((Expression)criteriaBuilder.literal(1)).where(subqueryPredicates.toArray(new Predicate[] {})); + + return criteriaBuilder.exists(subquery); + } + private void fillPredicates(List predicates, From from, CriteriaBuilder criteriaBuilder, CriteriaQuery criteriaQuery, TreeNodeField> child, String value, TreeNodeField> parent) { if ("null".equals(value) || value == null) { @@ -546,5 +580,9 @@ public DemoiselleRequestContext getDrc() { public Class getEntityClass() { return entityClass; } - + + private boolean isCollectionField(String name) { + return getAllFields(getEntityClass()).stream() + .anyMatch(f -> f.getName().equalsIgnoreCase(name) && Collection.class.isAssignableFrom(f.getType())); + } } \ No newline at end of file diff --git a/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/CrudUtilHelper.java b/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/CrudUtilHelper.java old mode 100644 new mode 100755 index 4c53b90f3..c7a5b3d64 --- a/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/CrudUtilHelper.java +++ b/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/CrudUtilHelper.java @@ -10,6 +10,7 @@ import java.lang.reflect.ParameterizedType; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.LinkedList; import java.util.List; import java.util.Set; @@ -315,7 +316,13 @@ public static void validateFields(TreeNodeField> tnf, Resour throw new IllegalArgumentException(crudMessage.fieldRequestDoesNotExistsOnObject(leaf.getKey(), targetClass.getName())); } - Class fieldClazz = fieldMaster.getType(); + Class fieldClazz; + + if (Collection.class.isAssignableFrom(fieldMaster.getType())) { + fieldClazz = (Class)((ParameterizedType)fieldMaster.getGenericType()).getActualTypeArguments()[0]; + } else { + fieldClazz = fieldMaster.getType(); + } leaf.getChildren().forEach((subLeaf) -> { try { From a244e85d791a1eaa9539233b05901d969fa4244b Mon Sep 17 00:00:00 2001 From: "Ernandes Jr." Date: Mon, 20 Jul 2020 11:05:19 -0300 Subject: [PATCH 4/5] Adicionado suporte a filtro por interval: ?ano=[2018...2019] => a <= X <= b ?ano=(2018...2019] => a < X <= b ?ano=[2018...2019) => a <= X < b ?ano=(2018...2019) => a < X < b --- .../org/demoiselle/jee/crud/AbstractDAO.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/AbstractDAO.java b/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/AbstractDAO.java index 6005a4631..406afea33 100755 --- a/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/AbstractDAO.java +++ b/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/AbstractDAO.java @@ -328,6 +328,8 @@ private void fillPredicates(List predicates, From from, Criter predicates.add(buildLikePredicate(criteriaBuilder, criteriaQuery, from, child.getKey(), value)); } else if (isRelationalFilter(child.getKey(), value)) { predicates.add(buildRelationalPredicate(criteriaBuilder, criteriaQuery, from, child.getKey(), value, parent)); + } else if (isIntervalFilter(value)) { + predicates.add(buildIntervalPredicate(criteriaBuilder, criteriaQuery, from, child.getKey(), value, parent)); } else if ("isTrue".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value)) { predicates.add(criteriaBuilder.isTrue(from.get(child.getKey()))); } else if ("isFalse".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value)) { @@ -481,6 +483,10 @@ protected Boolean isLikeFilter(String value) { return value.startsWith("*") || value.endsWith("*"); } + protected Boolean isIntervalFilter(String value) { + return value.matches("^(\\(|\\[).+\\.{3}.+(\\)|\\])$"); //e.g. [2018...2019] + } + protected boolean isRelationalFilter(String key, String value) { return value.startsWith(">") || value.startsWith("<"); } @@ -516,6 +522,32 @@ protected Predicate buildLikePredicate(CriteriaBuilder criteriaBuilder, Criteria return criteriaBuilder.like(criteriaBuilder.lower(root.get(key)), pattern.toLowerCase()); } + @SuppressWarnings("unchecked") + protected Predicate buildIntervalPredicate(CriteriaBuilder criteriaBuilder, CriteriaQuery criteriaQuery, From root, String key, String value, TreeNodeField> tnf) { + final String pattern = value.trim(); + final String op1 = pattern.substring(0, 1); + final String op2 = pattern.substring(pattern.length() -1); + final String value1 = pattern.substring(1, pattern.indexOf("...")); + final String value2 = pattern.substring(pattern.indexOf("...") + 3, pattern.length() -1); + // + final Predicate p1; + final Predicate p2; + // + if ("[".equals(op1)) { + p1 = criteriaBuilder.greaterThanOrEqualTo(root.get(key), (Comparable)convertToAppropriateType(key, value1, tnf)); + } else { + p1 = criteriaBuilder.greaterThan(root.get(key), (Comparable)convertToAppropriateType(key, value1, tnf)); + } + // + if ("]".equals(op2)) { + p2 = criteriaBuilder.lessThanOrEqualTo(root.get(key), (Comparable)convertToAppropriateType(key, value2, tnf)); + } else { + p2 = criteriaBuilder.lessThan(root.get(key), (Comparable)convertToAppropriateType(key, value2, tnf)); + } + // + return criteriaBuilder.and(p1, p2); + } + @SuppressWarnings("unchecked") protected Predicate buildRelationalPredicate(CriteriaBuilder criteriaBuilder, CriteriaQuery criteriaQuery, From root, String key, String value, TreeNodeField> tnf) { final String pattern = value.trim(); From 171a8f005ae58b85c7eb0b0f039f673e34f2dd99 Mon Sep 17 00:00:00 2001 From: Ernandes Date: Wed, 2 Feb 2022 15:01:29 -0300 Subject: [PATCH 5/5] =?UTF-8?q?Mecanismo=20para=20escapar=20v=C3=ADrgulas?= =?UTF-8?q?=20em=20valores=20de=20par=C3=A3metros.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../demoiselle/jee/crud/CrudUtilHelper.java | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/CrudUtilHelper.java b/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/CrudUtilHelper.java index c7a5b3d64..56fa3ab97 100755 --- a/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/CrudUtilHelper.java +++ b/demoiselle-crud/src/main/java/org/demoiselle/jee/crud/CrudUtilHelper.java @@ -16,6 +16,8 @@ import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; + import javax.persistence.Id; import javax.ws.rs.container.ResourceInfo; @@ -115,13 +117,26 @@ public static List extractFields(String fields) { int lastComma = 0; int lastPosition = 0; String subField = ""; + + int escapedCommas = 0; char fieldsArray[] = fields.toCharArray(); for (int i = 0; i < fieldsArray.length; i++) { char letter = fieldsArray[i]; - + char nextLetter = i + 1 < fieldsArray.length ? fieldsArray[i + 1] : Character.MIN_VALUE; + + if (letter == ',') { + if (nextLetter == ',' && escapedCommas == 0) { + escapedCommas++; + continue; + } else if (escapedCommas > 0) { + escapedCommas = 0; + continue; + } + } + // Find util the next ',' character if (letter == ',') { lastComma = i; @@ -178,7 +193,7 @@ public static List extractFields(String fields) { results.add(subField); } - return results; + return results.stream().map(s -> s.replace(",,", ",")).collect(Collectors.toList()); } /**