From af4e720acdcd9217ab884597e4189e7ec0a2fdb4 Mon Sep 17 00:00:00 2001 From: Angelo Paparazzi Date: Fri, 30 Oct 2020 18:13:13 -0400 Subject: [PATCH] DiscoveryV2 changes --- Sources/DiscoveryV2/Discovery.swift | 610 ++++++++++++------ .../DiscoveryV2/Models/AnalyzedDocument.swift | 40 ++ .../DiscoveryV2/Models/AnalyzedResult.swift | 53 ++ .../Models/CollectionDetails.swift | 6 - .../DiscoveryV2/Models/QueryAggregation.swift | 186 ++++-- .../DiscoveryV2/Models/QueryResponse.swift | 8 +- .../Models/QueryResponsePassage.swift | 70 ++ .../DiscoveryV2/Models/TrainingExample.swift | 10 +- .../DiscoveryV2/Models/TrainingQuery.swift | 13 +- 9 files changed, 713 insertions(+), 283 deletions(-) create mode 100644 Sources/DiscoveryV2/Models/AnalyzedDocument.swift create mode 100644 Sources/DiscoveryV2/Models/AnalyzedResult.swift create mode 100644 Sources/DiscoveryV2/Models/QueryResponsePassage.swift diff --git a/Sources/DiscoveryV2/Discovery.swift b/Sources/DiscoveryV2/Discovery.swift index 61a00371f..3992c91d0 100644 --- a/Sources/DiscoveryV2/Discovery.swift +++ b/Sources/DiscoveryV2/Discovery.swift @@ -1,5 +1,5 @@ /** - * (C) Copyright IBM Corp. 2019, 2020. + * (C) Copyright IBM Corp. 2020. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,11 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ + +/** + * IBM OpenAPI SDK Code Generator Version: 99-SNAPSHOT-36b26b63-20201028-122900 + **/ + // swiftlint:disable file_length import Foundation +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif import IBMSwiftSDKCore +public typealias WatsonError = RestError +public typealias WatsonResponse = RestResponse /** IBM Watson™ Discovery is a cognitive search and content analytics engine that you can add to applications to identify patterns, trends and actionable insights to drive better decision-making. Securely unify structured and @@ -29,8 +39,14 @@ public class Discovery { /// The base URL to use when contacting the service. public var serviceURL: String? = "https://api.us-south.discovery.watson.cloud.ibm.com" + /// Release date of the version of the API you want to use. Specify dates in YYYY-MM-DD format. The current version + /// is `2019-11-22`. + public var version: String + /// Service identifiers - internal let serviceName = "Discovery" + public static let defaultServiceName = "discovery" + // Service info for SDK headers + internal let serviceName = defaultServiceName internal let serviceVersion = "v2" internal let serviceSdkName = "discovery" @@ -39,41 +55,39 @@ public class Discovery { var session = URLSession(configuration: URLSessionConfiguration.default) public let authenticator: Authenticator - let version: String #if os(Linux) /** Create a `Discovery` object. - This initializer will retrieve credentials from the environment or a local credentials file. + If an authenticator is not supplied, the initializer will retrieve credentials from the environment or + a local credentials file and construct an appropriate authenticator using these credentials. The credentials file can be downloaded from your service instance on IBM Cloud as ibm-credentials.env. Make sure to add the credentials file to your project so that it can be loaded at runtime. - If credentials are not available in the environment or a local credentials file, initialization will fail. + If an authenticator is not supplied and credentials are not available in the environment or a local + credentials file, initialization will fail by throwing an exception. In that case, try another initializer that directly passes in the credentials. - - parameter version: The release date of the version of the API to use. Specify the date - in "YYYY-MM-DD" format. + - parameter version: Release date of the version of the API you want to use. Specify dates in YYYY-MM-DD format. + The current version is `2019-11-22`. + - parameter authenticator: The Authenticator object used to authenticate requests to the service + - serviceName: String = defaultServiceName */ - public init(version: String) throws { + public init(version: String, authenticator: Authenticator? = nil, serviceName: String = defaultServiceName) throws { self.version = version - - let authenticator = try ConfigBasedAuthenticatorFactory.getAuthenticator(credentialPrefix: serviceSdkName) - self.authenticator = authenticator - - if let serviceURL = CredentialUtils.getServiceURL(credentialPrefix: serviceSdkName) { + self.authenticator = try authenticator ?? ConfigBasedAuthenticatorFactory.getAuthenticator(credentialPrefix: serviceName) + if let serviceURL = CredentialUtils.getServiceURL(credentialPrefix: serviceName) { self.serviceURL = serviceURL } - RestRequest.userAgent = Shared.userAgent } - #endif - + #else /** Create a `Discovery` object. - - parameter version: The release date of the version of the API to use. Specify the date - in "YYYY-MM-DD" format. + - parameter version: Release date of the version of the API you want to use. Specify dates in YYYY-MM-DD format. + The current version is `2019-11-22`. - parameter authenticator: The Authenticator object used to authenticate requests to the service */ public init(version: String, authenticator: Authenticator) { @@ -81,6 +95,7 @@ public class Discovery { self.authenticator = authenticator RestRequest.userAgent = Shared.userAgent } + #endif #if !os(Linux) /** @@ -99,7 +114,7 @@ public class Discovery { - parameter data: Raw data returned by the service that may represent an error. - parameter response: the URL response returned by the service. */ - func errorResponseDecoder(data: Data, response: HTTPURLResponse) -> WatsonError { + func errorResponseDecoder(data: Data, response: HTTPURLResponse) -> RestError { let statusCode = response.statusCode var errorMessage: String? @@ -124,7 +139,7 @@ public class Discovery { errorMessage = HTTPURLResponse.localizedString(forStatusCode: response.statusCode) } - return WatsonError.http(statusCode: statusCode, message: errorMessage, metadata: metadata) + return RestError.http(statusCode: statusCode, message: errorMessage, metadata: metadata) } /** @@ -144,12 +159,12 @@ public class Discovery { { // construct header parameters var headerParameters = defaultHeaders - if let headers = headers { - headerParameters.merge(headers) { (_, new) in new } - } let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "listCollections") headerParameters.merge(sdkHeaders) { (_, new) in new } headerParameters["Accept"] = "application/json" + if let headers = headers { + headerParameters.merge(headers) { (_, new) in new } + } // construct query parameters var queryParameters = [URLQueryItem]() @@ -158,13 +173,13 @@ public class Discovery { // construct REST request let path = "/v2/projects/\(projectID)/collections" guard let encodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { - completionHandler(nil, WatsonError.urlEncoding(path: path)) + completionHandler(nil, RestError.urlEncoding(path: path)) return } // ensure that serviceURL is set guard let serviceEndpoint = serviceURL else { - completionHandler(nil, WatsonError.noEndpoint) + completionHandler(nil, RestError.noEndpoint) return } @@ -206,25 +221,25 @@ public class Discovery { completionHandler: @escaping (WatsonResponse?, WatsonError?) -> Void) { // construct body - let createCollectionRequest = CollectionDetails( + let createCollectionRequest = CreateCollectionRequest( name: name, description: description, language: language, enrichments: enrichments) guard let body = try? JSON.encoder.encode(createCollectionRequest) else { - completionHandler(nil, WatsonError.serialization(values: "request body")) + completionHandler(nil, RestError.serialization(values: "request body")) return } // construct header parameters var headerParameters = defaultHeaders - if let headers = headers { - headerParameters.merge(headers) { (_, new) in new } - } let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "createCollection") headerParameters.merge(sdkHeaders) { (_, new) in new } headerParameters["Accept"] = "application/json" headerParameters["Content-Type"] = "application/json" + if let headers = headers { + headerParameters.merge(headers) { (_, new) in new } + } // construct query parameters var queryParameters = [URLQueryItem]() @@ -233,13 +248,13 @@ public class Discovery { // construct REST request let path = "/v2/projects/\(projectID)/collections" guard let encodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { - completionHandler(nil, WatsonError.urlEncoding(path: path)) + completionHandler(nil, RestError.urlEncoding(path: path)) return } // ensure that serviceURL is set guard let serviceEndpoint = serviceURL else { - completionHandler(nil, WatsonError.noEndpoint) + completionHandler(nil, RestError.noEndpoint) return } @@ -258,6 +273,16 @@ public class Discovery { request.responseObject(completionHandler: completionHandler) } + // Private struct for the createCollection request body + private struct CreateCollectionRequest: Encodable { + // swiftlint:disable identifier_name + let name: String + let description: String? + let language: String? + let enrichments: [CollectionEnrichment]? + // swiftlint:enable identifier_name + } + /** Get collection. @@ -277,12 +302,12 @@ public class Discovery { { // construct header parameters var headerParameters = defaultHeaders - if let headers = headers { - headerParameters.merge(headers) { (_, new) in new } - } let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "getCollection") headerParameters.merge(sdkHeaders) { (_, new) in new } headerParameters["Accept"] = "application/json" + if let headers = headers { + headerParameters.merge(headers) { (_, new) in new } + } // construct query parameters var queryParameters = [URLQueryItem]() @@ -291,13 +316,13 @@ public class Discovery { // construct REST request let path = "/v2/projects/\(projectID)/collections/\(collectionID)" guard let encodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { - completionHandler(nil, WatsonError.urlEncoding(path: path)) + completionHandler(nil, RestError.urlEncoding(path: path)) return } // ensure that serviceURL is set guard let serviceEndpoint = serviceURL else { - completionHandler(nil, WatsonError.noEndpoint) + completionHandler(nil, RestError.noEndpoint) return } @@ -339,24 +364,24 @@ public class Discovery { completionHandler: @escaping (WatsonResponse?, WatsonError?) -> Void) { // construct body - let updateCollectionRequest = UpdateCollection( + let updateCollectionRequest = UpdateCollectionRequest( name: name, description: description, enrichments: enrichments) guard let body = try? JSON.encoder.encode(updateCollectionRequest) else { - completionHandler(nil, WatsonError.serialization(values: "request body")) + completionHandler(nil, RestError.serialization(values: "request body")) return } // construct header parameters var headerParameters = defaultHeaders - if let headers = headers { - headerParameters.merge(headers) { (_, new) in new } - } let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "updateCollection") headerParameters.merge(sdkHeaders) { (_, new) in new } headerParameters["Accept"] = "application/json" headerParameters["Content-Type"] = "application/json" + if let headers = headers { + headerParameters.merge(headers) { (_, new) in new } + } // construct query parameters var queryParameters = [URLQueryItem]() @@ -365,13 +390,13 @@ public class Discovery { // construct REST request let path = "/v2/projects/\(projectID)/collections/\(collectionID)" guard let encodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { - completionHandler(nil, WatsonError.urlEncoding(path: path)) + completionHandler(nil, RestError.urlEncoding(path: path)) return } // ensure that serviceURL is set guard let serviceEndpoint = serviceURL else { - completionHandler(nil, WatsonError.noEndpoint) + completionHandler(nil, RestError.noEndpoint) return } @@ -390,6 +415,15 @@ public class Discovery { request.responseObject(completionHandler: completionHandler) } + // Private struct for the updateCollection request body + private struct UpdateCollectionRequest: Encodable { + // swiftlint:disable identifier_name + let name: String? + let description: String? + let enrichments: [CollectionEnrichment]? + // swiftlint:enable identifier_name + } + /** Delete a collection. @@ -410,11 +444,11 @@ public class Discovery { { // construct header parameters var headerParameters = defaultHeaders + let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "deleteCollection") + headerParameters.merge(sdkHeaders) { (_, new) in new } if let headers = headers { headerParameters.merge(headers) { (_, new) in new } } - let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "deleteCollection") - headerParameters.merge(sdkHeaders) { (_, new) in new } // construct query parameters var queryParameters = [URLQueryItem]() @@ -423,13 +457,13 @@ public class Discovery { // construct REST request let path = "/v2/projects/\(projectID)/collections/\(collectionID)" guard let encodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { - completionHandler(nil, WatsonError.urlEncoding(path: path)) + completionHandler(nil, RestError.urlEncoding(path: path)) return } // ensure that serviceURL is set guard let serviceEndpoint = serviceURL else { - completionHandler(nil, WatsonError.noEndpoint) + completionHandler(nil, RestError.noEndpoint) return } @@ -509,7 +543,7 @@ public class Discovery { completionHandler: @escaping (WatsonResponse?, WatsonError?) -> Void) { // construct body - let queryRequest = QueryLarge( + let queryRequest = QueryRequest( collectionIDs: collectionIDs, filter: filter, query: query, @@ -524,20 +558,23 @@ public class Discovery { tableResults: tableResults, suggestedRefinements: suggestedRefinements, passages: passages) - guard let body = try? JSON.encoder.encodeIfPresent(queryRequest) else { - completionHandler(nil, WatsonError.serialization(values: "request body")) + let body: Data? + do { + body = try JSON.encoder.encodeIfPresent(queryRequest) + } catch { + completionHandler(nil, RestError.serialization(values: "request body")) return } // construct header parameters var headerParameters = defaultHeaders - if let headers = headers { - headerParameters.merge(headers) { (_, new) in new } - } let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "query") headerParameters.merge(sdkHeaders) { (_, new) in new } headerParameters["Accept"] = "application/json" headerParameters["Content-Type"] = "application/json" + if let headers = headers { + headerParameters.merge(headers) { (_, new) in new } + } // construct query parameters var queryParameters = [URLQueryItem]() @@ -546,13 +583,13 @@ public class Discovery { // construct REST request let path = "/v2/projects/\(projectID)/query" guard let encodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { - completionHandler(nil, WatsonError.urlEncoding(path: path)) + completionHandler(nil, RestError.urlEncoding(path: path)) return } // ensure that serviceURL is set guard let serviceEndpoint = serviceURL else { - completionHandler(nil, WatsonError.noEndpoint) + completionHandler(nil, RestError.noEndpoint) return } @@ -571,6 +608,61 @@ public class Discovery { request.responseObject(completionHandler: completionHandler) } + // Private struct for the query request body + private struct QueryRequest: Encodable { + // swiftlint:disable identifier_name + let collectionIDs: [String]? + let filter: String? + let query: String? + let naturalLanguageQuery: String? + let aggregation: String? + let count: Int? + let `return`: [String]? + let offset: Int? + let sort: String? + let highlight: Bool? + let spellingSuggestions: Bool? + let tableResults: QueryLargeTableResults? + let suggestedRefinements: QueryLargeSuggestedRefinements? + let passages: QueryLargePassages? + private enum CodingKeys: String, CodingKey { + case collectionIDs = "collection_ids" + case filter = "filter" + case query = "query" + case naturalLanguageQuery = "natural_language_query" + case aggregation = "aggregation" + case count = "count" + case `return` = "return" + case offset = "offset" + case sort = "sort" + case highlight = "highlight" + case spellingSuggestions = "spelling_suggestions" + case tableResults = "table_results" + case suggestedRefinements = "suggested_refinements" + case passages = "passages" + } + init? (collectionIDs: [String]? = nil, filter: String? = nil, query: String? = nil, naturalLanguageQuery: String? = nil, aggregation: String? = nil, count: Int? = nil, `return`: [String]? = nil, offset: Int? = nil, sort: String? = nil, highlight: Bool? = nil, spellingSuggestions: Bool? = nil, tableResults: QueryLargeTableResults? = nil, suggestedRefinements: QueryLargeSuggestedRefinements? = nil, passages: QueryLargePassages? = nil) { + if collectionIDs == nil && filter == nil && query == nil && naturalLanguageQuery == nil && aggregation == nil && count == nil && `return` == nil && offset == nil && sort == nil && highlight == nil && spellingSuggestions == nil && tableResults == nil && suggestedRefinements == nil && passages == nil { + return nil + } + self.collectionIDs = collectionIDs + self.filter = filter + self.query = query + self.naturalLanguageQuery = naturalLanguageQuery + self.aggregation = aggregation + self.count = count + self.`return` = `return` + self.offset = offset + self.sort = sort + self.highlight = highlight + self.spellingSuggestions = spellingSuggestions + self.tableResults = tableResults + self.suggestedRefinements = suggestedRefinements + self.passages = passages + } + // swiftlint:enable identifier_name + } + /** Get Autocomplete Suggestions. @@ -598,12 +690,12 @@ public class Discovery { { // construct header parameters var headerParameters = defaultHeaders - if let headers = headers { - headerParameters.merge(headers) { (_, new) in new } - } let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "getAutocompletion") headerParameters.merge(sdkHeaders) { (_, new) in new } headerParameters["Accept"] = "application/json" + if let headers = headers { + headerParameters.merge(headers) { (_, new) in new } + } // construct query parameters var queryParameters = [URLQueryItem]() @@ -625,13 +717,13 @@ public class Discovery { // construct REST request let path = "/v2/projects/\(projectID)/autocompletion" guard let encodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { - completionHandler(nil, WatsonError.urlEncoding(path: path)) + completionHandler(nil, RestError.urlEncoding(path: path)) return } // ensure that serviceURL is set guard let serviceEndpoint = serviceURL else { - completionHandler(nil, WatsonError.noEndpoint) + completionHandler(nil, RestError.noEndpoint) return } @@ -683,12 +775,12 @@ public class Discovery { { // construct header parameters var headerParameters = defaultHeaders - if let headers = headers { - headerParameters.merge(headers) { (_, new) in new } - } let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "queryNotices") headerParameters.merge(sdkHeaders) { (_, new) in new } headerParameters["Accept"] = "application/json" + if let headers = headers { + headerParameters.merge(headers) { (_, new) in new } + } // construct query parameters var queryParameters = [URLQueryItem]() @@ -717,13 +809,13 @@ public class Discovery { // construct REST request let path = "/v2/projects/\(projectID)/notices" guard let encodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { - completionHandler(nil, WatsonError.urlEncoding(path: path)) + completionHandler(nil, RestError.urlEncoding(path: path)) return } // ensure that serviceURL is set guard let serviceEndpoint = serviceURL else { - completionHandler(nil, WatsonError.noEndpoint) + completionHandler(nil, RestError.noEndpoint) return } @@ -761,12 +853,12 @@ public class Discovery { { // construct header parameters var headerParameters = defaultHeaders - if let headers = headers { - headerParameters.merge(headers) { (_, new) in new } - } let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "listFields") headerParameters.merge(sdkHeaders) { (_, new) in new } headerParameters["Accept"] = "application/json" + if let headers = headers { + headerParameters.merge(headers) { (_, new) in new } + } // construct query parameters var queryParameters = [URLQueryItem]() @@ -779,13 +871,13 @@ public class Discovery { // construct REST request let path = "/v2/projects/\(projectID)/fields" guard let encodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { - completionHandler(nil, WatsonError.urlEncoding(path: path)) + completionHandler(nil, RestError.urlEncoding(path: path)) return } // ensure that serviceURL is set guard let serviceEndpoint = serviceURL else { - completionHandler(nil, WatsonError.noEndpoint) + completionHandler(nil, RestError.noEndpoint) return } @@ -820,12 +912,12 @@ public class Discovery { { // construct header parameters var headerParameters = defaultHeaders - if let headers = headers { - headerParameters.merge(headers) { (_, new) in new } - } let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "getComponentSettings") headerParameters.merge(sdkHeaders) { (_, new) in new } headerParameters["Accept"] = "application/json" + if let headers = headers { + headerParameters.merge(headers) { (_, new) in new } + } // construct query parameters var queryParameters = [URLQueryItem]() @@ -834,13 +926,13 @@ public class Discovery { // construct REST request let path = "/v2/projects/\(projectID)/component_settings" guard let encodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { - completionHandler(nil, WatsonError.urlEncoding(path: path)) + completionHandler(nil, RestError.urlEncoding(path: path)) return } // ensure that serviceURL is set guard let serviceEndpoint = serviceURL else { - completionHandler(nil, WatsonError.noEndpoint) + completionHandler(nil, RestError.noEndpoint) return } @@ -920,15 +1012,12 @@ public class Discovery { } } guard let body = try? multipartFormData.toData() else { - completionHandler(nil, WatsonError.serialization(values: "request multipart form data")) + completionHandler(nil, RestError.serialization(values: "request multipart form data")) return } // construct header parameters var headerParameters = defaultHeaders - if let headers = headers { - headerParameters.merge(headers) { (_, new) in new } - } let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "addDocument") headerParameters.merge(sdkHeaders) { (_, new) in new } headerParameters["Accept"] = "application/json" @@ -936,6 +1025,9 @@ public class Discovery { if let xWatsonDiscoveryForce = xWatsonDiscoveryForce { headerParameters["X-Watson-Discovery-Force"] = "\(xWatsonDiscoveryForce)" } + if let headers = headers { + headerParameters.merge(headers) { (_, new) in new } + } // construct query parameters var queryParameters = [URLQueryItem]() @@ -944,13 +1036,13 @@ public class Discovery { // construct REST request let path = "/v2/projects/\(projectID)/collections/\(collectionID)/documents" guard let encodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { - completionHandler(nil, WatsonError.urlEncoding(path: path)) + completionHandler(nil, RestError.urlEncoding(path: path)) return } // ensure that serviceURL is set guard let serviceEndpoint = serviceURL else { - completionHandler(nil, WatsonError.noEndpoint) + completionHandler(nil, RestError.noEndpoint) return } @@ -1026,15 +1118,12 @@ public class Discovery { } } guard let body = try? multipartFormData.toData() else { - completionHandler(nil, WatsonError.serialization(values: "request multipart form data")) + completionHandler(nil, RestError.serialization(values: "request multipart form data")) return } // construct header parameters var headerParameters = defaultHeaders - if let headers = headers { - headerParameters.merge(headers) { (_, new) in new } - } let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "updateDocument") headerParameters.merge(sdkHeaders) { (_, new) in new } headerParameters["Accept"] = "application/json" @@ -1042,6 +1131,9 @@ public class Discovery { if let xWatsonDiscoveryForce = xWatsonDiscoveryForce { headerParameters["X-Watson-Discovery-Force"] = "\(xWatsonDiscoveryForce)" } + if let headers = headers { + headerParameters.merge(headers) { (_, new) in new } + } // construct query parameters var queryParameters = [URLQueryItem]() @@ -1050,13 +1142,13 @@ public class Discovery { // construct REST request let path = "/v2/projects/\(projectID)/collections/\(collectionID)/documents/\(documentID)" guard let encodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { - completionHandler(nil, WatsonError.urlEncoding(path: path)) + completionHandler(nil, RestError.urlEncoding(path: path)) return } // ensure that serviceURL is set guard let serviceEndpoint = serviceURL else { - completionHandler(nil, WatsonError.noEndpoint) + completionHandler(nil, RestError.noEndpoint) return } @@ -1104,15 +1196,15 @@ public class Discovery { { // construct header parameters var headerParameters = defaultHeaders - if let headers = headers { - headerParameters.merge(headers) { (_, new) in new } - } let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "deleteDocument") headerParameters.merge(sdkHeaders) { (_, new) in new } headerParameters["Accept"] = "application/json" if let xWatsonDiscoveryForce = xWatsonDiscoveryForce { headerParameters["X-Watson-Discovery-Force"] = "\(xWatsonDiscoveryForce)" } + if let headers = headers { + headerParameters.merge(headers) { (_, new) in new } + } // construct query parameters var queryParameters = [URLQueryItem]() @@ -1121,13 +1213,13 @@ public class Discovery { // construct REST request let path = "/v2/projects/\(projectID)/collections/\(collectionID)/documents/\(documentID)" guard let encodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { - completionHandler(nil, WatsonError.urlEncoding(path: path)) + completionHandler(nil, RestError.urlEncoding(path: path)) return } // ensure that serviceURL is set guard let serviceEndpoint = serviceURL else { - completionHandler(nil, WatsonError.noEndpoint) + completionHandler(nil, RestError.noEndpoint) return } @@ -1162,12 +1254,12 @@ public class Discovery { { // construct header parameters var headerParameters = defaultHeaders - if let headers = headers { - headerParameters.merge(headers) { (_, new) in new } - } let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "listTrainingQueries") headerParameters.merge(sdkHeaders) { (_, new) in new } headerParameters["Accept"] = "application/json" + if let headers = headers { + headerParameters.merge(headers) { (_, new) in new } + } // construct query parameters var queryParameters = [URLQueryItem]() @@ -1176,13 +1268,13 @@ public class Discovery { // construct REST request let path = "/v2/projects/\(projectID)/training_data/queries" guard let encodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { - completionHandler(nil, WatsonError.urlEncoding(path: path)) + completionHandler(nil, RestError.urlEncoding(path: path)) return } // ensure that serviceURL is set guard let serviceEndpoint = serviceURL else { - completionHandler(nil, WatsonError.noEndpoint) + completionHandler(nil, RestError.noEndpoint) return } @@ -1217,11 +1309,11 @@ public class Discovery { { // construct header parameters var headerParameters = defaultHeaders + let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "deleteTrainingQueries") + headerParameters.merge(sdkHeaders) { (_, new) in new } if let headers = headers { headerParameters.merge(headers) { (_, new) in new } } - let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "deleteTrainingQueries") - headerParameters.merge(sdkHeaders) { (_, new) in new } // construct query parameters var queryParameters = [URLQueryItem]() @@ -1230,13 +1322,13 @@ public class Discovery { // construct REST request let path = "/v2/projects/\(projectID)/training_data/queries" guard let encodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { - completionHandler(nil, WatsonError.urlEncoding(path: path)) + completionHandler(nil, RestError.urlEncoding(path: path)) return } // ensure that serviceURL is set guard let serviceEndpoint = serviceURL else { - completionHandler(nil, WatsonError.noEndpoint) + completionHandler(nil, RestError.noEndpoint) return } @@ -1276,24 +1368,24 @@ public class Discovery { completionHandler: @escaping (WatsonResponse?, WatsonError?) -> Void) { // construct body - let createTrainingQueryRequest = TrainingQuery( - naturalLanguageQuery: naturalLanguageQuery, + let createTrainingQueryRequest = CreateTrainingQueryRequest( + natural_language_query: naturalLanguageQuery, examples: examples, filter: filter) guard let body = try? JSON.encoder.encode(createTrainingQueryRequest) else { - completionHandler(nil, WatsonError.serialization(values: "request body")) + completionHandler(nil, RestError.serialization(values: "request body")) return } // construct header parameters var headerParameters = defaultHeaders - if let headers = headers { - headerParameters.merge(headers) { (_, new) in new } - } let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "createTrainingQuery") headerParameters.merge(sdkHeaders) { (_, new) in new } headerParameters["Accept"] = "application/json" headerParameters["Content-Type"] = "application/json" + if let headers = headers { + headerParameters.merge(headers) { (_, new) in new } + } // construct query parameters var queryParameters = [URLQueryItem]() @@ -1302,13 +1394,13 @@ public class Discovery { // construct REST request let path = "/v2/projects/\(projectID)/training_data/queries" guard let encodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { - completionHandler(nil, WatsonError.urlEncoding(path: path)) + completionHandler(nil, RestError.urlEncoding(path: path)) return } // ensure that serviceURL is set guard let serviceEndpoint = serviceURL else { - completionHandler(nil, WatsonError.noEndpoint) + completionHandler(nil, RestError.noEndpoint) return } @@ -1327,6 +1419,15 @@ public class Discovery { request.responseObject(completionHandler: completionHandler) } + // Private struct for the createTrainingQuery request body + private struct CreateTrainingQueryRequest: Encodable { + // swiftlint:disable identifier_name + let natural_language_query: String + let examples: [TrainingExample] + let filter: String? + // swiftlint:enable identifier_name + } + /** Get a training data query. @@ -1346,12 +1447,12 @@ public class Discovery { { // construct header parameters var headerParameters = defaultHeaders - if let headers = headers { - headerParameters.merge(headers) { (_, new) in new } - } let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "getTrainingQuery") headerParameters.merge(sdkHeaders) { (_, new) in new } headerParameters["Accept"] = "application/json" + if let headers = headers { + headerParameters.merge(headers) { (_, new) in new } + } // construct query parameters var queryParameters = [URLQueryItem]() @@ -1360,13 +1461,13 @@ public class Discovery { // construct REST request let path = "/v2/projects/\(projectID)/training_data/queries/\(queryID)" guard let encodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { - completionHandler(nil, WatsonError.urlEncoding(path: path)) + completionHandler(nil, RestError.urlEncoding(path: path)) return } // ensure that serviceURL is set guard let serviceEndpoint = serviceURL else { - completionHandler(nil, WatsonError.noEndpoint) + completionHandler(nil, RestError.noEndpoint) return } @@ -1408,24 +1509,24 @@ public class Discovery { completionHandler: @escaping (WatsonResponse?, WatsonError?) -> Void) { // construct body - let updateTrainingQueryRequest = TrainingQuery( - naturalLanguageQuery: naturalLanguageQuery, + let updateTrainingQueryRequest = UpdateTrainingQueryRequest( + natural_language_query: naturalLanguageQuery, examples: examples, filter: filter) guard let body = try? JSON.encoder.encode(updateTrainingQueryRequest) else { - completionHandler(nil, WatsonError.serialization(values: "request body")) + completionHandler(nil, RestError.serialization(values: "request body")) return } // construct header parameters var headerParameters = defaultHeaders - if let headers = headers { - headerParameters.merge(headers) { (_, new) in new } - } let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "updateTrainingQuery") headerParameters.merge(sdkHeaders) { (_, new) in new } headerParameters["Accept"] = "application/json" headerParameters["Content-Type"] = "application/json" + if let headers = headers { + headerParameters.merge(headers) { (_, new) in new } + } // construct query parameters var queryParameters = [URLQueryItem]() @@ -1434,13 +1535,113 @@ public class Discovery { // construct REST request let path = "/v2/projects/\(projectID)/training_data/queries/\(queryID)" guard let encodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { - completionHandler(nil, WatsonError.urlEncoding(path: path)) + completionHandler(nil, RestError.urlEncoding(path: path)) return } // ensure that serviceURL is set guard let serviceEndpoint = serviceURL else { - completionHandler(nil, WatsonError.noEndpoint) + completionHandler(nil, RestError.noEndpoint) + return + } + + let request = RestRequest( + session: session, + authenticator: authenticator, + errorResponseDecoder: errorResponseDecoder, + method: "POST", + url: serviceEndpoint + encodedPath, + headerParameters: headerParameters, + queryItems: queryParameters, + messageBody: body + ) + + // execute REST request + request.responseObject(completionHandler: completionHandler) + } + + // Private struct for the updateTrainingQuery request body + private struct UpdateTrainingQueryRequest: Encodable { + // swiftlint:disable identifier_name + let natural_language_query: String + let examples: [TrainingExample] + let filter: String? + // swiftlint:enable identifier_name + } + + /** + Analyze a Document. + + Process a document using the specified collection's settings and return it for realtime use. + **Note:** Documents processed using this method are not added to the specified collection. + **Note:** This method is only supported on IBM Cloud Pak for Data instances of Discovery. + + - parameter projectID: The ID of the project. This information can be found from the deploy page of the Discovery + administrative tooling. + - parameter collectionID: The ID of the collection. + - parameter file: The content of the document to ingest. The maximum supported file size when adding a file to a + collection is 50 megabytes, the maximum supported file size when testing a configuration is 1 megabyte. Files + larger than the supported size are rejected. + - parameter filename: The filename for file. + - parameter fileContentType: The content type of file. + - parameter metadata: The maximum supported metadata file size is 1 MB. Metadata parts larger than 1 MB are + rejected. + Example: ``` { + "Creator": "Johnny Appleseed", + "Subject": "Apples" + } ```. + - parameter headers: A dictionary of request headers to be sent with this request. + - parameter completionHandler: A function executed when the request completes with a successful result or error + */ + public func analyzeDocument( + projectID: String, + collectionID: String, + file: Data? = nil, + filename: String? = nil, + fileContentType: String? = nil, + metadata: String? = nil, + headers: [String: String]? = nil, + completionHandler: @escaping (WatsonResponse?, WatsonError?) -> Void) + { + // construct body + let multipartFormData = MultipartFormData() + if let file = file { + multipartFormData.append(file, withName: "file", mimeType: fileContentType, fileName: filename ?? "filename") + } + if let metadata = metadata { + if let metadataData = metadata.data(using: .utf8) { + multipartFormData.append(metadataData, withName: "metadata") + } + } + guard let body = try? multipartFormData.toData() else { + completionHandler(nil, RestError.serialization(values: "request multipart form data")) + return + } + + // construct header parameters + var headerParameters = defaultHeaders + let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "analyzeDocument") + headerParameters.merge(sdkHeaders) { (_, new) in new } + headerParameters["Accept"] = "application/json" + headerParameters["Content-Type"] = multipartFormData.contentType + if let headers = headers { + headerParameters.merge(headers) { (_, new) in new } + } + + // construct query parameters + var queryParameters = [URLQueryItem]() + queryParameters.append(URLQueryItem(name: "version", value: version)) + + // construct REST request + let path = "/v2/projects/\(projectID)/collections/\(collectionID)/analyze" + guard let encodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { + completionHandler(nil, RestError.urlEncoding(path: path)) + return + } + + // ensure that serviceURL is set + guard let serviceEndpoint = serviceURL else { + completionHandler(nil, RestError.noEndpoint) return } @@ -1476,12 +1677,12 @@ public class Discovery { { // construct header parameters var headerParameters = defaultHeaders - if let headers = headers { - headerParameters.merge(headers) { (_, new) in new } - } let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "listEnrichments") headerParameters.merge(sdkHeaders) { (_, new) in new } headerParameters["Accept"] = "application/json" + if let headers = headers { + headerParameters.merge(headers) { (_, new) in new } + } // construct query parameters var queryParameters = [URLQueryItem]() @@ -1490,13 +1691,13 @@ public class Discovery { // construct REST request let path = "/v2/projects/\(projectID)/enrichments" guard let encodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { - completionHandler(nil, WatsonError.urlEncoding(path: path)) + completionHandler(nil, RestError.urlEncoding(path: path)) return } // ensure that serviceURL is set guard let serviceEndpoint = serviceURL else { - completionHandler(nil, WatsonError.noEndpoint) + completionHandler(nil, RestError.noEndpoint) return } @@ -1535,32 +1736,26 @@ public class Discovery { { // construct body let multipartFormData = MultipartFormData() - - if let file = file { - multipartFormData.append(file, withName: "file", mimeType: "application/octet-stream", fileName: "filename") + if let enrichmentData = "\(enrichment)".data(using: .utf8) { + multipartFormData.append(enrichmentData, withName: "enrichment") } - - guard let enrichmentJSON = try? JSON.encoder.encode(enrichment) else { - completionHandler(nil, WatsonError.serialization(values: "request body")) - return + if let file = file { + multipartFormData.append(file, withName: "file", fileName: "filename") } - - multipartFormData.append(enrichmentJSON, withName: "enrichment") - guard let body = try? multipartFormData.toData() else { - completionHandler(nil, WatsonError.serialization(values: "request multipart form data")) + completionHandler(nil, RestError.serialization(values: "request multipart form data")) return } // construct header parameters var headerParameters = defaultHeaders - if let headers = headers { - headerParameters.merge(headers) { (_, new) in new } - } let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "createEnrichment") headerParameters.merge(sdkHeaders) { (_, new) in new } headerParameters["Accept"] = "application/json" headerParameters["Content-Type"] = multipartFormData.contentType + if let headers = headers { + headerParameters.merge(headers) { (_, new) in new } + } // construct query parameters var queryParameters = [URLQueryItem]() @@ -1569,13 +1764,13 @@ public class Discovery { // construct REST request let path = "/v2/projects/\(projectID)/enrichments" guard let encodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { - completionHandler(nil, WatsonError.urlEncoding(path: path)) + completionHandler(nil, RestError.urlEncoding(path: path)) return } // ensure that serviceURL is set guard let serviceEndpoint = serviceURL else { - completionHandler(nil, WatsonError.noEndpoint) + completionHandler(nil, RestError.noEndpoint) return } @@ -1613,12 +1808,12 @@ public class Discovery { { // construct header parameters var headerParameters = defaultHeaders - if let headers = headers { - headerParameters.merge(headers) { (_, new) in new } - } let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "getEnrichment") headerParameters.merge(sdkHeaders) { (_, new) in new } headerParameters["Accept"] = "application/json" + if let headers = headers { + headerParameters.merge(headers) { (_, new) in new } + } // construct query parameters var queryParameters = [URLQueryItem]() @@ -1627,13 +1822,13 @@ public class Discovery { // construct REST request let path = "/v2/projects/\(projectID)/enrichments/\(enrichmentID)" guard let encodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { - completionHandler(nil, WatsonError.urlEncoding(path: path)) + completionHandler(nil, RestError.urlEncoding(path: path)) return } // ensure that serviceURL is set guard let serviceEndpoint = serviceURL else { - completionHandler(nil, WatsonError.noEndpoint) + completionHandler(nil, RestError.noEndpoint) return } @@ -1673,23 +1868,23 @@ public class Discovery { completionHandler: @escaping (WatsonResponse?, WatsonError?) -> Void) { // construct body - let updateEnrichmentRequest = UpdateEnrichment( + let updateEnrichmentRequest = UpdateEnrichmentRequest( name: name, description: description) guard let body = try? JSON.encoder.encode(updateEnrichmentRequest) else { - completionHandler(nil, WatsonError.serialization(values: "request body")) + completionHandler(nil, RestError.serialization(values: "request body")) return } // construct header parameters var headerParameters = defaultHeaders - if let headers = headers { - headerParameters.merge(headers) { (_, new) in new } - } let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "updateEnrichment") headerParameters.merge(sdkHeaders) { (_, new) in new } headerParameters["Accept"] = "application/json" headerParameters["Content-Type"] = "application/json" + if let headers = headers { + headerParameters.merge(headers) { (_, new) in new } + } // construct query parameters var queryParameters = [URLQueryItem]() @@ -1698,13 +1893,13 @@ public class Discovery { // construct REST request let path = "/v2/projects/\(projectID)/enrichments/\(enrichmentID)" guard let encodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { - completionHandler(nil, WatsonError.urlEncoding(path: path)) + completionHandler(nil, RestError.urlEncoding(path: path)) return } // ensure that serviceURL is set guard let serviceEndpoint = serviceURL else { - completionHandler(nil, WatsonError.noEndpoint) + completionHandler(nil, RestError.noEndpoint) return } @@ -1723,6 +1918,14 @@ public class Discovery { request.responseObject(completionHandler: completionHandler) } + // Private struct for the updateEnrichment request body + private struct UpdateEnrichmentRequest: Encodable { + // swiftlint:disable identifier_name + let name: String + let description: String? + // swiftlint:enable identifier_name + } + /** Delete an enrichment. @@ -1743,11 +1946,11 @@ public class Discovery { { // construct header parameters var headerParameters = defaultHeaders + let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "deleteEnrichment") + headerParameters.merge(sdkHeaders) { (_, new) in new } if let headers = headers { headerParameters.merge(headers) { (_, new) in new } } - let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "deleteEnrichment") - headerParameters.merge(sdkHeaders) { (_, new) in new } // construct query parameters var queryParameters = [URLQueryItem]() @@ -1756,13 +1959,13 @@ public class Discovery { // construct REST request let path = "/v2/projects/\(projectID)/enrichments/\(enrichmentID)" guard let encodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { - completionHandler(nil, WatsonError.urlEncoding(path: path)) + completionHandler(nil, RestError.urlEncoding(path: path)) return } // ensure that serviceURL is set guard let serviceEndpoint = serviceURL else { - completionHandler(nil, WatsonError.noEndpoint) + completionHandler(nil, RestError.noEndpoint) return } @@ -1794,12 +1997,12 @@ public class Discovery { { // construct header parameters var headerParameters = defaultHeaders - if let headers = headers { - headerParameters.merge(headers) { (_, new) in new } - } let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "listProjects") headerParameters.merge(sdkHeaders) { (_, new) in new } headerParameters["Accept"] = "application/json" + if let headers = headers { + headerParameters.merge(headers) { (_, new) in new } + } // construct query parameters var queryParameters = [URLQueryItem]() @@ -1809,7 +2012,7 @@ public class Discovery { // ensure that serviceURL is set guard let serviceEndpoint = serviceURL else { - completionHandler(nil, WatsonError.noEndpoint) + completionHandler(nil, RestError.noEndpoint) return } @@ -1846,24 +2049,24 @@ public class Discovery { completionHandler: @escaping (WatsonResponse?, WatsonError?) -> Void) { // construct body - let createProjectRequest = ProjectCreation( + let createProjectRequest = CreateProjectRequest( name: name, type: type, - defaultQueryParameters: defaultQueryParameters) + default_query_parameters: defaultQueryParameters) guard let body = try? JSON.encoder.encode(createProjectRequest) else { - completionHandler(nil, WatsonError.serialization(values: "request body")) + completionHandler(nil, RestError.serialization(values: "request body")) return } // construct header parameters var headerParameters = defaultHeaders - if let headers = headers { - headerParameters.merge(headers) { (_, new) in new } - } let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "createProject") headerParameters.merge(sdkHeaders) { (_, new) in new } headerParameters["Accept"] = "application/json" headerParameters["Content-Type"] = "application/json" + if let headers = headers { + headerParameters.merge(headers) { (_, new) in new } + } // construct query parameters var queryParameters = [URLQueryItem]() @@ -1873,7 +2076,7 @@ public class Discovery { // ensure that serviceURL is set guard let serviceEndpoint = serviceURL else { - completionHandler(nil, WatsonError.noEndpoint) + completionHandler(nil, RestError.noEndpoint) return } @@ -1892,6 +2095,15 @@ public class Discovery { request.responseObject(completionHandler: completionHandler) } + // Private struct for the createProject request body + private struct CreateProjectRequest: Encodable { + // swiftlint:disable identifier_name + let name: String + let type: String + let default_query_parameters: DefaultQueryParams? + // swiftlint:enable identifier_name + } + /** Get project. @@ -1909,12 +2121,12 @@ public class Discovery { { // construct header parameters var headerParameters = defaultHeaders - if let headers = headers { - headerParameters.merge(headers) { (_, new) in new } - } let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "getProject") headerParameters.merge(sdkHeaders) { (_, new) in new } headerParameters["Accept"] = "application/json" + if let headers = headers { + headerParameters.merge(headers) { (_, new) in new } + } // construct query parameters var queryParameters = [URLQueryItem]() @@ -1923,13 +2135,13 @@ public class Discovery { // construct REST request let path = "/v2/projects/\(projectID)" guard let encodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { - completionHandler(nil, WatsonError.urlEncoding(path: path)) + completionHandler(nil, RestError.urlEncoding(path: path)) return } // ensure that serviceURL is set guard let serviceEndpoint = serviceURL else { - completionHandler(nil, WatsonError.noEndpoint) + completionHandler(nil, RestError.noEndpoint) return } @@ -1965,22 +2177,25 @@ public class Discovery { completionHandler: @escaping (WatsonResponse?, WatsonError?) -> Void) { // construct body - let updateProjectRequest = ProjectName( + let updateProjectRequest = UpdateProjectRequest( name: name) - guard let body = try? JSON.encoder.encodeIfPresent(updateProjectRequest) else { - completionHandler(nil, WatsonError.serialization(values: "request body")) + let body: Data? + do { + body = try JSON.encoder.encodeIfPresent(updateProjectRequest) + } catch { + completionHandler(nil, RestError.serialization(values: "request body")) return } // construct header parameters var headerParameters = defaultHeaders - if let headers = headers { - headerParameters.merge(headers) { (_, new) in new } - } let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "updateProject") headerParameters.merge(sdkHeaders) { (_, new) in new } headerParameters["Accept"] = "application/json" headerParameters["Content-Type"] = "application/json" + if let headers = headers { + headerParameters.merge(headers) { (_, new) in new } + } // construct query parameters var queryParameters = [URLQueryItem]() @@ -1989,13 +2204,13 @@ public class Discovery { // construct REST request let path = "/v2/projects/\(projectID)" guard let encodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { - completionHandler(nil, WatsonError.urlEncoding(path: path)) + completionHandler(nil, RestError.urlEncoding(path: path)) return } // ensure that serviceURL is set guard let serviceEndpoint = serviceURL else { - completionHandler(nil, WatsonError.noEndpoint) + completionHandler(nil, RestError.noEndpoint) return } @@ -2014,6 +2229,19 @@ public class Discovery { request.responseObject(completionHandler: completionHandler) } + // Private struct for the updateProject request body + private struct UpdateProjectRequest: Encodable { + // swiftlint:disable identifier_name + let name: String? + init? (name: String? = nil) { + if name == nil { + return nil + } + self.name = name + } + // swiftlint:enable identifier_name + } + /** Delete a project. @@ -2033,11 +2261,11 @@ public class Discovery { { // construct header parameters var headerParameters = defaultHeaders + let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "deleteProject") + headerParameters.merge(sdkHeaders) { (_, new) in new } if let headers = headers { headerParameters.merge(headers) { (_, new) in new } } - let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "deleteProject") - headerParameters.merge(sdkHeaders) { (_, new) in new } // construct query parameters var queryParameters = [URLQueryItem]() @@ -2046,13 +2274,13 @@ public class Discovery { // construct REST request let path = "/v2/projects/\(projectID)" guard let encodedPath = path.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { - completionHandler(nil, WatsonError.urlEncoding(path: path)) + completionHandler(nil, RestError.urlEncoding(path: path)) return } // ensure that serviceURL is set guard let serviceEndpoint = serviceURL else { - completionHandler(nil, WatsonError.noEndpoint) + completionHandler(nil, RestError.noEndpoint) return } @@ -2091,11 +2319,11 @@ public class Discovery { { // construct header parameters var headerParameters = defaultHeaders + let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "deleteUserData") + headerParameters.merge(sdkHeaders) { (_, new) in new } if let headers = headers { headerParameters.merge(headers) { (_, new) in new } } - let sdkHeaders = Shared.getSDKHeaders(serviceName: serviceName, serviceVersion: serviceVersion, methodName: "deleteUserData") - headerParameters.merge(sdkHeaders) { (_, new) in new } // construct query parameters var queryParameters = [URLQueryItem]() @@ -2106,7 +2334,7 @@ public class Discovery { // ensure that serviceURL is set guard let serviceEndpoint = serviceURL else { - completionHandler(nil, WatsonError.noEndpoint) + completionHandler(nil, RestError.noEndpoint) return } diff --git a/Sources/DiscoveryV2/Models/AnalyzedDocument.swift b/Sources/DiscoveryV2/Models/AnalyzedDocument.swift new file mode 100644 index 000000000..2e0f27273 --- /dev/null +++ b/Sources/DiscoveryV2/Models/AnalyzedDocument.swift @@ -0,0 +1,40 @@ +/** + * (C) Copyright IBM Corp. 2020. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +import Foundation + +/** + An object containing the converted document and any identified enrichments. + */ +public struct AnalyzedDocument: Codable, Equatable { + + /** + Array of document results that match the query. + */ + public var notices: [Notice]? + + /** + Result of the document analysis. + */ + public var result: AnalyzedResult? + + // Map each property name to the key that shall be used for encoding/decoding. + private enum CodingKeys: String, CodingKey { + case notices = "notices" + case result = "result" + } + +} diff --git a/Sources/DiscoveryV2/Models/AnalyzedResult.swift b/Sources/DiscoveryV2/Models/AnalyzedResult.swift new file mode 100644 index 000000000..56e73222d --- /dev/null +++ b/Sources/DiscoveryV2/Models/AnalyzedResult.swift @@ -0,0 +1,53 @@ +/** + * (C) Copyright IBM Corp. 2020. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +import Foundation +import IBMSwiftSDKCore + +/** + Result of the document analysis. + */ +public struct AnalyzedResult: Codable, Equatable { + + /** + Metadata of the document. + */ + public var metadata: [String: JSON]? + + /// Additional properties associated with this model. + public var additionalProperties: [String: JSON] + + // Map each property name to the key that shall be used for encoding/decoding. + private enum CodingKeys: String, CodingKey { + case metadata = "metadata" + static let allValues = [metadata] + } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + metadata = try container.decodeIfPresent([String: JSON].self, forKey: .metadata) + let dynamicContainer = try decoder.container(keyedBy: DynamicKeys.self) + additionalProperties = try dynamicContainer.decode([String: JSON].self, excluding: CodingKeys.allValues) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encodeIfPresent(metadata, forKey: .metadata) + var dynamicContainer = encoder.container(keyedBy: DynamicKeys.self) + try dynamicContainer.encodeIfPresent(additionalProperties) + } + +} diff --git a/Sources/DiscoveryV2/Models/CollectionDetails.swift b/Sources/DiscoveryV2/Models/CollectionDetails.swift index abdca9f71..a3847ae15 100644 --- a/Sources/DiscoveryV2/Models/CollectionDetails.swift +++ b/Sources/DiscoveryV2/Models/CollectionDetails.swift @@ -65,9 +65,7 @@ public struct CollectionDetails: Codable, Equatable { Initialize a `CollectionDetails` with member variables. - parameter name: The name of the collection. - - parameter collectionID: The unique identifier of the collection. - parameter description: A description of the collection. - - parameter created: The date that the collection was created. - parameter language: The language of the collection. - parameter enrichments: An array of enrichments that are applied to this collection. @@ -75,17 +73,13 @@ public struct CollectionDetails: Codable, Equatable { */ public init( name: String, - collectionID: String? = nil, description: String? = nil, - created: Date? = nil, language: String? = nil, enrichments: [CollectionEnrichment]? = nil ) { self.name = name - self.collectionID = collectionID self.description = description - self.created = created self.language = language self.enrichments = enrichments } diff --git a/Sources/DiscoveryV2/Models/QueryAggregation.swift b/Sources/DiscoveryV2/Models/QueryAggregation.swift index 28e03676a..3bad05992 100644 --- a/Sources/DiscoveryV2/Models/QueryAggregation.swift +++ b/Sources/DiscoveryV2/Models/QueryAggregation.swift @@ -1,5 +1,5 @@ /** - * (C) Copyright IBM Corp. 2019. + * (C) Copyright IBM Corp. 2020. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,91 +16,145 @@ import Foundation -/** An aggregation produced by the Discovery service to analyze the input provided. */ +/** + An abstract aggregation type produced by Discovery to analyze the input provided. + */ public enum QueryAggregation: Codable, Equatable { - // reference: https://cloud.ibm.com/docs/services/discovery/query-reference.html#aggregations - + case queryAggregation(GenericQueryAggregation) case term(QueryTermAggregation) - case filter(QueryFilterAggregation) - case nested(QueryNestedAggregation) case histogram(QueryHistogramAggregation) case timeslice(QueryTimesliceAggregation) - case topHits(QueryTopHitsAggregation) - case uniqueCount(QueryCalculationAggregation) - case max(QueryCalculationAggregation) + case nested(QueryNestedAggregation) + case filter(QueryFilterAggregation) case min(QueryCalculationAggregation) - case average(QueryCalculationAggregation) + case max(QueryCalculationAggregation) case sum(QueryCalculationAggregation) - case generic(GenericQueryAggregation) - - private enum CodingKeys: String, CodingKey { - case type = "type" - } + case average(QueryCalculationAggregation) + case uniqueCount(QueryCalculationAggregation) + case topHits(QueryTopHitsAggregation) + case groupBy(QueryGroupByAggregation) public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - guard let type = try container.decodeIfPresent(String.self, forKey: .type) else { - // the specification does not identify `type` as a required field, - // so we need a generic catch-all in case it is not present - self = .generic(try GenericQueryAggregation(from: decoder)) - return - } - switch type { - case "term": self = .term(try QueryTermAggregation(from: decoder)) - case "filter": self = .filter(try QueryFilterAggregation(from: decoder)) - case "nested": self = .nested(try QueryNestedAggregation(from: decoder)) - case "histogram": self = .histogram(try QueryHistogramAggregation(from: decoder)) - case "timeslice": self = .timeslice(try QueryTimesliceAggregation(from: decoder)) - case "top_hits": self = .topHits(try QueryTopHitsAggregation(from: decoder)) - case "unique_count": self = .uniqueCount(try QueryCalculationAggregation(from: decoder)) - case "max": self = .max(try QueryCalculationAggregation(from: decoder)) - case "min": self = .min(try QueryCalculationAggregation(from: decoder)) - case "average": self = .average(try QueryCalculationAggregation(from: decoder)) - case "sum": self = .sum(try QueryCalculationAggregation(from: decoder)) - default: self = .generic(try GenericQueryAggregation(from: decoder)) + let container = try decoder.singleValueContainer() + if let genericInstance = try? container.decode(GenericQueryAggregation.self) { + switch genericInstance.type { + case "term": + if let val = try? container.decode(QueryTermAggregation.self) { + self = .term(val) + return + } + case "histogram": + if let val = try? container.decode(QueryHistogramAggregation.self) { + self = .histogram(val) + return + } + case "timeslice": + if let val = try? container.decode(QueryTimesliceAggregation.self) { + self = .timeslice(val) + return + } + case "nested": + if let val = try? container.decode(QueryNestedAggregation.self) { + self = .nested(val) + return + } + case "filter": + if let val = try? container.decode(QueryFilterAggregation.self) { + self = .filter(val) + return + } + case "min": + if let val = try? container.decode(QueryCalculationAggregation.self) { + self = .min(val) + return + } + case "max": + if let val = try? container.decode(QueryCalculationAggregation.self) { + self = .max(val) + return + } + case "sum": + if let val = try? container.decode(QueryCalculationAggregation.self) { + self = .sum(val) + return + } + case "average": + if let val = try? container.decode(QueryCalculationAggregation.self) { + self = .average(val) + return + } + case "unique_count": + if let val = try? container.decode(QueryCalculationAggregation.self) { + self = .uniqueCount(val) + return + } + case "top_hits": + if let val = try? container.decode(QueryTopHitsAggregation.self) { + self = .topHits(val) + return + } + case "group_by": + if let val = try? container.decode(QueryGroupByAggregation.self) { + self = .groupBy(val) + return + } + default: + if let val = try? container.decode(GenericQueryAggregation.self) { + self = .queryAggregation(val) + return + } + } } + + throw DecodingError.typeMismatch(QueryAggregation.self, + DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Decoding failed for all associated types")) } public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) + var container = encoder.singleValueContainer() switch self { + case .queryAggregation(let queryAggregation): + try container.encode(queryAggregation) case .term(let term): - try container.encode("term", forKey: .type) - try term.encode(to: encoder) - case .filter(let filter): - try container.encode("filter", forKey: .type) - try filter.encode(to: encoder) - case .nested(let nested): - try container.encode("nested", forKey: .type) - try nested.encode(to: encoder) + try container.encode(term) case .histogram(let histogram): - try container.encode("histogram", forKey: .type) - try histogram.encode(to: encoder) + try container.encode(histogram) case .timeslice(let timeslice): - try container.encode("timeslice", forKey: .type) - try timeslice.encode(to: encoder) - case .topHits(let topHits): - try container.encode("top_hits", forKey: .type) - try topHits.encode(to: encoder) - case .uniqueCount(let uniqueCount): - try container.encode("unique_count", forKey: .type) - try uniqueCount.encode(to: encoder) - case .max(let max): - try container.encode("max", forKey: .type) - try max.encode(to: encoder) + try container.encode(timeslice) + case .nested(let nested): + try container.encode(nested) + case .filter(let filter): + try container.encode(filter) case .min(let min): - try container.encode("min", forKey: .type) - try min.encode(to: encoder) - case .average(let average): - try container.encode("average", forKey: .type) - try average.encode(to: encoder) + try container.encode(min) + case .max(let max): + try container.encode(max) case .sum(let sum): - try container.encode("sum", forKey: .type) - try sum.encode(to: encoder) - case .generic(let generic): - try generic.encode(to: encoder) + try container.encode(sum) + case .average(let average): + try container.encode(average) + case .uniqueCount(let unique_count): + try container.encode(unique_count) + case .topHits(let top_hits): + try container.encode(top_hits) + case .groupBy(let group_by): + try container.encode(group_by) } } +} + +public struct GenericQueryAggregation: Codable, Equatable { + + /** + The type of aggregation command used. Options include: term, histogram, timeslice, nested, filter, min, max, sum, + average, unique_count, and top_hits. + */ + public var type: String + + // Map each property name to the key that shall be used for encoding/decoding. + private enum CodingKeys: String, CodingKey { + case type = "type" + } } diff --git a/Sources/DiscoveryV2/Models/QueryResponse.swift b/Sources/DiscoveryV2/Models/QueryResponse.swift index f218b99fc..b3f0b9e54 100644 --- a/Sources/DiscoveryV2/Models/QueryResponse.swift +++ b/Sources/DiscoveryV2/Models/QueryResponse.swift @@ -1,5 +1,5 @@ /** - * (C) Copyright IBM Corp. 2019, 2020. + * (C) Copyright IBM Corp. 2020. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -56,6 +56,11 @@ public struct QueryResponse: Codable, Equatable { */ public var tableResults: [QueryTableResult]? + /** + Passages returned by Discovery. + */ + public var passages: [QueryResponsePassage]? + // Map each property name to the key that shall be used for encoding/decoding. private enum CodingKeys: String, CodingKey { case matchingResults = "matching_results" @@ -65,6 +70,7 @@ public struct QueryResponse: Codable, Equatable { case suggestedQuery = "suggested_query" case suggestedRefinements = "suggested_refinements" case tableResults = "table_results" + case passages = "passages" } } diff --git a/Sources/DiscoveryV2/Models/QueryResponsePassage.swift b/Sources/DiscoveryV2/Models/QueryResponsePassage.swift new file mode 100644 index 000000000..ec5b76af4 --- /dev/null +++ b/Sources/DiscoveryV2/Models/QueryResponsePassage.swift @@ -0,0 +1,70 @@ +/** + * (C) Copyright IBM Corp. 2020. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +import Foundation + +/** + A passage query response. + */ +public struct QueryResponsePassage: Codable, Equatable { + + /** + The content of the extracted passage. + */ + public var passageText: String? + + /** + The confidence score of the passage's analysis. A higher score indicates greater confidence. + */ + public var passageScore: Double? + + /** + The unique identifier of the ingested document. + */ + public var documentID: String? + + /** + The unique identifier of the collection. + */ + public var collectionID: String? + + /** + The position of the first character of the extracted passage in the originating field. + */ + public var startOffset: Int? + + /** + The position of the last character of the extracted passage in the originating field. + */ + public var endOffset: Int? + + /** + The label of the field from which the passage has been extracted. + */ + public var field: String? + + // Map each property name to the key that shall be used for encoding/decoding. + private enum CodingKeys: String, CodingKey { + case passageText = "passage_text" + case passageScore = "passage_score" + case documentID = "document_id" + case collectionID = "collection_id" + case startOffset = "start_offset" + case endOffset = "end_offset" + case field = "field" + } + +} diff --git a/Sources/DiscoveryV2/Models/TrainingExample.swift b/Sources/DiscoveryV2/Models/TrainingExample.swift index feea12896..1d091526a 100644 --- a/Sources/DiscoveryV2/Models/TrainingExample.swift +++ b/Sources/DiscoveryV2/Models/TrainingExample.swift @@ -1,5 +1,5 @@ /** - * (C) Copyright IBM Corp. 2019. + * (C) Copyright IBM Corp. 2020. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -61,24 +61,18 @@ public struct TrainingExample: Codable, Equatable { - parameter documentID: The document ID associated with this training example. - parameter collectionID: The collection ID associated with this training example. - parameter relevance: The relevance of the training example. - - parameter created: The date and time the example was created. - - parameter updated: The date and time the example was updated. - returns: An initialized `TrainingExample`. */ public init( documentID: String, collectionID: String, - relevance: Int, - created: Date? = nil, - updated: Date? = nil + relevance: Int ) { self.documentID = documentID self.collectionID = collectionID self.relevance = relevance - self.created = created - self.updated = updated } } diff --git a/Sources/DiscoveryV2/Models/TrainingQuery.swift b/Sources/DiscoveryV2/Models/TrainingQuery.swift index cf861fe89..e4fe331ea 100644 --- a/Sources/DiscoveryV2/Models/TrainingQuery.swift +++ b/Sources/DiscoveryV2/Models/TrainingQuery.swift @@ -1,5 +1,5 @@ /** - * (C) Copyright IBM Corp. 2019. + * (C) Copyright IBM Corp. 2020. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -66,28 +66,19 @@ public struct TrainingQuery: Codable, Equatable { - parameter naturalLanguageQuery: The natural text query for the training query. - parameter examples: Array of training examples. - - parameter queryID: The query ID associated with the training query. - parameter filter: The filter used on the collection before the **natural_language_query** is applied. - - parameter created: The date and time the query was created. - - parameter updated: The date and time the query was updated. - returns: An initialized `TrainingQuery`. */ public init( naturalLanguageQuery: String, examples: [TrainingExample], - queryID: String? = nil, - filter: String? = nil, - created: Date? = nil, - updated: Date? = nil + filter: String? = nil ) { self.naturalLanguageQuery = naturalLanguageQuery self.examples = examples - self.queryID = queryID self.filter = filter - self.created = created - self.updated = updated } }