Source

jython-db4o / db4o / db4o.py

Full commit
'''Lowlevel db4o access, returning native db4o objects
requres: db4o jar in the classpath
'''
__author__ = 'Sean Summers <SeanSummers@gmail.com>'

BLACKLIST = ('java.', 'com.db4o.')

import com.db4o.config.ConfigScope
import com.db4o.Db4oEmbedded.newConfiguration
import com.db4o.Db4oEmbedded.openFile

def readwriteConfiguration():
    ''' create a read write DB4O configuration object (to feed db()) '''
    config = com.db4o.Db4oEmbedded.newConfiguration()
    cf = config.file()
    cf.readOnly(False)
    cf.lockDatabaseFile(True)
    cf.recoveryMode(True)
    try:
        cf.generateCommitTimestamps(True) # >=8.0
    except AttributeError:
        cf.generateVersionNumbers(com.db4o.config.ConfigScope.GLOBALLY)   # <8.0
    cf.generateUUIDs(com.db4o.config.ConfigScope.GLOBALLY)
    co = config.common()
    co.callbacks(False)
    co.callConstructors(False) ## ??
    co.detectSchemaChanges(True)
    co.testConstructors(False)
    try: # >=8.0
        cid = config.idSystem()
        cid.useStackedBTreeSystem()
    except:
        pass
    return config

def readonlyConfiguration():
    ''' create a read only DB4O configuration object (to feed db()) '''
    config = com.db4o.Db4oEmbedded.newConfiguration()
    cf = config.file()
    cf.readOnly(True)
    cf.lockDatabaseFile(False)
    cf.recoveryMode(True)
    try:
        cf.generateCommitTimestamps(True) # >=8.0
    except AttributeError:
        cf.generateVersionNumbers(com.db4o.config.ConfigScope.GLOBALLY)   # <8.0
    cf.generateUUIDs(com.db4o.config.ConfigScope.GLOBALLY)
    co = config.common()
    co.callbacks(False)
    co.callConstructors(False) ## ??
    co.detectSchemaChanges(False)
    co.testConstructors(False)
    try: # >=8.0
        cid = config.idSystem()
        cid.useStackedBTreeSystem()
    except:
        pass
    return config

def db(db4ofilename, db4oConfig = None):
    ''' return db4o container for a file, optionally with a configuration (readonly, if not provided)
        db4o container has the following:
        .storedClasses -- all classes known to the container
        .storedClass(classname) -- returns StoredClass for a given string
         |.storedFields for classFields
         |.parentStoredClass for immediate parent class
         L.IDs for a list of all instance IDs
    '''
    if not db4oConfig: db4oConfig = readonlyConfiguration()
    return com.db4o.Db4oEmbedded.openFile(db4oConfig, db4ofilename)

def all(db):
    ''' return all storedClass instances in this container
        .IDs for all instance IDs
    '''
    return db.queryByExample(None)

def objCount(db, storedClass = None):
    ''' return a count of objects in this container, for a specified class (or all) '''
    return len(storedClass.IDs if storedClass else all(db).IDs)

def byID(db, id, depth = 2):
    ''' return an activated object by ID '''
    o = db.getByID(id)
    db.activate(o, depth)
    return o

def userClasses(db, blacklist = BLACKLIST):
    ''' generate StoredClass list for a given db4o container, filtering out system/jvm classes '''
    return (c for c in db.storedClasses() if not c.name.startswith(blacklist))

def path(classObject):
    ''' generate full class history '''
    c = getattr(classObject, 'genericClass', classObject)
    while getattr(c, 'declaredFields', getattr(c, 'storedFields', None)):
        yield c
        c = getattr(c, 'superclass', getattr(c, 'parentStoredClass', None))

def fields(classObject):
    ''' return all fields for a given StoredClass (including parent fields [heritage/index order]) '''
    fields = []
    for c in reversed(tuple(path(classObject))):
        fields.extend(getattr(c, 'declaredFields', getattr(c,'storedFields', None)))
    return fields

def valueOf(field, instance):
    ''' given a field and instance, return a tuple of values, recursing if necessary '''
    v = field.get(instance)
    try:
        if v.class.name.startswith('com.db4o.reflect.generic.'): # com.db4o.reflect.generic.GenericObject
            v = tuple(valueOf(f, v) for f in v.genericClass.declaredFields)
    except AttributeError: pass
    return (field.name, v)

def objTuple(instance):
    ''' return a tuple for an object, suitable for dict()
        input is (com.db4o.internal.StoredClassImpl, com.db4o.reflect.generic.GenericObject) from byID
    '''
    return [valueOf(f, instance) for f in fields(instance)]