<commit_before>define [
    '../../core'
    './nodes'
], (c, nodes) ->

    contextNodeModels =
        branch: nodes.BranchNodeModel
        condition: nodes.ConditionNodeModel
        composite: nodes.CompositeNodeModel


    # Returns the node type for attrs or throws an error if none can be
    # determined
    getContextNodeType = (attrs, options) ->
        if attrs instanceof nodes.ContextNodeModel
            return attrs.nodeType
        for type, model of contextNodeModels
            if not model::validate.call(attrs, attrs, options)
                return type
        throw new nodes.ContextNodeError 'Unknown context node type'


    # Class-level method for create a node instance of the specified type
    nodes.ContextNodeModel.create = (type, attrs, options) ->
        # No type provided, infer the type and validate
        if typeof type is 'object'
            attrs = type
            type = getContextNodeType(attrs, options)
        if not (klass = contextNodeModels[type])?
            throw new nodes.ContextNodeError 'Unknown context node type'
        return new klass(attrs, options)


    class ContextModel extends c.Backbone.Model
        url: ->
            if @isNew() then return super
            return @get('_links').self.href

        constructor: (attrs, options={}) ->
            @root = new nodes.BranchNodeModel
            options.parse = true
            super(attrs, options)

        initialize: ->
            @on 'request', ->
                c.publish c.CONTEXT_SYNCING, @

            @on 'sync', ->
                @resolve()
                c.publish c.CONTEXT_SYNCED, @, 'success'

            # If the sync fails on the server
            @on 'error', ->
                c.publish c.CONTEXT_SYNCED, @, 'error'

            # Notify subscribers the this object has changed
            @on 'change', ->
                c.publish c.CONTEXT_CHANGED, @

            # Pause syncing with the server
            c.subscribe c.CONTEXT_PAUSE, (id) =>
                if @id is id or not id and @isSession()
                    @pending()

            # Resume syncing with the server
            c.subscribe c.CONTEXT_RESUME, (id) =>
                if @id is id or not id and @isSession()
                    @resolve()

            # Clear all nodes from the context
            c.subscribe c.CONTEXT_CLEAR, (id) =>
                if @id is id or not id and @isSession()
                    @clear()

            c.subscribe c.CONTEXT_SAVE, (id) =>
                if @id is id or not id and @isSession()
                    @save()

            @resolve()

        parse: (resp) =>
            if (attrs = resp.json)?
                # This is for legacy responses where the root node has not
                # been correctly defined
                if attrs.concept? or attrs.field?
                    @root.children.add(attrs)
                else
                    @root.set(attrs, save: true)
                delete resp.json
            return resp

        save: ->
            @root.save()
            super

        toJSON: ->
            attrs = super
            attrs.json = @root.public.toJSON()
            return attrs

        isSession: ->
            @get 'session'

        isArchived: ->
            @get 'archived'


    class ContextCollection extends c.Backbone.Collection
        model: ContextModel

        url: -><commit_msg>Subclass ContextModel/Collection from base model classes<commit_after>define [
    '../../core'
    '../base'
    './nodes'
], (c, base, nodes) ->

    contextNodeModels =
        branch: nodes.BranchNodeModel
        condition: nodes.ConditionNodeModel
        composite: nodes.CompositeNodeModel


    # Returns the node type for attrs or throws an error if none can be
    # determined
    getContextNodeType = (attrs, options) ->
        if attrs instanceof nodes.ContextNodeModel
            return attrs.nodeType
        for type, model of contextNodeModels
            if not model::validate.call(attrs, attrs, options)
                return type
        throw new nodes.ContextNodeError 'Unknown context node type'


    # Class-level method for create a node instance of the specified type
    nodes.ContextNodeModel.create = (type, attrs, options) ->
        # No type provided, infer the type and validate
        if typeof type is 'object'
            attrs = type
            type = getContextNodeType(attrs, options)
        if not (klass = contextNodeModels[type])?
            throw new nodes.ContextNodeError 'Unknown context node type'
        return new klass(attrs, options)


    class ContextModel extends base.Model

        constructor: (attrs, options={}) ->
            @root = new nodes.BranchNodeModel
            options.parse = true
            super(attrs, options)

        initialize: ->

            @on 'request', ->
                @pending()
                c.publish c.CONTEXT_SYNCING, @

            @on 'sync', ->
                @resolve()
                c.publish c.CONTEXT_SYNCED, @, 'success'

            @on 'error', ->
                @resolve()
                c.publish c.CONTEXT_SYNCED, @, 'error'

            @on 'change', ->
                c.publish c.CONTEXT_CHANGED, @

            c.subscribe c.CONTEXT_PAUSE, (id) =>
                if @id is id or not id and @isSession()
                    @pending()

            c.subscribe c.CONTEXT_RESUME, (id) =>
                if @id is id or not id and @isSession()
                    @resolve()

            c.subscribe c.CONTEXT_CLEAR, (id) =>
                if @id is id or not id and @isSession()
                    @clear()

            c.subscribe c.CONTEXT_SAVE, (id) =>
                if @id is id or not id and @isSession()
                    @save()

            @resolve()

        parse: (resp) =>
            if (attrs = resp.json)?
                # This is for legacy responses where the root node has not
                # been correctly defined
                if attrs.concept? or attrs.field?
                    @root.children.add(attrs)
                else
                    @root.set(attrs, save: true)
                delete resp.json
            super(resp)

        save: ->
            @root.save()
            super

        toJSON: ->
            attrs = super
            attrs.json = @root.public.toJSON()
            return attrs

        isSession: ->
            @get 'session'

        isArchived: ->
            @get 'archived'


    class ContextCollection extends base.Collection
        model: ContextModel

        url: ->
{'fraction_non_alphanumeric': 0.08881129497495066, 'fraction_numerical': 0.0, 'mean_word_length': 1.4683402023229675, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 42, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '1204210', 'n_tokens_mistral': 1707, 'n_tokens_neox': 1660, 'n_words': 536}