@function ImmutableCoreModelView

create/register a new model view instance

@param {object} args

@returns {ImmutableCoreModelView}

@throws {Error}
function ImmutableCoreModelView (args) {
    // require name
    assert.ok(typeof args.name === 'string' && args.name.length, 'name required')
    // require valid type
    assert.ok(validTypes[args.type], 'invalid type '+args.type)
    // do not allow pre/post function with record type view
    if (args.type === 'record' && (args.post || args.pre)) {
        throw new Error('pre and post functions not allowed with record views')
    }
    // require function
    assert.ok(typeof args.each === 'function', 'each function required')
    // validate post function if passed
    if (args.post) {
        assert.ok(typeof args.post === 'function', 'post must be function')
    }
    // validate pre function if passed
    if (args.pre) {
        assert.ok(typeof args.pre === 'function', 'pre must be function')
    }
    // create new model view object
    var modelView = _.clone(defaultOptions)
    // set record type views to be parallel and out-of-order by default
    if (args.type === 'record') {
        modelView.sequential = false
    }
    // merge arguments over defaults
    mergeArgs(modelView, args)
    // if model view is being registered and override is not allowed then
    // it must not be defined
    if (modelView.register && !modelView.allowOverride && hasModelView(modelView.name)) {
        throw new Error('model view '+modelView.name+' already defined')
    }
    // make each, post, pre functions immutable
    if (modelView.immutable) {
        makeImmutable(modelView)
    }
    // return constructor function that will generate a custom model
    // view instance based on the parent model view class
    var modelViewConstructor = function () {
        // create new instance based on class meta data
        var instance = _.clone(modelView)
        // get number of args
        var numArgs = arguments.length
        // if function is passed a single object then these arguments will
        // be passed directly to the view instance func
        if (numArgs === 1 && typeof arguments[0] === 'object') {
            instance.args = arguments[0]
        }
        // otherwise create args as empty object
        else {
            instance.args = {}
            // if there are arguments then they must be string property names
            if (numArgs > 0) {
                // create properties
                instance.args.properties = []
                // check that all args are strings
                for (var i=0; i < numArgs; i++) {
                    assert(typeof arguments[i] === 'string', 'invalid argument '+arguments[i])
                    // add argument to list of properties
                    instance.args.properties[i] = arguments[i]
                }
            }
        }
        // set modelViewInstanceId on instance
        setModelViewInstanceId(instance)
        // set class properties
        instance.class = 'ImmutableCoreModelViewInstance'
        instance.ImmutableCoreModelViewInstance = true
        // return instance object
        return instance
    }
    // store class data on constructor function
    modelViewConstructor.modelView = modelView
    // add model view to global register
    if (modelView.register) {
        immutableCoreModelView.modelViews[modelView.name] = modelViewConstructor
    }
    // set class properties
    modelViewConstructor.class = 'ImmutableCoreModelView'
    modelViewConstructor.ImmutableCoreModelView = true
    // set modelViewId on modelView
    setModelViewId(modelViewConstructor)
    // return constructor function
    return modelViewConstructor
}