123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- //
- // Filter.swift
- // SwiftyBeaver
- //
- // Created by Jeff Roberts on 5/31/16.
- // Copyright © 2015 Sebastian Kreutzberger
- // Some rights reserved: http://opensource.org/licenses/MIT
- //
- import Foundation
- /// FilterType is a protocol that describes something that determines
- /// whether or not a message gets logged. A filter answers a Bool when it
- /// is applied to a value. If the filter passes, it shall return true,
- /// false otherwise.
- ///
- /// A filter must contain a target, which identifies what it filters against
- /// A filter can be required meaning that all required filters against a specific
- /// target must pass in order for the message to be logged. At least one non-required
- /// filter must pass in order for the message to be logged
- public protocol FilterType : class {
- func apply(_ value: Any) -> Bool
- func getTarget() -> Filter.TargetType
- func isRequired() -> Bool
- func isExcluded() -> Bool
- func reachedMinLevel(_ level: SwiftyBeaver.Level) -> Bool
- }
- /// Filters is syntactic sugar used to easily construct filters
- public class Filters {
- public static let Path = PathFilterFactory.self
- public static let Function = FunctionFilterFactory.self
- public static let Message = MessageFilterFactory.self
- }
- /// Filter is an abstract base class for other filters
- public class Filter {
- public enum TargetType {
- case Path(Filter.ComparisonType)
- case Function(Filter.ComparisonType)
- case Message(Filter.ComparisonType)
- }
- public enum ComparisonType {
- case StartsWith([String], Bool)
- case Contains([String], Bool)
- case Excludes([String], Bool)
- case EndsWith([String], Bool)
- case Equals([String], Bool)
- case Custom((String) -> Bool)
- }
- let targetType: Filter.TargetType
- let required: Bool
- let minLevel: SwiftyBeaver.Level
- public init(_ target: Filter.TargetType, required: Bool, minLevel: SwiftyBeaver.Level) {
- self.targetType = target
- self.required = required
- self.minLevel = minLevel
- }
- public func getTarget() -> Filter.TargetType {
- return self.targetType
- }
- public func isRequired() -> Bool {
- return self.required
- }
- public func isExcluded() -> Bool {
- return false
- }
- /// returns true of set minLevel is >= as given level
- public func reachedMinLevel(_ level: SwiftyBeaver.Level) -> Bool {
- //print("checking if given level \(level) >= \(minLevel)")
- return level.rawValue >= minLevel.rawValue
- }
- }
- /// CompareFilter is a FilterType that can filter based upon whether a target
- /// starts with, contains or ends with a specific string. CompareFilters can be
- /// case sensitive.
- public class CompareFilter: Filter, FilterType {
- private var filterComparisonType: Filter.ComparisonType?
- override public init(_ target: Filter.TargetType, required: Bool, minLevel: SwiftyBeaver.Level) {
- super.init(target, required: required, minLevel: minLevel)
- let comparisonType: Filter.ComparisonType?
- switch self.getTarget() {
- case let .Function(comparison):
- comparisonType = comparison
- case let .Path(comparison):
- comparisonType = comparison
- case let .Message(comparison):
- comparisonType = comparison
- /*default:
- comparisonType = nil*/
- }
- self.filterComparisonType = comparisonType
- }
- public func apply(_ value: Any) -> Bool {
- guard let value = value as? String else {
- return false
- }
- guard let filterComparisonType = self.filterComparisonType else {
- return false
- }
- let matches: Bool
- switch filterComparisonType {
- case let .Contains(strings, caseSensitive):
- matches = !strings.filter { string in
- return caseSensitive ? value.contains(string) :
- value.lowercased().contains(string.lowercased())
- }.isEmpty
- case let .Excludes(strings, caseSensitive):
- matches = !strings.filter { string in
- return caseSensitive ? !value.contains(string) :
- !value.lowercased().contains(string.lowercased())
- }.isEmpty
- case let .StartsWith(strings, caseSensitive):
- matches = !strings.filter { string in
- return caseSensitive ? value.hasPrefix(string) :
- value.lowercased().hasPrefix(string.lowercased())
- }.isEmpty
- case let .EndsWith(strings, caseSensitive):
- matches = !strings.filter { string in
- return caseSensitive ? value.hasSuffix(string) :
- value.lowercased().hasSuffix(string.lowercased())
- }.isEmpty
- case let .Equals(strings, caseSensitive):
- matches = !strings.filter { string in
- return caseSensitive ? value == string :
- value.lowercased() == string.lowercased()
- }.isEmpty
- case let .Custom(predicate):
- matches = predicate(value)
- }
- return matches
- }
- override public func isExcluded() -> Bool {
- guard let filterComparisonType = self.filterComparisonType else { return false }
- switch filterComparisonType {
- case .Excludes(_, _):
- return true
- default:
- return false
- }
- }
- }
- // Syntactic sugar for creating a function comparison filter
- public class FunctionFilterFactory {
- public static func startsWith(_ prefixes: String..., caseSensitive: Bool = false,
- required: Bool = false, minLevel: SwiftyBeaver.Level = .verbose) -> FilterType {
- return CompareFilter(.Function(.StartsWith(prefixes, caseSensitive)), required: required, minLevel: minLevel)
- }
- public static func contains(_ strings: String..., caseSensitive: Bool = false,
- required: Bool = false, minLevel: SwiftyBeaver.Level = .verbose) -> FilterType {
- return CompareFilter(.Function(.Contains(strings, caseSensitive)), required: required, minLevel: minLevel)
- }
- public static func excludes(_ strings: String..., caseSensitive: Bool = false,
- required: Bool = false, minLevel: SwiftyBeaver.Level = .verbose) -> FilterType {
- return CompareFilter(.Function(.Excludes(strings, caseSensitive)), required: required, minLevel: minLevel)
- }
- public static func endsWith(_ suffixes: String..., caseSensitive: Bool = false,
- required: Bool = false, minLevel: SwiftyBeaver.Level = .verbose) -> FilterType {
- return CompareFilter(.Function(.EndsWith(suffixes, caseSensitive)), required: required, minLevel: minLevel)
- }
- public static func equals(_ strings: String..., caseSensitive: Bool = false,
- required: Bool = false, minLevel: SwiftyBeaver.Level = .verbose) -> FilterType {
- return CompareFilter(.Function(.Equals(strings, caseSensitive)), required: required, minLevel: minLevel)
- }
- public static func custom(required: Bool = false, minLevel: SwiftyBeaver.Level = .verbose, filterPredicate: @escaping (String) -> Bool) -> FilterType {
- return CompareFilter(.Function(.Custom(filterPredicate)), required: required, minLevel: minLevel)
- }
- }
- // Syntactic sugar for creating a message comparison filter
- public class MessageFilterFactory {
- public static func startsWith(_ prefixes: String..., caseSensitive: Bool = false,
- required: Bool = false, minLevel: SwiftyBeaver.Level = .verbose) -> FilterType {
- return CompareFilter(.Message(.StartsWith(prefixes, caseSensitive)), required: required, minLevel: minLevel)
- }
- public static func contains(_ strings: String..., caseSensitive: Bool = false,
- required: Bool = false, minLevel: SwiftyBeaver.Level = .verbose) -> FilterType {
- return CompareFilter(.Message(.Contains(strings, caseSensitive)), required: required, minLevel: minLevel)
- }
- public static func excludes(_ strings: String..., caseSensitive: Bool = false,
- required: Bool = false, minLevel: SwiftyBeaver.Level = .verbose) -> FilterType {
- return CompareFilter(.Message(.Excludes(strings, caseSensitive)), required: required, minLevel: minLevel)
- }
- public static func endsWith(_ suffixes: String..., caseSensitive: Bool = false,
- required: Bool = false, minLevel: SwiftyBeaver.Level = .verbose) -> FilterType {
- return CompareFilter(.Message(.EndsWith(suffixes, caseSensitive)), required: required, minLevel: minLevel)
- }
- public static func equals(_ strings: String..., caseSensitive: Bool = false,
- required: Bool = false, minLevel: SwiftyBeaver.Level = .verbose) -> FilterType {
- return CompareFilter(.Message(.Equals(strings, caseSensitive)), required: required, minLevel: minLevel)
- }
- public static func custom(required: Bool = false, minLevel: SwiftyBeaver.Level = .verbose, filterPredicate: @escaping (String) -> Bool) -> FilterType {
- return CompareFilter(.Message(.Custom(filterPredicate)), required: required, minLevel: minLevel)
- }
- }
- // Syntactic sugar for creating a path comparison filter
- public class PathFilterFactory {
- public static func startsWith(_ prefixes: String..., caseSensitive: Bool = false,
- required: Bool = false, minLevel: SwiftyBeaver.Level = .verbose) -> FilterType {
- return CompareFilter(.Path(.StartsWith(prefixes, caseSensitive)), required: required, minLevel: minLevel)
- }
- public static func contains(_ strings: String..., caseSensitive: Bool = false,
- required: Bool = false, minLevel: SwiftyBeaver.Level = .verbose) -> FilterType {
- return CompareFilter(.Path(.Contains(strings, caseSensitive)), required: required, minLevel: minLevel)
- }
- public static func excludes(_ strings: String..., caseSensitive: Bool = false,
- required: Bool = false, minLevel: SwiftyBeaver.Level = .verbose) -> FilterType {
- return CompareFilter(.Path(.Excludes(strings, caseSensitive)), required: required, minLevel: minLevel)
- }
- public static func endsWith(_ suffixes: String..., caseSensitive: Bool = false,
- required: Bool = false, minLevel: SwiftyBeaver.Level = .verbose) -> FilterType {
- return CompareFilter(.Path(.EndsWith(suffixes, caseSensitive)), required: required, minLevel: minLevel)
- }
- public static func equals(_ strings: String..., caseSensitive: Bool = false,
- required: Bool = false, minLevel: SwiftyBeaver.Level = .verbose) -> FilterType {
- return CompareFilter(.Path(.Equals(strings, caseSensitive)), required: required, minLevel: minLevel)
- }
- public static func custom(required: Bool = false, minLevel: SwiftyBeaver.Level = .verbose, filterPredicate: @escaping (String) -> Bool) -> FilterType {
- return CompareFilter(.Path(.Custom(filterPredicate)), required: required, minLevel: minLevel)
- }
- }
- extension Filter.TargetType : Equatable {
- }
- // The == does not compare associated values for each enum. Instead == evaluates to true
- // if both enums are the same "types", ignoring the associated values of each enum
- public func == (lhs: Filter.TargetType, rhs: Filter.TargetType) -> Bool {
- switch (lhs, rhs) {
- case (.Path(_), .Path(_)):
- return true
- case (.Function(_), .Function(_)):
- return true
- case (.Message(_), .Message(_)):
- return true
- default:
- return false
- }
- }
|