io.devbench.uibuilder.data.common.dataprovidersupport.DataProcessor 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.dataprovidersupport;
import com.vaadin.flow.component.HasEnabled;
import elemental.json.*;
import io.devbench.uibuilder.api.exceptions.InternalResolverException;
import io.devbench.uibuilder.core.utils.reflection.ClassMetadata;
import io.devbench.uibuilder.data.api.filter.metadata.BindingMetadata;
import io.devbench.uibuilder.data.api.filter.metadata.BindingMetadataProvider;
import io.devbench.uibuilder.data.common.component.ItemPredicateProvider;
import io.devbench.uibuilder.data.common.dataprovidersupport.inlineedit.InlineEditHandler;
import io.devbench.uibuilder.data.common.dataprovidersupport.inlineedit.SimpleInlineEditHandler;
import io.devbench.uibuilder.data.common.dataprovidersupport.requestresponse.DataResponse;
import io.devbench.uibuilder.data.common.datasource.CommonDataSource;
import io.devbench.uibuilder.data.common.exceptions.DataSourceItemKeyNotFoundException;
import io.devbench.uibuilder.data.common.item.ItemState;
import lombok.Getter;
import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.NotNull;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class DataProcessor {
public static final String ITEM_KEY = "___ITEM_KEY";
public static final String ITEM_ENDPOINT_ID = "__ITEM_ENDPOINT_ID";
public static final String PRIMITIVE_VALUE_KEY = "___PRIMITIVE_VALUE";
public static final String ITEM = "item";
public static final String ITEM_WITH_DOT = "item.";
public static final String LEAF = "item.leaf";
@Getter
private final CommonDataSource dataSource;
@Getter
private final KeyMapper keyMapper;
private final BindingMetadataProvider metadataProvider;
private final Map metadataCache;
@Getter
private InlineEditHandler inlineEditHandler;
public DataProcessor(
CommonDataSource dataSource,
BindingMetadataProvider metadataProvider,
Supplier> keyMapperSupplier
) {
this.dataSource = dataSource;
this.metadataProvider = metadataProvider;
this.keyMapper = keyMapperSupplier.get();
this.metadataCache = new HashMap<>();
this.inlineEditHandler = new SimpleInlineEditHandler();
}
@NotNull
public static String getItemKey(@NotNull JsonObject jsonItem) {
JsonValue jsonValue = jsonItem.get(ITEM_KEY);
if (jsonValue instanceof JsonString) {
return jsonValue.asString();
}
throw new DataSourceItemKeyNotFoundException("Could not find datasource item key in json object: " + jsonItem);
}
public JsonArray convertToKeysArray(@NotNull Collection extends ELEMENT> items) {
return getJsonArray(items, (ignore) -> Json.createObject());
}
public DataResponse convertToDataResponse(@NotNull Collection extends ELEMENT> items) {
Objects.requireNonNull(items);
DataResponse dataResponse = new DataResponse();
JsonArray jsonArray = getJsonArray(items,
(finalClassMetadata) -> Stream.concat(mapBingingToValue(finalClassMetadata), mapHierarchicBinding(finalClassMetadata))
.collect(Json::createObject, this::addPathValueToJsonObject, this::combineJsonObjects));
applyInlineEditablePredicate(jsonArray);
handleInlineEditPropertyChanges(jsonArray);
dataResponse.setResponse(jsonArray);
return dataResponse;
}
private void applyInlineEditablePredicate(@NotNull JsonArray jsonArray) {
DataProviderEndpointManager.getInstance()
.getComponent(dataSource.getDataSourceId())
.filter(ItemPredicateProvider.class::isInstance)
.map(ItemPredicateProvider.class::cast)
.ifPresent(itemPredicateProvider -> {
onJsonItem(jsonArray, jsonItem -> true, jsonItem -> {
ELEMENT item = keyMapper.getItem(getItemKey(jsonItem));
@SuppressWarnings("unchecked")
Predicate itemPredicate = itemPredicateProvider.getItemPredicate();
if (itemPredicate != null) {
boolean editAllowed = itemPredicate.test(item);
ItemState itemState = inlineEditHandler.getItemState(jsonItem);
itemState.setEditAllowed(editAllowed);
if (!editAllowed) {
itemState.setEditMode(false);
}
itemState.applyOnJsonItem(jsonItem);
}
});
});
}
private void handleInlineEditPropertyChanges(@NotNull JsonArray jsonArray) {
DataProviderEndpointManager.getInstance()
.getComponent(dataSource.getDataSourceId())
.filter(HasEnabled.class::isInstance)
.map(HasEnabled.class::cast)
.ifPresent(component -> {
if (component.isEnabled()) {
onJsonItem(jsonArray, jsonItem -> inlineEditHandler.isEditMode(jsonItem), jsonItem -> {
for (String itemKey : jsonItem.keys()) {
if (!itemKey.startsWith("_") && inlineEditHandler.hasChangedPropertyValue(jsonItem, itemKey)) {
jsonItem.put(itemKey, inlineEditHandler.getChangedPropertyValue(jsonItem, itemKey));
}
}
});
} else {
onJsonItem(jsonArray, jsonItem -> true, jsonItem -> {
ItemState itemState = inlineEditHandler.getItemState(jsonItem);
itemState.setEditAllowed(false);
itemState.setSaveAllowed(false);
itemState.applyOnJsonItem(jsonItem);
});
}
});
}
private void onJsonItem(@NotNull JsonArray array, Predicate jsonItemPredicate, Consumer itemConsumer) {
for (int i = 0; i < array.length(); i++) {
JsonValue jsonValue = array.get(i);
if (jsonValue instanceof JsonObject) {
JsonObject item = (JsonObject) jsonValue;
if (jsonItemPredicate.test(item)) {
itemConsumer.accept(item);
}
}
}
}
@NotNull
private Stream> mapHierarchicBinding(ClassMetadata finalClassMetadata) {
if (dataSource.isHierarchical()) {
return Stream.of(Pair.of(LEAF, Json.create(!dataSource.hasChildren(finalClassMetadata))));
} else {
return Stream.empty();
}
}
@NotNull
public Stream> mapBingingToValue(ClassMetadata finalClassMetadata) {
return dataSource.getBindings().stream()
.filter(binding -> binding.startsWith(ITEM))
.map(binding -> Pair.of(binding, getConvertedValueForPath(binding, finalClassMetadata)));
}
private JsonArray getJsonArray(@NotNull Collection extends ELEMENT> items,
Function, JsonObject> createJsonObjectFromClassMetadata) {
JsonArray jsonArray = Json.createArray();
ClassMetadata classMetadata = null;
int index = 0;
Optional
© 2015 - 2025 Weber Informatics LLC | Privacy Policy