/**
   * The default implementation redefines all children as well, delegating to the {@link
   * #redefineAdded(IRedefinable, IRedefiner)} method if the replacement has a child not present in
   * this {@link IRedefinable}.
   */
  @Override
  public void redefine(IRedefinable replacement, IRedefiner redefiner) {
    if (replacement != null && !Util.equals(replacement.key(), key())) {
      throw new IllegalArgumentException("Internal error: key mismatch");
    }
    if (redefiner != null) {
      redefiner.changed(this, replacement);
    }
    HashSet<String> redefined = new HashSet();
    for (IRedefinable originalChild : getChildren()) {
      String key = originalChild.key();
      IRedefinable replacementChild = replacement.getChild(key);
      if (replacementChild != null) {
        replacementChild.redefine(originalChild, redefiner);
        redefined.add(key);
      } else {
        redefiner.deleted(originalChild);
      }
    }

    for (IRedefinable replaceChild : replacement.getChildren()) {
      if (!redefined.contains(replaceChild.key())) {
        redefiner.added(replaceChild);
      }
    }
  }
  @Override
  public boolean isPermissionRequested(String key) {
    if (key == null) {
      return false;
    }

    return requestedPermissions.contains(key) || isPermissionRequested(Util.getParentKey(key));
  }
 @Override
 public ITargetPhone load(IMemento memento, String name) {
   String addr = memento.getString("addr");
   Integer portInt = memento.getInteger("port");
   int port = portInt == null ? -1 : portInt.intValue();
   BTTargetPhone newPhone = new BTTargetPhone(name.toCharArray(), Util.fromBase16(addr), port);
   return newPhone;
 }
  private void addAvailablePermission(String permission) {
    String parent = Util.getParentKey(permission);
    if (parent == null) {
      parent = ROOT;
    }
    Set<String> lookupSet = availablePermissionLookup.get(parent);
    if (lookupSet == null) {
      lookupSet = new TreeSet<String>();
      availablePermissionLookup.put(parent, lookupSet);
    }

    lookupSet.add(permission);
  }
  @Override
  public boolean store(ITargetPhone aPhone, IMemento memento) {
    if (aPhone instanceof BTTargetPhone) {
      BTTargetPhone phone = (BTTargetPhone) aPhone;
      String addr = Util.toBase16(phone.getAddressAsBytes());
      int port = phone.getPort();

      memento.putString("addr", addr);
      memento.putInteger("port", phone.getPort());
      return true;
    } else {
      return false;
    }
  }
  private void setRequestedPermission(String requested, boolean set, boolean setSubPermissions) {
    if (requested == null) {
      return;
    }

    if (set) {
      requestedPermissions.add(requested);
      if (setSubPermissions) {
        List<String> subPermissions = getAvailablePermissions(requested);
        requestedPermissions.addAll(subPermissions);
      }
    } else {
      requestedPermissions.remove(requested);
      if (setSubPermissions) {
        List<String> subPermissions = getAvailablePermissions(requested);
        requestedPermissions.removeAll(subPermissions);
      }
    }

    String parentPermission = Util.getParentKey(requested);
    setRequestedPermission(parentPermission, allSubPermissionsSet(parentPermission), false);
    save();
  }