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

io.syndesis.project.converter.visitor.EndpointStepVisitor Maven / Gradle / Ivy

There is a newer version: 1.2.9
Show newest version
/*
 * Copyright (C) 2016 Red Hat, Inc.
 *
 * 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 io.syndesis.project.converter.visitor;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import io.syndesis.core.SyndesisServerException;
import io.syndesis.integration.model.steps.Endpoint;
import io.syndesis.model.WithConfigurationProperties;
import io.syndesis.model.connection.Action;
import io.syndesis.model.connection.Connection;
import io.syndesis.model.connection.Connector;
import io.syndesis.model.integration.Step;
import io.syndesis.project.converter.GenerateProjectRequest;

public class EndpointStepVisitor implements StepVisitor {
    private final GeneratorContext generatorContext;

    public static class Factory implements StepVisitorFactory {

        @Override
        public String getStepKind() {
            return Endpoint.KIND;
        }

        @Override
        public EndpointStepVisitor create(GeneratorContext generatorContext) {
            return new EndpointStepVisitor(generatorContext);
        }
    }

    public EndpointStepVisitor(GeneratorContext generatorContext) {
        this.generatorContext = generatorContext;
    }

    @Override
    public io.syndesis.integration.model.steps.Step visit(StepVisitorContext visitorContext) {
        Step step = visitorContext.getStep();
        if (!step.getAction().isPresent() || !step.getConnection().isPresent()) {
            return null;
        }

        try {
            return createEndpoint(
                visitorContext,
                generatorContext.getRequest(),
                step,
                step.getConnection().orElseThrow(() -> new IllegalStateException("Action is not present")),
                step.getAction().orElseThrow(() -> new IllegalStateException("Action is not present"))
            );
        } catch (IOException | URISyntaxException e) {
            throw SyndesisServerException.launderThrowable(e);
        }
    }

    private Endpoint createEndpoint(StepVisitorContext visitorContext, GenerateProjectRequest request, Step step, Connection connection, Action action) throws URISyntaxException, IOException {
        String connectorId = step.getConnection().get().getConnectorId().orElse(action.getConnectorId());
        if (!request.getConnectors().containsKey(connectorId)) {
            throw new IllegalStateException("Connector:[" + connectorId + "] not found.");
        }

        final String camelConnectorPrefix = action.getCamelConnectorPrefix();
        final Connector connector = request.getConnectors().get(connectorId);
        final Map configuredProperties = aggregate(connection.getConfiguredProperties(), step.getConfiguredProperties());
        final Map properties = aggregate(connector.filterProperties(configuredProperties, connector::isEndpointProperty), action.filterProperties(configuredProperties, action::isEndpointProperty));
        final boolean hasComponentOptions = hasComponentProperties(configuredProperties, connector, action);

        // connector prefix is suffixed with the computed id if needed (i.e. if
        // multiple instances of the same connector are defined). In such case
        // the prefix is something like:
        //
        //     twitter-search-connector-1
        //
        // otherwise it fallback to
        //
        //     twitter-search-connector
        //
        final String connectorPrefix = visitorContext.getConnectorIdSupplier().apply(step).map(id -> camelConnectorPrefix + "-" + id).orElse(camelConnectorPrefix);

        // connector prefix is suffixed with the computed id if needed (i.e. if
        // multiple instances of the same connector are defined) and if the
        // connector has component options to match the code in ActivateHandler
        // (see ActivateHandler#extractApplicationProperties) and in such case
        // the scheme generated scheme is something like:
        //
        //      twitter-search-connector-1
        //
        // otherwise it fallback to
        //
        //     twitter-search-connector
        //
        final String connectorScheme = hasComponentOptions ? visitorContext.getConnectorIdSupplier().apply(step).map(id -> camelConnectorPrefix + "-" + id).orElse(camelConnectorPrefix) : camelConnectorPrefix;

        // if the option is marked as secret use property placeholder as the
        // value is added to the integration secret.
        if (generatorContext.getGeneratorProperties().isSecretMaskingEnabled()) {
            properties.entrySet()
                .stream()
                .filter(or(connector::isSecret, action::isSecret))
                .forEach(e -> e.setValue(String.format("{{%s.%s}}", connectorPrefix, e.getKey())));
        }

        // TODO Remove this hack... when we can read endpointValues from connector schema then we should use those as initial properties.
        if ("periodic-timer".equals(camelConnectorPrefix)) {
            properties.put("timerName", "every");
        }

        return createEndpoint(camelConnectorPrefix, connectorScheme, properties);
    }

    private Endpoint createEndpoint(String camelConnectorPrefix, String connectorScheme, Map endpointOptions) throws URISyntaxException {
        String endpointUri = generatorContext.getConnectorCatalog().buildEndpointUri(camelConnectorPrefix, endpointOptions);

        if (endpointUri.startsWith(camelConnectorPrefix) && !camelConnectorPrefix.equals(connectorScheme)) {
            String remaining = endpointUri.substring(camelConnectorPrefix.length());

            if (!remaining.isEmpty()) {
                endpointUri = connectorScheme + remaining;
            } else {
                endpointUri = connectorScheme;
            }
        }

        return new Endpoint(endpointUri);
    }

    private static Map aggregate(Map ... maps) throws IOException {
        return Stream.of(maps).flatMap(map -> map.entrySet().stream()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> newValue));
    }

    private static  Predicate or(Predicate... predicates) {
        Predicate predicate = predicates[0];

        for (int i = 1; i < predicates.length; i++) {
            predicate = predicate.or(predicates[i]);
        }

        return predicate;
    }

    private static boolean hasComponentProperties(Map properties, WithConfigurationProperties... withConfigurationProperties) {
        for (WithConfigurationProperties wcp : withConfigurationProperties) {
            if (properties.entrySet().stream().anyMatch(wcp::isComponentProperty)) {
                return true;
            }
        }

        return false;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy