001/**
002 * Copyright (C) 2006-2020 Talend Inc. - www.talend.com
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.talend.sdk.component.server.service;
017
018import static java.util.Optional.ofNullable;
019import static java.util.stream.Collectors.toList;
020
021import java.util.Collection;
022import java.util.Map;
023import java.util.function.BiFunction;
024import java.util.function.Function;
025import java.util.stream.Stream;
026
027import javax.annotation.PostConstruct;
028import javax.enterprise.context.ApplicationScoped;
029
030import org.talend.sdk.component.runtime.manager.reflect.parameterenricher.ValidationParameterEnricher;
031import org.talend.sdk.component.server.front.model.PropertyValidation;
032
033@ApplicationScoped
034public class PropertyValidationService {
035
036    private Function<Map<String, String>, PropertyValidation> propertyValidationCreator;
037
038    @PostConstruct
039    private void initMapper() {
040        // precompute the mapping of validations to centralize the convention - note: can be moved to impl for setters
041        // part
042        final Collection<BiFunction<Object, Map<String, String>, Boolean>> validationSetters =
043                Stream.of(PropertyValidation.class.getDeclaredFields()).map(f -> {
044                    // we need boolean, int, string, collection<string>
045                    final Function<String, Object> valueConverter;
046                    if (Integer.class == f.getType()) {
047                        valueConverter = v -> Double.valueOf(v).intValue();
048                    } else if (Boolean.class == f.getType()) {
049                        valueConverter = Boolean::parseBoolean;
050                    } else if (Collection.class == f.getType()) {
051                        valueConverter = s -> Stream.of(s.split(",")).collect(toList());
052                    } else {
053                        valueConverter = s -> s;
054                    }
055                    if (!f.isAccessible()) {
056                        f.setAccessible(true);
057                    }
058                    return (BiFunction<Object, Map<String, String>, Boolean>) (instance,
059                            meta) -> ofNullable(meta.get(ValidationParameterEnricher.META_PREFIX + f.getName()))
060                                    .map(valueConverter)
061                                    .map(val -> {
062                                        try {
063                                            f.set(instance, val);
064                                        } catch (IllegalAccessException e) {
065                                            throw new IllegalStateException(e);
066                                        }
067                                        return true;
068                                    })
069                                    .orElse(false);
070                }).collect(toList());
071        propertyValidationCreator = config -> {
072            final PropertyValidation validation = new PropertyValidation();
073            if (validationSetters.stream().filter(s -> s.apply(validation, config)).count() == 0) {
074                return null;
075            }
076            return validation;
077        };
078    }
079
080    public PropertyValidation map(final Map<String, String> meta) {
081        return propertyValidationCreator.apply(meta);
082    }
083}