/* * Copyright 2015-2016 the original author or authors. * * 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 org.springframework.cloud.dataflow.completion; import java.util.HashSet; import java.util.List; import java.util.Set; import org.springframework.boot.configurationmetadata.ConfigurationMetadataProperty; import org.springframework.cloud.dataflow.core.ApplicationType; import org.springframework.cloud.dataflow.core.BindingPropertyKeys; import org.springframework.cloud.dataflow.core.StreamAppDefinition; import org.springframework.cloud.dataflow.core.StreamDefinition; import org.springframework.cloud.dataflow.core.TaskPropertyKeys; /** * Various utility methods used throughout the completion package. * * @author Eric Bottard * @author Mark Fisher */ public class CompletionUtils { /** * The names of properties that may be added implicitly to all stream app definitions, * even though the user did not type them himself. */ static final Set<String> IMPLICIT_PARAMETER_NAMES = new HashSet<>(); static final Set<String> IMPLICIT_TASK_PARAMETER_NAMES = new HashSet<>(); static { IMPLICIT_PARAMETER_NAMES.add(BindingPropertyKeys.INPUT_DESTINATION); IMPLICIT_PARAMETER_NAMES.add(BindingPropertyKeys.INPUT_GROUP); IMPLICIT_PARAMETER_NAMES.add(BindingPropertyKeys.OUTPUT_REQUIRED_GROUPS); IMPLICIT_PARAMETER_NAMES.add(BindingPropertyKeys.OUTPUT_DESTINATION); IMPLICIT_TASK_PARAMETER_NAMES.add(TaskPropertyKeys.TASK_NAME); } /** * Return the type(s) a given stream app definition <em>could</em> have, in the * context of code completion. */ static ApplicationType[] determinePotentialTypes(StreamAppDefinition appDefinition) { Set<String> properties = appDefinition.getProperties().keySet(); if (properties.contains(BindingPropertyKeys.INPUT_DESTINATION)) { // Can't be source. For the purpose of completion, being the last app // (hence having BindingPropertyKeys.OUTPUT_DESTINATION not set) does NOT // guarantee we're dealing // with a sink (could be an unfinished "source | processor | processor" // stream) if (properties.contains(BindingPropertyKeys.OUTPUT_DESTINATION)) { return new ApplicationType[] { ApplicationType.processor }; } else { return new ApplicationType[] { ApplicationType.processor, ApplicationType.sink }; } } // MUST be source else { return new ApplicationType[] { ApplicationType.source }; } } /** * Given a candidate app name, maybe prefix it with an auto-generated label if its use * would clash with an already existing definition. * <p> * <p> * As an example, consider the (unfinished) stream definition * {@literal http | filter | filter}. Here {@literal appName} refers to the second * "filter" app name. An invocation of this method would return * {@literal "filter2: filter"} in that case. * </p> * <p> * Contrast this with the case of {@literal http | transform | filter}, where "filter" * is not yet used. This method would simply return an unaltered "filter" in that * case. * </p> */ static String maybeQualifyWithLabel(String appName, StreamDefinition streamDefinition) { String candidate = appName; Set<String> alreadyUsed = new HashSet<>(); for (StreamAppDefinition appDefinition : streamDefinition.getAppDefinitions()) { alreadyUsed.add(appDefinition.getName()); } String result = candidate; int counter = 2; while (alreadyUsed.contains(candidate)) { candidate = appName + counter++; result = String.format("%s: %s", candidate, appName); } return result; } /** * Return whether the given property name should be considered matching the candidate * configuration property, also taking into account the list of whitelist properties * (which are tested on their short name). */ static boolean isMatchingProperty(String propertyName, ConfigurationMetadataProperty property, List<ConfigurationMetadataProperty> whiteListedProps) { if (property.getId().equals(propertyName)) { return true; // For any prop } // Handle special case of short form for whitelist else { for (ConfigurationMetadataProperty white : whiteListedProps) { if (property.getId().equals(white.getId())) { // prop#equals() not // implemented return property.getName().equals(propertyName); } } return false; } } }