package siena;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import siena.core.async.QueryAsync;
import siena.core.options.QueryOption;
import siena.embed.JsonSerializer;
/**
* The base implementation of Query<T> where T is the model being queried (not necessarily inheriting siena.Model)
*
* @author mandubian <pascal.voitot@mandubian.org>
*
* @param <T>
*/
public class BaseQuery<T> extends BaseQueryData<T> implements Query<T> {
private static final long serialVersionUID = 3533080111146350262L;
transient protected PersistenceManager pm;
@Deprecated
transient protected Object nextOffset;
public BaseQuery() {
}
public BaseQuery(PersistenceManager pm, Class<T> clazz) {
super(clazz);
this.pm = pm;
}
public BaseQuery(BaseQuery<T> query) {
super(query);
this.pm = query.pm;
//this.nextOffset = query.nextOffset;
}
public BaseQuery(PersistenceManager pm, BaseQueryData<T> data) {
super(data);
this.pm = pm;
}
public PersistenceManager getPersistenceManager(){
return pm;
}
public Query<T> filter(String fieldName, Object value) {
addFilter(fieldName, value, pm.supportedOperators());
return this;
}
public Query<T> order(String fieldName) {
addOrder(fieldName);
return this;
}
public Query<T> search(String match, String... fields) {
addSearch(match, fields);
return this;
}
public Query<T> search(String match, QueryOption opt, String... fields) {
addSearch(match, opt, fields);
return this;
}
@Deprecated
public Query<T> search(String match, boolean inBooleanMode, String index) {
//TODO implements default function for backward compat
//searches.add(new QuerySearch(match, inBooleanMode, index));
return this;
}
public Query<T> join(String fieldName, String... sortFields) {
addJoin(fieldName, sortFields);
return this;
}
public Query<T> aggregated(Object aggregator, String fieldName) {
addAggregated(aggregator, fieldName);
return this;
}
public Query<T> aggregated(Object aggregator, Field field) {
addAggregated(aggregator, field);
return this;
}
public Query<T> owned(Object owner, String fieldName) {
addOwned(owner, fieldName);
return this;
}
public Query<T> owned(Object owner, Field field) {
addOwned(owner, field);
return this;
}
public T get() {
return pm.get(this);
}
public List<T> fetch() {
return pm.fetch(this);
}
public List<T> fetch(int limit) {
return pm.fetch(this, limit);
}
public List<T> fetch(int limit, Object offset) {
return pm.fetch(this, limit, offset);
}
public int count() {
return pm.count(this);
}
@Deprecated
public int count(int limit) {
return pm.count(this, limit);
}
@Deprecated
public int count(int limit, Object offset) {
return pm.count(this, limit, offset);
}
public int delete() {
return pm.delete(this);
}
public List<T> fetchKeys() {
return pm.fetchKeys(this);
}
public List<T> fetchKeys(int limit) {
return pm.fetchKeys(this, limit);
}
public List<T> fetchKeys(int limit, Object offset) {
return pm.fetchKeys(this, limit, offset);
}
public Iterable<T> iter() {
return pm.iter(this);
}
public Iterable<T> iter(int limit) {
return pm.iter(this, limit);
}
public Iterable<T> iter(int limit, Object offset) {
return pm.iter(this, limit, offset);
}
public Iterable<T> iterPerPage(int pageSize) {
return pm.iterPerPage(this, pageSize);
}
public Query<T> copy() {
// TODO code a real deep clone function
return new BaseQuery<T>(this);
}
public Class<T> getQueriedClass() {
return clazz;
}
@Deprecated
public Object nextOffset() {
return nextOffset;
}
@Deprecated
public void setNextOffset(Object nextOffset) {
this.nextOffset = nextOffset;
}
public Query<T> paginate(int pageSize) {
optionPaginate(pageSize);
pm.paginate(this);
return this;
}
@Override
public Query<T> limit(int limit) {
optionLimit(limit);
return this;
}
@Override
public Query<T> offset(Object offset) {
optionOffset((Integer)offset);
return this;
}
@Override
public Query<T> nextPage() {
pm.nextPage(this);
return this;
}
@Override
public Query<T> previousPage() {
pm.previousPage(this);
return this;
}
public Query<T> customize(QueryOption... options) {
addOptions(options);
return this;
}
public Query<T> stateful() {
optionStateful();
return this;
}
@Override
public Query<T> stateless() {
// when going to stateless mode, we reset the options to default values
resetOptions();
optionStateless();
return this;
}
public Query<T> release() {
//super.reset();
pm.release(this);
return this;
}
public Query<T> resetData() {
super.reset();
return this;
}
public int update(Map<String, ?> fieldValues) {
return pm.update(this, fieldValues);
}
public QueryAsync<T> async() {
return pm.async().createQuery(this);
}
public T getByKey(Object key) {
return pm.getByKey(clazz, key);
}
public String dump(QueryOption... options) {
// TODO manage Java object serialization
return JsonSerializer.serialize(this).toString();
}
public void dump(OutputStream os, QueryOption... options) {
// TODO manage Java object serialization
OutputStreamWriter st = new OutputStreamWriter(os);
try {
st.write(JsonSerializer.serialize(this).toString());
} catch (IOException e) {
throw new SienaException(e);
}
}
@SuppressWarnings("unchecked")
public Query<T> restore(String dump, QueryOption... options) {
// TODO manage Java object serialization
return (Query<T>)JsonSerializer.deserialize(BaseQuery.class, Json.loads(dump));
}
@SuppressWarnings("unchecked")
public Query<T> restore(InputStream is, QueryOption... options) {
// TODO manage Java object serialization
InputStreamReader st = new InputStreamReader(is);
StringBuilder sb = new StringBuilder();
char[] buffer = new char[1024];
try {
while( st.read(buffer) != -1){
sb.append(buffer);
}
} catch (IOException e) {
throw new SienaException(e);
}
return (Query<T>)JsonSerializer.deserialize(BaseQuery.class, Json.loads(sb.toString()));
}
}