from twisted.python.reflect import namedAny
import sys

class ShoutModel(object):
	"""	A generic model is an abstract class
		ShoutModel can be subclassed to allow users to
			- add filters
			- get primary keys
			- apply foreign keys from other models on to this model
			- apply filters

			Though it can be used in lieu of a Model object, it is best used to 
			repeatedly add/apply filters (primitives and foreign keys) and then executing the filters
	"""

	def __init__(self):
		""" It is incorrect to try to initialize a ShoutModel object using __init__(self).
		"""
		raise NotImplementedError("ShoutModel is an abstract class")

	def addFilter(self, colName, op, value):
		""" Subclasses implement :addFilter to support include and exclude Filters
		"""
		raise NotImplementedError("ShoutModel is an abstract class and does not support addFilter")

	def applyFilter(self):
		""" Subclasses implement :applyFilter to apply all filters added using :addFilter. 
			ApplyFilter should return True/False depending on whether the filter was applied or not
		"""
		raise NotImplementedError("ShoutModel is an abstract class and does not support applyFilter")
	
	def dataWasFiltered(self):
		""" Subclasses implement :dataWasFiltered to tell callers whether applying the filter caused data to be filtered or not
		"""
		raise NotImplementedError("ShoutModel is an abstract class and does not support dataWasFiltered")

	def clear(self):
		""" Subclasses implement :clear to clear all data from the data set currently being filtered
			calling :getResults after calling :clear should return an empty result set
		"""
		raise NotImplementedError("ShoutModel is an abstract class and does not support clear")
			
	def getResults(self):
		""" Subclasses implement :getResults to return data after application of added filters
		"""
		raise NotImplementedError("ShoutModel is an abstract class and does not support getResults")

	def getPKs(self):
		""" Subclasses implement :getPKs to return a list of field(s) which can be used to filter other ShoutModels
			E.g. If the current ShoutModel represents a list of courses, getPKs could return a list of CourseIDs which 
				can be used to filter a list of students attending those courses
		"""
		raise NotImplementedError("ShoutModel is an abstract class and does not support getPKs")

	def getRelatedModelNames(self):
		""" Subclasses implement :getRelatedModelNames to return a list of ShoutModels related  with the current model
			If filtering data in the current model should cause data in related models to be filtered, the models are 
				said to be Related
			E.g. in a relational model, two Models are considered related if they enjoy a Pk-Fk relationship
		"""
		raise NotImplementedError("ShoutModel is an abstract class and does not support getRelatedModelNames")

	def applyFKs(self, fkTableName, fkArray):
		""" Subclasses implement :applyFKs to filter data in the current model based on a list of data 
				determined by :getPKs of a different model
		"""
		raise NotImplementedError("ShoutModel is an abstract class and does not support applyFKs")

	def getModelName(self):
		"""return name of Model object
		"""
		raise NotImplementedError("ShoutModel is an abstract class and does not support getModelName")

