181 lines
7.3 KiB
Swift
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
|
|
}
|
|
}
|