MultiBundleCSVFilter extends MultiBundleResourceFilter { @Override public void merge(InputStream baseStream, OutputStream outStream, Map<String, LanguageBundle> languageBundles, FilterOptions options) throws IOException, ResourceFilterException { Map<String, Map<String, String>> kvMaps = new HashMap<String, Map<String, String>>(); for (Entry<String, LanguageBundle> bundleEntry: languageBundles.entrySet()) { LanguageBundle languageBundle = bundleEntry.getValue(); Map<String, String> kvMap = new HashMap<String, String>(); for (ResourceString resString : languageBundle.getResourceStrings()) { kvMap.put(resString.getKey(), resString.getValue()); } kvMaps.put(bundleEntry.getKey(), kvMap); } CSVParser parser = CSVParser.parse(baseStream, StandardCharsets.UTF_8, CSVFormat.RFC4180.withHeader("module", "key", "value").withSkipHeaderRecord(true)); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outStream, StandardCharsets.UTF_8)); CSVPrinter printer = CSVFormat.RFC4180.withHeader("module", "key", "value").print(writer); for (CSVRecord record : parser) { String module = record.get(0); String key = record.get(1); String value = record.get(2); Map<String, String> moduleKVMap = kvMaps.get(module); if (moduleKVMap != null) { String trValue = moduleKVMap.get(key); if (trValue != null) { value = trValue; } } printer.printRecord(module, key, value); } printer.flush(); }  @Override Map<String, LanguageBundle> parse(InputStream inStream, FilterOptions options); @Override void write(OutputStream outStream, Map<String, LanguageBundle> languageBundles, FilterOptions options); @Override void merge(InputStream baseStream, OutputStream outStream, Map<String, LanguageBundle> languageBundles,
            FilterOptions options); static final String ID; static final Type TYPE; }
@Test public void testMerge() { String[] baseLines = { "module,key,value", "Japanese Foods,ramen,Ramen", "Italian Foods,minestrone,Minestrone", "Japanese Foods,sushi,Sushi", "Italian Foods,pizza,Pizza", "Italian Foods,spaghetti,Spaghetti" }; TestResourceStringData[] testDataJapanese = { new TestResourceStringData("sushi", "寿司", 1), new TestResourceStringData("ramen", "ラーメン", 2), new TestResourceStringData("tempura", "天ぷら", 3) }; TestResourceStringData[] testDataItalian = { new TestResourceStringData("spaghetti", "スパゲッティ", 1), new TestResourceStringData("pizza", "ピザ", 2) }; String[] expectedLines = { "module,key,value", "Japanese Foods,ramen,ラーメン", "Italian Foods,minestrone,Minestrone", "Japanese Foods,sushi,寿司", "Italian Foods,pizza,ピザ", "Italian Foods,spaghetti,スパゲッティ" }; Map<String, LanguageBundle> testDataMap = new LinkedHashMap<>(); testDataMap.put("Japanese Foods", TestUtils.createLanguageBundle(testDataJapanese)); testDataMap.put("Italian Foods", TestUtils.createLanguageBundle(testDataItalian)); MultiBundleResourceFilter filter = ResourceFilterFactory.getMultiBundleResourceFilter(MultiBundleCSVFilter.ID); try (InputStream baseStream = TestUtils.creteInputStream(baseLines); ByteArrayOutputStream outStream = new ByteArrayOutputStream()) { filter.merge(baseStream, outStream, testDataMap, new FilterOptions(Locale.JAPANESE)); TestUtils.compareLines(expectedLines, outStream.toByteArray()); } catch (IOException e) { fail(e.getMessage()); } catch (ResourceFilterException e) { fail(e.getMessage()); } }