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.
com.blazebit.persistence.impl.query.AbstractCustomQuery Maven / Gradle / Ivy
/*
* Copyright 2014 - 2020 Blazebit.
*
* 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 com.blazebit.persistence.impl.query;
import com.blazebit.persistence.impl.ParameterValueTransformer;
import com.blazebit.persistence.impl.ValuesParameterBinder;
import com.blazebit.persistence.impl.util.SetView;
import com.blazebit.persistence.spi.CteQueryWrapper;
import javax.persistence.Parameter;
import javax.persistence.Query;
import javax.persistence.TemporalType;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author Christian Beikov
* @since 1.2.0
*/
public abstract class AbstractCustomQuery implements Query, CteQueryWrapper {
protected final QuerySpecification querySpecification;
protected final Map transformers;
protected final Map valuesParameters;
protected final Map valuesElementParameters;
protected final Map> parameters;
protected final Map valueBinders;
protected int firstResult;
protected int maxResults = Integer.MAX_VALUE;
public AbstractCustomQuery(QuerySpecification querySpecification, Map transformers, Map valuesParameters, Map valuesBinders) {
this.querySpecification = querySpecification;
Map valuesParameterMap = new HashMap();
Map> parameters = new HashMap<>();
this.valueBinders = new HashMap<>(parameters.size());
for (Parameter p : querySpecification.getParameters()) {
String name = p.getName();
ValuesParameterBinder valuesParameterBinder = valuesBinders.get(name);
if (valuesParameterBinder == null) {
parameters.put(name, p);
valueBinders.put(name, null);
} else {
ValuesParameter param = new ValuesParameter(name, valuesParameterBinder);
parameters.put(name, param);
valueBinders.put(name, null);
valuesParameterMap.put(name, param);
}
}
Map newTransformers = new HashMap<>(transformers.size());
for (Map.Entry entry : transformers.entrySet()) {
newTransformers.put(entry.getKey(), entry.getValue().forQuery(this));
}
this.transformers = Collections.unmodifiableMap(newTransformers);
this.valuesParameters = Collections.unmodifiableMap(valuesParameterMap);
this.valuesElementParameters = Collections.unmodifiableMap(valuesParameters);
this.parameters = Collections.unmodifiableMap(parameters);
}
public QuerySpecification getQuerySpecification() {
return querySpecification;
}
public String getSql() {
return querySpecification.getSql();
}
@Override
public List getParticipatingQueries() {
return querySpecification.getParticipatingQueries();
}
@Override
public Query setMaxResults(int maxResults) {
this.maxResults = maxResults;
return this;
}
@Override
public int getMaxResults() {
return maxResults;
}
@Override
public Query setFirstResult(int startPosition) {
this.firstResult = startPosition;
return this;
}
@Override
public int getFirstResult() {
return firstResult;
}
protected void bindParameters() {
Set missingParameters = null;
for (Query q : querySpecification.getParticipatingQueries()) {
for (Parameter p : q.getParameters()) {
String name = p.getName();
String valuesName = valuesElementParameters.get(name);
if (valuesName == null) {
ValueBinder valueBinder = valueBinders.get(name);
if (valueBinder == null) {
if (missingParameters == null) {
missingParameters = new HashSet<>();
}
missingParameters.add(name);
} else {
valueBinder.bind(q, name);
}
} else {
ValuesParameter valuesParameter = valuesParameters.get(valuesName);
if (valuesParameter.getValue() == null) {
if (missingParameters == null) {
missingParameters = new HashSet<>();
}
missingParameters.add(name);
} else {
valuesParameter.bind(q);
}
}
}
}
if (missingParameters != null && !missingParameters.isEmpty()) {
// Re-Check since a transformer could spread values
Iterator iterator = missingParameters.iterator();
while (iterator.hasNext()) {
String missingParamName = iterator.next();
String valuesName = valuesElementParameters.get(missingParamName);
if (valuesName == null) {
if (valueBinders.get(missingParamName) != null) {
iterator.remove();
}
} else {
if (valuesParameters.get(valuesName).getValue() != null) {
iterator.remove();
}
}
}
if (!missingParameters.isEmpty()) {
throw new IllegalArgumentException("The following parameters have not been set: " + missingParameters);
}
}
}
@Override
public Query setParameter(Parameter param, T value) {
setParameter(param.getName(), value);
return this;
}
@Override
public Query setParameter(Parameter param, Calendar value, TemporalType temporalType) {
setParameter(param.getName(), value, temporalType);
return this;
}
@Override
public Query setParameter(Parameter param, Date value, TemporalType temporalType) {
setParameter(param.getName(), value, temporalType);
return this;
}
@Override
public Query setParameter(String name, Object value) {
ValuesParameter valuesParameter = valuesParameters.get(name);
if (valuesParameter == null) {
if (!parameters.containsKey(name)) {
throw new IllegalArgumentException("Invalid or unknown parameter with name: " + name);
}
ParameterValueTransformer transformer = transformers.get(name);
if (transformer != null) {
value = transformer.transform(value);
}
if (value instanceof Collection) {
querySpecification.onCollectionParameterChange(name, (Collection) value);
}
valueBinders.put(name, new DefaultValueBinder(value));
} else {
valuesParameter.setValue(value);
}
return this;
}
@Override
public Query setParameter(String name, Calendar value, TemporalType temporalType) {
if (!parameters.containsKey(name)) {
throw new IllegalArgumentException("Invalid or unknown parameter with name: " + name);
}
valueBinders.put(name, new CalendarValueBinder(value, temporalType));
return this;
}
@Override
public Query setParameter(String name, Date value, TemporalType temporalType) {
if (!parameters.containsKey(name)) {
throw new IllegalArgumentException("Invalid or unknown parameter with name: " + name);
}
valueBinders.put(name, new DateValueBinder(value, temporalType));
return this;
}
@Override
public Query setParameter(int position, Object value) {
return setParameter(Integer.toString(position), value);
}
@Override
public Query setParameter(int position, Calendar value, TemporalType temporalType) {
return setParameter(Integer.toString(position), value, temporalType);
}
@Override
public Query setParameter(int position, Date value, TemporalType temporalType) {
return setParameter(Integer.toString(position), value, temporalType);
}
@Override
public Set> getParameters() {
return new SetView<>(parameters.values());
}
@Override
public Parameter getParameter(String name) {
return parameters.get(name);
}
@Override
public Parameter getParameter(String name, Class type) {
Parameter p = getParameter(name);
if (!type.isAssignableFrom(p.getParameterType())) {
throw new IllegalArgumentException("Parameter '" + name + "' is not assignable to '" + type.getName() + "'!");
}
return (Parameter) p;
}
@Override
public Parameter getParameter(int position) {
throw new IllegalArgumentException("Positional parameters unsupported!");
}
@Override
public Parameter getParameter(int position, Class type) {
throw new IllegalArgumentException("Positional parameters unsupported!");
}
@Override
public boolean isBound(Parameter param) {
ValuesParameter valuesParameter = valuesParameters.get(param.getName());
if (valuesParameter != null) {
return valuesParameter.getValue() != null;
}
return valueBinders.get(param.getName()) != null;
}
@Override
public T getParameterValue(Parameter param) {
return (T) getParameterValue(param.getName());
}
@Override
public Object getParameterValue(String name) {
ValuesParameter valuesParameter = valuesParameters.get(name);
if (valuesParameter != null) {
return valuesParameter.getValue();
}
ValueBinder valueBinder = valueBinders.get(name);
return valueBinder == null ? null : valueBinder.getValue();
}
@Override
public Object getParameterValue(int position) {
throw new IllegalArgumentException("Positional parameters unsupported!");
}
/**
* @author Christian Beikov
* @since 1.2.0
*/
static interface ValueBinder {
void bind(Query query, String name);
Object getValue();
}
/**
* @author Christian Beikov
* @since 1.2.0
*/
static class DefaultValueBinder implements ValueBinder {
private final Object value;
public DefaultValueBinder(Object value) {
this.value = value;
}
@Override
public void bind(Query query, String name) {
query.setParameter(name, value);
}
@Override
public Object getValue() {
return value;
}
}
/**
* @author Christian Beikov
* @since 1.2.0
*/
static class CalendarValueBinder implements ValueBinder {
private final Calendar value;
private final TemporalType temporalType;
public CalendarValueBinder(Calendar value, TemporalType temporalType) {
this.value = value;
this.temporalType = temporalType;
}
@Override
public void bind(Query query, String name) {
query.setParameter(name, value, temporalType);
}
@Override
public Object getValue() {
return value;
}
}
/**
* @author Christian Beikov
* @since 1.2.0
*/
static class DateValueBinder implements ValueBinder {
private final Date value;
private final TemporalType temporalType;
public DateValueBinder(Date value, TemporalType temporalType) {
this.value = value;
this.temporalType = temporalType;
}
@Override
public void bind(Query query, String name) {
query.setParameter(name, value, temporalType);
}
@Override
public Object getValue() {
return value;
}
}
/**
* @author Christian Beikov
* @since 1.2.0
*/
static class ValuesParameter implements Parameter {
private final String name;
private final ValuesParameterBinder binder;
private Collection value;
public ValuesParameter(String name, ValuesParameterBinder binder) {
this.name = name;
this.binder = binder;
}
@Override
public String getName() {
return name;
}
@Override
public Integer getPosition() {
return null;
}
@Override
public Class getParameterType() {
return Collection.class;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
if (value == null) {
throw new IllegalArgumentException("null not allowed for VALUES parameter!");
}
if (!(value instanceof Collection)) {
throw new IllegalArgumentException("Value for VALUES parameter must be a collection! Unsupported type: " + value.getClass());
}
Collection collection = (Collection) value;
if (collection.size() > binder.size()) {
throw new IllegalArgumentException("The size of the collection must be lower or equal to the specified size for the VALUES clause.");
}
this.value = collection;
}
public void bind(Query query) {
binder.bind(query, value);
}
}
}