/**
   * For Ajax Editing : adds an element or an attribute to a metadata element ([add] link).
   *
   * @param dbms
   * @param session
   * @param id
   * @param ref
   * @param name
   * @param childName
   * @return
   * @throws Exception
   */
  public synchronized Element addElementEmbedded(
      Dbms dbms, UserSession session, String id, String ref, String name, String childName)
      throws Exception {
    String schema = dataManager.getMetadataSchema(dbms, id);
    // --- get metadata from session
    Element md = getMetadataFromSession(session, id);

    // --- ref is parent element so find it
    EditLib editLib = dataManager.getEditLib();
    Element el = editLib.findElement(md, ref);
    if (el == null) throw new IllegalStateException(MSG_ELEMENT_NOT_FOUND_AT_REF + ref);

    // --- locate the geonet:element and geonet:info elements and clone for
    // --- later re-use
    Element refEl = (Element) (el.getChild(Edit.RootChild.ELEMENT, Edit.NAMESPACE)).clone();
    Element info = (Element) (md.getChild(Edit.RootChild.INFO, Edit.NAMESPACE)).clone();
    md.removeChild(Edit.RootChild.INFO, Edit.NAMESPACE);

    Element child = null;
    MetadataSchema mds = dataManager.getSchema(schema);
    if (childName != null) {
      if (childName.equals("geonet:attribute")) {
        String defaultValue = "";
        List attributeDefs = el.getChildren(Edit.RootChild.ATTRIBUTE, Edit.NAMESPACE);
        for (Object a : attributeDefs) {
          Element attributeDef = (Element) a;
          if (attributeDef != null
              && attributeDef.getAttributeValue(Edit.Attribute.Attr.NAME).equals(name)) {
            Element defaultChild =
                attributeDef.getChild(Edit.Attribute.Child.DEFAULT, Edit.NAMESPACE);
            if (defaultChild != null) {
              defaultValue = defaultChild.getAttributeValue(Edit.Attribute.Attr.VALUE);
            }
          }
        }

        Pair<Namespace, String> attInfo = parseAttributeName(name, ":", id, md, dbms, editLib);
        // --- Add new attribute with default value
        el.setAttribute(new Attribute(attInfo.two(), defaultValue, attInfo.one()));

        // TODO : add attribute should be false and del true after adding an attribute
        child = el;
      } else {
        // --- normal element
        child = editLib.addElement(schema, el, name);
        if (!childName.equals("")) {
          // --- or element
          String uChildName = editLib.getUnqualifiedName(childName);
          String prefix = editLib.getPrefix(childName);
          String ns = editLib.getNamespace(childName, md, mds);
          if (prefix.equals("")) {
            prefix = editLib.getPrefix(el.getName());
            ns = editLib.getNamespace(el.getName(), md, mds);
          }
          Element orChild = new Element(uChildName, prefix, ns);
          child.addContent(orChild);

          // --- add mandatory sub-tags
          editLib.fillElement(schema, child, orChild);
        }
      }
    } else {
      child = editLib.addElement(schema, el, name);
    }
    // --- now enumerate the new child (if not a simple attribute)
    if (childName == null || !childName.equals("geonet:attribute")) {
      // --- now add the geonet:element back again to keep ref number
      el.addContent(refEl);

      int iRef = editLib.findMaximumRef(md);
      editLib.expandElements(schema, child);
      editLib.enumerateTreeStartingAt(child, iRef + 1, Integer.parseInt(ref));

      // --- add editing info to everything from the parent down
      editLib.expandTree(mds, el);
    }
    // --- attach the info element to the child
    child.addContent(info);

    // --- attach the info element to the metadata root)
    md.addContent((Element) info.clone());

    // --- store the metadata in the session again
    setMetadataIntoSession(session, (Element) md.clone(), id);

    // Return element added
    return child;
  }