Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- def get_words(camel_cased):
- """Split CamelCasedWord to list of Capitalized words, with special asterisk (*) case, where it have own list element.
- For example: AbraKadabra*PoraMora -> ['Abra','Kadabra','*','Pora','Mora']
- """
- if not camel_cased:
- return []
- for i, let in enumerate(camel_cased[0:]):
- is_capital = ord("A") <= ord(let) <= ord("Z") or let == "*"
- if is_capital and i > 0:
- first_word, other_words = camel_cased[:i], get_words(camel_cased[i:])
- return [first_word] + other_words
- return [camel_cased]
- class ClassMatcher(object):
- """Class matcher, that could find classes from the list provided in constructor. For find matches use
- method "find_matching".
- There list of rules, that you can search with:
- 1. Pattern contains Capital letters, that represents Capital letters
- in class name in original order.
- Example: "FB" will match with "FooBarBaz" and "FooBar"
- 2. Between Capital letters could be small letters, than appears in
- class name between same capital letter with same order.
- Example: "FoBa" and "FBar" will match with "FooBarBaz" and "FooBar"
- 3. If pattern ends with space, than it's last "word" (Capital letter with optional small letters)
- should be the last word in class name.
- Example: "FBar " will match with "FooBar", but not "FooBarBaz"
- 4. Pattern can contain asterisks (*), that matches any words.
- Example: "F*Baz" and "*BB" will match with "FooBarBaz"
- """
- def __init__(self, classes):
- self.classes = map(ProcessedClass, classes)
- self.pattern_words = []
- self.curr_patt_word_index = None
- self.next_asterisk_pos = None
- def find_matching(self, pattern):
- """Finds all classes which match given pattern.
- Arguments:
- pattern String representation of pattern to match classes
- Returns:
- sorted alphabetically list of match classes.
- """
- classes = self.classes
- self.pattern_words = get_words(pattern)
- for patt_word_index in range(len(self.pattern_words)):
- #Each pattern word is apply to classes. Those classes left that satisfy condition.
- self.curr_patt_word_index = patt_word_index
- next_position = patt_word_index + 1
- self.next_asterisk_pos = self.get_next_asterisk_pos(next_position, self.pattern_words)
- classification_filter = lambda clazz: self.is_class_matches_pattern(clazz)
- classes = filter(classification_filter, classes)
- self.restore_classes()
- return self.get_sorted_classes_fullnames(classes)
- def restore_classes(self):
- [clazz.restore() for clazz in self.classes]
- def get_sorted_classes_fullnames(self, classes):
- classes.sort(key=lambda clazz: clazz.class_name)
- return map(lambda clazz: clazz.full_name, classes)
- def get_next_asterisk_pos(self, starting_from, words):
- """Find closest asterisk (*) element in array starting from some index.
- """
- following_words = words[starting_from:]
- return words.index("*", starting_from) if "*" in following_words else None
- def is_class_matches_pattern(self, clazz):
- """Checking if given class is matching with any pattern word defined with list of all pattern words and index.
- """
- pattern_word = self.pattern_words[self.curr_patt_word_index]
- class_words = clazz.words
- class_words_length = len(class_words)
- if self.curr_patt_word_index >= class_words_length:
- return False
- if pattern_word == "*":
- return self.is_class_matches_asterisk_pattern(clazz)
- if not class_words[self.curr_patt_word_index].startswith(pattern_word.strip()):
- return False
- if pattern_word[-1] == " ":
- return self.curr_patt_word_index + 1 == class_words_length
- return True
- def is_class_matches_asterisk_pattern(self, clazz):
- """Checking if given class is matching with wildcard pattern word defined with list of all pattern words and index.
- """
- should_be_words = self.pattern_words[self.curr_patt_word_index + 1:self.next_asterisk_pos]
- if not should_be_words:
- return True
- new_class_words = self.find_n_replace_asterisk_match(clazz.words, should_be_words, self.curr_patt_word_index)
- if new_class_words:
- clazz.words = new_class_words
- return True
- def find_last_asterisk_match(self, class_words, starting_from, words_sequence):
- i = 0
- last_pos = None
- find_last = words_sequence[-1][-1] == " "
- for class_word_index in range(starting_from, len(class_words)):
- if class_words[class_word_index].startswith(words_sequence[i].strip()):
- i += 1
- else:
- i = 0
- if i == len(words_sequence):
- last_pos = class_word_index
- if not find_last:
- break
- i = 0
- return last_pos
- def replace_matched_area(self, class_words, starting_from, last_match_start_pos):
- return class_words[:starting_from] + ["*"] + class_words[last_match_start_pos:]
- def find_n_replace_asterisk_match(self, class_words, words_sequence, starting_from):
- """Searching for matching continues words sequence in the class words starting from some index.
- """
- last_position = self.find_last_asterisk_match(class_words, starting_from, words_sequence)
- if last_position is None:
- return None
- last_match_start_pos = last_position - len(words_sequence) + 1
- return self.replace_matched_area(class_words, starting_from, last_match_start_pos)
- class ProcessedClass(object):
- """A bit preprocessed representation of class name
- """
- def __init__(self, clazz):
- self.full_name = clazz
- self.class_name = clazz[clazz.rfind(".")+1:]
- self.words = get_words(self.class_name)
- self.orig_words = self.words[:]
- def __repr__(self):
- return self.full_name
- def restore(self):
- self.words = self.orig_words
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement