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

io.devbench.uibuilder.components.masterdetail.connector.HasValueMasterConnector Maven / Gradle / Ivy

There is a newer version: 3.0.2
Show 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.components.masterdetail.connector;

import com.vaadin.flow.component.AbstractField;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.HasEnabled;
import com.vaadin.flow.component.HasValue;
import com.vaadin.flow.data.provider.DataProvider;
import com.vaadin.flow.data.provider.HasDataView;
import com.vaadin.flow.data.provider.ListDataProvider;
import com.vaadin.flow.shared.Registration;
import io.devbench.uibuilder.api.components.masterconnector.AbstractUIBuilderMasterConnector;
import io.devbench.uibuilder.api.exceptions.MasterConnectorNotDirectlyModifiableException;
import io.devbench.uibuilder.api.exceptions.MasterConnectorUnsupportedOperationException;
import io.devbench.uibuilder.components.masterdetail.exception.MasterConnectorInternalException;
import io.devbench.uibuilder.components.masterdetail.exception.MasterConnectorNotHasEnabledComponentException;
import io.devbench.uibuilder.core.utils.reflection.MetadataReflectionUtils;

import java.util.*;

public class HasValueMasterConnector, T>, T>
    extends AbstractUIBuilderMasterConnector {

    private Registration hasValueValueChangesListenerRegistration;
    private Collection selectedItems = Collections.singleton(null);

    @SuppressWarnings("unchecked")
    public HasValueMasterConnector() {
        super((Class) Component.class);
    }

    @Override
    public boolean isApplicable(Class componentClass, String selector) {
        return DEFAULT_SELECTOR.equals(selector)
               && HasValue.class.isAssignableFrom(componentClass)
               && Component.class.isAssignableFrom(componentClass);
    }

    @Override
    public void onConnect(COMP masterComponent) {
        super.onConnect(masterComponent);
        hasValueValueChangesListenerRegistration = getMasterComponent().addValueChangeListener(event -> {
            Collection previouslySelectedItems = getSelectedItems();
            Collection newlySelectedItems = Collections.singleton(event.getValue());
            this.selectedItems = Collections.singleton(event.getValue());
            fireSelectionChangedEvent(
                new MasterSelectionChangedEvent<>(event.getSource(), event.isFromClient(), previouslySelectedItems, newlySelectedItems));
        });
    }

    @Override
    public void disconnect() {
        if (hasValueValueChangesListenerRegistration != null) {
            hasValueValueChangesListenerRegistration.remove();
            hasValueValueChangesListenerRegistration = null;
        }
    }

    @Override
    public Collection getSelectedItems() {
        return Collections.unmodifiableCollection(selectedItems);
    }

    @Override
    public void setSelectedItems(Collection items) {
        Objects.requireNonNull(items, "Selected items collection cannot be null");
        Iterator iterator = items.iterator();
        T value = iterator.hasNext() ? iterator.next() : null;
        getMasterComponent().setValue(value);
        selectedItems = Collections.unmodifiableCollection(items);
    }

    @Override
    public void refresh() {
        DataProvider dataProvider = getDataProvider().orElseThrow(MasterConnectorUnsupportedOperationException::new);
        dataProvider.refreshAll();
    }

    @Override
    public void refresh(T item) {
        DataProvider dataProvider = getDataProvider().orElseThrow(MasterConnectorUnsupportedOperationException::new);
        dataProvider.refreshItem(item);
    }

    @Override
    public void setEnabled(boolean enabled) {
        COMP masterComponent = getMasterComponent();
        if (masterComponent instanceof HasEnabled) {
            ((HasEnabled) masterComponent).setEnabled(enabled);
        } else {
            throw new MasterConnectorNotHasEnabledComponentException(masterComponent);
        }
    }

    @Override
    public boolean isEnabled() {
        COMP masterComponent = getMasterComponent();
        if (masterComponent instanceof HasEnabled) {
            return ((HasEnabled) masterComponent).isEnabled();
        }
        throw new MasterConnectorNotHasEnabledComponentException(masterComponent);
    }

    @Override
    public boolean isDirectModifiable() {
        return getListDataProvider().isPresent();
    }

    @Override
    public void addItem(T item) {
        ListDataProvider listDataProvider = getListDataProvider().orElseThrow(MasterConnectorNotDirectlyModifiableException::new);
        listDataProvider.getItems().add(item);
    }

    @Override
    public void removeItem(T item) {
        ListDataProvider listDataProvider = getListDataProvider().orElseThrow(MasterConnectorNotDirectlyModifiableException::new);
        listDataProvider.getItems().remove(item);
    }

    @SuppressWarnings("unchecked")
    private Optional> getListDataProvider() {
        return getDataProvider()
            .filter(ListDataProvider.class::isInstance)
            .map(dp -> (ListDataProvider) dp);
    }

    @SuppressWarnings("unchecked")
    private Optional> getDataProvider() {
        COMP masterComponent = getMasterComponent();
        if (masterComponent instanceof HasDataView) {
            try {
                return Optional.ofNullable((DataProvider) MetadataReflectionUtils
                    .getMethod(masterComponent.getClass(), "getDataProvider")
                    .invoke(masterComponent));
            } catch (NoSuchMethodException e) {
                throw new MasterConnectorInternalException("Master component doesn't contain getDataProvider", e);
            } catch (Exception e) {
                throw new MasterConnectorInternalException("Could not call getDataProvider on master component", e);
            }
        }
        return Optional.empty();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy