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.
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.fryske_akademy.ejb;
/*-
* #%L
* ejbCrudApi
* %%
* Copyright (C) 2018 Fryske Akademy
* %%
* 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.
* #L%
*/
import java.util.ArrayList;
import java.util.List;
/**
* Holder for parameter info that can be used when {@link JpqlBuilder building}
* a jpql query, adds spaces where needed. Uses {@link Builder#Builder() } with syntax support by default.
*
* @author eduard
*/
public class Param {
/**
* call {@link #one(java.lang.String, java.lang.Object, boolean, org.fryske_akademy.ejb.Param.Builder.WildcardMapping) } with true and
* {@link Builder#DEFAULT_MAPPING}
* @param key
* @param value
* @return
*/
public static List one(String key, Object value) {
return one(key, value, true, Builder.DEFAULT_MAPPING);
}
public static List one(String key, Object value, boolean syntaxSupport, Builder.WildcardMapping wildcardMapping) {
return new Builder(syntaxSupport,wildcardMapping).add(key, value).build();
}
public enum AndOr {
AND, OR;
private static AndOr fromBool(boolean or) {
return or ? OR : AND;
}
@Override
public String toString() {
return " " + name() + " ";
}
}
private final String propertyPath;
private final String paramKey;
private final String operator;
private final Object paramValue;
private final String not;
private final AndOr andOr;
private final boolean skipSetValue;
private final Class paramType;
/**
* Bottleneck constructor
*
* @param propertyPath the path to the property in an entity i.e.
* lemma.soart.id, or id
* @param paramKey the key of the parameter i.e. :id
* @param operator the operator i.e. like or =
* @param paramValue the value used in TypedQuery#setParameter
* @param not when true use negation
* @param or when true use or otherwise and
*/
private Param(String propertyPath, String paramKey, String operator, Object paramValue, boolean not, boolean or) {
this.propertyPath = propertyPath + " ";
this.skipSetValue = Builder.nullComp(operator) || Builder.emptyComp(operator);
this.paramKey = paramKey;
this.operator = " " + operator + " ";
this.paramValue = paramValue;
this.not = not ? " NOT " : " ";
this.andOr = AndOr.fromBool(or);
paramType = paramValue==null?Object.class:paramValue.getClass();
}
/**
* uses operator like for String and = for other paramValue
*
* @param propertyPath
* @param paramKey
* @param operator
* @param paramValue
*/
private Param(String propertyPath, String paramKey, String operator, Object paramValue) {
this(propertyPath, paramKey, operator, paramValue, false, false);
}
/**
* uses operator =
*
* @param paramKey
* @param paramValue
*/
private Param(String paramKey, Object paramValue) {
this(paramKey, paramKey, "=", paramValue, false, false);
}
public String getPropertyPath() {
return propertyPath;
}
/**
* for native queries this key should be a numeric positional parameter
* @return
*/
public String getParamKey() {
return paramKey;
}
public String getOperator() {
return operator;
}
public Object getParamValue() {
return paramValue;
}
public String getNot() {
return not;
}
public AndOr getAndOr() {
return andOr;
}
public boolean isSkipSetValue() {
return skipSetValue;
}
public Class getParamType() {
return paramType;
}
@Override
public String toString() {
return "Param{" + "propertyPath=" + propertyPath + ", paramKey=" + paramKey + ", operator=" + operator + ", paramValue=" + paramValue + ", not=" + not + ", andOr=" + andOr + ", skipSetValue=" + skipSetValue + '}';
}
/**
* helps building a list of Param, by default supports a bit of syntax in String values: "is [not] null/empty" and ! at the beginning of a value.
* You can also use {@link #Builder(boolean, WildcardMapping) }
*/
public static class Builder {
/**
* translation table a wildcard for more characters and a wildcard for one character
*/
public interface WildcardMapping {
char getMoreIn();
char getMoreOut();
char getOneIn();
char getOneOut();
}
/**
* * => %, ? => _
*/
public static class DefaultWildcardMapping implements WildcardMapping {
@Override
public char getMoreIn() {
return '*';
}
@Override
public char getMoreOut() {
return '%';
}
@Override
public char getOneIn() {
return '?';
}
@Override
public char getOneOut() {
return '_';
}
}
private final List params = new ArrayList<>(3);
public static final WildcardMapping DEFAULT_MAPPING = new DefaultWildcardMapping();
public static final String ISNULL = "is null";
public static final String ISNOTNULL = "is not null";
public static final String ISEMPTY = "is empty";
public static final String ISNOTEMPTY = "is not empty";
public static final char NEGATION = '!';
private final boolean syntaxInValue;
private final WildcardMapping wildcardMapping;
public Builder(boolean syntaxInValue, WildcardMapping wildcardMapping) {
this.syntaxInValue = syntaxInValue;
this.wildcardMapping = wildcardMapping;
}
/**
* Builder with syntax support in value (!, is [not] null). Calls
* {@link #Builder(boolean, WildcardMapping) } with true and null.
*/
public Builder() {
this(true,null);
}
/**
* When paramValue is a String call {@link #add(java.lang.String, java.lang.String, java.lang.String, java.lang.String, boolean)
* } with false otherwise call {@link #add(java.lang.String, java.lang.String, java.lang.String, java.lang.Object, boolean, boolean)
* } with false, false.
*
* @param propertyPath
* @param paramKey
* @param operator
* @param paramValue
* @return
*/
public Builder add(String propertyPath, String paramKey, String operator, Object paramValue) {
if (paramValue instanceof String) {
return add(propertyPath, paramKey, operator, String.valueOf(paramValue), false);
} else {
return add(propertyPath, paramKey, operator, paramValue, false, false);
}
}
/**
* When paramValue starts with a ! {@link #getNot() negation} is used,
* when trimmed paramValue is "is [not] null",
* operator is set to value and value will be ignored.
*
* @param propertyPath
* @param paramKey
* @param operator
* @param paramValue
* @param or
* @return
*/
public Builder add(String propertyPath, String paramKey, String operator, String paramValue, boolean or) {
return add(propertyPath, paramKey, determineOperator(operator, paramValue), replaceWildcards(stripNegation(paramValue)), isNegation(paramValue), or);
}
/**
* Bottleneck function, adds a new Param
*
* @param propertyPath
* @param paramKey
* @param operator
* @param paramValue
* @param not
* @param or
* @return
*/
public Builder add(String propertyPath, String paramKey, String operator, Object paramValue, boolean not, boolean or) {
params.add(new Param(propertyPath, paramKey, operator, paramValue, not, or));
return this;
}
/**
* check if a value indicates a negation
* @param value
* @return
*/
public boolean isNegation(String value) {
return syntaxInValue && value != null && value.indexOf(NEGATION) == 0;
}
private String stripNegation(String value) {
return isNegation(value) ? value.substring(1) : value;
}
private String replaceWildcards(String value) {
return wildcardMapping==null?value:value
.replace(wildcardMapping.getMoreIn(), wildcardMapping.getMoreOut())
.replace(wildcardMapping.getOneIn(), wildcardMapping.getOneOut());
}
private String determineOperator(String operator, String value) {
if (syntaxInValue && nullComp(value)) {
return value;
}
return operator;
}
/**
* check if a value is a null comparison
* @param s
* @return
*/
public static boolean nullComp(String s) {
if (s==null) return false;
String t = s.trim().toLowerCase();
return t.equals(ISNULL) || t.equals(ISNOTNULL);
}
/**
* check if a value is a empty comparison
* @param s
* @return
*/
public static boolean emptyComp(String s) {
if (s==null) return false;
String t = s.trim().toLowerCase();
return t.equals(ISEMPTY) || t.equals(ISNOTEMPTY);
}
/**
* Calls {@link #add(java.lang.String, java.lang.Object, boolean) } with
* false
*
* @param paramKey
* @param paramValue
* @return
*/
public Builder add(String paramKey, Object paramValue) {
return add(paramKey, paramValue, false);
}
/**
* When paramValue is a String use like as operator otherwise = and call
* {@link #add(java.lang.String, java.lang.String, java.lang.String, java.lang.String, boolean) },
* otherwise call {@link #add(java.lang.String, java.lang.String, java.lang.String, java.lang.Object, boolean, boolean)
* }
* with false for not.
*
* @param paramKey
* @param paramValue
* @param or when true use or in queries
* @return
*/
public Builder add(String paramKey, Object paramValue, boolean or) {
if (paramValue instanceof String) {
return add(paramKey, paramKey, "like", (String) paramValue, or);
} else {
return add(paramKey, paramKey, "=", paramValue, false, or);
}
}
public List build() {
return params;
}
public boolean isSyntaxInValue() {
return syntaxInValue;
}
public boolean containsKey(String key) {
return params.stream().anyMatch((t) -> {
return t.getParamKey().equals(key);
});
}
}
}