1 package org.unicode.cldr.util; 2 3 import com.google.common.base.Splitter; 4 import com.google.common.collect.ImmutableList; 5 import java.io.IOException; 6 import java.io.UncheckedIOException; 7 import java.nio.file.Files; 8 import java.nio.file.Path; 9 import java.util.ArrayList; 10 import java.util.List; 11 import java.util.regex.Pattern; 12 import java.util.stream.Stream; 13 14 public class LocalePathValueListMatcher { 15 16 private static final Splitter SPLIT_SEMI_COLON = Splitter.on(';').trimResults(); 17 18 public static class LocalePathValueMatcher { 19 final Pattern localePattern; 20 final Pattern pathPattern; 21 final Pattern valuePattern; 22 LocalePathValueMatcher(List<String> parts)23 public LocalePathValueMatcher(List<String> parts) { 24 localePattern = 25 parts.size() < 1 || parts.get(0).isEmpty() 26 ? null 27 : Pattern.compile(parts.get(0)); 28 pathPattern = 29 parts.size() < 2 || parts.get(1).isEmpty() 30 ? null 31 : Pattern.compile(parts.get(1).replace("[@", "\\[@")); 32 valuePattern = 33 parts.size() < 3 || parts.get(1).isEmpty() 34 ? null 35 : Pattern.compile(parts.get(2)); 36 } 37 38 public boolean lookingAt(String locale, String path, String value) { 39 return (localePattern == null || localePattern.matcher(locale).lookingAt()) 40 && (pathPattern == null || pathPattern.matcher(path).lookingAt()) 41 && (valuePattern == null || valuePattern.matcher(value).lookingAt()); 42 } 43 44 /** 45 * Just test the locale, to see if we need to bother looking at its path/values 46 * 47 * @param locale 48 * @param path 49 * @param value 50 * @return 51 */ 52 public boolean lookingAt(String locale) { 53 return (localePattern == null || localePattern.matcher(locale).lookingAt()); 54 } 55 56 @Override 57 public String toString() { 58 return String.format("%s\t;\t%s\t%;\ts", localePattern, pathPattern, valuePattern); 59 } 60 } 61 62 final List<LocalePathValueListMatcher.LocalePathValueMatcher> matchData; 63 64 public LocalePathValueListMatcher( 65 List<LocalePathValueListMatcher.LocalePathValueMatcher> _matchData) { 66 matchData = ImmutableList.copyOf(_matchData); 67 } 68 69 public static LocalePathValueListMatcher load(Path path) { 70 try { 71 return load(Files.lines(path)); 72 } catch (IOException ex) { 73 throw new UncheckedIOException(ex); 74 } 75 } 76 77 public static LocalePathValueListMatcher load(Stream<String> lines) { 78 List<LocalePathValueListMatcher.LocalePathValueMatcher> _matchData = new ArrayList<>(); 79 lines.forEach(line -> load(line, _matchData)); 80 return new LocalePathValueListMatcher(_matchData); 81 } 82 83 public boolean lookingAt(String locale, String path, String value) { 84 for (LocalePathValueListMatcher.LocalePathValueMatcher lpv : matchData) { 85 if (lpv.lookingAt(locale, path, value)) { 86 return true; 87 } 88 } 89 return false; 90 } 91 92 /** Just test the locale, to see if we need to bother */ 93 public boolean lookingAt(String locale) { 94 for (LocalePathValueListMatcher.LocalePathValueMatcher lpv : matchData) { 95 if (lpv.lookingAt(locale)) { 96 return true; 97 } 98 } 99 return false; 100 } 101 102 private static void load( 103 String line, List<LocalePathValueListMatcher.LocalePathValueMatcher> _matchData) { 104 line = line.trim(); 105 if (line.startsWith("#") || line.isEmpty()) { 106 return; 107 } 108 final List<String> lineList = SPLIT_SEMI_COLON.splitToList(line); 109 if (lineList.size() < 2) { 110 throw new IllegalArgumentException( 111 "Match lines must have at least locale ; path: «" + line + "»"); 112 } 113 if (lineList.size() > 3) { 114 throw new IllegalArgumentException( 115 "Match lines must have a maximum of 3 fields (locale; path; value): «" 116 + line 117 + "»"); 118 } 119 _matchData.add(new LocalePathValueMatcher(lineList)); 120 } 121 } 122