/*
* Copyright 2014-2015 Marius Volkhart
*
* 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.
*
* Original at https://gist.github.com/MariusVolkhart/3e2374b5fdbefad17d56
*/
package com.truckmuncher.app.data.sql;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Representation of a constructed SQL query where clause
*/
public final class WhereClause {
public final String selection;
public final String[] selectionArgs;
private WhereClause(String selection, String[] selectionArgs) {
this.selection = selection;
this.selectionArgs = selectionArgs;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
WhereClause that = (WhereClause) o;
return !(selection != null ? !selection.equals(that.selection) : that.selection != null)
&& Arrays.equals(selectionArgs, that.selectionArgs);
}
@Override
public int hashCode() {
int result = selection != null ? selection.hashCode() : 0;
result = 31 * result + (selectionArgs != null ? Arrays.hashCode(selectionArgs) : 0);
return result;
}
@Override
public String toString() {
return WhereClause.class.getSimpleName() + "{" +
"selection='" + selection + '\'' +
", selectionArgs=" + Arrays.toString(selectionArgs) +
'}';
}
/**
* Common SQL operators. For convenience, consider implementing this interface if creating a
* lot of queries.
*/
public interface Operator {
public String EQUALS = "=";
public String NOT_EQUALS = "!=";
public String GREATER_THAN = ">";
public String LESS_THAN = "<";
public String GREATER_THAN_EQUALS = ">=";
public String LESS_THAN_EQUALS = "<=";
public String LIKE = " LIKE ";
public String IS = " IS ";
public String IS_NOT = " IS NOT ";
}
public static class Builder {
private static final String AND = " AND ";
private static final String OR = " OR ";
private final StringBuilder stringBuilder = new StringBuilder();
private final List<String> args = new ArrayList<>();
private String nextOperator;
public Builder where(String column, String operand, String arg) {
setNextOperatorIfNeeded();
stringBuilder.append(column).append(operand).append('?');
args.add(arg);
nextOperator = null;
return this;
}
public Builder where(String column, String operand, boolean arg) {
return where(column, operand, arg ? "1" : "0");
}
public Builder where(String column, String operand, int arg) {
return where(column, operand, Integer.toString(arg));
}
public Builder where(String column, String operand, long arg) {
return where(column, operand, Long.toString(arg));
}
public Builder where(String column, String operand, float arg) {
return where(column, operand, Float.toString(arg));
}
public Builder where(String column, String operand, double arg) {
return where(column, operand, Double.toString(arg));
}
public Builder where(WhereClause whereClause) {
if (whereClause.selectionArgs.length > 0) {
setNextOperatorIfNeeded();
stringBuilder.append('(').append(whereClause.selection).append(')');
args.addAll(Arrays.asList(whereClause.selectionArgs));
}
nextOperator = null;
return this;
}
/**
* Joins two statements with an {@code AND} operator. This is also the implicit behavior.
*/
public Builder and() {
nextOperator = AND;
return this;
}
public Builder or() {
nextOperator = OR;
return this;
}
/**
* Ensures that multiple {@code where} statements can be joined safely. Defaults to using
* {@code AND}.
*/
private void setNextOperatorIfNeeded() {
if (stringBuilder.length() == 0) {
return;
}
if (nextOperator == null) {
stringBuilder.append(AND);
} else {
stringBuilder.append(nextOperator);
nextOperator = null;
}
}
public WhereClause build() {
String[] arguments = args.toArray(new String[args.size()]);
return new WhereClause(stringBuilder.toString(), arguments);
}
}
}