<commit_before>//
// https://github.com/SteveKChiu/CoreDataMonk
//
// Copyright 2015, <NAME> <<EMAIL>>
//
// The MIT License (http://www.opensource.org/licenses/mit-license.php)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//

import CoreData

//---------------------------------------------------------------------------

public class CoreDataContext {
    public static let CommitNotification = "CoreDataDidCommit"

    public enum UpdateTarget {
        case MainContext
        case RootContext(autoMerge: Bool)
        case PersistentStore
    }

    public enum UpdateOrder {
        case Serial
        case Default
    }
    
    public class Observer {
        var observer: NSObjectProtocol
        
        init(notification: String, object: AnyObject?, queue: NSOperationQueue?, block: (NSNotification) -> Void) {
            self.observer = NSNotificationCenter.defaultCenter().addObserverForName(notification, object: object, queue: queue, usingBlock: block)
        }
        
        deinit {
            NSNotificationCenter.defaultCenter().removeObserver(self.observer)
        }
    }

    let mainContext: NSManagedObjectContext?
    let stack: CoreDataStack
    let updateTarget: UpdateTarget
    let updateQueue: dispatch_queue_t?
    var autoMergeObserver: Observer?

    public init(stack: CoreDataStack, mainContext: NSManagedObjectContext? = nil, updateTarget: UpdateTarget = .RootContext(autoMerge: false), updateOrder: UpdateOrder = .Default) throws {
        if updateOrder == .Serial {
            self.updateQueue = dispatch_queue_create("CoreDataContext.UpdateQueue", DISPATCH_QUEUE_SERIAL)
        } else {
            self.updateQueue = nil
        }
        
        self.stack = stack
        self.mainContext = mainContext
        self.updateTarget = updateTarget

        switch updateTarget {
        case .MainContext:
            guard mainContext != nil else {
                throw CoreDataError("CoreDataContext.UpdateTarget(.MainContext) need MainContext but it is not specified")
            }
        
        case let .RootContext(autoMerge: autoMerge):
            guard let rootContext = stack.rootManagedObjectContext else {
                throw CoreDataError("CoreDataContext.UpdateTarget(.RootContext) need RootContext but CoreDataStack does not have one")
            }
            
            if autoMerge {
                guard let mainContext = mainContext else {
                    throw CoreDataError("CoreDataContext.UpdateTarget(.RootContext) need to auto merge MainContext but it is not specified")
                }

                self.autoMergeObserver = Observer(notification: NSManagedObjectContextDidSaveNotification, object: rootContext, queue: nil) {
                    [weak mainContext] notification in
                    
                    mainContext?.performBlock() {
                        mainContext?.mergeChangesFromContextDidSaveNotification(notification)
                    }
                }
            }
            
        default:
            break
        }
    }

    public final func metadataForEntityClass(type: NSManagedObject.Type) throws -> (entity: NSEntityDescription, store: NSPersistentStore) {
        return try self.stack.metadataForEntityClass(type)
    }

    public class func observeCommit(queue queue: NSOperationQueue? = nil, block: () -> Void) -> Observer {
        return Observer(notification: CoreDataContext.CommitNotification, object: nil, queue: queue ?? NSOperationQueue.mainQueue()) {
            _ in
            
            block()
        }
    }

    public func observeCommit(queue queue: NSOperationQueue? = nil, block: () -> Void) -> Observer {
        return Observer(notification: CoreDataContext.CommitNotification, object: self, queue: queue ?? NSOperationQueue.mainQueue()) {
            _ in
            
            block()<commit_msg>No need to export Observer class<commit_after>//
// https://github.com/SteveKChiu/CoreDataMonk
//
// Copyright 2015, <NAME> <<EMAIL>>
//
// The MIT License (http://www.opensource.org/licenses/mit-license.php)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//

import CoreData

//---------------------------------------------------------------------------

public class CoreDataContext {
    public static let CommitNotification = "CoreDataDidCommit"

    public enum UpdateTarget {
        case MainContext
        case RootContext(autoMerge: Bool)
        case PersistentStore
    }

    public enum UpdateOrder {
        case Serial
        case Default
    }
    
    private class Observer {
        var observer: NSObjectProtocol
        
        init(notification: String, object: AnyObject?, queue: NSOperationQueue?, block: (NSNotification) -> Void) {
            self.observer = NSNotificationCenter.defaultCenter().addObserverForName(notification, object: object, queue: queue, usingBlock: block)
        }
        
        deinit {
            NSNotificationCenter.defaultCenter().removeObserver(self.observer)
        }
    }

    let mainContext: NSManagedObjectContext?
    let stack: CoreDataStack
    let updateTarget: UpdateTarget
    let updateQueue: dispatch_queue_t?
    var autoMergeObserver: AnyObject?

    public init(stack: CoreDataStack, mainContext: NSManagedObjectContext? = nil, updateTarget: UpdateTarget = .RootContext(autoMerge: false), updateOrder: UpdateOrder = .Default) throws {
        if updateOrder == .Serial {
            self.updateQueue = dispatch_queue_create("CoreDataContext.UpdateQueue", DISPATCH_QUEUE_SERIAL)
        } else {
            self.updateQueue = nil
        }
        
        self.stack = stack
        self.mainContext = mainContext
        self.updateTarget = updateTarget

        switch updateTarget {
        case .MainContext:
            guard mainContext != nil else {
                throw CoreDataError("CoreDataContext.UpdateTarget(.MainContext) need MainContext but it is not specified")
            }
        
        case let .RootContext(autoMerge: autoMerge):
            guard let rootContext = stack.rootManagedObjectContext else {
                throw CoreDataError("CoreDataContext.UpdateTarget(.RootContext) need RootContext but CoreDataStack does not have one")
            }
            
            if autoMerge {
                guard let mainContext = mainContext else {
                    throw CoreDataError("CoreDataContext.UpdateTarget(.RootContext) need to auto merge MainContext but it is not specified")
                }

                self.autoMergeObserver = Observer(notification: NSManagedObjectContextDidSaveNotification, object: rootContext, queue: nil) {
                    [weak mainContext] notification in
                    
                    mainContext?.performBlock() {
                        mainContext?.mergeChangesFromContextDidSaveNotification(notification)
                    }
                }
            }
            
        default:
            break
        }
    }

    public final func metadataForEntityClass(type: NSManagedObject.Type) throws -> (entity: NSEntityDescription, store: NSPersistentStore) {
        return try self.stack.metadataForEntityClass(type)
    }

    public class func observeCommit(queue queue: NSOperationQueue? = nil, block: () -> Void) -> AnyObject {
        return Observer(notification: CoreDataContext.CommitNotification, object: nil, queue: queue ?? NSOperationQueue.mainQueue()) {
            _ in
            
            block()
        }
    }

    public func observeCommit(queue queue: NSOperationQueue? = nil, block: () -> Void) -> AnyObject {
        return Observer(notification: CoreDataContext.CommitNotification, object: self, queue: queue ?? NSOperationQueue.mainQueue()) {
            _ in
            
            block()
{'fraction_non_alphanumeric': 0.08962503810588354, 'fraction_numerical': 0.000812925515699624, 'mean_word_length': 2.3914541695382496, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 21, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1765525', 'n_tokens_mistral': 2371, 'n_tokens_neox': 2266, 'n_words': 784}