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.design.extension.repository; 017 018import static java.util.Collections.singletonList; 019import static java.util.function.Function.identity; 020import static java.util.stream.Collectors.toList; 021import static java.util.stream.Collectors.toMap; 022import static org.talend.sdk.component.runtime.manager.util.Lazy.lazy; 023 024import java.lang.reflect.Type; 025import java.util.ArrayList; 026import java.util.Collection; 027import java.util.LinkedHashMap; 028import java.util.List; 029import java.util.Map; 030import java.util.stream.Stream; 031 032import org.talend.sdk.component.api.component.MigrationHandler; 033import org.talend.sdk.component.api.component.Version; 034import org.talend.sdk.component.design.extension.RepositoryModel; 035import org.talend.sdk.component.runtime.manager.ComponentFamilyMeta; 036import org.talend.sdk.component.runtime.manager.ComponentManager; 037import org.talend.sdk.component.runtime.manager.ParameterMeta; 038import org.talend.sdk.component.runtime.manager.reflect.MigrationHandlerFactory; 039import org.talend.sdk.component.runtime.manager.util.IdGenerator; 040 041/** 042 * Copyright (C) 2006-2025 Talend Inc. - www.talend.com 043 * <p> 044 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 045 * use this file except in compliance with the License. You may obtain a copy of 046 * the License at 047 * <p> 048 * http://www.apache.org/licenses/LICENSE-2.0 049 * <p> 050 * Unless required by applicable law or agreed to in writing, software 051 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 052 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 053 * License for the specific language governing permissions and limitations under 054 * the License. 055 */ 056public class RepositoryModelBuilder { 057 058 public RepositoryModel create(final ComponentManager.AllServices services, 059 final Collection<ComponentFamilyMeta> familyMetas, final MigrationHandlerFactory migrationHandlerFactory) { 060 final List<Family> families = familyMetas 061 .stream() 062 .map(familyMeta -> createConfigForFamily(services, migrationHandlerFactory, familyMeta)) 063 .collect(toList()); 064 return new RepositoryModel(families); 065 } 066 067 private Family createConfigForFamily(final ComponentManager.AllServices services, 068 final MigrationHandlerFactory migrationHandlerFactory, final ComponentFamilyMeta familyMeta) { 069 final Family family = new Family(); 070 family.setId(familyMeta.getId()); 071 family.setMeta(familyMeta); 072 family 073 .setConfigs(lazy(() -> extractConfigurations(services, migrationHandlerFactory, familyMeta) 074 .values() 075 .stream() 076 .collect(ArrayList::new, (aggregator, item) -> { 077 final Collection<Config> configs = aggregator 078 .stream() 079 .filter(c -> toParamStream(item.getMeta().getNestedParameters()) 080 .anyMatch(p -> p.getJavaType() == c.getMeta().getJavaType())) 081 .findFirst() 082 .map(Config::getChildConfigs) 083 .orElse(aggregator); 084 if (configs 085 .stream() 086 .noneMatch(c -> c.getMeta().getJavaType() == item.getMeta().getJavaType())) { 087 configs.add(item); 088 } 089 }, List::addAll))); 090 return family; 091 } 092 093 private Map<Type, Config> extractConfigurations(final ComponentManager.AllServices services, 094 final MigrationHandlerFactory migrationHandlerFactory, final ComponentFamilyMeta familyMeta) { 095 return Stream 096 .of(familyMeta.getPartitionMappers().values().stream(), familyMeta.getProcessors().values().stream(), 097 familyMeta.getDriverRunners().values().stream()) 098 .flatMap(t -> t) 099 .flatMap(b -> b.getParameterMetas().get().stream()) 100 .flatMap(this::flatten) 101 .filter(RepositoryModelBuilder::isConfiguration) 102 .map(p -> createConfig(familyMeta.getPlugin(), services, p, familyMeta.getName(), familyMeta.getIcon(), 103 migrationHandlerFactory)) 104 .collect(toMap(c -> c.getMeta().getJavaType(), identity(), (config1, config2) -> config1, 105 LinkedHashMap::new)); 106 } 107 108 private Stream<ParameterMeta> toParamStream(final Collection<ParameterMeta> params) { 109 if (params.isEmpty()) { 110 return Stream.empty(); 111 } 112 return Stream.concat(params.stream(), params.stream().flatMap(p -> toParamStream(p.getNestedParameters()))); 113 } 114 115 private Stream<ParameterMeta> flatten(final ParameterMeta meta) { 116 if (meta.getNestedParameters() == null || meta.getNestedParameters().isEmpty()) { 117 return Stream.of(meta); 118 } 119 return Stream.concat(meta.getNestedParameters().stream().flatMap(this::flatten), Stream.of(meta)); 120 } 121 122 private Config createConfig(final String plugin, final ComponentManager.AllServices services, 123 final ParameterMeta config, final String familyName, final String familyIcon, 124 final MigrationHandlerFactory migrationHandlerFactory) { 125 final Config c = new Config(); 126 c.setIcon(familyIcon); 127 c.setKey(getKey(familyName, config.getMetadata())); 128 c.setMeta(translate(config, config.getPath().length(), "configuration")); 129 c 130 .setId(IdGenerator 131 .get(plugin, c.getKey().getFamily(), c.getKey().getConfigType(), c.getKey().getConfigName())); 132 133 if (Class.class.isInstance(config.getJavaType())) { 134 final Class<?> clazz = Class.class.cast(config.getJavaType()); 135 final Version version = clazz.getAnnotation(Version.class); 136 if (version != null) { 137 c.setVersion(version.value()); 138 if (version.migrationHandler() != MigrationHandler.class) { 139 c 140 .setMigrationHandler(migrationHandlerFactory 141 .findMigrationHandler(() -> singletonList(c.getMeta()), clazz, services)); 142 } 143 } else { 144 c.setVersion(-1); 145 } 146 } 147 if (c.getMigrationHandler() == null) { 148 c.setMigrationHandler((v, d) -> d); 149 } 150 151 return c; 152 } 153 154 private ConfigKey getKey(final String family, final Map<String, String> meta) { 155 final String configName = meta.get("tcomp::configurationtype::name"); 156 final String configType = meta.get("tcomp::configurationtype::type"); 157 return new ConfigKey(family, configName, configType); 158 } 159 160 private static boolean isConfiguration(final ParameterMeta parameterMeta) { 161 return parameterMeta.getMetadata().keySet().stream().anyMatch(m -> m.startsWith("tcomp::configurationtype::")); 162 } 163 164 private ParameterMeta translate(final ParameterMeta config, final int replacedPrefixLen, final String newPrefix) { 165 return new ParameterMeta(config.getSource(), config.getJavaType(), config.getType(), 166 newPrefix + config.getPath().substring(replacedPrefixLen), 167 config.getPath().length() == replacedPrefixLen ? newPrefix : config.getName(), config.getI18nPackages(), 168 config 169 .getNestedParameters() 170 .stream() 171 .map(it -> translate(it, replacedPrefixLen, newPrefix)) 172 .collect(toList()), 173 config.getProposals(), config.getMetadata(), config.isLogMissingResourceBundle()); 174 } 175}