private static Object[] prepareArgsForEffectorFromMap(Effector<?> eff, Map m) { m = Maps.newLinkedHashMap(m); // make editable copy List newArgs = Lists.newArrayList(); int newArgsNeeded = eff.getParameters().size(); boolean mapUsed = false; for (int index = 0; index < eff.getParameters().size(); index++) { ParameterType<?> it = eff.getParameters().get(index); Object v; if (truth(it.getName()) && m.containsKey(it.getName())) { // argument is in the map v = m.remove(it.getName()); } else if (it instanceof BasicParameterType && ((BasicParameterType) it).hasDefaultValue()) { // finally, default values are used to make up for missing parameters v = ((BasicParameterType) it).getDefaultValue(); } else { throw new IllegalArgumentException( "Invalid arguments (missing argument " + it + ") for effector " + eff + ": " + m); } newArgs.add(TypeCoercions.coerce(v, it.getParameterClass())); newArgsNeeded--; } if (newArgsNeeded > 0) throw new IllegalArgumentException( "Invalid arguments (missing " + newArgsNeeded + ") for effector " + eff + ": " + m); return newArgs.toArray(new Object[newArgs.size()]); }
@SuppressWarnings("unchecked") private Object coerce(Object v) { if (v != PollConfig.UNSET) { return TypeCoercions.coerce(v, sensor.getType()); } else { return v; } }
public AbstractLocation(Map properties) { configure(properties); boolean deferConstructionChecks = (properties.containsKey("deferConstructionChecks") && TypeCoercions.coerce(properties.get("deferConstructionChecks"), Boolean.class)); if (!deferConstructionChecks) { FlagUtils.checkRequiredFields(this); } }
@Override public <T> T getConfig(ConfigKey<T> key, T defaultValue) { if (!containsKey(key.getName())) { if (defaultValue != null) return defaultValue; return key.getDefaultValue(); } Object value = get(key.getName()); if (value == null) return null; // no evaluation / key extraction here return TypeCoercions.coerce(value, key.getType()); }
@SuppressWarnings("unchecked") protected void setSensor(Object v) { if (v == FeedConfig.UNCHANGED) { // nothing } else if (v == FeedConfig.REMOVE) { ((EntityInternal) entity).removeAttribute(sensor); } else if (sensor == FeedConfig.NO_SENSOR) { // nothing } else { entity.setAttribute(sensor, TypeCoercions.coerce(v, sensor.getType())); } }
/** * 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); } }
protected void unmarshalStringKey( HierarchicalStreamReader reader, UnmarshallingContext context, Map map, String key) { String type = reader.getAttribute("type"); Object value; if (type == null && reader.hasMoreChildren()) { reader.moveDown(); value = readItem(reader, context, map); reader.moveUp(); } else { Class typeC = type != null ? mapper().realClass(type) : String.class; try { value = TypeCoercions.coerce(reader.getValue(), typeC); } catch (Exception e) { log.warn("FAILED to coerce " + reader.getValue() + " to " + typeC + ": " + e); throw Exceptions.propagate(e); } } map.put(key, value); }
/** * 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; }
/** * attempt to resolve the given value as the given type, waiting on futures, submitting if * necessary, and coercing as allowed by TypeCoercions; contextMessage (optional) will be * displayed in status reports while it waits (e.g. the name of the config key being looked up) */ @SuppressWarnings({"unchecked", "rawtypes"}) public static <T> T resolveValue( Object v, Class<T> type, ExecutionContext exec, String contextMessage) throws ExecutionException, InterruptedException { // if the expected type is a closure or map and that's what we have, we're done (or if it's // null); // but not allowed to return a future or DeferredSupplier as the resolved value if (v == null || (type.isInstance(v) && !Future.class.isInstance(v) && !DeferredSupplier.class.isInstance(v))) return (T) v; try { // if it's a task or a future, we wait for the task to complete if (v instanceof Task) { // if it's a task, we make sure it is submitted // (perhaps could run it here? ... tbd) if (!((Task) v).isSubmitted()) { exec.submit((Task) v); } } if (v instanceof Future) { final Future<?> vfuture = (Future<?>) v; // including tasks, above if (!vfuture.isDone()) { final AtomicReference<Object> vref = new AtomicReference<Object>(v); withBlockingDetails( "Waiting for " + (contextMessage != null ? contextMessage + ", " : "") + v, new Callable<Void>() { public Void call() throws Exception { vref.set(vfuture.get()); return null; } }); v = vref.get(); } else { v = vfuture.get(); } } else if (v instanceof DeferredSupplier<?>) { v = ((DeferredSupplier<?>) v).get(); } else if (v instanceof Map) { // and if a map or list we look inside Map result = Maps.newLinkedHashMap(); for (Map.Entry<?, ?> entry : ((Map<?, ?>) v).entrySet()) { result.put( entry.getKey(), resolveValue( entry.getValue(), type, exec, (contextMessage != null ? contextMessage + ", " : "") + "map entry " + entry.getKey())); } return (T) result; } else if (v instanceof List) { List result = Lists.newArrayList(); int count = 0; for (Object it : (List) v) { result.add( resolveValue( it, type, exec, (contextMessage != null ? contextMessage + ", " : "") + "list entry " + count)); count++; } return (T) result; } else { return TypeCoercions.coerce(v, type); } } catch (Exception e) { throw new IllegalArgumentException( "Error resolving " + (contextMessage != null ? contextMessage + ", " : "") + v + ", in " + exec + ": " + e, e); } return resolveValue(v, type, exec, contextMessage); }