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

org.talend.sdk.component.runtime.manager.ComponentFamilyMeta Maven / Gradle / Ivy

There is a newer version: 10.57.0
Show newest version
/**
 * Copyright (C) 2006-2024 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.runtime.manager;

import static java.util.Optional.empty;
import static java.util.Optional.ofNullable;

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;

import org.talend.sdk.component.api.component.MigrationHandler;
import org.talend.sdk.component.api.processor.ElementListener;
import org.talend.sdk.component.runtime.base.Lifecycle;
import org.talend.sdk.component.runtime.input.Mapper;
import org.talend.sdk.component.runtime.internationalization.ComponentBundle;
import org.talend.sdk.component.runtime.internationalization.FamilyBundle;
import org.talend.sdk.component.runtime.manager.util.IdGenerator;
import org.talend.sdk.component.runtime.output.Processor;
import org.talend.sdk.component.runtime.standalone.DriverRunner;

import lombok.AccessLevel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;

@Data
@Slf4j
public class ComponentFamilyMeta {

    private static final FamilyBundle NO_COMPONENT_BUNDLE = new FamilyBundle(null, null) {

        @Override
        public Optional actionDisplayName(final String type, final String name) {
            return empty();
        }

        @Override
        public Optional category(final String value) {
            return empty();
        }

        @Override
        public Optional configurationDisplayName(final String type, final String name) {
            return empty();
        }

        @Override
        public Optional displayName() {
            return empty();
        }
    };

    private final String id;

    private final String plugin;

    private final Collection categories;

    private final String icon;

    private final String name;

    private final String packageName;

    private final Map partitionMappers = new HashMap<>();

    private final Map processors = new HashMap<>();

    private final Map driverRunners = new HashMap<>();

    private final ConcurrentMap bundles = new ConcurrentHashMap<>();

    public ComponentFamilyMeta(final String plugin, final Collection categories, final String icon,
            final String name, final String packageName) {
        this.id = IdGenerator.get(plugin, name);
        this.plugin = plugin;
        this.categories = categories;
        this.icon = icon;
        this.name = name;
        this.packageName = packageName;
    }

    public FamilyBundle findBundle(final ClassLoader loader, final Locale locale) {
        return bundles.computeIfAbsent(locale, l -> {
            try {
                final ResourceBundle bundle = ResourceBundle
                        .getBundle((packageName.isEmpty() ? packageName : (packageName + '.')) + "Messages", locale,
                                loader);
                return new FamilyBundle(bundle, name + '.');
            } catch (final MissingResourceException mre) {
                log
                        .warn("No bundle for " + packageName + " (" + name
                                + "), means the display names will be the technical names");
                log.debug(mre.getMessage(), mre);
                return NO_COMPONENT_BUNDLE;
            }
        });
    }

    @Data
    public static class BaseMeta {

        private static final ComponentBundle NO_COMPONENT_BUNDLE = new ComponentBundle(null, null) {

            @Override
            public Optional displayName() {
                return empty();
            }
        };

        private final ComponentFamilyMeta parent;

        private final String name;

        private final String icon;

        private final int version;

        private final String packageName;

        private final Supplier migrationHandler;

        private final Supplier> parameterMetas;

        private final ConcurrentMap bundles = new ConcurrentHashMap<>();

        /**
         * Stores data provided by extensions like ContainerListenerExtension
         */
        @Getter(AccessLevel.NONE)
        private final ConcurrentMap, Object> extensionsData = new ConcurrentHashMap<>();

        private final String id;

        private final Class type;

        private final Function, T> instantiator;

        private final boolean validated;

        private final Map metadata;

        BaseMeta(final ComponentFamilyMeta parent, final String name, final String icon, final int version,
                final Class type, final Supplier> parameterMetas,
                final Supplier migrationHandler, final Function, T> instantiator,
                final boolean validated, final Map metas) {
            this.parent = parent;
            this.name = name;
            this.icon = icon;
            this.version = version;
            this.packageName = ofNullable(type.getPackage()).map(Package::getName).orElse("");
            this.parameterMetas = parameterMetas;
            this.migrationHandler = migrationHandler;
            this.type = type;
            this.instantiator = instantiator;
            this.validated = validated;
            this.metadata = metas;

            this.id = IdGenerator.get(parent.getPlugin(), parent.getName(), name);

        }

        public ComponentBundle findBundle(final ClassLoader loader, final Locale locale) {
            return bundles.computeIfAbsent(locale, l -> {
                try {
                    final ResourceBundle bundle = ResourceBundle
                            .getBundle((packageName.isEmpty() ? packageName : (packageName + '.')) + "Messages", locale,
                                    loader);
                    return new ComponentBundle(bundle, parent.name + '.' + name + '.');
                } catch (final MissingResourceException mre) {
                    log
                            .warn("No bundle for " + packageName + " (" + parent.name + " / " + name
                                    + "), means the display names will be the technical names");
                    log.debug(mre.getMessage(), mre);
                    return NO_COMPONENT_BUNDLE;
                }
            });
        }

        public T instantiate(final Map configuration, final int configVersion) {
            if (configuration == null) {
                return this.getInstantiator().apply(null);
            }
            final Supplier migrationHandler = this.getMigrationHandler();
            final Map migratedConfiguration =
                    migrationHandler.get().migrate(configVersion, configuration);
            return this.getInstantiator().apply(migratedConfiguration);
        }

        /**
         * Sets data provided by extension
         *
         * @param key {@link Class} of data provided
         * @param instance data instance
         * @param  the type of the instance to store.
         *
         * @return data instance
         */
        public  D set(final Class key, final D instance) {
            return (D) extensionsData.put(key, instance);
        }

        /**
         * Returns extension data instance
         *
         * @param key {@link Class} of data instance to return
         * @param  the type of the instance to store.
         *
         * @return data instance
         */
        public  D get(final Class key) {
            return (D) extensionsData.get(key);
        }
    }

    @ToString
    @EqualsAndHashCode(callSuper = true)
    public static class PartitionMapperMeta extends BaseMeta {

        public static final String MAPPER_INFINITE = "mapper::infinite";

        protected PartitionMapperMeta(final ComponentFamilyMeta parent, final String name, final String icon,
                final int version, final Class type, final Supplier> parameterMetas,
                final Function, Mapper> instantiator,
                final Supplier migrationHandler, final boolean validated,
                final Map metas) {
            super(parent, name, icon, version, type, parameterMetas, migrationHandler, instantiator, validated, metas);
        }

        protected PartitionMapperMeta(final ComponentFamilyMeta parent, final String name, final String icon,
                final int version, final Class type, final Supplier> parameterMetas,
                final Function, Mapper> instantiator,
                final Supplier migrationHandler, final boolean validated, final boolean infinite) {
            super(parent, name, icon, version, type, parameterMetas, migrationHandler, instantiator, validated,
                    new HashMap() {

                        {
                            put(MAPPER_INFINITE, Boolean.toString(infinite));
                        }
                    });
        }

        public boolean isInfinite() {
            return Boolean.parseBoolean(getMetadata().getOrDefault(MAPPER_INFINITE, "false"));
        }
    }

    @ToString
    @EqualsAndHashCode(callSuper = true)
    public static class ProcessorMeta extends BaseMeta {

        protected ProcessorMeta(final ComponentFamilyMeta parent, final String name, final String icon,
                final int version, final Class type, final Supplier> parameterMetas,
                final Function, Processor> instantiator,
                final Supplier migrationHandler, final boolean validated,
                final Map metas) {
            super(parent, name, icon, version, type, parameterMetas, migrationHandler, instantiator, validated, metas);
        }

        /**
         * Returns {@link Processor} class method annotated with {@link ElementListener}
         *
         * @return listener method
         */
        public Method getListener() {
            return Stream
                    .of(getType().getMethods())
                    .filter(m -> m.isAnnotationPresent(ElementListener.class))
                    .findFirst()
                    .orElseThrow(() -> new IllegalArgumentException("No @ElementListener method in " + getType()));
        }
    }

    @ToString
    @EqualsAndHashCode(callSuper = true)
    public static class DriverRunnerMeta extends BaseMeta {

        protected DriverRunnerMeta(final ComponentFamilyMeta parent, final String name, final String icon,
                final int version, final Class type, final Supplier> parameterMetas,
                final Function, DriverRunner> instantiator,
                final Supplier migrationHandler, final boolean validated,
                final Map metas) {
            super(parent, name, icon, version, type, parameterMetas, migrationHandler, instantiator, validated, metas);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy