// file      : examples/cxx/tree/library/driver.cxx
// author    : Boris Kolpackov <boris@codesynthesis.com>
// copyright : not copyrighted - public domain

#include <memory>   // std::auto_ptr
#include <iostream>

#include "library.hxx"

using std::cerr;
using std::endl;

int
main (int argc, char* argv[])
{
  if (argc != 2)
  {
    cerr << "usage: " << argv[0] << " library.xml" << endl;
    return 1;
  }

  try
  {
    using namespace library;

    // Read in the file.
    //
    std::auto_ptr<catalog> c (catalog_ (argv[1]));


    // Let's print what we've got.
    //
    for (catalog::book::const_iterator bi (c->book ().begin ());
         bi != c->book ().end ();
         ++bi)
    {
      cerr << endl
           << "ID           : " << bi->id () << endl
           << "ISBN         : " << bi->isbn () << endl
           << "Title        : " << bi->title () << endl
           << "Genre        : " << bi->genre () << endl;

      for (book::author::const_iterator ai (bi->author ().begin ());
           ai != bi->author ().end ();
           ++ai)
      {
        cerr << "Author       : " << ai->name () << endl;
        cerr << "  Born       : " << ai->born () << endl;

        if (ai->died ())
          cerr << "  Died       : " << *ai->died () << endl;

        if (ai->recommends ())
          cerr << "  Recommends : " << (*ai->recommends ())->title () << endl;
      }

      cerr  << "Available    : " << std::boolalpha << bi->available () << endl;
    }


    // Now we are going to modify in-memory representation and serialize it
    // back to XML.
    //

    catalog::book::container& bc (c->book ());


    // Get rid of all unavailable books.
    //
    for (catalog::book::iterator bi (bc.begin ()); bi != bc.end ();)
    {
      if (!bi->available ())
        bi = bc.erase (bi);
      else
        ++bi;
    }


    // Insert a new book.
    //
    book b (679776443,            // ISBN
            title ("Dead Souls"), // Title
            genre::philosophy,    // Genre
            "DS");                // ID

    b.author ().push_back (author ("Nikolai Gogol", "1809-03-31"));

    bc.insert (bc.begin (), b);


    // Because we removed all unavailable books, some IDREFs might be
    // broken. Let's fix this.
    //
    for (catalog::book::iterator bi (bc.begin ()); bi != bc.end (); ++bi)
    {
      for (book::author::iterator ai (bi->author ().begin ());
           ai != bi->author ().end ();
           ++ai)
      {
        if (author::recommends::container& c = ai->recommends ())
        {
          author::recommends::type& ref (*c);
          if (!ref)
            c.reset ();
        }
      }
    }


    // Prepare namespace mapping and schema location information.
    //
    xml_schema::namespace_infomap map;

    map["lib"].name = "http://www.codesynthesis.com/library";
    map["lib"].schema = "library.xsd";


    // Write it out.
    //
    catalog_ (std::cout, *c, map);
  }
  catch (const xml_schema::exception& e)
  {
    cerr << e << endl;
    return 1;
  }
}
