/*
* Copyright 2012 Harlan Noonkester
*
* 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 com.couchace.core.internal;
import com.couchace.core.api.*;
import com.couchace.core.api.meta.CouchMetaRepository;
import com.couchace.core.api.meta.EntityMeta;
import com.couchace.core.api.http.CouchMediaType;
import com.couchace.core.api.request.GetDocumentRequest;
import com.couchace.core.api.response.*;
import com.couchace.core.spi.http.CouchHttpResponse;
import com.couchace.core.api.http.CouchStatusCode;
import com.couchace.core.api.query.CouchPageNavigation;
import com.couchace.core.api.query.CouchPageQuery;
import com.couchace.core.api.query.CouchViewQuery;
import com.couchace.core.api.request.GetEntityRequest;
import com.couchace.core.spi.http.CouchHttpClient;
import com.couchace.core.spi.json.CouchJsonStrategy;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.net.URI;
import java.util.Collections;
import java.util.List;
public class GetResponseBuilder {
private static Log log = LogFactory.getLog(GetResponseBuilder.class);
private final CouchDatabase couch;
private final CouchHttpClient httpClient;
private final CouchJsonStrategy jsonStrategy;
private final CouchMetaRepository metaRepository;
public GetResponseBuilder(CouchDatabase couch) {
this.couch = couch;
this.httpClient = couch.getHttpClient();
this.jsonStrategy = couch.getJsonStrategy();
this.metaRepository = couch.getMetaRepository();
}
public <T> GetEntityResponse<T> buildEntityResponse(GetEntityRequest<T> request, CouchHttpResponse couchHttpResponse) {
CouchMediaType contentType = CouchMediaType.APPLICATION_JSON;
EntityMeta<T> entityMeta = metaRepository.getOrCreateEntityMeta(request.getEntityClass());
GetEntityResponse<T> entityResponse;
if (couchHttpResponse.isSuccess()) {
if (request.getDocumentId() != null) {
EntityDocument<T> entityDocument = jsonStrategy.readEntityDocument(
couch.get(),
entityMeta,
couchHttpResponse.getStringContent());
entityResponse = GetEntityResponse.withEntity(couchHttpResponse.getStatusCode(),
contentType,
entityMeta.getEntityClass(),
entityDocument);
} else {
// Parse entity documents
List<EntityDocument<T>> entityDocuments = jsonStrategy.readEntityDocuments(
couch.get(),
entityMeta,
couchHttpResponse.getStringContent());
CouchPageNavigation couchPageNavigation;
if (request.getViewQuery() != null) {
couchPageNavigation = buildPageNavigationForViewQuery(couchHttpResponse.getUri(), entityDocuments, request.getViewQuery());
} else if (request.getPageQuery() != null) {
couchPageNavigation = buildPageNavigationForPageQuery(couchHttpResponse.getUri(), entityDocuments, request.getPageQuery());
} else {
throw new CouchException(CouchStatusCode.BAD_REQUEST, "Get request did not supply document id, view query or page query.");
}
// Return our response.
entityResponse = GetEntityResponse.withEntities(couchHttpResponse.getStatusCode(),
contentType,
entityMeta.getEntityClass(),
couchPageNavigation,
entityDocuments);
}
} else {
CouchErrorContent errorContent = CouchErrorContent.parseJson(couchHttpResponse.getStringContent());
entityResponse = GetEntityResponse.withError(couchHttpResponse.getStatusCode(),
contentType,
entityMeta.getEntityClass(),
errorContent);
}
return entityResponse;
}
public GetDocumentResponse buildDocumentResponse(GetDocumentRequest request, CouchHttpResponse couchHttpResponse) {
GetDocumentResponse docResponse;
if (couchHttpResponse.isSuccess()) {
if (request.getDocumentId() != null &&
(request.getDocumentId().equals("_all_docs") ||
request.getDocumentId().startsWith("/_all_docs?"))) {
List<TextDocument> documentList = jsonStrategy.readTextDocuments(couchHttpResponse.getStringContent());
docResponse = GetDocumentResponse.withDocuments(couchHttpResponse.getStatusCode(),
couchHttpResponse.getContentType(),
CouchPageNavigation.empty(),
documentList);
} else if (request.getDocumentId() != null) {
TextDocument textDocument = jsonStrategy.readTextDocument(couchHttpResponse.getStringContent());
docResponse = GetDocumentResponse.withDocument(couchHttpResponse.getStatusCode(),
couchHttpResponse.getContentType(),
textDocument);
} else if (request.getDocumentId() != null &&
(request.getDocumentId().equals("_all_docs") ||
request.getDocumentId().startsWith("/_all_docs?"))) {
List<TextDocument> documentList = jsonStrategy.readTextDocuments(couchHttpResponse.getStringContent());
docResponse = GetDocumentResponse.withDocuments(couchHttpResponse.getStatusCode(),
couchHttpResponse.getContentType(),
CouchPageNavigation.empty(),
documentList);
} else {
List<TextDocument> documentList = jsonStrategy.readTextDocuments(couchHttpResponse.getStringContent());
CouchPageNavigation couchPageNavigation;
if (request.getViewQuery() != null) {
couchPageNavigation = buildPageNavigationForViewQuery(couchHttpResponse.getUri(), documentList, request.getViewQuery());
} else if (request.getPageQuery() != null) {
couchPageNavigation = buildPageNavigationForPageQuery(couchHttpResponse.getUri(), documentList, request.getPageQuery());
} else {
throw new CouchException(CouchStatusCode.BAD_REQUEST, "Get request did not supply document id, view query or page query.");
}
docResponse = GetDocumentResponse.withDocuments(couchHttpResponse.getStatusCode(),
couchHttpResponse.getContentType(),
couchPageNavigation,
documentList);
}
} else {
CouchErrorContent errorContent = CouchErrorContent.parseJson(couchHttpResponse.getStringContent());
docResponse = GetDocumentResponse.withError(couchHttpResponse.getStatusCode(),
CouchMediaType.APPLICATION_JSON,
errorContent);
}
return docResponse;
}
protected CouchPageNavigation buildPageNavigationForPageQuery(URI requestedPageUri, List<? extends CouchDocument> documentList, CouchPageQuery pageQuery) {
// Paging
String backPageUri = null;
if (!documentList.isEmpty()) {
CouchDocument pageBeginEntity = documentList.get(0);
backPageUri = httpClient.pageUri(requestedPageUri, pageBeginEntity, pageQuery.isForward()).toString();
}
String forwardPageUri = null;
if (documentList.size() > pageQuery.getPageSize()) {
// We found one more that requested so remove last and create pageEndUri.
documentList.remove(pageQuery.getPageSize());
CouchDocument pageEndEntity = documentList.get(documentList.size() - 1);
forwardPageUri = httpClient.pageUri(requestedPageUri, pageEndEntity, pageQuery.isReverse()).toString();
}
CouchPageNavigation pageNavigation;
if (pageQuery.isReverse()) {
Collections.reverse(documentList);
pageNavigation = new CouchPageNavigation(pageQuery.getPageSize(), pageQuery.getRequestedPage(), forwardPageUri, backPageUri, pageQuery.isIncludeDocs());
} else {
pageNavigation = new CouchPageNavigation(pageQuery.getPageSize(), pageQuery.getRequestedPage(), backPageUri, forwardPageUri, pageQuery.isIncludeDocs());
}
return pageNavigation;
}
protected CouchPageNavigation buildPageNavigationForViewQuery(URI requestedPageUri, List<? extends CouchDocument> documentList, CouchViewQuery viewQuery) {
String nextPage = null;
if (viewQuery.getLimit() > 0 && documentList.size() > viewQuery.getLimit()) {
// We found one more that requested so we have a next page.
documentList.remove(viewQuery.getLimit());
CouchDocument pageEndEntityDoc = documentList.get(documentList.size() - 1);
nextPage = httpClient.pageUri(requestedPageUri, pageEndEntityDoc, false).toString();
}
// With viewQuery it's always the first page so will never have previous, always have requested and may have next.
String requestedPage = requestedPageUri.toString();
int designIndex = requestedPage.indexOf("_design");
if (designIndex > 0) {
requestedPage = requestedPage.substring(designIndex);
}
return new CouchPageNavigation(viewQuery.getLimit(), requestedPage, null, nextPage, viewQuery.isIncludeDocs());
}
}