/* * 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 com.addthis.hydra.job.spawn.search; import java.util.HashSet; import java.util.Map; import java.util.Scanner; import java.util.Set; import java.util.TreeMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; /** * Describes if/where various dependency includes live (e.g. marco/parameters inside a job config or macro). * <p/> * This calss is a wrapper of an internal map of marco/param names to their locations (in a body of text). Note that * the location represents that of the full pattern, which includes the <code>%{...}%/%[...]%</code> enclosure. * <p/> * Static methods are provided for processing given text, such as job config or macro, to find included marcos or job * parameters. */ public class IncludeLocations { private final Map<String, Set<TextLocation>> locations; // Example: %{macro-name}% private static final Pattern MACRO_PATTERN = Pattern.compile("%\\{(.+?)\\}%"); private static final int MACRO_PATTERN_GROUP = 1; // Example: %[parameter-name:default-value]% private static final Pattern JOB_PARAM_PATTERN = Pattern.compile("%\\[(.+?)(:.+?)?\\]%"); private static final int JOB_PARAM_PATTERN_GROUP = 1; /** Finds all macro locations in the given text. */ public static IncludeLocations forMacros(String text) { return new IncludeLocations(text, MACRO_PATTERN, MACRO_PATTERN_GROUP); } /** Finds all job parameter locations in the given text. */ public static IncludeLocations forJobParams(String text) { return new IncludeLocations(text, JOB_PARAM_PATTERN, JOB_PARAM_PATTERN_GROUP); } /** * @param text the text to search * @param pattern should match a section of a line for including a dependency * @param patternGroup the group of the matched pattern which contains the name of the dependency being included */ private IncludeLocations(String text, Pattern pattern, int patternGroup) { if (patternGroup < 0) { throw new IllegalArgumentException("The patternGroup cannot be negative"); } Map<String, Set<TextLocation>> locs = new TreeMap<>(); Scanner s = new Scanner(text); int lineNum = 0; while (s.hasNextLine()) { Matcher m = pattern.matcher(s.nextLine()); while (m.find()) { String depName = m.group(patternGroup); TextLocation match = new TextLocation(lineNum, m.start(), m.end()); Set<TextLocation> matches = locs.get(depName); if (matches == null) { matches = new HashSet<>(); locs.put(depName, matches); } matches.add(match); } lineNum++; } locations = ImmutableMap.copyOf(locs); } /** * Returns the locations of the included <code>name</code> * * @param name the macro/param name which may included * @return empty set if "name" is not included */ public Set<TextLocation> locationsFor(String name) { return locations.getOrDefault(name, ImmutableSet.of()); } /** * Returns all the included macro/parameter names. */ public Set<String> dependencies() { return locations.keySet(); } }