CSVFilter extends ResourceFilter { @Override public LanguageBundle parse(InputStream inStream, FilterOptions options) throws IOException, ResourceFilterException { LanguageBundleBuilder bundleBuilder = new LanguageBundleBuilder(true); CSVParser parser = CSVParser.parse(inStream, StandardCharsets.UTF_8, CSVFormat.RFC4180.withHeader("key", "value").withSkipHeaderRecord(true)); for (CSVRecord record : parser) { String key = record.get(0); String value = record.get(1); bundleBuilder.addResourceString(key, value); } return bundleBuilder.build(); }  @Override LanguageBundle parse(InputStream inStream, FilterOptions options); @Override void write(OutputStream outStream, LanguageBundle languageBundle, FilterOptions options); @Override void merge(InputStream baseStream, OutputStream outStream, LanguageBundle languageBundle,
            FilterOptions options); static final String ID; static final Type TYPE; }
@Test public void testParse() { TestResourceStringData[] expectedData = { new TestResourceStringData("msg_hello", "Hello", 1), new TestResourceStringData("msg_bye", "Bye", 2) }; ResourceFilter filter = ResourceFilterFactory.getResourceFilter(CSVFilter.ID); try (InputStream inStream = this.getClass().getResourceAsStream("/test.csv")) { LanguageBundle bundle = filter.parse(inStream, new FilterOptions(Locale.ENGLISH)); List<ResourceString> resStrings = bundle.getSortedResourceStrings(); assertEquals("Number of resource strings", expectedData.length, resStrings.size()); int idx = 0; for (ResourceString resString : resStrings) { String key = resString.getKey(); String value = resString.getValue(); int seqNum = resString.getSequenceNumber(); TestResourceStringData expected = expectedData[idx++]; assertEquals("Resource key at index " + idx, expected.key, key); assertEquals("Resource value at index " + idx, expected.value, value); assertEquals("Resource sequence number at index " + idx, expected.seq, seqNum); } } catch (IOException e) { fail(e.getMessage()); } catch (ResourceFilterException e) { fail(e.getMessage()); } }