########################################
# 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.views import BaseView

##############################################################################
#
# CachedView
#
# Simply keeps a copy of data around for faster access.  Place this view
# after any view you desire rapid access to.
#
# This class does not need to override _mapKeysToParent
#
##############################################################################

class CachedView(BaseView):
  """
  Provides a cache between views.

  The CachedView should be used under very specific circumstances.  If one has
  a deep tree of views and is performing many operations on the leaf views
  of the view tree, then a performance issue may arrise due to the data being
  continually evaluated and passed dow from the root Dataset object.

  If this is the case, a CachedView placed after the leaf view will cache
  the results from a getData() and allow for direct access.  This may make
  a large difference in the speed of execution.
  """
  
  def __init__(self, dataset, name=None):
    BaseView.__init__(self, dataset, name=name)
    self._refresh()
    
  def _refresh(self):

    if self.dataset.isDirty():
      self.dataset._refresh()
    
    self.cache = self.dataset.getData()
    self.dirty = 0
    
  def getData(self, key=None):

    if self.isDirty():
      self._refresh()
      
    v = None

    if key is None:
      v = self.cache

    else:

      keyMax = self.getKeyMax()
      if key < 0 or key >= keyMax:
        raise ValueError()

      numRows = self.getNumRows()
          
      if key < numRows:
        v = self.cache[key]
      else:
        v = self.cache[:, key - numRows]

    return v

    
