001/**
002 * Copyright (C) 2006-2024 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.runtime.manager.reflect.parameterenricher;
017
018import java.lang.annotation.Annotation;
019import java.lang.reflect.ParameterizedType;
020import java.lang.reflect.Type;
021import java.util.Collection;
022import java.util.Collections;
023import java.util.Map;
024import java.util.stream.Stream;
025
026import org.talend.sdk.component.api.configuration.dependency.ConnectorRef;
027
028import lombok.extern.slf4j.Slf4j;
029
030@Slf4j
031public class DependencyParameterEnricher extends BaseParameterEnricher {
032
033    public static final String TCOMP_DEPENDENCIES_CONNECTOR_KEY = "tcomp::dependencies::connector";
034
035    @Override
036    public Map<String, String> onParameterAnnotation(final String parameterName,
037            final Type parameterType,
038            final Annotation annotation) {
039
040        // mark class type as the one that carry dependencies
041        if (this.isConnectorReference(parameterType)
042                || this.isCollectionConnectorReference(parameterType)) {
043            return Collections.singletonMap(TCOMP_DEPENDENCIES_CONNECTOR_KEY, "family");
044        }
045
046        // mark relevant fields with metadata
047        if (String.class.equals(parameterType) && annotation != null
048                && ConnectorRef.class.equals(annotation.annotationType())) {
049            return Collections.singletonMap(TCOMP_DEPENDENCIES_CONNECTOR_KEY,
050                    ((ConnectorRef) annotation).value().getRefValue());
051        }
052
053        return Collections.emptyMap();
054    }
055
056    // Check if parameter is of a simple collection (List, Set ...) of ConnectorReference
057    // don't work with Map (composed collection), nor List<? extends ConnectorReference> (not used in framework)
058    private boolean isCollectionConnectorReference(final Type parameterType) {
059        // check generic
060        if (!(parameterType instanceof ParameterizedType)) {
061            return false;
062        }
063        final ParameterizedType parameterClass = (ParameterizedType) parameterType;
064
065        // Check it's a Collection (java.util)
066        final Type rawType = parameterClass.getRawType();
067        if ((!(rawType instanceof Class)) || !Collection.class.isAssignableFrom((Class) rawType)) {
068            return false;
069        }
070
071        // Check arguments.
072        final Type[] arguments = parameterClass.getActualTypeArguments();
073        if (arguments.length != 1) {
074            return false;
075        }
076        final Type argument = arguments[0];
077        return this.isConnectorReference(argument);
078    }
079
080    // Check if parameter is of type or subtype of ConnectorReference
081    private boolean isConnectorReference(final Type parameterType) {
082        return parameterType instanceof Class
083                && Stream.of(((Class<?>) parameterType).getDeclaredFields())
084                        .anyMatch(field -> field.isAnnotationPresent(ConnectorRef.class));
085    }
086}