package com.sleepycat.dbxml.examples.gettingStarted;

import java.io.*;
import com.sleepycat.dbxml.examples.gettingStarted.myDb;
import com.sleepycat.dbxml.examples.gettingStarted.myDbEnv;
import com.sleepycat.dbxml.examples.gettingStarted.myXmlContainer;

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

class retrieveDB
{
    
    private static String theContainer = "namespaceExampleData.dbxml";
    private static String theDB = "testBerkeleyDB";

    private static void usage()
    {

        String usageMessage = "This program retrieves data from a Berkeley DB database based on information \n";
               usageMessage += "retrieved from a document in a DB XML container. Both the DB XML container and the\n";
               usageMessage += "Berkeley DB database are stored in the same database environment. The text()\n";
               usageMessage += "value of the node found on the XML document is used as the Berkeley DB key for the\n";
               usageMessage += "sample data stored in the database.\n\n";

               usageMessage += "Before running this program, run exampleLoadContainer to pre-populate\n";
               usageMessage += "the DB XML container with the appropriate data. Then, use the 'buildDB' sample\n";
               usageMessage += "program to build the Berkeley DB database that this program requires.\n\n";

               usageMessage += "When you run this program, identify the directory where you told exampleLoadContainer\n";
               usageMessage += "to place the sample data:\n\n";

               usageMessage += "\t-h <dbenv directory>\n";

               usageMessage += "For example:\n";
               usageMessage += "\tjava com.sleepycat.dbxml.examples.gettingStarted.retrieveDB -h examplesEnvironment\n";

         System.out.println(usageMessage);
         System.exit( -1 );
    }

    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;
       myDb openedDatabase = null;
       myXmlContainer openedContainer = null;
       DbTxn txn = null;
       try
       {
            //Open a database environment
            theDBEnv = new myDbEnv(path2DbEnv);

            //Open a database in that environment
            openedDatabase = new myDb(theDB, theDBEnv );

            //Open a container in the same environment
            openedContainer = new myXmlContainer(theContainer, theDBEnv);

            //Start a transaction
            txn = theDBEnv.getDbEnv().txnBegin(null, 0);

            //Get all the vendor documents out of the container
            XmlResults results = openedContainer.getContainer().queryWithXPath(null, "/vendor", null, 0);

            //Obtain an XmlQueryContext with the result type set to values (not documents).
            XmlQueryContext resultsContext = new XmlQueryContext(XmlQueryContext.ResultValues, XmlQueryContext.Eager);
            XmlDocument document = new XmlDocument();
            while (results.next(document)) {
                //Query on the document for the salesrep's name
                XmlResults docResult = document.queryWithXPath("/vendor/salesrep/name/text()", resultsContext);

                //The result set from the document query should be of size 1. If not, the
                // document schema has changed and the query must be modified..
                if (docResult.size() != 1) {
                     throw new Exception("retrieveDB: Expected result set size to be 1, but found " + docResult.size() + " instead.");
                }

                //Pull the value out of the document query result set.
                XmlValue docValue = docResult.next();
                String theSalesRepKey = docValue.asString(null);

                //By not explicitly identifying a length for the byte array in the Dbt constructor calls,
                //  we're causing the Dbt length field to be set to the size of the byte array.
                Dbt theKey = new Dbt(theSalesRepKey.getBytes());
                Dbt theData = new Dbt();
                //Tell db to allocate on retrieval
                theData.setFlags(Db.DB_DBT_MALLOC);

                openedDatabase.getDatabase().get(txn, theKey, theData, 0);
                System.out.println("For key: " + theSalesRepKey + ", retrieved:");
                System.out.println( new String(theData.getData(), 0, theData.getSize()));
           }
           txn.commit(0);

       } catch (Exception e) {

           System.err.println("Error performing query against " + theContainer);
           System.err.println("   Message: " + e.getMessage());
           if ( txn != null ) {
             txn.abort();
           }
           throw e;

       } finally {
           if (openedContainer != null) {
              openedContainer.cleanup();
           }

           if (openedDatabase != null) {
              openedDatabase.cleanup();
           }

           if (theDBEnv != null) {
              theDBEnv.cleanup();
           }
       }

    } //End main

}
