/**
* Copyright (C) 2010 Michael Mosmann <michael@mosmann.de>
*
* 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.
*/
package de.flapdoodle.mongoom.datastore.query;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import de.flapdoodle.mongoom.IQueryResult;
import de.flapdoodle.mongoom.datastore.factories.DBObjectFactory;
import de.flapdoodle.mongoom.datastore.iterator.TypedIterator;
import de.flapdoodle.mongoom.exceptions.MappingException;
import de.flapdoodle.mongoom.logging.LogConfig;
import de.flapdoodle.mongoom.mapping.IEntityTransformation;
import de.flapdoodle.mongoom.mapping.ITransformation;
import de.flapdoodle.mongoom.mapping.naming.PropertyName;
public class QueryResult<T> implements IQueryResult<T> {
private static final Logger _logger = LogConfig.getLogger(QueryResult.class);
private int _limit = -1;
private int _skip = -1;
private final DBCollection _dbCollection;
private final ITransformation<T,DBObject> _converter;
private final DBObject _query;
private final DBObject _view;
private final IEntityTransformation<?> _entityConverter;
private final Map<String, Integer> _sort = Maps.newLinkedHashMap();
public QueryResult(IEntityTransformation<?> entityConverter, ITransformation<T,DBObject> converter, DBCollection dbCollection,
DBObject query, DBObject view) {
_entityConverter = entityConverter;
_converter = converter != null
? converter
: (ITransformation<T,DBObject>) entityConverter;
_dbCollection = dbCollection;
_query = query;
_view = view;
}
@Override
public List<T> asList() {
DBCursor find = getCursor();
if (_limit > 0)
find.limit(_limit);
if (_skip > 0)
find.skip(_skip);
return asList(find);
}
@Override
public T get() {
// List<T> list = asList(_dbCollection.find(query).limit(1));
// return list.isEmpty() ? null : list.get(0);
DBObject one = _view != null
? _dbCollection.findOne(_query, _view)
: _dbCollection.findOne(_query);
return one != null
? _converter.asEntity(one)
: null;
}
@Override
public IQueryResult<T> limit(int limit) {
_limit = limit;
return this;
}
@Override
public IQueryResult<T> skip(int skip) {
_skip = skip;
return this;
}
@Override
public long countAll() {
return getCursor().count();
}
private DBCursor getCursor() {
_logger.severe("Query: " + _query + ", View: " + _view);
DBCursor ret = _view != null
? _dbCollection.find(_query, _view)
: _dbCollection.find(_query);
if (!_sort.isEmpty()) {
DBObjectFactory sort = DBObjectFactory.start();
for (String name : _sort.keySet()) {
sort.set(name, _sort.get(name));
}
DBObject sortBy = sort.get();
_logger.severe("Sort: " + sortBy);
ret.sort(sortBy);
}
return ret;
}
@Override
public Iterator<T> iterator() {
DBCursor find = getCursor();
if (_limit > 0)
find.limit(_limit);
if (_skip > 0)
find.skip(_skip);
return new TypedIterator<T>(this, _converter, find);
}
@Override
public IQueryResult<T> order(String field, boolean asc) {
PropertyName propertyName = _entityConverter.propertyName(field);
if (propertyName==null)
throw new MappingException("Field " + field + " not mapped");
_sort.put(propertyName.getMapped(), asc
? 1
: -1);
return this;
}
private List<T> asList(DBCursor cursor) {
return Lists.transform(Lists.newArrayList(cursor.iterator()), new DBObjectToEntityTransformator());
}
private final class DBObjectToEntityTransformator implements Function<DBObject, T> {
@Override
public T apply(DBObject dbobject) {
return _converter.asEntity(dbobject);
}
}
}