package org.fdroid.fdroid.data;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
abstract class QueryBuilder {
private final List<String> fields = new ArrayList<>();
private final StringBuilder tables = new StringBuilder(getRequiredTables());
private String selection;
private String[] selectionArgs;
private final List<OrderClause> orderBys = new ArrayList<>();
protected abstract String getRequiredTables();
public abstract void addField(String field);
protected int fieldCount() {
return fields.size();
}
public void addFields(String[] fields) {
for (final String field : fields) {
addField(field);
}
}
protected boolean isDistinct() {
return false;
}
protected String groupBy() {
return null;
}
protected void appendField(String field) {
appendField(field, null, null);
}
protected void appendField(String field, String tableAlias) {
appendField(field, tableAlias, null);
}
protected final void appendField(String field, String tableAlias,
String fieldAlias) {
StringBuilder fieldBuilder = new StringBuilder();
if (tableAlias != null) {
fieldBuilder.append(tableAlias).append('.');
}
fieldBuilder.append(field);
if (fieldAlias != null) {
fieldBuilder.append(" AS ").append(fieldAlias);
}
fields.add(fieldBuilder.toString());
}
public void addSelection(@Nullable QuerySelection selection) {
if (selection == null) {
this.selection = null;
this.selectionArgs = null;
} else {
this.selection = selection.getSelection();
this.selectionArgs = selection.getArgs();
}
}
/**
* Add an order by, which includes an expression and optionally ASC or DESC afterward.
*/
public void addOrderBy(String orderBy) {
if (orderBy != null) {
orderBys.add(new OrderClause(orderBy));
}
}
public void addOrderBy(@Nullable OrderClause orderClause) {
if (orderClause != null) {
orderBys.add(orderClause);
}
}
public String[] getArgs() {
List<String> args = new ArrayList<>();
if (selectionArgs != null) {
Collections.addAll(args, selectionArgs);
}
for (OrderClause orderBy : orderBys) {
if (orderBy.getArgs() != null) {
Collections.addAll(args, orderBy.getArgs());
}
}
String[] strings = new String[args.size()];
args.toArray(strings);
return strings;
}
protected final void leftJoin(String table, String alias, String condition) {
joinWithType("LEFT", table, alias, condition);
}
protected final void join(String table, String alias, String condition) {
joinWithType("", table, alias, condition);
}
private void joinWithType(String type, String table, String alias, String condition) {
tables.append(' ')
.append(type)
.append(" JOIN ")
.append(table);
if (alias != null) {
tables.append(" AS ").append(alias);
}
tables.append(" ON (")
.append(condition)
.append(')');
}
private String distinctSql() {
return isDistinct() ? " DISTINCT " : "";
}
private String fieldsSql() {
return TextUtils.join(", ", fields);
}
private String whereSql() {
return selection != null ? " WHERE " + selection : "";
}
private String orderBySql() {
if (orderBys.size() == 0) {
return "";
}
return " ORDER BY " + TextUtils.join(", ", orderBys);
}
private String groupBySql() {
return groupBy() != null ? " GROUP BY " + groupBy() : "";
}
private String tablesSql() {
return tables.toString();
}
public String toString() {
return "SELECT " + distinctSql() + fieldsSql() + " FROM " + tablesSql() + whereSql() + groupBySql() + orderBySql();
}
}