/*
* (C) Copyright 2007-2011 Nuxeo SA (http://nuxeo.com/) and others.
*
* 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.
*
* Contributors:
* Julien Anguenot
* Florent Guillaume
*/
package org.nuxeo.ecm.core.search.api.client.search.results.impl;
import java.util.ArrayList;
import java.util.List;
import org.nuxeo.ecm.core.api.CoreSession;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.api.DocumentModelList;
import org.nuxeo.ecm.core.api.DocumentSecurityException;
import org.nuxeo.ecm.core.query.QueryParseException;
import org.nuxeo.ecm.core.query.sql.model.SQLQuery;
import org.nuxeo.ecm.core.search.api.client.SearchException;
import org.nuxeo.ecm.core.search.api.client.search.results.ResultItem;
import org.nuxeo.ecm.core.search.api.client.search.results.ResultSet;
import org.nuxeo.runtime.api.Framework;
/**
* Result set implementation.
*/
public class ResultSetImpl extends ArrayList<ResultItem> implements ResultSet {
private static final long serialVersionUID = -6376330426798015144L;
protected final int offset;
/** 0 means all results */
protected final int range;
protected final int totalHits;
protected final int pageHits;
protected final String query;
protected final SQLQuery sqlQuery;
protected final CoreSession session;
protected Boolean detachResultsFlag;
/**
* Constructor used when a CoreSession is available.
*/
public ResultSetImpl(String query, CoreSession session, int offset, int range, List<ResultItem> resultItems,
int totalHits, int pageHits) {
this.query = query;
sqlQuery = null;
this.session = session;
this.offset = offset;
this.range = range;
this.totalHits = totalHits;
this.pageHits = pageHits;
if (resultItems != null) {
addAll(resultItems);
}
}
public boolean detachResults() {
if (detachResultsFlag == null) {
detachResultsFlag = Framework.isBooleanPropertyTrue(ALWAYS_DETACH_SEARCH_RESULTS_KEY);
}
return detachResultsFlag.booleanValue();
}
@Override
public int getOffset() {
return offset;
}
@Override
public int getRange() {
return range;
}
@Override
public ResultSet nextPage() throws SearchException {
if (!hasNextPage()) {
return null;
}
return replay(offset + range, range);
}
@Override
public ResultSet goToPage(int page) throws SearchException {
int newOffset = range * (page - 1);
if (newOffset >= 0 && newOffset < totalHits) {
return replay(newOffset, range);
}
return null;
}
@Override
public int getTotalHits() {
return totalHits;
}
@Override
public int getPageHits() {
return pageHits;
}
@Override
public boolean hasNextPage() {
if (range == 0) {
return false;
}
if (pageHits < range) {
return false;
}
return (offset + range) < totalHits;
}
@Override
public boolean isFirstPage() {
return range == 0 ? true : offset < range;
}
@Override
public ResultSet replay() throws SearchException {
return replay(offset, range);
}
@Override
public ResultSet replay(int offset, int range) throws SearchException {
if (session != null) {
try {
DocumentModelList list = session.query(query, null, range, offset, true);
List<ResultItem> resultItems = new ArrayList<ResultItem>(list.size());
for (DocumentModel doc : list) {
if (doc == null) {
continue;
}
if (detachResults()) {
// detach the document so that we can use it beyond the
// session
try {
doc.detach(true);
} catch (DocumentSecurityException e) {
// no access to the document (why?)
continue;
}
}
resultItems.add(new DocumentModelResultItem(doc));
}
return new ResultSetImpl(query, session, offset, range, resultItems, (int) list.totalSize(),
list.size());
} catch (QueryParseException e) {
throw new SearchException("QueryException for: " + query, e);
}
}
throw new SearchException("No session");
}
@Override
public int getPageNumber() {
if (range == 0) {
return 1;
}
return (offset + range) / range;
}
}