package yacs.net;

import yacs.domain.*;

import java.util.*;

/**
 * <p>Container-Klasse für die Repräsentation von Lösungen eines
 * Constraint-Problems.</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 Solutions {

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

  /**
   * Liste zum Ablegen der vorhandenen Lösungen (enthält Instanzen der Klasse
   * <code>yacs.net.Solution</code>). */
  private List solutions = new LinkedList();

  /**
   * Dummy für UML-Diagramm (Borland Together).
   * @supplierCardinality 0..*
   * @clientCardinality 1
   * @link aggregation
   */
  private Solution lnkSolution;

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

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

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

  /**
   * Fügt die übergebene Lösung den vorhandenen hinzu, wenn sie nicht bereits
   * enthalten ist. Liefert <code>true</code>, wenn dies erfolgreich verlaufen
   * ist (Lösung war noch nicht vorhanden), <code>false</code> wenn nicht
   * (Lösung existierte bereits).
   * @param solution Solution
   */
  public boolean addSolution(Solution solution) {
    if (!this.containsSolution(solution)) {
      this.solutions.add(solution);
      return true;
    }
    return false;
  }

  /**
   * Liefert eine "unmodifizierbare" Liste mit den enthaltenen Lösungen
   * (Instanzen der Klassse <code>yacs.net.Solution</code>).
   * @return List
   */
  public List getSolutions() {
    return Collections.unmodifiableList(this.solutions);
  }

  /**
   * Liefert <code>true</code>, wenn Lösungen existieren, <code>false</code>
   * wenn nicht.
   * @return boolean
   */
  public boolean hasSolutions() {
    if (!this.solutions.isEmpty()) {
      return true;
    } else {
      return false;
    }
  }

  /**
   * Überprüft, ob die übergebene Lösung bereits enthalten ist
   * (<code>true</code>) oder nicht (<code>false</code>).
   * @param solution Solution
   * @return boolean
   */
  public boolean containsSolution(Solution solution) {
//    return this.solutions.contains(solution); -> funzt net ... :-(
    // Alle Lösungen durchgehen:
    Iterator it = this.solutions.iterator();
    while (it.hasNext()) {
      // Wenn identische Lösung gefunden "true" zurückgeben:
      if (solution.equals((Solution)it.next())) {
        return true;
      }
    }
    // ... ansonsten "false":
    return false;
  }

  /**
   * Generiert zu Debugging-Zwecken einen String mit den in diesem Container
   * enthaltenen Lösungen.
   * @return String
   */
  public String toString() {
    String returnString = new String();
    // Alle enthaltenen Lösungen durchgehen:
    for (int i=0; i < this.solutions.size(); i++) {
      returnString += "\n(" + (i+1) + ") " + this.solutions.get(i);
    }
    return returnString;
  }

/*
  public static void main(String[] args) {
    //
    // Test der containsSolution()-Methode ...
    //
    Solution s1 = new Solution();
    Solution s2 = new Solution();

    // Unterschiedliche Domänen-Objekte erzeugen:
    NumericFDElement value1 = new NumericFDElement(5);
    NumericFDElement value2 = new NumericFDElement(10);
    SymbolicFDElement value3 = new SymbolicFDElement("rot");
    SymbolicFDElement value4 = new SymbolicFDElement("grün");
    IntervalDomainElement value5 = new IntervalDomainElement(5,6);
    IntervalDomainElement value6 = new IntervalDomainElement(10,11);

    // ... und den Lösungen ...
    s1.addVariable("Variable1", value1);
    s1.addVariable("Variable2", value2);
    s1.addVariable("Variable3", value2);
    s1.addVariable("Variable4", value2);
    s1.addVariable("Variable5", value2);
    s1.addVariable("Variable6", value2);
    // ... hinzufügen.
    s2.addVariable("Variable1", value1);
    s2.addVariable("Variable2", value2);
    s2.addVariable("Variable3", value2);
    s2.addVariable("Variable4", value2);
    s2.addVariable("Variable5", value2);
    s2.addVariable("Variable6", value2);

    // Solutions-Container erzeugen:
    Solutions solutions = new Solutions();
    // ... und die Lösung hinzufügen:
    solutions.addSolution(s1);

    // Funktioniert nur, wenn die "Values" dieselben Objekte sind! Solutions
    // mit gleich angelegten DomainElements als "Values" ergeben false:
    System.out.println("s1.equals(s2): " + s1.equals(s2));
    System.out.println("solutions.conatainsSolution(s2): " + solutions.containsSolution(s2));

    // Versucht eine gleiche Lösung hinzuzufügen:
    System.out.println(solutions);
    solutions.addSolution(s2);
    System.out.println(solutions);
    // ... gelingt nicht. :-)
  }
*/

}
