001/**
002 * Copyright (C) 2006-2025 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;
017
018import static lombok.AccessLevel.PRIVATE;
019
020import java.lang.reflect.Constructor;
021import java.util.stream.Stream;
022
023import org.talend.sdk.component.api.configuration.Option;
024
025import lombok.NoArgsConstructor;
026
027@NoArgsConstructor(access = PRIVATE)
028public final class Constructors {
029
030    public static Constructor<?> findConstructor(final Class<?> type) {
031        return Stream
032                .of(type.getConstructors())
033                // we select the constructor with arguments which uses @Option or no-arg
034                // constructor if no param construct
035                // is matching
036                .sorted((c1, c2) -> {
037                    final int options1 = Stream
038                            .of(c1.getParameters())
039                            .mapToInt(p -> p.isAnnotationPresent(Option.class) ? 1 : 0)
040                            .sum();
041                    final int options2 = Stream
042                            .of(c1.getParameters())
043                            .mapToInt(p -> p.isAnnotationPresent(Option.class) ? 1 : 0)
044                            .sum();
045                    if (options1 == options2) {
046                        final int paramCount1 = c1.getParameterCount();
047                        final int paramCount2 = c2.getParameterCount();
048                        return paramCount2 - paramCount1;
049                    }
050                    return options2 - options1;
051
052                })
053                .findFirst()
054                .orElseThrow(() -> new IllegalArgumentException("No constructor usable in " + type.getName()));
055    }
056}