AmdJsResource extends ResourceFilter { @Override public void merge(InputStream baseStream, OutputStream outStream, LanguageBundle languageBundle, FilterOptions options) throws IOException, ResourceFilterException { CharArrayWriter caw = new CharArrayWriter(); try (InputStreamReader reader = new InputStreamReader(new BomInputStream(baseStream), "UTF-8")) { char[] buf = new char[1024]; int len; while ((len = reader.read(buf)) >= 0) { caw.write(buf, 0, len); } } char[] baseContent = caw.toCharArray(); CharArrayReader car = new CharArrayReader(baseContent); AstRoot root = new Parser().parse(car, null , 1); KeyValueVisitor visitor = new KeyValueVisitor(); root.visitAll(visitor); LinkedHashMap<String, ValueData> baseKVMap = visitor.elements; Map<String, String> kvMap = Utils.createKeyValueMap(languageBundle.getResourceStrings()); try (OutputStreamWriter writer = new OutputStreamWriter(new BufferedOutputStream(outStream), StandardCharsets.UTF_8)) { int idx = 0; for (Entry<String, ValueData> baseEntry : baseKVMap.entrySet()) { String key = baseEntry.getKey(); ValueData valData = baseEntry.getValue(); int start = valData.getStart(); int end = valData.getEnd(); if (idx < start) { writer.write(baseContent, idx, start - idx); idx = start; } String translatedValue = kvMap.get(key); if (translatedValue == null) { writer.write(baseContent, idx, end - idx); } else { char quote = baseContent[idx]; writer.write(quote); writer.write(escapeString(translatedValue, quote)); assert quote == baseContent[end - 1]; writer.write(quote); } idx = end; } if (idx < baseContent.length) { writer.write(baseContent, idx, baseContent.length - idx); } } }  @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);  }
@Test public void testMerge() throws IOException, ResourceFilterException { File tempFile; tempFile = File.createTempFile(this.getClass().getSimpleName(), ".js"); tempFile.deleteOnExit(); try (OutputStream os = new FileOutputStream(tempFile); InputStream is = new FileInputStream(MERGE_INPUT_1_FILE)) { res.merge(is, os, MERGE_BUNDLE, new FilterOptions(Locale.ENGLISH)); os.flush(); assertTrue(ResourceTestUtil.compareFiles(EXPECTED_MERGE_1_FILE, tempFile)); } tempFile = File.createTempFile(this.getClass().getSimpleName(), ".js"); tempFile.deleteOnExit(); try (OutputStream os = new FileOutputStream(tempFile); InputStream is = new FileInputStream(MERGE_INPUT_2_FILE)) { res.merge(is, os, MERGE_BUNDLE, new FilterOptions(Locale.ENGLISH)); os.flush(); assertTrue(ResourceTestUtil.compareFiles(EXPECTED_MERGE_2_FILE, tempFile)); } tempFile = File.createTempFile(this.getClass().getSimpleName(), ".js"); tempFile.deleteOnExit(); try (OutputStream os = new FileOutputStream(tempFile); InputStream is = new FileInputStream(MERGE_INPUT_3_FILE)) { res.merge(is, os, MERGE_BUNDLE, new FilterOptions(Locale.JAPANESE)); os.flush(); assertTrue(ResourceTestUtil.compareFiles(EXPECTED_MERGE_3_FILE, tempFile)); } }