### Question:
FeatureServiceImpl { private FeatureExtension[] mergeExtensions(Feature f1, Feature f2, MergeContext ctx) { Map<String,FeatureExtension> extensions = new HashMap<>(f1.getExtensions()); Map<String,FeatureExtension> addExtensions = new HashMap<>(); for (Map.Entry<String,FeatureExtension> exEntry : f2.getExtensions().entrySet()) { String key = exEntry.getKey(); FeatureExtension newEx = exEntry.getValue(); FeatureExtension orgEx = extensions.get(key); if (orgEx != null) { FeatureExtension resEx = ctx.handleExtensionConflict(f1, orgEx, f2, newEx); if (!resEx.equals(orgEx)) { extensions.remove(key); addExtensions.put(key, resEx); } } else { addExtensions.put(key, newEx); } } extensions.putAll(addExtensions); return extensions.values().toArray(new FeatureExtension[] {}); }  BuilderFactory getBuilderFactory(); Feature readFeature(Reader jsonReader); void writeFeature(Feature feature, Writer jsonWriter); Feature mergeFeatures(ID targetID, Feature f1, Feature f2, MergeContext ctx);  }### Answer:
@Test public void testMergeExtensions() throws IOException { BuilderFactory bf = Features.getBuilderFactory(); URL res1 = getClass().getResource("/features/test-exfeat1.json"); Feature f1; try (Reader r = new InputStreamReader(res1.openStream())) { f1 = Features.readFeature(r); } URL res2 = getClass().getResource("/features/test-exfeat2.json"); Feature f2; try (Reader r = new InputStreamReader(res2.openStream())) { f2 = Features.readFeature(r); } MergeContext ctx = bf.newMergeContextBuilder() .extensionConflictHandler((cf1, e1, cf2, e2) -> new ExtensionBuilderImpl(e1.getName(), e1.getType(), e1.getKind()) .addText(e1.getText()) .addText(e2.getText()) .build()) .build(); ID tid = new ID("g", "a", "1.2.3"); Feature f3 = Features.mergeFeatures(tid, f1, f2, ctx); Map<String, FeatureExtension> extensions = f3.getExtensions(); assertEquals(3, extensions.size()); FeatureExtension txtEx = extensions.get("my-text-ex"); assertEquals("ABCDEF", txtEx.getText()); assertEquals(FeatureExtension.Kind.OPTIONAL, txtEx.getKind()); assertEquals(FeatureExtension.Type.TEXT, txtEx.getType()); FeatureExtension artEx = extensions.get("my-art-ex"); assertEquals(FeatureExtension.Kind.MANDATORY, artEx.getKind()); assertEquals(FeatureExtension.Type.ARTIFACTS, artEx.getType()); List<ID> artifacts = artEx.getArtifacts(); assertEquals(2, artifacts.size()); assertTrue(artifacts.contains(new ID("g", "a", "1"))); assertTrue(artifacts.contains(new ID("g", "a", "2"))); FeatureExtension jsonEx = extensions.get("my-json-ex"); assertEquals(FeatureExtension.Kind.TRANSIENT, jsonEx.getKind()); assertEquals(FeatureExtension.Type.JSON, jsonEx.getType()); assertEquals("{\"foo\":[1,2,3]}", jsonEx.getJSON()); }