package reading.models trait Filter { def filter(book: Book): Boolean def kind: FilterKind def nonFormattedName: String def name: String override def equals(that: Any): Boolean = that match { case that: Filter => this.kind == that.kind && this.name == that.name case _ => false } override def hashCode: Int = this.kind.hashCode + this.nonFormattedName.hashCode } object Filter { def apply[T](in: T)(implicit filterFactory: FilterFactory[T]): Filter = filterFactory.create(in) def apply(kind: FilterKind, nonFormattedName: String): Option[Filter] = kind match { case FilterKind.Period => Period.withNameOption(nonFormattedName).map(apply[Period]) case FilterKind.GroupedTheme => GroupedTheme.withNameOption(nonFormattedName).map(apply[GroupedTheme]) case FilterKind.Theme => Theme.withNameOption(nonFormattedName).map(apply[Theme]) case FilterKind.Genre => Genre.withNameOption(nonFormattedName).map(apply[Genre]) case FilterKind.Level => Level.withNameOption(nonFormattedName).map(apply[Level]) case FilterKind.Program => Program.withNameOption(nonFormattedName).map(apply[Program]) case FilterKind.Grade => Grade.withNameOption(nonFormattedName).map(apply[Grade]) } def contains(filters: Seq[Filter], filter: Filter): Boolean = filters.find(_ == filter).nonEmpty def remove(fs: Seq[Filter], rf: Filter): Seq[Filter] = fs.filterNot { f => (f == rf || rf.kind == FilterKind.Grade && f.kind == FilterKind.Program || rf.kind == FilterKind.GroupedTheme && f.kind == FilterKind.Theme) } val onBooks: Map[Filter, Seq[Book]] = Seq( Grade.values.map(Filter.apply(_)), Program.values.map(Filter.apply(_)), Theme.values.map(Filter.apply(_)), GroupedTheme.values.map(Filter.apply(_)), Genre.values.map(Filter.apply(_)), Level.values.map(Filter.apply(_)), Period.values.map(Filter.apply(_)) ) .flatten .map(f => (f, Books().filter(f.filter))) .toMap def add(books: Seq[Book], filters: Seq[Filter]): Seq[Book] = filters.foldLeft(books)(add) def add(books: Seq[Book], filter: Filter): Seq[Book] = books.intersect(onBooks.getOrElse(filter, Nil)) }