
net.oneandone.troilus.SingleReadQuery Maven / Gradle / Ivy
/*
* Copyright 1&1 Internet AG, https://github.com/1and1/
*
* 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 net.oneandone.troilus;
import java.util.Iterator;
import java.util.List;
import org.reactivestreams.Publisher;
import net.oneandone.troilus.java7.FetchingIterator;
import net.oneandone.troilus.java7.Record;
import net.oneandone.troilus.java7.ResultList;
import net.oneandone.troilus.java7.SingleRead;
import net.oneandone.troilus.java7.SingleReadWithUnit;
import net.oneandone.troilus.java7.interceptor.ReadQueryData;
import net.oneandone.troilus.java7.interceptor.ResultListAdapter;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Read query implementation
*/
class SingleReadQuery extends AbstractQuery implements SingleReadWithUnit {
private final ReadQueryData data;
/**
* @param ctx the context
* @param data the data
*/
SingleReadQuery(Context ctx, ReadQueryData data) {
super(ctx);
this.data = data;
}
////////////////////
// factory methods
@Override
protected SingleReadQuery newQuery(Context newContext) {
return new SingleReadQuery(newContext, data);
}
private SingleReadQuery newQuery(ReadQueryData data) {
return new SingleReadQuery(getContext(), data);
}
//
////////////////////
@Override
public SingleReadQuery all() {
return newQuery(data.columnsToFetch(ImmutableMap.of()));
}
@Override
public SingleReadQuery column(String name) {
return newQuery(data.columnsToFetch(Immutables.join(data.getColumnsToFetch(), name, false)));
}
@Override
public SingleReadQuery columnWithMetadata(String name) {
return newQuery(data.columnsToFetch(Immutables.join(data.getColumnsToFetch(), name, true)));
}
@Override
public SingleReadQuery columns(String... names) {
return columns(ImmutableList.copyOf(names));
}
private SingleReadQuery columns(ImmutableList names) {
SingleReadQuery read = this;
for (String columnName : names) {
read = read.column(columnName);
}
return read;
}
@Override
public SingleReadQuery column(ColumnName> name) {
return column(name.getName());
}
@Override
public SingleReadQuery columnWithMetadata(ColumnName> name) {
return column(name.getName());
}
@Override
public SingleReadQuery columns(ColumnName>... names) {
List ns = Lists.newArrayList();
for (ColumnName> name : names) {
ns.add(name.getName());
}
return columns(ImmutableList.copyOf(ns));
}
@Override
public SingleEntityReadQuery asEntity(Class objectClass) {
return new SingleEntityReadQuery(getContext(), this, objectClass);
}
@Override
public Record execute() {
return ListenableFutures.getUninterruptibly(executeAsync());
}
@Override
public ListenableFuture executeAsync() {
ListenableFuture> recordsFuture = new ListReadQuery(getContext(), data).executeAsync();
recordsFuture = toSingleEntryResultList(recordsFuture);
Function, Record> fetchRecordFunction = new Function, Record>() {
@Override
public Record apply(ResultList records) {
Iterator it = records.iterator();
if (it.hasNext()) {
Record record = it.next();
if (it.hasNext()) {
throw new TooManyResultsException(records, "more than one record exists");
}
return record;
} else {
return null;
}
}
};
return Futures.transform(recordsFuture, fetchRecordFunction);
}
@Override
public Publisher executeRx() {
ListenableFuture> recordsFuture = new ListReadQuery(getContext(), data).executeAsync();
recordsFuture = toSingleEntryResultList(recordsFuture);
return new ResultListPublisher(recordsFuture);
}
/**
* Entity read query
* @param the entity type
*/
static class SingleEntityReadQuery extends AbstractQuery> implements SingleRead {
private final Class clazz;
private final SingleReadQuery query;
/**
* @param ctx the context
* @param query the underlying query
* @param clazz the entity type
*/
SingleEntityReadQuery(Context ctx, SingleReadQuery query, Class clazz) {
super(ctx);
this.query = query;
this.clazz = clazz;
}
@Override
protected SingleEntityReadQuery newQuery(Context newContext) {
return new SingleReadQuery(newContext, query.data).asEntity(clazz);
}
@Override
public E execute() {
return ListenableFutures.getUninterruptibly(executeAsync());
}
@Override
public ListenableFuture executeAsync() {
ListenableFuture future = query.executeAsync();
Function mapEntity = new Function() {
@Override
public E apply(Record record) {
if (record == null) {
return null;
} else {
return getContext().getBeanMapper().fromValues(clazz, RecordImpl.toPropertiesSource(record), getContext().getDbSession().getColumnNames());
}
}
};
return Futures.transform(future, mapEntity);
}
@Override
public Publisher executeRx() {
ListenableFuture> recordsFuture = new ListReadQuery(getContext(), query.data).asEntity(clazz).executeAsync();
recordsFuture = toSingleEntryResultList(recordsFuture);
return new ResultListPublisher(recordsFuture);
}
}
private static ListenableFuture> toSingleEntryResultList(ListenableFuture> list) {
Function, ResultList> mapperFunction = new Function, ResultList>() {
@Override
public ResultList apply(ResultList list) {
return new SingleEntryResultList<>(list);
}
};
return Futures.transform(list, mapperFunction);
}
private static final class SingleEntryResultList extends ResultListAdapter {
public SingleEntryResultList(ResultList list) {
super(list);
}
@Override
public FetchingIterator iterator() {
return new SingleFetchingIterator<>(super.iterator());
}
private final class SingleFetchingIterator implements FetchingIterator {
private final FetchingIterator iterator;
public SingleFetchingIterator(FetchingIterator iterator) {
this.iterator = iterator;
}
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public E next() {
E element = iterator.next();
if (iterator.hasNext()) {
throw new TooManyResultsException(SingleEntryResultList.this, "more than one record exists");
}
return element;
}
@Override
public int getAvailableWithoutFetching() {
return iterator.getAvailableWithoutFetching();
}
@Override
public ListenableFuture fetchMoreResultsAsync() {
return iterator.fetchMoreResultsAsync();
}
@Override
public boolean isFullyFetched() {
return iterator.isFullyFetched();
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy