com.cloudera.csd.StringInterpolator.java Source code

Java tutorial

Introduction

Here is the source code for com.cloudera.csd.StringInterpolator.java

Source

// Licensed to Cloudera, Inc. under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  Cloudera, Inc. licenses this file
// to you 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 com.cloudera.csd;

import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Nullable;

/**
 * Provides string interpolation on a string
 * that has substitution variables. For example:
 * "My name is ${name}" when provided:
 * name -> "Bob" then this string gets interpolated
 * to: "My name is Bob"
 */
public class StringInterpolator {

    private static final String START_TOKEN = "\\$\\{";
    private static final String END_TOKEN = "\\}";

    private static final String REGEX = START_TOKEN + "([^}]+)" + END_TOKEN;
    private static final Pattern PATTERN = Pattern.compile(REGEX);

    /**
     * An interface that facilitates getting
     * variable information from the caller.
     */
    public interface VariableProvider {
        @Nullable
        String provide(String variableName);

    }

    /**
     * A convenience method for
     * {@link #interpolate(String,
     * StringInterpolator.VariableProvider)}.
     * Calls toString() on the variable values.
     */
    public String interpolate(String template, final Map<String, ?> variables) {
        return interpolate(template, new VariableProvider() {
            public String provide(String variableName) {
                Object value = variables.get(variableName);
                if (value == null) {
                    return null;
                }
                return value.toString();
            }
        });
    }

    /**
     * Performs the search and replace on the template given the
     * substitution variables. If there is a variable in
     * the message but there is no corresponding variable
     * in the map, an IllegalArgumentException is thrown.
     *
     * @param template the template.
     * @param provider the variable provider
     * @return the converted template.
     */
    public String interpolate(String template, VariableProvider provider) {
        Matcher m = PATTERN.matcher(template);
        String result = template;
        while (m.find()) {
            String var = m.group(); // This will be: ${myVar}
            String varName = m.group(1); // This will be: myVar
            String value = provider.provide(varName);
            if (value == null) {
                String msg = String.format("The variable [%s] does not have a corresponding value.", var);
                throw new IllegalArgumentException(msg);
            }
            result = result.replaceFirst(REGEX, value);
        }
        return result;
    }

    /**
     * Return all the placeholder variables that exist in
     * the template.
     *
     * @param template the template.
     * @return the set of variables in the template.
     */
    public Set<String> getVariables(String template) {
        Set<String> variables = Sets.newHashSet();
        Matcher m = PATTERN.matcher(template);
        while (m.find()) {
            variables.add(m.group(1));
        }
        return ImmutableSet.copyOf(variables);
    }

    /**
     * Iterates through all the values of the map and substitutes
     * variables as given by the provider. If the templates
     * map is null, an empty map is returned.
     *
     * @param templates the templates map.
     * @param provider the variable provider.
     * @return a new map with converted values.
     */
    public Map<String, String> interpolateValues(@Nullable Map<String, String> templates,
            VariableProvider provider) {
        if (templates == null) {
            return ImmutableMap.of();
        }
        Function<String, String> transformer = transformer(provider);
        return Maps.transformValues(templates, transformer);
    }

    /**
     * Iterates through all the values in the list and substitutes
     * variables as given by the provider. If the list is null,
     * an empty list is returned.
     *
     * @param templates the list of templates.
     * @param provider the variable provider.
     * @return a new list with converted values.
     */
    public List<String> interpolateList(@Nullable List<String> templates, VariableProvider provider) {
        if (templates == null) {
            return ImmutableList.of();
        }
        Function<String, String> transformer = transformer(provider);
        return Lists.transform(templates, transformer);
    }

    /**
     * The function used to iterate through the collections.
     */
    private Function<String, String> transformer(final VariableProvider provider) {
        return new Function<String, String>() {
            public String apply(@Nullable String input) {
                Preconditions.checkNotNull(input);
                return interpolate(input, provider);
            }
        };
    }
}