@SuppressWarnings({"unchecked", "rawtypes"})
  public <T extends Enricher> T createEnricher(EnricherSpec<T> spec) {
    if (spec.getFlags().containsKey("parent")) {
      throw new IllegalArgumentException(
          "Spec's flags must not contain parent; use spec.parent() instead for " + spec);
    }

    try {
      Class<? extends T> clazz = spec.getType();

      T enricher;
      if (isNewStyleEnricher(clazz)) {
        enricher = constructEnricher(clazz);
      } else {
        enricher = constructOldStyle(clazz, MutableMap.copyOf(spec.getFlags()));
      }

      if (spec.getDisplayName() != null)
        ((AbstractEnricher) enricher).setName(spec.getDisplayName());

      if (isNewStyleEnricher(clazz)) {
        ((AbstractEnricher) enricher).setManagementContext(managementContext);
        Map<String, Object> config =
            ConfigBag.newInstance().putAll(spec.getFlags()).putAll(spec.getConfig()).getAllConfig();
        ((AbstractEnricher) enricher)
            .configure(
                MutableMap.copyOf(config)); // TODO AbstractEnricher.configure modifies the map
      }

      // TODO Can we avoid this for "new-style policies"? Should we just trust the configure()
      // method,
      // which the user may have overridden?
      // Also see InternalLocationFactory for same issue, which this code is based on.
      for (Map.Entry<ConfigKey<?>, Object> entry : spec.getConfig().entrySet()) {
        ((AbstractEnricher) enricher).setConfig((ConfigKey) entry.getKey(), entry.getValue());
      }
      ((AbstractEnricher) enricher).init();

      return enricher;

    } catch (Exception e) {
      throw Exceptions.propagate(e);
    }
  }
  @Test
  public void testServiceFailureDetectorWorksAfterRebind() throws Exception {
    origEntity.addEnricher(EnricherSpec.create(ServiceFailureDetector.class));

    // rebind
    TestApplication newApp = rebind();
    final TestEntity newEntity =
        (TestEntity) Iterables.find(newApp.getChildren(), Predicates.instanceOf(TestEntity.class));

    newApp
        .getManagementContext()
        .getSubscriptionManager()
        .subscribe(newEntity, HASensors.ENTITY_FAILED, eventListener);

    newEntity.setAttribute(TestEntity.SERVICE_UP, true);
    ServiceStateLogic.setExpectedState(newEntity, Lifecycle.RUNNING);

    // trigger the failure
    newEntity.setAttribute(TestEntity.SERVICE_UP, false);

    assertHasEventEventually(HASensors.ENTITY_FAILED, Predicates.<Object>equalTo(newEntity), null);
    assertEquals(events.size(), 1, "events=" + events);
  }