#!/usr/bin/env python
############################################################################
#  
#  Copyright (c)2000 Fourthought, Inc.
#  http://ftsuite.com/4ODS
#
############################################################################
#
# File Name: 		4odb dig.py
#
# Documentation:	http://docs.ftsuite.com/4ODS/Tools/4odb_dig.py.html
#


#A Tool for pretty printing a 4ODS database
import Ft, sys
try:
    import readline
except ImportError:
    pass

__doc__ = """Tool to view data in a 4ODS database."""

import os, code, string

import string
import sys
from Ft.Ods import Database
from Ft.Ods.StorageManager import Extent
from Ft.Ods.Collections import CollectionBase
from Ft.Ods import Object
from Ft.Ods.PersistentObject import TupleDefinitions
td = TupleDefinitions

def ResolveName(name):
    steps = string.split(name,'.')

    for step in steps:
        pass

    o = db.lookup(steps[0])

    o = ResolveSteps(o,steps[1:],db)

    if o == None:
        raise "Unknown Name %s" % name
    Show(o)


def ResolveSteps(o,steps,db):
    if len(steps) == 0:
        return o
    if isinstance(o,Extent.Extent):
        raise "Cannot step through a collection"

    o = getattr(o,steps[0])
    return ResolveSteps(o,steps[1:],db)


def Show(obj,indent=0):
    print '  ' * indent + "Class: ",str(obj.__class__)
    if isinstance(obj,Extent.Extent):
        ShowCollection(obj,indent)
        return
    if isinstance(obj,CollectionBase.CollectionBase):
        ShowCollection(obj,indent)
        return
    ShowObject(obj,obj.__class__,indent)


def ShowObject(obj,klass,indent=0):

    for name in klass._tupleNames:
        data = klass._tupleDefinitions[name]
        if not data.get(td.RELATIONSHIP):
            print '  ' * indent + "  Attribute: " + name +  " =  " + str(getattr(obj,name))
    for rel in klass._tupleNames:
        data = klass._tupleDefinitions[rel]
        if data.get(td.RELATIONSHIP):

            if hasattr(obj,rel):
                target = getattr(obj,rel)
            else:
                target = None
            if target:
                if isinstance(target,CollectionBase.CollectionBase):
                    targetStr = "Oids %s" % str(map(lambda x:x._4ods_getId(),target))
                else:
                    targetStr = "Oid: %d" % target._4ods_getId()
            else:
                targetStr = "Nothing"
            print '  ' * indent + "  Relationship: " + rel +  " to " + targetStr



def ShowCollection(coll,indent):

    for c in coll:
        print c
        Show(c,indent+1)


def Run(options,args):

    from Ft.Ods.StorageManager import Adapters
    dbName = args['dbName']
    Adapters.g_driverName = options.get('adapter')


    global db
    db = Database.Database()
    db.open(dbName)

    console = code.InteractiveConsole({})


    tx = db.new()
    tx.begin()
    try:
        while 1:
            cmd = console.raw_input(">>> ")

            lcmd = string.strip(string.lower(cmd))

            if lcmd == 'quit':
                break
            else:
                #Resolve a name
                obj = ResolveName(cmd)

    finally:
        tx.abort()

    db.close()

    return


def Register():

    from Ft.Lib.CommandLine import Options, Command, Arguments

    cmd = Command.Command('dig',
                          'Display data in a 4ODS database.',
                          ' test',
                          __doc__,
                          function = Run,
                          arguments = [Arguments.RequiredArgument('dbName',
                                                                  'The name of the database.',
                                                                  str),
                                       ],
                          heading = """4ODS Data Digggin Tool
Version %s Copyright Fourthought, Inc 2000""" % Ft.__version__,
                          )
    return cmd
