/*
 * This file is released under terms of BSD license
 * See LICENSE file for more information
 */

package cx2x.xcodeml.xnode;

import org.w3c.dom.Element;
import org.w3c.dom.Node;

import java.util.Collection;
import java.util.Hashtable;

import cx2x.xcodeml.helper.*;

/**
 * The XdeclTable represents the typeTable (5.2) element in XcodeML intermediate
 * representation.
 *
 * Elements: ( varDecl | FstructDecl | externDecl | FuseDecl | FuseOnlyDecl
 *            | FinterfaceDecl | FnamelistDecl | FequivalenceDecl
 *            | FcommonDecl )*
 *
 * - Optional:
 *   - varDecl
 *   - FstructDecl
 *   - externDecl
 *   - FuseDecl
 *   - FuseOnlyDecl
 *   - FinterfaceDecl
 *   - FnamelistDecl
 *   - FequivalenceDecl
 *   - FcommonDecl
 *
 * @author clementval
 */

public class XdeclTable extends Xnode {

  private final Hashtable<String, Xdecl> _table;

  /**
   * Element standard ctor. Pass the base element to the base class and read
   * inner information (elements and attributes).
   * @param baseElement The root of the element.
   */
  public XdeclTable(Element baseElement){
    super(baseElement);
    _table = new Hashtable<>();
    readTable();
  }

  /**
   * Read the declaration table.
   */
  private void readTable(){
    Node crtNode = _baseElement.getFirstChild();
    while(crtNode != null){
      if (crtNode.getNodeType() == Node.ELEMENT_NODE) {
        Element element = (Element)crtNode;

        switch (element.getTagName()){
          case Xname.VAR_DECL:
            Xdecl varDecl = new Xdecl(element);
            _table.put(varDecl.find(Xcode.NAME).getValue(), varDecl);
            break;
          case Xname.F_USE_DECL:
            Xdecl useDecl = new Xdecl(element);
            _table.put(useDecl.getAttribute(Xattr.NAME), useDecl);
            break;

          // TODO read FstructDecl elements
          // TODO read externDecl elements
          // TODO read FuseOnlyDecl elements
          // TODO read FinterfaceDecl elements
          // TODO read FnamelistDecl elements
          // TODO read FequivalenceDecl elements
          // TODO read FcommonDecl elements

        }
      }
      crtNode = crtNode.getNextSibling();
    }
  }

  /**
   * Replace a declaration in the table.
   * @param decl The new declaration to be inserted.
   * @param name Name describing the declaration in the table.
   */
  public void replace(Xdecl decl, String name){
    Xdecl oldDecl = _table.get(name);
    if(oldDecl == null){
      appendToChildren(decl, false);
    } else {
      XnodeUtil.insertAfter(oldDecl, decl);
      oldDecl.delete();
    }
  }

  /**
   * Add a new declaration.
   * @param decl The new declaration object.
   */
  public void add(Xdecl decl){
    _baseElement.appendChild(decl.cloneNode());
    _table.put(decl.find(Xcode.NAME).getValue(), decl);
  }

  /**
   * Get a specific declaration based on its name.
   * @param key The name of the declaration to be returned.
   * @return A XvarDecl object if key is found. Null otherwise.
   */
  public Xdecl get(String key){
    if(_table.containsKey(key)) {
      return _table.get(key);
    }
    return null;
  }

  /**
   * Get all elements in the table.
   * @return All elements stored in the table.
   */
  public Collection<Xdecl> getAll(){
    return _table.values();
  }

  /**
   * Get the number of declarations in the table.
   * @return The number of declarations in the table.
   */
  public int count(){
    return _table.size();
  }

  /**
   * Check if a name is already present in the declaration table.
   * @param name String value of the name to check.
   * @return True if the name is already in the table. False otherwise.
   */
  public boolean contains(String name){
    return _table.containsKey(name);
  }


  @Override
  public XdeclTable cloneObject() {
    Element clone = (Element)cloneNode();
    return new XdeclTable(clone);
  }
}

@@ -198,46 +198,9 @@
 til.
-Collection;%0Aimport java.util.Hashtable
+*
 ;%0A%0Ai
@@ -3248,32 +3248,927 @@
 .values();%0A  %7D%0A%0A
+  /**%0A   * Get all declarations of a specific kind of elements.%0A   * @param decl Kind of elements to return.%0A   * @return A list of all declarations of this kind.%0A   */%0A  public List%3CXdecl%3E getAll(Xcode decl)%7B%0A    switch (decl) %7B%0A      case VARDECL:%0A      case FUSEDECL:%0A      case FUSEONLYDECL:%0A      case FSTRUCTDECL:%0A      case EXTERNDECL:%0A      case FINTERFACEDECL:%0A      case FNAMELISTDECL:%0A      case FEQUIVALENCEDECL:%0A      case FCOMMONDECL:%0A        Iterator%3CMap.Entry%3CString, Xdecl%3E%3E it = _table.entrySet().iterator();%0A        List%3CXdecl%3E decls = new ArrayList%3C%3E();%0A        while(it.hasNext())%7B%0A          Map.Entry%3CString, Xdecl%3E entry = it.next();%0A          if(entry.getValue().Opcode() == decl)%7B%0A            decls.add(entry.getValue());%0A          %7D%0A        %7D%0A        return decls;%0A      default:%0A        throw new IllegalArgumentException(%22Not a member of the decl table%22);%0A    %7D%0A  %7D%0A%0A
   /**%0A   * Get t

Add getAll(Xcode decl)