// // CSSelect.swift // CoreStore // // Copyright © 2016 John Rommel Estropia // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. // import Foundation import CoreData // MARK: - CSSelectTerm /** The `CSSelectTerm` serves as the Objective-C bridging type for `SelectTerm`. - SeeAlso: `SelectTerm` */ @objc public final class CSSelectTerm: NSObject, CoreStoreObjectiveCType { /** Provides a `CSSelectTerm` to a `CSSelect` clause for querying an entity attribute. ``` NSString *fullName = [CSCoreStore queryValueFrom:[CSFrom entityClass:[MyPersonEntity class]] select:CSSelectString(CSAttribute(@"fullname")) fetchClauses:@[[CSWhere keyPath:@"employeeID" isEqualTo: @1111]]]; ``` - parameter keyPath: the attribute name */ @objc public convenience init(keyPath: KeyPath) { self.init(.attribute(keyPath)) } /** Provides a `CSSelectTerm` to a `CSSelect` clause for querying the average value of an attribute. ``` NSNumber *averageAge = [CSCoreStore queryValueFrom:[CSFrom entityClass:[MyPersonEntity class]] select:[CSSelect numberForTerm:[CSSelectTerm average:@"age" as:nil]]]; ``` - parameter keyPath: the attribute name - parameter `as`: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "average()" is used - returns: a `CSSelectTerm` to a `CSSelect` clause for querying the average value of an attribute */ @objc public static func average(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm { return self.init(.average(keyPath, as: alias)) } /** Provides a `CSSelectTerm` to a `CSSelect` clause for a count query. ``` NSNumber *numberOfEmployees = [CSCoreStore queryValueFrom:[CSFrom entityClass:[MyPersonEntity class]] select:[CSSelect numberForTerm:[CSSelectTerm count:@"employeeID" as:nil]]]; ``` - parameter keyPath: the attribute name - parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "count()" is used - returns: a `SelectTerm` to a `Select` clause for a count query */ @objc public static func count(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm { return self.init(.count(keyPath, as: alias)) } /** Provides a `CSSelectTerm` to a `CSSelect` clause for querying the maximum value for an attribute. ``` NSNumber *maximumAge = [CSCoreStore queryValueFrom:[CSFrom entityClass:[MyPersonEntity class]] select:[CSSelect numberForTerm:[CSSelectTerm maximum:@"age" as:nil]]]; ``` - parameter keyPath: the attribute name - parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "max()" is used - returns: a `CSSelectTerm` to a `CSSelect` clause for querying the maximum value for an attribute */ @objc public static func maximum(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm { return self.init(.maximum(keyPath, as: alias)) } /** Provides a `CSSelectTerm` to a `CSSelect` clause for querying the minimum value for an attribute. ``` NSNumber *minimumAge = [CSCoreStore queryValueFrom:[CSFrom entityClass:[MyPersonEntity class]] select:[CSSelect numberForTerm:[CSSelectTerm minimum:@"age" as:nil]]]; ``` - parameter keyPath: the attribute name - parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "min()" is used - returns: a `CSSelectTerm` to a `CSSelect` clause for querying the minimum value for an attribute */ @objc public static func minimum(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm { return self.init(.minimum(keyPath, as: alias)) } /** Provides a `CSSelectTerm` to a `CSSelect` clause for querying the sum value for an attribute. ``` NSNumber *totalAge = [CSCoreStore queryValueFrom:[CSFrom entityClass:[MyPersonEntity class]] select:[CSSelect numberForTerm:[CSSelectTerm sum:@"age" as:nil]]]; ``` - parameter keyPath: the attribute name - parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "sum()" is used - returns: a `CSSelectTerm` to a `CSSelect` clause for querying the sum value for an attribute */ @objc public static func sum(_ keyPath: KeyPath, as alias: KeyPath?) -> CSSelectTerm { return self.init(.sum(keyPath, as: alias)) } /** Provides a `CSSelectTerm` to a `CSSelect` clause for querying the `NSManagedObjectID`. ``` NSManagedObjectID *objectID = [CSCoreStore queryValueFrom:[CSFrom entityClass:[MyPersonEntity class]] select:[CSSelect objectIDForTerm:[CSSelectTerm objectIDAs:nil]] fetchClauses:@[[CSWhere keyPath:@"employeeID" isEqualTo: @1111]]]; ``` - parameter alias: the dictionary key to use to access the result. Ignored when the query return value is not an `NSDictionary`. If `nil`, the default key "objecID" is used - returns: a `SelectTerm` to a `Select` clause for querying the sum value for an attribute */ @objc public static func objectIDAs(_ alias: KeyPath? = nil) -> CSSelectTerm { return self.init(.objectID(as: alias)) } // MARK: NSObject public override var hash: Int { return self.bridgeToSwift.hashValue } public override func isEqual(_ object: Any?) -> Bool { guard let object = object as? CSSelectTerm else { return false } return self.bridgeToSwift == object.bridgeToSwift } // MARK: CoreStoreObjectiveCType public let bridgeToSwift: SelectTerm public init(_ swiftValue: SelectTerm) { self.bridgeToSwift = swiftValue super.init() } } // MARK: - SelectTerm extension SelectTerm: CoreStoreSwiftType { // MARK: CoreStoreSwiftType public var bridgeToObjectiveC: CSSelectTerm { return CSSelectTerm(self) } } // MARK: - CSSelect /** The `CSSelect` serves as the Objective-C bridging type for `Select`. - SeeAlso: `Select` */ @objc public final class CSSelect: NSObject { /** Creates a `CSSelect` clause for querying `NSNumber` values. ``` NSNumber *maxAge = [CSCoreStore queryValueFrom:CSFromClass([MyPersonEntity class]) select:CSSelectNumber(CSAggregateMax(@"age")) // ... ``` - parameter numberTerm: the `CSSelectTerm` specifying the attribute/aggregate value to query */ public convenience init(numberTerm: CSSelectTerm) { self.init(Select(numberTerm.bridgeToSwift)) } /** Creates a `CSSelect` clause for querying `NSDecimalNumber` values. ``` NSDecimalNumber *averagePrice = [CSCoreStore queryValueFrom:CSFromClass([MyPersonEntity class]) select:CSSelectDecimal(CSAggregateAverage(@"price")) // ... ``` - parameter decimalTerm: the `CSSelectTerm` specifying the attribute/aggregate value to query */ public convenience init(decimalTerm: CSSelectTerm) { self.init(Select(decimalTerm.bridgeToSwift)) } /** Creates a `CSSelect` clause for querying `NSString` values. ``` NSString *fullname = [CSCoreStore queryValueFrom:CSFromClass([MyPersonEntity class]) select:CSSelectString(CSAttribute(@"fullname")) // ... ``` - parameter stringTerm: the `CSSelectTerm` specifying the attribute/aggregate value to query */ public convenience init(stringTerm: CSSelectTerm) { self.init(Select(stringTerm.bridgeToSwift)) } /** Creates a `CSSelect` clause for querying `NSDate` values. ``` NSDate *lastUpdate = [CSCoreStore queryValueFrom:CSFromClass([MyPersonEntity class]) select:CSSelectDate(CSAggregateMax(@"updatedDate")) // ... ``` - parameter dateTerm: the `CSSelectTerm` specifying the attribute/aggregate value to query */ public convenience init(dateTerm: CSSelectTerm) { self.init(Select(dateTerm.bridgeToSwift)) } /** Creates a `CSSelect` clause for querying `NSData` values. ``` NSData *imageData = [CSCoreStore queryValueFrom:CSFromClass([MyPersonEntity class]) select:CSSelectData(CSAttribute(@"imageData")) // ... ``` - parameter dataTerm: the `CSSelectTerm` specifying the attribute/aggregate value to query */ public convenience init(dataTerm: CSSelectTerm) { self.init(Select(dataTerm.bridgeToSwift)) } /** Creates a `CSSelect` clause for querying `NSManagedObjectID` values. ``` NSManagedObjectID *objectID = [CSCoreStore queryValueFrom:CSFromClass([MyPersonEntity class]) select:CSSelectObjectID() // ... ``` */ public convenience init(objectIDTerm: ()) { self.init(Select(.objectID())) } /** Creates a `CSSelect` clause for querying `NSDictionary` of an entity's attribute keys and values. ``` NSDictionary *keyValues = [CSCoreStore queryValueFrom:[CSFrom entityClass:[MyPersonEntity class]] select:[CSSelect dictionaryForTerm:[CSSelectTerm maximum:@"age" as:nil]]]; ``` - parameter term: the `CSSelectTerm` specifying the attribute/aggregate value to query - returns: a `CSSelect` clause for querying an entity attribute */ public static func dictionaryForTerm(_ term: CSSelectTerm) -> CSSelect { return self.init(Select(term.bridgeToSwift)) } /** Creates a `CSSelect` clause for querying `NSDictionary` of an entity's attribute keys and values. ``` NSDictionary *keyValues = [CSCoreStore queryValueFrom:[CSFrom entityClass:[MyPersonEntity class]] select:[CSSelect dictionaryForTerms:@[ [CSSelectTerm attribute:@"name" as:nil], [CSSelectTerm attribute:@"age" as:nil] ]]]; ``` - parameter terms: the `CSSelectTerm`s specifying the attribute/aggregate values to query - returns: a `CSSelect` clause for querying an entity attribute */ public static func dictionaryForTerms(_ terms: [CSSelectTerm]) -> CSSelect { return self.init(Select(terms.map { $0.bridgeToSwift })) } // MARK: NSObject public override var hash: Int { return self.attributeType.hashValue ^ self.selectTerms.map { $0.hashValue }.reduce(0, ^) } public override func isEqual(_ object: Any?) -> Bool { guard let object = object as? CSSelect else { return false } return self.attributeType == object.attributeType && self.selectTerms == object.selectTerms } public override var description: String { return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)" } // MARK: CoreStoreObjectiveCType public init(_ swiftValue: Select) { self.attributeType = T.cs_rawAttributeType self.selectTerms = swiftValue.selectTerms self.bridgeToSwift = swiftValue super.init() } public init(_ swiftValue: Select) { self.attributeType = .undefinedAttributeType self.selectTerms = swiftValue.selectTerms self.bridgeToSwift = swiftValue super.init() } // MARK: Internal internal let attributeType: NSAttributeType internal let selectTerms: [SelectTerm] // MARK: Private private let bridgeToSwift: CoreStoreDebugStringConvertible } // MARK: - Select extension Select: CoreStoreSwiftType { // MARK: CoreStoreSwiftType public var bridgeToObjectiveC: CSSelect { return CSSelect(self) } }