An amazing project that generates micro reports from tournament results
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
pa-tournament-stats/Carthage/Checkouts/realm-cocoa/Realm/RLMSyncPermissionResults.mm

258 lines
9.1 KiB

////////////////////////////////////////////////////////////////////////////
//
// 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