text:
/*!
 * Module exports class Model
 */
module.exports = DataAccessObject;

/*!
 * Module dependencies
 */
var async = require('async');
var jutil = require('./jutil');
var ValidationError = require('./validations').ValidationError;
var Relation = require('./relations.js');
var Inclusion = require('./include.js');
var List = require('./list.js');
var geo = require('./geo');
var Memory = require('./connectors/memory').Memory;
var utils = require('./utils');
var fieldsToArray = utils.fieldsToArray;
var removeUndefined = utils.removeUndefined;
var setScopeValuesFromWhere = utils.setScopeValuesFromWhere;
var mergeQuery = utils.mergeQuery;
var util = require('util');
var assert = require('assert');
var BaseModel = require('./model');
var debug = require('debug')('loopback:dao');

/**
 * Base class for all persistent objects.
 * Provides a common API to access any database connector.
 * This class describes only abstract behavior.  Refer to the specific connector for additional details.
 *
 * `DataAccessObject` mixes `Inclusion` classes methods.
 * @class DataAccessObject
 */
function DataAccessObject() {
  if (DataAccessObject._mixins) {
    var self = this;
    var args = arguments;
    DataAccessObject._mixins.forEach(function (m) {
      m.call(self, args);
    });
  }
}

function idName(m) {
  return m.definition.idName() || 'id';
}

function getIdValue(m, data) {
  return data && data[idName(m)];
}

function setIdValue(m, data, value) {
  if (data) {
    data[idName(m)] = value;
  }
}

function byIdQuery(m, id) {
  var pk = idName(m);
  var query = { where: {} };
  query.where[pk] = id;
  return query;
}

function isWhereByGivenId(Model, where, idValue) {
  var keys = Object.keys(where);
  if (keys.length != 1) return false;

  var pk = idName(Model);
  if (keys[0] !== pk) return false;

  return where[pk] === idValue;
}

DataAccessObject._forDB = function (data) {
  if (!(this.getDataSource().isRelational && this.getDataSource().isRelational())) {
    return data;
  }
  var res = {};
  for (var propName in data) {
    var type = this.getPropertyType(propName);
    if (type === 'JSON' || type === 'Any' || type === 'Object' || data[propName] instanceof Array) {
      res[propName] = JSON.stringify(data[propName]);
    } else {
      res[propName] = data[propName];
    }
  }
  return res;
};

DataAccessObject.defaultScope = function(target, inst) {
  var scope = this.definition.settings.scope;
  if (typeof scope === 'function') {
    scope = this.definition.settings.scope.call(this, target, inst);
  }
  return scope;
};

DataAccessObject.applyScope = function(query, inst) {
  var scope = this.defaultScope(query, inst) || {};
  if (typeof scope === 'object') {
    mergeQuery(query, scope || {}, this.definition.settings.scope);
  }
};

DataAccessObject.applyProperties = function(data, inst) {
  var properties = this.definition.settings.properties;
  properties = properties || this.definition.settings.attributes;
  if (typeof properties === 'object') {
    util._extend(data, properties);
  } else if (typeof properties === 'function') {
    util._extend(data, properties.call(this, data, inst) || {});
  } else if (properties !== false) {
    var scope = this.defaultScope(data, inst) || {};
    if (typeof scope.where === 'object') {
      setScopeValuesFromWhere(data, scope.where, this);
    }
  }
};

DataAccessObject.lookupModel = function(data) {
  return this;
};

/**
 * Get the connector instance for the given model class
 * @returns {Connector} The connector instance
 */
DataAccessObject.getConnector = function() {
  return this.getDataSource().connector;
}

// Empty callback function
function noCallback(err, result) {
  // NOOP
  debug('callback is ignored: err=%j, result=%j', err, result);
}

/**
 * Create an instance of Model with given data and save to the attached data source. Callback is optional.
 * Example:
 *```js
 * User.create({first: 'Joe', last: 'Bob'}, function(err, user) {
 *  console.log(user instanceof User); // true
 * });
 * ```
 * Note: You must include a callback and use the created model provided in the callback if your code depends on your model being
 * saved or having an ID.
 *
 * @param {Object} [data] Optional data object
 * @param {Object} [options] Options for create
 * @param {Function} [cb]  Callback function called with these arguments:
 *   - err (null or Error)
 *   - instance (null or Model)
 */
DataAccessObject.create = function (data, options, cb) {
  var connectionPromise = stillConnecting(this.getDataSource(), this, arguments);
  if (connectionPromise) {
    return connectionPromise;
  }

  var Model = this;
  var connector = Model.getConnector();
  assert(typeof connector.create === 'function',
    'create() must be implemented by the connector');

  var self = this;

  if (options === undefined && cb === undefined) {
    if (typeof data === 'function') {
      // create(cb)
      cb = data;
      data = {};
    }
  } else if (cb === undefined) {
    if (typeof options === 'function') {
      // create(data, cb);
      cb = options;
      options = {};
    }
  }

  data = data || {};
  options = options || {};
  cb = cb || (Array.isArray(data) ? noCallback : utils.createPromiseCallback());

  assert(typeof data === 'object', 'The data argument must be an object or array');
  assert(typeof options === 'object', 'The options argument must be an object');
  assert(typeof cb === 'function', 'The cb argument must be a function');

  var hookState = {};

  if (Array.isArray(data)) {
    // Undefined item will be skipped by async.map() which internally uses
    // Array.prototype.map(). The following loop makes sure all items are
    // iterated
    for (var i = 0, n = data.length; i < n; i++) {
      if (data[i] === undefined) {
        data[i] = {};
      }
    }
    async.map(data, function(item, done) {
      self.create(item, options, function(err, result) {
        // Collect all errors and results
        done(null, {err: err, result: result || item});
      });
    }, function(err, results) {
      if (err) {
        return cb(err, results);
      }
      // Convert the results into two arrays
      var errors = null;
      var data = [];
      for (var i = 0, n = results.length; i < n; i++) {
        if (results[i].err) {
          if (!errors) {
            errors = [];
          }
          errors[i] = results[i].err;
        }
        data[i] = results[i].result;
      }
      cb(errors, data);
    });
    return data;
  }

  var enforced = {};
  var obj;
  var idValue = getIdValue(this, data);

  // if we come from save
  if (data instanceof Model && !idValue) {
    obj = data;
  } else {
    obj = new Model(data);
  }

  this.applyProperties(enforced, obj);
  obj.setAttributes(enforced);

  Model = this.lookupModel(data); // data-specific
  if (Model !== obj.constructor) obj = new Model(data);

  var context = {
    Model: Model,
    instance: obj,
    isNewInstance: true,
    hookState: hookState,
    options: options
  };
  Model.notifyObserversOf('before save', context, function(err) {
    if (err) return cb(err);

    data = obj.toObject(true);

    // validation required
    obj.isValid(function (valid) {
      if (valid) {
        create();
      } else {
        cb(new ValidationError(obj), obj);
      }
    }, data);
  });

  function create() {
    obj.trigger('create', function (createDone) {
      obj.trigger('save', function (saveDone) {
        var _idName = idName(Model);
        var modelName = Model.modelName;
        var val = removeUndefined(obj.toObject(true));
        function createCallback(err, id, rev) {
          if (id) {
            obj.__data[_idName] = id;
            defineReadonlyProp(obj, _idName, id);
          }
          if (rev) {
            obj._rev = rev;
          }
          if (err) {
            return cb(err, obj);
          }
          obj.__persisted = true;
          saveDone.call(obj, function () {
            createDone.call(obj, function () {
              if (err) {
                return cb(err, obj);
              }
              var context = {
                Model: Model,
                instance: obj,
                isNewInstance: true,
                hookState: hookState,
                options: options
              };
              Model.notifyObserversOf('after save', context, function(err) {
                cb(err, obj);
                if(!err) Model.emit('changed', obj);
              });
            });
          });
        }

        if (connector.create.length === 4) {
          connector.create(modelName, this.constructor._forDB(val), options, createCallback);
        } else {
          connector.create(modelName, this.constructor._forDB(val), createCallback);
        }
      }, obj, cb);
    }, obj, cb);
  }

  // Does this make any sense? How would chaining be used here? -partap

  // for chaining
  return cb.promise || obj;
};

function stillConnecting(dataSource, obj, args) {
  if (typeof args[args.length-1] === 'function') {
    return dataSource.ready(obj, args);
  }

  // promise variant
  var promiseArgs = Array.prototype.slice.call(args);
  promiseArgs.callee = args.callee
  var cb =  utils.createPromiseCallback();
  promiseArgs.push(cb);
  if (dataSource.ready(obj, promiseArgs)) {
    return cb.promise;
  } else {
    return false;
  }
}

/**
 * Update or insert a model instance: update exiting record if one is found, such that parameter `data.id` matches `id` of model instance;
 * otherwise, insert a new record.
 *
 * NOTE: No setters, validations, or hooks are applied when using upsert.
 * `updateOrCreate` is an alias
 * @param {Object} data The model instance data
 * @param {Object} [options] Options for upsert
 * @param {Function} cb The callback function (optional).
 */
// [FIXME] rfeng: This is a hack to set up 'upsert' first so that
// 'upsert' will be used as the name for strong-remoting to keep it backward
// compatible for angular SDK
DataAccessObject.updateOrCreate = DataAccessObject.upsert = function upsert(data, options, cb) {
  var connectionPromise = stillConnecting(this.getDataSource(), this, arguments);
  if (connectionPromise) {
    return connectionPromise;
  }

  if (options === undefined && cb === undefined) {
    if (typeof data === 'function') {
      // upsert(cb)
      cb = data;
      data = {};
    }
  } else if (cb === undefined) {
    if (typeof options === 'function') {
      // upsert(data, cb)
      cb = options;
      options = {};
    }
  }

  cb = cb || utils.createPromiseCallback();
  data = data || {};
  options = options || {};

  assert(typeof data === 'object', 'The data argument must be an object');
  assert(typeof options === 'object', 'The options argument must be an object');
  assert(typeof cb === 'function', 'The cb argument must be a function');

  var hookState = {};

  var self = this;
  var Model = this;
  var connector = Model.getConnector();

  var id = getIdValue(this, data);
  if (id === undefined || id === null) {
    return this.create(data, options, cb);
  }

  var context = {
    Model: Model,
    query: byIdQuery(Model, id),
    hookState: hookState,
    options: options
  };
  Model.notifyObserversOf('access', context, doUpdateOrCreate);

  function doUpdateOrCreate(err, ctx) {
    if (err) return cb(err);

    var isOriginalQuery = isWhereByGivenId(Model, ctx.query.where, id)
    if (connector.updateOrCreate && isOriginalQuery) {
      var context = {
        Model: Model,
        where: ctx.query.where,
        data: data,
        hookState: hookState,
        options: options
      };
      Model.notifyObserversOf('before save', context, function(err, ctx) {
        if (err) return cb(err);

        data = ctx.data;
        var update = data;
        var inst = data;
        if(!(data instanceof Model)) {
          inst = new Model(data);
        }
        update = inst.toObject(false);

        Model.applyProperties(update, inst);
        Model = Model.lookupModel(update);

        var connector = self.getConnector();

        if (Model.settings.validateUpsert === false) {
          update = removeUndefined(update);
          if (connector.updateOrCreate.length === 4) {
            connector.updateOrCreate(Model.modelName, update, options, done);
          } else {
            connector.updateOrCreate(Model.modelName, update, done);
          }
        } else {
          inst.isValid(function(valid) {
            if (!valid) {
              if (Model.settings.validateUpsert) {
                return cb(new ValidationError(inst), inst);
              } else {
                // TODO(bajtos) Remove validateUpsert:undefined in v3.0
                console.warn('Ignoring validation errors in updateOrCreate():');
                console.warn('  %s', new ValidationError(inst).message);
                // continue with updateOrCreate
              }
            }

            update = removeUndefined(update);
            if (connector.updateOrCreate.length === 4) {
              connector.updateOrCreate(Model.modelName, update, options, done);
            } else {
              connector.updateOrCreate(Model.modelName, update, done);
            }
          }, update);
        }

        function done(err, data, info) {
          var obj;
          if (data && !(data instanceof Model)) {
            inst._initProperties(data, { persisted: true });
            obj = inst;
          } else {
            obj = data;
          }
          if (err) {
            cb(err, obj);
            if(!err) {
              Model.emit('changed', inst);
            }
          } else {
            var context = {
              Model: Model,
              instance: obj,
              isNewInstance: info ? info.isNewInstance : undefined,
              hookState: hookState,
              options: options
            };
            Model.notifyObserversOf('after save', context, function(err) {
              cb(err, obj);
              if(!err) {
                Model.emit('changed', inst);
              }
            });
          }
        }
      });
    } else {
      Model.findOne({ where: ctx.query.where }, { notify: false }, function (err, inst) {
        if (err) {
          return cb(err);
        }
        if (!isOriginalQuery) {
          // The custom query returned from a hook may hide the fact that
          // there is already a model with `id` value `data[idName(Model)]`
          delete data[idName(Model)];
        }
        if (inst) {
          inst.updateAttributes(data, options, cb);
        } else {
          Model = self.lookupModel(data);
          var obj = new Model(data);
          obj.save(options, cb);
        }
      });
    }
  }
  return cb.promise;
};

/**
 * Find one record that matches specified query criteria.  Same as `find`, but limited to one record, and this function returns an
 * object, not a collection.
 * If the specified instance is not found, then create it using data provided as second argument.
 *
 * @param {Object} query Search conditions. See [find](#dataaccessobjectfindquery-callback) for query format.
 * For example: `{where: {test: 'me'}}`.
 * @param {Object} data Object to create.
 * @param {Object} [options] Option for findOrCreate
 * @param {Function} cb Callback called with (err, instance, created)
 */
DataAccessObject.findOrCreate = function findOrCreate(query, data, options, cb) {
  var connectionPromise = stillConnecting(this.getDataSource(), this, arguments);
  if (connectionPromise) {
    return connectionPromise;
  }

  assert(arguments.length >= 1, 'At least one argument is required');
  if (data === undefined && options === undefined && cb === undefined) {
    assert(typeof query === 'object', 'Single argument must be data object');
    // findOrCreate(data);
    // query will be built from data, and method will return Promise
    data = query;
    query = {where: data};
  } else  if (options === undefined && cb === undefined) {
    if (typeof data === 'function') {
      // findOrCreate(data, cb);
      // query will be built from data
      cb = data;
      data = query;
      query = {where: data};
    }
  } else if (cb === undefined) {
    if (typeof options === 'function') {
      // findOrCreate(query, data, cb)
      cb = options;
      options = {};
    }
  }

  cb = cb || utils.createPromiseCallback();
  query = query || {where: {}};
  data = data || {};
  options = options || {};

  assert(typeof query === 'object', 'The query argument must be an object');
  assert(typeof data === 'object', 'The data argument must be an object');
  assert(typeof options === 'object', 'The options argument must be an object');
  assert(typeof cb === 'function', 'The cb argument must be a function');

  var hookState = {};

  var Model = this;
  var self = this;
  var connector = Model.getConnector();

  function _findOrCreate(query, data) {
    var modelName = self.modelName;
    data = removeUndefined(data);
    function findOrCreateCallback(err, data, created) {
      var obj, Model = self.lookupModel(data);

      if (data) {
        obj = new Model(data, {fields: query.fields, applySetters: false,
          persisted: true});
      }

      if (created) {
        var context = {
          Model: Model,
          instance: obj,
          isNewInstance: true,
          hookState: hookState,
          options: options
        };
        Model.notifyObserversOf('after save', context, function(err) {
          if (cb.promise) {
            cb(err, [obj, created]);
          } else {
            cb(err, obj, created);
          }
          if (!err) Model.emit('changed', obj);
        });
      } else {
        if (cb.promise) {
          cb(err, [obj, created]);
        } else {
          cb(err, obj, created);
        }
      }
    }

    if (connector.findOrCreate.length === 5) {
      connector.findOrCreate(modelName, query, self._forDB(data), options, findOrCreateCallback);
    } else {
      connector.findOrCreate(modelName, query, self._forDB(data), findOrCreateCallback);
    }
  }

  if (connector.findOrCreate) {
    query.limit = 1;

    try {
      this._normalize(query);
    } catch (err) {
      process.nextTick(function () {
        cb(err);
      });
      return cb.promise;
    }

    this.applyScope(query);

    var context = {
      Model: Model,
      query: query,
      hookState: hookState,
      options: options
    };
    Model.notifyObserversOf('access', context, function (err, ctx) {
      if (err) return cb(err);

      var query = ctx.query;

      var enforced = {};
      var Model = self.lookupModel(data);
      var obj = data instanceof Model ? data : new Model(data);

      Model.applyProperties(enforced, obj);
      obj.setAttributes(enforced);

      var context = {
        Model: Model,
        instance: obj,
        isNewInstance: true,
        hookState: hookState,
        options: options
       };
      Model.notifyObserversOf('before save', context, function(err, ctx) {
        if (err) return cb(err);

        var obj = ctx.instance;
        var data = obj.toObject(true);

        // validation required
        obj.isValid(function (valid) {
          if (valid) {
            _findOrCreate(query, data);
          } else {
            cb(new ValidationError(obj), obj);
          }
        }, data);
      });
    });
  } else {
    Model.findOne(query, options, function (err, record) {
      if (err) return cb(err);
      if (record) {
        if (cb.promise) {
          return cb(null, [record, false]);
        } else {
          return cb(null, record, false);
        }
      }
      Model.create(data, options, function (err, record) {
        if (cb.promise) {
          cb(err, [record, record != null]);
        } else {
          cb(err, record, record != null);
        }
      });
    });
  }
  return cb.promise;
};

/**
 * Check whether a model instance exists in database
 *
 * @param {id} id Identifier of object (primary key value)
 * @param {Object} [options] Options
 * @param {Function} cb Callback function called with (err, exists: Bool)
 */
DataAccessObject.exists = function exists(id, options, cb) {
  var connectionPromise = stillConnecting(this.getDataSource(), this, arguments);
  if (connectionPromise) {
    return connectionPromise;
  }

  assert(arguments.length >= 1, 'The id argument is required');
  if (cb === undefined) {
    if (typeof options === 'function') {
      // exists(id, cb)
      cb = options;
      options = {};
    }
  }

  cb = cb || utils.createPromiseCallback();
  options = options || {};

  assert(typeof options === 'object', 'The options argument must be an object');
  assert(typeof cb === 'function', 'The cb argument must be a function');

  if (id !== undefined && id !== null && id !== '') {
    this.count(byIdQuery(this, id).where, options, function(err, count) {
      cb(err, err ? false : count === 1);
    });
  } else {
    process.nextTick(function() {
      cb(new Error('Model::exists requires the id argument'));
    });
  }
  return cb.promise;
};

/**
 * Find model instance by ID.
 *
 * Example:
 * ```js
 * User.findById(23, function(err, user) {
 *   console.info(user.id); // 23
 * });
 * ```
 *
 * @param {*} id Primary key value
 * @param {Object} [filter] The filter that contains `include` or `fields`.
 * Other settings such as `where`, `order`, `limit`, or `offset` will be
 * ignored.
 * @param {Object} [options] Options
 * @param {Function} cb Callback called with (err, instance)
 */
DataAccessObject.findById = function findById(id, filter, options, cb) {
  var connectionPromise = stillConnecting(this.getDataSource(), this, arguments);
  if (connectionPromise) {
    return connectionPromise;
  }

  assert(arguments.length >= 1, 'The id argument is required');

  if (options === undefined && cb === undefined) {
    if (typeof filter === 'function') {
      // findById(id, cb)
      cb = filter;
      filter = {};
    }
  } else if (cb === undefined) {
    if (typeof options === 'function') {
      // findById(id, query, cb)
      cb = options;
      options = {};
      if (typeof filter === 'object' && !(filter.include || filter.fields)) {
        // If filter doesn't have include or fields, assuming it's options
        options = filter;
        filter = {};
      }
    }
  }

  cb = cb || utils.createPromiseCallback();
  options = options || {};
  filter = filter || {};

  assert(typeof filter === 'object', 'The filter argument must be an object');
  assert(typeof options === 'object', 'The options argument must be an object');
  assert(typeof cb === 'function', 'The cb argument must be a function');

  if (id == null || id === '') {
    process.nextTick(function() {
      cb(new Error('Model::findById requires the id argument'));
    });
  } else {
    var query = byIdQuery(this, id);
    if (filter.include) {
      query.include = filter.include;
    }
    if (filter.fields) {
      query.fields = filter.fields;
    }
    this.findOne(query, options, cb);
  }
  return cb.promise;
};

/**
 * Find model instances by ids
 * @param {Array} ids An array of ids
 * @param {Object} query Query filter
 * @param {Object} [options] Options
 * @param {Function} cb Callback called with (err, instance)
 */
DataAccessObject.findByIds = function(ids, query, options, cb) {
  if (options === undefined && cb === undefined) {
    if (typeof query === 'function') {
      // findByIds(ids, cb)
      cb = query;
      query = {};
    }
  } else if (cb === undefined) {
    if (typeof options === 'function') {
      // findByIds(ids, query, cb)
      cb = options;
      options = {};
    }
  }

  cb = cb || utils.createPromiseCallback();
  options = options || {};
  query = query || {};

  assert(Array.isArray(ids), 'The ids argument must be an array');
  assert(typeof query === 'object', 'The query argument must be an object');
  assert(typeof options === 'object', 'The options argument must be an object');
  assert(typeof cb === 'function', 'The cb argument must be a function');

  var pk = idName(this);
  if (ids.length === 0) {
    process.nextTick(function() { cb(null, []); });
    return cb.promise;;
  }

  var filter = { where: {} };
  filter.where[pk] = { inq: [].concat(ids) };
  mergeQuery(filter, query || {});
  this.find(filter, options, function(err, results) {
    cb(err, err ? results : utils.sortObjectsByIds(pk, ids, results));
  });
  return cb.promise;
};

function convertNullToNotFoundError(ctx, cb) {
  if (ctx.result !== null) return cb();

  var modelName = ctx.method.sharedClass.name;
  var id = ctx.getArgByName('id');
  var msg = 'Unknown "' + modelName + '" id "' + id + '".';
  var error = new Error(msg);
  error.statusCode = error.status = 404;
  cb(error);
}

// alias function for backwards compat.
DataAccessObject.all = function () {
  return DataAccessObject.find.apply(this, arguments);
};

var operators = {
  gt: '>',
  gte: '>=',
  lt: '<',
  lte: '<=',
  between: 'BETWEEN',
  inq: 'IN',
  nin: 'NOT IN',
  neq: '!=',
  like: 'LIKE',
  nlike: 'NOT LIKE'
};

/*
 * Normalize the filter object and throw errors if invalid values are detected
 * @param {Object} filter The query filter object
 * @returns {Object} The normalized filter object
 * @private
 */
DataAccessObject._normalize = function (filter) {
  if (!filter) {
    return undefined;
  }
  var err = null;
  if ((typeof filter !== 'object') || Array.isArray(filter)) {
    err = new Error(util.format('The query filter %j is not an object', filter));
    err.statusCode = 400;
    throw err;
  }
  if (filter.limit || filter.skip || filter.offset) {
    var limit = Number(filter.limit || 100);
    var offset = Number(filter.skip || filter.offset || 0);
    if (isNaN(limit) || limit <= 0 || Math.ceil(limit) !== limit) {
      err = new Error(util.format('The limit parameter %j is not valid',
        filter.limit));
      err.statusCode = 400;
      throw err;
    }
    if (isNaN(offset) || offset < 0 || Math.ceil(offset) !== offset) {
      err = new Error(util.format('The offset/skip parameter %j is not valid',
          filter.skip || filter.offset));
      err.statusCode = 400;
      throw err;
    }
    filter.limit = limit;
    filter.offset = offset;
    filter.skip = offset;
  }

  if (filter.order) {
    var order = filter.order;
    if (!Array.isArray(order)) {
      order = [order];
    }
    var fields = [];
    for (var i = 0, m = order.length; i < m; i++) {
      if (typeof order[i] === 'string') {
        // Normalize 'f1 ASC, f2 DESC, f3' to ['f1 ASC', 'f2 DESC', 'f3']
        var tokens = order[i].split(/(?:\s*,\s*)+/);
        for (var t = 0, n = tokens.length; t < n; t++) {
          var token = tokens[t];
          if (token.length === 0) {
            // Skip empty token
            continue;
          }
          var parts = token.split(/\s+/);
          if (parts.length >= 2) {
            var dir = parts[1].toUpperCase();
            if (dir === 'ASC' || dir === 'DESC') {
              token = parts[0] + ' ' + dir;
            } else {
              err = new Error(util.format('The order %j has invalid direction', token));
              err.statusCode = 400;
              throw err;
            }
          }
          fields.push(token);
        }
      } else {
        err = new Error(util.format('The order %j is not valid', order[i]));
        err.statusCode = 400;
        throw err;
      }
    }
    if (fields.length === 1 && typeof filter.order === 'string') {
      filter.order = fields[0];
    } else {
      filter.order = fields;
    }
  }

  // normalize fields as array of included property names
  if (filter.fields) {
    filter.fields = fieldsToArray(filter.fields,
      Object.keys(this.definition.properties), this.settings.strict);
  }

  filter = removeUndefined(filter);
  this._coerce(filter.where);
  return filter;
};

function DateType(arg) {
  var d = new Date(arg);
  if (isNaN(d.getTime())) {
    throw new Error('Invalid date: ' + arg);
  }
  return d;
}

function BooleanType(arg) {
  if (typeof arg === 'string') {
    switch (arg) {
      case 'true':
      case '1':
        return true;
      case 'false':
      case '0':
        return false;
    }
  }
  if (arg == null) {
    return null;
  }
  return Boolean(arg);
}

function NumberType(val) {
  var num = Number(val);
  return !isNaN(num) ? num : val;
}

/*
 * Coerce values based the property types
 * @param {Object} where The where clause
 * @returns {Object} The coerced where clause
 * @private
 */
DataAccessObject._coerce = function (where) {
  var self = this;
  if (!where) {
    return where;
  }

  var err;
  if (typeof where !== 'object' || Array.isArray(where)) {
    err = new Error(util.format('The where clause %j is not an object', where));
    err.statusCode = 400;
    throw err;
  }

  var props = self.definition.properties;
  for (var p in where) {
    // Handle logical operators
    if (p === 'and' || p === 'or' || p === 'nor') {
      var clauses = where[p];
      if (Array.isArray(clauses)) {
        for (var k = 0; k < clauses.length; k++) {
          self._coerce(clauses[k]);
        }
      } else {
        err = new Error(util.format('The %s operator has invalid clauses %j', p, clauses));
        err.statusCode = 400;
        throw err;
      }
      return where;
    }
    var DataType = props[p] && props[p].type;
    if (!DataType) {
      continue;
    }
    if (Array.isArray(DataType) || DataType === Array) {
      DataType = DataType[0];
    }
    if (DataType === Date) {
      DataType = DateType;
    } else if (DataType === Boolean) {
      DataType = BooleanType;
    } else if (DataType === Number) {
      // This fixes a regression in mongodb connector
      // For numbers, only convert it produces a valid number
      // LoopBack by default injects a number id. We should fix it based
      // on the connector's input, for example, MongoDB should use string
      // while RDBs typically use number
      DataType = NumberType;
    }

    if (!DataType) {
      continue;
    }

    if (DataType.prototype instanceof BaseModel) {
      continue;
    }

    if (DataType === geo.GeoPoint) {
      // Skip the GeoPoint as the near operator breaks the assumption that
      // an operation has only one property
      // We should probably fix it based on
      // http://docs.mongodb.org/manual/reference/operator/query/near/
      // The other option is to make operators start with $
      continue;
    }

    var val = where[p];
    if (val === null || val === undefined) {
      continue;
    }
    // Check there is an operator
    var operator = null;
    if ('object' === typeof val) {
      if (Object.keys(val).length !== 1) {
        // Skip if there are not only one properties
        // as the assumption for operators is not true here
        continue;
      }
      for (var op in operators) {
        if (op in val) {
          val = val[op];
          operator = op;
          switch(operator) {
            case 'inq':
            case 'nin':
              if (!Array.isArray(val)) {
                err = new Error(util.format('The %s property has invalid clause %j', p, where[p]));
                err.statusCode = 400;
                throw err;
              }
              break;
            case 'between':
              if (!Array.isArray(val) || val.length !== 2) {
                err = new Error(util.format('The %s property has invalid clause %j', p, where[p]));
                err.statusCode = 400;
                throw err;
              }
              break;
            case 'like':
            case 'nlike':
              if (!(typeof val === 'string' || val instanceof RegExp)) {
                err = new Error(util.format('The %s property has invalid clause %j', p, where[p]));
                err.statusCode = 400;
                throw err;
              }
              break;
          }
          break;
        }
      }
    }
    // Coerce the array items
    if (Array.isArray(val)) {
      for (var i = 0; i < val.length; i++) {
        if (val[i] !== null && val[i] !== undefined) {
          val[i] = DataType(val[i]);
        }
      }
    } else {
      if (val !== null && val !== undefined) {
        val = DataType(val);
      }
    }
    // Rebuild {property: {operator: value}}
    if (operator) {
      var value = {};
      value[operator] = val;
      val = value;
    }
    where[p] = val;
  }
  return where;
};

/**
 * Find all instances of Model that match the specified query.
 * Fields used for filter and sort should be declared with `{index: true}` in model definition.
 * See [Querying models](http://docs.strongloop.com/display/DOC/Querying+models) for more information.
 *
 * For example, find the second page of ten users over age 21 in descending order exluding the password property.
 *
 * ```js
 * User.find({
 *   where: {
 *     age: {gt: 21}},
 *     order: 'age DESC',
 *     limit: 10,
 *     skip: 10,
 *     fields: {password: false}
 *   },
 *   console.log
 * );
 * ```
 *
 * @options {Object} [query] Optional JSON object that specifies query criteria and parameters.
 * @property {Object} where Search criteria in JSON format `{ key: val, key2: {gt: 'val2'}}`.
 * Operations:
 * - gt: >
 * - gte: >=
 * - lt: <
 * - lte: <=
 * - between
 * - inq: IN
 * - nin: NOT IN
 * - neq: !=
 * - like: LIKE
 * - nlike: NOT LIKE
 *
 * You can also use `and` and `or` operations.  See [Querying models](http://docs.strongloop.com/display/DOC/Querying+models) for more information.
 * @property {String|Object|Array} include Allows you to load relations of several objects and optimize numbers of requests.
 * Format examples;
 * - `'posts'`: Load posts
 * - `['posts', 'passports']`: Load posts and passports
 * - `{'owner': 'posts'}`: Load owner and owner's posts
 * - `{'owner': ['posts', 'passports']}`: Load owner, owner's posts, and owner's passports
 * - `{'owner': [{posts: 'images'}, 'passports']}`: Load owner, owner's posts, owner's posts' images, and owner's passports
 * See `DataAccessObject.include()`.
 * @property {String} order Sort order.  Format: `'key1 ASC, key2 DESC'`
 * @property {Number} limit Maximum number of instances to return.
 * @property {Number} skip Number of instances to skip.
 * @property {Number} offset Alias for `skip`.
 * @property {Object|Array|String} fields Included/excluded fields.
 * - `['foo']` or `'foo'` - include only the foo property
 *  - `['foo', 'bar']` - include the foo and bar properties.  Format:
 *  - `{foo: true}` - include only foo
 * - `{bat: false}` - include all properties, exclude bat
 *
 * @param {Function} cb Required callback function.  Call this function with two arguments: `err` (null or Error) and an array of instances.
 */

DataAccessObject.find = function find(query, options, cb) {
  var connectionPromise = stillConnecting(this.getDataSource(), this, arguments);
  if (connectionPromise) {
    return connectionPromise;
  }

  if (options === undefined && cb === undefined) {
    if (typeof query === 'function') {
      // find(cb);
      cb = query;
      query = {};
    }
  } else if (cb === undefined) {
    if (typeof options === 'function') {
      // find(query, cb);
      cb = options;
      options = {};
    }
  }

  cb = cb || utils.createPromiseCallback();
  query = query || {};
  options = options || {};

  assert(typeof query === 'object', 'The query argument must be an object');
  assert(typeof options === 'object', 'The options argument must be an object');
  assert(typeof cb === 'function', 'The cb argument must be a function');

  var hookState = {};
  var self = this;
  var connector = self.getConnector();

  assert(typeof connector.all === 'function',
    'all() must be implemented by the connector');

  try {
    this._normalize(query);
  } catch (err) {
    process.nextTick(function () {
      cb(err);
    });
    return cb.promise;
  }

  this.applyScope(query);

  var near = query && geo.nearFilter(query.where);
  var supportsGeo = !!connector.buildNearFilter;

  if (near) {
    if (supportsGeo) {
      // convert it
      connector.buildNearFilter(query, near);
    } else if (query.where) {
      // do in memory query
      // using all documents
      // TODO [fabien] use default scope here?

      var context = {
        Model: self,
        query: query,
        hookState: hookState,
        options: options
      };
      self.notifyObserversOf('access', context, function(err, ctx) {
        if (err) return cb(err);

        function geoCallback(err, data) {
          var memory = new Memory();
          var modelName = self.modelName;

          if (err) {
            cb(err);
          } else if (Array.isArray(data)) {
            memory.define({
              properties: self.dataSource.definitions[self.modelName].properties,
              settings: self.dataSource.definitions[self.modelName].settings,
              model: self
            });

            data.forEach(function(obj) {
              memory.create(modelName, obj, options, function() {
                // noop
              });
            });

            // FIXME: apply "includes" and other transforms - see allCb below
            memory.all(modelName, ctx.query, options, cb);
          } else {
            cb(null, []);
          }
        }

        if (connector.all.length === 4) {
          connector.all(self.modelName, {}, options, geoCallback);
        } else {
          connector.all(self.modelName, {}, geoCallback);
        }
      });

      // already handled
      return cb.promise;
    }
  }

  var allCb = function(err, data) {
    var results = [];
    if (Array.isArray(data)) {
      for (var i = 0, n = data.length; i < n; i++) {
        var d = data[i];
        var Model = self.lookupModel(d);
        var obj = new Model(d, {fields: query.fields, applySetters: false, persisted: true});

        if (query && query.include) {
          if (query.collect) {
            // The collect property indicates that the query is to return the
            // standalone items for a related model, not as child of the parent object
            // For example, article.tags
            obj = obj.__cachedRelations[query.collect];
            if (obj === null) {
              obj = undefined;
            }
          } else {
            // This handles the case to return parent items including the related
            // models. For example, Article.find({include: 'tags'}, ...);
            // Try to normalize the include
            var includes = Inclusion.normalizeInclude(query.include || []);
            includes.forEach(function(inc) {
              var relationName = inc;
              if (utils.isPlainObject(inc)) {
                relationName = Object.keys(inc)[0];
              }

              // Promote the included model as a direct property
              var included = obj.__cachedRelations[relationName];
              if (Array.isArray(included)) {
                included = new List(included, null, obj);
              }
              if (included) obj.__data[relationName] = included;
            });
            delete obj.__data.__cachedRelations;
          }
        }
        if (obj !== undefined) {
          results.push(obj);
        }
      }

      if (data && data.countBeforeLimit) {
        results.countBeforeLimit = data.countBeforeLimit;
      }
      if (!supportsGeo && near) {
        results = geo.filter(results, near);
      }

      cb(err, results);
    }
    else
      cb(err, []);
  };

  if (options.notify === false) {
    if (connector.all.length === 4) {
      connector.all(self.modelName, query, options, allCb);
    } else {
      connector.all(self.modelName, query, allCb);
    }
  } else {
    var context =  {
      Model: this,
      query: query,
      hookState: hookState,
      options: options
    };
    this.notifyObserversOf('access', context, function(err, ctx) {
      if (err) return cb(err);
      var query = ctx.query;
      if (connector.all.length === 4) {
        connector.all(self.modelName, query, options, allCb);
      } else {
        connector.all(self.modelName, query, allCb);
      }
    });
  }
  return cb.promise;
};

/**
 * Find one record, same as `find`, but limited to one result. This function returns an object, not a collection.
 *
 * @param {Object} query Search conditions.  See [find](#dataaccessobjectfindquery-callback) for query format.
 * For example: `{where: {test: 'me'}}`.
 * @param {Object} [options] Options
 * @param {Function} cb Callback function called with (err, instance)
 */
DataAccessObject.findOne = function findOne(query, options, cb) {
  var connectionPromise = stillConnecting(this.getDataSource(), this, arguments);
  if (connectionPromise) {
    return connectionPromise;
  }

  if (options === undefined && cb === undefined) {
    if (typeof query === 'function') {
      cb = query;
      query = {};
    }
  } else if (cb === undefined) {
    if (typeof options === 'function') {
      cb = options;
      options = {};
    }
  }

  cb = cb || utils.createPromiseCallback();
  query = query || {};
  options = options || {};

  assert(typeof query === 'object', 'The query argument must be an object');
  assert(typeof options === 'object', 'The options argument must be an object');
  assert(typeof cb === 'function', 'The cb argument must be a function');

  query.limit = 1;
  this.find(query, options, function (err, collection) {
    if (err || !collection || !collection.length > 0) return cb(err, null);
    cb(err, collection[0]);
  });
  return cb.promise;
};

/**
 * Destroy all matching records.
 * Delete all model instances from data source. Note: destroyAll method does not destroy hooks.
 * Example:
 *````js
 * Product.destroyAll({price: {gt: 99}}, function(err) {
   // removed matching products
 * });
 * ````
 *
 * @param {Object} [where] Optional object that defines the criteria.  This is a "where" object. Do NOT pass a filter object.
 * @param {Object) [options] Options
 * @param {Function} [cb] Callback called with (err, info)
 */
DataAccessObject.remove = DataAccessObject.deleteAll = DataAccessObject.destroyAll = function destroyAll(where, options, cb) {
  var connectionPromise = stillConnecting(this.getDataSource(), this, arguments);
  if (connectionPromise) {
    return connectionPromise;
  }

  var Model = this;
  var connector = Model.getConnector();

  assert(typeof connector.destroyAll === 'function',
    'destroyAll() must be implemented by the connector');

  if (options === undefined && cb === undefined) {
    if (typeof where === 'function') {
      cb = where;
      where = {};
    }
  } else if (cb === undefined) {
    if (typeof options === 'function') {
      cb = options;
      options = {};
    }
  }

  cb = cb || utils.createPromiseCallback();
  where = where || {};
  options = options || {};

  assert(typeof where === 'object', 'The where argument must be an object');
  assert(typeof options === 'object', 'The options argument must be an object');
  assert(typeof cb === 'function', 'The cb argument must be a function');

  var hookState = {};

  var query = { where: where };
  this.applyScope(query);
  where = query.where;

  var context = {
    Model: Model,
    where: whereIsEmpty(where) ? {} : where,
    hookState: hookState,
    options: options
  };

  if (options.notify === false) {
    doDelete(where);
  } else {
    query = { where: whereIsEmpty(where) ? {} : where };
    var context = {
      Model: Model,
      query: query,
      hookState: hookState,
      options: options
    };
    Model.notifyObserversOf('access', context, function(err, ctx) {
        if (err) return cb(err);
        var context = {
          Model: Model,
          where: ctx.query.where,
          hookState: hookState,
          options: options
        };
        Model.notifyObserversOf('before delete', context, function(err, ctx) {
          if (err) return cb(err);
          doDelete(ctx.where);
        });
      });
  }

  function doDelete(where) {
    if (whereIsEmpty(where)) {
      if (connector.destroyAll.length === 4) {
        connector.destroyAll(Model.modelName, {}, options, done);
      } else {
        connector.destroyAll(Model.modelName, {}, done);
      }
    } else {
      try {
        // Support an optional where object
        where = removeUndefined(where);
        where = Model._coerce(where);
      } catch (err) {
        return process.nextTick(function() {
          cb(err);
        });
      }

      if (connector.destroyAll.length === 4) {
        connector.destroyAll(Model.modelName, where, options, done);
      } else {
        connector.destroyAll(Model.modelName, where, done);
      }

    }

    function done(err, info) {
      if (err) return cb(err);

      if (options.notify === false) {
        return cb(err, info);
      }

      var context = {
        Model: Model,
        where: where,
        hookState: hookState,
        options: options
      };
      Model.notifyObserversOf('after delete', context, function(err) {
        cb(err, info);
        if (!err)
          Model.emit('deletedAll', whereIsEmpty(where) ? undefined : where);
      });
    }
  }
  return cb.promise;
};

function whereIsEmpty(where) {
  return !where ||
     (typeof where === 'object' && Object.keys(where).length === 0)
}

/**
 * Delete the record with the specified ID.
 * Aliases are `destroyById` and `deleteById`.
 * @param {*} id The id value
 * @param {Function} cb Callback called with (err)
 */

// [FIXME] rfeng: This is a hack to set up 'deleteById' first so that
// 'deleteById' will be used as the name for strong-remoting to keep it backward
// compatible for angular SDK
DataAccessObject.removeById = DataAccessObject.destroyById = DataAccessObject.deleteById = function deleteById(id, options, cb) {
  var connectionPromise = stillConnecting(this.getDataSource(), this, arguments);
  if (connectionPromise) {
    return connectionPromise;
  }

  assert(arguments.length >= 1, 'The id argument is required');
  if (cb === undefined) {
    if (typeof options === 'function') {
      // destroyById(id, cb)
      cb = options;
      options = {};
    }
  }

  options = options || {};
  cb = cb || utils.createPromiseCallback();

  assert(typeof options === 'object', 'The options argument must be an object');
  assert(typeof cb === 'function', 'The cb argument must be a function');

  if (id == null || id === '') {
    process.nextTick(function() {
      cb(new Error('Model::deleteById requires the id argument'));
    });
    return cb.promise;
  }

  var Model = this;

  this.remove(byIdQuery(this, id).where, options, function(err) {
    if ('function' === typeof cb) {
      cb(err);
    }
    if(!err) Model.emit('deleted', id);
  });
  return cb.promise;
};

/**
 * Return count of matched records. Optional query parameter allows you to count filtered set of model instances.
 * Example:
 *
 *```js
 * User.count({approved: true}, function(err, count) {
 *     console.log(count); // 2081
 * });
 * ```
 *
 * @param {Object} [where] Search conditions (optional)
 * @param {Object} [options] Options
 * @param {Function} cb Callback, called with (err, count)
 */
DataAccessObject.count = function (where, options, cb) {
  var connectionPromise = stillConnecting(this.getDataSource(), this, arguments);
  if (connectionPromise) {
    return connectionPromise;
  }

  if (options === undefined && cb === undefined) {
    if (typeof where === 'function') {
      // count(cb)
      cb = where;
      where = {};
    }
  } else if (cb === undefined) {
    if (typeof options === 'function') {
      // count(where, cb)
      cb = options;
      options = {};
    }
  }

  cb = cb || utils.createPromiseCallback();
  where = where || {};
  options = options || {};

  assert(typeof where === 'object', 'The where argument must be an object');
  assert(typeof options === 'object', 'The options argument must be an object');
  assert(typeof cb === 'function', 'The cb argument must be a function');

  var Model = this;
  var connector = Model.getConnector();
  assert(typeof connector.count === 'function',
    'count() must be implemented by the connector');
  assert(connector.count.length >= 3,
    'count() must take at least 3 arguments');

  var hookState = {};

  var query = { where: where };
  this.applyScope(query);
  where = query.where;

  try {
    where = removeUndefined(where);
    where = this._coerce(where);
  } catch (err) {
    process.nextTick(function () {
      cb(err);
    });
    return cb.promise;
  }

  var context = {
    Model: Model,
    query: { where: where },
    hookState: hookState,
    options: options
  };
  this.notifyObserversOf('access', context, function(err, ctx) {
    if (err) return cb(err);
    where = ctx.query.where;

    if (connector.count.length <= 3) {
      // Old signature, please note where is the last
      // count(model, cb, where)
      connector.count(Model.modelName, cb, where);
    } else {
      // New signature
      // count(model, where, options, cb)
      connector.count(Model.modelName, where, options, cb);
    }
  });
  return cb.promise;
};

/**
 * Save instance. If the instance does not have an ID, call `create` instead.
 * Triggers: validate, save, update or create.
 * @options {Object} options Optional options to use.
 * @property {Boolean} validate Default is true.
 * @property {Boolean} throws  Default is false.
 * @param {Function} cb Callback function with err and object arguments
 */
DataAccessObject.prototype.save = function (options, cb) {
  var connectionPromise = stillConnecting(this.getDataSource(), this, arguments);
  if (connectionPromise) {
    return connectionPromise;
  }
  var Model = this.constructor;

  if (typeof options === 'function') {
    cb = options;
    options = {};
  }

  cb = cb || utils.createPromiseCallback();
  options = options || {};

  assert(typeof options === 'object', 'The options argument should be an object');
  assert(typeof cb === 'function', 'The cb argument should be a function');

  if (this.isNewRecord()) {
    return Model.create(this, options, cb);
  }

  var hookState = {};

  if (options.validate === undefined) {
    options.validate = true;
  }
  if (options.throws === undefined) {
    options.throws = false;
  }

  var inst = this;
  var connector = inst.getConnector();
  var modelName = Model.modelName;

  var context = {
    Model: Model,
    instance: inst,
    hookState: hookState,
    options: options
  };
  Model.notifyObserversOf('before save', context, function(err) {
    if (err) return cb(err);

    var data = inst.toObject(true);
    Model.applyProperties(data, inst);
    inst.setAttributes(data);

    // validate first
    if (!options.validate) {
      return save();
    }

    inst.isValid(function (valid) {
      if (valid) {
        save();
      } else {
        var err = new ValidationError(inst);
        // throws option is dangerous for async usage
        if (options.throws) {
          throw err;
        }
        cb(err, inst);
      }
    });

    // then save
    function save() {
      inst.trigger('save', function (saveDone) {
        inst.trigger('update', function (updateDone) {
          data = removeUndefined(data);
          function saveCallback(err, unusedData, result) {
            if (err) {
              return cb(err, inst);
            }
            inst._initProperties(data, { persisted: true });
            var context = {
              Model: Model,
              instance: inst,
              isNewInstance: result && result.isNewInstance,
              hookState: hookState,
              options: options
            };
            Model.notifyObserversOf('after save', context, function(err) {
              if (err) return cb(err, inst);
              updateDone.call(inst, function () {
                saveDone.call(inst, function () {
                  cb(err, inst);
                  if(!err) {
                    Model.emit('changed', inst);
                  }
                });
              });
            });
          }

          if (connector.save.length === 4) {
            connector.save(modelName, inst.constructor._forDB(data), options, saveCallback);
          } else {
            connector.save(modelName, inst.constructor._forDB(data), saveCallback);
          }
        }, data, cb);
      }, data, cb);
    }
  });
  return cb.promise;
};

/**
 * Update multiple instances that match the where clause
 *
 * Example:
 *
 *```js
 * Employee.update({managerId: 'x001'}, {managerId: 'x002'}, function(err) {
 *     ...
 * });
 * ```
 *
 * @param {Object} [where] Search conditions (optional)
 * @param {Object} data Changes to be made
 * @param {Object} [options] Options for update
 * @param {Function} cb Callback, called with (err, info)
 */
DataAccessObject.update =
DataAccessObject.updateAll = function (where, data, options, cb) {
  var connectionPromise = stillConnecting(this.getDataSource(), this, arguments);
  if (connectionPromise) {
    return connectionPromise;
  }

  assert(arguments.length >= 1, 'At least one argument is required');

  if (data === undefined && options === undefined && cb === undefined && arguments.length === 1) {
    data = where;
    where = {};
  } else if (options === undefined && cb === undefined) {
    // One of:
    // updateAll(data, cb)
    // updateAll(where, data) -> Promise
    if (typeof data === 'function') {
      cb = data;
      data = where;
      where = {};
    }

  } else if (cb === undefined) {
    // One of:
    // updateAll(where, data, options) -> Promise
    // updateAll(where, data, cb)
    if (typeof options === 'function') {
      cb = options;
      options = {};
    }
  }

  data = data || {};
  options = options || {};
  cb = cb || utils.createPromiseCallback();

  assert(typeof where === 'object', 'The where argument must be an object');
  assert(typeof data === 'object', 'The data argument must be an object');
  assert(typeof options === 'object', 'The options argument must be an object');
  assert(typeof cb === 'function', 'The cb argument must be a function');

  var Model = this;
  var connector = Model.getDataSource().connector;
  assert(typeof connector.update === 'function',
    'update() must be implemented by the connector');

  var hookState = {};

  var query = { where: where };
  this.applyScope(query);
  this.applyProperties(data);

  where = query.where;

  var context = {
    Model: Model,
    query: { where: where },
    hookState: hookState,
    options: options
  };
  Model.notifyObserversOf('access', context, function(err, ctx) {
    if (err) return cb(err);
    var context = {
      Model: Model,
      where: ctx.query.where,
      data: data,
      hookState: hookState,
      options: options
    };
    Model.notifyObserversOf('before save', context,
      function(err, ctx) {
        if (err) return cb(err);
        doUpdate(ctx.where, ctx.data);
      });
  });

  function doUpdate(where, data) {
    try {
      where = removeUndefined(where);
      where = Model._coerce(where);
      data = removeUndefined(data);
      data = Model._coerce(data);
    } catch (err) {
      return process.nextTick(function () {
        cb(err);
      });
    }

    function updateCallback(err, info) {
      if (err) return cb (err);
      var context = {
        Model: Model,
        where: where,
        data: data,
        hookState: hookState,
        options: options
      };
      Model.notifyObserversOf('after save', context, function(err, ctx) {
        return cb(err, info);
      });
    }

    if (connector.update.length === 5) {
      connector.update(Model.modelName, where, data, options, updateCallback);
    } else {
      connector.update(Model.modelName, where, data, updateCallback);
    }
  }
  return cb.promise;
};

DataAccessObject.prototype.isNewRecord = function () {
  return !this.__persisted;
};

/**
 * Return connector of current record
 * @private
 */
DataAccessObject.prototype.getConnector = function () {
  return this.getDataSource().connector;
};

/**
 * Delete object from persistence
 *
 * Triggers `destroy` hook (async) before and after destroying object
 *
 * @param {Object} [options] Options for delete
 * @param {Function} cb Callback
 */
DataAccessObject.prototype.remove =
  DataAccessObject.prototype.delete =
    DataAccessObject.prototype.destroy = function (options, cb) {
      var connectionPromise = stillConnecting(this.getDataSource(), this, arguments);
      if (connectionPromise) {
        return connectionPromise;
      }

      if (cb === undefined && typeof options === 'function') {
        cb = options;
        options = {};
      }

      cb = cb || utils.createPromiseCallback();
      options = options || {};

      assert(typeof options === 'object', 'The options argument should be an object');
      assert(typeof cb === 'function', 'The cb argument should be a function');

      var inst = this;
      var connector = this.getConnector();

      var Model = this.constructor;
      var id = getIdValue(this.constructor, this);
      var hookState = {};

      var context = {
        Model: Model,
        query: byIdQuery(Model, id),
        hookState: hookState,
        options: options
      };

      Model.notifyObserversOf('access', context, function(err, ctx) {
          if (err) return cb(err);
          var context = {
            Model: Model,
            where: ctx.query.where,
            instance: inst,
            hookState: hookState,
            options: options
          };
          Model.notifyObserversOf('before delete', context, function(err, ctx) {
              if (err) return cb(err);
              doDeleteInstance(ctx.where);
            });
        });

      function doDeleteInstance(where) {
        if (!isWhereByGivenId(Model, where, id)) {
          // A hook modified the query, it is no longer
          // a simple 'delete model with the given id'.
          // We must switch to full query-based delete.
          Model.deleteAll(where, { notify: false }, function(err) {
            if (err) return cb(err);
            var context = {
              Model: Model,
              where: where,
              instance: inst,
              hookState: hookState,
              options: options
            };
            Model.notifyObserversOf('after delete', context, function(err) {
              cb(err);
              if (!err) Model.emit('deleted', id);
            });
          });
          return;
        }

        inst.trigger('destroy', function (destroyed) {
          function destroyCallback(err) {
            if (err) {
              return cb(err);
            }

            destroyed(function() {
              var context = {
                Model: Model,
                where: where,
                instance: inst,
                hookState: hookState,
                options: options
              };
              Model.notifyObserversOf('after delete', context, function(err) {
                cb(err);
                if (!err) Model.emit('deleted', id);
              });
            });
          }

          if (connector.destroy.length === 4) {
            connector.destroy(inst.constructor.modelName, id, options, destroyCallback);
          } else {
            connector.destroy(inst.constructor.modelName, id, destroyCallback);
          }
        }, null, cb);
      }
      return cb.promise;
    };

/**
 * Set a single attribute.
 * Equivalent to `setAttributes({name: value})`
 *
 * @param {String} name Name of property
 * @param {Mixed} value Value of property
 */
DataAccessObject.prototype.setAttribute = function setAttribute(name, value) {
  this[name] = value; // TODO [fabien] - currently not protected by applyProperties
};

/**
 * Update a single attribute.
 * Equivalent to `updateAttributes({name: value}, cb)`
 *
 * @param {String} name Name of property
 * @param {Mixed} value Value of property
 * @param {Function} cb Callback function called with (err, instance)
 */
DataAccessObject.prototype.updateAttribute = function updateAttribute(name, value, options, cb) {
  var data = {};
  data[name] = value;
  return this.updateAttributes(data, options, cb);
};

/**
 * Update set of attributes.
 *
 * @trigger `change` hook
 * @param {Object} data Data to update
 */
DataAccessObject.prototype.setAttributes = function setAttributes(data) {
  if (typeof data !== 'object') return;

  this.constructor.applyProperties(data, this);

  var Model = this.constructor;
  var inst = this;

  // update instance's properties
  for (var key in data) {
    inst.setAttribute(key, data[key]);
  }

  Model.emit('set', inst);
};

DataAccessObject.prototype.unsetAttribute = function unsetAttribute(name, nullify) {
  if (nullify || this.constructor.definition.settings.persistUndefinedAsNull) {
    this[name] = this.__data[name] = null;
  } else {
    delete this[name];
    delete this.__data[name];
  }
};

// Compare two id values to decide if updateAttributes is trying to change
// the id value for a given instance
function idEquals(id1, id2) {
  if (id1 === id2) {
    return true;
  }
  // Allows number/string conversions
  if ((typeof id1 === 'number' && typeof id2 === 'string') ||
    (typeof id1 === 'string' && typeof id2 === 'number')) {
    return id1 == id2;
  }
  // For complex id types such as MongoDB ObjectID
  id1 = JSON.stringify(id1);
  id2 = JSON.stringify(id2);
  if (id1 === id2) {
    return true;
  }

  return false;
}

/**
 * Update set of attributes.
 * Performs validation before updating.
 *
 * @trigger `validation`, `save` and `update` hooks
 * @param {Object} data Data to update
 * @param {Object} [options] Options for updateAttributes
 * @param {Function} cb Callback function called with (err, instance)
 */
DataAccessObject.prototype.updateAttributes = function updateAttributes(data, options, cb) {
  var connectionPromise = stillConnecting(this.getDataSource(), this, arguments);
  if (connectionPromise) {
    return connectionPromise;
  }

  if (options === undefined && cb === undefined) {
    if (typeof data === 'function') {
      // updateAttributes(cb)
      cb = data;
      data = undefined;
    }
  } else if (cb === undefined) {
    if (typeof options === 'function') {
      // updateAttributes(data, cb)
      cb = options;
      options = {};
    }
  }

  cb = cb || utils.createPromiseCallback();
  options = options || {};

  assert((typeof data === 'object') && (data !== null),
    'The data argument must be an object');
  assert(typeof options === 'object', 'The options argument must be an object');
  assert(typeof cb === 'function', 'The cb argument must be a function');

  var inst = this;
  var Model = this.constructor;
  var connector = inst.getConnector();
  assert(typeof connector.updateAttributes === 'function',
    'updateAttributes() must be implemented by the connector');

  var model = Model.modelName;
  var hookState = {};

  // Convert the data to be plain object so that update won't be confused
  if (data instanceof Model) {
    data = data.toObject(false);
  }
  data = removeUndefined(data);

  // Make sure id(s) cannot be changed
  var idNames = Model.definition.idNames();
  for (var i = 0, n = idNames.length; i < n; i++) {
    var idName = idNames[i];
    if (data[idName] !== undefined && !idEquals(data[idName], inst[idName])) {
      var err = new Error('id property (' + idName + ') ' +
        'cannot be updated from ' + inst[idName] + ' to ' + data[idName]);
      err.statusCode = 400;
      return process.nextTick(function() {
        cb(err);
      });
    }
  }

  var context = {
    Model: Model,
    where: byIdQuery(Model, getIdValue(Model, inst)).where,
    data: data,
    currentInstance: inst,
    hookState: hookState,
    options: options
  };

  Model.notifyObserversOf('before save', context, function(err, ctx) {
    if (err) return cb(err);
    data = ctx.data;

    // update instance's properties
    inst.setAttributes(data);

    inst.isValid(function (valid) {
      if (!valid) {
        cb(new ValidationError(inst), inst);
        return;
      }

      inst.trigger('save', function (saveDone) {
        inst.trigger('update', function (done) {
          var typedData = {};

          for (var key in data) {
            // Convert the properties by type
            inst[key] = data[key];
            typedData[key] = inst[key];
            if (typeof typedData[key] === 'object'
              && typedData[key] !== null
              && typeof typedData[key].toObject === 'function') {
              typedData[key] = typedData[key].toObject();
            }
          }

          function updateAttributesCallback(err) {
            if (!err) inst.__persisted = true;
            done.call(inst, function () {
              saveDone.call(inst, function () {
                if (err) return cb(err, inst);
                var context = {
                  Model: Model,
                  instance: inst,
                  isNewInstance: false,
                  hookState: hookState,
                  options: options
                };
                Model.notifyObserversOf('after save', context, function(err) {
                  if(!err) Model.emit('changed', inst);
                  cb(err, inst);
                });
              });
            });
          }

          if (connector.updateAttributes.length === 5) {
            connector.updateAttributes(model, getIdValue(inst.constructor, inst),
              inst.constructor._forDB(typedData), options, updateAttributesCallback);
          } else {
            connector.updateAttributes(model, getIdValue(inst.constructor, inst),
              inst.constructor._forDB(typedData), updateAttributesCallback);
          }
        }, data, cb);
      }, data, cb);
    }, data);
  });
return cb.promise;
};

/**
 * Reload object from persistence
 * Requires `id` member of `object` to be able to call `find`
 * @param {Function} cb Called with (err, instance) arguments
 * @private
 */
DataAccessObject.prototype.reload = function reload(cb) {
  var connectionPromise = stillConnecting(this.getDataSource(), this, arguments);
  if (connectionPromise) {
    return connectionPromise;
  }

  return this.constructor.findById(getIdValue(this.constructor, this), cb);
};

/*
 * Define readonly property on object
 *
 * @param {Object} obj
 * @param {String} key
 * @param {Mixed} value
 * @private
 */
function defineReadonlyProp(obj, key, value) {
  Object.defineProperty(obj, key, {
    writable: false,
    enumerable: true,
    configurable: true,
    value: value
  });
}

var defineScope = require('./scope.js').defineScope;

/**
 * Define a scope for the model class. Scopes enable you to specify commonly-used
 * queries that you can reference as method calls on a model.
 *
 * @param {String} name The scope name
 * @param {Object} query The query object for DataAccessObject.find()
 * @param {ModelClass} [targetClass] The model class for the query, default to
 * the declaring model
 */
DataAccessObject.scope = function (name, query, targetClass, methods, options) {
  var cls = this;
  if (options && options.isStatic === false) {
    cls = cls.prototype;
  }
  return defineScope(cls, targetClass || cls, name, query, methods, options);
};

/*
 * Add 'include'
 */
jutil.mixin(DataAccessObject, Inclusion);

/*
 * Add 'relation'
 */
jutil.mixin(DataAccessObject, Relation);

/*
 * Add 'transaction'
 */
jutil.mixin(DataAccessObject, require('./transaction'));

redpajama_set_name: RedPajamaGithub


text:
Tunes for a Monday Morning
Old stories made new
The Muses of Rooms
From "The Writer Herself" by Janet Sternberg:
"I'm drawn back to a room from my childhood -- the back room of my aunt's apartment. When my parents and I visited, I used to vanish into that room. My means of escape was the typewriter, an old manual that sat on a desk in the back room. It belonged to my aunt, but she had long since left it for the adjoining room, the kitchen. She had once wanted to write, but as the eldest of a large and troubled first-generation American family, she had other claims on her energies as well as proscriptions to contend with: class, gender, and situation joined to make her feel unworthy of literature.
"I now know I inherited some of her proscriptions," Sternberg contines, "but the back room at age nine was a place of freedom. There I could perform that significant act: I could close the door. Certainly I felt peculiar on leaving the warm and buzzing room of conversation, with its charge of familial love and invasion. But it wasn't the living room I needed: it was the writing room, which now comes back to me with its metal table, its stack of white papers that did not diminish between my visits. I would try my hand at poems; I would also construct elaborate multiple-choice tests. 'A child is an artist when, seeing a tree at dusk, she (a) climbs it (b) sketches it (c) goes home and describes it in her notebook.' And another (possibly imagined) one: 'A child is an artist when, visiting her relatives, she (a) goes down the street to play (b) talks with her family and becomes part of them (c) goes into the back room to write.'
"Oh my. Buried in those self-administered tests were the seeds of what, years later, made me stop writing. Who could possible respond correctly to so severe an inquisition? Nonetheless, that room was essential to me. I remember sitting at the desk and feeling my excitement start to build; soon I'd touch the typewriter keys, soon I'd be back in my own world. Although I felt strange and isolated, I was beginning to speak, through writing. And if I chose, I could throw out what I'd done that day; there was no obligation to show my work to anyone.
"Looking back nowl I feel sad at so constrained a sense of freedom, so defensive a stance: retreat behind a closed door. Much later, when I returned to writing after many silent years, I believed that the central act was to open that door, to make writing something that would not stand in opposition to others. I imagined a room at the heart of the house, and life in its variety flowing in and out. Later still I came to see that I continued to value separation and privacy. I began to realize that once again I'd constructed a test: a true writer either retreats and pays the price of isolation from the human stream or opens the door and pays the price of exposure to too many diverse currents. Now I've come to believe that there is no central act; instead there is a central struggle, ongoing, which is to retain control over the door -- to shut it when necessary, open it at other times -- and to retain the freedom to give up that control, and experiment with the room as porous.
"I've also come to believe that my harsh childhood testing was an attempt at self-definition -- but one made in isolation, with no knowledge of living writers. In place of a more expansive range of choices that acquaintance, particularly with working women writers, could have provided, I substituted the notion of a single criterion for an artist. That view has altered with becoming a woman and an artist."
The paintings today are by the great American realist artist Andrew Wyeth (1917-2009), whose subject was the land, people and animals around him in rural Pennsylvania and coastal Maine. He was the son of the illustrator N.C. Wyeth (1882-1945); and his own son, Jamie Wyeth, is also a painter working in the realist tradition. To learn more, I recommend An American Vision: Three Generations of Wyeth Art by James H. Duff.
The passage above is from "The Writer Herself," the introduction to The Writer on Her Work, edited by Janet Sternburg (Virago Press, 1992), which I recommend. The poem in the picture captions is "The Muses of Rooms" by Vern Rutsala (1934-2014) from Poetry Magazine, January, 1990. (Run your cursor over Wyeth's art to read it.) All rights to the text and art in this post are reserved by the authors and artist or their estates.
in Creative inspiration, On the creative process, On writing | Permalink | Comments (15)

redpajama_set_name: RedPajamaCommonCrawl


text:
Military health records contract awarded
The Department of Defense's Theater Medical Information Program has awarded a $47.8 million contract to Lockheed Martin Corp. to develop and integrate software applications.
The expected total value of the contract includes $10.25 million for the first year, plus five option periods.
The new software will be able to generate and maintain standard electronic medical records that travel with a military patient from the theater to central Defense Department health care facilities. These records can then be consolidated and made available to commanders in near real-time through the Global Combat Support System.
TMIP is a joint program between the Tricare Medical Activity and the Defense Department's Military Health System. Its mission is to provide an interoperable, integrated suite of software tools that pull together data from several existing Military Health System medical applications.
The program's applications are designed to operate in austere communications environments and run on handhelds, notebooks or client-server systems.
TMIP is designed to address shortcomings identified during the Gulf War. These deficiencies included the inability to consistently capture information within and between military services, a lack of interoperability between systems and deficiencies in communications between medical groups.
Linda Gooden, president of Lockheed Martin Information Technology, said the company has assembled a strong team to complete the work. Teammates include Booz Allen Hamilton Inc., EDS Corp., Equalnox Consulting Inc., Integic Corp. and ScenPro Inc.


Nostalgia is a funny thing for anyone who's resided abroad. Just one whiff of cous cous sends you back to the souks of Marrakesh, the notes of a strained tango to Buenos Aires. A crush of happy memories and the angst of longing for that moment. At the same time, thinking of your favorite place can be an end-all cure for homesickness of a place that may have just been your home for a brief wink of time.
This picture is of the Paseo de Espolón, a tree-lined path that winds along the bank of the Rio Arlanzón in Burgos, Spain. Despite frigid winters and blistering summers, Burgaleses can be found strolling the Espolón year round. This photo was taken in the dead of winter and, if you look closely, you can see how the knotted branches have grown together over time. When I'm feeling homesick for Spain I just look at this picture and am taken back to a cold winter day, outside of my favorite cafe in a little town in Northern Spain.
Kayla is an avid traveler with a love for photography, adventure and all things Spanish. She has spent time living in Spain, Costa Rica and Argentina and currently resides in Chicago, IL. You can see more of her photos at http://kaylachristensen.weebly.com.
Love taking shots? Been to Seville or Spain? I'm looking for travelers with a good eye to capture beautiful Spain and contribute to my weekly Snapshots section. Send your photos to sunshineandsiestas @ gmail.com with your name and a short description of the photo and look to be featured on Monday.


text:
The Blog of the Center for the Study of Constitutional Originalism
at the University of San Diego School of Law
Originalism Center YouTube Channel
Watch the Eleventh Conference
Watch the Tenth Conference
« Originalism and Birthright Citizenship
Michael Ramsey | Main | Judge Barrett on Originalism
Michael Ramsey »
Can the Vice President Break a Tie on Appointments? (with Comment from Andrew Hyman)
In the Boston Globe, Laurence Tribe (Harvard) makes an originalist case that the Vice President cannot break ties on appointments votes. It's an interesting issue but I am not persuaded.
He begins:
While the vice president has the power to cast a tiebreaking vote to pass a bill, the Constitution does not give him the power to break ties when it comes to the Senate's "Advice and Consent" role in approving presidential appointments to the Supreme Court.
You don't have to take my word for it. Alexander Hamilton said the same thing way back in 1788, in Federalist No. 69: "In the national government, if the Senate should be divided, no appointment could be made." ...
Well, I don't always take Alexander Hamilton's word for things either, although Hamilton is persuasive evidence of original meaning when he gives a persuasive account. Federalist 69, however, doesn't contain any supporting reasoning on this point, so it's unclear why Hamilton thought this was so. Federalist 69 isn't a description of the Vice President's powers. It's a wide ranging description of the President's powers, touching on appointments only briefly, and not mentioning the Vice President. It seems as likely that Hamilton ("writ[ing] like he was running out of time") simply forgot about the Vice President's role. I would count this as some evidence, but not at all conclusive.
Professor Tribe next says:
Consistent with Hamilton's understanding, as two thoughtful recent scholarly analyses have pointed out, no vice president in our history has ever cast a tiebreaking vote to confirm an appointment to the Supreme Court. If Pence tried to cast the deciding vote to confirm Trump's nomination to replace Justice Ruth Bader Ginsburg, who died last week at age 87, it would be the first time that has ever happened. That should matter to everyone — it certainly matters (or used to matter) to "originalists," who emphasize the importance of history when interpreting our Constitution.
Actually I don't think the facts stated here matter much at all to originalists. That no Vice President has ever done it proves little; we need to know whether any Vice President ever had the opportunity to do so and declined on constitutional grounds. (I assume not, or else Professor Tribe would mention it.) Also, if a Vice President had done so, it would matter a lot to originalists whether it happened early on, or in more recent years. Originalists don't generically "emphasize the importance of history when interpreting our Constitution"; they emphasize the importance of immediate post-ratification events as a way of understanding original meaning.
Skipping a bit of modern history clearly not relevant to originalists, we come to:
When it comes to legislation, the vice president's tiebreaking power affects only half of the lawmaking process: the vice president can break a tie in the Senate, but has zero say in the House of Representatives. Breaking a tie on judicial appointments, though, would give the vice president power over the entire appointments process, since it is only the Senate that weighs in on such matters. A thumb on part of the scale in the legislative process is hugely different from single-handedly tipping the entire scale when it comes to confirming justices — justices who will sit in judgment over the work of the other two branches, potentially including disputes over the upcoming election itself, in which Pence obviously has the most direct interest imaginable.
True enough, I suppose, but this isn't an originalist argument -- just an argument that there might be some policy reasons to prefer a different design. That I don't doubt: the whole Vice-President-as-President-of-the-Senate seems like a dumb idea to me, but there it is. Propose an amendment if you don't like it.
(And incidentally, under the original meaning, giving the Vice President a tiebreaking vote wasn't akin to giving the President a tiebreaking vote, since it wasn't assumed that the President and Vice President would be allies (as likely, they would be rivals, as with Adams and Jefferson). This was of course changed by the 12th Amendment, but that change didn't change the original meaning of the Vice President's tiebreaking power.)
Then there is this central structural point:
For those who care about the details, Hamilton's view and the historical practice (up until this administration) is confirmed by the structure and drafting history of our Constitution. As a structural matter, the provision granting the vice president the power to break ties in the Senate is located in Article I, which addresses Legislative Power. By contrast, the Senate's "Advice and Consent" power over judicial appointments appears in Article II, making it a form of power wielded by the Senate that is executive, not legislative, in nature. The vice president has some power to influence legislation, by casting a tiebreaking vote in the Senate, while the Senate has some power to influence executive appointments, by granting or withholding consent. Structurally, the vice president cannot smuggle his Article I legislative tiebreaking power into Article II to undermine the Senate's unique Article II executive power of advice and consent.
I like this argument because it works closely with the text. But I think it ends up being inconclusive. Maybe the framers thought about the design this way. Maybe that's why Hamilton said in Federalist 69 that a divided Senate would produce no appointment. But I can't see it as more than speculation. It's a lot of weight to put on a very subtle point about the text's structure. We can speculate that the founding generation attached this significance to the placement of the tiebreaking power in Article I, but there's not much evidence that they did. And it's not obvious that they would have drafted the Vice President's power differently if they wanted to state the tiebreaking vote on appointments expressly: maybe they would have put it in Article II as well, but as likely they would have thought the power in Article I carried over to the next article. Nothing in Article I says its powers and procedures don't carry over to later articles, and often they do. For example, when Congress exercises powers that are not granted in Article I (for example, creating lower federal courts [Article III, Sec. 1] or passing regulations for the territories [Article IV]), it follows the same procedures outlined in Article 1, Section 7; and the President has the same veto power in these non-Article I situations as is granted in Article I, Section 7.
Finally, as to drafting history:
[T]he Framers first considered a provision that "Judges shall be nominated by the Executive, and such nomination shall become an appointment if not disagreed to by the [Senate]." But they rejected that language in favor of the provision that ultimately made its way into our Constitution: "[t]he President . . . shall nominate and by and with the advice and consent of the Senate appoint . . . Judges of the Supreme Court."
That shift in language matters a lot — but only in the context of a tie. Under the first formulation, a tie favors the president, because the Senate cannot muster a majority to "disagree" with the appointment, while under the second — which became our constitutional law — a tie works against the president, because the Senate cannot muster a majority to "consent" to the appointment, leaving the nominee unconfirmed. But if the vice president is able to cast a tiebreaking vote, the difference is meaningless: The vice president decides whether the appointment goes through regardless of whether the standard is "if not disagreed to" or is "with the … consent." Surely the Founders would not have spent their time and effort changing this language, which matters only when such votes are tied, if they understood the vice president had the power to break those ties.
I think the change in language matters for a different reason. Under the original formulation, if the Senate fails to act, the appointment happens. Under the revised language, if the Senate fails to act, the appointment fails. That's a big difference unrelated to ties. Relatedly, the original draft formulation has the problem of leaving unclear how long the Senate can delay in registering its disagreement before the appointment takes effect; the revision gets rid of this problem by substituting the simple rule of no-action-no-appointment. So there are multiple reasons to change the language that have nothing to do with a tie.
In sum, it's an interesting and worthwhile argument, but I think it fails to overcome the simple text. Article I, Section 3 says that the Vice President, as President of the Senate, "shall have no Vote, unless they [the Senators] be equally divided." It does not say that the Vice President has this voting power only as to Article I matters. Rather, the Vice President has this voting power whenever the Senators are equally divided. Article I, Section 3 is about how the Senate operates -- not just as to powers in Article I, but generally. Professor Tribe's contrary arguments aren't nothing (from an originalist perspective), but they aren't enough.
ANDREW HYMAN ADDS: Remember that (1) back in those days, the Vice-President was merely the second place finisher in the presidential election so the VP often failed to support the President, and (2) a nomination or any other measure has always failed in the Senate if the vote is tied and is not broken by the casting vote of the Vice-President. So Hamilton was right that if the Senate is equally divided, then no appointment can be made, and if the Vice President (as president of the Senate) votes then the Senate is no longer equally divided. Hamilton was making the point that the President of the U.S. had less power in this regard than the Governor of New York, and Hamilton was right about that too. At the time, the council that appointed judges in New York consisted of the Governor and four state senators, and if the state senators were equally divided then the Governor could break the tie; in contrast, the President cannot break a Senate tie or force the Vice-President to break a Senate tie.


Correctly resourcing your business with employees is an important issue for all businesses. Having the right number of staff with the right employment status allows existing businesses to meet demand and growing businesses to take on more work. There are significant costs associated with employing staff, so getting the balance right between meeting customer demand and staff utilisation is vital. One of the most important aspects to consider when hiring staff is the different employment statuses that exist, and being aware of your responsibilities as an employer.
Staff can be employed under a number of categories. Some categories offer more flexibility for workers, while others provide more security for the business. Ideally, when looking to employ you would choose an employment structure for each staff member that suits both the business and the employee. There are four main employment statuses to choose from and each one comes with their own set of obligations for you and your staff: Permanent Full Time, Permanent Part Time, Casual and Temporary.
Full-Time Employees work 38 hours per week: which is 7.6 hours per day, 5 days a week. They are entitled to Annual Leave, Personal Leave, Public Holidays, Parental Leave, Long Service Leave, Superannuation Guarantee and a period of notice if their job is terminated.
Permanent Part-Time Employees work less than 38 hours per week but these are usually set hours and/or days. They are eligible to the same entitlements as permanent full-time employees (above), but just proportionally less based on time accrued in the job.
Casual Employee's work hours may vary each week, depending on the work available, and are not guaranteed. They are paid for the hours worked and receive a loading (usually 25%) to compensate them for not receiving the same benefits as full or part time workers. Casuals can be entitled to penalty rates, loadings and allowances.
Temporary Employees are engaged for a specific period of time either a fixed term contract or to work on a particular project with an end date. Employees are also considered temporary if they are engaged via an agency or replace permanent employees who may have taken long service, parental or some other leave. Temporary employees are eligible for entitlements depending on whether they are employed on a full time, part time or casual basis.
It's important to distinguish if your workers are employees or independent contractors. If they are employees, then their employment status and your obligations as an employer is one of the most important things to consider when deciding on how to manage your human resources. Contractors can also be deemed employees with regard to superannuation and workers' compensation, so it's important to understand the parameters. The ATO offers a handy resource to work this out.
For more specific information related to your industry and employees, please refer to your specific industry award or the Fairwork website.


LOGAN, Ohio - An alleged illegal casino was closed in Hocking County Friday.
Agents with the Ohio Attorney General's Office served a search warrant at the Red Door Casino at 44 E. Main St. in Logan Friday afternoon.
Agents removed gaming machines from the business.
"The people that do go in there and gamble it's nothing major maybe $5 here, $10 dollars there," said Logan Resident Jacob Keister looking on.
The search warrant was served as part of an ongoing investigation regarding allegations of illegal gambling at the location.
The owner claims the raid isn't your typical raid on a suspected illegal gambling joint.
"This is in retaliation for operating as a tribal people," said Marshall Lucas who goes by the name Dancing Elk. He tells NBC4's Denise Alex that he is a member of the Notweega nation.
That's where the raid, where computers, televisions, gaming machines and cash that were seized, gets more interesting.
Ohio BCI agents and member of the Ohio Investigative Unit spent about 4 hours seizing items from the Red Door on East Main Street in downtown Logan. The business owner says he is being unfairly targeted because he's a member of the sovereign nation.
"They have no right to enter our property. This is sovereign property. We are non-reservation Indians. We are operating a sovereign business," added Dancing Elk.
He says the Notweega nation is a Native American tribe that governs itself.
Ohio BCI agents say the Logan native is breaking the law.
"There's several different variables that actually makes it illegal but some of the cash pay outs and some of the things they were doing, allegedly going on are suspected at this establishment," said Special Agent Supervisor Scott Fitch.
Tribal members say they are misunderstood.
"Insult to injury would be the best to describe the scenario right now," said Karmelita Plains Bull.
"They are stealing our property, the are destroying our property. We've been dealing with this for over 5 years now," said Dancing Elk.
Dancing Elk took NBC4's Denise Alex inside the Red Door after police cleared the scene.
Newspaper articles taped to the wall tell the Red Door's battle to stay open for business.
Dancing Elk claims to be harassed for years by many Logan city leaders and has $20 million dollar lawsuit against them pending in federal court.
No arrests were made in Friday's raid, but officials said charitable law prosecutors with the Ohio Attorney General's Office will decide on charges.


Cabins | The cottage has two bedrooms. One with a double and one with 4 beds. Full bathroom with shower. Livingroom and kitchen all together. TV with cable TV connection.
Refrigerator / freezer, stove / oven, dishwasher, microwave and sink with hot water. Coffee maker and kettle. Kitchenware for 8 people. Bathroom with toilet and shower. Patio with garden furniture. Pets are not allowed.


text:
How do you identify the intercepts on a linear graph?
Algebra Graphs of Linear Equations and Functions Intercepts by Substitution
An intercept is a point of intersection (a point where a line crosses another line)- Typically, in terms of linear graphs, finding #x# and #y# intercepts are asked, or the intercepts of line with another line.
Let's look at #x# and #y# intercepts. We can consider the #x#-axis as a line, and the #y#-axis as a line. A line can only intersect another line in one point, so there will be one #x#-intercept, and one #y#-intercept for a linear graph. Note that an intercept is a point in the form of (#x,y#)
-To find an #x# intercept, we have to find the point where the line intersects the #x#-axis. To do this, we set #y#=0 and solve the equation for #x#. This makes sense because when y=0, we can only move in the #x#-direction...hence finding the exact value of #x# when #y# is zero.
-To find a #y# intercept, we have to find the point where the line intersects the #y#-axis. To do this, this time we set x=0 and solve the equation for the remaining #y#. This makes sense because when x=0, we can only move in the y-direction, and then find the point where the line crosses that y-axis.
After that we end up with an #x#-intercept in the form of (#x,0#) and a #y#-intercept in the form of (#0,y#).
To find where a line intersects another line, you can solve both equations for #y# (or #x#) and then set them equal to each other. When you set them equal to each other, you end up with one unknown, which you can solve for with some algebra. When you get that unknown, you can plug it into one of the original equations to the other unknown.
Alternatively, we could always graph the line(s) and observe the points of intersection.
For example, to see where the line #y=2x+4 # intersects the axes, you can just look at the graph. You'll see that it intersects the #x#-axis in the point (-2,0) and the #y#-axis in the point (0,4).
graph{2x+4 [-10, 10, -5, 5]}
Notice that if you wanted to find this algebraically, you would set the #y=0# and solve for #x# to find #x=-2# as an intercept, and then set #x=0# and find #y=4# as another.
What is the x and y Intercepts?
How many intercepts can a line have?
How do you use substitution to find intercepts?
How do you use the x and y intercepts to graph a linear equation?
How do you find the x and y intercept for #y=2x+3#?
How do you find the x intercept for #y=2#?
What is the y intercept for the #y=2# graph?
What is the y intercept for #x=-1#?
How do you find the intercepts of #x^2y-x^2+4y=0#?
How do you find the x-intercept of the line #6x + 2y = 24#?
See all questions in Intercepts by Substitution


text:
Ruperto Kangleon (Macrohon, 27 maart 1890 - 27 februari 1958) was een Filipijns militair en politicus.

Biografie
Ruperto Kangleon werd geboren in barangay San Roque in de gemeente Macrohon in de Southern Leyte. Hij was het tweede kind uit een gezin van zes van Braulio Kangleon en Flora Kadaba. Tijdens de Tweede Wereldoorlog was hij guerrillaleider op Leyte. Na het voltooien van de Cebu High School studeerde hij aan het College of Liberal Arts van de University of the Philippines in Manilla. Na enige tijd switchte hij echter naar de Philippine Constabulary Academy in Baguio, de voorloper van de Philippine Military Academy. Na het behalen van zijn diploma in 1916 diende hij als officier op het platteland onveilig maakten, waar bandieten in die dagen de omgeving onveilig maakten.

In de Tweede Wereldoorlog speelde zijn guerrillagroepering een belangrijke rol voorafgaand aan de landing van de Amerikaanse troepen onder leiding van generaal Douglas MacArthur op het strand van Palo op 20 oktober 1944. Voor zijn rol bij de verovering van Leyte kreeg Kangleon van MacArthur de Distinguished Service Cross uitgereikt en werd hij bevorderd tot kolonel. Na de oorlog werd hij door de nieuwe regering onder leiding van Sergio Osmeña benoemd tot gouverneur van Leyte. Na het verkrijgen van de onafhankelijkheid in 1946 werd Kangleon benoemd tot Ministerie van Defensie in het kabinet van president Manuel Roxas. Ook in de beginperiode van diens opvolger Elpidio Quirino bleef hij minister tot hij in augustus 1950 werd opgevolgd door een andere oud-guerrillaleider Ramon Magsaysay. Bij de verkiezingen van 1953 werd Kangleon gekozen in de Filipijnse Senaat. In de Senaat zette hij zich in voor de belangen van Filipijnse veteranen.

Bronnen
 , Historical dictionary of the Philippines, 3e editie, The Scarecrow Press, Inc. (2012)
 Biografie Ruperto Kangleon, website Filipijns Ministerie van Defensie

Filipijns militair
Filipijns minister
Filipijns senator

redpajama_set_name: RedPajamaWikipedia


Looking back at the past is indeed important. We can't help but notice that no matter how many times we look back, the taxi industry is still slowly dying.
But how many of us are really fond of those smelly public taxis and extortionate fares for the privileged? Well, it was only a matter of time until something new came up with a better option.
Private hire cars are indeed making a scene in the modern transportation system. If you are still unfamiliar with its mechanics, just imagine having a friend who drops everything to come and pick you up and drop you off at any time.
Perhaps the biggest difference between taxis and private hired cars is the rating system. Riders are able to send in their overall rating about their ride directly through the agency.
For users, the rating systems is often a relief so you can easily send comments for better services.
It's no secret that taxis have been slowly destroying its own reputation with various cases of misdemeanours and lack of driving ethics.
Overall, private hired cars are considered to be the safer option, with drivers easier to track, identify and contact. If you are planning on taking a long trip, it is best to consider the private hired car option.
The rating system also helps ensure cleaner vehicles. If you were to find yourself in an untidy and ill-kept taxi, the best you could do is take down the plate and driver number, call the company and file a report.
United Radio Cars offers a comprehensive range of services, including private cars for hire and airport transfers in Swindon. We take pride in countless satisfied and repeat customers who swear by our staff's professionalism and excellent level of service.
United Radio Cars are a local, professional and dedicated Private Hire company who strive to offer excellent service and fair pricing to it's customers.