123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258 |
- ////////////////////////////////////////////////////////////////////////////
- //
- // Copyright 2017 Realm Inc.
- //
- // 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 "RLMSyncPermissionResults.h"
- #import "RLMCollection_Private.hpp"
- #import "RLMObjectSchema_Private.hpp"
- #import "RLMQueryUtil.hpp"
- #import "RLMResults_Private.hpp"
- #import "RLMSchema_Private.hpp"
- #import "RLMSyncPermission_Private.hpp"
- #import "RLMSyncUtil_Private.hpp"
- #import "RLMUtil.hpp"
- #import "object.hpp"
- using namespace realm;
- namespace {
- bool keypath_is_valid(NSString *keypath)
- {
- static auto valid = [NSSet setWithArray:@[RLMSyncPermissionSortPropertyPath,
- RLMSyncPermissionSortPropertyUserID,
- RLMSyncPermissionSortPropertyUpdated]];
- return [valid containsObject:keypath];
- }
- }
- /// Sort by the Realm Object Server path to the Realm to which the permission applies.
- RLMSyncPermissionSortProperty const RLMSyncPermissionSortPropertyPath = @"path";
- /// Sort by the identity of the user to whom the permission applies.
- RLMSyncPermissionSortProperty const RLMSyncPermissionSortPropertyUserID = @"userId";
- /// Sort by the date the permissions were last updated.
- RLMSyncPermissionSortProperty const RLMSyncPermissionSortPropertyUpdated = @"updatedAt";
- @interface RLMSyncPermissionResults ()
- @property (nonatomic, strong) RLMSchema *schema;
- @property (nonatomic, strong) RLMObjectSchema *objectSchema;
- @end
- @implementation RLMSyncPermissionResults
- #pragma mark - Public API
- - (RLMPropertyType)type {
- return RLMPropertyTypeObject;
- }
- - (NSString *)objectClassName {
- return NSStringFromClass([RLMSyncPermission class]);
- }
- - (RLMRealm *)realm {
- return nil;
- }
- - (RLMSyncPermission *)objectAtIndex:(NSUInteger)index {
- return translateRLMResultsErrors([&] {
- Object permission(_results.get_realm(), _results.get_object_schema(), _results.get(index));
- return [[RLMSyncPermission alloc] initWithPermission:Permission(permission)];
- });
- }
- - (RLMSyncPermission *)firstObject {
- return self.count == 0 ? nil : [self objectAtIndex:0];
- }
- - (RLMSyncPermission *)lastObject {
- return self.count == 0 ? nil : [self objectAtIndex:(self.count - 1)];
- }
- - (NSUInteger)indexOfObject:(RLMSyncPermission *)object {
- if (object.key) {
- // Key-value permissions are only used for setting; they are never returned.
- return NSNotFound;
- }
- // Canonicalize the path.
- NSString *path = object.path;
- if ([path rangeOfString:@"~"].location != NSNotFound) {
- path = [path stringByReplacingOccurrencesOfString:@"~" withString:object.identity];
- }
- NSString *topPrivilege;
- switch (object.accessLevel) {
- case RLMSyncAccessLevelNone:
- // Deleted permissions are removed from the permissions Realm by ROS.
- return NSNotFound;
- case RLMSyncAccessLevelRead:
- topPrivilege = @"mayRead";
- break;
- case RLMSyncAccessLevelWrite:
- topPrivilege = @"mayWrite";
- break;
- case RLMSyncAccessLevelAdmin:
- topPrivilege = @"mayManage";
- break;
- }
- // Build the predicate.
- NSPredicate *p = [NSPredicate predicateWithFormat:@"%K = %@ AND %K = %@ AND %K == YES",
- RLMSyncPermissionSortPropertyPath, path,
- RLMSyncPermissionSortPropertyUserID, object.identity,
- topPrivilege];
- return [self indexOfObjectWithPredicate:p];
- }
- - (NSUInteger)indexOfObjectWithPredicate:(NSPredicate *)predicate {
- return translateRLMResultsErrors([&] {
- auto& group = _results.get_realm()->read_group();
- auto query = RLMPredicateToQuery(predicate, self.objectSchema, self.schema, group);
- return RLMConvertNotFound(_results.index_of(std::move(query)));
- });
- }
- - (RLMResults<RLMSyncPermission *> *)objectsWithPredicate:(NSPredicate *)predicate {
- return translateRLMResultsErrors([&] {
- auto query = RLMPredicateToQuery(predicate, self.objectSchema, self.schema, _results.get_realm()->read_group());
- return [[RLMSyncPermissionResults alloc] initWithResults:_results.filter(std::move(query))];
- });
- }
- - (RLMResults<RLMSyncPermission *> *)sortedResultsUsingDescriptors:(NSArray<RLMSortDescriptor *> *)properties {
- if (properties.count == 0) {
- return self;
- }
- for (RLMSortDescriptor *descriptor in properties) {
- if (!keypath_is_valid(descriptor.keyPath)) {
- @throw RLMException(@"Invalid keypath specified. Use one of the constants defined in "
- @" `RLMSyncPermissionSortProperty`.");
- }
- }
- return translateRLMResultsErrors([&] {
- auto sorted = _results.sort(RLMSortDescriptorsToKeypathArray(properties));
- return [[RLMSyncPermissionResults alloc] initWithResults:std::move(sorted)];
- });
- }
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wmismatched-parameter-types"
- - (RLMNotificationToken *)addNotificationBlock:(void(^)(RLMSyncPermissionResults *results,
- RLMCollectionChange *change,
- NSError *error))block {
- auto cb = [=](const realm::CollectionChangeSet& changes, std::exception_ptr ptr) {
- if (ptr) {
- NSError *error = translateSyncExceptionPtrToError(std::move(ptr), RLMPermissionActionTypeGet);
- REALM_ASSERT(error);
- block(nil, nil, error);
- } else {
- // Finished successfully
- block(self, [[RLMCollectionChange alloc] initWithChanges:changes], nil);
- }
- };
- return [[RLMCancellationToken alloc] initWithToken:_results.add_notification_callback(std::move(cb)) realm:nil];
- }
- #pragma clang diagnostic pop
- - (id)aggregate:(__unused NSString *)property
- method:(__unused util::Optional<Mixed> (Results::*)(size_t))method
- methodName:(__unused NSString *)methodName returnNilForEmpty:(__unused BOOL)returnNilForEmpty {
- // We don't support any of the min/max/average/sum APIs; they don't make sense for this collection type.
- return nil;
- }
- - (id)valueForKey:(NSString *)key {
- size_t count = self.count;
- if (count == 0) {
- return @[];
- }
- NSMutableArray *results = [NSMutableArray arrayWithCapacity:count];
- if ([key isEqualToString:@"self"]) {
- for (size_t i = 0; i < count; i++) {
- [results addObject:[self objectAtIndex:i]];
- }
- } else {
- for (size_t i = 0; i < count; i++) {
- [results addObject:[[self objectAtIndex:i] valueForKey:key] ?: NSNull.null];
- }
- }
- return results;
- }
- - (void)setValue:(__unused id)value forKey:(__unused NSString *)key {
- @throw RLMException(@"Cannot set values for the read-only type `RLMSyncPermission`.");
- }
- #pragma mark - System
- - (RLMSchema *)schema {
- if (!_schema) {
- _schema = [RLMSchema dynamicSchemaFromObjectStoreSchema:_results.get_realm()->schema()];
- }
- return _schema;
- }
- - (RLMObjectSchema *)objectSchema {
- if (!_objectSchema) {
- _objectSchema = [RLMObjectSchema objectSchemaForObjectStoreSchema:_results.get_object_schema()];
- }
- return _objectSchema;
- }
- - (NSString *)description {
- return RLMDescriptionWithMaxDepth(@"RLMSyncPermissionResults", self, 1);
- }
- - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state
- objects:(id __unsafe_unretained [])buffer
- count:(NSUInteger)len {
- // FIXME: It would be nice to have a shared fast enumeration implementation for `realm::Results`-only RLMResults.
- NSUInteger thisSize = self.count;
- if (state->state == 0) {
- state->extra[0] = 0;
- state->extra[1] = (long)thisSize;
- state->state = 1;
- }
- NSUInteger objectsInBuffer = 0;
- long idx = state->extra[0];
- if ((unsigned long)idx == thisSize) {
- // finished
- return 0;
- }
- state->itemsPtr = buffer;
- state->mutationsPtr = state->extra + 1;
- while (true) {
- if (objectsInBuffer == len) {
- // Buffer is full.
- state->extra[0] = idx;
- return objectsInBuffer;
- }
- if ((unsigned long)idx == thisSize) {
- // finished
- state->extra[0] = idx;
- return objectsInBuffer;
- }
- // Otherwise, add an object and advance the index pointer.
- RLMSyncPermission * __autoreleasing thisPermission = [self objectAtIndex:idx];
- buffer[objectsInBuffer] = thisPermission;
- idx++;
- objectsInBuffer++;
- }
- }
- @end
|