########################################
# The contents of this file are subject to the MLX PUBLIC LICENSE version
# 1.0 (the "License"); you may not use this file except in
# compliance with the License.
# 
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
# the License for the specific language governing rights and limitations
# under the License.
# 
# The Original Source Code is "compClust", released 2003 September 03.
# 
# The Original Source Code was developed by the California Institute of
# Technology (Caltech).  Portions created by Caltech are Copyright (C)
# 2002-2003 California Institute of Technology. All Rights Reserved.
########################################
#
#       Authors: Lucas Scharenbroich
#                Christopher Hart
# Last Modified: Dec 13 23:41:29 PST 2001
#

from compClust.mlx.datasets import Dataset

###############################################################################
#
# BaseView
#
# All other view should be derived from this class as it provides the ground
# work for tying into the base Dataset class
#
# This class does not need to override _mapKeysToParent
#
##############################################################################

class BaseView(Dataset):
  """
  The base class for all views.
  
  A BaseView provides a clean 'pass-through' view class from which to derive
  other, simple views.  It takes care of initializing itself and tying into
  all of the helper functions of the base dataset class.  A class deriving from
  a BaseView need only override the getData() method.
  """

  def __init__(self, dataset, name=None):

    #
    # Reference the parent dataset
    
    self.dataset = dataset
    self.__name = None
    # Set name handels adding us to the dataset viewsByName dictionary
    self.setName(name)
    self.dirty   = 0
    
    #
    # Clear the labelings and views of this new view

    self.resetVars()

    #
    # And add this view to the parent view list

    self.dataset.addView(self)

    #
    # copy over any mixins applied to the dataset
    self.copyMixins(dataset)

  def getName(self):
    """
    Returns the name of the Dataset or View.
    """
    return self.__name


  def setName(self, name):
    """
    Sets the name of the Dataset or View.
    """
    if name is not None:
      if self.dataset.viewsByName.has_key(name):
        raise KeyError("View names must be unique, %s was not" % (name))
      else:
        self.__name = name
        self.dataset.viewsByName[name] = self

  name = property(getName, setName, doc="Set or return the datasets name")

  def getData(self, key=None):
    return(self.dataset.getData(key))

  def getNumRows(self):
    if self.isDirty():
      self._refresh()
    return self.dataset.getNumRows()

  def getNumCols(self):
    if self.isDirty():
      self._refresh()
    return self.dataset.getNumCols()

  def detatch(self):
    self.dataset = None

  def _getLab2Key(self):
    if self.isDirty():
      self._refresh()
    return self.dataset._getLab2Key()

  def _getKey2Lab(self):
    if self.isDirty():
      self._refresh()
    return self.dataset._getKey2Lab()
  
  def _getUID(self):
    return self.dataset._getUID()

  def _addUID(self, uid, key):
    if self.isDirty():
      self._refresh()
    self.dataset._addUID(uid, key)

  def _getUIDsByKey(self, key=None):
    return(self.dataset._getUIDsByKey(key))

  def _getKeysByUID(self, key=None):
    return(self.dataset._getKeysByUID(key))

  def getLineage(self):
    lineage = self.dataset.getLineage()
    for branch in lineage:
      branch.insert(0, self)
    return lineage
  
  #######################
  #
  # Cache functionality
  #
  #######################

  def _makeDirtyChildren(self):
    """
    Sets the dirty bit for all the children and recurse.
    """
    
    for v in self.getViews():
      v.dirty = 1
      v._makeDirtyChildren()
    

  def _refresh(self):
    """
    Default _refresh() function.  If the view is dirty, refresh the parent
    and clear the dirty bit.
    """

    if self.dataset.isDirty():
      self.dataset._refresh()
    self.dirty = 0
    
    
