amplify-swift/AmplifyPlugins/Geo/Sources/AWSLocationGeoPlugin/Configuration/AWSLocationGeoPluginConfigu...

181 lines
7.3 KiB
Swift

//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//
import Amplify
import Foundation
import AWSLocation
public struct AWSLocationGeoPluginConfiguration {
let defaultMap: String?
let maps: [String: Geo.MapStyle]
let defaultSearchIndex: String?
let searchIndices: [String]
public let regionName: String
init(config: Any?) throws {
guard let configJSON = config as? JSONValue else {
throw GeoPluginConfigError.configurationInvalid(section: .plugin)
}
let configObject = try AWSLocationGeoPluginConfiguration.getConfigObject(section: .plugin,
configJSON: configJSON)
let regionName = try AWSLocationGeoPluginConfiguration.getRegion(configObject)
var maps = [String: Geo.MapStyle]()
var defaultMap: String?
if let mapsConfigJSON = configObject[Section.maps.key] {
let mapsConfigObject = try AWSLocationGeoPluginConfiguration.getConfigObject(section: .maps,
configJSON: mapsConfigJSON)
maps = try AWSLocationGeoPluginConfiguration.getMaps(mapConfig: mapsConfigObject, regionName: regionName)
defaultMap = try AWSLocationGeoPluginConfiguration.getDefault(section: .maps,
configObject: mapsConfigObject)
guard let map = defaultMap, maps[map] != nil else {
throw GeoPluginConfigError.mapDefaultNotFound(mapName: defaultMap)
}
}
var searchIndices = [String]()
var defaultSearchIndex: String?
if let searchConfigJSON = configObject[Section.searchIndices.key] {
let searchConfigObject = try AWSLocationGeoPluginConfiguration.getConfigObject(section: .searchIndices,
configJSON: searchConfigJSON)
searchIndices = try AWSLocationGeoPluginConfiguration.getItemsStrings(section: .searchIndices,
configObject: searchConfigObject)
defaultSearchIndex = try AWSLocationGeoPluginConfiguration.getDefault(section: .searchIndices,
configObject: searchConfigObject)
guard let index = defaultSearchIndex, searchIndices.contains(index) else {
throw GeoPluginConfigError.searchDefaultNotFound(indexName: defaultSearchIndex)
}
}
self.init(regionName: regionName,
defaultMap: defaultMap,
maps: maps,
defaultSearchIndex: defaultSearchIndex,
searchIndices: searchIndices)
}
init(regionName: String,
defaultMap: String?,
maps: [String: Geo.MapStyle],
defaultSearchIndex: String?,
searchIndices: [String]) {
self.regionName = regionName
self.defaultMap = defaultMap
self.maps = maps
self.defaultSearchIndex = defaultSearchIndex
self.searchIndices = searchIndices
}
// MARK: - Private helper methods
private static func getRegion(_ configObject: [String: JSONValue]) throws -> String {
guard let regionJSON = configObject[Node.region.key] else {
throw GeoPluginConfigError.regionMissing
}
guard case let .string(region) = regionJSON else {
throw GeoPluginConfigError.regionInvalid
}
if region.isEmpty {
throw GeoPluginConfigError.regionEmpty
}
guard region != "Unknown" else {
throw GeoPluginConfigError.regionMissing
}
return region
}
private static func getDefault(section: Section, configObject: [String: JSONValue]) throws -> String {
guard let defaultJSON = configObject[Node.default.key] else {
throw GeoPluginConfigError.defaultMissing(section: section)
}
guard case let .string(defaultItem) = defaultJSON else {
throw GeoPluginConfigError.defaultNotString(section: section)
}
if defaultItem.isEmpty {
throw GeoPluginConfigError.defaultIsEmpty(section: section)
}
return defaultItem
}
private static func getConfigObject(section: Section, configJSON: JSONValue) throws -> [String: JSONValue] {
guard case let .object(configObject) = configJSON else {
throw GeoPluginConfigError.configurationInvalid(section: section)
}
return configObject
}
private static func getItemsJSON(section: Section, configObject: [String: JSONValue]) throws -> JSONValue {
guard let itemsJSON = configObject[Node.items.key] else {
throw GeoPluginConfigError.itemsMissing(section: section)
}
return itemsJSON
}
private static func getItemsObject(section: Section,
configObject: [String: JSONValue]) throws -> [String: JSONValue] {
let itemsJSON = try getItemsJSON(section: section, configObject: configObject)
let itemsObject = try getConfigObject(section: section, configJSON: itemsJSON)
return itemsObject
}
private static func getItemsStrings(section: Section, configObject: [String: JSONValue]) throws -> [String] {
let itemsJSON = try getItemsJSON(section: section, configObject: configObject)
guard case let .array(itemsArray) = itemsJSON else {
throw GeoPluginConfigError.itemsInvalid(section: section)
}
let itemStrings: [String] = try itemsArray.map { item in
guard case let .string(itemString) = item else {
throw GeoPluginConfigError.itemsIsNotStringArray(section: section)
}
return itemString
}
return itemStrings
}
// MARK: - Maps
private static func getMaps(mapConfig: [String: JSONValue], regionName: String) throws -> [String: Geo.MapStyle] {
let mapItemsObject = try getItemsObject(section: .maps, configObject: mapConfig)
let mapTuples: [(String, Geo.MapStyle)] = try mapItemsObject.map { mapName, itemJSON in
guard case let .object(itemObject) = itemJSON else {
throw GeoPluginConfigError.mapInvalid(mapName: mapName)
}
guard let styleJSON = itemObject[Node.style.key] else {
throw GeoPluginConfigError.mapStyleMissing(mapName: mapName)
}
guard case let .string(style) = styleJSON else {
throw GeoPluginConfigError.mapStyleIsNotString(mapName: mapName)
}
let urlString = "https://maps.geo.\(regionName).amazonaws.com/maps/v0/maps/\(mapName)/style-descriptor"
let url = URL(string: urlString)
guard let styleURL = url else {
throw GeoPluginConfigError.mapStyleURLInvalid(mapName: mapName)
}
let mapStyle = Geo.MapStyle.init(mapName: mapName, style: style, styleURL: styleURL)
return (mapName, mapStyle)
}
let mapStyles = Dictionary(uniqueKeysWithValues: mapTuples)
return mapStyles
}
}