io.devbench.uibuilder.data.common.datasource.CommonDataSource Maven / Gradle / Ivy
/*
*
* Copyright © 2018 Webvalto Ltd.
*
* 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 io.devbench.uibuilder.data.common.datasource;
import elemental.json.JsonArray;
import elemental.json.JsonObject;
import io.devbench.uibuilder.api.parse.BindingContext;
import io.devbench.uibuilder.core.utils.reflection.ClassMetadata;
import io.devbench.uibuilder.data.api.datasource.DataSource;
import io.devbench.uibuilder.data.api.filter.FilterExpression;
import io.devbench.uibuilder.data.api.filter.FilterExpressionFactory;
import io.devbench.uibuilder.data.api.filter.metadata.BindingMetadata;
import io.devbench.uibuilder.data.api.filter.metadata.BindingMetadataProvider;
import io.devbench.uibuilder.data.api.filter.metadata.HasMetadataProvider;
import io.devbench.uibuilder.data.api.order.OrderExpression;
import io.devbench.uibuilder.data.api.order.OrderExpressionFactory;
import io.devbench.uibuilder.data.api.order.SortOrder;
import io.devbench.uibuilder.data.common.dataprovidersupport.DataProcessor;
import io.devbench.uibuilder.data.common.dataprovidersupport.KeyMapper;
import io.devbench.uibuilder.data.common.dataprovidersupport.requestresponse.DataFilter;
import io.devbench.uibuilder.data.common.dataprovidersupport.requestresponse.DataProviderRequest;
import io.devbench.uibuilder.data.common.dataprovidersupport.requestresponse.DataResponse;
import io.devbench.uibuilder.data.common.filter.comperingfilters.BinaryOperandFilterExpression;
import io.devbench.uibuilder.data.common.filter.comperingfilters.ExpressionTypes;
import io.devbench.uibuilder.data.common.filter.logicaloperators.AndFilterExpression;
import io.devbench.uibuilder.data.common.filter.metadata.CommonBindingMetadataProvider;
import io.devbench.uibuilder.data.common.filter.operator.OperatorType;
import lombok.Getter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public abstract class CommonDataSource<
ELEMENT,
ORDER_EXPRESSION_TYPE extends OrderExpression,
FILTER_EXPRESSION_TYPE extends FilterExpression>,
BINDING_CONTEXT_TYPE extends BindingContext>
implements DataSource, ORDER_EXPRESSION_TYPE, FILTER_EXPRESSION_TYPE, PagingFetchRequest>, HasMetadataProvider {
@Getter
private final BINDING_CONTEXT_TYPE bindingContext;
private DataProcessor dataProcessor;
protected CommonDataSource(BINDING_CONTEXT_TYPE bindingContext) {
this.bindingContext = bindingContext;
}
protected static boolean isPagingFetchRequestPresent(@Nullable PagingFetchRequest pagingFetchRequest) {
return pagingFetchRequest != null && pagingFetchRequest.getPage() != null && pagingFetchRequest.getPageSize() != null;
}
@Override
public Collection getBindings() {
return bindingContext.getBindings();
}
public String getDataSourceId() {
return bindingContext.getDataSourceId();
}
protected DataProcessor createDataProcessor() {
return new DataProcessor<>(this, getMetadataProvider(), this::createKeyMapper);
}
public DataProcessor getDataProcessor() {
if (dataProcessor == null) {
dataProcessor = createDataProcessor();
}
return dataProcessor;
}
public DataResponse fetchData(DataProviderRequest request) {
PagingFetchRequest fetchRequest = mapPagingInfoFromRequest(request);
handleFilterPartOfRequest(request);
handleOrderPartOfRequest(request);
handleHierarchicalRequest(request);
return getDataProcessor().convertToDataResponse(this.fetchData(fetchRequest));
}
protected abstract void handleHierarchicalRequest(DataProviderRequest request);
protected final Object getObjectFromRequest(DataProviderRequest request) {
final JsonObject parentItem = (JsonObject) request.getBody().getParentItem();
if (parentItem == null) {
return null;
}
final String key = parentItem.getString(DataProcessor.ITEM_KEY);
return getDataProcessor().getKeyMapper().getItem(key);
}
public abstract boolean hasChildren(ClassMetadata element);
protected abstract Collection getKeyPaths();
public Long fetchSize(DataProviderRequest request) {
PagingFetchRequest fetchRequest = mapPagingInfoFromRequest(request);
handleFilterPartOfRequest(request);
handleHierarchicalRequest(request);
return this.fetchSize(fetchRequest);
}
private PagingFetchRequest mapPagingInfoFromRequest(DataProviderRequest request) {
return PagingFetchRequest.builder()
.page(request.getBody().getPage())
.pageSize(request.getBody().getPageSize())
.build();
}
@SuppressWarnings("unchecked")
private void handleFilterPartOfRequest(DataProviderRequest request) {
List filters = request.getBody().getFilters();
if (filters != null && !filters.isEmpty()) {
AndFilterExpression, ?> containerExpression = getAndFilterExpression(filters);
registerFilter((FILTER_EXPRESSION_TYPE) containerExpression);
}
if (request.getBody().getResetFilters() != null && request.getBody().getResetFilters()) {
registerFilter(null);
}
}
@NotNull
@SuppressWarnings({"rawtypes", "unchecked"})
private AndFilterExpression getAndFilterExpression(List filters) {
FilterExpressionFactory> expressionFactory = (FilterExpressionFactory>) this.getFilterExpressionFactory();
AndFilterExpression containerExpression = expressionFactory.create(AndFilterExpression.class);
BindingMetadataProvider metadataProvider = this.getMetadataProvider();
for (DataFilter filter : filters) {
BindingMetadata metadata = metadataProvider.getMetadataForPath(filter.getPath());
BinaryOperandFilterExpression> leafExpression;
if (metadata.getPropertyType() != null) {
leafExpression = createFilterExpression(filter, String.class.isAssignableFrom(metadata.getPropertyType()));
leafExpression.setPath(filter.getPath());
leafExpression.setValue(tryToConvertFilterValue(filter, metadata));
if (leafExpression.getValue() != null) {
containerExpression.add(leafExpression);
}
}
}
return containerExpression;
}
private Optional getLikeExpressionType(DefaultFilterDescriptor.FilterType filterType) {
return Optional.ofNullable(ExpressionTypes.BaseLike.LikeExpressionType.fromMode(filterType.getMode()));
}
private DefaultFilterDescriptor getDefaultFilterDescriptor() {
if (bindingContext instanceof BaseDataSourceBindingContext) {
return ((BaseDataSourceBindingContext) bindingContext).getDefaultFilterDescriptor();
} else {
return new DefaultFilterDescriptor();
}
}
protected BinaryOperandFilterExpression> createFilterExpression(DataFilter filter, boolean stringTypeProperty) {
DefaultFilterDescriptor defaultFilterDescriptor = getDefaultFilterDescriptor();
DefaultFilterDescriptor.FilterType filterType = defaultFilterDescriptor.getFilterType(filter.getPath(), stringTypeProperty);
OperatorType operatorType = OperatorType.fromName(filterType.getName());
Class> expressionType = operatorType != null ?
operatorType.getExpressionType() :
ExpressionTypes.Equals.class;
@SuppressWarnings("unchecked")
FilterExpressionFactory> expressionFactory = (FilterExpressionFactory>) this.getFilterExpressionFactory();
@SuppressWarnings("unchecked")
BinaryOperandFilterExpression> filterExpression = (BinaryOperandFilterExpression>) expressionFactory
.create((Class extends FilterExpression>>) expressionType);
if (filterExpression instanceof ExpressionTypes.BaseLike) {
getLikeExpressionType(filterType).ifPresent(((ExpressionTypes.BaseLike>) filterExpression)::setLikeExpressionType);
}
return filterExpression;
}
private void handleOrderPartOfRequest(DataProviderRequest request) {
List sortOrders = request.getBody().getSortOrders();
if (sortOrders != null && !sortOrders.isEmpty()) {
OrderExpressionFactory expressionFactory = this.getOrderExpressionFactory();
ORDER_EXPRESSION_TYPE orderExpression = expressionFactory.create();
sortOrders.forEach(orderExpression::addOrder);
this.registerOrder(orderExpression);
}
}
private Object tryToConvertFilterValue(DataFilter filter, BindingMetadata metadata) {
try {
return metadata.getConverter().convertFrom(filter.getValue());
} catch (Exception ignore) {
return null;
}
}
public abstract boolean isHierarchical();
public Optional findItem(@NotNull JsonObject jsonItem) {
return Optional.ofNullable(getDataProcessor().getKeyMapper().getItem(DataProcessor.getItemKey(jsonItem)));
}
public List findItemsByJson(JsonArray frontendSelectedItems) {
return getDataProcessor().getItems(frontendSelectedItems);
}
public ELEMENT findItemByIdValue(@NotNull JsonObject key) {
return getDataProcessor().getKeyMapper().getItem(key);
}
public ELEMENT findItemByIdValue(String encodedId) {
return getDataProcessor().getKeyMapper().getItem(encodedId);
}
@Override
public BindingMetadataProvider getMetadataProvider() {
return new CommonBindingMetadataProvider<>(this::getElementType);
}
public DataResponse convertToDataResponse(@NotNull Collection extends ELEMENT> items) {
return getDataProcessor().convertToDataResponse(items);
}
public JsonArray convertToKeysArray(@NotNull Collection extends ELEMENT> items) {
return getDataProcessor().convertToKeysArray(items);
}
public JsonObject convertToKey(@NotNull ELEMENT item) {
return getDataProcessor().convertToKey(item);
}
public abstract ELEMENT findElementByKeyFilter(@NotNull FILTER_EXPRESSION_TYPE keyFilter);
public abstract Class extends ELEMENT> getElementType();
protected abstract KeyMapper createKeyMapper();
public boolean isSourceOrdered() {
return true;
}
public Optional getIndexOfItem(ELEMENT item) {
return Optional.empty();
}
public Optional
© 2015 - 2025 Weber Informatics LLC | Privacy Policy