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.github.rutledgepaulv.qbuilders.builders.QBuilder
* * *
* * * Copyright (C) 2016 Paul Rutledge
* * *
* * * This software may be modified and distributed under the terms
* * * of the MIT license. See the LICENSE file for details.
* *
*
*/
package com.github.rutledgepaulv.qbuilders.builders;
import com.github.rutledgepaulv.qbuilders.conditions.Condition;
import com.github.rutledgepaulv.qbuilders.conditions.Partial;
import com.github.rutledgepaulv.qbuilders.delegates.concrete.*;
import com.github.rutledgepaulv.qbuilders.delegates.virtual.Delegate;
import com.github.rutledgepaulv.qbuilders.delegates.virtual.PropertyDelegate;
import com.github.rutledgepaulv.qbuilders.nodes.*;
import com.github.rutledgepaulv.qbuilders.operators.ComparisonOperator;
import com.github.rutledgepaulv.qbuilders.properties.concrete.*;
import com.github.rutledgepaulv.qbuilders.properties.virtual.Property;
import com.github.rutledgepaulv.qbuilders.structures.FieldPath;
import com.github.rutledgepaulv.qbuilders.utilities.ObjectUtils;
import com.github.rutledgepaulv.qbuilders.visitors.ContextualNodeVisitor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import static java.util.Arrays.asList;
/**
* The single class that can be used to construct an abstract representation of a query. Designed
* to be extended for each domain model that might be queried against, with each field exposed as
* a property condition builder.
*
* @param The final type of the builder, used for a fluid chaining interface.
*/
@SuppressWarnings("unchecked")
public class QBuilder> implements Partial {
protected LogicalNode root;
protected LogicalNode current;
public QBuilder() {
root = current = new OrNode();
}
public final > EnumProperty enumeration(String field) {
return prop(field, EnumPropertyDelegate.class, EnumProperty.class);
}
public final BooleanProperty bool(String field) {
return prop(field, BooleanPropertyDelegate.class, BooleanProperty.class);
}
public final StringProperty string(String field) {
return prop(field, StringPropertyDelegate.class, StringProperty.class);
}
public final ShortProperty shortNum(String field) {
return prop(field, ShortPropertyDelegate.class, ShortProperty.class);
}
public final IntegerProperty intNum(String field) {
return prop(field, IntegerPropertyDelegate.class, IntegerProperty.class);
}
public final LongProperty longNum(String field) {
return prop(field, LongPropertyDelegate.class, LongProperty.class);
}
public final FloatProperty floatNum(String field) {
return prop(field, FloatPropertyDelegate.class, FloatProperty.class);
}
public final DoubleProperty doubleNum(String field) {
return prop(field, DoublePropertyDelegate.class, DoubleProperty.class);
}
public final InstantProperty instant(String field) {
return prop(field, InstantPropertyDelegate.class, InstantProperty.class);
}
public final > ConditionProperty condition(String field) {
return prop(field, ConditionPropertyDelegate.class, ConditionProperty.class);
}
protected final , Q extends Property> Q prop(String field, Class delegate, Class inter) {
if(!inter.isAssignableFrom(delegate)) {
throw new IllegalArgumentException("Must provide a delegate that implements the interface to be returned.");
}
return (Q) ObjectUtils.init(delegate, new FieldPath(field), self());
}
@SafeVarargs
public final Condition and(Condition c1, Condition c2, Condition... cn) {
List> conditions = new ArrayList<>();
conditions.addAll(asList(c1,c2));
conditions.addAll(asList(cn));
return and(conditions);
}
@SafeVarargs
public final Condition or(Condition c1, Condition c2, Condition... cn) {
List> conditions = new ArrayList<>();
conditions.addAll(asList(c1,c2));
conditions.addAll(asList(cn));
return or(conditions);
}
public final Condition and(List> conditions) {
return combine(conditions, AndNode.class);
}
public final Condition or(List> conditions) {
return combine(conditions, OrNode.class);
}
private Condition combine(List> conditions, Class type) {
List children = conditions.stream()
.map(condition -> ((QBuilder) condition).self().current)
.collect(Collectors.toList());
S node = ObjectUtils.init(type, self().current, children);
self().current.getChildren().add(node);
return new ConditionDelegate(self());
}
/**
* Call this method to add a condition to the current logical node of the underlying query tree.
*
* @param field The field that this condition belongs to.
* @param operator The operator indicating how the values provided should be interpreted against the field.
* @param values The values to use in the comparison against the value of the field.
*
* @return A completed {@link Condition} that can be built into a query or logically composed into other conditions.
*/
protected final Condition condition(FieldPath field, ComparisonOperator operator, Collection> values) {
ComparisonNode node = new ComparisonNode(self().current);
node.setField(field);
node.setOperator(operator);
node.setValues(values);
self().current.getChildren().add(node);
return new ConditionDelegate(self());
}
/**
* Since we have delegate classes that extend this class but not its potential end-user imposed subclasses
* we instead pass the original instance of whatever the final QBuilder class is around as
* a delegate which each view calls for any operations instead of calling 'this' thereby providing type safe
* compatibility with extensions.
*
* @return The instance that should be modified on actions.
*/
protected T self() {
return (T) this;
}
/**
* A delegate view of this builder that represents a logically complete condition. A logically complete
* condition can either be directly built into a query or it can be composed with other conditions in
* the form of 'AND' or 'OR'
*/
protected final class ConditionDelegate extends Delegate implements Condition {
private ConditionDelegate(T canonical) {
super(canonical);
}
public final T and() {
QBuilder self = self();
LogicalNode current = self.current;
if(!(current instanceof AndNode)) {
List children = new ArrayList<>();
children.add(current);
AndNode node = new AndNode(current.getParent(), children);
// referential comparison intended.
if (current == self.root) {
self.root = node;
}
self.current = node;
}
return (T) self;
}
public final T or() {
QBuilder self = self();
LogicalNode current = self.current;
if(!(current instanceof OrNode)) {
List children = new ArrayList<>();
children.add(current);
OrNode node = new OrNode(current.getParent(), children);
// referential comparison intended.
if (current == self.root) {
self.root = node;
}
self.current = node;
}
return (T) self;
}
public final Q query(ContextualNodeVisitor visitor) {
QBuilder self = self();
return self.root.visit(visitor);
}
public final Q query(ContextualNodeVisitor visitor, S context) {
QBuilder self = self();
return self.root.visit(visitor, context);
}
public final LogicalNode getRootNode() {
return self().root;
}
}
}