package basics.xml.pull;

import java.io.File;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.helpers.DefaultHandler;
import basics.testing.Test;
import basics.unexpected.Failure;
import basics.unexpected.Problem;
import basics.utl.Empty;
import basics.xml.TPath;

public abstract class XParser implements XmlDataHandler
{
public static boolean verbose     = false;
SAXParser             parser      = null;
DefaultHandler        handler     = null;
File                  sourceFile  = null;
public boolean        skip0       = true; // if true, any entry or attribute
                                           // with
                                           // value=0 wil be skipped.
private String        currentPath = "";

/* ***************************************************** */
/* ******** imlement / overwrite this ****************** */
// this callback method sends the node name to the client
public abstract void start(String node);

// {
// if (verbose) System.out.println("NODE: " + node);
// }
// this callback method sends attributename and value to the client
public abstract void attribute(String name, String value);

// {
// if (isin("root/main/node/other")) { consume (name,value); }
// }
// this callback method sends the value to the client
public abstract void value(String value);// {}
// {
// if (isin("root/main/node/other")) { consume (value); }
// }
// this callback method notifies end of node

public abstract void end(String name);

// {
// System.out.println("Name: " + name);
// }
/** ***************************************************** */
/** ***************************************************** */
public XParser()
{
   try
   {
      this.handler = new CommonHandler();
      ((CommonHandler)this.handler).setDataHandler(this);
      SAXParserFactory factory = SAXParserFactory.newInstance();
      try
      {
         parser = factory.newSAXParser();
      }
      catch(Throwable t)
      {
         throw new Problem(t);
      }
   }
   catch(Exception e)
   {
      throw new Failure(e, "Parser not loaded. ");
   }
}

public XParser(File file)
{
   this();
   this.sourceFile = file;
}

public void parse(String file) throws Problem
{
   this.sourceFile = new File(file);
   parse();
}

public void parse(File file) throws Problem
{
   this.sourceFile = file;
   parse();
}

public void parse() throws Problem
{
   if(this.sourceFile == null)
   {
      return;
   }
   else
   {
      try
      {
         parser.parse(sourceFile, handler);
      }
      catch(Throwable t)
      {
         throw new Problem(t);
      }
   }
}

// attribute
public void __nextAttribute(String name, String value)
{
   if(hasValue(value))
      attribute(name, value);
}

public void __nextNode(TPath path, String name)
{
   currentPath = path.toString();
   start(name);
}

// entry
public void __nextValue(String value)
{
   if(hasValue(value))
      value(value);
}

public void __exitNode(TPath path, String name)
{
   currentPath = path.toString();
   end(name);
}

public String getCurrentPath()
{
   return currentPath;
}

public boolean is(String path)
{
   return (path).equals(currentPath);
}

public boolean isin(String path)
{
   return currentPath.startsWith(path);
}

public boolean hasValue(String v)
{
   return(!skip0 || !Empty.is(v));
}

public static void unittest()
{
   Test.printout("Abstract class - no tests.");
}
}
