Generates a property definition for a model type
@param {*} model
@param {*} property
@param {*} modelName
@param {*} propertyName
@param {*} isInputType
774344
function mapProperty(model, property, modelName, propertyName, isInputType = false) {

    // If property is deprecated, ignore it.
    if (property.deprecated) {
        return;
    }

    // Bootstrap basic property object
    types[modelName].meta.fields[propertyName] = {
        generated: false,
        meta: {
            required: property.required,
            hidden: model.definition.settings.hidden && model.definition.settings.hidden.indexOf(propertyName) !== -1
        }
    };
    const currentProperty = types[modelName].meta.fields[propertyName];

    const typeName = `${modelName}_${propertyName}`;
    let propertyType = property.type;

    // Add resolver
    currentProperty.resolve = (obj, args, context) => (_.isNil(obj[propertyName]) ? null : obj[propertyName]);

    // If it's an Array type, map it to JSON Scalar
    if (propertyType.name === 'Array') { // JSON Array
        currentProperty.meta.list = true;
        currentProperty.meta.type = 'JSON';
        currentProperty.meta.scalar = true;
        return;
    }

    // If it's an Array type, map it to JSON Scalar
    if (propertyType.name === 'GeoPoint') { // JSON Array
        currentProperty.meta.type = (isInputType) ? 'GeoPointInput' : 'GeoPoint';
        return;
    }

    // If property.type is an array, its a list type.
    if (_.isArray(property.type)) {
        currentProperty.meta.list = true;
        propertyType = property.type[0];
    }

    // See if this property is a scalar.
    let scalar = getScalar(propertyType.name);

    if (property.defaultFn) {
        scalar = getScalar(property.defaultFn);
    }

    if (scalar) {
        currentProperty.meta.scalar = true;
        currentProperty.meta.type = scalar;

        if (property.enum) { // enum has a dedicated type but no input type is required
            types[typeName] = {
                generated: false,
                name: typeName,
                values: property.enum,
                meta: {
                    category: 'ENUM'
                }
            };
            currentProperty.type = typeName;
        }
    }

    // If this property is another Model
    if (propertyType.name === 'ModelConstructor' && property.defaultFn !== 'now') {
        currentProperty.meta.type = (!isInputType) ? propertyType.modelName : `${propertyType.modelName}Input`;
        const union = propertyType.modelName.split('|');

        // type is a union
        if (union.length > 1) { // union type
            types[typeName] = { // creating a new union type
                generated: false,
                name: typeName,
                meta: {
                    category: 'UNION'
                },
                values: toTypes(union)
            };
        } else if (propertyType.settings && propertyType.settings.anonymous && propertyType.definition) {
            currentProperty.meta.type = typeName;
            types[typeName] = {
                generated: false,
                name: typeName,
                meta: {
                    category: 'TYPE',
                    input: isInputType,
                    fields: {}
                }
            }; // creating a new type
            _.forEach(propertyType.definition.properties, (p, key) => {
                mapProperty(propertyType, p, typeName, key, isInputType);
            });
        }
    }
}
1232724
function findScope(model, prop) {
    while (model[parentScopeName] &&
           !Object.prototype.hasOwnProperty.call(model, prop)) {
      model = model[parentScopeName];
    }

    return model;
  }
980245
function findPropertyMetaInfo(type, property) {
    if (!type) {
        return;
    }
    if (typeof type === 'string') {
        var context = findTypeMetaInfo(type);
    } else {
        var context = type;
        type = type.name;
    }
    if (!context) {
        return;
    }

    var info = (context.inputsClass || []).find(i => i.name == property) ||
        (context.outputsClass || []).find(i => i.name == property) ||
        mergeProperties(context).find(i => i.name == property) ||
        (context.methodsClass || context.methods || []).find(i => i.name == property);
    if (info) {
        return {type: context, property: info};
    }
    return findPropertyMetaInfo(context.extends, property);
}
1181727
function generateModel(path, modelName, modelFields, generateMethod, ts, cb) {
    var fields = formatTools.getFieldsForModelTemplate(modelFields);
    var schemaName = modelName + 'Schema';

    var extension = (ts) ? 'ts' : 'js';
    var model = ft.loadTemplateSync('model.' + extension);
    model = model.replace(/{modelName}/, modelName);
    model = model.replace(/{schemaName}/g, schemaName);
    model = model.replace(/{fields}/, fields);

    if (generateMethod === 't') {
        ft.createDirIfIsNotDefined(path, 'models', function () {
            ft.writeFile(path + '/models/' + modelName + 'Model.' + extension, model, null, cb);
        });
    } else {
        ft.createDirIfIsNotDefined(path, modelName, function () {
            ft.writeFile(path + '/' + modelName + '/' + modelName + 'Model.' + extension, model, null, cb);
        });
    }
}
288585
function (name, schema, models, modelPropertyMacro) {
    var strongOpen = '<span class="strong">';
    var strongClose = '</span>';

    var optionHtml = function (label, value) {
      return '<tr><td class="optionName">' + label + ':</td><td>' + value + '</td></tr>';
    };


    // Allow for ignoring the 'name' argument.... shifting the rest
    if(_.isObject(arguments[0])) {
      name = void 0;
      schema = arguments[0];
      models = arguments[1];
      modelPropertyMacro = arguments[2];
    }

    models = models || {};

    // Resolve the schema (Handle nested schemas)
    schema = resolveSchema(schema);

    // Return for empty object
    if(_.isEmpty(schema)) {
      return strongOpen + 'Empty' + strongClose;
    }

    // Dereference $ref from 'models'
    if(typeof schema.$ref === 'string') {
      name = simpleRef(schema.$ref);
      schema = models[name];
      if(typeof schema === 'undefined')
      {
        return strongOpen + name + ' is not defined!' + strongClose;
      }
    }

    if(typeof name !== 'string') {
      name = schema.title || 'Inline Model';
    }

    // If we are a Model object... adjust accordingly
    if(schema.definition) {
      schema = schema.definition;
    }

    if(typeof modelPropertyMacro !== 'function') {
      modelPropertyMacro = function(prop){
        return (prop || {}).default;
      };
    }

    var references = {};
    var seenModels = [];
    var inlineModels = 0;

    // Generate current HTML
    var html = processModel(schema, name);

    // Generate references HTML
    while (_.keys(references).length > 0) {
      /* jshint ignore:start */
      _.forEach(references, function (schema, name) {
        var seenModel = _.indexOf(seenModels, name) > -1;

        delete references[name];

        if (!seenModel) {
          seenModels.push(name);

          html += '<br />' + processModel(schema, name);
        }
      });
      /* jshint ignore:end */
    }

    return html;


    function addReference(schema, name, skipRef) {
      var modelName = name;
      var model;

      if (schema.$ref) {
        modelName = schema.title || simpleRef(schema.$ref);
        model = models[simpleRef(schema.$ref)];
      } else if (_.isUndefined(name)) {
        modelName = schema.title || 'Inline Model ' + (++inlineModels);
        model = {definition: schema};
      }

      if (skipRef !== true) {
        references[modelName] = _.isUndefined(model) ? {} : model.definition;
      }

      return modelName;
    }

    function primitiveToHTML(schema) {
      var html = '<span class="propType">';
      var type = schema.type || 'object';

      if (schema.$ref) {
        html += addReference(schema, simpleRef(schema.$ref));
      } else if (type === 'object') {
        if (!_.isUndefined(schema.properties)) {
          html += addReference(schema);
        } else {
          html += 'object';
        }
      } else if (type === 'array') {
        html += 'Array[';

        if (_.isArray(schema.items)) {
          html += _.map(schema.items, addReference).join(',');
        } else if (_.isPlainObject(schema.items)) {
          if (_.isUndefined(schema.items.$ref)) {
            if (!_.isUndefined(schema.items.type) && _.indexOf(['array', 'object'], schema.items.type) === -1) {
              html += schema.items.type;
            } else {
              html += addReference(schema.items);
            }
          } else {
            html += addReference(schema.items, simpleRef(schema.items.$ref));
          }
        } else {
          console.log('Array type\'s \'items\' schema is not an array or an object, cannot process');
          html += 'object';
        }

        html += ']';
      } else {
        html += schema.type;
      }

      html += '</span>';

      return html;
    }

    function primitiveToOptionsHTML(schema, html) {
      var options = '';
      var type = schema.type || 'object';
      var isArray = type === 'array';

      if (isArray) {
        if (_.isPlainObject(schema.items) && !_.isUndefined(schema.items.type)) {
          type = schema.items.type;
        } else {
          type = 'object';
        }
      }

      if (!_.isUndefined(schema.default)) {
        options += optionHtml('Default', schema.default);
      }

      switch (type) {
      case 'string':
        if (schema.minLength) {
          options += optionHtml('Min. Length', schema.minLength);
        }

        if (schema.maxLength) {
          options += optionHtml('Max. Length', schema.maxLength);
        }

        if (schema.pattern) {
          options += optionHtml('Reg. Exp.', schema.pattern);
        }
        break;
      case 'integer':
      case 'number':
        if (schema.minimum) {
          options += optionHtml('Min. Value', schema.minimum);
        }

        if (schema.exclusiveMinimum) {
          options += optionHtml('Exclusive Min.', 'true');
        }

        if (schema.maximum) {
          options += optionHtml('Max. Value', schema.maximum);
        }

        if (schema.exclusiveMaximum) {
          options += optionHtml('Exclusive Max.', 'true');
        }

        if (schema.multipleOf) {
          options += optionHtml('Multiple Of', schema.multipleOf);
        }

        break;
      }

      if (isArray) {
        if (schema.minItems) {
          options += optionHtml('Min. Items', schema.minItems);
        }

        if (schema.maxItems) {
          options += optionHtml('Max. Items', schema.maxItems);
        }

        if (schema.uniqueItems) {
          options += optionHtml('Unique Items', 'true');
        }

        if (schema.collectionFormat) {
          options += optionHtml('Coll. Format', schema.collectionFormat);
        }
      }

      if (_.isUndefined(schema.items)) {
        if (_.isArray(schema.enum)) {
          var enumString;

          if (type === 'number' || type === 'integer') {
            enumString = schema.enum.join(', ');
          } else {
            enumString = '"' + schema.enum.join('", "') + '"';
          }

          options += optionHtml('Enum', enumString);
        }
      }

      if (options.length > 0) {
        html = '<span class="propWrap">' + html + '<table class="optionsWrapper"><tr><th colspan="2">' + type + '</th></tr>' + options + '</table></span>';
      }

      return html;
    }

    function processModel(schema, name) {
      var type = schema.type || 'object';
      var isArray = schema.type === 'array';
      var html = strongOpen + name + ' ' + (isArray ? '[' : '{') + strongClose;
      var contents;

      if (name) {
        seenModels.push(name);
      }

      if (isArray) {
        if (_.isArray(schema.items)) {
          html += '<div>' + _.map(schema.items, function (item) {
            var type = item.type || 'object';

            if (_.isUndefined(item.$ref)) {
              if (_.indexOf(['array', 'object'], type) > -1) {
                if (type === 'object' && _.isUndefined(item.properties)) {
                  return 'object';
                } else {
                  return addReference(item);
                }
              } else {
                return primitiveToOptionsHTML(item, type);
              }
            } else {
              return addReference(item, simpleRef(item.$ref));
            }
          }).join(',</div><div>');
        } else if (_.isPlainObject(schema.items)) {
          if (_.isUndefined(schema.items.$ref)) {
            if (_.indexOf(['array', 'object'], schema.items.type || 'object') > -1) {
              if ((_.isUndefined(schema.items.type) || schema.items.type === 'object') && _.isUndefined(schema.items.properties)) {
                html += '<div>object</div>';
              } else {
                html += '<div>' + addReference(schema.items) + '</div>';
              }
            } else {
              html += '<div>' + primitiveToOptionsHTML(schema.items, schema.items.type) + '</div>';
            }
          } else {
            html += '<div>' + addReference(schema.items, simpleRef(schema.items.$ref)) + '</div>';
          }
        } else {
          console.log('Array type\'s \'items\' property is not an array or an object, cannot process');
          html += '<div>object</div>';
        }
      } else {
        if (schema.$ref) {
          html += '<div>' + addReference(schema, name) + '</div>';
        } else if (type === 'object') {
          if (_.isPlainObject(schema.properties)) {
            contents = _.map(schema.properties, function (property, name) {
              var propertyIsRequired = (_.indexOf(schema.required, name) >= 0);
              var cProperty = _.cloneDeep(property);

              var requiredClass = propertyIsRequired ? 'required' : '';
              var html = '<span class="propName ' + requiredClass + '">' + name + '</span> (';
              var model;
              var propDescription;

              // Allow macro to set the default value
              cProperty.default = modelPropertyMacro(cProperty);

              // Resolve the schema (Handle nested schemas)
              cProperty = resolveSchema(cProperty);

              propDescription = property.description || cProperty.description;

              // We need to handle property references to primitives (Issue 339)
              if (!_.isUndefined(cProperty.$ref)) {
                model = models[simpleRef(cProperty.$ref)];

                if (!_.isUndefined(model) && _.indexOf([undefined, 'array', 'object'], model.definition.type) === -1) {
                  // Use referenced schema
                  cProperty = resolveSchema(model.definition);
                }
              }

              html += primitiveToHTML(cProperty);

              if(!propertyIsRequired) {
                html += ', <span class="propOptKey">optional</span>';
              }

              if(property.readOnly) {
                  html += ', <span class="propReadOnly">read only</span>';
              }

              html += ')';

              if (!_.isUndefined(propDescription)) {
                html += ': ' + '<span class="propDesc">' + propDescription + '</span>';
              }

              if (cProperty.enum) {
                html += ' = <span class="propVals">[\'' + cProperty.enum.join('\', \'') + '\']</span>';
              }

              return '<div' + (property.readOnly ? ' class="readOnly"' : '') + '>' + primitiveToOptionsHTML(cProperty, html);
            }).join(',</div>');
          }

          if (contents) {
            html += contents + '</div>';
          }
        } else {
          html += '<div>' + primitiveToOptionsHTML(schema, type) + '</div>';
        }
      }

      return html + strongOpen + (isArray ? ']' : '}') + strongClose;
    }

  }
181184
function mapDefinitionsFromModel(model) {
  const definitionMap = [];

  /* istanbul ignore else */
  if (model && model.definitions) {
    debug('Parsing %s definitions', Object.keys(model.definitions).length);
    for (const definitionName of Object.keys(model.definitions)) {
      debug('  Reading definition for %s', definitionName);
      const definitionKey = util.format('#/definitions/%s', definitionName);
      const currentDef = model.definitions[definitionName];
      currentDef.definitionName = definitionName;
      currentDef.referencePath = definitionKey;
      definitionMap[definitionKey] = currentDef;
    }
  }

  return definitionMap;
}
1197038
function modelItem(data, model) {
    var res = {};

    utils.defineProperties(res, {
        _isModelItem: { value: true },

        model: { value: model.value },

        update: { value: function(data, sync) {
            if (sync == null) sync = true;

            return update(res, model, data).then(function() {
                if (!sync) return;
                return res.save();
            });
        } },

        save: { value: function() {
            if (_.has(res, 'id')) {
                var props = serverProperties(res, model);
                return utils.socketPost(model.io, model.url + '/update/' + res.id, props.properties).then(function() {
                    return Promise.all(_.map(props.refresh, function(item) {
                        return item.refresh();
                    }));
                });
            }
            return create(res, model);
        } },

        refresh: { value: function() {
            if (!_.has(res, 'id')) return create(res, model);

            return utils.socketGet(model.io, model.url + '/' + res.id).then(function(data) {
                return update(res, model, data, { noRefresh: true });
            });
        } },

        delete: { value: function() {
            model._removeItem(res);
            return utils.socketDelete(model.io, model.url, { id: res.id });
        } },

        matches: { value: function(query) {
            return utils.socketGet(model.io, model.url, query).then(function(r) {
                for (var i = 0; i < r.length; i++) {
                    if (r[i].id === res.id) return true;
                }
                return false;
            });
        } },

        then: { value: function() {
            return res.ready.then.apply(res.ready, arguments);
        } },

        catch: { value: function() {
            return res.ready.catch.apply(res.ready, arguments);
        } }
    });

    res.ready = Promise.resolve();

    update(res, model, data || {});

    return res;
}
84888
function initModel (args) {
    // if model is not passed then do nothing
    if (!args.model) {
        return
    }
    // if paths is false then do not create any default paths
    if (args.paths === false) {
        return
    }
    // require object to have ImmutableCoreObject class property
    assert.ok(args.model.ImmutableCoreModel, 'invalid model')
    // save model
    this.model = args.model
    // register controller with model
    this.model.controller = this
    // if model has data then create form for it
    if (this.model.schemaData && _.keys(this.model.schemaData.properties).length) {
        // build args for new form
        var formArgs = {
            action: './',
            method: 'POST',
            model: this.model,
            submit: {
                title: 'Create '+changeCase.titleCase(this.model.name),
            },
            title: 'New '+changeCase.titleCase(this.model.name),
        }
        // merge any args for form
        _.merge(formArgs, args.form)
        // create new form instance from model
        this.form = new ImmutableCoreModelForm(formArgs)
    }
    // create path entry if it does not exist
    if (!this.paths) {
        this.paths = {}
    }
    // create actions object
    this.actions = {}
    // merge actions from controller spec
    if (defined(args.actions)) {
        // do not allow array
        if (Array.isArray(args.actions)) {
            throw new Error(`actions array deprecated for controller ${this.model.name}`)
        }
        // get actions from controller spec
        _.merge(this.actions, args.actions)
    }
    // create list view controller
    this.initModelList(args)
    // new instance controller
    this.initModelNew(args)
    // create instance controller
    this.initModelCreate(args)
    // get instance controller
    this.initModelRead(args)
    // update instance controller
    this.initModelUpdate(args)
    // link model to relations controller
    this.initModelLink(args)
    // unlink model from relation controller
    this.initModelUnlink(args)
    // delete instance controller
    this.initModelDelete(args)
    // model schema controller
    this.initModelSchema(args)
    // validate data controller
    this.initModelValidate(args)
}
323534
function (model, data, action, options) {
                var schema = model.schema,
                    schemaDefinition,
                    schemaType,
                    value,
                    factory,
                    newData = {};

                // convert top level properties to Models respective to there schema
                for (var key in schema) {
                    if (schema.hasOwnProperty(key)) {

                        schemaDefinition = schema[key];
                        schemaType = schemaDefinition.type;
                        value = this._getValueForKey(data, key, schemaType, schemaDefinition);

                        factory = null;
                        var typeResolver,
                            entity,
                            i,
                            list;
                        if (schemaType instanceof Array) {
                            if (schemaType.length === 1) {
                                typeResolver = schemaType[0];
                            } else if (schemaType.length === 0) {
                                this.log('ModelFactory for ListItem for "' + key + '" not defined', 'warn');
                                factory = Entity;
                            } else {
                                throw "Cannot determinate ModelFactory. Multiple factories defined for '" + key + "'.";
                            }

                            if (typeResolver instanceof Function) {
                                factory = typeResolver;
                                typeResolver = null;
                            }

                            if (value && value instanceof Array) {
                                // only create the list if items are there
                                list = newData[key] = new List();

                                for (i = 0; i < value.length; i++) {

                                    if (typeResolver) {
                                        factory = typeResolver.resolve(value[i], key);
                                    }

                                    if ((factory && factory.classof(Entity))) {
                                        entity = this.$dataSource._getContext(factory, model, value[i]).createEntity(factory, this._getIdForValue(value[i], factory));
                                        if (entity instanceof Entity && !(entity instanceof Model)) {
                                            entity.$parent = model;
                                            entity.$parentEntity = model;
                                        }
                                        entity.set(this._parseModel(entity, value[i], action, options));

                                        list.add(entity);
                                    } else {
                                        list.add(value[i]);
                                    }

                                }
                            }


                        } else if (Collection && schemaType.classof(Collection)) {
                            var contextForChildren = this.$dataSource._getContext(schemaType, model, value);
                            if (contextForChildren) {
                                if (model.$[key] instanceof Collection) {
                                    newData[key] = model.$[key];
                                    list = model.$[key];
                                } else {
                                    list = newData[key] = contextForChildren.createCollection(schemaType, (value instanceof Object) && !(value instanceof Array) ? value : null);
                                    list.$parent = contextForChildren.$contextModel;
                                }
                                if (value && value instanceof Array) {
                                    list.reset(this.parseCollection(list, value, action, options));
                                }

                            }
                        } else if (schemaType === Date && value && !(value instanceof Date)) {
                            newData[key] = moment(value, this.$dataSource.$.dateFormat).toDate();
                        } else if (schemaType.classof(Entity)) {
                            var id;
                            if (value && schemaType instanceof TypeResolver) {
                                factory = schemaType.resolve(value, key);
                            } else {
                                factory = schemaType || Entity;
                            }

                            if (!(factory && factory.classof(Entity))) {
                                throw "Factory for type '" + key + "' isn't an instance of Entity";
                            }

                            if (factory.classof(Model) && factory.prototype.$isDependentObject) {
                                id = key;
                                value = value || {};
                            } else if (value) {
                                id = this._getIdForValue(value, factory);
                            }
                            if (value) {
                                newData[key] = entity = this.$dataSource._getContext(factory, model, value).createEntity(factory, id);
                                if (entity instanceof Entity && !(entity instanceof Model)) {
                                    entity.$parent = model;
                                    entity.$parentEntity = model;
                                }
                                entity.set(this._parseModel(entity, value, action, options));
                            }

                        }
                    }
                }

                // add all values that are not defined in schema ...
                _.defaults(newData, data);

                return model.parse(newData);
            }
299555
public Type getPropertyType(String property) {
    Type type = (Type) propertyTypes.get(property);
    if (null == type) {
      Class<?> propertyType = PropertyUtils.getPropertyType(entityClass, property);
      if (null != propertyType) {
        if (Entity.class.isAssignableFrom(propertyType)) type = new EntityType(propertyType);
        if (propertyType.isInterface()) type = Model.getType(propertyType.getName());
        if (null == type) type = new IdentifierType(propertyType);
      }
    }
    if (null == type) logger.error("{} doesn't contains property {}", entityName, property);
    return type;
  }
728159
function(modelName)
	{
		modelName = modelName || '*';
		if(this._bindingIndex !== null && this.scope.hasOwnProperty(modelName)) return this._bindingIndex;
		if(this.parentView instanceof View) return this.parentView.getBindingIndex(modelName);
		return null;
	}
743420
function(model) {
    var fields = _.keys(model);
    var updated = {};

    _.each(fields, function(field) {
        var updatedField = {};
        var modelField = {};
        if (!(field === Object(field))) {
            updatedField.field = field;
            if (!(model[field] === Object(model[field]))) {
                modelField = { type: model[field] };
            } else {
                modelField = model[field];
            }
            updatedField = _.defaults(updatedField, modelField);
        } else {
            updatedField = field;
        }
        updated[updatedField.field] = updatedField;
    });

    return updated;
}
786053
public static void beginStringConversion(Builder methodBuilder, ModelProperty property) {
		TypeName modelType = typeName(property.getElement().asType());

		beginStringConversion(methodBuilder, modelType);
	}
1178768
function View(primaryModel, relatedModels, attributes) {
  if (false === (this instanceof View)) throw new Error('new operator required');
  if (!(primaryModel instanceof Model)) throw new Error('argument must be a Model');
  if (typeof relatedModels != 'object') throw new Error('object expected');
  if (!(attributes instanceof Array)) throw new Error('array of attributes expected');
  this.primaryModel = primaryModel;
  this.relatedModels = relatedModels;
  this.attributes = attributes;
  var id = new Attribute('id', 'ID');
  id.model = primaryModel;
  this.attributes.unshift(id);

  /**
   * Make sure relatedModels valid
   */
  for (var relatedModel in relatedModels) {
    if (relatedModels.hasOwnProperty(relatedModel)) {
      var obj = relatedModels[relatedModel];
      //console.log('relatedModel ' + relatedModel);
      //console.log('obj ' + JSON.stringify(obj));
      if (typeof obj != 'object') throw new Error('relatedModel key values expect object');
      if (obj.id === undefined) throw new Error('relatedModel key values expect object with id key');
      if (obj.model === undefined) throw new Error('relatedModel key values expect object with model key');
      if (!(obj.id instanceof Attribute)) throw new Error('relatedModel id must be a Attribute');
      if (!(obj.model instanceof Model)) throw new Error('relatedModel model must be a Model');
    }
  }
  /**
   * Check attributes
   */
  for (var i = 0; i < attributes.length; i++) {
    var attribute = attributes[i];
    if (!(attribute instanceof Attribute)) throw new Error('attribute array must contain Attributes');
    if (!(attribute.model instanceof Model)) {
      throw new Error('attribute array must contain Attributes with model references');
    }

  }
}
825147
function(attrs, options) {
      if (attrs instanceof Model) return attrs;
      options = options ? _.clone(options) : {};
      options.collection = this;
      var model = new this.model(attrs, options);
      if (!model.validationError) return model;
      this.trigger('invalid', this, model.validationError, options);
      return false;
    }
416172
function normalizeProperties (properties, name) {
  // HACK
  if (!model) {
    model = require('./model')
  }

  // Allow for shorthand type declaration:
  // Check to see if the user passed in a raw type of a properties hash.
  if (properties) {
    // Raw type passed.
    // index: Type is translated to index: {type: Type}
    // Properties hash created.
    if (properties.type === undefined) {
      properties = {
        type: properties
      }

      // Properties hash passed.
      // Copy properties hash before modifying.
      // Users can pass in their own custom types to the schema and we don't want to write to that object.
      // Especially since properties.name contains the index of our field and copying that will break functionality.
    } else {
      properties = clone(properties)
    }
  }

  // Type may be an object with properties.
  // If "type.type" exists, we'll assume it's meant to be properties.
  // This means that shorthand objects can't use the "type" index.
  // If "type" is necessary, they must be wrapped in a Model.
  if (_.isObject(properties.type) && properties.type.type !== undefined) {
    _.each(properties.type, (value, key) => {
      if (properties[key] === undefined) {
        properties[key] = value
      }
    })
    properties.type = properties.type.type
  }

  // Null or undefined should be flexible and allow any value.
  if (properties.type === null || properties.type === undefined) {
    properties.type = 'any'

    // Convert object representation of type to lowercase string.
    // String is converted to 'string', Number to 'number', etc.
    // Do not convert the initialized ModelInstance to a string!
    // Check for a shorthand declaration of schema by key length.
  } else if (_.isString(properties.type.name) && properties.type.name !== 'ModelInstance' && Object.keys(properties.type).length === 0) {
    properties.type = properties.type.name
  }
  if (_.isString(properties.type)) {
    properties.type = properties.type.toLowerCase()
  }

  // index: [Type] or index: [] is translated to index: {type: Array, arrayType: Type}
  if (_.isArray(properties.type)) {
    if (_.size(properties.type)) {
      // Properties will be normalized when array is initialized.
      properties.arrayType = properties.type[0]
    }
    properties.type = 'array'
  }

  // index: {} or index: Model is translated to index: {type: Object, objectType: Type}
  if (!_.isString(properties.type)) {
    if (_.isFunction(properties.type)) {
      properties.objectType = properties.type
      properties.type = 'object'

      // if it's a function we have a ctor. if we have model name defined than it's one of ours.
      // set it as ref so we can typecase appropriately
      if (properties.objectType.modelName) {
        properties.ref = true
      }
    } else if (_.isObject(properties.type)) {
      // When {} is passed, no schema is enforced.
      if (_.size(properties.type)) {
        // Options should be inherited by sub-models.
        properties.objectType = model.compile(properties.type, this.options || {}, undefined, this.lounge)
      }
      properties.type = 'object'
    }
  }

  // Set name if passed on properties.
  // It's used to show what field an error what generated on.
  if (name) {
    properties.name = name
  }

  return properties
}
1141717
function generateTypeDefs(models) {

    types = Object.assign({}, types, getCustomTypeDefs());

    _.forEach(models, (model) => {
        mapType(model);
        mapInputType(model);
    });

    return types;
}