org.dbflute.bhv.readable.coins.VirtualUnionPagingBean Maven / Gradle / Ivy
/*
* Copyright 2014-2020 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.dbflute.bhv.readable.coins;
import java.util.ArrayList;
import java.util.List;
import org.dbflute.cbean.result.PagingResultBean;
import org.dbflute.cbean.result.ResultBeanBuilder;
/**
* The handler of entity row.
* @param The type of identity.
* @param The type of mapped result.
* @author jflute
* @since 1.1.0 (2014/12/30 Tuesday)
*/
public class VirtualUnionPagingBean {
// ===================================================================================
// Attribute
// =========
protected final List _metaMap = new ArrayList();
protected int _pageSize;
protected int _pageNumber;
// ===================================================================================
// Constructor
// ===========
public VirtualUnionPagingBean(VirtualUnionPagingIdSelector noArgLambda, VirtualUnionPagingDataMapper oneArgLambda) {
unionAll(noArgLambda, oneArgLambda);
}
// ===================================================================================
// Union
// =====
// _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
// cannot order through all records
// and no union(), you should remove duplicate records after select manually
// _/_/_/_/_/_/_/_/_/_/
public VirtualUnionPagingBean unionAll(VirtualUnionPagingIdSelector noArgLambda,
VirtualUnionPagingDataMapper oneArgLambda) {
_metaMap.add(newVirtualUnionPagingMetaInfo(noArgLambda, oneArgLambda));
return this;
}
protected VirtualUnionPagingMeta newVirtualUnionPagingMetaInfo(VirtualUnionPagingIdSelector idSelector,
VirtualUnionPagingDataMapper dataMapper) {
return new VirtualUnionPagingMeta(idSelector, dataMapper);
}
// ===================================================================================
// Paging
// ======
public VirtualUnionPagingSelector paging(int pageSize, int pageNumber) {
if (pageSize < 1) {
throw new IllegalArgumentException("The pageSize should not be minus or zero: " + pageSize);
}
if (pageNumber < 1) {
throw new IllegalArgumentException("The pageNumber should not be minus or zero: " + pageNumber);
}
_pageSize = pageSize;
_pageNumber = pageNumber;
return new VirtualUnionPagingSelector() {
public PagingResultBean selectPage() {
return doSelectPage();
}
};
}
protected PagingResultBean doSelectPage() {
final PagingResultBean page = actuallySelectPage(_pageSize, _pageNumber);
if (page.getCurrentPageNumber() > 1 && page.isEmpty()) {
return actuallySelectPage(_pageSize, page.getAllPageCount()); // retry
}
return page;
}
protected PagingResultBean actuallySelectPage(int pageSize, int pageNumber) {
final int allRecordCount = prepareIdList();
final List resultList = new ArrayList();
final boolean usePaging = pageSize > 0 && pageNumber > 0;
final int limit = usePaging ? pageSize * pageNumber : -1;
final int offset = usePaging ? pageSize * (pageNumber - 1) : -1;
int skippedCount = 0;
boolean overOffset = false;
int actualCount = 0;
for (VirtualUnionPagingMeta meta : _metaMap) {
final VirtualUnionPagingDataMapper dataMapper = meta.getDataMapper();
List idList = meta.getIdList();
if (idList.isEmpty()) {
continue;
}
if (usePaging) {
if (!overOffset) {
final int scheduledSkippedCount = skippedCount + idList.size();
if (scheduledSkippedCount < offset) {
skippedCount = skippedCount + idList.size();
continue;
}
overOffset = true;
idList = filterIdListByOffset(idList, skippedCount, offset);
if (idList.isEmpty()) { // re-check
continue;
}
}
idList = filterIdListByLimit(idList, actualCount, limit, offset);
if (idList.isEmpty()) { // re-check
continue;
}
}
final List mappedList = dataMapper.selectMappedList(idList);
final int mappedSize = mappedList.size();
assertMappedSizeValidForIdList(idList, mappedSize);
resultList.addAll(mappedList);
actualCount = actualCount + mappedSize;
if (usePaging && actualCount >= limit) {
break;
}
}
final ResultBeanBuilder builder = new ResultBeanBuilder("UNION_PAGING");
return builder.buildPagingSimply(pageSize, pageNumber, allRecordCount, resultList);
}
protected int prepareIdList() {
int count = 0;
for (VirtualUnionPagingMeta meta : _metaMap) {
final VirtualUnionPagingIdSelector idSelector = meta.getIdSelector();
final List idList = idSelector.selectIdList();
meta.setIdList(idList);
count = count + idList.size();
}
return count;
}
protected List filterIdListByOffset(List idList, int skippedCount, int offset) {
return idList.subList(offset - skippedCount, idList.size());
}
protected List filterIdListByLimit(List idList, int actualCount, int limit, int offset) {
final int scheduledCount = actualCount + idList.size();
final int pageSize = limit - offset; // not use instance variable for independent
if (scheduledCount > pageSize) { // mean last
if (actualCount == 0) {
idList = idList.subList(0, pageSize);
} else {
final int remainderSize = pageSize - actualCount;
idList = remainderSize < idList.size() ? idList.subList(0, remainderSize) : idList;
}
}
return idList;
}
protected void assertMappedSizeValidForIdList(List idList, final int mappedSize) {
if (mappedSize > idList.size()) {
String msg = "mapped list is over the ID list: " + mappedSize + ", " + idList;
throw new IllegalStateException(msg);
}
}
// ===================================================================================
// Helper Class
// ============
public interface VirtualUnionPagingSelector { // not function interface, for chain
PagingResultBean selectPage();
}
public class VirtualUnionPagingMeta {
protected VirtualUnionPagingIdSelector _idSelector;
protected VirtualUnionPagingDataMapper _dataMapper;
protected List _idList; // set later
public VirtualUnionPagingMeta(VirtualUnionPagingIdSelector idSelector, VirtualUnionPagingDataMapper dataMapper) {
_idSelector = idSelector;
_dataMapper = dataMapper;
}
public VirtualUnionPagingIdSelector getIdSelector() {
return _idSelector;
}
public void setIdSelector(VirtualUnionPagingIdSelector idSelector) {
_idSelector = idSelector;
}
public VirtualUnionPagingDataMapper getDataMapper() {
return _dataMapper;
}
public void setDataMapper(VirtualUnionPagingDataMapper dataMapper) {
_dataMapper = dataMapper;
}
public List getIdList() {
return _idList;
}
public void setIdList(List idList) {
_idList = idList;
}
}
@FunctionalInterface
public interface VirtualUnionPagingIdSelector {
List selectIdList();
}
@FunctionalInterface
public interface VirtualUnionPagingDataMapper {
List selectMappedList(List idList);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy