All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.jboss.pnc.facade.rsql.RSQLProducerImpl Maven / Gradle / Ivy
/**
* JBoss, Home of Professional Open Source.
* Copyright 2014-2022 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jboss.pnc.facade.rsql;
import cz.jirutka.rsql.parser.RSQLParser;
import cz.jirutka.rsql.parser.RSQLParserException;
import cz.jirutka.rsql.parser.ast.ComparisonOperator;
import cz.jirutka.rsql.parser.ast.Node;
import cz.jirutka.rsql.parser.ast.RSQLOperators;
import org.jboss.pnc.facade.rsql.mapper.RSQLMapper;
import org.jboss.pnc.spi.datastore.repositories.api.impl.StableEmptySortInfo;
import org.jboss.pnc.datastore.predicates.rsql.EmptyRSQLPredicate;
import org.jboss.pnc.facade.rsql.mapper.UniversalRSQLMapper;
import org.jboss.pnc.model.GenericEntity;
import org.jboss.pnc.spi.datastore.repositories.api.Predicate;
import org.jboss.pnc.spi.datastore.repositories.api.SortInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
*
* @author Honza Brázdil <[email protected] >
*/
@ApplicationScoped
public class RSQLProducerImpl implements RSQLProducer {
private static final Logger logger = LoggerFactory.getLogger(RSQLProducerImpl.class);
private final RSQLParser predicateParser;
private final RSQLParser sortParser;
private final static Pattern likePattern = Pattern.compile("(%[a-zA-Z0-9\\s]+%)");
/**
* RSQL wildcard character to replace single character.
*/
final static String WILDCARD_SINGLE_CHARACTER = "?";
/**
* RSQL wildcard character to replace multiple characters.
*/
final static String WILDCARD_MULTIPLE_CHARACTERS = "*";
/**
* RSQL wildcard character to replace multiple characters.
*/
final static String WILDCARD_MULTIPLE_CHARACTERS_DB = "%";
private static final String FIXED_START_OF_SORTING_EXPRESSION = "sort";
final static ComparisonOperator LIKE = new ComparisonOperator("=like=", "=LIKE=");
final static ComparisonOperator NOT_LIKE = new ComparisonOperator("=notlike=", "=NOTLIKE=");
final static ComparisonOperator IS_NULL = new ComparisonOperator("=isnull=", "=ISNULL=");
static final ComparisonOperator ASC = new ComparisonOperator("=asc=", true);
static final ComparisonOperator DESC = new ComparisonOperator("=desc=", true);
@Inject
UniversalRSQLMapper universalMapper;
public RSQLProducerImpl() {
Set predicateOperators = RSQLOperators.defaultOperators();
predicateOperators.add(LIKE);
predicateOperators.add(NOT_LIKE);
predicateOperators.add(IS_NULL);
predicateParser = new RSQLParser(predicateOperators);
Set sortOperators = new HashSet<>();
sortOperators.add(ASC);
sortOperators.add(DESC);
sortParser = new RSQLParser(sortOperators);
}
@Override
public > Predicate getCriteriaPredicate(Class type, String rsql) {
// TODO: Remove this empty check once NCL-8692, NCL-8693 are fixed
if (rsql == null || rsql.isEmpty()) {
return new EmptyRSQLPredicate();
}
return getCriteriaPredicate(universalMapper.mapper(type), rsql);
}
@Override
public > Predicate getCriteriaPredicate(RSQLMapper mapper, String rsql) {
if (rsql == null || rsql.isEmpty()) {
return new EmptyRSQLPredicate();
}
try {
Node rootNode = predicateParser.parse(preprocessRSQL(rsql));
return getEntityPredicate(rootNode, mapper);
} catch (RSQLParserException ex) {
throw new RSQLException("failure parsing RSQL", ex);
}
}
@Override
public java.util.function.Predicate getStreamPredicate(String rsql) {
if (rsql == null || rsql.isEmpty()) {
return x -> true;
}
try {
Node rootNode = predicateParser.parse(preprocessRSQL(rsql));
return getStreamPredicate(rootNode);
} catch (RSQLParserException ex) {
throw new RSQLException("failure parsing RSQL", ex);
}
}
@Override
public > SortInfo getSortInfo(Class type, String rsql) {
// TODO: Remove this empty check once NCL-8692, NCL-8693 are fixed
if (rsql == null || rsql.isEmpty()) {
return new StableEmptySortInfo<>();
}
return getSortInfo(universalMapper.mapper(type), rsql);
}
@Override
public > SortInfo getSortInfo(RSQLMapper mapper, String rsql) {
if (rsql == null || rsql.isEmpty()) {
return new StableEmptySortInfo<>();
}
if (!rsql.startsWith(FIXED_START_OF_SORTING_EXPRESSION)) {
rsql = FIXED_START_OF_SORTING_EXPRESSION + rsql;
}
Node rootNode = sortParser.parse(preprocessRSQL(rsql));
return (SortInfo) rootNode.accept(new SortRSQLNodeTraveller(mapper));
}
@Override
public Comparator getComparator(String rsql) {
if (rsql == null || rsql.isEmpty()) {
throw new RSQLException("RSQL sort query must be non-empty and non-null.");
}
if (!rsql.startsWith(FIXED_START_OF_SORTING_EXPRESSION)) {
rsql = FIXED_START_OF_SORTING_EXPRESSION + rsql;
}
Node rootNode = sortParser.parse(preprocessRSQL(rsql));
return rootNode.accept(new ComparatorRSQLNodeTraveller<>());
}
private String preprocessRSQL(String rsql) {
String result = rsql;
Matcher matcher = likePattern.matcher(rsql);
while (matcher.find()) {
result = rsql.replaceAll(matcher.group(1), matcher.group(1).replaceAll("\\s", WILDCARD_SINGLE_CHARACTER));
}
return result;
}
private > Predicate getEntityPredicate(Node rootNode, RSQLMapper mapper) {
return (root, query, cb) -> {
RSQLNodeTraveller visitor = new EntityRSQLNodeTraveller(
root,
cb,
mapper,
universalMapper.getConverter());
return rootNode.accept(visitor);
};
}
private java.util.function.Predicate getStreamPredicate(Node rootNode) {
return instance -> {
RSQLNodeTraveller visitor = new StreamRSQLNodeTraveller(instance);
return rootNode.accept(visitor);
};
}
}