<commit_before>URLHandler = require './urlhandler'
VASTResponse = require './response'
VASTAd = require './ad'
VASTAdExtension = require './extension'
VASTAdExtensionChild = require './extensionchild'
VASTUtil = require './util'
VASTCreativeLinear = require('./creative').VASTCreativeLinear
VASTCreativeCompanion = require('./creative').VASTCreativeCompanion
VASTCreativeNonLinear = require('./creative').VASTCreativeNonLinear
VASTMediaFile = require './mediafile'
VASTIcon = require './icon'
VASTCompanionAd = require './companionad'
VASTNonLinear = require './nonlinear'
EventEmitter = require('events').EventEmitter

class VASTParser
    URLTemplateFilters = []

    @addURLTemplateFilter: (func) ->
        URLTemplateFilters.push(func) if typeof func is 'function'
        return

    @removeURLTemplateFilter: () -> URLTemplateFilters.pop()
    @countURLTemplateFilters: () -> URLTemplateFilters.length
    @clearUrlTemplateFilters: () -> URLTemplateFilters = []

    @parse: (url, options, cb) ->
        if not cb
            cb = options if typeof options is 'function'
            options = {}

        @_parse url, null, options, (err, response) ->
            cb(response, err)

    @load: (xml, options, cb) ->
        if not cb
            cb = options if typeof options is 'function'
            options = {}

        @parseXmlDocument(null, [], options, xml, cb)

    @vent = new EventEmitter()
    @track: (templates, errorCode) ->
        @vent.emit 'VAST-error', errorCode
        VASTUtil.track(templates, errorCode)

    @on: (eventName, cb) ->
        @vent.on eventName, cb

    @once: (eventName, cb) ->
        @vent.once eventName, cb

    @off: (eventName, cb) ->
        @vent.removeListener eventName, cb

    @_parse: (url, parentURLs, options, cb) ->
        # Options param can be skipped
        if not cb
            cb = options if typeof options is 'function'
            options = {}

        # Process url with defined filter
        url = filter(url) for filter in URLTemplateFilters

        parentURLs ?= []
        parentURLs.push url

        URLHandler.get url, options, (err, xml) =>
            return cb(err) if err?
            @parseXmlDocument(url, parentURLs, options, xml, cb)

    @parseXmlDocument: (url, parentURLs, options, xml, cb) =>
        response = new VASTResponse()

        unless xml?.documentElement? and xml.documentElement.nodeName is "VAST"
            return cb(new Error('Invalid VAST XMLDocument'))

        for node in xml.documentElement.childNodes
            if node.nodeName is 'Error'
                response.errorURLTemplates.push (@parseNodeText node)

        for node in xml.documentElement.childNodes
            if node.nodeName is 'Ad'
                ad = @parseAdElement node
                if ad?
                    if options.determinedSequence?
                        ad.sequence = options.determinedSequence

                    response.ads.push ad
                else
                    # VAST version of response not supported.
                    @track(response.errorURLTemplates, ERRORCODE: 101)<commit_msg>set sequence from wrapper only if there isn't one already on the ad<commit_after>URLHandler = require './urlhandler'
VASTResponse = require './response'
VASTAd = require './ad'
VASTAdExtension = require './extension'
VASTAdExtensionChild = require './extensionchild'
VASTUtil = require './util'
VASTCreativeLinear = require('./creative').VASTCreativeLinear
VASTCreativeCompanion = require('./creative').VASTCreativeCompanion
VASTCreativeNonLinear = require('./creative').VASTCreativeNonLinear
VASTMediaFile = require './mediafile'
VASTIcon = require './icon'
VASTCompanionAd = require './companionad'
VASTNonLinear = require './nonlinear'
EventEmitter = require('events').EventEmitter

class VASTParser
    URLTemplateFilters = []

    @addURLTemplateFilter: (func) ->
        URLTemplateFilters.push(func) if typeof func is 'function'
        return

    @removeURLTemplateFilter: () -> URLTemplateFilters.pop()
    @countURLTemplateFilters: () -> URLTemplateFilters.length
    @clearUrlTemplateFilters: () -> URLTemplateFilters = []

    @parse: (url, options, cb) ->
        if not cb
            cb = options if typeof options is 'function'
            options = {}

        @_parse url, null, options, (err, response) ->
            cb(response, err)

    @load: (xml, options, cb) ->
        if not cb
            cb = options if typeof options is 'function'
            options = {}

        @parseXmlDocument(null, [], options, xml, cb)

    @vent = new EventEmitter()
    @track: (templates, errorCode) ->
        @vent.emit 'VAST-error', errorCode
        VASTUtil.track(templates, errorCode)

    @on: (eventName, cb) ->
        @vent.on eventName, cb

    @once: (eventName, cb) ->
        @vent.once eventName, cb

    @off: (eventName, cb) ->
        @vent.removeListener eventName, cb

    @_parse: (url, parentURLs, options, cb) ->
        # Options param can be skipped
        if not cb
            cb = options if typeof options is 'function'
            options = {}

        # Process url with defined filter
        url = filter(url) for filter in URLTemplateFilters

        parentURLs ?= []
        parentURLs.push url

        URLHandler.get url, options, (err, xml) =>
            return cb(err) if err?
            @parseXmlDocument(url, parentURLs, options, xml, cb)

    @parseXmlDocument: (url, parentURLs, options, xml, cb) =>
        response = new VASTResponse()

        unless xml?.documentElement? and xml.documentElement.nodeName is "VAST"
            return cb(new Error('Invalid VAST XMLDocument'))

        for node in xml.documentElement.childNodes
            if node.nodeName is 'Error'
                response.errorURLTemplates.push (@parseNodeText node)

        for node in xml.documentElement.childNodes
            if node.nodeName is 'Ad'
                ad = @parseAdElement node
                if ad?
                    if options.determinedSequence? and not ad.sequence?
                        # Set sequence from wrapper if there isn't one on the ad
                        ad.sequence = options.determinedSequence

                    response.ads.push ad
                else
                    # VAST version of response not supported.
                    @track(response.errorURLTemplates, ERRORCODE: 101)
{'fraction_non_alphanumeric': 0.10238319222326749, 'fraction_numerical': 0.0009407337723424271, 'mean_word_length': 2.352075669994745, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 18}, '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': '4965383', 'n_tokens_mistral': 1758, 'n_tokens_neox': 1695, 'n_words': 497}