All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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>) 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 items) {
        return getDataProcessor().convertToDataResponse(items);
    }

    public JsonArray convertToKeysArray(@NotNull Collection 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 getElementType();

    protected abstract KeyMapper createKeyMapper();

    public boolean isSourceOrdered() {
        return true;
    }

    public Optional getIndexOfItem(ELEMENT item) {
        return Optional.empty();
    }

    public Optional> getIndexOfItems() {
        return Optional.empty();
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy