public static BasicEnricherMemento.Builder newEnricherMementoBuilder(Enricher enricher) {
    BasicEnricherMemento.Builder builder = BasicEnricherMemento.builder();

    builder.type = enricher.getClass().getName();
    builder.typeClass = enricher.getClass();
    builder.id = enricher.getId();
    builder.displayName = enricher.getName();

    // 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;
  }
Exemple #2
0
  private static Map<String, Object> findMembers(Object o, Predicate<Field> fieldPredicate)
      throws IllegalArgumentException, IllegalAccessException {
    Map<String, Object> result = Maps.newLinkedHashMap();
    Class<?> clazz = (o != null) ? o.getClass() : null;

    if (o instanceof Iterable) {
      int i = 0;
      for (Object member : (Iterable) o) {
        result.put("member" + (i++), member);
      }
    } else if (o instanceof Map) {
      int i = 0;
      Map<?, ?> m = (Map<?, ?>) o;
      for (Map.Entry<?, ?> entry : m.entrySet()) {
        result.put("member" + (i++), new Entry(entry.getKey(), entry.getValue()));
      }
    } else {
      for (Field field : FlagUtils.getAllFields(clazz, fieldPredicate)) {
        field.setAccessible(true);
        String fieldName = field.getName();
        Object fieldVal = field.get(o);
        result.put(fieldName, fieldVal);
      }
    }

    return result;
  }
  /**
   * will set fields from flags. The unused configuration can be found via the {@linkplain
   * ConfigBag#getUnusedConfig()}. This can be overridden for custom initialization but note the
   * following.
   *
   * <p>if you require fields to be initialized you must do that in this method, with a guard (as in
   * FixedListMachineProvisioningLocation). you must *not* rely on field initializers because they
   * may not run until *after* this method (this method is invoked by the constructor in this class,
   * so initializers in subclasses will not have run when this overridden method is invoked.)
   */
  protected void configure(Map properties) {
    boolean firstTime = (id == null);
    if (firstTime) {
      // pick a random ID if one not set
      id =
          properties.containsKey("id")
              ? (String) properties.get("id")
              : Identifiers.makeRandomId(8);
    }
    configBag.putAll(properties);

    if (properties.containsKey(PARENT_LOCATION.getName())) {
      // need to ensure parent's list of children is also updated
      setParentLocation(configBag.get(PARENT_LOCATION));

      // don't include parentLocation in configBag, as breaks rebind
      configBag.remove(PARENT_LOCATION);
    }

    // NB: flag-setting done here must also be done in BasicLocationRebindSupport
    FlagUtils.setFieldsFromFlagsWithBag(this, properties, configBag, firstTime);

    if (!truth(name) && truth(properties.get("displayName"))) {
      // 'displayName' is a legacy way to refer to a location's name
      // FIXME could this be a GString?
      Preconditions.checkArgument(
          properties.get("displayName") instanceof String,
          "'displayName' property should be a string");
      name = (String) properties.remove("displayName");
    }
  }
  /**
   * Will set fields from flags. The unused configuration can be found via the {@linkplain
   * ConfigBag#getUnusedConfig()}. This can be overridden for custom initialization but note the
   * following.
   *
   * <p>For new-style locations (i.e. not calling constructor directly, this will be invoked
   * automatically by brooklyn-core post-construction).
   *
   * <p>For legacy location use, this will be invoked by the constructor in this class. Therefore if
   * over-riding you must *not* rely on field initializers because they may not run until *after*
   * this method (this method is invoked by the constructor in this class, so initializers in
   * subclasses will not have run when this overridden method is invoked.) If you require fields to
   * be initialized you must do that in this method with a guard (as in
   * FixedListMachineProvisioningLocation).
   */
  public void configure(Map properties) {
    assertNotYetManaged();

    boolean firstTime = !configured.getAndSet(true);

    configBag.putAll(properties);

    if (properties.containsKey(PARENT_LOCATION.getName())) {
      // need to ensure parent's list of children is also updated
      setParent(configBag.get(PARENT_LOCATION));

      // don't include parentLocation in configBag, as breaks rebind
      configBag.remove(PARENT_LOCATION);
    }

    // NB: flag-setting done here must also be done in BasicLocationRebindSupport
    FlagUtils.setFieldsFromFlagsWithBag(this, properties, configBag, firstTime);
    FlagUtils.setAllConfigKeys(this, configBag, false);

    if (properties.containsKey("displayName")) {
      name.set((String) removeIfPossible(properties, "displayName"));
      displayNameAutoGenerated = false;
    } else if (properties.containsKey("name")) {
      name.set((String) removeIfPossible(properties, "name"));
      displayNameAutoGenerated = false;
    } else if (isLegacyConstruction()) {
      name.set(getClass().getSimpleName() + ":" + id.substring(0, Math.min(id.length(), 4)));
      displayNameAutoGenerated = true;
    }

    // TODO Explicitly dealing with iso3166 here because want custom splitter rule comma-separated
    // string.
    // Is there a better way to do it (e.g. more similar to latitude, where configKey+TypeCoercion
    // is enough)?
    if (groovyTruth(properties.get("iso3166"))) {
      Object rawCodes = removeIfPossible(properties, "iso3166");
      Set<String> codes;
      if (rawCodes instanceof CharSequence) {
        codes = ImmutableSet.copyOf(Splitter.on(",").trimResults().split((CharSequence) rawCodes));
      } else {
        codes = TypeCoercions.coerce(rawCodes, Set.class);
      }
      configBag.put(LocationConfigKeys.ISO_3166, codes);
    }
  }
 public AbstractLocation(Map properties) {
   configure(properties);
   boolean deferConstructionChecks =
       (properties.containsKey("deferConstructionChecks")
           && TypeCoercions.coerce(properties.get("deferConstructionChecks"), Boolean.class));
   if (!deferConstructionChecks) {
     FlagUtils.checkRequiredFields(this);
   }
 }
  public static BasicLocationMemento.Builder newLocationMementoBuilder(Location location) {
    BasicLocationMemento.Builder builder = BasicLocationMemento.builder();

    Set<String> nonPersistableFlagNames =
        MutableMap.<String, Object>builder()
            .putAll(FlagUtils.getFieldsWithFlagsWithModifiers(location, Modifier.TRANSIENT))
            .putAll(FlagUtils.getFieldsWithFlagsWithModifiers(location, Modifier.STATIC))
            .put("id", String.class)
            .filterValues(Predicates.not(Predicates.instanceOf(ConfigKey.class)))
            .build()
            .keySet();
    Map<String, Object> persistableFlags =
        MutableMap.<String, Object>builder()
            .putAll(
                FlagUtils.getFieldsWithFlagsExcludingModifiers(
                    location, Modifier.STATIC ^ Modifier.TRANSIENT))
            .removeAll(nonPersistableFlagNames)
            .build();
    ConfigBag persistableConfig =
        new ConfigBag()
            .copy(((AbstractLocation) location).getLocalConfigBag())
            .removeAll(nonPersistableFlagNames);

    builder.type = location.getClass().getName();
    builder.typeClass = location.getClass();
    builder.id = location.getId();
    builder.displayName = location.getDisplayName();
    builder.copyConfig(persistableConfig);
    builder.locationConfig.putAll(persistableFlags);

    Location parentLocation = location.getParent();
    builder.parent = (parentLocation != null) ? parentLocation.getId() : null;

    for (Location child : location.getChildren()) {
      builder.children.add(child.getId());
    }

    return builder;
  }
  /**
   * Construct a new instance of an AbstractLocation.
   *
   * <p>The properties map recognizes the following keys:
   *
   * <ul>
   *   <li>name - a name for the location
   *   <li>parentLocation - the parent {@link Location}
   * </ul>
   *
   * Other common properties (retrieved via get/findLocationProperty) include:
   *
   * <ul>
   *   <li>latitude
   *   <li>longitude
   *   <li>displayName
   *   <li>iso3166 - list of iso3166-2 code strings
   *   <li>timeZone
   *   <li>abbreviatedName
   * </ul>
   */
  public AbstractLocation(Map properties) {
    inConstruction = true;
    _legacyConstruction = !InternalLocationFactory.FactoryConstructionTracker.isConstructing();
    if (!_legacyConstruction && properties != null && !properties.isEmpty()) {
      LOG.warn(
          "Forcing use of deprecated old-style location construction for "
              + getClass().getName()
              + " because properties were specified ("
              + properties
              + ")");
      _legacyConstruction = true;
    }

    // When one calls getConfig(key), we want to use the default value specified on *this* location
    // if it overrides the default config. The easiest way to look up all our config keys is to
    // reuse the code for Entity (and this will become identical when locations become first-class
    // entities). See {@link #getConfig(ConfigKey)}
    entityType = new EntityDynamicType((Class) getClass());

    if (_legacyConstruction) {
      LOG.warn(
          "Deprecated use of old-style location construction for "
              + getClass().getName()
              + "; instead use LocationManager().createLocation(spec)");
      if (LOG.isDebugEnabled())
        LOG.debug(
            "Source of use of old-style location construction",
            new Throwable("Source of use of old-style location construction"));

      configure(properties);

      boolean deferConstructionChecks =
          (properties.containsKey("deferConstructionChecks")
              && TypeCoercions.coerce(properties.get("deferConstructionChecks"), Boolean.class));
      if (!deferConstructionChecks) {
        FlagUtils.checkRequiredFields(this);
      }
    }

    inConstruction = false;
  }