package org.deephacks.confit.internal.hbase.query;
import org.apache.hadoop.hbase.util.Bytes;
import org.deephacks.confit.admin.query.BeanQuery;
import org.deephacks.confit.admin.query.BeanQueryBuilder.BeanRestriction;
import org.deephacks.confit.admin.query.BeanQueryBuilder.Between;
import org.deephacks.confit.admin.query.BeanQueryBuilder.Equals;
import org.deephacks.confit.admin.query.BeanQueryBuilder.GreaterThan;
import org.deephacks.confit.admin.query.BeanQueryBuilder.Has;
import org.deephacks.confit.admin.query.BeanQueryBuilder.In;
import org.deephacks.confit.admin.query.BeanQueryBuilder.LessThan;
import org.deephacks.confit.admin.query.BeanQueryBuilder.LogicalRestriction;
import org.deephacks.confit.admin.query.BeanQueryBuilder.Not;
import org.deephacks.confit.admin.query.BeanQueryBuilder.PropertyRestriction;
import org.deephacks.confit.admin.query.BeanQueryBuilder.StringContains;
import org.deephacks.confit.admin.query.BeanQueryResult;
import org.deephacks.confit.internal.hbase.HBeanRow;
import org.deephacks.confit.internal.hbase.HBeanTable;
import org.deephacks.confit.internal.hbase.UniqueIds;
import org.deephacks.confit.internal.hbase.MultiKeyValueComparisonFilter;
import org.deephacks.confit.internal.hbase.query.RestrictionBuilder.HBaseBetween;
import org.deephacks.confit.internal.hbase.query.RestrictionBuilder.HBaseEquals;
import org.deephacks.confit.internal.hbase.query.RestrictionBuilder.HBaseGreaterThan;
import org.deephacks.confit.internal.hbase.query.RestrictionBuilder.HBaseLessThan;
import org.deephacks.confit.internal.hbase.query.RestrictionBuilder.HBaseStringContains;
import org.deephacks.confit.model.Bean;
import org.deephacks.confit.model.Schema;
import java.util.ArrayList;
import java.util.List;
import static org.deephacks.confit.admin.query.BeanQueryBuilder.equal;
public class HBaseBeanQuery implements BeanQuery {
private final HBeanTable table;
private final MultiKeyValueComparisonFilter filter;
private final UniqueIds uids;
private final byte[] sid;
private String firstResult;
private int maxResults = Integer.MAX_VALUE;
public HBaseBeanQuery(Schema schema, HBeanTable table, UniqueIds uids) {
this.uids = uids;
this.table = table;
this.sid = table.extractSidPrefix(schema.getName());
filter = new MultiKeyValueComparisonFilter(sid);
}
@Override
public BeanQuery add(BeanRestriction restriction) {
if(restriction instanceof PropertyRestriction) {
PropertyRestriction propertyRestriction = ((PropertyRestriction) restriction);
String property = propertyRestriction.getProperty();
int id = Bytes.toShort(uids.getUpid().getId(property));
if (restriction instanceof Equals) {
Equals specific = (Equals) restriction;
HBaseEquals hbaseRestriction = new HBaseEquals(id, specific.getValue());
if(propertyRestriction.isNot()) {
hbaseRestriction.setNot();
}
filter.add(hbaseRestriction);
return this;
} else if (restriction instanceof StringContains) {
StringContains specific = (StringContains) restriction;
HBaseStringContains hbaseRestriction = new HBaseStringContains(id, specific.getValue());
if(propertyRestriction.isNot()) {
hbaseRestriction.setNot();
}
filter.add(hbaseRestriction);
return this;
} else if (restriction instanceof Between) {
Between specific = (Between) restriction;
HBaseBetween hbaseRestriction = new HBaseBetween(id, specific.getLower(), specific.getUpper());
filter.add(hbaseRestriction);
return this;
} else if (restriction instanceof GreaterThan) {
GreaterThan specific = (GreaterThan) restriction;
HBaseGreaterThan hbaseRestriction = new HBaseGreaterThan(id, specific.getValue());
filter.add(hbaseRestriction);
return this;
} else if (restriction instanceof LessThan) {
LessThan specific = (LessThan) restriction;
HBaseLessThan hbaseRestriction = new HBaseLessThan(id, specific.getValue());
filter.add(hbaseRestriction);
return this;
} else if (restriction instanceof Has) {
throw new UnsupportedOperationException("'Has' not implemented yet");
} else if (restriction instanceof In) {
In in = ((In) restriction);
List<Object> values = in.getValues();
for (Object value : values) {
PropertyRestriction equal = (PropertyRestriction) equal(property, value);
if(in.isNot()) {
equal.setNot();
}
add(equal);
}
return this;
} else {
throw new IllegalArgumentException("Could not identify restriction: " + restriction);
}
} else if(restriction instanceof LogicalRestriction) {
if (restriction instanceof Not) {
// support only one logical NOT statement at the moment
PropertyRestriction not = (PropertyRestriction) ((Not) restriction).getRestrictions().get(0);
not.setNot();
add(not);
return this;
}
throw new UnsupportedOperationException("logical restriction not supported " + restriction);
}
throw new UnsupportedOperationException("Could not identify restriction: " + restriction);
}
@Override
public BeanQuery setFirstResult(String firstResult) {
this.firstResult = firstResult;
return this;
}
@Override
public BeanQuery setMaxResults(int maxResults) {
filter.setMaxResults(maxResults);
this.maxResults = maxResults;
return this;
}
@Override
public BeanQueryResult retrieve() {
final List<Bean> beans = new ArrayList<>();
final List<HBeanRow> rows = table.scan(sid, filter, firstResult);
int i = 0;
String firstResult = null;
for (HBeanRow row : rows) {
if (i++ < maxResults) {
beans.add(row.getBean());
} else {
firstResult = row.getBean().getId().getInstanceId();
break;
}
}
final String nextFirstResult = firstResult;
return new BeanQueryResult() {
@Override
public List<Bean> get() {
return beans;
}
@Override
public String nextFirstResult() {
return nextFirstResult;
}
};
}
}