<commit_before>/* jshint node: true */
'use strict';

var zdoHelper = require('./zdo_helper.js'),
    debug = require('debug')('zigbee-shepherd:event_bridge')

var bridge = {};

// Bridge functions for ZDO, SAPI, NWK
// Do nothing. No need to bridge: SYS, MAC, NWK, UTIL, DBG, APP
var subsysAreqBridge = { ZDO: zdoIndicationEventBridge, SAPI: sapiIndicationEventBridge, NWK: nwkIndicationEventBridge }

bridge.areqEventBridge = function (controller, msg) {
    // msg: { subsys: 'ZDO', ind: 'endDeviceAnnceInd', data: { srcaddr: 63536, nwkaddr: 63536, ieeeaddr: '0x00124b0001ce3631', ... }
    var mandatoryEvent = msg.subsys + ':' + msg.ind;    // 'SYS:resetInd', 'SYS:osalTimerExpired'

    controller.emit(mandatoryEvent, msg.data);          // bridge to subsystem events, like 'SYS:resetInd', 'SYS:osalTimerExpired'

    if (msg.subsys === 'AF')
        debug('IND <-- %s, transId: %d', mandatoryEvent, msg.data.transid || msg.data.transseqnumber);
    else
        debug('IND <-- %s', mandatoryEvent);

    // dispatch to specific event bridge
    var dispatchTo = subsysAreqBridge[msg.subsys]
    if(dispatchTo) dispatchTo(controller, msg)
};

function zdoIndicationEventBridge (controller, msg) {
    var payload = msg.data,
        zdoEventHead = 'ZDO:' + msg.ind,
        zdoBridgedEvent;

    if (msg.ind === 'stateChangeInd') {    // this is a special event
        if (!payload.hasOwnProperty('nwkaddr'))    // Coord itself
            zdoBridgedEvent = 'coordStateInd';
        else if (payload.state === 0x83 || payload.state === 'NOT_ACTIVE')
            zdoBridgedEvent = zdoEventHead + ':' + payload.nwkaddr + ':NOT_ACTIVE';
        else if (payload.state === 0x82 || payload.state === 'INVALID_EP')
            zdoBridgedEvent = zdoEventHead + ':' + payload.nwkaddr + ':INVALID_EP';
    } else {
        zdoBridgedEvent = zdoHelper.generateEventOfIndication(msg.ind, payload);
    }

    if (zdoBridgedEvent)
        controller.emit(zdoBridgedEvent, payload);
};

function sapiIndicationEventBridge (controller, msg) {
    var payload = msg.data,
        sapiEventHead = 'SAPI:' + msg.ind,
        sapiBridgedEvent;

    switch (msg.ind) {
        case 'bindConfirm':
            sapiBridgedEvent = sapiEventHead + ':' + payload.commandid;
            break;
        case 'sendDataConfirm':
            sapiBridgedEvent = sapiEventHead + ':' + payload.handle;
            break;
        case 'receiveDataIndication':
            sapiBridgedEvent = sapiEventHead + ':' + payload.source + ':' + payload.command;
            break;
        case 'findDeviceConfirm':
            if (payload.hasOwnProperty('result'))
                sapiBridgedEvent = sapiEventHead + ':' + payload.result;
            break;
        // startConfirm and allowBindConfirm need no bridging
    }

    if (sapiBridgedEvent)
        controller.emit(sapiBridgedEvent, payload);
}

function nwkIndicationEventBridge (controller, msg) {
    if (msg.ind == "pollInd") {
        controller.emit('NWK:' + msg.ind, msg.data);
    }
}

module.exports = bridge;
<commit_msg>shorter log name<commit_after>/* jshint node: true */
'use strict';

var zdoHelper = require('./zdo_helper.js'),
    debug = require('debug')('zigbee-shepherd:bridge')

var bridge = {};

// Bridge functions for ZDO, SAPI, NWK
// Do nothing. No need to bridge: SYS, MAC, NWK, UTIL, DBG, APP
var subsysAreqBridge = { ZDO: zdoIndicationEventBridge, SAPI: sapiIndicationEventBridge, NWK: nwkIndicationEventBridge }

bridge.areqEventBridge = function (controller, msg) {
    // msg: { subsys: 'ZDO', ind: 'endDeviceAnnceInd', data: { srcaddr: 63536, nwkaddr: 63536, ieeeaddr: '0x00124b0001ce3631', ... }
    var mandatoryEvent = msg.subsys + ':' + msg.ind;    // 'SYS:resetInd', 'SYS:osalTimerExpired'

    controller.emit(mandatoryEvent, msg.data);          // bridge to subsystem events, like 'SYS:resetInd', 'SYS:osalTimerExpired'

    if (msg.subsys === 'AF')
        debug('IND <-- %s, transId: %d', mandatoryEvent, msg.data.transid || msg.data.transseqnumber);
    else
        debug('IND <-- %s', mandatoryEvent);

    // dispatch to specific event bridge
    var dispatchTo = subsysAreqBridge[msg.subsys]
    if(dispatchTo) dispatchTo(controller, msg)
};

function zdoIndicationEventBridge (controller, msg) {
    var payload = msg.data,
        zdoEventHead = 'ZDO:' + msg.ind,
        zdoBridgedEvent;

    if (msg.ind === 'stateChangeInd') {    // this is a special event
        if (!payload.hasOwnProperty('nwkaddr'))    // Coord itself
            zdoBridgedEvent = 'coordStateInd';
        else if (payload.state === 0x83 || payload.state === 'NOT_ACTIVE')
            zdoBridgedEvent = zdoEventHead + ':' + payload.nwkaddr + ':NOT_ACTIVE';
        else if (payload.state === 0x82 || payload.state === 'INVALID_EP')
            zdoBridgedEvent = zdoEventHead + ':' + payload.nwkaddr + ':INVALID_EP';
    } else {
        zdoBridgedEvent = zdoHelper.generateEventOfIndication(msg.ind, payload);
    }

    if (zdoBridgedEvent)
        controller.emit(zdoBridgedEvent, payload);
};

function sapiIndicationEventBridge (controller, msg) {
    var payload = msg.data,
        sapiEventHead = 'SAPI:' + msg.ind,
        sapiBridgedEvent;

    switch (msg.ind) {
        case 'bindConfirm':
            sapiBridgedEvent = sapiEventHead + ':' + payload.commandid;
            break;
        case 'sendDataConfirm':
            sapiBridgedEvent = sapiEventHead + ':' + payload.handle;
            break;
        case 'receiveDataIndication':
            sapiBridgedEvent = sapiEventHead + ':' + payload.source + ':' + payload.command;
            break;
        case 'findDeviceConfirm':
            if (payload.hasOwnProperty('result'))
                sapiBridgedEvent = sapiEventHead + ':' + payload.result;
            break;
        // startConfirm and allowBindConfirm need no bridging
    }

    if (sapiBridgedEvent)
        controller.emit(sapiBridgedEvent, payload);
}

function nwkIndicationEventBridge (controller, msg) {
    if (msg.ind == "pollInd") {
        controller.emit('NWK:' + msg.ind, msg.data);
    }
}

module.exports = bridge;
<|endoftext|>


<commit_before>'use strict';

var Utils = require('../../utils')
  , AbstractQuery = require('../abstract/query')
  , DataTypes = require('../../data-types')
  , hstore = require('./hstore')
  , range = require('./range')
  , QueryTypes = require('../../query-types')
  , Promise = require('../../promise')
  , sequelizeErrors = require('../../errors.js');

// Parses hstore fields if the model has any hstore fields.
// This cannot be done in the 'pg' lib because hstore is a UDT.
var parseHstoreFields = function(model, row) {
  Utils._.forEach(row, function(value, key) {
    if(value === null) return row[key] = null;

    if (model._isHstoreAttribute(key)) {
      row[key] = hstore.parse(value);
    }else if (model.attributes[key] && DataTypes.ARRAY.is(model.attributes[key].type, DataTypes.HSTORE)) {
      var array = JSON.parse('[' + value.slice(1).slice(0,-1) + ']');
      row[key] = Utils._.map(array, function(v){return hstore.parse(v);});
    }else{
      row[key] = value;
    }
  });
};

var parseRangeFields = function (model, row) {
  Utils._.forEach(row, function (value, key) {
    if (value === null) return row[key] = null;

    if (model._isRangeAttribute(key)) {
      row[key] = range.parse(value, model.attributes[key].type);
    } else if (model.attributes[key] && DataTypes.ARRAY.is(model.attributes[key].type, DataTypes.RANGE)) {
      var array = JSON.parse('[' + value.slice(1).slice(0, -1) + ']');
      row[key] = Utils._.map(array, function (v) { return range.parse(v, model.attributes[key].type.type); });
    } else {
      row[key] = value;
    }
  });
};

module.exports = (function() {
  var Query = function(client, sequelize, callee, options) {
    this.client = client;
    this.sequelize = sequelize;
    this.callee = callee;
    this.options = Utils._.extend({
      logging: console.log,
      plain: false,
      raw: false
    }, options || {});

    this.checkLoggingOption();
  };
  Utils.inherit(Query, AbstractQuery);

  Query.prototype.run = function(sql) {
    /* jshint -W027 */
    this.sql = sql;

    var self = this
      , receivedError = false
      , query = this.client.query(sql)
      , rows = [];

    this.sequelize.log('Executing (' + (this.client.uuid || 'default') + '): ' + this.sql, this.options);

    var promise = new Promise(function(resolve, reject) {
      query.on('row', function(row) {
        rows.push(row);
      });

      query.on('error', function(err) {
        receivedError = true;
        err.sql = sql;
        promise.emit('sql', sql, self.client.uuid);
        reject(self.formatError(err));
      });

      query.on('end', function(result) {
        if (receivedError) {
          return;
        }

        promise.emit('sql', self.sql, self.client.uuid);
        resolve([rows, sql, result]);
      });
    }).spread(function(rows, sql, result) {
      var results = rows
        , isTableNameQuery = (sql.indexOf('SELECT table_name FROM information_schema.tables') === 0)
        , isRelNameQuery = (sql.indexOf('SELECT relname FROM pg_class WHERE oid IN') === 0);

      if (isTableNameQuery || isRelNameQuery) {
        if (isRelNameQuery) {
          results = rows.map(function(row) {
            return {
              name: row.relname,
              tableName: row.relname.split('_')[0]
            };
          });
        } else {
          results = rows.map(function(row) { return Utils._.values(row); });
        }
        return results;
      }

      if (rows[0] && rows[0].sequelize_caught_exception) {
        throw new self.formatError({
          code: '23505',
          detail: rows[0].sequelize_caught_exception
        });
      }

      if (self.isShowIndexesQuery()) {
        results.forEach(function (result) {
          var attributes = /ON .*? (?:USING .*?\s)?\((.*)\)/gi.exec(result.definition)[1].split(',')
            , field
            , attribute
            , columns;

          // Map column index in table to column name
          columns = Utils._.zipObject(
            result.column_indexes,
            self.sequelize.queryInterface.QueryGenerator.fromArray(result.column_names)
          );
          delete result.column_indexes;
          delete result.column_names;

          // Indkey is the order of attributes in the index, specified by a string of attribute indexes
          result.fields = result.indkey.split(' ').map(function (indKey, index) {
            field = columns[indKey];
            attribute = attributes[index];
            return {
              attribute: field,
              collate: attribute.match(/COLLATE "(.*?)"/) ? /COLLATE "(.*?)"/.exec(attribute)[1] : undefined,
              order: attribute.indexOf('DESC') !== -1 ? 'DESC' : attribute.indexOf('ASC') !== -1 ? 'ASC': undefined,
              length: undefined
            };
          });
          delete result.columns;
        });
        return results;
      } else if (self.isForeignKeysQuery()) {
        result = [];
        rows.forEach(function(row) {
          var defParts;
          if (row.condef !== undefined && (defParts = row.condef.match(/FOREIGN KEY \((.+)\) REFERENCES (.+)\((.+)\)( ON (UPDATE|DELETE) (CASCADE|RESTRICT))?( ON (UPDATE|DELETE) (CASCADE|RESTRICT))?/))) {
            row.id = row.constraint_name;
            row.table = defParts[2];
            row.from = defParts[1];
            row.to = defParts[3];
            var i;
            for (i=5;i<=8;i+=3) {
              if (/(UPDATE|DELETE)/.test(defParts[i])) {
                row['on_'+defParts[i].toLowerCase()] = defParts[i+1];
              }
            }
          }
          result.push(row);
        });
        return result;
      } else if (self.isSelectQuery()) {
        // Postgres will treat tables as case-insensitive, so fix the case
        // of the returned values to match attributes
        if (self.options.raw === false && self.sequelize.options.quoteIdentifiers === false) {
          var attrsMap = Utils._.reduce(self.callee.attributes, function(m, v, k) { m[k.toLowerCase()] = k; return m; }, {});
          rows.forEach(function(row) {
            Utils._.keys(row).forEach(function(key) {
              var targetAttr = attrsMap[key];
              if (targetAttr !== key) {
                row[targetAttr] = row[key];
                delete row[key];
              }
            });
          });
        }

        if (!!self.callee && !!self.callee._hasHstoreAttributes) {
          rows.forEach(function(row) {
            parseHstoreFields(self.callee, row);
          });
        }

        if (!!self.callee && !!self.callee._hasRangeAttributes) {
          rows.forEach(function (row) {
            parseRangeFields(self.callee, row);
          });
        }

        return self.handleSelectQuery(rows);
      } else if (QueryTypes.DESCRIBE === self.options.type) {
        result = {};

        rows.forEach(function(_result) {
          result[_result.Field] = {
            type: _result.Type.toUpperCase(),
            allowNull: (_result.Null === 'YES'),
            defaultValue: _result.Default,
            special: (!!_result.special ? self.sequelize.queryInterface.QueryGenerator.fromArray(_result.special) : [])
          };

          if (result[_result.Field].type === 'BOOLEAN') {
            result[_result.Field].defaultValue = { 'false': false, 'true': true }[result[_result.Field].defaultValue];

            if (result[_result.Field].defaultValue === undefined) {
              result[_result.Field].defaultValue = null;
            }
          }

          if (typeof result[_result.Field].defaultValue === 'string') {
            result[_result.Field].defaultValue = result[_result.Field].defaultValue.replace(/'/g, '');

            if (result[_result.Field].defaultValue.indexOf('::') > -1) {
              var split = result[_result.Field].defaultValue.split('::');
              if (split[1].toLowerCase() !== 'regclass)') {
                result[_result.Field].defaultValue = split[0];
              }
            }
          }
        });

        return result;
      } else if (self.isShowOrDescribeQuery()) {
        return results;
      } else if (QueryTypes.BULKUPDATE === self.options.type) {
        if (!self.options.returning) {
          return parseInt(result.rowCount, 10);
        }

        if (!!self.callee && !!self.callee._hasHstoreAttributes) {
          rows.forEach(function(row) {
            parseHstoreFields(self.callee, row);
          });
        }

        if (!!self.callee && !!self.callee._hasRangeAttributes) {
          rows.forEach(function (row) {
            parseRangeFields(self.callee, row);
          });
        }

        return self.handleSelectQuery(rows);
      } else if (QueryTypes.BULKDELETE === self.options.type) {
        return parseInt(result.rowCount, 10);
      } else if (self.isUpsertQuery()) {
        return rows[0].sequelize_upsert;
      } else if (self.isInsertQuery() || self.isUpdateQuery()) {
        if (!!self.callee && self.callee.dataValues) {
          if (!!self.callee.Model && !!self.callee.Model._hasHstoreAttributes) {
            parseHstoreFields(self.callee.Model, rows[0]);
          }

          if (!!self.callee.Model && !!self.callee.Model._hasRangeAttributes) {
            parseRangeFields(self.callee.Model, rows[0]);
          }

          for (var key in rows[0]) {
            if (rows[0].hasOwnProperty(key)) {
              var record = rows[0][key];

              var attr = Utils._.find(self.callee.Model.rawAttributes, function (attribute) {
                return attribute.fieldName === key || attribute.field === key;
              });

              self.callee.dataValues[attr && attr.fieldName || key] = record;
            }
          }
        }

        return self.callee || (rows && ((self.options.plain && rows[0]) || rows)) || undefined;
      } else if (self.isVersionQuery()) {
        return results[0].version;
      } else if (self.isRawQuery()) {
        return [rows, result];
      } else {
        return results;
      }
    });

    return promise;
  };

  Query.prototype.formatError = function (err) {
    var match
      , table
      , index
      , fields
      , errors
      , message;

    var code = err.code || err.sqlState
      , errMessage = err.message || err.messagePrimary
      , errDetail = err.detail || err.messageDetail;

    switch (code) {
      case '23503':
        index = errMessage.match(/violates foreign key constraint \"(.+?)\"/)[1];
        table = errMessage.match(/on table \"(.+?)\"/)[1];

        return new sequelizeErrors.ForeignKeyConstraintError({
          fields: null,
          index: index,
          table: table,
          parent: err
        });
      case '23505':
        // there are multiple different formats of error messages for this error code
        // this regex should check at least two
        match = errDetail.match(/Key \((.*?)\)=\((.*?)\)/);

        if (match) {
          fields = Utils._.zipObject(match[1].split(', '), match[2].split(', '));
          errors = [];
          message = 'Validation error';

          Utils._.forOwn(fields, function(value, field) {
            errors.push(new sequelizeErrors.ValidationErrorItem(
              field + ' must be unique', 'unique violation', field, value));
          });

          if (this.callee && this.callee.__options && this.callee.__options.uniqueKeys) {
            Utils._.forOwn(this.callee.__options.uniqueKeys, function(constraint) {
              if (Utils._.isEqual(constraint.fields, Object.keys(fields)) && !!constraint.msg) {
                message = constraint.msg;
                return false;
              }
            });
          }

          return new sequelizeErrors.UniqueConstraintError({
            message: message,
            errors: errors,
            parent: err,
            fields: fields
          });
        } else {
          return new sequelizeErrors.UniqueConstraintError({
            message: errMessage,
            parent: err
          });
        }

        break;
      case '23P01':
        match = errDetail.match(/Key \((.*?)\)=\((.*?)\)/);

        fields = Utils._.zipObject(match[1].split(', '), match[2].split(', '));
        message = 'Exclusion constraint error';

        return new sequelizeErrors.ExclusionConstraintError({
          message: message,
          constraint: err.constraint,
          fields: fields,
          table: err.table,
          parent: err
        });

      default:
        return new sequelizeErrors.DatabaseError(err);
    }
  };

  Query.prototype.isForeignKeysQuery = function() {
    return /SELECT conname as constraint_name, pg_catalog\.pg_get_constraintdef\(r\.oid, true\) as condef FROM pg_catalog\.pg_constraint r WHERE r\.conrelid = \(SELECT oid FROM pg_class WHERE relname = '.*' LIMIT 1\) AND r\.contype = 'f' ORDER BY 1;/.test(this.sql);
  };

  Query.prototype.getInsertIdField = function() {
    return 'id';
  };

  return Query;
})();
<commit_msg>Proper parsing of HSTORE and RANGE attributes in included models<commit_after>'use strict';

var Utils = require('../../utils')
  , AbstractQuery = require('../abstract/query')
  , DataTypes = require('../../data-types')
  , hstore = require('./hstore')
  , range = require('./range')
  , QueryTypes = require('../../query-types')
  , Promise = require('../../promise')
  , sequelizeErrors = require('../../errors.js');

var parseDialectSpecificFields = {
      // Parses hstore fields if the model has any hstore fields.
      // This cannot be done in the 'pg' lib because hstore is a UDT.
      hstore: function (value, options) {
        if (value === null) return null;

        return DataTypes.ARRAY.is(options.dataType, DataTypes.HSTORE) ?
          Utils._.map(
            JSON.parse('[' + value.substring(1, value.length - 1) + ']'), function (v) {
              return hstore.parse(v);
            }) : hstore.parse(value);
      },
      range:  function (value, options) {
        if (value === null) return null;

        return DataTypes.ARRAY.is(options.dataType, DataTypes.RANGE) ?
          Utils._.map(
            JSON.parse('[' + value.substring(1, value.length - 1) + ']'),
            function (v) {
              return range.parse(v, options.dataType.type);
            }) :
          range.parse(value, options.dataType);
      }
    },
    dialectSpecificTypes  = Utils._.keys(parseDialectSpecificFields);

function dialectSpecificFieldDatatypeMap (options, prefix) {
  if (!Utils._.isArray(options.types))
    return [];

  prefix = prefix || '';

  var fields = {};
  if (options.callee) {
    if (options.as)
      prefix += options.as + '.';

    Utils._.each(options.types, function (type) {
      Utils._.each(options.callee['_' + type + 'Attributes'], function (attrName) {
        fields[prefix + attrName] = {
          dataType: options.callee.attributes[attrName].type || null,
          type:     type
        };
      });
    });
  }

  Utils._.each(options.include, function (include) {
    fields = Utils._.merge(fields, dialectSpecificFieldDatatypeMap({
      callee:  include.model,
      as:      include.as,
      include: include.include,
      types:   options.types
    }, prefix));
  });

  return fields;
}

module.exports = (function() {
  var Query = function(client, sequelize, callee, options) {
    this.client = client;
    this.sequelize = sequelize;
    this.callee = callee;
    this.options = Utils._.extend({
      logging: console.log,
      plain: false,
      raw: false
    }, options || {});

    this.checkLoggingOption();
  };
  Utils.inherit(Query, AbstractQuery);

  Query.prototype.run = function(sql) {
    /* jshint -W027 */
    this.sql = sql;

    var self = this
      , receivedError = false
      , query = this.client.query(sql)
      , rows = [];

    this.sequelize.log('Executing (' + (this.client.uuid || 'default') + '): ' + this.sql, this.options);

    var promise = new Promise(function(resolve, reject) {
      query.on('row', function(row) {
        rows.push(row);
      });

      query.on('error', function(err) {
        receivedError = true;
        err.sql = sql;
        promise.emit('sql', sql, self.client.uuid);
        reject(self.formatError(err));
      });

      query.on('end', function(result) {
        if (receivedError) {
          return;
        }

        promise.emit('sql', self.sql, self.client.uuid);
        resolve([rows, sql, result]);
      });
    }).spread(function(rows, sql, result) {
      var results = rows
        , isTableNameQuery = (sql.indexOf('SELECT table_name FROM information_schema.tables') === 0)
        , isRelNameQuery = (sql.indexOf('SELECT relname FROM pg_class WHERE oid IN') === 0)
        , dialectSpecificFields
        , isDialectSpecificField = Utils._.memoize(function (key) { return dialectSpecificFields.hasOwnProperty(key); });

      if (isTableNameQuery || isRelNameQuery) {
        if (isRelNameQuery) {
          results = rows.map(function(row) {
            return {
              name: row.relname,
              tableName: row.relname.split('_')[0]
            };
          });
        } else {
          results = rows.map(function(row) { return Utils._.values(row); });
        }
        return results;
      }

      if (rows[0] && rows[0].sequelize_caught_exception) {
        throw new self.formatError({
          code: '23505',
          detail: rows[0].sequelize_caught_exception
        });
      }

      if (self.isShowIndexesQuery()) {
        results.forEach(function (result) {
          var attributes = /ON .*? (?:USING .*?\s)?\((.*)\)/gi.exec(result.definition)[1].split(',')
            , field
            , attribute
            , columns;

          // Map column index in table to column name
          columns = Utils._.zipObject(
            result.column_indexes,
            self.sequelize.queryInterface.QueryGenerator.fromArray(result.column_names)
          );
          delete result.column_indexes;
          delete result.column_names;

          // Indkey is the order of attributes in the index, specified by a string of attribute indexes
          result.fields = result.indkey.split(' ').map(function (indKey, index) {
            field = columns[indKey];
            attribute = attributes[index];
            return {
              attribute: field,
              collate: attribute.match(/COLLATE "(.*?)"/) ? /COLLATE "(.*?)"/.exec(attribute)[1] : undefined,
              order: attribute.indexOf('DESC') !== -1 ? 'DESC' : attribute.indexOf('ASC') !== -1 ? 'ASC': undefined,
              length: undefined
            };
          });
          delete result.columns;
        });
        return results;
      } else if (self.isForeignKeysQuery()) {
        result = [];
        rows.forEach(function(row) {
          var defParts;
          if (row.condef !== undefined && (defParts = row.condef.match(/FOREIGN KEY \((.+)\) REFERENCES (.+)\((.+)\)( ON (UPDATE|DELETE) (CASCADE|RESTRICT))?( ON (UPDATE|DELETE) (CASCADE|RESTRICT))?/))) {
            row.id = row.constraint_name;
            row.table = defParts[2];
            row.from = defParts[1];
            row.to = defParts[3];
            var i;
            for (i=5;i<=8;i+=3) {
              if (/(UPDATE|DELETE)/.test(defParts[i])) {
                row['on_'+defParts[i].toLowerCase()] = defParts[i+1];
              }
            }
          }
          result.push(row);
        });
        return result;
      } else if (self.isSelectQuery()) {
        // Postgres will treat tables as case-insensitive, so fix the case
        // of the returned values to match attributes
        if (self.options.raw === false && self.sequelize.options.quoteIdentifiers === false) {
          var attrsMap = Utils._.reduce(self.callee.attributes, function(m, v, k) { m[k.toLowerCase()] = k; return m; }, {});
          rows.forEach(function(row) {
            Utils._.keys(row).forEach(function(key) {
              var targetAttr = attrsMap[key];
              if (targetAttr !== key) {
                row[targetAttr] = row[key];
                delete row[key];
              }
            });
          });
        }

        if (!!self.callee && rows.length > 0) {
          dialectSpecificFields = dialectSpecificFieldDatatypeMap({
            callee:  self.callee,
            include: self.options.include,
            types:   dialectSpecificTypes
          });

          // check whether custom fields exist in responses model
          if (!Utils._.isEmpty(dialectSpecificFields)) {
            rows.forEach(function (row, rowId, rows) {
              Utils._.each(row, function (value, key) {
                if (isDialectSpecificField(key))
                  rows[rowId][key] =
                  parseDialectSpecificFields[dialectSpecificFields[key].type](value, { dataType: dialectSpecificFields[key].dataType });
              });
            });
          }
        }

        return self.handleSelectQuery(rows);
      } else if (QueryTypes.DESCRIBE === self.options.type) {
        result = {};

        rows.forEach(function(_result) {
          result[_result.Field] = {
            type: _result.Type.toUpperCase(),
            allowNull: (_result.Null === 'YES'),
            defaultValue: _result.Default,
            special: (!!_result.special ? self.sequelize.queryInterface.QueryGenerator.fromArray(_result.special) : [])
          };

          if (result[_result.Field].type === 'BOOLEAN') {
            result[_result.Field].defaultValue = { 'false': false, 'true': true }[result[_result.Field].defaultValue];

            if (result[_result.Field].defaultValue === undefined) {
              result[_result.Field].defaultValue = null;
            }
          }

          if (typeof result[_result.Field].defaultValue === 'string') {
            result[_result.Field].defaultValue = result[_result.Field].defaultValue.replace(/'/g, '');

            if (result[_result.Field].defaultValue.indexOf('::') > -1) {
              var split = result[_result.Field].defaultValue.split('::');
              if (split[1].toLowerCase() !== 'regclass)') {
                result[_result.Field].defaultValue = split[0];
              }
            }
          }
        });

        return result;
      } else if (self.isShowOrDescribeQuery()) {
        return results;
      } else if (QueryTypes.BULKUPDATE === self.options.type) {
        if (!self.options.returning) {
          return parseInt(result.rowCount, 10);
        }

        if (!!self.callee && rows.length > 0) {
          dialectSpecificFields = dialectSpecificFieldDatatypeMap({
            callee:  self.callee,
            types:   dialectSpecificTypes
          });

          // check whether custom fields exist in responses model
          if (!Utils._.isEmpty(dialectSpecificFields)) {
            rows.forEach(function (row, rowId, rows) {
              Utils._.each(row, function (value, key) {
                if (isDialectSpecificField(key))
                  rows[rowId][key] =
                  parseDialectSpecificFields[dialectSpecificFields[key].type](value, { dataType: dialectSpecificFields[key].dataType });
              });
            });
          }
        }

        return self.handleSelectQuery(rows);
      } else if (QueryTypes.BULKDELETE === self.options.type) {
        return parseInt(result.rowCount, 10);
      } else if (self.isUpsertQuery()) {
        return rows[0].sequelize_upsert;
      } else if (self.isInsertQuery() || self.isUpdateQuery()) {
        if (!!self.callee && self.callee.dataValues) {
          if (!!self.callee.Model) {
            dialectSpecificFields = dialectSpecificFieldDatatypeMap({
              callee:  self.callee.Model,
              types:   dialectSpecificTypes
            });

            // check whether custom fields exist in responses model
            if (!Utils._.isEmpty(dialectSpecificFields)) {
              Utils._.each(rows[0], function (value, key) {
                if (isDialectSpecificField(key))
                  rows[0][key] =
                  parseDialectSpecificFields[dialectSpecificFields[key].type](value, { dataType: dialectSpecificFields[key].dataType });
              });
            }
          }

          for (var key in rows[0]) {
            if (rows[0].hasOwnProperty(key)) {
              var record = rows[0][key];

              var attr = Utils._.find(self.callee.Model.rawAttributes, function (attribute) {
                return attribute.fieldName === key || attribute.field === key;
              });

              self.callee.dataValues[attr && attr.fieldName || key] = record;
            }
          }
        }

        return self.callee || (rows && ((self.options.plain && rows[0]) || rows)) || undefined;
      } else if (self.isVersionQuery()) {
        return results[0].version;
      } else if (self.isRawQuery()) {
        return [rows, result];
      } else {
        return results;
      }
    });

    return promise;
  };

  Query.prototype.formatError = function (err) {
    var match
      , table
      , index
      , fields
      , errors
      , message;

    var code = err.code || err.sqlState
      , errMessage = err.message || err.messagePrimary
      , errDetail = err.detail || err.messageDetail;

    switch (code) {
      case '23503':
        index = errMessage.match(/violates foreign key constraint \"(.+?)\"/)[1];
        table = errMessage.match(/on table \"(.+?)\"/)[1];

        return new sequelizeErrors.ForeignKeyConstraintError({
          fields: null,
          index: index,
          table: table,
          parent: err
        });
      case '23505':
        // there are multiple different formats of error messages for this error code
        // this regex should check at least two
        match = errDetail.match(/Key \((.*?)\)=\((.*?)\)/);

        if (match) {
          fields = Utils._.zipObject(match[1].split(', '), match[2].split(', '));
          errors = [];
          message = 'Validation error';

          Utils._.forOwn(fields, function(value, field) {
            errors.push(new sequelizeErrors.ValidationErrorItem(
              field + ' must be unique', 'unique violation', field, value));
          });

          if (this.callee && this.callee.__options && this.callee.__options.uniqueKeys) {
            Utils._.forOwn(this.callee.__options.uniqueKeys, function(constraint) {
              if (Utils._.isEqual(constraint.fields, Object.keys(fields)) && !!constraint.msg) {
                message = constraint.msg;
                return false;
              }
            });
          }

          return new sequelizeErrors.UniqueConstraintError({
            message: message,
            errors: errors,
            parent: err,
            fields: fields
          });
        } else {
          return new sequelizeErrors.UniqueConstraintError({
            message: errMessage,
            parent: err
          });
        }

        break;
      case '23P01':
        match = errDetail.match(/Key \((.*?)\)=\((.*?)\)/);

        fields = Utils._.zipObject(match[1].split(', '), match[2].split(', '));
        message = 'Exclusion constraint error';

        return new sequelizeErrors.ExclusionConstraintError({
          message: message,
          constraint: err.constraint,
          fields: fields,
          table: err.table,
          parent: err
        });

      default:
        return new sequelizeErrors.DatabaseError(err);
    }
  };

  Query.prototype.isForeignKeysQuery = function() {
    return /SELECT conname as constraint_name, pg_catalog\.pg_get_constraintdef\(r\.oid, true\) as condef FROM pg_catalog\.pg_constraint r WHERE r\.conrelid = \(SELECT oid FROM pg_class WHERE relname = '.*' LIMIT 1\) AND r\.contype = 'f' ORDER BY 1;/.test(this.sql);
  };

  Query.prototype.getInsertIdField = function() {
    return 'id';
  };

  return Query;
})();
<|endoftext|>


<commit_before>var global = (typeof window !== 'undefined') ? window : {},
    Ember = global.Ember;

// Need to track
// 1) channel object
// 2) event bindings which consist of
//    - handler
//    - event name
//    - a unique string representing the target
//
//  bindings: {
//    'channel-one': {
//      channel: Pusher.Channel,
//      eventBindings: {
//        Ember.Route.toString(): [
//          { handler: Function, eventName: String },
//          { handler: Function, eventName: String }
//        ]
//      }
//    }
//  }
//
//  wire(target, channelName, events)
//  ================
//  Initialize object in bindings if it's empty, with eventBindings: {}
//  If eventBindings.length for the current target is 0
//    connect to the channel
//    store channel in the hash
//  For each event in events
//    bind the channel to the eventName
//    store the handler and eventName in the eventBindings array for this channel and controller
//    the key for storing is in target._pusherTargetId()
//    (we store the eventName for when we might want to programmatically unwire)
//
//
//  unwire(route):
//  =================
//  get the channel object
//  for each  handler, eventName in eventBindings for the current route
//    call channel.unbind(eventName, handler)
//  delete the routes record in EventBindings
//  if eventBindings for this channel is empty
//    unsubscribe from the channel
//    delete the channel from bindings

var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

var Controller = Ember.Controller.extend({

  connection: null,
  isDisconnected: true,
  isConnected: Ember.computed.not('isDisconnected'),

  init: function() {
    this._super();
    this.set('bindings', {});
  },

  // Called by the application initializer
  didCreatePusher: function(pusher) {
    this.set('connection', pusher);
    pusher.connection.bind('connected',     __bind(this._didConnect,    this));
    pusher.connection.bind('disconnected',  __bind(this._didDisconnect, this));
    pusher.connection.bind('unavailable',   __bind(this._didDisconnect, this));
  },

  // @events a hash in the form { channel-name: ['event1', 'event2'] }
  // @target any object that responds to send() and _pusherEventsId()
  wire: function(target, channelName, events) {
    var channel = this.connectChannel(channelName),
        bindings = this.get('bindings'),
        targetId = target._pusherEventsId();

    // Setup the eventBindings array for this target
    if(!bindings[channelName].eventBindings[targetId])
      bindings[channelName].eventBindings[targetId] = [];

    // Iterate over the events and bind them
    events.forEach(function(eventName) {
      var normalizedEventName = Ember.String.camelize(eventName), handler;
      handler = function(data) {
        if(target.get('logPusherEvents')) {
          console.log(target.constructor.toString() +
            ": Pusher event received", eventName, data);
        }
        target.send(Ember.String.camelize(eventName), data);
      };
      channel.bind(eventName, handler);
      bindings[channelName].eventBindings[targetId].pushObject({
        handler: handler,
        eventName: eventName
      });
    });
  },

  connectChannel: function(channelName) {
    var pusher = this.get('connection'),
        bindings = this.get('bindings');
    if(!bindings[channelName]) {
      bindings[channelName] = { eventBindings: {} };
    }
    if(Ember.isEmpty(Object.keys(bindings[channelName].eventBindings))) {
      bindings[channelName].channel = pusher.subscribe(channelName);

      // Spit out a bunch of logging if asked
      if(this.namespace.PUSHER_OPTS.logAllEvents) {
        bindings[channelName].channel.bind_all(function(eventName, data) {
          console.log("Pusher event received", eventName, data);
        });
      }
    }
    return bindings[channelName].channel;
  },

  unwire: function(target, channelName) {
    var pusher = this.get('connection'),
        bindings = this.get('bindings'),
        targetId = target._pusherEventsId(),
        channel = bindings[channelName].channel;

    // Unbind all the events for this target
    for(var binding in bindings[channelName].eventBindings[targetId]) {
      channel.unbind(binding.eventName, binding.handler);
    }
    delete bindings[channelName].eventBindings[targetId];

    // Unsubscribe from the channel if this is the last thing listening
    if(bindings[channelName].eventBindings.length === 0) {
      pusher.unsubscribe(channelName);
      delete bindings[channelName];
      return true;
    }
    return false;
  },

  channelFor: function(channelName) {
    return this.get('bindings')[channelName].channel;
  },

  socketId: function() {
    try {
      return this.get('connection').connection.socket_id;
    }
    catch(error) {
      console.warn(error);
    }
  }.property('isDisconnected'),

  _didConnect: function() {
    this.set('isDisconnected', false);
  },

  _didDisconnect: function() {
    this.set('isDisconnected', true);
  }

});

export { Controller };
<commit_msg>Include the channel name in the logging of all events<commit_after>var global = (typeof window !== 'undefined') ? window : {},
    Ember = global.Ember;

// Need to track
// 1) channel object
// 2) event bindings which consist of
//    - handler
//    - event name
//    - a unique string representing the target
//
//  bindings: {
//    'channel-one': {
//      channel: Pusher.Channel,
//      eventBindings: {
//        Ember.Route.toString(): [
//          { handler: Function, eventName: String },
//          { handler: Function, eventName: String }
//        ]
//      }
//    }
//  }
//
//  wire(target, channelName, events)
//  ================
//  Initialize object in bindings if it's empty, with eventBindings: {}
//  If eventBindings.length for the current target is 0
//    connect to the channel
//    store channel in the hash
//  For each event in events
//    bind the channel to the eventName
//    store the handler and eventName in the eventBindings array for this channel and controller
//    the key for storing is in target._pusherTargetId()
//    (we store the eventName for when we might want to programmatically unwire)
//
//
//  unwire(route):
//  =================
//  get the channel object
//  for each  handler, eventName in eventBindings for the current route
//    call channel.unbind(eventName, handler)
//  delete the routes record in EventBindings
//  if eventBindings for this channel is empty
//    unsubscribe from the channel
//    delete the channel from bindings

var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

var Controller = Ember.Controller.extend({

  connection: null,
  isDisconnected: true,
  isConnected: Ember.computed.not('isDisconnected'),

  init: function() {
    this._super();
    this.set('bindings', {});
  },

  // Called by the application initializer
  didCreatePusher: function(pusher) {
    this.set('connection', pusher);
    pusher.connection.bind('connected',     __bind(this._didConnect,    this));
    pusher.connection.bind('disconnected',  __bind(this._didDisconnect, this));
    pusher.connection.bind('unavailable',   __bind(this._didDisconnect, this));
  },

  // @events a hash in the form { channel-name: ['event1', 'event2'] }
  // @target any object that responds to send() and _pusherEventsId()
  wire: function(target, channelName, events) {
    var channel = this.connectChannel(channelName),
        bindings = this.get('bindings'),
        targetId = target._pusherEventsId();

    // Setup the eventBindings array for this target
    if(!bindings[channelName].eventBindings[targetId])
      bindings[channelName].eventBindings[targetId] = [];

    // Iterate over the events and bind them
    events.forEach(function(eventName) {
      var normalizedEventName = Ember.String.camelize(eventName), handler;
      handler = function(data) {
        if(target.get('logPusherEvents')) {
          console.log(target.constructor.toString() +
            ": Pusher event received", eventName, data);
        }
        target.send(Ember.String.camelize(eventName), data);
      };
      channel.bind(eventName, handler);
      bindings[channelName].eventBindings[targetId].pushObject({
        handler: handler,
        eventName: eventName
      });
    });
  },

  connectChannel: function(channelName) {
    var pusher = this.get('connection'),
        bindings = this.get('bindings');
    if(!bindings[channelName]) {
      bindings[channelName] = { eventBindings: {} };
    }
    if(Ember.isEmpty(Object.keys(bindings[channelName].eventBindings))) {
      bindings[channelName].channel = pusher.subscribe(channelName);

      // Spit out a bunch of logging if asked
      if(this.namespace.PUSHER_OPTS.logAllEvents) {
        bindings[channelName].channel.bind_all(function(eventName, data) {
          console.log(
            "Pusher event received on " + channelName + ":",
            eventName,
            data
          );
        });
      }
    }
    return bindings[channelName].channel;
  },

  unwire: function(target, channelName) {
    var pusher = this.get('connection'),
        bindings = this.get('bindings'),
        targetId = target._pusherEventsId(),
        channel = bindings[channelName].channel;

    // Unbind all the events for this target
    for(var binding in bindings[channelName].eventBindings[targetId]) {
      channel.unbind(binding.eventName, binding.handler);
    }
    delete bindings[channelName].eventBindings[targetId];

    // Unsubscribe from the channel if this is the last thing listening
    if(bindings[channelName].eventBindings.length === 0) {
      pusher.unsubscribe(channelName);
      delete bindings[channelName];
      return true;
    }
    return false;
  },

  channelFor: function(channelName) {
    return this.get('bindings')[channelName].channel;
  },

  socketId: function() {
    try {
      return this.get('connection').connection.socket_id;
    }
    catch(error) {
      console.warn(error);
    }
  }.property('isDisconnected'),

  _didConnect: function() {
    this.set('isDisconnected', false);
  },

  _didDisconnect: function() {
    this.set('isDisconnected', true);
  }

});

export { Controller };
<|endoftext|>


<commit_before>'use strict';

var _ = require('lodash');

var ClientError = require('./clienterror');

var errors = {
  INVALID_BACKUP: 'Invalid Backup',
  WALLET_DOES_NOT_EXIST: 'Wallet does not exists. Need to recreate',
  MISSING_PRIVATE_KEY: 'Missing private keys to sign',
  ENCRYPTED_PRIVATE_KEY: 'Private Key is encrypted, cannot sign',
  SERVER_COMPROMISED: 'Server response could not be verifed',
};

var errorObjects = _.zipObject(_.map(errors, function(msg, code) {
  return [code, new ClientError(code, msg)];
}));

errorObjects.codes = _.mapValues(errors, function(v, k) {
  return k;
});

module.exports = errorObjects;
<commit_msg>fix typos in error messages<commit_after>'use strict';

var _ = require('lodash');

var ClientError = require('./clienterror');

var errors = {
  INVALID_BACKUP: 'Invalid Backup',
  WALLET_DOES_NOT_EXIST: 'Wallet does not exist. Need to recreate',
  MISSING_PRIVATE_KEY: 'Missing private keys to sign',
  ENCRYPTED_PRIVATE_KEY: 'Private key is encrypted, cannot sign',
  SERVER_COMPROMISED: 'Server response could not be verified',
};

var errorObjects = _.zipObject(_.map(errors, function(msg, code) {
  return [code, new ClientError(code, msg)];
}));

errorObjects.codes = _.mapValues(errors, function(v, k) {
  return k;
});

module.exports = errorObjects;
<|endoftext|>


<commit_before>/*
GunDB-R Alpha-Filter
QXIP BV (http://qxip.net)
 */

var base_filter = require('../lib/base_filter');
var  util = require('util'),
  logger = require('log4node');

var gun_helper = require('../lib/gun_helper');
var gun = gun_helper.gun;

var Extract = function(key,data){
   if(key.indexOf('.') !== -1) {
	return key.split('.').reduce(function(a, b) {
	  return a[b];
	}, data);
   } else { return data[key]; }
}

function FilterGunRead() {
  base_filter.BaseFilter.call(this);
  this.mergeConfig(gun_helper.config());
  this.mergeConfig({
    name: 'GunRead',
    optional_params: ['target_field'],
    host_field: 'field',
    default_values: {
      'target_field': 'gun',
      'write': 'false'
    },
    start_hook: this.start,
  });
}

util.inherits(FilterGunRead, base_filter.BaseFilter);

FilterGunRead.prototype.start = function(callback) {
  callback();
};

FilterGunRead.prototype.process = function(data) {

  if (!data[this.target_field]) {
        var rvalue = Extract(this.field,data);
        //this.emit('output', data);
        gun.get(rvalue).val(function(result,key) {
		delete result._;
		delete result['#'];
	 	// if (result) { data[this.target_field] = result; }
		data[this.target_field] = { gun: JSON.stringify(result) };
		//console.log('OUT:',data);
	      this.emit('output',data);
        }.bind(this));
  }
  else {
    console.log('SENDING:',data.type)
    return data;
  }
};

exports.create = function() {
  return new FilterGunRead();
};
<commit_msg>fix temp mapping style<commit_after>/*
GunDB-R Alpha-Filter
QXIP BV (http://qxip.net)
 */

var base_filter = require('../lib/base_filter');
var  util = require('util'),
  logger = require('log4node');

var gun_helper = require('../lib/gun_helper');
var gun = gun_helper.gun;

var Extract = function(key,data){
   if(key.indexOf('.') !== -1) {
	return key.split('.').reduce(function(a, b) {
	  return a[b];
	}, data);
   } else { return data[key]; }
}

function FilterGunRead() {
  base_filter.BaseFilter.call(this);
  this.mergeConfig(gun_helper.config());
  this.mergeConfig({
    name: 'GunRead',
    optional_params: ['target_field'],
    host_field: 'field',
    default_values: {
      'target_field': 'gun',
      'write': 'false'
    },
    start_hook: this.start,
  });
}

util.inherits(FilterGunRead, base_filter.BaseFilter);

FilterGunRead.prototype.start = function(callback) {
  callback();
};

FilterGunRead.prototype.process = function(data) {

  if (!data[this.target_field]) {
        var rvalue = Extract(this.field,data);
        //this.emit('output', data);
        gun.get(rvalue).val(function(result,key) {
		delete result._;
		delete result['#'];
	 	// if (result) { data[this.target_field] = result; }
		for(var i in result){
			data[this.target_field] = result[i];
		}
		// data[this.target_field] = { gun: JSON.stringify(result) };
	      this.emit('output',data);
        }.bind(this));
  }
  else {
    // console.log('SENDING:',data.type)
    return data;
  }
};

exports.create = function() {
  return new FilterGunRead();
};
<|endoftext|>


<commit_before>const lexer = require('pug-lexer')
const parser = require('pug-parser')
const pugWalk = require('pug-walk')
const babylon = require('babylon')
const codeWalk = require('babel-traverse').default

const isComponent = string => /^[A-Z].*$/.test(string)

const parseAndFindVarsInProgram = (program) => {
  const out = []
  const code = babylon.parse(program)

  codeWalk(code, {
    enter(path) {
      if (path.type === 'ExpressionStatement') {
        const varsInGlobal = Object.keys(path.scope.globals)

        out.push(...varsInGlobal)
      }
    },
  })

  return out
}

const prepareValueToBeParsed = value => String(value)

const findVariablesInTemplate = (template) => {
  if (template) {
    const tokens = lexer(template)
    const ast = parser(tokens)

    const variables = []

    pugWalk(ast, (node) => {
      if (node.type === 'Tag') {
        if (isComponent(node.name)) {
          variables.push(node.name)
        }

        node.attrs.forEach((attribute) => {
          const value = prepareValueToBeParsed(attribute.val)

          const code = babylon.parseExpression(value)

          if (code.type === 'Identifier') {
            variables.push(code.name)
            return
          }

          if (code.type === 'MemberExpression') {
            variables.push(code.object.name)

            if (code.computed && code.property.type === 'Identifier') {
              variables.push(code.property.name)
            }
          }
        })

        return
      }

      if (node.type === 'Code') {
        const vars = parseAndFindVarsInProgram(node.val)

        variables.push(...vars)

        return
      }

      if (node.type === 'Conditional') {
        const vars = parseAndFindVarsInProgram(node.test)

        variables.push(...vars)

        return
      }

      if (node.type === 'Each') {
        const vars = parseAndFindVarsInProgram(node.obj)

        variables.push(...vars)
      }
    })

    return variables
  }

  return []
}

module.exports = findVariablesInTemplate
<commit_msg>Handle invocations of functions passed in attributes<commit_after>const lexer = require('pug-lexer')
const parser = require('pug-parser')
const pugWalk = require('pug-walk')
const babylon = require('babylon')
const codeWalk = require('babel-traverse').default

const isComponent = string => /^[A-Z].*$/.test(string)

const parseAndFindVarsInProgram = (program) => {
  const out = []
  const code = babylon.parse(program)

  codeWalk(code, {
    enter(path) {
      if (path.type === 'ExpressionStatement') {
        const varsInGlobal = Object.keys(path.scope.globals)

        out.push(...varsInGlobal)
      }
    },
  })

  return out
}

const prepareValueToBeParsed = value => String(value)

const findVariablesInTemplate = (template) => {
  if (template) {
    const tokens = lexer(template)
    const ast = parser(tokens)

    const variables = []

    pugWalk(ast, (node) => {
      if (node.type === 'Tag') {
        if (isComponent(node.name)) {
          variables.push(node.name)
        }

        node.attrs.forEach((attribute) => {
          const value = prepareValueToBeParsed(attribute.val)
          const vars = parseAndFindVarsInProgram(value)

          variables.push(...vars)
        })

        return
      }

      if (node.type === 'Code') {
        const vars = parseAndFindVarsInProgram(node.val)

        variables.push(...vars)

        return
      }

      if (node.type === 'Conditional') {
        const vars = parseAndFindVarsInProgram(node.test)

        variables.push(...vars)

        return
      }

      if (node.type === 'Each') {
        const vars = parseAndFindVarsInProgram(node.obj)

        variables.push(...vars)
      }
    })

    return variables
  }

  return []
}

module.exports = findVariablesInTemplate
<|endoftext|>


<commit_before>var GEOM_UTIL = require("./util");
var UTIL = require("../util");
var PROJ = require("../proj");

var jts = Packages.com.vividsolutions.jts;
var geotools = Packages.org.geotools;
var CRS = geotools.referencing.CRS;
var GeometryTX = geotools.geometry.jts.GeometryCoordinateSequenceTransformer;
var prepFactory = new jts.geom.prep.PreparedGeometryFactory();
var _getMethod = GEOM_UTIL._getMethod;
var _prepConfig = GEOM_UTIL._prepConfig;

var arrayRepr = function(array) {
    var str;
    if (array.map) {
        str = "[" + array.map(arrayRepr).join(", ") + "]";
    } else {
        str = array;
    }
    return str;
}

var sameProjection = function(source, other) {
    if (source.projection && other.projection && !source.projection.equals(other.projection)) {
        other = other.transform(source.projection);
    }
    return other;
};

/** api: (define)
 *  module = geom
 *  class = Geometry
 */
var Geometry = UTIL.extend(Object, {

    /** private: property[_geometry]
     *  ``jts.geom.Geometry``
     */
    _geometry: undefined,

    /** private: property[cache]
     *  ``Object``
     */
    cache: null,

    /** api: constructor
     *  .. class:: Geometry
     *
     *      A Geometry instance should not be created directly.
     *      Create an instance of a Geometry subclass instead.
     */
    constructor: function Geometry(config) {
        this.cache = {};
        config = _prepConfig(config);
        if (config.coordinates) {
            this._geometry = this._create(config.coordinates);
        }
        if (config.projection) {
            this.projection = config.projection;
        }
    },

    /** private: method[_create]
     *  :arg coords: ``Array`` A coordinates array.
     *
     *  Create a JTS geometry from an array of coordinates.  Must be implemented
     *  by a subclass.
     */
    _create: function(coords) {
        throw new Error("Geometry subclass must implement _create.");
    },

    /** api: property[projection]
     *  :class:`proj.Projection`
     *  Optional projection for the geometry.  If this is set, it is assumed
     *  that the geometry coordinates are in the corresponding coordinate
     *  reference system.  Use the :meth:`transform` method to transform a
     *  geometry from one coordinate reference system to another.
     */
    get projection() {
        return this.cache.projection;
    },
    set projection(projection) {
        if (projection) {
            if (!(projection instanceof PROJ.Projection)) {
                projection = new PROJ.Projection(projection);
            }
            // clear anything else in the cache
            this.cache = {projection: projection};
        }
    },

    /** api: method[transform]
     *  :arg to: :class:`proj.Projection`
     *  :returns: :class:`geom.Geometry`
     *
     *  Transform coordinates of this geometry to the given projection.  The
     *  :attr:`projection` of this geometry must be set before calling this
     *  method.  Returns a new geometry.
     */
    transform: function(to) {
        var from = this.projection;
        if (!from) {
            throw "Projection must be set before calling transform.";
        }
        if (!(to instanceof PROJ.Projection)) {
            to = new PROJ.Projection(to);
        }
        var gt = new GeometryTX();
        gt.mathTransform = CRS.findMathTransform(from._projection, to._projection);
        var _geometry = gt.transform(this._geometry);
        var transformed = Geometry.from_(_geometry);
        transformed.projection = to;
        return transformed;
    },

    /** api: method[prepare]
     *  :returns: :class:`geom.Geometry`
     *
     *  Prepare a geometry for multiple spatial operations.  Preparing optimizes
     *  the geometry for multiple calls to :meth:`contains`, :meth:`coveredBy`,
     *  :meth:`covers`, :meth:`crosses`, :meth:`disjoint`, :meth:`intersects`,
     *  :meth:`overlaps`, :meth:`touches`, and :meth:`within`.
     */
    prepare: function() {
        if (!this.prepared) {
            this._geometry = prepFactory.create(this._geometry);
        }
        return this;
    },

    /** api: property[prepared]
     *  ``Boolean``
     *  This is a prepared geometry.  See :meth:`prepare`.
     */
    get prepared() {
        return this._geometry instanceof jts.geom.prep.PreparedGeometry;
    },

    /** api: property[coordinates]
     *  ``Array``
     *  The geometry's coordinates array.
     */
    get coordinates() {
        return this._extractCoordinates(this._geometry);
    },

    /** api: property[bounds]
     *  :class:`geom.Bounds`
     *  The bounds defined by minimum and maximum x and y values in this geometry.
     */
    get bounds() {
        if (!this.cache.bounds) {
            var _bounds = _getMethod(this._geometry, "getEnvelopeInternal")();
            var bounds = GEOM_UTIL.create({
                type: "Bounds",
                minx: Number(_bounds.getMinX()), maxx: Number(_bounds.getMaxX()),
                miny: Number(_bounds.getMinY()), maxy: Number(_bounds.getMaxY()),
                projection: this.projection
            });
            this.cache.bounds = bounds;
        }
        return this.cache.bounds;
    },

    /** private: method[extractCoordinates]
     *  :returns: ``Array`` An array of coordinates.
     *
     *  Generate an array of coordinates for the geometry.
     */
    _extractCoordinates: function() {
        throw new Error("Geometry subclasses must implement _extractCoordinates.");
    },

    /** private: method[toFullString]
     *  :returns: ``String``
     *
     *  The Well-Known Text representation of the geometry.
     */
    toFullString: function() {
        return arrayRepr(this.coordinates);
    },

    /** api: property[json]
     *  ``String``
     *  The JSON representation of the geometry (see http://geojson.org).
     */
    get json() {
        return JSON.stringify(this.config);
    },

    /** private: property[config]
     *  ``Object``
     */
    get config() {
        return {
            type: this.constructor.name,
            coordinates: this.coordinates
        };
    },

    /** api: property[centroid]
     *  ``geom.Point``
     *  The centroid of this geometry.
     */
    get centroid() {
        var _point = this._geometry.getCentroid();
        var point = Geometry.from_(_point);
        point.projection = this.projection;
        return point;
    },

    /** api: method[buffer]
     *  :arg dist: ``Number`` Width of buffer.  May be positive, negative, or
     *      zero.
     *  :arg segs: ``Number`` Integer number of quadrant segments for circular
     *      arcs.  Default is 8.
     *  :arg caps: ``Number`` One of :data:`BUFFER_CAP_ROUND`,
     *      :data:`BUFFER_CAP_BUTT`, or :data:`BUFFER_CAP_SQUARE`.  Default
     *      is :data:`BUFFER_CAP_ROUND`.
     *  :returns: :class:`geom.Geometry`
     *
     *  Construct a goemetry that buffers this geometry by the given width.
     */
    buffer: function(dist, segs, caps) {
        if (segs === undefined) {
            segs = 8;
        } else {
            segs |= 0;
        }
        if (caps === undefined) {
            caps = GEOM_UTIL.BUFFER_CAP_ROUND;
        }
        var geometry = Geometry.from_(_getMethod(this._geometry, "buffer")(dist, segs, caps));
        geometry.projection = this.projection;
        return geometry;
    },

    /** api: method[distance]
     *  :arg geometry: :class:`geom.Geometry`
     *  :returns: ``Number``
     *
     *  Returns the minimum distance between this and the supplied geometry.
     */
    distance: function(geometry) {
        geometry = sameProjection(this, geometry);
        return _getMethod(this._geometry, "distance")(geometry._geometry);
    },

    /** api: property[area]
     *  ``Number``
     *  The geometry area.
     */
    get area() {
        return _getMethod(this._geometry, "getArea")();
    },

    /** api: property[length]
     *  ``Number``
     *  The geometry length.
     */
    get length() {
        return _getMethod(this._geometry, "getLength")();
    }

});

var constructive = [
    /** api: method[clone]
     *  :returns: :class:`geom.Geometry`
     *
     *  Creates a complete copy of this geometry.
     */
    "clone",

    /** api: method[convexHull]
     *  :returns: :class:`geom.Geometry`
     *
     *  Computes the smallest convex :class:`Polygon` that contains this
     *  geometry.
     */
    "convexHull",

    /** api: method[difference]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: :class:`geom.Geometry`
     *
     *  Creates a geometry made up of all the points in this geometry that are
     *  not in the other geometry.
     */
    "difference",

    /** api: method[getBoundary]
     *  :returns: :class:`geom.Geometry`
     *
     *  Returns the boundary, or an empty geometry of appropriate dimension if
     *  this geometry is empty.
     */
    "getBoundary",

    /** api: method[getEnvelope]
     *  :returns: :class:`geom.Geometry`
     *
     *  Returns this geometry's bounding box.
     */
    "getEnvelope",

    /** api: method[intersection]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: :class:`geom.Geometry`
     *
     *  Creates a geometry representing all the points shared by this geometry
     *  and the other.
     */
    "intersection",

    /** api: method[symDifference]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: :class:`geom.Geometry`
     *
     *  Creates a geometry representing all the points in this geometry but not
     *  in the other plus all the points in the other but not in this geometry.
     */
    "symDifference",

    /** api: method[symDifference]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: :class:`geom.Geometry`
     *
     *  Creates a geometry representing all the points in this geometry but not
     *  in the other plus all the points in the other but not in this geometry.
     */
    "union"
];
constructive.forEach(function(method) {
    Geometry.prototype[method] = function() {
        var _geometry;
        if (arguments.length) {
            _geometry = _getMethod(this._geometry, method)(sameProjection(this, arguments[0])._geometry);
        } else {
            _geometry = _getMethod(this._geometry, method)();
        }
        var geometry = Geometry.from_(_geometry);
        geometry.projection = this.projection;
        return geometry;
    };
});

var unary = [
    /** api: method[isEmpty]
     *  :returns: ``Boolean``
     *
     *  Tests if this geometry is empty.
     */
    "isEmpty",

    /** api: method[isRectangle]
     *  :returns: ``Boolean``
     *
     *  Tests if this geometry is a rectangle.
     */
    "isRectangle",

    /** api: method[isSimple]
     *  :returns: ``Boolean``
     *
     *  Tests if this geometry is simple.
     */
    "isSimple",

    /** api: method[isValid]
     *  :returns: ``Boolean``
     *
     *  Tests if this geometry is valid.
     */
    "isValid"
];
unary.forEach(function(method) {
    Geometry.prototype[method] = function() {
        return Boolean(_getMethod(this._geometry, method)());
    };
});

var binary = [
    /** api: method[contains]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: ``Boolean``
     *
     *  Tests if this geometry contains the other geometry (without boundaries
     *  touching).
     */
    "contains",

    /** api: method[coveredBy]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: ``Boolean``
     *
     *  Tests if this geometry is covered by other geometry.
     */
    "coveredBy",

    /** api: method[covers]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: ``Boolean``
     *
     *  Tests if this geometry covers the other geometry.
     */
    "covers",

    /** api: method[crosses]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: ``Boolean``
     *
     *  Tests if this geometry crosses the other geometry.
     */
    "crosses",

    /** api: method[disjoint]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: ``Boolean``
     *
     *  Tests if this geometry is disjoint to the other geometry.
     */
    "disjoint",

    /** api: method[equals]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: ``Boolean``
     *
     *  Geometries are considered equal if they share at least one point in
     *  common and if no point of either geometry lies in the exterior of the
     *  other.
     */
    "equals",

    /** api: method[equalsExact]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: ``Boolean``
     *
     *  Tests if this geometry is exactly equal to the other geometry.
     */
    "equalsExact",

    /** api: method[overlaps]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: ``Boolean``
     *
     *  Tests if this geometry overlaps the other geometry.
     */
    "overlaps",

    /** api: method[intersects]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: ``Boolean``
     *
     *  Tests if this geometry intersects the other geometry.
     */
    "intersects",

    /** api: method[touches]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: ``Boolean``
     *
     *  Tests if this geometry `only` touches the other geometry.
     */
    "touches",

    /** api: method[within]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: ``Boolean``
     *
     *  Tests if this geometry is within the other geometry.  This is the
     *  inverse of :meth:`contains`.
     */
    "within"
];
binary.forEach(function(method) {
    Geometry.prototype[method] = function(g) {
        return Boolean(_getMethod(this._geometry, method)(sameProjection(this, g)._geometry));
    }
});

/** private: staticproperty[_factory]
 *  ``jts.geom.GeometryFactory``
 *  A jts geometry factory.
 */
Geometry._factory = new jts.geom.GeometryFactory();

/** private: staticmethod[from_]
 *  :arg geometry: ``jts.geom.Geometry`` A JTS geometry object.
 *  :returns: :class`Geometry`
 *
 *  Create a geoscript geometry object from a JTS geometry object.
 */
Geometry.from_ = function(_geometry) {
    var name = String(_getMethod(_geometry, "getGeometryType")());
    var g = GEOM_UTIL.create({type: name});
    g._geometry = _geometry;
    return g;
};

exports.Geometry = Geometry;
<commit_msg>Avoid instanceof check.<commit_after>var GEOM_UTIL = require("./util");
var UTIL = require("../util");
var PROJ = require("../proj");

var jts = Packages.com.vividsolutions.jts;
var geotools = Packages.org.geotools;
var CRS = geotools.referencing.CRS;
var GeometryTX = geotools.geometry.jts.GeometryCoordinateSequenceTransformer;
var prepFactory = new jts.geom.prep.PreparedGeometryFactory();
var _getMethod = GEOM_UTIL._getMethod;
var _prepConfig = GEOM_UTIL._prepConfig;

var arrayRepr = function(array) {
    var str;
    if (array.map) {
        str = "[" + array.map(arrayRepr).join(", ") + "]";
    } else {
        str = array;
    }
    return str;
}

var sameProjection = function(source, other) {
    if (source.projection && other.projection && !source.projection.equals(other.projection)) {
        other = other.transform(source.projection);
    }
    return other;
};

/** api: (define)
 *  module = geom
 *  class = Geometry
 */
var Geometry = UTIL.extend(Object, {

    /** private: property[_geometry]
     *  ``jts.geom.Geometry``
     */
    _geometry: undefined,

    /** private: property[cache]
     *  ``Object``
     */
    cache: null,

    /** api: constructor
     *  .. class:: Geometry
     *
     *      A Geometry instance should not be created directly.
     *      Create an instance of a Geometry subclass instead.
     */
    constructor: function Geometry(config) {
        this.cache = {};
        config = _prepConfig(config);
        if (config.coordinates) {
            this._geometry = this._create(config.coordinates);
        }
        if (config.projection) {
            this.projection = config.projection;
        }
    },

    /** private: method[_create]
     *  :arg coords: ``Array`` A coordinates array.
     *
     *  Create a JTS geometry from an array of coordinates.  Must be implemented
     *  by a subclass.
     */
    _create: function(coords) {
        throw new Error("Geometry subclass must implement _create.");
    },

    /** api: property[projection]
     *  :class:`proj.Projection`
     *  Optional projection for the geometry.  If this is set, it is assumed
     *  that the geometry coordinates are in the corresponding coordinate
     *  reference system.  Use the :meth:`transform` method to transform a
     *  geometry from one coordinate reference system to another.
     */
    get projection() {
        return this.cache.projection;
    },
    set projection(projection) {
        if (projection) {
            if (!(projection instanceof PROJ.Projection)) {
                projection = new PROJ.Projection(projection);
            }
            // clear anything else in the cache
            this.cache = {projection: projection};
        }
    },

    /** api: method[transform]
     *  :arg to: :class:`proj.Projection`
     *  :returns: :class:`geom.Geometry`
     *
     *  Transform coordinates of this geometry to the given projection.  The
     *  :attr:`projection` of this geometry must be set before calling this
     *  method.  Returns a new geometry.
     */
    transform: function(to) {
        var from = this.projection;
        if (!from) {
            throw "Projection must be set before calling transform.";
        }
        if (typeof to == "string") {
            to = new PROJ.Projection(to);
        }
        var gt = new GeometryTX();
        gt.mathTransform = CRS.findMathTransform(from._projection, to._projection);
        var _geometry = gt.transform(this._geometry);
        var transformed = Geometry.from_(_geometry);
        transformed.projection = to;
        return transformed;
    },

    /** api: method[prepare]
     *  :returns: :class:`geom.Geometry`
     *
     *  Prepare a geometry for multiple spatial operations.  Preparing optimizes
     *  the geometry for multiple calls to :meth:`contains`, :meth:`coveredBy`,
     *  :meth:`covers`, :meth:`crosses`, :meth:`disjoint`, :meth:`intersects`,
     *  :meth:`overlaps`, :meth:`touches`, and :meth:`within`.
     */
    prepare: function() {
        if (!this.prepared) {
            this._geometry = prepFactory.create(this._geometry);
        }
        return this;
    },

    /** api: property[prepared]
     *  ``Boolean``
     *  This is a prepared geometry.  See :meth:`prepare`.
     */
    get prepared() {
        return this._geometry instanceof jts.geom.prep.PreparedGeometry;
    },

    /** api: property[coordinates]
     *  ``Array``
     *  The geometry's coordinates array.
     */
    get coordinates() {
        return this._extractCoordinates(this._geometry);
    },

    /** api: property[bounds]
     *  :class:`geom.Bounds`
     *  The bounds defined by minimum and maximum x and y values in this geometry.
     */
    get bounds() {
        if (!this.cache.bounds) {
            var _bounds = _getMethod(this._geometry, "getEnvelopeInternal")();
            var bounds = GEOM_UTIL.create({
                type: "Bounds",
                minx: Number(_bounds.getMinX()), maxx: Number(_bounds.getMaxX()),
                miny: Number(_bounds.getMinY()), maxy: Number(_bounds.getMaxY()),
                projection: this.projection
            });
            this.cache.bounds = bounds;
        }
        return this.cache.bounds;
    },

    /** private: method[extractCoordinates]
     *  :returns: ``Array`` An array of coordinates.
     *
     *  Generate an array of coordinates for the geometry.
     */
    _extractCoordinates: function() {
        throw new Error("Geometry subclasses must implement _extractCoordinates.");
    },

    /** private: method[toFullString]
     *  :returns: ``String``
     *
     *  The Well-Known Text representation of the geometry.
     */
    toFullString: function() {
        return arrayRepr(this.coordinates);
    },

    /** api: property[json]
     *  ``String``
     *  The JSON representation of the geometry (see http://geojson.org).
     */
    get json() {
        return JSON.stringify(this.config);
    },

    /** private: property[config]
     *  ``Object``
     */
    get config() {
        return {
            type: this.constructor.name,
            coordinates: this.coordinates
        };
    },

    /** api: property[centroid]
     *  ``geom.Point``
     *  The centroid of this geometry.
     */
    get centroid() {
        var _point = this._geometry.getCentroid();
        var point = Geometry.from_(_point);
        point.projection = this.projection;
        return point;
    },

    /** api: method[buffer]
     *  :arg dist: ``Number`` Width of buffer.  May be positive, negative, or
     *      zero.
     *  :arg segs: ``Number`` Integer number of quadrant segments for circular
     *      arcs.  Default is 8.
     *  :arg caps: ``Number`` One of :data:`BUFFER_CAP_ROUND`,
     *      :data:`BUFFER_CAP_BUTT`, or :data:`BUFFER_CAP_SQUARE`.  Default
     *      is :data:`BUFFER_CAP_ROUND`.
     *  :returns: :class:`geom.Geometry`
     *
     *  Construct a goemetry that buffers this geometry by the given width.
     */
    buffer: function(dist, segs, caps) {
        if (segs === undefined) {
            segs = 8;
        } else {
            segs |= 0;
        }
        if (caps === undefined) {
            caps = GEOM_UTIL.BUFFER_CAP_ROUND;
        }
        var geometry = Geometry.from_(_getMethod(this._geometry, "buffer")(dist, segs, caps));
        geometry.projection = this.projection;
        return geometry;
    },

    /** api: method[distance]
     *  :arg geometry: :class:`geom.Geometry`
     *  :returns: ``Number``
     *
     *  Returns the minimum distance between this and the supplied geometry.
     */
    distance: function(geometry) {
        geometry = sameProjection(this, geometry);
        return _getMethod(this._geometry, "distance")(geometry._geometry);
    },

    /** api: property[area]
     *  ``Number``
     *  The geometry area.
     */
    get area() {
        return _getMethod(this._geometry, "getArea")();
    },

    /** api: property[length]
     *  ``Number``
     *  The geometry length.
     */
    get length() {
        return _getMethod(this._geometry, "getLength")();
    }

});

var constructive = [
    /** api: method[clone]
     *  :returns: :class:`geom.Geometry`
     *
     *  Creates a complete copy of this geometry.
     */
    "clone",

    /** api: method[convexHull]
     *  :returns: :class:`geom.Geometry`
     *
     *  Computes the smallest convex :class:`Polygon` that contains this
     *  geometry.
     */
    "convexHull",

    /** api: method[difference]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: :class:`geom.Geometry`
     *
     *  Creates a geometry made up of all the points in this geometry that are
     *  not in the other geometry.
     */
    "difference",

    /** api: method[getBoundary]
     *  :returns: :class:`geom.Geometry`
     *
     *  Returns the boundary, or an empty geometry of appropriate dimension if
     *  this geometry is empty.
     */
    "getBoundary",

    /** api: method[getEnvelope]
     *  :returns: :class:`geom.Geometry`
     *
     *  Returns this geometry's bounding box.
     */
    "getEnvelope",

    /** api: method[intersection]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: :class:`geom.Geometry`
     *
     *  Creates a geometry representing all the points shared by this geometry
     *  and the other.
     */
    "intersection",

    /** api: method[symDifference]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: :class:`geom.Geometry`
     *
     *  Creates a geometry representing all the points in this geometry but not
     *  in the other plus all the points in the other but not in this geometry.
     */
    "symDifference",

    /** api: method[symDifference]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: :class:`geom.Geometry`
     *
     *  Creates a geometry representing all the points in this geometry but not
     *  in the other plus all the points in the other but not in this geometry.
     */
    "union"
];
constructive.forEach(function(method) {
    Geometry.prototype[method] = function() {
        var _geometry;
        if (arguments.length) {
            _geometry = _getMethod(this._geometry, method)(sameProjection(this, arguments[0])._geometry);
        } else {
            _geometry = _getMethod(this._geometry, method)();
        }
        var geometry = Geometry.from_(_geometry);
        geometry.projection = this.projection;
        return geometry;
    };
});

var unary = [
    /** api: method[isEmpty]
     *  :returns: ``Boolean``
     *
     *  Tests if this geometry is empty.
     */
    "isEmpty",

    /** api: method[isRectangle]
     *  :returns: ``Boolean``
     *
     *  Tests if this geometry is a rectangle.
     */
    "isRectangle",

    /** api: method[isSimple]
     *  :returns: ``Boolean``
     *
     *  Tests if this geometry is simple.
     */
    "isSimple",

    /** api: method[isValid]
     *  :returns: ``Boolean``
     *
     *  Tests if this geometry is valid.
     */
    "isValid"
];
unary.forEach(function(method) {
    Geometry.prototype[method] = function() {
        return Boolean(_getMethod(this._geometry, method)());
    };
});

var binary = [
    /** api: method[contains]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: ``Boolean``
     *
     *  Tests if this geometry contains the other geometry (without boundaries
     *  touching).
     */
    "contains",

    /** api: method[coveredBy]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: ``Boolean``
     *
     *  Tests if this geometry is covered by other geometry.
     */
    "coveredBy",

    /** api: method[covers]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: ``Boolean``
     *
     *  Tests if this geometry covers the other geometry.
     */
    "covers",

    /** api: method[crosses]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: ``Boolean``
     *
     *  Tests if this geometry crosses the other geometry.
     */
    "crosses",

    /** api: method[disjoint]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: ``Boolean``
     *
     *  Tests if this geometry is disjoint to the other geometry.
     */
    "disjoint",

    /** api: method[equals]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: ``Boolean``
     *
     *  Geometries are considered equal if they share at least one point in
     *  common and if no point of either geometry lies in the exterior of the
     *  other.
     */
    "equals",

    /** api: method[equalsExact]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: ``Boolean``
     *
     *  Tests if this geometry is exactly equal to the other geometry.
     */
    "equalsExact",

    /** api: method[overlaps]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: ``Boolean``
     *
     *  Tests if this geometry overlaps the other geometry.
     */
    "overlaps",

    /** api: method[intersects]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: ``Boolean``
     *
     *  Tests if this geometry intersects the other geometry.
     */
    "intersects",

    /** api: method[touches]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: ``Boolean``
     *
     *  Tests if this geometry `only` touches the other geometry.
     */
    "touches",

    /** api: method[within]
     *  :arg other: :class:`geom.Geometry`
     *  :returns: ``Boolean``
     *
     *  Tests if this geometry is within the other geometry.  This is the
     *  inverse of :meth:`contains`.
     */
    "within"
];
binary.forEach(function(method) {
    Geometry.prototype[method] = function(g) {
        return Boolean(_getMethod(this._geometry, method)(sameProjection(this, g)._geometry));
    }
});

/** private: staticproperty[_factory]
 *  ``jts.geom.GeometryFactory``
 *  A jts geometry factory.
 */
Geometry._factory = new jts.geom.GeometryFactory();

/** private: staticmethod[from_]
 *  :arg geometry: ``jts.geom.Geometry`` A JTS geometry object.
 *  :returns: :class`Geometry`
 *
 *  Create a geoscript geometry object from a JTS geometry object.
 */
Geometry.from_ = function(_geometry) {
    var name = String(_getMethod(_geometry, "getGeometryType")());
    var g = GEOM_UTIL.create({type: name});
    g._geometry = _geometry;
    return g;
};

exports.Geometry = Geometry;
<|endoftext|>


<commit_before>module.exports = function(sails) {

	/**
	 * Module dependencies.
	 */

	var _ = require('lodash'),
		async = require('async'),
		util = require('../../util'),
		Modules = require('../../moduleloader'),
		Controller = {
			'*': require('./controller.action.js')(sails),
			find: require('./controller.find.js')(sails),
			create: require('./controller.create.js')(sails),
			update: require('./controller.update.js')(sails),
			destroy: require('./controller.destroy.js')(sails)
		};

	/**
	 * Expose `Controller` hook definition
	 */

	return {

		blueprints: {

			// Automatically create routes for every action in the controller
			actions: {
				'get /:controller/:action?': Controller['*'],
				'post /:controller/:action?': Controller['*'],
				'put /:controller/:action?': Controller['*'],
				'delete /:controller/:action?': Controller['*']
			},

			crud: {

				// Naive CRUD actions
				// (these should be disabled in production!)
				'/:controller/find/:id?': Controller.find,
				'/:controller/create': Controller.create,
				'/:controller/update/:id': Controller.update,
				'/:controller/destroy/:id': Controller.destroy,

				// RESTful CRUD actions
				'get /:controller/:id?': Controller.find,
				'post /:controller': Controller.create,
				'put /:controller/:id': Controller.update,
				'delete /:controller/:id': Controller.destroy
			}

		},

		/**
		 * Initialize is fired first thing when the hook is loaded
		 *
		 * @api public
		 */

		initialize: function(cb) {

			// Optional callback
			cb = util.optional(cb);

			// bind action routes
			// (auto-routing for controller blueprints)
			var bindActionRoutes_dependencies = [
				'router:after'
			];

			// bind crud routes
			var bindCRUDRoutes_dependencies = [
				'router:after',
				'hook:controllers:bound:actions'
			];

			// If views hook is enabled, wait to register CRUD routes
			// until after the view routes are registered
			if (sails.config.hooks.views) {
				bindCRUDRoutes_dependencies.push('hook:views:bound');
			}

			// If policies hook is enabled, wait until policies are bound
			// before binding action AND crud blueprint routes
			if (sails.config.hooks.policies) {
				bindActionRoutes_dependencies.push('hook:policies:bound');
				bindCRUDRoutes_dependencies.push('hook:policies:bound');
			}

			// Bind routes at the appropriate times
			waitForAll(bindActionRoutes_dependencies, this.bindActionRoutes);
			waitForAll(bindCRUDRoutes_dependencies, this.bindCRUDRoutes);

			// Grab middleware modules and trigger callback
			this.loadMiddleware(cb);

		},

		/**
		 * Bind blueprint routes handle controller actions
		 */

		bindActionRoutes: function () {
			_.each(this.blueprints.actions, this.bindRoute);
			sails.emit('hook:controllers:bound:actions');
		},

		/**
		 * Bind blueprint routes
		 * (serves CRUD middleware for controllers with matching models)
		 * Then fire the final :bound event
		 */

		bindCRUDRoutes: function ( ) {
			_.each(this.blueprints.crud, this.bindRoute);
			sails.emit('hook:controllers:bound:crud');
			sails.emit('hook:controllers:bound');
		},

		/**
		 * Bind a route
		 * @param {Function} ware
		 * @param {String} route
		 */

		bindRoute: function (ware, route) {

			// Get global blueprint config
			var blueprintsEnabled = sails.config.controllers.blueprints.routes;
			var blueprintsPrefix = sails.config.controllers.blueprints.prefix;

			// TODO: support blueprint config on a per-controller basis

			// Apply prefix config (but strip leading and trailing slash)
			// Pull route apart into pieces so that the prefix can be injected
			var actualRoute = route;
			blueprintsPrefix = blueprintsPrefix.replace(/^\/|\/$/g, '');
			var verb = util.detectVerb(actualRoute).verb;
			actualRoute = actionId = util.detectVerb(actualRoute).path;

			// If a verb is set, the prefix looks like `get /`
			// otherwise, it's just a trailing slash
			actualRoute = (verb ? verb + ' ' : '') + blueprintsPrefix + actualRoute;

			// If the blueprint is enabled, we must prepare to bind a route
			if ( blueprintsEnabled[route] ) {

				// If the user overrode the blueprint ware,
				// set the custom method up to be bound
				if ( _.isFunction (blueprintsEnabled[route]) ) {
					ware = blueprintsEnabled[route];
				}

				// Otherwise the default will be used

				// Bind the blueprint
				sails.router.bind(actualRoute, function wrapperFn (req,res,next) {

					// Track the controller/action target
					// (grab from the path params)
					req.target = {
						controller: req.params.controller,
						action: req.params.action
					};

					ware(req,res,next);
				});
			}
		},

		/**
		 * Wipe everything and (re)load middleware from controllers
		 *
		 * @api private
		 */

		loadMiddleware: function(cb) {
			var self = this;

			sails.log.verbose('Building middleware registry...');

			async.auto({

				controllers: [function(cb) {

					sails.log.verbose('Loading app controllers...');

					// Load app controllers
					sails.controllers = Modules.optional({
						dirname: sails.config.paths.controllers,
						filter: /(.+)Controller\.(js|coffee)$/,
						replaceExpr: /Controller/
					});

					// Get federated controllers where actions are specified each in their own file
					var federatedControllers = Modules.optional({
						dirname: sails.config.paths.controllers,
						pathFilter: /(.+)\/(.+)\.(js|coffee)$/
					});
					sails.controllers = _.extend(sails.controllers, federatedControllers);

					// Register controllers
					_.each(sails.controllers, function(controller, controllerId) {

						// Override whatever was here before
						if (!_.isObject(self.middleware[controllerId])) {
							self.middleware[controllerId] = {};
						}

						// Mix in middleware from blueprints
						self.middleware[controllerId].find = Controller.find;
						self.middleware[controllerId].create = Controller.create;
						self.middleware[controllerId].update = Controller.update;
						self.middleware[controllerId].destroy = Controller.destroy;

						// Mix in middleware from user controller
						_.each(controller, function(action, actionId) {

							// If the action is set to `false`, explicitly disable it
							if (action === false) {
								delete self.middleware[controllerId][actionId];
							}

							// Otherwise mix it in (this will override CRUD blueprints from above)
							else if (_.isFunction(action)) {
								self.middleware[controllerId][actionId] = action;
							}

						});
					});

					// Done
					cb();

				}]

			}, cb);
		}
	};

	/**
	 * Wait until dependency conditions have been satisfied
	 *
	 * @param {Object} events - list of sails.on() event names to wait for
	 * @param {Function} cb
	 *
	 * @api private
	 */

	function waitForAll (events, cb) {
		sails.log.verbose('Waiting to lift guard until all these events have fired ::', events);

		var dependencies = [];
		_.each(events, function (event) {
			dependencies.push(function waitFor (cb) {
				return sails.on(event, cb);
			});
		});

		async.auto(dependencies, function (err) {
			sails.log.verbose('Lifting guard-- all conditions satisfied.');
			return cb(err);
		});
	}

};<commit_msg>TODO for blueprints/policies mashup<commit_after>module.exports = function(sails) {

	/**
	 * Module dependencies.
	 */

	var _ = require('lodash'),
		async = require('async'),
		util = require('../../util'),
		Modules = require('../../moduleloader'),
		Controller = {
			'*': require('./controller.action.js')(sails),
			find: require('./controller.find.js')(sails),
			create: require('./controller.create.js')(sails),
			update: require('./controller.update.js')(sails),
			destroy: require('./controller.destroy.js')(sails)
		};

	// TODO: bind policies to blueprints if policy hook is enabled
	// (this should really happen in the policies hook,
	// but we'll want to expose the blueprints as members of the hook instance just to be safe)

	/**
	 * Expose `Controller` hook definition
	 */

	return {

		blueprints: {

			// Automatically create routes for every action in the controller
			actions: {
				'get /:controller/:action?': Controller['*'],
				'post /:controller/:action?': Controller['*'],
				'put /:controller/:action?': Controller['*'],
				'delete /:controller/:action?': Controller['*']
			},

			crud: {

				// Naive CRUD actions
				// (these should be disabled in production!)
				'/:controller/find/:id?': Controller.find,
				'/:controller/create': Controller.create,
				'/:controller/update/:id': Controller.update,
				'/:controller/destroy/:id': Controller.destroy,

				// RESTful CRUD actions
				'get /:controller/:id?': Controller.find,
				'post /:controller': Controller.create,
				'put /:controller/:id': Controller.update,
				'delete /:controller/:id': Controller.destroy
			}

		},

		/**
		 * Initialize is fired first thing when the hook is loaded
		 *
		 * @api public
		 */

		initialize: function(cb) {

			// Optional callback
			cb = util.optional(cb);

			// bind action routes
			// (auto-routing for controller blueprints)
			var bindActionRoutes_dependencies = [
				'router:after'
			];

			// bind crud routes
			var bindCRUDRoutes_dependencies = [
				'router:after',
				'hook:controllers:bound:actions'
			];

			// If views hook is enabled, wait to register CRUD routes
			// until after the view routes are registered
			if (sails.config.hooks.views) {
				bindCRUDRoutes_dependencies.push('hook:views:bound');
			}

			// If policies hook is enabled, wait until policies are bound
			// before binding action AND crud blueprint routes
			if (sails.config.hooks.policies) {
				bindActionRoutes_dependencies.push('hook:policies:bound');
				bindCRUDRoutes_dependencies.push('hook:policies:bound');
			}

			// Bind routes at the appropriate times
			waitForAll(bindActionRoutes_dependencies, this.bindActionRoutes);
			waitForAll(bindCRUDRoutes_dependencies, this.bindCRUDRoutes);

			// Grab middleware modules and trigger callback
			this.loadMiddleware(cb);

		},

		/**
		 * Bind blueprint routes handle controller actions
		 */

		bindActionRoutes: function () {
			_.each(this.blueprints.actions, this.bindRoute);
			sails.emit('hook:controllers:bound:actions');
		},

		/**
		 * Bind blueprint routes
		 * (serves CRUD middleware for controllers with matching models)
		 * Then fire the final :bound event
		 */

		bindCRUDRoutes: function ( ) {
			_.each(this.blueprints.crud, this.bindRoute);
			sails.emit('hook:controllers:bound:crud');
			sails.emit('hook:controllers:bound');
		},

		/**
		 * Bind a route
		 * @param {Function} ware
		 * @param {String} route
		 */

		bindRoute: function (ware, route) {

			// Get global blueprint config
			var blueprintsEnabled = sails.config.controllers.blueprints.routes;
			var blueprintsPrefix = sails.config.controllers.blueprints.prefix;

			// TODO: support blueprint config on a per-controller basis

			// Apply prefix config (but strip leading and trailing slash)
			// Pull route apart into pieces so that the prefix can be injected
			var actualRoute = route;
			blueprintsPrefix = blueprintsPrefix.replace(/^\/|\/$/g, '');
			var verb = util.detectVerb(actualRoute).verb;
			actualRoute = actionId = util.detectVerb(actualRoute).path;

			// If a verb is set, the prefix looks like `get /`
			// otherwise, it's just a trailing slash
			actualRoute = (verb ? verb + ' ' : '') + blueprintsPrefix + actualRoute;

			// If the blueprint is enabled, we must prepare to bind a route
			if ( blueprintsEnabled[route] ) {

				// If the user overrode the blueprint ware,
				// set the custom method up to be bound
				if ( _.isFunction (blueprintsEnabled[route]) ) {
					ware = blueprintsEnabled[route];
				}

				// Otherwise the default will be used

				// Bind the blueprint
				sails.router.bind(actualRoute, function wrapperFn (req,res,next) {

					// Track the controller/action target
					// (grab from the path params)
					req.target = {
						controller: req.params.controller,
						action: req.params.action
					};

					ware(req,res,next);
				});
			}
		},

		/**
		 * Wipe everything and (re)load middleware from controllers
		 *
		 * @api private
		 */

		loadMiddleware: function(cb) {
			var self = this;

			sails.log.verbose('Building middleware registry...');

			async.auto({

				controllers: [function(cb) {

					sails.log.verbose('Loading app controllers...');

					// Load app controllers
					sails.controllers = Modules.optional({
						dirname: sails.config.paths.controllers,
						filter: /(.+)Controller\.(js|coffee)$/,
						replaceExpr: /Controller/
					});

					// Get federated controllers where actions are specified each in their own file
					var federatedControllers = Modules.optional({
						dirname: sails.config.paths.controllers,
						pathFilter: /(.+)\/(.+)\.(js|coffee)$/
					});
					sails.controllers = _.extend(sails.controllers, federatedControllers);

					// Register controllers
					_.each(sails.controllers, function(controller, controllerId) {

						// Override whatever was here before
						if (!_.isObject(self.middleware[controllerId])) {
							self.middleware[controllerId] = {};
						}

						// Mix in middleware from blueprints
						self.middleware[controllerId].find = Controller.find;
						self.middleware[controllerId].create = Controller.create;
						self.middleware[controllerId].update = Controller.update;
						self.middleware[controllerId].destroy = Controller.destroy;

						// Mix in middleware from user controller
						_.each(controller, function(action, actionId) {

							// If the action is set to `false`, explicitly disable it
							if (action === false) {
								delete self.middleware[controllerId][actionId];
							}

							// Otherwise mix it in (this will override CRUD blueprints from above)
							else if (_.isFunction(action)) {
								self.middleware[controllerId][actionId] = action;
							}

						});
					});

					// Done
					cb();

				}]

			}, cb);
		}
	};

	/**
	 * Wait until dependency conditions have been satisfied
	 *
	 * @param {Object} events - list of sails.on() event names to wait for
	 * @param {Function} cb
	 *
	 * @api private
	 */

	function waitForAll (events, cb) {
		sails.log.verbose('Waiting to lift guard until all these events have fired ::', events);

		var dependencies = [];
		_.each(events, function (event) {
			dependencies.push(function waitFor (cb) {
				return sails.on(event, cb);
			});
		});

		async.auto(dependencies, function (err) {
			sails.log.verbose('Lifting guard-- all conditions satisfied.');
			return cb(err);
		});
	}

};<|endoftext|>