io.devbench.uibuilder.spring.crud.SpringGenericCrudControllerBean Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of uibuilder-spring Show documentation
Show all versions of uibuilder-spring Show documentation
Spring support for the UIBuilder Framework
The newest version!
/*
*
* 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.spring.crud;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.spring.annotation.UIScope;
import io.devbench.uibuilder.annotations.ControllerBean;
import io.devbench.uibuilder.api.controllerbean.uieventhandler.Item;
import io.devbench.uibuilder.api.controllerbean.uieventhandler.Source;
import io.devbench.uibuilder.api.controllerbean.uieventhandler.UIEventHandler;
import io.devbench.uibuilder.api.controllerbean.uieventhandler.Value;
import io.devbench.uibuilder.api.crud.CanCreate;
import io.devbench.uibuilder.api.crud.GenericCrudControllerBean;
import io.devbench.uibuilder.api.crud.Refreshable;
import io.devbench.uibuilder.data.api.annotations.TargetDataSource;
import io.devbench.uibuilder.spring.data.SpringCommonDataSourceProvider;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.ApplicationContext;
import org.springframework.data.repository.PagingAndSortingRepository;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;
@Slf4j
@UIScope
@ControllerBean(GenericCrudControllerBean.BUILT_IN_GENERIC_CRUD_PANEL_CONTROLLER_BEAN_NAME)
public class SpringGenericCrudControllerBean implements GenericCrudControllerBean {
@Getter(AccessLevel.PACKAGE)
private final Map> genericCrudDataMdcIdMap;
private final SpringCommonDataSourceProvider commonDataSourceProvider;
private final ApplicationContext applicationContext;
private Consumer inlineItemSaveCrudPanelIdConsumer;
public SpringGenericCrudControllerBean(SpringCommonDataSourceProvider commonDataSourceProvider, ApplicationContext applicationContext) {
this.commonDataSourceProvider = commonDataSourceProvider;
this.applicationContext = applicationContext;
this.genericCrudDataMdcIdMap = new HashMap<>();
}
private void withMdc(Refreshable refreshable, Consumer> crudDataConsumer) {
if (refreshable instanceof Component) {
((Component) refreshable).getId().ifPresent(mdcId -> {
@SuppressWarnings("unchecked")
GenericCrudData crudData = (GenericCrudData) genericCrudDataMdcIdMap.get(mdcId);
if (crudData != null) {
crudDataConsumer.accept(crudData);
refreshable.refresh();
} else {
log.error("Crud data is unavailable for MDC ID: {}", mdcId);
}
});
}
}
private void withRepository(Refreshable refreshable, Consumer> repositoryConsumer) {
withMdc(refreshable, crudData -> repositoryConsumer.accept(crudData.getRepository()));
}
private Optional> createCrudData(@NotNull String datasourceName) {
@SuppressWarnings("unchecked")
Pair>> datasourceRepoPair =
(Pair>>)
commonDataSourceProvider.getDataSourceRepositories().get(datasourceName);
if (datasourceRepoPair != null) {
Class extends PagingAndSortingRepository> repositoryClass = datasourceRepoPair.getValue();
ObjectProvider extends PagingAndSortingRepository> repositoryProvider = applicationContext.getBeanProvider(repositoryClass);
PagingAndSortingRepository repository = repositoryProvider.getIfAvailable();
if (repository != null) {
@SuppressWarnings("unchecked")
Optional> itemClass = commonDataSourceProvider.tryToFindEntityClassByRepositoryClass(repositoryClass);
if (itemClass.isPresent()) {
return Optional.of(new GenericCrudData<>(itemClass.get(), repository));
} else {
log.error("Could not find repository item type for datasource: {}", datasourceName);
}
} else {
log.error("Could not get repository bean for class: {}", repositoryClass);
}
}
return Optional.empty();
}
@Override
public void registerGenericCrudData(@NotNull String mdcId, @NotNull String datasourceName) {
createCrudData(datasourceName).ifPresent(crudData -> genericCrudDataMdcIdMap.put(mdcId, crudData));
}
@Override
public void registerNestedInlineItemSaveHandler(@NotNull Consumer inlineItemSaveCrudPanelIdConsumer) {
this.inlineItemSaveCrudPanelIdConsumer = inlineItemSaveCrudPanelIdConsumer;
}
@Override
@UIEventHandler("onSave")
public void onSave(@Item TYPE subject, @Source Refreshable refreshable) {
withRepository(refreshable, repository -> repository.save(subject));
}
@Override
@UIEventHandler("onDelete")
public void onDelete(@Item TYPE subject, @Source Refreshable refreshable) {
withRepository(refreshable, repository -> repository.delete(subject));
}
@Override
@UIEventHandler("onRefresh")
public void refresh(@Source Refreshable refreshable) {
if (refreshable != null) {
refreshable.refresh();
}
}
@Override
@UIEventHandler("onCreate")
public void onCreate(@Source Refreshable refreshable) {
withMdc(refreshable, crudData -> {
try {
Constructor constructor = crudData.getItemClass().getConstructor();
TYPE item = constructor.newInstance();
if (refreshable instanceof CanCreate) {
@SuppressWarnings("unchecked")
CanCreate canCreate = (CanCreate) refreshable;
canCreate.createItem(item);
} else {
log.error("Component cannot create item: {}", refreshable);
}
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
log.error("Could not created generic type instance", e);
}
});
}
@UIEventHandler("handleNestedInlineItemSave")
public void handleNestedInlineItemSave(@Nullable @Value("detail.crudPanel") String memberCrudPanelId) {
if (inlineItemSaveCrudPanelIdConsumer != null) {
inlineItemSaveCrudPanelIdConsumer.accept(memberCrudPanelId);
}
}
}