package jpasearch.repository.query.selector;
import jpasearch.repository.query.Path;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
/**
* Range support for {@link Comparable} types.
*/
@SuppressWarnings("rawtypes")
public class Range<E, D extends Comparable> implements SingleSelector<E, D, Range<E, D>> {
private static final long serialVersionUID = 201312031754L;
private final Path<E, D> path;
private D lowerBound;
private boolean includeLowerBound = true;
private D higherBound;
private boolean includeHigherBound = true;
private Boolean includeNull;
/**
* Constructs a new {@link Range} with no boundaries and no restrictions on
* field's nullability.
*
* @param path
* the path to the attribute of an existing entity.
*/
public Range(Path<E, D> path) {
this.path = path;
}
/**
* Constructs a new Range.
*
* @param lowerBound
* the lower boundary of this range. Null means no lower
* boundary.
* @param higherBound
* the upper boundary of this range. Null means no upper
* boundary.
* @param path
* the path to the attribute of an existing entity.
*/
public Range(D lowerBound, D higherBound, Path<E, D> path) {
this(path);
this.lowerBound = lowerBound;
this.higherBound = higherBound;
}
/**
* Constructs a new Range.
*
* @param lowerBound
* the lower boundary of this range. Null means no lower
* boundary.
* @param higherBound
* the upper boundary of this range. Null means no upper
* boundary.
* @param includeNull
* tells whether null should be filtered out or not.
* @param path
* the path to the attribute of an existing entity.
*/
public Range(D lowerBound, D higherBound, Boolean includeNull, Path<E, D> path) {
this(lowerBound, higherBound, path);
this.includeNull = includeNull;
}
private Range(Range<E, D> other) {
this.path = other.path;
this.lowerBound = other.lowerBound;
this.higherBound = other.higherBound;
this.includeNull = other.includeNull;
}
@Override
public Range<E, D> copy() {
return new Range<E, D>(this);
}
public String getPath() {
return path.getPath();
}
/**
* @return the lower range boundary or null for unbound lower range.
*/
public D getLowerBound() {
return lowerBound;
}
/**
* Sets the lower range boundary. Accepts null for unbound lower range.
*/
public void setLowerBound(D lowerBound) {
this.lowerBound = lowerBound;
}
public Range<E, D> lowerBound(D lowerBound) {
setLowerBound(lowerBound);
return this;
}
public boolean isLowerBoundSet() {
return getLowerBound() != null;
}
/**
* @return the upper range boundary or null for unbound upper range.
*/
public D getHigherBound() {
return higherBound;
}
public Range<E, D> higherBound(D higherBound) {
setHigherBound(higherBound);
return this;
}
/**
* Sets the upper range boundary. Accepts null for unbound upper range.
*/
public void setHigherBound(D higherBound) {
this.higherBound = higherBound;
}
public boolean isHigherBoundSet() {
return getHigherBound() != null;
}
public void setIncludeNull(Boolean includeNull) {
this.includeNull = includeNull;
}
public Range<E, D> includeNull(Boolean includeNull) {
setIncludeNull(includeNull);
return this;
}
public Boolean getIncludeNull() {
return includeNull;
}
public boolean isIncludeNullSet() {
return includeNull != null;
}
public boolean isBetween() {
return isLowerBoundSet() && isHigherBoundSet();
}
public boolean isSet() {
return isLowerBoundSet() || isHigherBoundSet() || isIncludeNullSet();
}
@SuppressWarnings("unchecked")
public boolean isValid() {
if (isBetween()) {
return getLowerBound().compareTo(getHigherBound()) <= 0;
}
return true;
}
public void resetRange() {
lowerBound = null;
higherBound = null;
includeNull = null;
includeLowerBound = true;
includeHigherBound = true;
}
/**
* @return whether lowerBound bound should included or not. Default is true.
*/
public boolean isIncludeLowerBound() {
return includeLowerBound;
}
public void setIncludeLowerBound(boolean includeLowerBound) {
this.includeLowerBound = includeLowerBound;
}
public Range<E, D> includeLowerBound(boolean includeLowerBound) {
setIncludeLowerBound(includeLowerBound);
return this;
}
/**
* @return whether higherBound bound should included or not. Default is
* true.
*/
public boolean isIncludeHigherBound() {
return includeHigherBound;
}
public void setIncludeHigherBound(boolean includeHigherBound) {
this.includeHigherBound = includeHigherBound;
}
public Range<E, D> includeHigherBound(boolean includeHigherBound) {
setIncludeHigherBound(includeHigherBound);
return this;
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
}