| // Copyright 2016 The Vanadium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| import Foundation |
| import SyncbaseCore |
| |
| /// Represents an ordered set of key-value pairs. |
| /// To get a Collection handle, call `Database.collection`. |
| public class Collection: CustomStringConvertible { |
| let coreCollection: SyncbaseCore.Collection |
| let databaseHandle: DatabaseHandle |
| |
| func createIfMissing() throws { |
| do { |
| try SyncbaseError.wrap { |
| try self.coreCollection.create(defaultCollectionPerms()) |
| } |
| } catch SyncbaseError.Exist { |
| // Collection already exists. |
| } |
| } |
| |
| init(coreCollection: SyncbaseCore.Collection, databaseHandle: DatabaseHandle) { |
| self.coreCollection = coreCollection |
| self.databaseHandle = databaseHandle |
| } |
| |
| /// Returns the id of this collection. |
| public var collectionId: Identifier { |
| return Identifier(coreId: coreCollection.collectionId) |
| } |
| |
| /// Deletes the collection locally and anywhere else the collection is synced to. |
| public func destroy() throws { |
| try coreCollection.destroy() |
| } |
| |
| /// Shortcut for `Database.getSyncgroup(collection.collectionId)`, helpful for the common case |
| /// of one syncgroup per collection. |
| public func syncgroup() throws -> Syncgroup { |
| switch databaseHandle { |
| case is BatchDatabase: throw SyncbaseError.BatchError(detail: "Must not call getSyncgroup within batch") |
| case let h as Database: return h.syncgroup(collectionId) |
| default: fatalError("Unexpected type") |
| } |
| } |
| |
| /// Returns the value associated with `key`. |
| public func get<T: SyncbaseCore.SyncbaseConvertible>(key: String) throws -> T? { |
| return try SyncbaseError.wrap { |
| let value: T? = try self.coreCollection.get(key) |
| return value |
| } |
| } |
| |
| /// Returns true if there is a value associated with `key`. |
| public func exists(key: String) throws -> Bool { |
| return try SyncbaseError.wrap { |
| return try self.coreCollection.exists(key) |
| } |
| } |
| |
| /// Puts `value` for `key`, overwriting any existing value. This call is idempotent, meaning |
| /// you can safely call it multiple times in a row with the same values. |
| public func put<T: SyncbaseCore.SyncbaseConvertible>(key: String, value: T) throws { |
| try SyncbaseError.wrap { |
| try self.coreCollection.put(key, value: value) |
| } |
| } |
| |
| /// Deletes the value associated with `key`. If the row does not exist for the associated key, |
| /// this call is a no-op. That is to say, `delete` is idempotent. |
| public func delete(key: String) throws { |
| try SyncbaseError.wrap { |
| try self.coreCollection.delete(key) |
| } |
| } |
| |
| /// **FOR ADVANCED USERS**. Returns the `AccessList` for this collection. Users should |
| /// typically manipulate access lists via `collection.syncgroup()`. |
| public func accessList() throws -> AccessList { |
| return try SyncbaseError.wrap { |
| return try AccessList(perms: try self.coreCollection.getPermissions()) |
| } |
| } |
| |
| /// **FOR ADVANCED USERS**. Updates the `AccessList` for this collection. Users should |
| /// typically manipulate access lists via `collection.syncgroup()`}. |
| public func updateAccessList(delta: AccessList) throws { |
| let op = { (db: BatchDatabase) in |
| try SyncbaseError.wrap { |
| let vCx = try db.collection(self.collectionId).coreCollection |
| let perms = try vCx.getPermissions() |
| AccessList.applyDelta(perms, delta: delta) |
| try vCx.setPermissions(perms) |
| } |
| } |
| // Create a batch if we're not already in a batch. |
| if let batchDb = databaseHandle as? BatchDatabase { |
| try op(batchDb) |
| } else { |
| try (databaseHandle as! Database).runInBatch(op: op) |
| } |
| } |
| |
| public var description: String { |
| return "[Syncbase.Collection id=\(collectionId)]" |
| } |
| } |