package yacs.solver.fdsolver.consistency;

import yacs.domain.*;
import yacs.parser.*;

import java.util.*;

/**
 * <p>Hilfsklasse zur Beschreibung einer beliebigstelligen "Kante" für
 * Algorithmen zur Herstellung von (Hyper-)Kantenkonsistenz. Eine Kante zwischen
 * <i>n</i> Knoten entspricht einem <i>n</i>-stelligen Constraint, welches
 * <i>n</i> Constraint-Variablen beschränkt.</p>
 *
 * <p>Copyright (C) 2005  Wolfgang Runte
 * <br><br>
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * <br><br>
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * <br><br>
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
 * USA</p>
 *
 * @author Wolfgang Runte (woru@tzi.org)
 * @version YACS 0.1.1
 */
public class HyperArc {

// ********** private attributs **********

// ********** protected attributs **********

  /**
   * <code>HashMap</code> über die Knoten der Kante als "Keys"
   * (<code>String</code>) und die zugehörigen Domänen als "Values"
   * (<code>yacs.domain.Domain</code>). */
  protected HashMap nodesMap;

  /** Zugehöriger Constraint-Ausdruck. */
  protected Expression expr;

// ********** public attributs **********

// ********** private methods **********

// ********** protected methods **********

  /**
   * Benötigt eine Liste mit den Knoten der Kante (enthält Instanzen der Klasse
   * <code>String</code>) sowie den Constraint-Ausdruck, der diese Kante
   * beinhaltet. Erzeugt eine <code>HashMap</code> mit den Knoten der Kante als
   * "Keys" (<code>String</code>) und die zugehörigen Domänen als "Values"
   * (<code>yacs.domain.Domain</code>).
   * @param nodes List
   * @param expr Expression
   * @return HashMap
   */
  protected HashMap initNodesMap(List nodes, Expression expr) {
    HashMap nodesMap = new HashMap();
    String curNode;
    Iterator it = nodes.iterator();
    // Namen der Nodes mit den zugehörigen Domänen in der HashMap ablegen:
    while (it.hasNext()) {
      curNode = (String) it.next();
      nodesMap.put(curNode, this.expr.getDomain(curNode));
    }
    return nodesMap;
  }

// ********** public methods **********

  /**
   * Konstruktor -- Instantiiert die Hyperkante.
   */
  public HyperArc() {
    this.expr = null;
    this.nodesMap = null;
  }

  /**
   * Konstruktor -- Benötigt eine Liste mit den Knoten der Kante (enthält
   * Instanzen der Klasse <code>String</code>) sowie den Constraint-Ausdruck,
   * der diese Kante beinhaltet.
   */
  public HyperArc(List nodes, Expression expr) {
    this.expr = expr;
    this.nodesMap = this.initNodesMap(nodes, this.expr);
  }

  /**
   * Liefert eine "unmodifizierbare" Liste mit den Knoten der Kante (enthält
   * Instanzen der Klasse <code>String</code>).
   * @return List
   */
  public List getNodes() {
    return Collections.unmodifiableList(new LinkedList(this.nodesMap.keySet()));
  }

  /**
   * Liefert die jeweilige Domäne zum übergebenen Knoten.
   * @param node String
   * @return Domain
   */
  public Domain getDomain(String node) {
    return (Domain)this.nodesMap.get(node);
  }

  /**
   * Liefert eine "unmodifizierbare" Map über die Knoten der Kante als "Keys"
   * (<code>String</code>) und die zugehörigen Domänen als "Values"
   * (<code>yacs.domain.Domain</code>).
   * @return Map
   */
/*  public Map getNodesMap() {
    return Collections.unmodifiableMap(this.nodesMap);
  }*/

  /**
   * Liefert den Constraint-Ausdruck, zu dem diese Kante gehört.
   * @return Expression
   */
  public Expression expression() {
    return this.expr;
  }

  /**
   * Liefert die Kante als String (für Debugging).
   * @return String
   */
  public String toString() {
    return "HyperArc: " + this.nodesMap + "; Expression: " + this.expr;
  }

}
