@Override
  public MutableConfig clone() {
    final MutableConfig ret = (MutableConfig) super.clone();
    ret.theSubConfigs = new MutableConfig[theSubConfigs.length];
    ret.theListeners = new ConfigListener[0];
    ret.theSubConfigListener =
        new ConfigListener() {
          @Override
          public void configAdded(MutableConfig config) {
            ret.configAdded(config);
          }

          @Override
          public void configRemoved(MutableConfig config) {
            ret.configRemoved(config);
          }

          @Override
          public void configChanged(MutableConfig config, String previousValue) {
            ret.configChanged(config, previousValue);
          }
        };
    for (int i = 0; i < theSubConfigs.length; i++) {
      ret.theSubConfigs[i] = theSubConfigs[i].clone();
      ret.theSubConfigs[i].addListener(ret.theSubConfigListener);
    }
    return ret;
  }
 /**
  * @param key The name of the sub-configuration to store the value in
  * @param value The value to store for the given sub-configuration
  * @return This config, for chaining
  */
 public MutableConfig set(String key, String value) {
   MutableConfig config = subConfig(key);
   if (value == null) {
     if (config != null) removeSubConfig(config);
   } else {
     if (config == null) {
       config = new MutableConfig(key);
       addSubConfig(config);
     }
     config.setValue(value);
   }
   return this;
 }
 /**
  * @return The path to this configuration from the top-level config, including the top-level
  *     config. '/'-separated.
  */
 public String getPath() {
   java.util.ArrayList<MutableConfig> configPath = new java.util.ArrayList<>();
   MutableConfig config = this;
   while (config != null) {
     configPath.add(config);
     config = config.getParent();
   }
   StringBuilder ret = new StringBuilder();
   for (int i = configPath.size() - 1; i >= 0; i--) {
     ret.append(configPath.get(i).getName());
     if (i > 0) ret.append('/');
   }
   return ret.toString();
 }
 /**
  * @param config The configuration to write as XML
  * @param out The stream to write the configuration to
  * @throws java.io.IOException If an error occurs writing the XML document
  */
 public static void writeAsXml(MutableConfig config, java.io.OutputStream out)
     throws java.io.IOException {
   org.dom4j.DocumentFactory df = org.dom4j.DocumentFactory.getInstance();
   Element root = config.toXML(df);
   org.dom4j.Document doc = df.createDocument(root);
   org.dom4j.io.OutputFormat format = org.dom4j.io.OutputFormat.createPrettyPrint();
   format.setIndent("\t");
   org.dom4j.io.XMLWriter writer;
   writer = new org.dom4j.io.XMLWriter(out, format);
   writer.write(doc);
   writer.flush();
 }
 /**
  * Writes this configuration to an XML element
  *
  * @param df The document factory with which to create the element
  * @return The XML element representing this configuration
  */
 public Element toXML(org.dom4j.DocumentFactory df) {
   Element ret = df.createElement(theName);
   if (theValue != null) ret.setText(theValue);
   java.util.HashMap<String, int[]> attrs = new java.util.HashMap<String, int[]>();
   for (MutableConfig sub : theSubConfigs) {
     int[] count = attrs.get(sub.theName);
     if (count == null) {
       count = new int[1];
       attrs.put(sub.theName, count);
     }
     count[0]++;
   }
   for (MutableConfig sub : theSubConfigs) {
     if (attrs.get(sub.theName)[0] == 1
         && sub.theSubConfigs.length == 0
         && sub.theValue != null
         && sub.theValue.indexOf('\n') < 0) ret.addAttribute(sub.theName, sub.theValue);
     else ret.add(sub.toXML(df));
   }
   return ret;
 }
 /** @param sub The sub configuration to remove from this configuration */
 public void removeSubConfig(MutableConfig sub) {
   theSubConfigs = prisms.util.ArrayUtils.remove(theSubConfigs, sub);
   if (sub.theParent == this) sub.theParent = null;
   sub.removeListener(theSubConfigListener);
 }
 /**
  * @param sub The sub configuration to add to this configuration
  * @return The added config, for chaining
  */
 public MutableConfig addSubConfig(MutableConfig sub) {
   theSubConfigs = prisms.util.ArrayUtils.add(theSubConfigs, sub);
   sub.theParent = this;
   sub.addListener(theSubConfigListener);
   return sub;
 }