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; }
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; }