package com.sleepycat.dbxml.examples.gettingStarted;

import java.io.*;

import com.sleepycat.dbxml.examples.gettingStarted.myDbEnv;
import com.sleepycat.dbxml.examples.gettingStarted.myXmlContainer;

import com.sleepycat.dbxml.*;
import com.sleepycat.db.*;

class modifyDocument
{
    
    private static String theContainer = "namespaceExampleData.dbxml";
    private static void usage()
    {
	String usageMessage = "\nThis program modifies documents found in a DBXML container.\n";
	        usageMessage += "You should run exampleLoadContainer before running this example.\n";
                usageMessage += "You are only required to pass this command the path location of the\n";
                usageMessage += "database environment that you specified when you loaded the examples data:\n\n";
                usageMessage += "\t-h <dbenv directory>\n";
                usageMessage += "For example:\n";
                usageMessage += "\tjava com.sleepycat.dbxml.examples.gettingStarted.modifyDocument -h examplesEnvironment\n";
         System.out.println(usageMessage);
         System.exit( -1 );
    }

    // display documents matching the query
    private static void dumpDocuments(DbTxn txn, XmlContainer container, 
				      XmlQueryExpression expression) throws Throwable
    {
	XmlResults results = container.queryWithXPath(txn, expression, 0);
	System.out.println("Found " + results.size() + " documents matching the expression '" + 
			   expression.getXPathQuery() + ". ");
	XmlDocument document = new XmlDocument();
	while( results.next(document) ) {
	    String docString =document.getContentAsString();
	    System.out.println("Document content: \n" + docString);
	}
    }

    public static void main(String args[]) throws Throwable
    {
     File path2DbEnv = null;
       for(int i = 0; i < args.length; ++i) 
       {
            if (args[i].startsWith("-")) {
               switch(args[i].charAt(1)) {
                    case 'h':
                         path2DbEnv = new File( args[++i] );
                         break;
                    default:
                    usage();
               }
            } 
       }


       if (path2DbEnv == null || ! path2DbEnv.isDirectory()) {
            usage();
       }


       myDbEnv theDBEnv = null;
       myXmlContainer openedContainer = null;
       DbTxn txn = null;
       theDBEnv = new myDbEnv(path2DbEnv);
       openedContainer = new myXmlContainer(theContainer, theDBEnv);
       
       //Create a context and declare the namespaces
       XmlQueryContext context = new XmlQueryContext(XmlQueryContext.ResultDocumentsAndValues, XmlQueryContext.Eager);
       context.setNamespace( "fruits", "http://groceryItem.dbxml/fruits");
       context.setNamespace( "vegetables", "http://groceryItem.dbxml/vegetables");
       context.setNamespace( "desserts", "http://groceryItem.dbxml/desserts");
       
       String query = "/fruits:item/product[text() = 'Zapote Blanco']";
       XmlQueryExpression expression = openedContainer.getContainer().parseXPathExpression(null, query, context);
       
       System.out.println("Updating document for the expression: '" + query + "' ");
       System.out.println("Return to continue: ");
       System.in.read();
       
       // print the document(s) to be updated -- those that describe Zapote Blanco (a fruit)
       // The document strings are only being printed to show before/after results.
       // Most modification programs would not perform the additional queries.
       dumpDocuments(txn, openedContainer.getContainer(), expression);
       
       System.out.println("About to update the document(s) above.\n" +
			  "Look for a new element after the target " +
			  "element, named 'description' ...\n" +
			  "Return to continue: ");
       System.in.read();
       
       try {
	
	   //Get a transaction
	   txn = theDBEnv.getDbEnv().txnBegin(null, 0);
	   
	   // the modification is a new element in the target node, called "descripton,
	   // which goes immediately after the <product> element.
	   // if this program is run more than once, and committed, additional
	   // identical elements are added.  It is easy to modify this program
	   // to change the modification.
	   XmlModify modify = new XmlModify(expression, XmlModify.InsertAfter, XmlModify.Element, "description", "very nice", 0);
	   openedContainer.getContainer().modifyDocument(txn, modify, null, 0);
	   System.out.println("Peformed " + modify.getNumModifications() + " modification operations");
       } catch(Exception e) {
           System.err.println("Error performing document modification against " + theContainer);
           System.err.println("   Message: " + e.getMessage());
           // In the event of an error, we abort the operation
           // The database is left in the same state as it was in before
           // we started this operation.
           if ( txn != null ) {
              txn.abort();
           }
           throw e;
	}
	// print the modified documents
	dumpDocuments(txn, openedContainer.getContainer(), expression);
	
	System.out.println("If committed, this program will add a new element each time it is run.\n" +
			   "Press 'c' to commit this change:");
	int c = System.in.read();
	if (c == 'c' || c =='C')
		txn.commit(0);
	else
		txn.abort();
       }
}
