You've already forked My-Mind-2.0
mirror of
https://github.com/MrLyallCSIT/My-Mind-2.0.git
synced 2026-01-18 07:09:40 +00:00
142 lines
5.9 KiB
Objective-C
142 lines
5.9 KiB
Objective-C
/*
|
|
* Copyright 2017 Google
|
|
*
|
|
* 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 "FEventGenerator.h"
|
|
#import "FNode.h"
|
|
#import "FIRDatabaseQuery_Private.h"
|
|
#import "FQueryParams.h"
|
|
#import "FQuerySpec.h"
|
|
#import "FChange.h"
|
|
#import "FNamedNode.h"
|
|
#import "FEventRegistration.h"
|
|
#import "FEvent.h"
|
|
#import "FDataEvent.h"
|
|
|
|
@interface FEventGenerator ()
|
|
@property (nonatomic, strong) FQuerySpec *query;
|
|
@end
|
|
|
|
/**
|
|
* An EventGenerator is used to convert "raw" changes (fb.core.view.Change) as computed by the
|
|
* CacheDiffer into actual events (fb.core.view.Event) that can be raised. See generateEventsForChanges()
|
|
* for details.
|
|
*/
|
|
@implementation FEventGenerator
|
|
|
|
- (id)initWithQuery:(FQuerySpec *)query {
|
|
self = [super init];
|
|
if (self) {
|
|
self.query = query;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
/**
|
|
* Given a set of raw changes (no moved events, and prevName not specified yet), and a set of EventRegistrations that
|
|
* should be notified of these changes, generate the actual events to be raised.
|
|
*
|
|
* Notes:
|
|
* - child_moved events will be synthesized at this time for any child_changed events that affect our index
|
|
* - prevName will be calculated based on the index ordering
|
|
*
|
|
* @param changes NSArray of FChange, not necessarily in order.
|
|
* @param registrations is NSArray of FEventRegistration.
|
|
* @return NSArray of FEvent.
|
|
*/
|
|
- (NSArray *) generateEventsForChanges:(NSArray *)changes
|
|
eventCache:(FIndexedNode *)eventCache
|
|
eventRegistrations:(NSArray *)registrations
|
|
{
|
|
NSMutableArray *events = [[NSMutableArray alloc] init];
|
|
|
|
// child_moved is index-specific, so check all our child_changed events to see if we need to materialize
|
|
// child_moved events with this view's index
|
|
NSMutableArray *moves = [[NSMutableArray alloc] init];
|
|
for (FChange *change in changes) {
|
|
if (change.type == FIRDataEventTypeChildChanged && [self.query.index indexedValueChangedBetween:change.oldIndexedNode.node
|
|
and:change.indexedNode.node]) {
|
|
FChange *moveChange = [[FChange alloc] initWithType:FIRDataEventTypeChildMoved
|
|
indexedNode:change.indexedNode
|
|
childKey:change.childKey
|
|
oldIndexedNode:nil];
|
|
[moves addObject:moveChange];
|
|
}
|
|
}
|
|
|
|
[self generateEvents:events forType:FIRDataEventTypeChildRemoved changes:changes eventCache:eventCache eventRegistrations:registrations];
|
|
[self generateEvents:events forType:FIRDataEventTypeChildAdded changes:changes eventCache:eventCache eventRegistrations:registrations];
|
|
[self generateEvents:events forType:FIRDataEventTypeChildMoved changes:moves eventCache:eventCache eventRegistrations:registrations];
|
|
[self generateEvents:events forType:FIRDataEventTypeChildChanged changes:changes eventCache:eventCache eventRegistrations:registrations];
|
|
[self generateEvents:events forType:FIRDataEventTypeValue changes:changes eventCache:eventCache eventRegistrations:registrations];
|
|
|
|
return events;
|
|
}
|
|
|
|
- (void) generateEvents:(NSMutableArray *)events
|
|
forType:(FIRDataEventType)eventType
|
|
changes:(NSArray *)changes
|
|
eventCache:(FIndexedNode *)eventCache
|
|
eventRegistrations:(NSArray *)registrations
|
|
{
|
|
NSMutableArray *filteredChanges = [[NSMutableArray alloc] init];
|
|
for (FChange *change in changes) {
|
|
if (change.type == eventType) {
|
|
[filteredChanges addObject:change];
|
|
}
|
|
}
|
|
|
|
id<FIndex> index = self.query.index;
|
|
|
|
[filteredChanges sortUsingComparator:^NSComparisonResult(FChange *one, FChange *two) {
|
|
if (one.childKey == nil || two.childKey == nil) {
|
|
@throw [[NSException alloc] initWithName:@"InternalInconsistencyError"
|
|
reason:@"Should only compare child_ events"
|
|
userInfo:nil];
|
|
}
|
|
return [index compareKey:one.childKey
|
|
andNode:one.indexedNode.node
|
|
toOtherKey:two.childKey
|
|
andNode:two.indexedNode.node];
|
|
}];
|
|
|
|
for (FChange *change in filteredChanges) {
|
|
for (id<FEventRegistration> registration in registrations) {
|
|
if ([registration responseTo:eventType]) {
|
|
id<FEvent> event = [self generateEventForChange:change registration:registration eventCache:eventCache];
|
|
[events addObject:event];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
- (id<FEvent>) generateEventForChange:(FChange *)change
|
|
registration:(id<FEventRegistration>)registration
|
|
eventCache:(FIndexedNode *)eventCache
|
|
{
|
|
FChange *materializedChange;
|
|
if (change.type == FIRDataEventTypeValue || change.type == FIRDataEventTypeChildRemoved) {
|
|
materializedChange = change;
|
|
} else {
|
|
NSString *prevChildKey = [eventCache predecessorForChildKey:change.childKey
|
|
childNode:change.indexedNode.node
|
|
index:self.query.index];
|
|
materializedChange = [change changeWithPrevKey:prevChildKey];
|
|
}
|
|
return [registration createEventFrom:materializedChange query:self.query];
|
|
}
|
|
|
|
@end
|