text: /**
   * Since we make rendr files AMD friendly on app setup stage
   * we need to pretend that this code is pure commonjs
   * means no AMD-style require calls.
   */
  var requireAMD = require;
  
  var BaseModel = require("./base/model"),
      BaseCollection = require("./base/collection");
  
  var typePath = {
    model: "app/models/",
    collection: "app/collections/"
  };
  
  module.exports = ModelUtils;
  
  function ModelUtils(entryPath) {
    this.entryPath = entryPath;
    this._classMap = {};
  }
  
  ModelUtils.prototype.getModel = function(path, attrs, options, callback) {
    var Model;
    attrs = attrs || {};
    options = options || {};
    if (typeof callback == 'function') {
      this.getModelConstructor(path, function(Model) {
        callback(new Model(attrs, options));
      });
    } else {
      Model = this.getModelConstructor(path);
      return new Model(attrs, options);
    }
  };
  
  ModelUtils.prototype.getCollection = function(path, models, options, callback) {
    var Collection;
    models = models || [];
    options = options || {};
    if (typeof callback == 'function') {
      this.getCollectionConstructor(path, function(Collection) {
        callback(new Collection(models, options));
      });
    } else {
      Collection = this.getCollectionConstructor(path);
      return new Collection(models, options);
    }
  };
  
  ModelUtils.prototype.getModelConstructor = function(path, callback) {
    return this.fetchConstructor('model', path, callback);
  };
  
  ModelUtils.prototype.getCollectionConstructor = function(path, callback) {
    return this.fetchConstructor('collection', path, callback);
  };
  
  ModelUtils.prototype.getFullPath = function(type, path) {
    return this.entryPath + typePath[type] + path;
  };
  
  ModelUtils.prototype.fetchConstructor = function(type, path, callback) {
    path = this.underscorize(path);
  
    var fullPath = this.getFullPath(type, path);
  
    if (this._classMap[path]) {
      return (typeof callback == 'function') ? callback(this._classMap[path]) : this._classMap[path];
    } else if (typeof callback == 'function') {
      // Only used in AMD environment
      if (typeof define != 'undefined') {
        requireAMD([fullPath], callback);
      } else {
        callback(require(fullPath));
      }
      return;
    } else {
      return require(fullPath);
    }
  };
  
  ModelUtils.prototype.isModel = function(obj) {
    return obj instanceof BaseModel;
  };
  
  ModelUtils.prototype.isCollection = function(obj) {
    return obj instanceof BaseCollection;
  };
  
  ModelUtils.prototype.getModelNameForCollectionName = function(collectionName) {
    var Collection;
    Collection = this.getCollectionConstructor(collectionName);
    return this.modelName(Collection.prototype.model);
  };
  
  ModelUtils.uppercaseRe = /([A-Z])/g;
  
  ModelUtils.prototype.underscorize = function(name) {
    if (name == null) {
      return undefined;
    }
    name = name.replace(ModelUtils.uppercaseRe, function(c) {
      return "_" + c.toLowerCase();
    });
    if (name[0] === "_") {
      name = name.slice(1);
    }
    return name;
  };
  
  /**
   * The 'name' property is added to the constructor when using a named function,
   * and it cannot be changed.  I.e.:
   *
   * function MyClass(){}
   * MyClass.name
   * -> "MyClass"
   *
   * We first look for the 'id' property of the constructor, which is compatible
   * with standard Backbone-style class inheritance.
   *
   * var MyClass = Backbone.Model.extend({});
   * MyClass.name
   * -> ""
   * MyClass.id = "MyClass"
   */
  ModelUtils.prototype.modelName = function(modelOrCollectionClass) {
    return this.underscorize(modelOrCollectionClass.id || modelOrCollectionClass.name);
  };
  
  ModelUtils.prototype.modelIdAttribute = function(modelName, callback) {
    this.getModelConstructor(modelName, function(constructor) {
      callback(constructor.prototype.idAttribute);
    });
  };
  