/* This software was developed within the context of the project Metaphor for Science
	Museums (Mesmuses) in the framework of the Information Society Technology
	Programme, part of the Fifth Research And Technological Development
	Framework Programme of the European Community, under the Consortium
	Agreement dated <June 30, 2001>, between INRIA, Finsiel Spa, IMSS,
	Valoris , CSI, ICS-FORTH, ENSTB, EDW International.
*/

// Main.java

package gr.forth.ics.vrp.corevrp;

import java.io.*;
import java.util.*;
import gr.forth.ics.vrp.corevrp.parser.*;
import gr.forth.ics.vrp.corevrp.model.*;
import gr.forth.ics.vrp.corevrp.validator.*;
import gr.forth.ics.vrp.corevrp.broker.*;
import gr.forth.ics.vrp.statistics.*;
import gr.forth.ics.vrp.visualization.*;
import gr.forth.ics.vrp.vrpgui.*;

/**
 *  Main.java - Containing the main method.
 *
  * @author Karsten Tolle & Sofia Alexaki
  * @version 2.5  (30 Januar 2003)
 */
public class Main  {
	/** String containing the name of the output file. Default is standard output (if not specified). */
	private static String OutputFile;
	private String inFile;
	/** Will be used mainly by the RDF_Error.class. */
	static public parser p_all;
	/** A global error counter. */
	static public int error_counter = 0;

	/** When this option is set the lexer will print the token names and values. Default is 'false'. */
	private boolean debug = false;
	/** Flag to print textual representation of the model. Default is 'false'. */
	private boolean graph = false;
	/** Flag to generate svg graphic representation of the model. Default is 'false'. */
	private boolean svg = false;
	/** Flag to print the triples of the model. Default is 'false'. */
	private boolean statements = false;
	/** Flag to print also the triples of the Parser. Default is 'false'. */
	private boolean triples = false;
  /** Flag wether to contact to explicit stated namespace and enter all
	 * triples or not. Default is 'false'.
	 */
	private boolean fetch_all = false;
	private boolean inheritance= false;
	private boolean typeInfer= false;


	/** Flag whether to contact to namespace or not. Default is 'false'.*/
	private boolean fetch = false;
	/** Not creating the model, this means no validation and just creating the triples by the parser.*/
	private boolean only = false;
	/** Printing a feedback about the things VRP does.*/
	private boolean verbose = false;

	/** new since 8 April 2001
	 *  Duplicate links of a property are permitted
	 **/
	// private boolean duplicate = false;

	 // validation constraints
	private boolean classLoop= false;
	private boolean propertyLoop= false;
	private boolean subsetSubpropertyDomainRange = false;
	private boolean typing = false;
	private boolean sourceTargetTypes = false;

	//Define what statistics information is necessary
	private boolean[] modelStatistics = {false, false, false, false, false, false};
  private boolean timeStatistics = false;

	private boolean simple = false;
	private String svgoutput = "output.svg";
	private static boolean noerrormsg = false;

	/**
	 * HashSet containing the namespaces that should be kept in the final model
	 */
	private HashSet selectedNSURI = null;

  /**
	* VRP GUI.
	*/
	public static MyPanel gui;

  /**
	* VRP Output.
	*/
	public static Output Print = new Output();

	 /** A global warning counter. */
	public static int warning_counter = 0;

	public Main() {}


/* 	public void setinFile(String inFile) {
		this.inFile = inFile;
	}*/

 /**
  * Returns the name of the output file where are written VRP messages.
  */
	public static String getOutputFile() {
		return OutputFile;
	}

 /**
  * Sets the output file where are written VRP messages.
  */

	public void setOutputFile(String outfile) {
		OutputFile = outfile;
	}

  /**
	* Sets whether the VRP error messages will not displayed.
	* Default is 'false'
	*/
	public void setnoerrormsg(boolean b) {
		noerrormsg = b;
	}

  /**
	* Returns whether the VRP error messages will not displayed.
	*/

	public static boolean getnoerrormsg() {
		return noerrormsg;
	}

  /**
	* Enables/disables the constraint 'Class Hierarchy Loops': No loops are permitted in the subclass hierarchy.
	* Default is 'false'.
	* @see Main#setpropertyLoop(boolean) setpropertyLoop
	* @see Main#setsubsetSubpropertyDomainRange(boolean) setsubsetSubpropertyDomainRange
	* @see Main#settyping(boolean) settyping
	* @see Main#setsourceTargetTypes(boolean) setsourceTargetTypes
	* @see Main#setfetch_all(boolean) setfetch_all
	* @see Main#setinheritance(boolean) setinheritance
	*/
	public void setclassLoop(boolean b) {
		this.classLoop = b;
	}

  /**
	* Enables/disables the constraint 'Types of Resources': The resources used as RDF Classes, Properties,
	* Containers and Stataments should have been assigned the respective RDF type.
	* The XML Datatypes values should belong to the lexical space of the respective datatype.
	* Default is 'false'.
	* @see Main#setclassLoop(boolean) setclassLoop
	* @see Main#setpropertyLoop(boolean) setpropertyLoop
	* @see Main#setsubsetSubpropertyDomainRange(boolean) setsubsetSubpropertyDomainRange
	* @see Main#setsourceTargetTypes(boolean) setsourceTargetTypes
	* @see Main#setfetch_all(boolean) setfetch_all
	* @see Main#setinheritance(boolean) setinheritance
	*/
	public void settyping(boolean b) {
		this.typing = b;
	}

  /**
	* Sets whether inheritance on the domain/range of properties will be performed.
	* Default is 'false'
	*/
	public void setinheritance(boolean b) {
		this.inheritance = b;
	}

  /**
	* Sets whether inheritance on the types of objects will be performed.
   * Default is 'false'
   */
	public void setTypeInfer(boolean b) {
		this.typeInfer = b;
	}


 /**
   * Enables/disables the constraint 'Property Hierarchy Loops':
   * No loops are permitted in the subproperty hierarchy.
	* Default is 'false'.
   * @see Main#setclassLoop(boolean) setclassLoop
   * @see Main#setsubsetSubpropertyDomainRange(boolean) setsubsetSubpropertyDomainRange
	* @see Main#settyping(boolean) settyping
   * @see Main#setsourceTargetTypes(boolean) setsourceTargetTypes
   * @see Main#setfetch_all(boolean) setfetch_all
   * @see Main#setinheritance(boolean) setinheritance
   */
   	public void setpropertyLoop(boolean b) {
		this.propertyLoop = b;
	}

  /**
   * Enables/disables the constraint 'Source/Target Resources of properties':
   * The source/target values of a property should be instances of the
   * domain/range classes of the property.
   * Default is 'false'.
   * @see Main#setclassLoop(boolean) setclassLoop
	* @see Main#setpropertyLoop(boolean) setpropertyLoop
   * @see Main#setsubsetSubpropertyDomainRange(boolean) setsubsetSubpropertyDomainRange
   * @see Main#settyping(boolean) settyping
   * @see Main#setfetch_all(boolean) setfetch_all
	* @see Main#setinheritance(boolean) setinheritance
   */
  public void setsourceTargetTypes(boolean b) {
		this.sourceTargetTypes = b;
  }

  /**
   * Enables/disables the constraint Domain/Range of SubProperties: The domain/range of a property should be
   * subset of the domain/range of its superproperties.
   * Default is 'false'.
   * @see Main#setclassLoop(boolean) setclassLoop
   * @see Main#setpropertyLoop(boolean) setpropertyLoop
   * @see Main#settyping(boolean) settyping
   * @see Main#setsourceTargetTypes(boolean) setsourceTargetTypes
   * @see Main#setfetch_all(boolean) setfetch_all
   * @see Main#setinheritance(boolean) setinheritance
	*
   */
	public void setsubsetSubpropertyDomainRange(boolean b) {
		this.subsetSubpropertyDomainRange = b;
	}

  /**
   * Sets whether VRP will connect to namespaces stated in the NS declaration
   * and enter all triples or not. Default is 'false'.
   */

	public void setfetch_all(boolean b) {
		this.fetch_all = b;
	}

  /**
	* Sets whether the Lexer will print the token names and token values it creates.
   * Default is 'false'
   */

 	public void setdebug(boolean b) {
		this.debug = b;
	}

/*	public void setfetch(boolean b) {
		this.fetch = b;
	}*/

  /**
   * Sets whether the textual representation of the created RDF graph.
   * Default is 'false'
   */

 	public void setgraph(boolean b) {
		this.graph = b;
	}

  /**
	* Sets whether the svg graphic representation of the created RDFS schema.
   * Default is 'false'
   */

  public void setsvg(boolean b) {
	this.svg = b;
  }

  /**
   * Setting this option only syntactic validation will be performed and
   * no model will be created.
   * Default is 'false'
	*/

  	public void setonly(boolean b) {
		this.only = b;
	}

 /**
  * Sets the simple lexer for the syntactic validation.
  * Default is false.
  * @see gr.forth.ics.vrp.corevrp.parser.Lexer_Simple
  */
  public void setsimple(boolean b) {
		this.simple = b;
	}

  /**
   * Sets whether the triples included in the VRP model will be printed.
   * This set of triples may differ from the set of triples created
   * by the parser (see settriples(boolean) method), because the VRP model produced:
   * <UL>
	* <LI> does not contain duplicate statements </LI>
	* <LI> contains additional statements from external namespaces, if the VRP
   * have been set to connect to external namespaces (see setfetch_all(boolean))</LI>.
   * <LI>contains additional statements from inference on domain/range of subproperties (see setinheritance(boolean)).</LI></UL>
   * Default is 'false'
   * @see Main#settriples(boolean) settriples
   * @see Main#setfetch_all(boolean) setfetch_all
   * @see Main#setinheritance(boolean) setinheritance
     */

 	public void setstatements(boolean b) {
		this.statements = b;
	}

  /**
	* Sets whether the triples produced by the parser for the input
   * RDF descriptions will be printed.
   * Default is 'false'
   */

 	public void settriples(boolean b) {
		this.triples = b;
	}

  /**
	* Sets whether messages about the actions performed by the VRP will be reported.
	*/
	public void setverbose(boolean b) {
		this.verbose = b;
	}

  /**
	* Sets whether time statistics will be reported. Precisely prints time for:
	* <UL> <LI> parsing the input namespace </LI>
	* <LI> parsing the external namespaces & for inheritance on domain/range of properties
	* <LI> semantic validation
	* </UL>
	*/
  public void settimeStatistics(boolean b) {
		this.timeStatistics = b;
	}

	public void setSelectedNS(HashSet selectedNSURI) {
		this.selectedNSURI = selectedNSURI;
	}

  /**
	 * Set the desired model statistics
	 * <OL> <LI>
	 * enableModelStatistics(0, true): Prints the number of triples, RDF class,
	 * properties, containers, statements and resources found in the input file
	 * <LI>enableModelStatistics(1, true): For subclass hierarchy, prints the number
	 * of classes contained, the average/maximum number of subclasses and the
	 * average/maximum number length of the paths
	 * <LI> enableModelStatistics(2, true): similar to  enableModelStatistics(1, true)
	 * for property hierachy
	 * <LI> enableModelStatistics(3, true): Prints the number of instances per classes
	 * <LI> enableModelStatistics(4, true): Similar to enableModelStatistics(1, true)
	 * but prints the statistics for every subclass hierarchy
	 * <LI> enableModelStatistics(5, true): Similar to enableModelStatisticsenableModelStatistics(2, true)
	 * but prints the statistics for every subproperty hierarchy and not totally
	 </OL>
	 */
	public void enableModelStatistics (int i, boolean b) {
		modelStatistics[i] = b;
	}

  /**
	* Returns true if the modelStatistics option which corresponds to the integer i.
	* is enables, otherwise false
	* @see Main#enableModelStatistics(int, boolean) enableModelStatistics
	  */
	public boolean isModelStatisticsEnabled(int i) {
	  return modelStatistics[i];
	}

/*  public boolean gettimeStatistics() {
		return timeStatistics;
	}*/
	public void setsvgoutput (String out) {
	   this.svgoutput = out;
	}
	public void setsvgsize (int w, int h) {
	   SVGGenerator.setSVGSize(w, h);
	}

  /**
   * Sets the VRP GUI.
   */
	public void setGUI(MyPanel f) {
		gui = f;
	}


  /**
	 * Clear the output file and enter time of gerneration.
	 * If the <OutputFile> exists it asks for overwriting the file.
	 * The answere 'n' (no) will exit the program.
	 */
	private void clean_file(String filename) throws Exception {
		PrintWriter pw = null;
		try {
			// clear the outputfile
			File f = new File(OutputFile);
			if (f.exists()) {
				try {
					BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
					String act;
					// changed on 04.10.2000 by Karsten Tolle
					if (gui != null) {
        					((VRPPanel)gui).clean_file_request(OutputFile);
						if (! VRPPanel.clean_file) {
						    throw new Exception("Main.clean_file Exception");
						}

					} else {
					    do {
						System.out.println("Do you want to overwrite the file "+OutputFile+"? (y or n) ");
						act = in.readLine();
						if (act.startsWith("n")) throw new Exception("Main.clean_file Exception");
					    } while (! act.startsWith("y"));
					}
					// changed on 04.10.2000 by Karsten Tolle
				} catch (IOException e) {}
			}
			FileWriter fw = new FileWriter(OutputFile);
			if (!f.exists() || !f.canRead()) Print.outln("geht nicht", false);
			if (!f.canWrite()) Print.outln("Not allowed to write!", false);
			pw = new PrintWriter(fw);
			pw.println("");

			// bugfix by Olivier Corby
			pw.close();

			// enter the filename and actual date to the OutputFile
			Output put = new Output();
			Date d = new Date();
			put.out("Information about: "+filename+"\nTime of gerneration: "+d.toString()+"\n", false);
		} catch (Exception e) {
			Print.outln(e.getMessage(), false);

		}
	}

	 /**
	  * Create and start the parser and the validator.
	  */
	public Model start(String Name) {
	  // String Name = inFile;
		initVRP();
		Model out_model = new Model(true);
		parser p = null;
		RDF_Validator v = null;
		boolean valid = false;
		StringBuffer b = new StringBuffer();
		  if (verbose) Print.outln("Filename: " +Name, false);
			try {
			if (OutputFile != null) clean_file(Name); // empty the outputfile
		  //Modified

			long startParsing = System.currentTimeMillis();
			p = new parser(Name);
			setparseroptions(p);
			p_all = p;
			if (verbose) Print.outln("Parsing the file ...", false);
			if (verbose) Print.outln("", false);
			  Object result = p.parse().value;
			long endParsing = System.currentTimeMillis();
			if (only) {
				Print.outln("Only......option enabled", true);
				if (error_counter == 0)
					Print.outln("The file "+Name+" is a valid RDF-File.", true);
				else
					Print.outln("The file "+Name+" is not a valid RDF-File.", true);
				if ( timeStatistics )
					 Print.outln("Time for parsing the input file : " + ( endParsing - startParsing - p.getextParsingTime()) + " msec", true);
				return null;
			}

			long startValidation = 0 ;
			long endValidation = 0 ;
			if (verbose)
				Print.outln("Start Validation", false);
		  if (result instanceof Model) {
				out_model = (Model)result;
				out_model.setResourceRoot(fetch_all);
				out_model.castToMetaClass();
				if (typeInfer) {
				  out_model.infer();
		  }
		  out_model.solve_links();
		  startValidation = System.currentTimeMillis();
		  v = new RDF_Validator(out_model);
		  setvalidatoroptions(v);
		  //Note: change in order not mix VRP Loader. Find a way to determine
		  //Loader if we will have statistics.
		  //if (!Loader.dbvalid)
		  v.validate();
		  endValidation = System.currentTimeMillis();
		  if (! (warning_counter == 0))
			Print.outln(warning_counter+" warnings occured during processing the file "+Name, true);
		  if (error_counter == 0) {
			Print.outln("The file "+Name+" is a valid RDF-File.", true);
			valid = true;
		  } else Print.outln("The file "+Name+" is not a valid RDF-File.", true);
				error_counter = 0;
		  if ( (gui != null) && (out_model.getNamespaces().size() !=0) ) {
			  ChooseOutNamespaceDialog nsDial =	new ChooseOutNamespaceDialog(null, out_model.getNamespaces().keySet());
			  selectedNSURI = nsDial.getSelectedNS();
		  }
		  //Not all namespaces are selected
		  if ( (selectedNSURI!=null) && (selectedNSURI.size() != out_model.getNamespaces().size() ) ) {
                        //System.out.println("SELECT NAMESPACES");
			HashSet selectedNS = new HashSet();
			for (Iterator it = selectedNSURI.iterator(); it.hasNext(); ){
				 String nsURI  = (String)it.next();
				 Namespace ns = (Namespace)out_model.getNamespaces().get(nsURI);
				 if (ns != null )
					 selectedNS.add(ns);
				 else
					 Print.outln("\nThe namespace  "+ nsURI +" is not declared in the input file or you have not enabled the option external namespaces. Thus the namespace will not participate in the final output model\n", true);
			  }
			  out_model = out_model.getModelPart(selectedNS);
			  //a new valiator with the same options as v but new class_dag, property_dag
			  v = new RDF_Validator(out_model);
			  setvalidatoroptions(v);
			  v.create_class_dag();
                          v.getsubClassOfDAG().findRoots();
			  v.create_property_dag();
                          v.getsubPropertyOfDAG().findRoots();
		  }
		  if (graph) {
			  if (verbose) Print.outln("Writing the model to file "+OutputFile, false);
					out_model.dump();
		  }
		  if (statements) {
					if (verbose) Print.outln("Writing the triples of the model to file "+OutputFile, false);
					out_model.printStatements();
		  }
		  if ( timeStatistics ) {
					Print.outln("Time for parsing the input file : " + ( endParsing - startParsing - p.getextParsingTime()) + " msec", true);
					Print.outln("Time for parsing external namespaces & for inference on domain/range : " + (p.getextParsingTime() + v.getinheritTime()) + " msec\t",true);
					Print.outln("Semantic validation time : " + ( endValidation - startValidation - v.getinheritTime()) + " msec\t",true);
		  }
		  if (valid) {
				if (modelStatistics[0] || modelStatistics[1] || modelStatistics[2] || modelStatistics[3] )
					 if ( !isAllConstraintSet() )
						  Print.outln("Model statistics will be displayed only if all semantic constraints are selected", false);
					  else
						 getModelStatistics(out_model, v.getsubClassOfDAG(), v.getsubPropertyOfDAG());
				  // print SVG
				if (svg) {
				try
				{
					RDF_SemanticBroker broker = new RDF_SemanticBroker(out_model, v);
					RDF_Visualization viz = new SVGGenerator(broker);
					viz.writeToFile(svgoutput);
					Print.outln("SVG output file: "+svgoutput, true);
				} catch (Exception e) { Print.outln(e.getMessage(), false);
					e.printStackTrace();
				}
				}
				return out_model;
				}
			} else {
				Print.outln("The file "+Name+" is not a valid RDF-File.", true);
			 if (modelStatistics[0] || modelStatistics[1] || modelStatistics[2] || modelStatistics[3] )
				Print.outln("Model statistics will be displayed only if the total descriptions are valid", false);
				if ( timeStatistics ) {
				  Print.outln("Time for parsing the input file : " + ( endParsing - startParsing - p.getextParsingTime()) + " msec", true);
				  Print.outln("Time for parsing external namespaces  :" + ( p.getextParsingTime() ) + " msec\t",true);
				}
			}
		} catch (Exception e) {
			Print.outln("Error during execution: "+e.getMessage(), false);
		}
		 return null;
	}

// setting the options for the differend modules that will be used
// parser (including lexer); Model; Validator

	/**
	 * Setting all the options of the parser according to the options setted here.
	 */
	public void setparseroptions(parser p) {
		p.setonly(only);
		p.setdebug(debug);
		p.settriples(triples);
		p.setfetch_all(fetch_all);
		p.setsimple(simple);
		p.setverbose(verbose);
	}

	/**
	 * Setting all the options of the Model according to the options setted here.
	 */
	public void setmodeloptions(Model m) {
	}

	/**
	 * Setting all the options of the Validator according to the options setted here.
	 */
	public void setvalidatoroptions(RDF_Validator v) {
		v.setverbose(verbose);
		v.setgraph(graph);
		v.setclassLoop(classLoop);
		v.setpropertyLoop(propertyLoop);
		v.setpropertyLoop(propertyLoop);
		v.setsubsetSubpropertyDomainRange(subsetSubpropertyDomainRange);
	 //	v.setuniqueDefinedDomainRange(uniqueDefinedDomainRange);
		v.settyping(typing);
		v.setsourceTargetTypes(sourceTargetTypes);
		v.setinheritance(inheritance);
	}

  /**
	 * Method to set the options: count, debug, fetch, lexer, print, triples and statements.
	 */
	private void set_options(String options) {
		RDF_Error e = new RDF_Error();
		for (int i = options.length(); i>0 ; ) {
			String o = String.valueOf(options.charAt(--i));
			// Print.outln(o);
			if (o.equals("t")) triples = true;
			if (o.equals("f")) fetch = true;
			if (o.equals("a")) fetch_all = true;
			if (o.equals("d")) debug = true;
			if (o.equals("g")) graph = true;
			if (o.equals("s")) statements = true;
			if (o.equals("e")) simple = true;
			if (o.equals("o")) only =true;
			if (o.equals("v")) verbose =true;
			if (! (o.equals("t") ||
				o.equals("f") ||
				o.equals("a") ||
				o.equals("d") ||
				o.equals("g") ||
				o.equals("e") ||
				o.equals("s") ||
				o.equals("o") ||
				o.equals("v") )) {
					e.emit_error(4, 7, "", "VRP.Main.set_options");
					System.exit(0);
			}
		} // for
		// we do not want to have the flags fetch and fetch_all true at the same time
		int j = options.indexOf("a");
		int k = options.indexOf("f");
		if (j>=0 && k>=0) {
		     e.emit_error(4, 8, "The options 'a' and 'f' are not allowd together!", "VRP.Main.set_options");
		     System.exit(0);
		}
	}

   /**
    * Returns true if all the semantic constraint are selected
    */
   private boolean isAllConstraintSet() {
      boolean b = false;
      if ( classLoop && propertyLoop && subsetSubpropertyDomainRange &&
            typing && sourceTargetTypes) {
         b = true;
      }
		return b;
   }

   private void initVRP() {
      error_counter = 0 ;
      warning_counter = 0;
      setnoerrormsg(false);
   }

   void getModelStatistics(Model outModel, RDF_DAG class_dag, RDF_DAG property_dag)  {
      if (modelStatistics[0])
	      outModel.printStatistics();
		RDFModelStatistics stats = new RDFModelStatistics(outModel);
		Output out = new Output();
		if (modelStatistics[1]) {
			out.outln("\nClass Hierarchies Statistics", true);
			out.outln("---------------------------------", true);
			stats.printHierarchyStatistics(class_dag, true);
		}
		if (modelStatistics[2]) {
			out.outln("\nProperty Hierarchies Statistics", true);
			out.outln("-----------------------------------", true);
			stats.printHierarchyStatistics(property_dag, false);
		}
		if (modelStatistics[3])
			stats.printInstanceDistribution();
	}

  /**
	 * The main method.
	 */
	public static void main(String args[]) {
		// wrong use
		if (args.length == 0) {
			StringBuffer b = new StringBuffer();
			b.append("usage: java VRP.Main <filename> [<-options> [<filename>]]");
			b.append("\n\n");
			b.append(" valid options:");
			b.append("\n\n");
			b.append("\ta \tEnables the fetching of all explicit stated \n\t\tnamespaces. Should not be used together with the f option.");
			b.append("\n\n");
			b.append("\td \tForces the lexical analyser to print the \n\t\ttoken name and token value he sends to \n\t\tthe parser.  If no file is specified for \n\t\tthe output it will be printed to stdout.");
			b.append("\n\n");
			b.append("\te \tUsing a more simple lexical \n\t\tanalyser. Quicker and needs less memory.");
			b.append("\n\n");
			b.append("\tf \tEnables the validator to connect to \n\t\tnamespaces.");
			b.append("\n\n");
			b.append("\tg \tA textual representation of the model will be\n\t\tprinted. If no file is specified for the \n\t\toutput it will be printed to stdout.");
			b.append("\n\n");
			b.append("\to \tThe parser will not send the triples to \n\t\tthe model. This means we have no \n\t\tvalidation against the RDF Schema and just \n\t\tmake a syntactic checking.");
			b.append("\n\n");
			b.append("\ts \tThe triples of the model will be printed. \n\t\tIf no file is specified for the output \n\t\tit will be printed to stdout.");
			b.append("\n\n");
			b.append("\tt \tThe triples of the parser will be printed. \n\t\tIf no file is specified for the output \n\t\tit will be printed to stdout.");
			b.append("\n\n");
			b.append("\tv \tCauses VRP to print a feedback of the activities \n\t\tto stdout.");
			b.append("\n\n\n");
			b.append("\t<filename> \tChanges the default output 'stdout' to <filename>.");
			Print.outln(b.toString(), false);
			return;
		}
		// set the options
		// the options are already set to default value in the rdfparse class
		Main pav = new Main();
		String filename = args[0];
		if (args.length > 3) {
			RDF_Error e = new RDF_Error();
			e.emit_error(4, 8, "", "VRP.Main");
			return;
		}
		if (args.length > 1) { // two or more options
			String options = args[1];
			if (! options.startsWith("-")) {
				RDF_Error e = new RDF_Error();
				e.emit_error(4, 9, "", "VRP.Main");
				return;
			} else pav.set_options(options.substring(1));
		}
		if (args.length > 2) OutputFile = args[2];
		pav.start(filename);
	}

}
