/**
   * 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 void setManagementContext(ManagementContextInternal managementContext) {
    this.managementContext = managementContext;
    if (displayNameAutoGenerated && id != null)
      name.set(getClass().getSimpleName() + ":" + id.substring(0, Math.min(id.length(), 4)));

    Location oldParent = parent.get();
    Set<Location> oldChildren = children;
    Map<String, Object> oldConfig = configBag.getAllConfig();
    Long oldCreationTimeUtc = creationTimeUtc.get();
    String oldDisplayName = name.get();
    HostGeoInfo oldHostGeoInfo = hostGeoInfo.get();

    parent = managementContext.getStorage().getReference(id + "-parent");
    children =
        SetFromLiveMap.create(
            managementContext.getStorage().<Location, Boolean>getMap(id + "-children"));
    creationTimeUtc = managementContext.getStorage().getReference(id + "-creationTime");
    hostGeoInfo = managementContext.getStorage().getReference(id + "-hostGeoInfo");
    name = managementContext.getStorage().getReference(id + "-displayName");

    // Only override stored defaults if we have actual values. We might be in setManagementContext
    // because we are reconstituting an existing entity in a new brooklyn management-node (in which
    // case believe what is already in the storage), or we might be in the middle of creating a new
    // entity. Normally for a new entity (using EntitySpec creation approach), this will get called
    // before setting the parent etc. However, for backwards compatibility we still support some
    // things calling the entity's constructor directly.
    if (oldParent != null) parent.set(oldParent);
    if (oldChildren.size() > 0) children.addAll(oldChildren);
    if (creationTimeUtc.isNull()) creationTimeUtc.set(oldCreationTimeUtc);
    if (hostGeoInfo.isNull()) hostGeoInfo.set(oldHostGeoInfo);
    if (name.isNull()) {
      name.set(oldDisplayName);
    } else {
      displayNameAutoGenerated = false;
    }

    configBag =
        ConfigBag.newLiveInstance(
            managementContext.getStorage().<String, Object>getMap(id + "-config"));
    if (oldConfig.size() > 0) {
      configBag.putAll(oldConfig);
    }
  }
  @Override
  public void setParent(Location newParent) {
    if (newParent == this) {
      throw new IllegalArgumentException("Location cannot be its own parent: " + this);
    }
    if (newParent == parent.get()) {
      return; // no-op; already have desired parent
    }

    // TODO Should we support a location changing parent? The resulting unmanage/manage might cause
    // problems.
    if (parent.get() != null) {
      Location oldParent = parent.get();
      parent.set(null);
      ((AbstractLocation) oldParent).removeChild(this); // FIXME Nasty cast
    }
    if (newParent != null) {
      parent.set(newParent);
      ((AbstractLocation) parent.get()).addChild(this); // FIXME Nasty cast
    }
  }
 public void setDisplayName(String newName) {
   name.set(newName);
   displayNameAutoGenerated = false;
 }
 public void onManagementStarted() {
   if (displayNameAutoGenerated)
     name.set(getClass().getSimpleName() + ":" + id.substring(0, Math.min(id.length(), 4)));
   this.managed = true;
 }