<commit_before>/*
 * Copyright (c) 2008-2016 Haulmont.
 *
 * 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 com.haulmont.cuba.gui.components.listeditor;

import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.haulmont.bali.events.EventHub;
import com.haulmont.bali.events.Subscription;
import com.haulmont.chile.core.datatypes.DatatypeRegistry;
import com.haulmont.cuba.gui.ComponentsHelper;
import com.haulmont.cuba.gui.UiComponents;
import com.haulmont.cuba.gui.components.*;
import com.haulmont.cuba.gui.components.actions.BaseAction;
import com.haulmont.cuba.gui.components.data.Options;
import com.haulmont.cuba.gui.icons.CubaIcon;
import com.haulmont.cuba.gui.screen.*;
import org.slf4j.Logger;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;

@Component(ListEditorDelegate.NAME)
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class ListEditorDelegateImpl<V> implements ListEditorDelegate<V> {
    /* Beans */
    protected UiComponents uiComponents;

    protected Field actualField;

    protected List<V> value;

    protected Options<V> options;
    protected Function<? super V, String> optionCaptionProvider;

    protected Supplier<Map<String, Object>> editorParamsSupplier;
    protected String editorWindowId = "list-editor-popup";

    protected ListEditor.ItemType itemType;
    protected String entityName;
    protected String lookupScreen;
    protected boolean useLookupField;

    protected Map<String, V> optionsMap; // todo where it is written ?

    protected String entityJoinClause;
    protected String entityWhereClause;
    protected Class<? extends Enum> enumClass;
    protected TimeZone timeZone;
    protected List<Consumer<? super V>> validators;

    protected TextField<String> displayValuesField;
    protected HBoxLayout layout;
    protected Button clearBtn;

    protected boolean displayDescription = true;

    protected boolean editable = true;

    private EventHub eventHub;

    @Inject
    protected DatatypeRegistry datatypeRegistry;

    @Inject
    protected Logger log;

    @Inject
    public void setUiComponents(UiComponents uiComponents) {
        this.uiComponents = uiComponents;
    }

    @PostConstruct
    public void init() {
        layout = uiComponents.create(HBoxLayout.class);
        layout.setStyleName("c-listeditor-layout");
        layout.setWidth("100%");

        displayValuesField = uiComponents.create(TextField.NAME);
        displayValuesField.setStyleName("c-listeditor-text");
        displayValuesField.setEditable(false);

        initDisplayValuesFieldValueChangeListener();

        Button openEditorBtn = uiComponents.create(Button.class);
        openEditorBtn.setIconFromSet(CubaIcon.PICKERFIELD_LOOKUP);
        openEditorBtn.setStyleName("c-listeditor-button");
        openEditorBtn.setCaption("");
        openEditorBtn.addClickListener(e -> openEditor());

        layout.add(displayValuesField);
        layout.add(openEditorBtn);
        layout.expand(displayValuesField);
    }

    /**
     * displayValuesField may be editable, e.g. for IN condition in the Filter component. For such cases,
     * we should parse the string value and transform it to values list
     */
    protected void initDisplayValuesFieldValueChangeListener() {
        displayValuesField.addValueChangeListener(valueChangeEvent -> {
            //only handle cases when user directly modified the field value
            if (valueChangeEvent.isUserOriginated()) {
                String strValue = valueChangeEvent.getValue();
                List<Object> values = new ArrayList<>();
                if (!Strings.isNullOrEmpty(strValue)) {
                    List<String> parts = Splitter.on(",").trimResults().splitToList(strValue);
                    parts.forEach(value -> {
                        Object typedValue = null;
                        try {
                            switch (itemType) {
                                case STRING:
                                    typedValue = value;
                                    break;
                                case INTEGER:
                                    typedValue = datatypeRegistry.getNN(Integer.class).parse(value);
                                    break;
                                case BIGDECIMAL:
                                    typedValue = datatypeRegistry.getNN(BigDecimal.class).parse(value);
                                    break;
                                case LONG:
                                    typedValue = datatypeRegistry.getNN(Long.class).parse(value);
                                    break;
                                case DOUBLE:
                                    typedValue = datatypeRegistry.getNN(Double.class).parse(value);
                                    break;
                            }
                        } catch (ParseException e) {
                            log.error("Invalid value {}", value);
                        }
                        if (typedValue != null) {
                            values.add(typedValue);
                        }
                    });
                }
                actualField.setValue(values);
            }
        });
    }

    protected void openEditor() {
        Map<String, Object> params = new HashMap<>();
        params.put("itemType", itemType);
        params.put("entityName", entityName);
        params.put("useLookupField", useLookupField);
        params.put("options", options);
        params.put("optionCaptionProvider", optionCaptionProvider);
        params.put("enumClass", enumClass);
        params.put("lookupScreen", lookupScreen);
        params.put("entityJoinClause", entityJoinClause);
        params.put("entityWhereClause", entityWhereClause);
        params.put("values", getValue());
        params.put("editable", editable);<commit_msg>Allow enter comma-separated values for generic filter IN condition (spotbugs error fixed) #1643<commit_after>/*
 * Copyright (c) 2008-2016 Haulmont.
 *
 * 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 com.haulmont.cuba.gui.components.listeditor;

import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.haulmont.bali.events.EventHub;
import com.haulmont.bali.events.Subscription;
import com.haulmont.chile.core.datatypes.DatatypeRegistry;
import com.haulmont.cuba.gui.ComponentsHelper;
import com.haulmont.cuba.gui.UiComponents;
import com.haulmont.cuba.gui.components.*;
import com.haulmont.cuba.gui.components.actions.BaseAction;
import com.haulmont.cuba.gui.components.data.Options;
import com.haulmont.cuba.gui.icons.CubaIcon;
import com.haulmont.cuba.gui.screen.*;
import org.slf4j.Logger;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;

@Component(ListEditorDelegate.NAME)
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class ListEditorDelegateImpl<V> implements ListEditorDelegate<V> {
    /* Beans */
    protected UiComponents uiComponents;

    protected Field actualField;

    protected List<V> value;

    protected Options<V> options;
    protected Function<? super V, String> optionCaptionProvider;

    protected Supplier<Map<String, Object>> editorParamsSupplier;
    protected String editorWindowId = "list-editor-popup";

    protected ListEditor.ItemType itemType;
    protected String entityName;
    protected String lookupScreen;
    protected boolean useLookupField;

    protected Map<String, V> optionsMap; // todo where it is written ?

    protected String entityJoinClause;
    protected String entityWhereClause;
    protected Class<? extends Enum> enumClass;
    protected TimeZone timeZone;
    protected List<Consumer<? super V>> validators;

    protected TextField<String> displayValuesField;
    protected HBoxLayout layout;
    protected Button clearBtn;

    protected boolean displayDescription = true;

    protected boolean editable = true;

    private EventHub eventHub;

    @Inject
    protected DatatypeRegistry datatypeRegistry;

    @Inject
    protected Logger log;

    @Inject
    public void setUiComponents(UiComponents uiComponents) {
        this.uiComponents = uiComponents;
    }

    @PostConstruct
    public void init() {
        layout = uiComponents.create(HBoxLayout.class);
        layout.setStyleName("c-listeditor-layout");
        layout.setWidth("100%");

        displayValuesField = uiComponents.create(TextField.NAME);
        displayValuesField.setStyleName("c-listeditor-text");
        displayValuesField.setEditable(false);

        initDisplayValuesFieldValueChangeListener();

        Button openEditorBtn = uiComponents.create(Button.class);
        openEditorBtn.setIconFromSet(CubaIcon.PICKERFIELD_LOOKUP);
        openEditorBtn.setStyleName("c-listeditor-button");
        openEditorBtn.setCaption("");
        openEditorBtn.addClickListener(e -> openEditor());

        layout.add(displayValuesField);
        layout.add(openEditorBtn);
        layout.expand(displayValuesField);
    }

    /**
     * displayValuesField may be editable, e.g. for IN condition in the Filter component. For such cases,
     * we should parse the string value and transform it to values list
     */
    protected void initDisplayValuesFieldValueChangeListener() {
        displayValuesField.addValueChangeListener(valueChangeEvent -> {
            //only handle cases when user directly modified the field value
            if (valueChangeEvent.isUserOriginated()) {
                String strValue = valueChangeEvent.getValue();
                List<Object> values = new ArrayList<>();
                if (!Strings.isNullOrEmpty(strValue)) {
                    List<String> parts = Splitter.on(",").trimResults().splitToList(strValue);
                    parts.forEach(value -> {
                        Object typedValue = null;
                        try {
                            switch (itemType) {
                                case STRING:
                                    typedValue = value;
                                    break;
                                case INTEGER:
                                    typedValue = datatypeRegistry.getNN(Integer.class).parse(value);
                                    break;
                                case BIGDECIMAL:
                                    typedValue = datatypeRegistry.getNN(BigDecimal.class).parse(value);
                                    break;
                                case LONG:
                                    typedValue = datatypeRegistry.getNN(Long.class).parse(value);
                                    break;
                                case DOUBLE:
                                    typedValue = datatypeRegistry.getNN(Double.class).parse(value);
                                    break;
                                default:
                                    typedValue = null;
                            }
                        } catch (ParseException e) {
                            log.error("Invalid value {}", value);
                        }
                        if (typedValue != null) {
                            values.add(typedValue);
                        }
                    });
                }
                actualField.setValue(values);
            }
        });
    }

    protected void openEditor() {
        Map<String, Object> params = new HashMap<>();
        params.put("itemType", itemType);
        params.put("entityName", entityName);
        params.put("useLookupField", useLookupField);
        params.put("options", options);
        params.put("optionCaptionProvider", optionCaptionProvider);
        params.put("enumClass", enumClass);
        params.put("lookupScreen", lookupScreen);
        params.put("entityJoinClause", entityJoinClause);
        params.put("entityWhereClause", entityWhereClause);
        params.put("values", getValue());
        params.put("editable", editable);
{'fraction_non_alphanumeric': 0.08863767281105991, 'fraction_numerical': 0.0025921658986175116, 'mean_word_length': 2.2990498812351543, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 21, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3527593', 'n_tokens_mistral': 3504, 'n_tokens_neox': 3383, 'n_words': 810}