/**
   * Given an enricher, extracts its state for serialization.
   *
   * @deprecated since 0.7.0, see {@link #newBasicMemento(BrooklynObject)}
   */
  @Deprecated
  public static EnricherMemento newEnricherMemento(Enricher enricher) {
    BasicEnricherMemento.Builder builder = BasicEnricherMemento.builder();
    populateBrooklynObjectMementoBuilder(enricher, builder);

    // TODO persist config keys as well? Or only support those defined on policy class;
    // current code will lose the ConfigKey type on rebind for anything not defined on class.
    // Whereas entities support that.
    // TODO Do we need the "nonPersistableFlagNames" that locations use?
    Map<ConfigKey<?>, Object> config = ((AbstractEnricher) enricher).getConfigMap().getAllConfig();
    for (Map.Entry<ConfigKey<?>, Object> entry : config.entrySet()) {
      ConfigKey<?> key = checkNotNull(entry.getKey(), "config=%s", config);
      Object value = configValueToPersistable(entry.getValue());
      builder.config.put(key.getName(), value);
    }

    Map<String, Object> persistableFlags =
        MutableMap.<String, Object>builder()
            .putAll(
                FlagUtils.getFieldsWithFlagsExcludingModifiers(
                    enricher, Modifier.STATIC ^ Modifier.TRANSIENT))
            .remove("id")
            .remove("name")
            .build();
    builder.config.putAll(persistableFlags);

    return builder.build();
  }
  /**
   * Given a feed, extracts its state for serialization.
   *
   * @deprecated since 0.7.0, see {@link #newBasicMemento(BrooklynObject)}
   */
  @Deprecated
  public static FeedMemento newFeedMemento(Feed feed) {
    BasicFeedMemento.Builder builder = BasicFeedMemento.builder();
    populateBrooklynObjectMementoBuilder(feed, builder);

    // TODO persist config keys as well? Or only support those defined on policy class;
    // current code will lose the ConfigKey type on rebind for anything not defined on class.
    // Whereas entities support that.
    // TODO Do we need the "nonPersistableFlagNames" that locations use?
    Map<ConfigKey<?>, Object> config = ((AbstractFeed) feed).getConfigMap().getAllConfig();
    for (Map.Entry<ConfigKey<?>, Object> entry : config.entrySet()) {
      ConfigKey<?> key = checkNotNull(entry.getKey(), "config=%s", config);
      Object value = configValueToPersistable(entry.getValue());
      builder.config.put(key.getName(), value);
    }

    return builder.build();
  }
 protected <K> K getRequiredConfig(ConfigKey<K> key) {
   K result = config().get(key);
   if (result == null)
     throw new NullPointerException("Value required for '" + key.getName() + "' in " + this);
   return result;
 }
  public static HostAndPort getBrooklynAccessibleAddress(Entity entity, int port) {
    String host;

    // look up port forwarding
    PortForwardManager pfw = entity.getConfig(PORT_FORWARDING_MANAGER);
    if (pfw != null) {
      Collection<Location> ll = entity.getLocations();

      synchronized (BrooklynAccessUtils.class) {
        // TODO finer-grained synchronization

        for (MachineLocation machine : Iterables.filter(ll, MachineLocation.class)) {
          HostAndPort hp = pfw.lookup(machine, port);
          if (hp != null) {
            log.debug(
                "BrooklynAccessUtils found port-forwarded address {} for entity {}, port {}, using machine {}",
                new Object[] {hp, entity, port, machine});
            return hp;
          }
        }

        Maybe<SupportsPortForwarding> supportPortForwardingLoc =
            Machines.findUniqueElement(ll, SupportsPortForwarding.class);
        if (supportPortForwardingLoc.isPresent()) {
          Cidr source = entity.getConfig(MANAGEMENT_ACCESS_CIDR);
          SupportsPortForwarding loc = supportPortForwardingLoc.get();
          if (source != null) {
            log.debug(
                "BrooklynAccessUtils requesting new port-forwarding rule to access "
                    + port
                    + " on "
                    + entity
                    + " (at "
                    + loc
                    + ", enabled for "
                    + source
                    + ")");
            // TODO discuss, is this the best way to do it
            // (will probably _create_ the port forwarding rule!)
            HostAndPort hp = loc.getSocketEndpointFor(source, port);
            if (hp != null) {
              log.debug(
                  "BrooklynAccessUtils created port-forwarded address {} for entity {}, port {}, using {}",
                  new Object[] {hp, entity, port, loc});
              return hp;
            }
          } else {
            log.warn(
                "No "
                    + MANAGEMENT_ACCESS_CIDR.getName()
                    + " configured for "
                    + entity
                    + ", so cannot forward "
                    + "port "
                    + port
                    + " "
                    + "even though "
                    + PORT_FORWARDING_MANAGER.getName()
                    + " was supplied, and "
                    + "have location supporting port forwarding "
                    + loc);
          }
        }
      }
    }

    host = entity.getAttribute(Attributes.HOSTNAME);
    if (host != null) return HostAndPort.fromParts(host, port);

    throw new IllegalStateException(
        "Cannot find way to access port "
            + port
            + " on "
            + entity
            + " from Brooklyn (no host.name)");
  }
  /** @deprecated since 0.7.0; use {@link #newBasicMemento(BrooklynObject)} instead */
  @Deprecated
  public static BasicEntityMemento.Builder newEntityMementoBuilder(Entity entityRaw) {
    EntityInternal entity = (EntityInternal) entityRaw;
    BasicEntityMemento.Builder builder = BasicEntityMemento.builder();
    populateBrooklynObjectMementoBuilder(entity, builder);

    EntityDynamicType definedType = BrooklynTypes.getDefinedEntityType(entity.getClass());

    // TODO the dynamic attributeKeys and configKeys are computed in the BasicEntityMemento
    // whereas effectors are computed here -- should be consistent!
    // (probably best to compute attrKeys and configKeys here)
    builder.effectors.addAll(entity.getEntityType().getEffectors());
    builder.effectors.removeAll(definedType.getEffectors().values());

    builder.isTopLevelApp = (entity instanceof Application && entity.getParent() == null);

    Map<ConfigKey<?>, Object> localConfig = entity.getConfigMap().getLocalConfig();
    for (Map.Entry<ConfigKey<?>, Object> entry : localConfig.entrySet()) {
      ConfigKey<?> key = checkNotNull(entry.getKey(), localConfig);
      Object value = configValueToPersistable(entry.getValue());
      builder.config.put(key, value);
    }

    Map<String, Object> localConfigUnmatched =
        MutableMap.copyOf(entity.getConfigMap().getLocalConfigBag().getAllConfig());
    for (ConfigKey<?> key : localConfig.keySet()) {
      localConfigUnmatched.remove(key.getName());
    }
    for (Map.Entry<String, Object> entry : localConfigUnmatched.entrySet()) {
      String key = checkNotNull(entry.getKey(), localConfig);
      Object value = entry.getValue();
      // TODO Not transforming; that code is deleted in another pending PR anyway!
      builder.configUnmatched.put(key, value);
    }

    @SuppressWarnings("rawtypes")
    Map<AttributeSensor, Object> allAttributes = entity.getAllAttributes();
    for (@SuppressWarnings("rawtypes")
    Map.Entry<AttributeSensor, Object> entry : allAttributes.entrySet()) {
      AttributeSensor<?> key = checkNotNull(entry.getKey(), allAttributes);
      if (key.getPersistenceMode() != SensorPersistenceMode.NONE) {
        Object value = entry.getValue();
        builder.attributes.put((AttributeSensor<?>) key, value);
      }
    }

    for (Location location : entity.getLocations()) {
      builder.locations.add(location.getId());
    }

    for (Entity child : entity.getChildren()) {
      builder.children.add(child.getId());
    }

    for (Policy policy : entity.getPolicies()) {
      builder.policies.add(policy.getId());
    }

    for (Enricher enricher : entity.getEnrichers()) {
      builder.enrichers.add(enricher.getId());
    }

    for (Feed feed : entity.feeds().getFeeds()) {
      builder.feeds.add(feed.getId());
    }

    Entity parentEntity = entity.getParent();
    builder.parent = (parentEntity != null) ? parentEntity.getId() : null;

    if (entity instanceof Group) {
      for (Entity member : ((Group) entity).getMembers()) {
        builder.members.add(member.getId());
      }
    }

    return builder;
  }