namespace weka.associations;

class AssociatorEvaluation
{
  isA RevisionHandler;
 depend java.io.BufferedWriter;
 depend java.io.FileWriter;
 depend java.util.Enumeration;
 depend weka.core.Drawable;
 depend weka.core.Instances;
 depend weka.core.Option;
 depend weka.core.OptionHandler;
 depend weka.core.RevisionHandler;
 depend weka.core.RevisionUtils;
 depend weka.core.Utils;
 depend weka.core.converters.ConverterUtils.DataSource;
/** 
 * the result string 
 */
protected StringBuffer m_Result;

/** 
 * default constructor
 */
public AssociatorEvaluation(){
  super();
  m_Result=new StringBuffer();
}

/** 
 * Generates an option string to output on the commandline.
 * @param associator the associator to generate the string for
 * @return the option string
 */
protected static String makeOptionString(Associator associator){
  StringBuffer text;
  text=new StringBuffer();
  text.append("\nGeneral options:\n\n");
  text.append("-t <training file>\n");
  text.append("\tThe name of the training file.\n");
  text.append("-g <name of graph file>\n");
  text.append("\tOutputs the graph representation (if supported) of the associator to a file.\n");
  if (associator instanceof OptionHandler) {
    text.append("\nOptions specific to " + associator.getClass().getName().replaceAll(".*\\.","") + ":\n\n");
    Enumeration<Option> enm=((OptionHandler)associator).listOptions();
    while (enm.hasMoreElements()) {
      Option option=enm.nextElement();
      text.append(option.synopsis() + "\n");
      text.append(option.description() + "\n");
    }
  }
  return text.toString();
}

/** 
 * Evaluates an associator with the options given in an array of strings.
 * @param associatorString class of associator as a string
 * @param options the array of string containing the options
 * @throws Exception if model could not be evaluated successfully
 * @return a string describing the results
 */
public static String evaluate(String associatorString,String[] options) throws Exception {
  Associator associator;
  try {
    associator=(Associator)Class.forName(associatorString).newInstance();
  }
 catch (  Exception e) {
    throw new Exception("Can't find class with name " + associatorString + '.');
  }
  return evaluate(associator,options);
}

/** 
 * Evaluates the associator with the given commandline options and returns the evaluation string.
 * @param associator the Associator to evaluate
 * @param options the commandline options
 * @return the generated output string
 * @throws Exception if evaluation fails
 */
public static String evaluate(Associator associator,String[] options) throws Exception {
  String trainFileString="";
  String graphFileName="";
  AssociatorEvaluation eval;
  DataSource loader;
  if (Utils.getFlag('h',options)) {
    throw new Exception("\nHelp requested.\n" + makeOptionString(associator));
  }
  try {
    trainFileString=Utils.getOption('t',options);
    if (trainFileString.length() == 0) {
      throw new Exception("No training file given!");
    }
    loader=new DataSource(trainFileString);
    graphFileName=Utils.getOption('g',options);
    if (associator instanceof OptionHandler) {
      ((OptionHandler)associator).setOptions(options);
    }
    Utils.checkForRemainingOptions(options);
  }
 catch (  Exception e) {
    throw new Exception("\nWeka exception: " + e.getMessage() + "\n"+ makeOptionString(associator));
  }
  eval=new AssociatorEvaluation();
  String results=eval.evaluate(associator,new Instances(loader.getDataSet()));
  if ((associator instanceof Drawable) && (graphFileName.length() != 0)) {
    BufferedWriter writer=new BufferedWriter(new FileWriter(graphFileName));
    writer.write(((Drawable)associator).graph());
    writer.newLine();
    writer.flush();
    writer.close();
  }
  return results;
}

/** 
 * Evaluates the associator with the given commandline options and returns the evaluation string.
 * @param associator the Associator to evaluate
 * @param data the data to run the associator with
 * @return the generated output string
 * @throws Exception if evaluation fails
 */
public String evaluate(Associator associator,Instances data) throws Exception {
  long startTime;
  long endTime;
  startTime=System.currentTimeMillis();
  associator.buildAssociations(data);
  endTime=System.currentTimeMillis();
  m_Result=new StringBuffer(associator.toString());
  m_Result.append("\n=== Evaluation ===\n\n");
  m_Result.append("Elapsed time: " + (((double)(endTime - startTime)) / 1000) + "s");
  m_Result.append("\n");
  return m_Result.toString();
}

/** 
 * Tests whether the current evaluation object is equal to another evaluation object
 * @param obj the object to compare against
 * @return true if the two objects are equal
 */
@Override public boolean equals(Object obj){
  if ((obj == null) || !(obj.getClass().equals(this.getClass()))) {
    return false;
  }
  AssociatorEvaluation cmp=(AssociatorEvaluation)obj;
  String associatingResults1=m_Result.toString().replaceAll("Elapsed time.*","");
  String associatingResults2=cmp.m_Result.toString().replaceAll("Elapsed time.*","");
  if (!associatingResults1.equals(associatingResults2)) {
    return false;
  }
  return true;
}

/** 
 * returns a summary string of the evaluation with a no title
 * @return the summary string
 */
public String toSummaryString(){
  return toSummaryString("");
}

/** 
 * returns a summary string of the evaluation with a default title
 * @param title the title to print before the result
 * @return the summary string
 */
public String toSummaryString(String title){
  StringBuffer result;
  result=new StringBuffer(title);
  if (title.length() != 0) {
    result.append("\n");
  }
  result.append(m_Result);
  return result.toString();
}

/** 
 * returns the current result
 * @return the currently stored result
 * @see #toSummaryString()
 */
@Override public String toString(){
  return toSummaryString();
}

/** 
 * Returns the revision string.
 * @return the revision
 */
@Override public String getRevision(){
  return RevisionUtils.extract("$Revision: 10172 $");
}

/** 
 * A test method for this class. Just extracts the first command line argument as an associator class name and calls evaluate.
 * @param args an array of command line arguments, the first of which must bethe class name of an associator.
 */
public static void main(String[] args){
  try {
    if (args.length == 0) {
      throw new Exception("The first argument must be the class name of a kernel");
    }
    String associator=args[0];
    args[0]="";
    System.out.println(evaluate(associator,args));
  }
 catch (  Exception ex) {
    ex.printStackTrace();
    System.err.println(ex.getMessage());
  }
}
}
