Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2012-2015 the original author or authors
*
* 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 org.springframework.data.couchbase.repository.query;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import com.couchbase.client.core.lang.Tuple2;
import com.couchbase.client.java.document.json.JsonArray;
import com.couchbase.client.java.document.json.JsonObject;
import com.couchbase.client.java.document.json.JsonValue;
import com.couchbase.client.java.query.N1qlParams;
import com.couchbase.client.java.query.N1qlQuery;
import com.couchbase.client.java.query.Statement;
import com.couchbase.client.java.query.consistency.ScanConsistency;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.couchbase.core.CouchbaseOperations;
import org.springframework.data.couchbase.core.CouchbaseQueryExecutionException;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.SliceImpl;
import org.springframework.data.repository.query.ParameterAccessor;
import org.springframework.data.repository.query.ParametersParameterAccessor;
import org.springframework.data.repository.query.QueryMethod;
import org.springframework.data.repository.query.RepositoryQuery;
import org.springframework.data.util.StreamUtils;
import org.springframework.util.Assert;
/**
* Abstract base for all Couchbase {@link RepositoryQuery}. It is in charge of inspecting the parameters
* and choosing the correct {@link N1qlQuery} implementation to use.
*/
public abstract class AbstractN1qlBasedQuery implements RepositoryQuery {
private static final Logger LOG = LoggerFactory.getLogger(AbstractN1qlBasedQuery.class);
protected final CouchbaseQueryMethod queryMethod;
private final CouchbaseOperations couchbaseOperations;
protected AbstractN1qlBasedQuery(CouchbaseQueryMethod queryMethod, CouchbaseOperations couchbaseOperations) {
this.queryMethod = queryMethod;
this.couchbaseOperations = couchbaseOperations;
}
/**
* The statement for a count() query. This must aggregate using count with the alias {@link CountFragment#COUNT_ALIAS}.
* @see CountFragment
*/
protected abstract Statement getCount(ParameterAccessor accessor, Object[] runtimeParameters);
/**
* @return true if the {@link #getCount(ParameterAccessor, Object[]) count statement} should also be used when
* the return type of the QueryMethod is a primitive type.
*/
protected abstract boolean useGeneratedCountQuery();
protected abstract Statement getStatement(ParameterAccessor accessor, Object[] runtimeParameters);
protected abstract JsonValue getPlaceholderValues(ParameterAccessor accessor);
@Override
public Object execute(Object[] parameters) {
ParametersParameterAccessor accessor = new ParametersParameterAccessor(queryMethod.getParameters(), parameters);
Statement statement = getStatement(accessor, parameters);
JsonValue queryPlaceholderValues = getPlaceholderValues(accessor);
//prepare the final query
N1qlQuery query = buildQuery(statement, queryPlaceholderValues,
getCouchbaseOperations().getDefaultConsistency().n1qlConsistency());
//prepare a count query
Statement countStatement = getCount(accessor, parameters);
N1qlQuery countQuery = buildQuery(countStatement, queryPlaceholderValues,
getCouchbaseOperations().getDefaultConsistency().n1qlConsistency());
return executeDependingOnType(query, countQuery, queryMethod, accessor.getPageable(),
queryMethod.isPageQuery(), queryMethod.isSliceQuery(), queryMethod.isModifyingQuery());
}
protected static N1qlQuery buildQuery(Statement statement, JsonValue queryPlaceholderValues, ScanConsistency scanConsistency) {
N1qlParams n1qlParams = N1qlParams.build().consistency(scanConsistency);
N1qlQuery query;
if (queryPlaceholderValues instanceof JsonObject && !((JsonObject) queryPlaceholderValues).isEmpty()) {
query = N1qlQuery.parameterized(statement, (JsonObject) queryPlaceholderValues, n1qlParams);
} else if (queryPlaceholderValues instanceof JsonArray && !((JsonArray) queryPlaceholderValues).isEmpty()) {
query = N1qlQuery.parameterized(statement, (JsonArray) queryPlaceholderValues, n1qlParams);
} else {
query = N1qlQuery.simple(statement, n1qlParams);
}
return query;
}
protected Object executeDependingOnType(N1qlQuery query, N1qlQuery countQuery, QueryMethod queryMethod, Pageable pageable,
boolean isPage, boolean isSlice, boolean isModifying) {
if (isModifying) {
throw new UnsupportedOperationException("Modifying queries not yet supported");
}
if (isPage) {
return executePaged(query, countQuery, pageable);
} else if (isSlice) {
return executeSliced(query, countQuery, pageable);
} else if (queryMethod.isCollectionQuery()) {
return executeCollection(query);
} else if (queryMethod.isQueryForEntity()) {
return executeEntity(query);
} else if (queryMethod.isStreamQuery()){
return executeStream(query);
} else if (queryMethod.getReturnedObjectType().isPrimitive()
&& useGeneratedCountQuery()) {
//attempt to execute the created COUNT query
return executeSingleProjection(countQuery);
} else {
//attempt a single projection on a simple type
// (ie, a single row with a single k->v entry where v is the desired value)
return executeSingleProjection(query);
}
//more complex projections could be added in the future, like DTO direct mapping with a SELECT a,b,c FROM something
}
private void logIfNecessary(N1qlQuery query) {
if (LOG.isDebugEnabled()) {
LOG.debug("Executing N1QL query: " + query.n1ql());
}
}
protected List executeCollection(N1qlQuery query) {
logIfNecessary(query);
List result = couchbaseOperations.findByN1QL(query, queryMethod.getEntityInformation().getJavaType());
return result;
}
protected Object executeEntity(N1qlQuery query) {
logIfNecessary(query);
List result = executeCollection(query);
return result.isEmpty() ? null : result.get(0);
}
protected Object executeStream(N1qlQuery query) {
logIfNecessary(query);
return StreamUtils.createStreamFromIterator(executeCollection(query).iterator());
}
protected Object executePaged(N1qlQuery query, N1qlQuery countQuery, Pageable pageable) {
Assert.notNull(pageable);
long total = 0L;
logIfNecessary(countQuery);
List countResult = couchbaseOperations.findByN1QLProjection(countQuery, CountFragment.class);
if (countResult != null && !countResult.isEmpty()) {
total = countResult.get(0).count;
}
logIfNecessary(query);
List result = couchbaseOperations.findByN1QL(query, queryMethod.getEntityInformation().getJavaType());
return new PageImpl(result, pageable, total);
}
protected Object executeSliced(N1qlQuery query, N1qlQuery countQuery, Pageable pageable) {
Assert.notNull(pageable);
logIfNecessary(query);
List result = couchbaseOperations.findByN1QL(query, queryMethod.getEntityInformation().getJavaType());
int pageSize = pageable.getPageSize();
boolean hasNext = result.size() > pageSize;
return new SliceImpl(hasNext ? result.subList(0, pageSize) : result, pageable, hasNext);
}
protected Object executeSingleProjection(N1qlQuery query) {
logIfNecessary(query);
//the structure of the response from N1QL gives us a JSON object even when selecting a single aggregation
List