Skip to content

Commit

Permalink
Make mappers builder more convenient
Browse files Browse the repository at this point in the history
  • Loading branch information
ArtDu authored and akudiyar committed Mar 1, 2023
1 parent 84194cc commit ef61296
Show file tree
Hide file tree
Showing 3 changed files with 214 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package io.tarantool.driver.mappers.factories;

import io.tarantool.driver.api.CallResult;
import io.tarantool.driver.api.MultiValueCallResult;
import io.tarantool.driver.api.SingleValueCallResult;
import io.tarantool.driver.api.TarantoolResult;
import io.tarantool.driver.api.metadata.TarantoolSpaceMetadata;
import io.tarantool.driver.api.tuple.TarantoolTuple;
import io.tarantool.driver.api.tuple.TarantoolTupleResult;
import io.tarantool.driver.mappers.CallResultMapper;
import io.tarantool.driver.mappers.MessagePackMapper;
import io.tarantool.driver.mappers.MessagePackValueMapper;
Expand Down Expand Up @@ -197,20 +197,170 @@ public interface ResultMapperFactoryFactory {
*/
<T> ArrayValueToTarantoolResultMapperFactory<T> rowsMetadataStructureResultMapperFactory();

Builder createMapper();
/**
* Return builder to create mapper which may depend on input clientMapper
* For example, you can create maper that can obtain crud and box results from lua
* and read it into {@link TarantoolTupleResult} structure.
* <pre>
* <code>
* CallResultMapper callReturnMapper = factory.createMapper(valueMapper)
* .withSingleValueConverter( // obtain first value from lua multi-value response
* factory.createMapper(valueMapper)
* .withArrayValueToTarantoolTupleResultConverter() // box type response
* .withRowsMetadataToTarantoolTupleResultMapper() // crud type response
* .buildCallResultMapper()
* )
* .buildCallResultMapper();
* </code>
* </pre>
* This mapper wouldn't have metadata to take fields by their names.
*
* @param messagePackMapper input client mapper
* @return Builder to create mapper with specific converters inside
*/
Builder createMapper(MessagePackMapper messagePackMapper);

/**
* Return builder to create mapper which may depend on input clientMapper
* For example, you can create maper that can obtain crud and box results from lua
* and read it into {@link TarantoolTupleResult} structure.
* <pre>
* <code>
* CallResultMapper callReturnMapper = factory.createMapper(valueMapper)
* .withSingleValueConverter( // obtain first value from lua multi-value response
* factory.createMapper(valueMapper)
* .withArrayValueToTarantoolTupleResultConverter() // box type response
* .withRowsMetadataToTarantoolTupleResultMapper() // crud type response
* .buildCallResultMapper()
* )
* .buildCallResultMapper();
* </code>
* </pre>
*
* @param messagePackMapper input client mapper
* @param spaceMetadata metadata to get fields by names
* @return Builder to create mapper with specific converters inside
*/
Builder createMapper(MessagePackMapper messagePackMapper, TarantoolSpaceMetadata spaceMetadata);

interface Builder {

/**
* Add a converter for mapping stored Lua function call results to {@link SingleValueCallResult}
* <p>
* input: [x, y, ...], MessagePack array from a Lua function multi-return response
* <br>
* where <code>x, y</code> are some MessagePack values. <code>x</code> is interpreted as a stored Lua function
* result and <code>y</code> may be interpreted as a stored Lua function error if it is not empty and there are
* no more arguments after <code>y</code>.
* <br>
* mapper result: some Java type converted from the value of <code>x</code> according to the mapper, passed as a
* parameter to builder constructor for parsing the result contents.
* <p>
* Converter result and its inner contents depend on the parameters or the passed converters.
*
* @return builder with single value converter
*/
Builder withSingleValueConverter();

/**
* Add a converter for mapping stored Lua function call results to {@link SingleValueCallResult}
* <p>
* input: [x, y, ...], MessagePack array from a Lua function multi-return response
* <br>
* where <code>x, y</code> are some MessagePack values. <code>x</code> is interpreted as a stored Lua function
* result and <code>y</code> may be interpreted as a stored Lua function error if it is not empty and there are
* no more arguments after <code>y</code>.
* <br>
* mapper result: some Java type converted from the value of <code>x</code> according to the mapper, passed as a
* parameter to this one for parsing the result contents.
* <p>
* Converter result and its inner contents depend on the parameters or the passed converters.
*
* @param messagePackMapper to parse fields
* @return builder with single value converter
*/
Builder withSingleValueConverter(
MessagePackValueMapper messagePackMapper);

/**
* Add converter parses result from a list of tuples.
* Use this converter for handling containers with {@link TarantoolTuple} inside.
* The IProto method results by default contain lists of tuples.
* This converter can be used at the inner level by other mapper factories that are handling higher-level
* containers.
* <p>
* input: array of tuples with MessagePack values inside ([t1, t2, ...])
* <br>
* converter result: {@code TarantoolResult<TarantoolTuple>}
* <p>
* For example, it can be used to parse result from IPROTO_SELECT.
* fields result: some Java type converted from the value of <code>x</code> according to the mapper, passed as a
* parameter to builder constructor for parsing the result contents.
*
* @return builder with converter that parses list of arrays to {@code TarantoolResult<TarantoolTuple>}
*/
Builder withArrayValueToTarantoolTupleResultConverter();

/**
* Add converter parses result from a list of tuples.
* Use this converter for handling containers with {@link TarantoolTuple} inside.
* The IProto method results by default contain lists of tuples.
* This converter can be used at the inner level by other mapper factories that are handling higher-level
* containers.
* <p>
* input: array of tuples with MessagePack values inside ([t1, t2, ...])
* <br>
* converter result: {@code TarantoolResult<TarantoolTuple>}
* <p>
* For example, it can be used to parse result from IPROTO_SELECT
* fields result: some Java type converted from the value of <code>x</code> according to the mapper, passed as a
* parameter to this one for parsing the result contents.
*
* @param messagePackMapper to parse fields
* @return builder with converter that parses list of arrays to {@code TarantoolResult<TarantoolTuple>}
*/
Builder withArrayValueToTarantoolTupleResultConverter(
MessagePackMapper messagePackMapper, TarantoolSpaceMetadata spaceMetadata);
MessagePackMapper messagePackMapper);

/**
* Add converter parses result from a map with list of tuples and metadata.
* Use this converter for handling containers with {@link TarantoolTuple} inside.
* The crud method results by default contain map with list of tuples and metadata.
* This converter can be used at the inner level by other mapper factories that are handling higher-level
* containers.
* <p>
* input: map with metadata and array of tuples with MessagePack values inside ([t1, t2, ...])
* <br>
* fields result: some Java type converted from the value of <code>x</code> according to the mapper, passed as a
* parameter to builder constructor for parsing the result contents.
* <p>
*
* @return builder with converter that parses map to {@code TarantoolResult<TarantoolTuple>}
*/
Builder withRowsMetadataToTarantoolTupleResultConverter();

/**
* Add converter parses result from a map with list of tuples and metadata.
* Use this converter for handling containers with {@link TarantoolTuple} inside.
* The crud method results by default contain map with list of tuples and metadata.
* This converter can be used at the inner level by other mapper factories that are handling higher-level
* containers.
* <p>
* input: map with metadata and array of tuples with MessagePack values inside ([t1, t2, ...])
* <br>
* fields result: some Java type converted from the value of <code>x</code> according to the mapper, passed as a
* parameter to this one for parsing the result contents.
* <p>
*
* @param messagePackMapper to parse fields
* @return builder with converter that parses map to {@code TarantoolResult<TarantoolTuple>}
*/
Builder withRowsMetadataToTarantoolTupleResultConverter(
MessagePackMapper messagePackMapper);

MessagePackValueMapper buildMessagePackMapper(MessagePackValueMapper valueMapper);
CallResultMapper buildCallResultMapper();

CallResultMapper buildCallResultMapper(MessagePackValueMapper valueMapper);
Builder withRowsMetadataToTarantoolTupleResultMapper(
MessagePackMapper messagePackMapper, TarantoolSpaceMetadata spaceMetadata);
CallResultMapper buildCallResultMapper(MessagePackMapper valueMapper);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -127,16 +127,36 @@ private <V extends Value, T> ValueConverter<V, T> getConverter(
}

@Override
public Builder createMapper() {
return new Builder();
public Builder createMapper(MessagePackMapper messagePackMapper) {
return createMapper(messagePackMapper, null);
}

@Override
public Builder createMapper(MessagePackMapper messagePackMapper, TarantoolSpaceMetadata spaceMetadata) {
return new Builder(messagePackMapper, spaceMetadata);
}

private class Builder implements ResultMapperFactoryFactory.Builder {

private final List<ValueConverterWithInputTypeWrapper<Object>> mappers;
private final MessagePackMapper clientMapper;
private final TarantoolSpaceMetadata spaceMetadata;

Builder() {
Builder(MessagePackMapper messagePackMapper, TarantoolSpaceMetadata spaceMetadata) {
this.mappers = new ArrayList<>();
this.clientMapper = messagePackMapper;
this.spaceMetadata = spaceMetadata;
}

@Override
public ResultMapperFactoryFactory.Builder withSingleValueConverter() {
this.mappers.add(
singleValueResultMapperFactory()
.getSingleValueResultConverter(
clientMapper
)
);
return this;
}

public Builder withSingleValueConverter(
Expand All @@ -150,30 +170,52 @@ public Builder withSingleValueConverter(
return this;
}

@Override
public Builder withArrayValueToTarantoolTupleResultConverter(
MessagePackMapper messagePackMapper, TarantoolSpaceMetadata spaceMetadata) {
MessagePackMapper messagePackMapper) {
this.mappers.add(
arrayTupleResultMapperFactory()
.getArrayValueToTarantoolTupleResultConverter(messagePackMapper, spaceMetadata)
);
return this;
}

public Builder withRowsMetadataToTarantoolTupleResultMapper(
MessagePackMapper messagePackMapper, TarantoolSpaceMetadata spaceMetadata) {
@Override
public ResultMapperFactoryFactory.Builder withArrayValueToTarantoolTupleResultConverter() {
this.mappers.add(
arrayTupleResultMapperFactory()
.getArrayValueToTarantoolTupleResultConverter(clientMapper, spaceMetadata)
);
return this;
}

@Override
public Builder withRowsMetadataToTarantoolTupleResultConverter(
MessagePackMapper messagePackMapper) {
this.mappers.add(
rowsMetadataTupleResultMapperFactory()
.getRowsMetadataToTarantoolTupleResultConverter(messagePackMapper, spaceMetadata)
);
return this;
}

public MessagePackValueMapper buildMessagePackMapper(MessagePackValueMapper valueMapper) {
return new CallResultMapper(valueMapper, mappers);
@Override
public ResultMapperFactoryFactory.Builder withRowsMetadataToTarantoolTupleResultConverter() {
this.mappers.add(
rowsMetadataTupleResultMapperFactory()
.getRowsMetadataToTarantoolTupleResultConverter(clientMapper, spaceMetadata)
);
return this;
}

public CallResultMapper buildCallResultMapper(MessagePackValueMapper valueMapper) {
@Override
public CallResultMapper buildCallResultMapper(MessagePackMapper valueMapper) {
return new CallResultMapper(valueMapper, mappers);
}

@Override
public CallResultMapper buildCallResultMapper() {
return new CallResultMapper(clientMapper.copy(), mappers);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import io.tarantool.driver.api.tuple.DefaultTarantoolTupleFactory;
import io.tarantool.driver.api.tuple.TarantoolTuple;
import io.tarantool.driver.api.tuple.TarantoolTupleFactory;
import io.tarantool.driver.api.tuple.TarantoolTupleResult;
import io.tarantool.driver.api.tuple.operations.TupleOperations;
import io.tarantool.driver.auth.SimpleTarantoolCredentials;
import io.tarantool.driver.auth.TarantoolCredentials;
Expand Down Expand Up @@ -443,14 +442,14 @@ public void test_universalConverter_shouldWorkWithBoxAndCrudCorrectly() {

ResultMapperFactoryFactory factory =
client.getResultMapperFactoryFactory();
CallResultMapper callReturnMapper = factory.createMapper()
CallResultMapper callReturnMapper = factory.createMapper(valueMapper)
.withSingleValueConverter(
factory.createMapper()
.withArrayValueToTarantoolTupleResultConverter(valueMapper, null)
.withRowsMetadataToTarantoolTupleResultMapper(valueMapper, null)
.buildMessagePackMapper(valueMapper.copy())
factory.createMapper(valueMapper)
.withArrayValueToTarantoolTupleResultConverter()
.withRowsMetadataToTarantoolTupleResultConverter()
.buildCallResultMapper()
)
.buildCallResultMapper(valueMapper.copy());
.buildCallResultMapper();

Object crudResult =
client.call("crud.select", Collections.singletonList("test_space"), callReturnMapper).join();
Expand Down

0 comments on commit ef61296

Please sign in to comment.