#
#  $Id: Connector.py,v 1.1 1999/12/04 22:08:21 rob Exp $
#
#  Copyright 1999 Rob Tillotson <robt@debian.org>
#  All Rights Reserved
#
#  Permission to use, copy, modify, and distribute this software and
#  its documentation for any purpose and without fee or royalty is
#  hereby granted, provided that the above copyright notice appear in
#  all copies and that both the copyright notice and this permission
#  notice appear in supporting documentation or portions thereof,
#  including modifications, that you you make.
#
#  THE AUTHOR ROB TILLOTSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
#  THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
#  AND FITNESS.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
#  SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
#  RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
#  CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
#  CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE!
#
"""Application Modules.
"""

__version__ = '$Id: Connector.py,v 1.1 1999/12/04 22:08:21 rob Exp $'

__copyright__ = 'Copyright 1999 Rob Tillotson <robt@debian.org>'

import sys
from Pyrite import Plugin, Database, PrefBlock, _

class Connector(Plugin.Plugin):
    """Superclass for all application modules.
    """
    type = 'Connector'
    
    def __init__(self, *a, **kw):
	apply(Plugin.Plugin.__init__, (self,)+a, kw)
	self.default_name = None
	self.default_class = Database
	self.default_creator = 'Pyri'
	self.default_type = 'DATA'
	self.default_version = 0
	self.default_flags = 0

	self.pref_map = {}
	
    def classify(self, info={}):
	"""Classify a database.

	Given a dictionary representing a database header, this
	function checks whether this App has support for that
	database.  (Usually, it will check the creator and type,
	and maybe the version.)  If the App is not capable of
	handling the database, this function returns None; otherwise,
	it returns an appropriate subclass of Database.
	"""
	return None
    
    def open(self, store, name=None, mode='rs', **kw):
	"""Open a database associated with this application.

	If no name is specified, opens the 'default' database for this
	application, whatever that happens to be ('MemoDB' for the Memo
	module, for example).  Note that a particular App plug-in may
	accept 'names' which are not the name of an actual database, but
	which are instead symbolic of something else (eg. a composite of
	several databases).  Also, a particular App need not accept
	arbitrary database names at all.

	In the default implementation, additional keyword arguments are
	passed along to the Store's open method.
	"""
	if not name: name = self.default_name

	if not name:
	    raise RuntimeError, _("no database name specified")

	if store is None:
	    return apply(self.context.open, (name, mode, self.default_class), kw)
	else:
	    return apply(store.open, (name, mode, self.default_class), kw)

    def create(self, store, name=None, creator=None, type=None, flags=None,
	       version=None, **kw):
	"""Create a database associated with this application.

	See the documentation for 'open'.  If no creator, type, flags,
	and/or version are specified, default values will be used for the
	missing items.
	"""
	if not name: name = self.default_name
	if not name:
	    raise RuntimeError, _("no database name specified")

	if creator is None: creator = self.default_creator
	if type is None: type = self.default_type
	if flags is None: flags = self.default_flags
	if version is None: version = self.default_version

	return apply(store.create, (name, creator, type, flags, version, self.default_class), kw)

    # There is no 'delete' method. Do we need one?
    
    def list(self, store):
	"""List databases associated with this application (names only).

	Like the Store's 'list' method, but only lists names of databases
	which this plug-in can handle (as determined by its 'classify'
	method).
	"""
	return map(lambda x: x['name'], self.listinfo(store))

    def listinfo(self, store):
	"""List databases associated with this application (full info).

	Like the Store's 'listinfo' method, but lists information about
	databases which this plug-in can handle (as determined by its
	'classify' method).
	"""
	return filter(lambda x, s=self: s.classify(x) is not None,
		      store.listinfo())
    
    def getpref(self, store, id=0):
	"""Get a preference.

	The default version of this method assumes that the app uses only
	saved preferences with its own creator, and maps id numbers to
	block classes using a simple dictionary.  This should be adequate
	for many apps; anything more complicated will require overriding
	this method.
	"""
	if self.pref_map.has_key(id): cls = self.pref_map[id]
	else: cls = PrefBlock
	
	p, v = store.getpref(self.default_creator, id)
	if p is not None:
	    return cls(p, self.default_creator, id, v, 1)

    def setpref(self, store, blk):
	"""Set a preference.
	"""
	raw = blk.pack()
	return store.setpref(raw, blk.creator, blk.id, blk.version, blk.backup)
    
