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 buildDB
{
    
    private static String theContainer = "namespaceExampleData.dbxml";
    private static String theDB = "testBerkeleyDB";

    private static void usage()
    {
        String usageMessage = "This program retrieves node information from a specific set of XML \n";
               usageMessage += "documents stored in a DB XML container, and then saves relevant sample\n";
               usageMessage += "data to a Berkeley DB database. Both the DB XML container and the Berkeley\n";
               usageMessage += "DB database are stored in the same database environment. The text() value of\n";
               usageMessage += "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 += "Use the 'retrieveDB' sample program to retrieve the stored data.\n\n";

               usageMessage += "Before running this program, run exampleLoadContainer to pre-populate\n";
               usageMessage += "the DB XML container with the appropriate data.\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.buildDB -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
       {
            //Get a database environment
            theDBEnv = new myDbEnv(path2DbEnv);
            //Open a Berkeley DB Database
            openedDatabase = new myDb(theDB, theDBEnv);
            //Open a DB XML container
            openedContainer = new myXmlContainer(theContainer, theDBEnv);

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

            //Create a query context that is set to ResultValues. This allows us to retrieve
            // specific sections of a document.
            XmlQueryContext resultsContext = new XmlQueryContext(XmlQueryContext.ResultValues, XmlQueryContext.Eager);

            //We're going to perform a query using the default result type (ResultDocuments) and iterate over the
            // result set using XmlDocument
            XmlDocument document = new XmlDocument();

            //Perform the query, retrieving entire documents
            XmlResults results = openedContainer.getContainer().queryWithXPath(null, "/vendor", null, 0);

            //Iterate over the result set
            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("buildDB: Expected result set size to be 1, but found " + docResult.size() + " instead.");
                }

                //Obtain the value of the query as a string
                XmlValue docValue = docResult.next();
                String theSalesRepKey = docValue.asString(null);

                //This is the data that we're putting into the database. A real world example would probably
                //include a BLOB, such as a jpeg image of the salereps, a public key, or some other bit of
                //information that doesn't fit into the XML document schema. In our case, we'll just put in
                //a descriptive string so we can see what is going on when we retrieve this data.
                String theSalesRepData = "This is the data stored in the database for " + theSalesRepKey + ".";

                //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(theSalesRepData.getBytes());

                //Finally, write the actual data to the Berkeley DB.
                openedDatabase.getDatabase().put(txn, theKey, theData, Db.DB_NOOVERWRITE);
           }
           //This causes the write to be made permanent.
           txn.commit(0);

       } catch (Exception e) {

           System.err.println("Error performing query 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
           // we started this operation.
           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

}
