### Question:
AttributeMunger { public void transformSensorStringReplacingWithPublicAddressAndPort( final EntityAndAttribute<String> targetToUpdate, final Optional<EntityAndAttribute<Integer>> optionalTargetPort, final Iterable<? extends AttributeSensor<String>> targetsToMatch, final EntityAndAttribute<String> replacementSource) { SensorPropagaterWithReplacement mapper = new SensorPropagaterWithReplacement(targetToUpdate, false, new Function<String,String>() { @Override public String apply(String sensorVal) { if (sensorVal==null) return null; String input = targetToUpdate.get(); String replacementText = replacementSource.get(); log.debug("sensor mapper transforming address in "+targetToUpdate+", with "+replacementText+" (old value is "+input+")"); String suffix = ""; if (optionalTargetPort.isPresent()) { Integer port = optionalTargetPort.get().get(); if (port==null) { log.warn("no map-from port available for sensor mapper replacing addresses in "+targetToUpdate+ " (listening on "+optionalTargetPort+")"); return input; } suffix = ":"+port; } Map<AttributeSensor<String>, String> targetValsToMatch = Maps.newLinkedHashMap(); for (AttributeSensor<String> targetToMatch : targetsToMatch) { targetValsToMatch.put(targetToMatch, targetToUpdate.getEntity().getAttribute(targetToMatch)); } String output = input; for (String targetValToMatch : targetValsToMatch.values()) { output = replaceIfNotNull(output, targetValToMatch+suffix, replacementText); } log.debug("sensor mapper transforming address in "+targetToUpdate+": "+ "input="+input+"; output="+output+"; suffix="+suffix+ "; replacementSource="+replacementSource+ "; replacementText="+replacementText+ "; targetValsToMatch="+targetValsToMatch); return output; } }); for (AttributeSensor<String> targetToMatch : targetsToMatch) { subscribe(targetToUpdate.getEntity(), targetToMatch, mapper); } subscribe(targetToUpdate.getEntity(), targetToUpdate.getAttribute(), mapper); subscribe(replacementSource.getEntity(), replacementSource.getAttribute(), mapper); String newval = mapper.apply(targetToUpdate.get()); if (newval != null) { setAttributeIfChanged(targetToUpdate, newval); } } AttributeMunger(Entity adjunctEntity); void transformSensorStringReplacingWithPublicAddressAndPort(
            final EntityAndAttribute<String> targetToUpdate,
            final Optional<EntityAndAttribute<Integer>> optionalTargetPort,
            final Iterable<? extends AttributeSensor<String>> targetsToMatch,
            final EntityAndAttribute<String> replacementSource); static String replaceIfNotNull(String string, String searchFor, String replaceWith); static void setAttributeIfChanged(EntityAndAttribute<T> entityAndAttribute, T val); static void setAttributeIfChanged(Entity entity, AttributeSensor<T> attribute, T val);  }### Answer:
@Test public void testTransformSensorStringReplacingWithPublicAddressAndPort() throws Exception { final AttributeSensor<String> TARGET_HOSTNAME = new BasicAttributeSensor<String>(String.class, "hostname"); final AttributeSensor<String> OTHER_HOSTNAME = new BasicAttributeSensor<String>(String.class, "otherhostname"); final AttributeSensor<Integer> TARGET_PORT = new BasicAttributeSensor<Integer>(Integer.class, "target.port"); final AttributeSensor<String> ENDPOINT = new BasicAttributeSensor<String>(String.class, "endpoint"); final AttributeSensor<String> PUBLIC_ENDPOINT = new BasicAttributeSensor<String>(String.class, "publicEndpoint"); AttributeMunger munger = new AttributeMunger(app); munger.transformSensorStringReplacingWithPublicAddressAndPort( new EntityAndAttribute<String>(app, ENDPOINT), Optional.of(new EntityAndAttribute<Integer>(app, TARGET_PORT)), ImmutableList.of(TARGET_HOSTNAME, OTHER_HOSTNAME), new EntityAndAttribute<String>(app, PUBLIC_ENDPOINT)); app.sensors().set(TARGET_HOSTNAME, "myprivatehostname"); app.sensors().set(TARGET_PORT, 1234); app.sensors().set(ENDPOINT, "PREFIX: app.sensors().set(PUBLIC_ENDPOINT, "mypublichostname:5678"); EntityAsserts.assertAttributeEqualsEventually(app, ENDPOINT, "PREFIX: }