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

org.talend.sdk.component.server.service.PropertiesService Maven / Gradle / Ivy

/**
 * Copyright (C) 2006-2021 Talend Inc. - www.talend.com
 *
 * 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 org.talend.sdk.component.server.service;

import static java.util.Optional.ofNullable;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toSet;
import static org.talend.sdk.component.server.lang.CustomCollectors.toLinkedMap;

import java.util.AbstractMap;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.json.bind.Jsonb;

import org.talend.sdk.component.runtime.internationalization.ParameterBundle;
import org.talend.sdk.component.runtime.manager.ParameterMeta;
import org.talend.sdk.component.runtime.manager.reflect.parameterenricher.ValidationParameterEnricher;
import org.talend.sdk.component.runtime.manager.util.DefaultValueInspector;
import org.talend.sdk.component.server.configuration.ComponentServerConfiguration;
import org.talend.sdk.component.server.front.model.PropertyValidation;
import org.talend.sdk.component.server.front.model.SimplePropertyDefinition;
import org.talend.sdk.component.server.service.qualifier.ComponentServer;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@ApplicationScoped
public class PropertiesService {

    private final DefaultValueInspector defaultValueInspector = new DefaultValueInspector();

    @Inject
    private PropertyValidationService propertyValidationService;

    @Inject
    private ComponentServerConfiguration componentServerConfiguration;

    @Inject
    @ComponentServer
    private Jsonb defaultMapper;

    public Stream buildProperties(final List meta, final ClassLoader loader,
            final Locale locale, final DefaultValueInspector.Instance rootInstance) {
        return buildProperties(meta, loader, locale, rootInstance, null);
    }

    private Stream buildProperties(final List meta, final ClassLoader loader,
            final Locale locale, final DefaultValueInspector.Instance rootInstance, final ParameterMeta parent) {
        return meta.stream().flatMap(p -> {
            final String path = sanitizePropertyName(p.getPath());
            final String name = sanitizePropertyName(p.getName());
            final String type = p.getType().name();
            final boolean isEnum = p.getType() == ParameterMeta.Type.ENUM;
            PropertyValidation validation = propertyValidationService.map(p.getMetadata());
            if (isEnum) {
                if (validation == null) {
                    validation = new PropertyValidation();
                }
                validation.setEnumValues(p.getProposals());
            }
            final Map sanitizedMetadata = ofNullable(p.getMetadata())
                    .map(m -> m
                            .entrySet()
                            .stream()
                            .filter(e -> !e.getKey().startsWith(ValidationParameterEnricher.META_PREFIX))
                            .collect(toLinkedMap(e -> e.getKey().replace("tcomp::", ""), Map.Entry::getValue)))
                    .orElse(null);
            final Map metadata;
            if (parent != null) {
                metadata = sanitizedMetadata;
            } else {
                metadata = ofNullable(sanitizedMetadata).orElseGet(HashMap::new);
                metadata.put("definition::parameter::index", String.valueOf(meta.indexOf(p)));
            }
            final DefaultValueInspector.Instance instance = defaultValueInspector
                    .createDemoInstance(
                            ofNullable(rootInstance).map(DefaultValueInspector.Instance::getValue).orElse(null), p);
            final ParameterBundle bundle = p.findBundle(loader, locale);
            final ParameterBundle parentBundle = parent == null ? null : parent.findBundle(loader, locale);
            return Stream
                    .concat(Stream
                            .of(new SimplePropertyDefinition(path, name,
                                    bundle.displayName(parentBundle).orElse(p.getName()), type, toDefault(instance, p),
                                    validation, rewriteMetadataForLocale(metadata, parentBundle, bundle),
                                    bundle.placeholder(parentBundle).orElse(p.getName()),
                                    !isEnum ? null
                                            : p
                                                    .getProposals()
                                                    .stream()
                                                    .collect(toLinkedMap(identity(),
                                                            key -> bundle
                                                                    .enumDisplayName(parentBundle, key)
                                                                    .orElse(key))))),
                            buildProperties(p.getNestedParameters(), loader, locale, instance, p));
        }).sorted(Comparator.comparing(SimplePropertyDefinition::getPath)); // important cause it is the way you want to
        // see it
    }

    private Map rewriteMetadataForLocale(final Map metadata,
            final ParameterBundle parentBundle, final ParameterBundle bundle) {
        return rewriteLayoutMetadata(rewriteDocMetadata(metadata, parentBundle, bundle), parentBundle, bundle);
    }

    private Map rewriteDocMetadata(final Map metadata,
            final ParameterBundle parentBundle, final ParameterBundle bundle) {
        final String defaultDoc = metadata.get("documentation::value");
        final String bundleDoc = bundle.documentation(parentBundle).orElse(null);
        if (bundleDoc == null || bundleDoc.equals(defaultDoc)) {
            return metadata;
        }
        final Map copy = new HashMap<>(metadata);
        copy.put("documentation::value", bundleDoc);
        return copy;
    }

    private Map rewriteLayoutMetadata(final Map metadata,
            final ParameterBundle parentBundle, final ParameterBundle bundle) {
        if (!componentServerConfiguration.getTranslateGridLayoutTabNames()) {
            return metadata;
        }

        final Collection keysToRewrite = metadata
                .keySet()
                .stream()
                .filter(it -> it.startsWith("ui::gridlayout::") && it.endsWith("::value"))
                .collect(toSet());
        if (keysToRewrite.isEmpty()) {
            return metadata;
        }
        final Predicate> shouldBeRewritten = k -> keysToRewrite.contains(k.getKey());
        return Stream
                .concat(metadata.entrySet().stream().filter(shouldBeRewritten.negate()),
                        metadata
                                .entrySet()
                                .stream()
                                .filter(shouldBeRewritten)
                                .map(it -> new AbstractMap.SimpleEntry<>(bundle
                                        .gridLayoutName(parentBundle,
                                                it
                                                        .getKey()
                                                        .substring("ui::gridlayout::".length(),
                                                                it.getKey().length() - "::value".length()))
                                        .map(t -> "ui::gridlayout::" + t + "::value")
                                        .orElse(it.getKey()), it.getValue())))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    }

    private String toDefault(final DefaultValueInspector.Instance instance, final ParameterMeta p) {
        if (instance.isCreated()) {
            return null;
        }
        if (Collection.class.isInstance(instance.getValue()) || Map.class.isInstance(instance.getValue())) {
            // @Experimental("not primitives are a challenge, for now use that but can change if not adapted")
            return defaultMapper.toJson(instance.getValue());
        }
        return defaultValueInspector.findDefault(instance.getValue(), p);
    }

    private String sanitizePropertyName(final String path) {
        return path.replace("${index}", "");
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy