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.tools.validator;
017
018import static java.util.stream.Stream.of;
019
020import java.io.File;
021import java.lang.annotation.Annotation;
022import java.lang.reflect.Parameter;
023import java.util.ArrayList;
024import java.util.Collection;
025import java.util.LinkedHashSet;
026import java.util.List;
027import java.util.ResourceBundle;
028import java.util.Set;
029import java.util.stream.Stream;
030
031import org.apache.xbean.finder.AnnotationFinder;
032import org.talend.sdk.component.api.component.Icon;
033import org.talend.sdk.component.api.service.asyncvalidation.AsyncValidation;
034import org.talend.sdk.component.api.service.completion.DynamicValues;
035import org.talend.sdk.component.api.service.completion.Suggestions;
036import org.talend.sdk.component.api.service.dependency.DynamicDependencies;
037import org.talend.sdk.component.api.service.healthcheck.HealthCheck;
038import org.talend.sdk.component.api.service.schema.DiscoverSchema;
039import org.talend.sdk.component.api.service.update.Update;
040import org.talend.sdk.component.runtime.manager.ParameterMeta;
041import org.talend.sdk.component.runtime.manager.reflect.ParameterModelService;
042import org.talend.sdk.component.tools.ComponentValidator.Configuration;
043import org.talend.sdk.component.tools.spi.ValidationExtension;
044
045public class Validators {
046
047    private final List<Validator> validators;
048
049    private Validators(final List<Validator> validators) {
050        this.validators = validators;
051    }
052
053    public interface ValidatorHelper {
054
055        boolean isService(Parameter parameter);
056
057        ResourceBundle findResourceBundle(final Class<?> component);
058
059        String validateFamilyI18nKey(final Class<?> clazz, final String... keys);
060
061        List<ParameterMeta> buildOrGetParameters(final Class<?> c);
062
063        String validateIcon(final Icon annotation, final Collection<String> errors);
064
065        ParameterModelService getParameterModelService();
066
067        Stream<File> componentClassFiles();
068    }
069
070    public Set<String> validate(final AnnotationFinder finder, final List<Class<?>> components) {
071        final Set<String> errors = new LinkedHashSet<>();
072
073        this.validators
074                .stream()
075                .flatMap((Validator validator) -> validator.validate(finder, components))
076                .forEach(errors::add);
077        return errors;
078    }
079
080    public static Validators build(final Configuration configuration, final ValidatorHelper helper,
081            final Iterable<ValidationExtension> extensions, final File sourceRoot) {
082
083        final List<Validator> activeValidators = new ArrayList<>();
084
085        if (configuration.isValidateSerializable()) {
086            activeValidators.add(new SerializationValidator());
087        }
088
089        if (configuration.isValidateInternationalization()) {
090            InternationalizationValidator intern = new InternationalizationValidator(helper, sourceRoot,
091                    configuration.isValidatePlaceholder(), configuration.isValidateInternationalizationAutoFix());
092            activeValidators.add(intern);
093        }
094
095        if (configuration.isValidateHttpClient()) {
096            activeValidators.add(new HttpValidator());
097        }
098
099        if (configuration.isValidateModel()) {
100            final ModelValidator modelValidator = new ModelValidator(configuration.isValidateComponent(), helper);
101            activeValidators.add(modelValidator);
102        }
103
104        if (configuration.isValidateMetadata()) {
105            final MetadataValidator metaValidator = new MetadataValidator(helper);
106            activeValidators.add(metaValidator);
107        }
108
109        if (configuration.isValidateDataStore()) {
110            final DataStoreValidator validator = new DataStoreValidator(helper);
111            activeValidators.add(validator);
112        }
113
114        if (configuration.isValidateDataSet()) {
115            final DatasetValidator validator = new DatasetValidator(helper);
116            activeValidators.add(validator);
117            final DatasetDiscoveryValidator discoveryValidator = new DatasetDiscoveryValidator(helper);
118            activeValidators.add(discoveryValidator);
119        }
120
121        if (configuration.isValidateActions()) {
122            final ActionValidator validator = new ActionValidator(helper);
123            activeValidators.add(validator);
124        }
125
126        if (configuration.isValidateDocumentation()) {
127            activeValidators.add(new DocumentationValidator());
128        }
129
130        if (configuration.isValidateLayout()) {
131            final LayoutValidator validator = new LayoutValidator(helper);
132            activeValidators.add(validator);
133        }
134        if (configuration.isValidateOptionNames()) {
135            activeValidators.add(new OptionNameValidator());
136            activeValidators.add(new OptionParameterValidator());
137        }
138
139        if (configuration.isValidateLocalConfiguration()) {
140            final LocalConfigurationValidator validator = new LocalConfigurationValidator(helper, configuration);
141            activeValidators.add(validator);
142        }
143        if (configuration.isValidateOutputConnection()) {
144            activeValidators.add(new OutputConnectionValidator());
145        }
146        if (configuration.isValidateNoFinalOption()) {
147            activeValidators.add(new NoFinalOptionValidator());
148        }
149        if (configuration.isValidateWording()) {
150            if (configuration.isValidateDocumentation()) {
151                activeValidators.add(new DocumentationWordingValidator());
152            }
153        }
154
155        if (configuration.isValidateExceptions()) {
156            final ExceptionValidator validator = new ExceptionValidator(helper, configuration);
157            activeValidators.add(validator);
158        }
159
160        if (configuration.isValidateFamily()) {
161            final FamilyValidator validator = new FamilyValidator(helper);
162            activeValidators.add(validator);
163        }
164        if (extensions != null) {
165            extensions.forEach((ValidationExtension ext) -> {
166                final ExtensionValidator validator = new ExtensionValidator(ext, helper);
167                activeValidators.add(validator);
168            });
169        }
170        if (configuration.isValidateRecord()) {
171            activeValidators.add(new RecordValidator());
172        }
173        if (configuration.isValidateSchema()) {
174            activeValidators.add(new SchemaValidator());
175        }
176
177        return new Validators(activeValidators);
178
179    };
180
181    public static Stream<Class<? extends Annotation>> getActionsStream() {
182        return of(AsyncValidation.class, DynamicValues.class, HealthCheck.class, DiscoverSchema.class,
183                Suggestions.class, Update.class, DynamicDependencies.class);
184    }
185
186    public static Stream<ParameterMeta> flatten(final Collection<ParameterMeta> options) {
187        return options
188                .stream()
189                .flatMap((ParameterMeta it) -> Stream
190                        .concat(Stream.of(it), it.getNestedParameters().isEmpty() ? Stream.empty()
191                                : Validators.flatten(it.getNestedParameters())));
192    }
193}