import abc, re
from cppy.cp_util import *

'''
如果在基类层面上进行设计，这样就能获得多个子类同一层面上的抽象操作。
在一些语言里面，这种模式叫基于接口的编程，接口要求纯抽象类。
Python 因为对象协议的缘故，所以抽象接口设计不是必须。
沿用抽象接口设计是为工程性规整 。
'''

class IDataStorage (metaclass=abc.ABCMeta):  
    @abc.abstractmethod
    def words(self):
        pass

class IStopWordFilter (metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def is_stop_word(self, word):
        pass

class IWordFrequencyCounter(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def increment_count(self, word):
        pass

    @abc.abstractmethod
    def sorted(self):
        pass

#
# 类实现
#
class DataStorageManager1:    
    def __init__(self, path_to_file):        
        self._data = read_file(path_to_file)        
        self._data = re_split(self._data)

    def words(self): return self._data


class DataStorageManager2:    
    def __init__(self, path_to_file):
        self._data = read_file(path_to_file)
        self._data = re.findall('[a-z]{2,}', self._data)        

    def words(self): return self._data

            
class StopWordManager:    
    def __init__(self):
        self._stop_words = get_stopwords()        

    def is_stop_word(self, word):
        return word in self._stop_words


class WordFrequencyManager:
    def __init__(self):
        self._word_freqs = {}    

    def increment_count(self, word):
        self._word_freqs[word] = self._word_freqs.get(word, 0) + 1

    def sorted(self):
        return sort_dict( self._word_freqs )        


#
# 注册到抽象接口：并非必要
#
# IDataStorage.register(subclass=DataStorageManager1)
IDataStorage.register(subclass=DataStorageManager2)
IStopWordFilter.register(subclass=StopWordManager)
IWordFrequencyCounter.register(subclass=WordFrequencyManager)


#
# 应用类
#
class WordFrequencyController:
    def __init__(self, path_to_file):        
        self.storage = DataStorageManager2(path_to_file)
        self.stop_word_manager = StopWordManager()
        self.word_freq_counter = WordFrequencyManager()

    def run(self): # 可以看做面向协议编程
        for word in self.storage.words():
            if not self.stop_word_manager.is_stop_word(word):
                self.word_freq_counter.increment_count(word)
        
        print_word_freqs( self.word_freq_counter.sorted() ) 


if __name__ == '__main__':
    WordFrequencyController(testfilepath).run()