com.datastax.oss.driver.api.mapper.result.MapperResultProducer Maven / Gradle / Ivy
/*
* Copyright DataStax, Inc.
*
* 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.datastax.oss.driver.api.mapper.result;
import com.datastax.oss.driver.api.core.cql.Statement;
import com.datastax.oss.driver.api.core.data.GettableByName;
import com.datastax.oss.driver.api.core.type.reflect.GenericType;
import com.datastax.oss.driver.api.mapper.MapperContext;
import com.datastax.oss.driver.api.mapper.entity.EntityHelper;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.util.concurrent.CompletionStage;
/**
* A component that can be plugged into the object mapper, in order to return custom result types
* from DAO methods.
*
* For example, this could be used to substitute a 3rd-party future implementation for {@link
* CompletionStage}:
*
*
* public class CustomFutureProducer implements MapperResultProducer {
* ...
* }
*
*
* Producers are registered via the Java Service Provider mechanism (see {@link
* MapperResultProducerService}). DAO methods can then use the new type:
*
*
* @Dao
* public interface ProductDao {
* @Select
* CustomFuture<Product> findById(UUID productId);
* }
*
*
* See the javadocs of the methods in this interface for more explanations.
*/
public interface MapperResultProducer {
/**
* Checks if this producer can handle a particular result type.
*
* This will be invoked at runtime to select a producer: if a DAO method declares a return type
* that is not supported natively, then the mapper generates an implementation which, for every
* invocation, iterates through all the producers in the order that they were registered,
* and picks the first one where {@code canProduce()} returns true.
*
* @param resultType the DAO method's declared return type. If checking the top-level type is
* sufficient, then {@link GenericType#getRawType()} should do the trick. If you need to
* recurse into the type arguments, call {@link GenericType#getType()} and use the {@code
* java.lang.reflect} APIs.
*/
boolean canProduce(@NonNull GenericType> resultType);
/**
* Executes the statement generated by the mapper, and converts the result to the expected type.
*
*
This will be executed at runtime, every time the DAO method is called.
*
* @param statement the statement, ready to execute: the mapper has already bound all the values,
* and set all the necessary attributes (consistency, page size, etc).
* @param context the context in which the DAO method is executed. In particular, this is how you
* get access to the {@linkplain MapperContext#getSession() session}.
* @param entityHelper if the type to produce contains a mapped entity (e.g. {@code
* ListenableFuture}), an instance of the helper class to manipulate that entity. In
* particular, {@link EntityHelper#get(GettableByName) entityHelper.get()} allows you to
* convert rows into entity instances. If the type to produce does not contain an entity, this
* will be {@code null}.
* @return the object to return from the DAO method. This must match the type that this producer
* was selected for, there will be an unchecked cast at runtime.
*/
@Nullable
Object execute(
@NonNull Statement> statement,
@NonNull MapperContext context,
@Nullable EntityHelper> entityHelper);
/**
* Surfaces any error encountered in the DAO method (either in the generated mapper code that
* builds the statement, or during invocation of {@link #execute}).
*
* For some result types, it is expected that errors will be wrapped in some sort of container
* instead of thrown directly; for example a failed future or publisher.
*
*
If rethrowing is the right thing to do, then it is perfectly fine to do so from this method.
* If you throw checked exceptions, they will be propagated directly if the DAO method also
* declares them, or wrapped into a {@link RuntimeException} otherwise.
*/
@Nullable
Object wrapError(@NonNull Exception e) throws Exception;
}