module Filtering; import Questions.Question; import QuestionManagement.Database; export Filter, Tag, TagKey, Characteristic; object Tag components: key:TagKey, keyVal:string; description: (* A key value pair. *); end Tag; object TagKey components: key:string and values:string*; description: (* A tag's key and all possible values. *); end TagKey; object Boolean extends FilterItem components: type:integer; description: (* AND, OR, NOT, (, ), XOR *); end Boolean; object Characteristic description: (* Provided for common inheritance. *); end Characteristic; object CharacteristicCriteria extends Criteria components: type:integer, operator:integer, compareTo:integer; description: (* Some condition on a characteristic. *); end CharactersiticCriteria; object TagCriteria extends Criteria components: key:TagKey, v:string; description: (* A key value pair to match; *); end TagCriteria; object Criteria extends FilterItem description: (* Provided for common inheritance. A CharacteristicCriteria or a TagCriteria. *); end Criteria; object FilterItem description: (* Provided for common inheritance. Criteria or Boolean. *); end FilterItem; object Filter components: items:FilterItem*; description: (* An ordered set of conditions that describe a set of questions to match. *); end Filter; operation NewFilter inputs: ; outputs: filter:Filter; precondition: ; postcondition: #filter.items = 0; description: (* Creates an empty filter. *); end NewFilter; operation BuildFilter inputs: filter:Filter, item:FilterItem; outputs: filter':Filter; precondition: ; postcondition: forall(i:integer | i >= 1 and i <= #filter.items) (filter.items[i] = filter'.items[i]) and filter'.items[#filter.items + 1] = item and #filter'.items = #filter.items + 1; description: (* Adds something to a filter. *); end BuildFilter; operation RemoveFromFilter inputs: i:integer, filter:Filter; outputs: filter':Filter; precondition: i >=1 and i <= #filter.items; postcondition: #filter'.items = #filter.items - 1 and forall(j:integer | j >= 1 and j < i) (filter.items[j] = filter'.items[j]) and forall(j:integer | j >= i and j <= #filter'.items) (filter.items[j + 1] = filter'.items[j]) and not(filter.items[i] in filter'.items); description: (* Removes the given item from the given filter. *); end RemoveFromFilter; operation FilterQuestions inputs: database:Database, filter:Filter; outputs: questions:Question*; precondition: ; postcondition: (* all questions in questions meet the given filter *); description: (* Returns the questions from the given database that meet the given filter. *); end FilterQuestions; end Filtering;