<commit_before>/**
 * Copyright 2012-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"). You
 * may not use this file except in compliance with the License. A copy of
 * the License is located at
 *
 *     http://aws.amazon.com/apache2.0/
 *
 * or in the "license" file accompanying this file. This file is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
 * ANY KIND, either express or implied. See the License for the specific
 * language governing permissions and limitations under the License.
 */

var AWS = require('../core');
var Stream = require('stream').Stream;

AWS.S3 = AWS.Service.defineService('s3', ['2006-03-01'], {
  /**
   * @api private
   */
  initialize: function initialize(options) {
    AWS.Service.prototype.initialize.call(this, options);
    this.setEndpoint((options || {}).endpoint, options);
  },

  setupRequestListeners: function setupRequestListeners(request) {
    request.addListener('build', this.populateURI);
    request.addListener('build', this.computeContentMd5);
    request.removeListener('validate',
      AWS.EventListeners.Core.VALIDATE_REGION);
    request.addListener('extractError', this.extractError);
    request.addListener('extractData', this.extractData);
  },

  /**
   * S3 prefers dns-compatible bucket names to be moved from the uri path
   * to the hostname as a sub-domain.  This is not possible, even for dns-compat
   * buckets when using SSL and the bucket name contains a dot ('.').  The
   * ssl wildcard certificate is only 1-level deep.
   *
   * @api private
   */
  populateURI: function populateURI(req) {
    var httpRequest = req.httpRequest;
    var b = req.params.Bucket;

    if (b) {
      if (!req.service.pathStyleBucketName(b)) {
        httpRequest.endpoint.host = httpRequest.endpoint.hostname = b + '.' +
          httpRequest.endpoint.hostname;

        httpRequest.virtualHostedBucket = b; // needed for signing the request
        httpRequest.path = httpRequest.path.replace(new RegExp('^/' + b), '');
        if (httpRequest.path[0] !== '/') {
          httpRequest.path = '/' + httpRequest.path;
        }
      }
    }
  },

  /**
   * @api private
   */
  computableChecksumOperations: {
    putBucketCors: true,
    putBucketLifecycle: true,
    putBucketTagging: true,
    deleteObjects: true
  },

  /**
   * Checks whether checksums should be computed for the request.
   * If the request requires checksums to be computed, this will always
   * return true, otherwise it depends on whether {AWS.Config.computeChecksums}
   * is set.
   *
   * @param req [AWS.Request] the request to check against
   * @return [Boolean] whether to compute checksums for a request.
   * @api private
   */
  willComputeChecksums: function willComputeChecksums(req) {
    if (this.computableChecksumOperations[req.operation]) return true;
    if (!this.config.computeChecksums) return false;

    // TODO: compute checksums for Stream objects
    if (req.httpRequest.body instanceof Stream) return false;

    var rules = req.service.api.operations[req.operation].input.members;
    if (rules.ContentMD5 && !req.params.ContentMD5) return true;
  },

  /**
   * A listener that computes the Content-MD5 and sets it in the header.
   * @see AWS.S3.willComputeChecksums
   * @api private
   */
  computeContentMd5: function computeContentMd5(req) {
    if (req.service.willComputeChecksums(req)) {
      var md5 = AWS.util.crypto.md5(req.httpRequest.body, 'base64');
      req.httpRequest.headers['Content-MD5'] = md5;
    }
  },

  /**
   * Returns true if the bucket name should be left in the URI path for
   * a request to S3.  This function takes into account the current
   * endpoint protocol (e.g. http or https).
   *
   * @api private
   */
  pathStyleBucketName: function pathStyleBucketName(bucketName) {
    // user can force path style requests via the configuration
    if (this.config.s3ForcePathStyle) return true;

    if (this.dnsCompatibleBucketName(bucketName)) {
      return (this.config.sslEnabled && bucketName.match(/\./)) ? true : false;
    } else {
      return true; // not dns compatible names must always use path style
    }
  },

  /**
   * Returns true if the bucket name is DNS compatible.  Buckets created
   * outside of the classic region MUST be DNS compatible.
   *
   * @api private
   */
  dnsCompatibleBucketName: function dnsCompatibleBucketName(bucketName) {
    var b = bucketName;
    var domain = new RegExp(/^[a-z0-9][a-z0-9\.\-]{1,61}[a-z0-9]$/);
    var ipAddress = new RegExp(/(\d+\.){3}\d+/);
    var dots = new RegExp(/\.\./);
    return (b.match(domain) && !b.match(ipAddress) && !b.match(dots)) ? true : false;
  },

  /**
   * S3 requires that path params not escape forward slashes.
   *
   * @api private
   */
  escapePathParam: function escapePathParam(value) {
    return AWS.util.uriEscapePath(String(value));
  },

  /**
   * @return [Boolean] whether response contains an error
   * @api private
   */
  successfulResponse: function successfulResponse(resp) {
    var req = resp.request;
    var httpResponse = resp.httpResponse;
    if (req.operation === 'completeMultipartUpload' &&
        httpResponse.body.toString().match('<Error>'))
      return false;
    else
      return httpResponse.statusCode < 300;
  },

  /**
   * @return [Boolean] whether the error can be retried
   * @api private
   */
  retryableError: function retryableError(error, request) {
    if (request.operation == 'completeMultipartUpload' &&
        error.statusCode === 200) {
      return true;
    } else {
      var _super = AWS.Service.prototype.retryableError;
      return _super.call(this, error, request);
    }
  },

  /**
   * Provides a specialized parser for getBucketLocation -- all other
   * operations are parsed by the super class.
   *
   * @api private
   */
  extractData: function extractData(resp) {
    var req = resp.request;
    if (req.operation === 'getBucketLocation') {
      /*jshint regexp:false*/
      var match = resp.httpResponse.body.toString().match(/>(.+)<\/Location/);
      if (match) {
        delete resp.data['_'];
        resp.data.LocationConstraint = match[1];
      }
    }
  },

  /**
   * Extracts an error object from the http response.
   *
   * @api private
   */
  extractError: function extractError(resp) {
    var codes = {
      304: 'NotModified',
      403: 'Forbidden',
      400: 'BadRequest',
      404: 'NotFound'
    };

    var code = resp.httpResponse.statusCode;
    var body = resp.httpResponse.body;
    if (codes[code] && body.length === 0) {
      resp.error = AWS.util.error(new Error(), {
        code: codes[resp.httpResponse.statusCode],
        message: null
      });
    } else {
      var data = new AWS.XML.Parser({}).parse(body.toString());
      resp.error = AWS.util.error(new Error(), {
        code: data.Code || code,
        message: data.Message || null
      });
    }
  },

  /**
   * @api private
   */
  setEndpoint: function setEndpoint(endpoint) {
    if (endpoint) {
      this.endpoint = new AWS.Endpoint(endpoint, this.config);
    } else if (this.config.region && this.config.region !== 'us-east-1') {
      var hostname = 's3-' + this.config.region + '.amazonaws.com';
      this.endpoint = new AWS.Endpoint(hostname);
    } else {
      this.endpoint = new AWS.Endpoint(this.api.globalEndpoint, this.config);
    }
  },

  /**
   * Get a pre-signed URL for a given operation name.
   *
   * @note You must ensure that you have static or previously resolved
   *   credentials if you call this method synchronously (with no callback),
   *   otherwise it may not properly sign the request. If you cannot guarantee
   *   this (you are using an asynchronous credential provider, i.e., EC2
   *   IAM roles), you should always call this method with an asynchronous
   *   callback.
   * @param operation [String] the name of the operation to call
   * @param params [map] parameters to pass to the operation. See the given
   *   operation for the expected operation parameters. In addition, you can
   *   also pass the "Expires" parameter to inform S3 how long the URL should
   *   work for.
   * @option params Expires [Integer] (900) the number of seconds to expire
   *   the pre-signed URL operation in. Defaults to 15 minutes.
   * @param callback [Function] if a callback is provided, this function will
   *   pass the URL as the second parameter (after the error parameter) to
   *   the callback function.
   * @return [String] if called synchronously (with no callback), returns the
   *   signed URL.
   * @return [null] nothing is returned if a callback is provided.
   * @example Pre-signing a getObject operation (synchronously)
   *   var params = {Bucket: 'bucket', Key: 'key', Body: 'body'};
   *   var url = s3.getSignedUrl('getObject', params);
   *   console.log("The URL is", url);
   * @example Pre-signing a putObject operation with a specific payload (asynchronously)
   *   var params = {Bucket: 'bucket', Key: 'key', Body: 'body'};
   *   s3.getSignedUrl('putObject', params, function (err, url) {
   *     console.log("The URL is", url);
   *   });
   * @example Passing in a 1-minute expiry time for a pre-signed URL
   *   var params = {Bucket: 'bucket', Key: 'key', Expires: 60};
   *   var url = s3.getSignedUrl('getObject', params);
   *   console.log("The URL is", url); // expires in 60 seconds
   */
  getSignedUrl: function getSignedUrl(operation, params, callback) {
    var url = require('url');
    var events = ['validate', 'build', 'sign'];
    var request = this.makeRequest(operation, params);
    var expires = params.Expires || 900;

    function signedUrlBuilder() {
      delete request.httpRequest.headers['User-Agent'];
      request.httpRequest.headers['Expires'] = parseInt(
        AWS.util.date.unixTimestamp() + expires, 10).toString();
    }

    function signedUrlSigner() {
      var queryParams = {};

      AWS.util.each(request.httpRequest.headers, function (key, value) {
        queryParams[key] = value;
      });

      var auth = queryParams['Authorization'].split(':');
      delete queryParams['Authorization'];
      queryParams['AWSAccessKeyId'] = auth[0].split(' ')[1];
      queryParams['Signature'] = auth[1];

      // build URL
      request.httpRequest.endpoint.pathname = request.httpRequest.path;
      var querystring = AWS.util.queryParamsToString(queryParams);
      var qSep = request.httpRequest.endpoint.pathname.match('\\?') ? '&' : '?';
      request.httpRequest.endpoint.pathname += qSep + querystring;
    }

    request.on('build', signedUrlBuilder);
    request.on('sign', signedUrlSigner);
    if (!params.Body) { // no Content-MD5 signing if body is not provided
      request.removeListener('build', this.computeContentMd5);
    }
    delete params.Expires; // we can't validate this

    if (callback) {
      request.emitEvents(events, new AWS.Response(request), function (err) {
        if (err) callback(err, null);
        else callback(null, url.format(request.httpRequest.endpoint));
      });
    } else {
      AWS.util.arrayEach(events, function (item) {
        request.emitEvent(item, [request]);
      });
      return url.format(request.httpRequest.endpoint);
    }
  }
});

AWS.S3.prototype.createBucket = function createBucket(params, callback) {
  // When creating a bucket *outside* the classic region, the location
  // constraint must be set for the bucket and it must match the endpoint.
  // This chunk of code will set the location constraint param based
  // on the region (when possible), but it will not override a passed-in
  // location constraint.
  if (!params) params = {};
  var hostname = this.endpoint.hostname;
  if (hostname != this.api.globalEndpoint && !params.CreateBucketConfiguration) {
    params.CreateBucketConfiguration = { LocationConstraint: this.config.region };
  }
  return this.makeRequest('createBucket', params, callback);
};

module.exports = AWS.S3;
<commit_msg>Fix 0.10.x compatibility with query string contents<commit_after>/**
 * Copyright 2012-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"). You
 * may not use this file except in compliance with the License. A copy of
 * the License is located at
 *
 *     http://aws.amazon.com/apache2.0/
 *
 * or in the "license" file accompanying this file. This file is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
 * ANY KIND, either express or implied. See the License for the specific
 * language governing permissions and limitations under the License.
 */

var AWS = require('../core');
var Stream = require('stream').Stream;

AWS.S3 = AWS.Service.defineService('s3', ['2006-03-01'], {
  /**
   * @api private
   */
  initialize: function initialize(options) {
    AWS.Service.prototype.initialize.call(this, options);
    this.setEndpoint((options || {}).endpoint, options);
  },

  setupRequestListeners: function setupRequestListeners(request) {
    request.addListener('build', this.populateURI);
    request.addListener('build', this.computeContentMd5);
    request.removeListener('validate',
      AWS.EventListeners.Core.VALIDATE_REGION);
    request.addListener('extractError', this.extractError);
    request.addListener('extractData', this.extractData);
  },

  /**
   * S3 prefers dns-compatible bucket names to be moved from the uri path
   * to the hostname as a sub-domain.  This is not possible, even for dns-compat
   * buckets when using SSL and the bucket name contains a dot ('.').  The
   * ssl wildcard certificate is only 1-level deep.
   *
   * @api private
   */
  populateURI: function populateURI(req) {
    var httpRequest = req.httpRequest;
    var b = req.params.Bucket;

    if (b) {
      if (!req.service.pathStyleBucketName(b)) {
        httpRequest.endpoint.host = httpRequest.endpoint.hostname = b + '.' +
          httpRequest.endpoint.hostname;

        httpRequest.virtualHostedBucket = b; // needed for signing the request
        httpRequest.path = httpRequest.path.replace(new RegExp('^/' + b), '');
        if (httpRequest.path[0] !== '/') {
          httpRequest.path = '/' + httpRequest.path;
        }
      }
    }
  },

  /**
   * @api private
   */
  computableChecksumOperations: {
    putBucketCors: true,
    putBucketLifecycle: true,
    putBucketTagging: true,
    deleteObjects: true
  },

  /**
   * Checks whether checksums should be computed for the request.
   * If the request requires checksums to be computed, this will always
   * return true, otherwise it depends on whether {AWS.Config.computeChecksums}
   * is set.
   *
   * @param req [AWS.Request] the request to check against
   * @return [Boolean] whether to compute checksums for a request.
   * @api private
   */
  willComputeChecksums: function willComputeChecksums(req) {
    if (this.computableChecksumOperations[req.operation]) return true;
    if (!this.config.computeChecksums) return false;

    // TODO: compute checksums for Stream objects
    if (req.httpRequest.body instanceof Stream) return false;

    var rules = req.service.api.operations[req.operation].input.members;
    if (rules.ContentMD5 && !req.params.ContentMD5) return true;
  },

  /**
   * A listener that computes the Content-MD5 and sets it in the header.
   * @see AWS.S3.willComputeChecksums
   * @api private
   */
  computeContentMd5: function computeContentMd5(req) {
    if (req.service.willComputeChecksums(req)) {
      var md5 = AWS.util.crypto.md5(req.httpRequest.body, 'base64');
      req.httpRequest.headers['Content-MD5'] = md5;
    }
  },

  /**
   * Returns true if the bucket name should be left in the URI path for
   * a request to S3.  This function takes into account the current
   * endpoint protocol (e.g. http or https).
   *
   * @api private
   */
  pathStyleBucketName: function pathStyleBucketName(bucketName) {
    // user can force path style requests via the configuration
    if (this.config.s3ForcePathStyle) return true;

    if (this.dnsCompatibleBucketName(bucketName)) {
      return (this.config.sslEnabled && bucketName.match(/\./)) ? true : false;
    } else {
      return true; // not dns compatible names must always use path style
    }
  },

  /**
   * Returns true if the bucket name is DNS compatible.  Buckets created
   * outside of the classic region MUST be DNS compatible.
   *
   * @api private
   */
  dnsCompatibleBucketName: function dnsCompatibleBucketName(bucketName) {
    var b = bucketName;
    var domain = new RegExp(/^[a-z0-9][a-z0-9\.\-]{1,61}[a-z0-9]$/);
    var ipAddress = new RegExp(/(\d+\.){3}\d+/);
    var dots = new RegExp(/\.\./);
    return (b.match(domain) && !b.match(ipAddress) && !b.match(dots)) ? true : false;
  },

  /**
   * S3 requires that path params not escape forward slashes.
   *
   * @api private
   */
  escapePathParam: function escapePathParam(value) {
    return AWS.util.uriEscapePath(String(value));
  },

  /**
   * @return [Boolean] whether response contains an error
   * @api private
   */
  successfulResponse: function successfulResponse(resp) {
    var req = resp.request;
    var httpResponse = resp.httpResponse;
    if (req.operation === 'completeMultipartUpload' &&
        httpResponse.body.toString().match('<Error>'))
      return false;
    else
      return httpResponse.statusCode < 300;
  },

  /**
   * @return [Boolean] whether the error can be retried
   * @api private
   */
  retryableError: function retryableError(error, request) {
    if (request.operation == 'completeMultipartUpload' &&
        error.statusCode === 200) {
      return true;
    } else {
      var _super = AWS.Service.prototype.retryableError;
      return _super.call(this, error, request);
    }
  },

  /**
   * Provides a specialized parser for getBucketLocation -- all other
   * operations are parsed by the super class.
   *
   * @api private
   */
  extractData: function extractData(resp) {
    var req = resp.request;
    if (req.operation === 'getBucketLocation') {
      /*jshint regexp:false*/
      var match = resp.httpResponse.body.toString().match(/>(.+)<\/Location/);
      if (match) {
        delete resp.data['_'];
        resp.data.LocationConstraint = match[1];
      }
    }
  },

  /**
   * Extracts an error object from the http response.
   *
   * @api private
   */
  extractError: function extractError(resp) {
    var codes = {
      304: 'NotModified',
      403: 'Forbidden',
      400: 'BadRequest',
      404: 'NotFound'
    };

    var code = resp.httpResponse.statusCode;
    var body = resp.httpResponse.body;
    if (codes[code] && body.length === 0) {
      resp.error = AWS.util.error(new Error(), {
        code: codes[resp.httpResponse.statusCode],
        message: null
      });
    } else {
      var data = new AWS.XML.Parser({}).parse(body.toString());
      resp.error = AWS.util.error(new Error(), {
        code: data.Code || code,
        message: data.Message || null
      });
    }
  },

  /**
   * @api private
   */
  setEndpoint: function setEndpoint(endpoint) {
    if (endpoint) {
      this.endpoint = new AWS.Endpoint(endpoint, this.config);
    } else if (this.config.region && this.config.region !== 'us-east-1') {
      var hostname = 's3-' + this.config.region + '.amazonaws.com';
      this.endpoint = new AWS.Endpoint(hostname);
    } else {
      this.endpoint = new AWS.Endpoint(this.api.globalEndpoint, this.config);
    }
  },

  /**
   * Get a pre-signed URL for a given operation name.
   *
   * @note You must ensure that you have static or previously resolved
   *   credentials if you call this method synchronously (with no callback),
   *   otherwise it may not properly sign the request. If you cannot guarantee
   *   this (you are using an asynchronous credential provider, i.e., EC2
   *   IAM roles), you should always call this method with an asynchronous
   *   callback.
   * @param operation [String] the name of the operation to call
   * @param params [map] parameters to pass to the operation. See the given
   *   operation for the expected operation parameters. In addition, you can
   *   also pass the "Expires" parameter to inform S3 how long the URL should
   *   work for.
   * @option params Expires [Integer] (900) the number of seconds to expire
   *   the pre-signed URL operation in. Defaults to 15 minutes.
   * @param callback [Function] if a callback is provided, this function will
   *   pass the URL as the second parameter (after the error parameter) to
   *   the callback function.
   * @return [String] if called synchronously (with no callback), returns the
   *   signed URL.
   * @return [null] nothing is returned if a callback is provided.
   * @example Pre-signing a getObject operation (synchronously)
   *   var params = {Bucket: 'bucket', Key: 'key', Body: 'body'};
   *   var url = s3.getSignedUrl('getObject', params);
   *   console.log("The URL is", url);
   * @example Pre-signing a putObject operation with a specific payload (asynchronously)
   *   var params = {Bucket: 'bucket', Key: 'key', Body: 'body'};
   *   s3.getSignedUrl('putObject', params, function (err, url) {
   *     console.log("The URL is", url);
   *   });
   * @example Passing in a 1-minute expiry time for a pre-signed URL
   *   var params = {Bucket: 'bucket', Key: 'key', Expires: 60};
   *   var url = s3.getSignedUrl('getObject', params);
   *   console.log("The URL is", url); // expires in 60 seconds
   */
  getSignedUrl: function getSignedUrl(operation, params, callback) {
    var url = require('url');
    var events = ['validate', 'build', 'sign'];
    var request = this.makeRequest(operation, params);
    var expires = params.Expires || 900;

    function signedUrlBuilder() {
      delete request.httpRequest.headers['User-Agent'];
      request.httpRequest.headers['Expires'] = parseInt(
        AWS.util.date.unixTimestamp() + expires, 10).toString();
    }

    function signedUrlSigner() {
      var queryParams = {};

      AWS.util.each(request.httpRequest.headers, function (key, value) {
        queryParams[key] = value;
      });

      var auth = queryParams['Authorization'].split(':');
      delete queryParams['Authorization'];
      queryParams['AWSAccessKeyId'] = auth[0].split(' ')[1];
      queryParams['Signature'] = auth[1];

      // build URL
      var endpoint = request.httpRequest.endpoint;
      var parsedUrl = url.parse(request.httpRequest.path);
      var querystring = AWS.util.queryParamsToString(queryParams);
      endpoint.pathname = parsedUrl.pathname;
      endpoint.search = !parsedUrl.search ? querystring :
                        parsedUrl.search + '&' + querystring;
    }

    request.on('build', signedUrlBuilder);
    request.on('sign', signedUrlSigner);
    if (!params.Body) { // no Content-MD5 signing if body is not provided
      request.removeListener('build', this.computeContentMd5);
    }
    delete params.Expires; // we can't validate this

    if (callback) {
      request.emitEvents(events, new AWS.Response(request), function (err) {
        if (err) callback(err, null);
        else callback(null, url.format(request.httpRequest.endpoint));
      });
    } else {
      AWS.util.arrayEach(events, function (item) {
        request.emitEvent(item, [request]);
      });
      return url.format(request.httpRequest.endpoint);
    }
  }
});

AWS.S3.prototype.createBucket = function createBucket(params, callback) {
  // When creating a bucket *outside* the classic region, the location
  // constraint must be set for the bucket and it must match the endpoint.
  // This chunk of code will set the location constraint param based
  // on the region (when possible), but it will not override a passed-in
  // location constraint.
  if (!params) params = {};
  var hostname = this.endpoint.hostname;
  if (hostname != this.api.globalEndpoint && !params.CreateBucketConfiguration) {
    params.CreateBucketConfiguration = { LocationConstraint: this.config.region };
  }
  return this.makeRequest('createBucket', params, callback);
};

module.exports = AWS.S3;
<|endoftext|>


<commit_before>/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for
 * full list of contributors). Published under the Clear BSD license.
 * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
 * full text of the license. */

/**
 * @requires OpenLayers/Layer/Vector.js
 * @requires OpenLayers/Console.js
 */

/**
 * Class: OpenLayers.Layer.PointTrack
 * Vector layer to display ordered point features as a line, creating one
 * LineString feature for each pair of two points.
 *
 * Inherits from:
 *  - <OpenLayers.Layer.Vector>
 */
OpenLayers.Layer.PointTrack = OpenLayers.Class(OpenLayers.Layer.Vector, {

    /**
     * APIProperty:
     * dataFrom  - {<OpenLayers.Layer.PointTrack.dataFrom>} optional. If the
     *             lines should get the data/attributes from one of the two
     *             points, creating it, which one should it be?
     */
    dataFrom: null,

    /**
     * Constructor: OpenLayers.PointTrack
     * Constructor for a new OpenLayers.PointTrack instance.
     *
     * Parameters:
     * name     - {String} name of the layer
     * options  - {Object} Optional object with properties to tag onto the
     *            instance.
     */
    initialize: function(name, options) {
        OpenLayers.Layer.Vector.prototype.initialize.apply(this, arguments);
    },

    /**
     * APIMethod: addNodes
     * Adds point features that will be used to create lines from, using point
     * pairs. The first point of a pair will be the source node, the second
     * will be the target node.
     *
     * Parameters:
     * pointFeatures - {Array(<OpenLayers.Feature>)}
     *
     */
    addNodes: function(pointFeatures) {
        if (pointFeatures.length < 2) {
            OpenLayers.Console.error(
                    "At least two point features have to be added to create" +
                    "a line from");
            return;
        }

        var lines = new Array(pointFeatures.length-1);

        var pointFeature, startPoint, endPoint;
        for(var i=0, len=pointFeatures.length; i<len; i++) {
            pointFeature = pointFeatures[i];
            endPoint = pointFeature.geometry;

            if (!endPoint) {
              var lonlat = pointFeature.lonlat;
              endPoint = new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat);
            } else if(endPoint.CLASS_NAME != "OpenLayers.Geometry.Point") {
                OpenLayers.Console.error(
                        "Only features with point geometries are supported.");
                return;
            }

            if(i > 0) {
                var attributes = (this.dataFrom != null) ?
                        (pointFeatures[i+this.dataFrom].data ||
                                pointFeatures[i+this.dataFrom].attributes) :
                        null;
                var line = new OpenLayers.Geometry.LineString([startPoint,
                        endPoint]);

                lines[i-1] = new OpenLayers.Feature.Vector(line, attributes);
            }

            startPoint = endPoint;
        }

        this.addFeatures(lines);
    },

    CLASS_NAME: "OpenLayers.Layer.PointTrack"
});

/**
 * Constant: OpenLayers.Layer.PointTrack.dataFrom
 * {Object} with the following keys
 * - SOURCE_NODE: take data/attributes from the source node of the line
 * - TARGET_NODE: take data/attributes from the target node of the line
 */
OpenLayers.Layer.PointTrack.dataFrom = {'SOURCE_NODE': -1, 'TARGET_NODE': 0};

<commit_msg>Making Layer.PointTrack play nicely with gx:Track from Format.KML. Thanks bartvde for the updated patch. r=fredj,bartvde (closes #2792)<commit_after>/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for
 * full list of contributors). Published under the Clear BSD license.
 * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
 * full text of the license. */

/**
 * @requires OpenLayers/Layer/Vector.js
 * @requires OpenLayers/Console.js
 */

/**
 * Class: OpenLayers.Layer.PointTrack
 * Vector layer to display ordered point features as a line, creating one
 * LineString feature for each pair of two points.
 *
 * Inherits from:
 *  - <OpenLayers.Layer.Vector>
 */
OpenLayers.Layer.PointTrack = OpenLayers.Class(OpenLayers.Layer.Vector, {

    /**
     * APIProperty:
     * dataFrom  - {<OpenLayers.Layer.PointTrack.TARGET_NODE>} or
     *     {<OpenLayers.Layer.PointTrack.SOURCE_NODE>} optional. If the lines
     *     should get the data/attributes from one of the two points it is
     *     composed of, which one should it be?
     */
    dataFrom: null,

    /**
     * APIProperty:
     * styleFrom  - {<OpenLayers.Layer.PointTrack.TARGET_NODE>} or
     *     {<OpenLayers.Layer.PointTrack.SOURCE_NODE>} optional. If the lines
     *     should get the style from one of the two points it is composed of,
     *     which one should it be?
     */
    styleFrom: null,

    /**
     * Constructor: OpenLayers.PointTrack
     * Constructor for a new OpenLayers.PointTrack instance.
     *
     * Parameters:
     * name     - {String} name of the layer
     * options  - {Object} Optional object with properties to tag onto the
     *            instance.
     */
    initialize: function(name, options) {
        OpenLayers.Layer.Vector.prototype.initialize.apply(this, arguments);
    },

    /**
     * APIMethod: addNodes
     * Adds point features that will be used to create lines from, using point
     * pairs. The first point of a pair will be the source node, the second
     * will be the target node.
     *
     * Parameters:
     * pointFeatures - {Array(<OpenLayers.Feature>)}
     * options - {Object}
     *
     * Supported options:
     * silent - {Boolean} true to suppress (before)feature(s)added events
     */
    addNodes: function(pointFeatures, options) {
        if (pointFeatures.length < 2) {
            OpenLayers.Console.error(
                    "At least two point features have to be added to create" +
                    "a line from");
            return;
        }

        var lines = new Array(pointFeatures.length-1);

        var pointFeature, startPoint, endPoint;
        for(var i=0, len=pointFeatures.length; i<len; i++) {
            pointFeature = pointFeatures[i];
            endPoint = pointFeature.geometry;

            if (!endPoint) {
              var lonlat = pointFeature.lonlat;
              endPoint = new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat);
            } else if(endPoint.CLASS_NAME != "OpenLayers.Geometry.Point") {
                OpenLayers.Console.error(
                        "Only features with point geometries are supported.");
                return;
            }

            if(i > 0) {
                var attributes = (this.dataFrom != null) ?
                        (pointFeatures[i+this.dataFrom].data ||
                                pointFeatures[i+this.dataFrom].attributes) :
                        null;
                var style = (this.styleFrom != null) ?
                        (pointFeatures[i+this.styleFrom].style) :
                        null;
                var line = new OpenLayers.Geometry.LineString([startPoint,
                        endPoint]);

                lines[i-1] = new OpenLayers.Feature.Vector(line, attributes,
                    style);
            }

            startPoint = endPoint;
        }

        this.addFeatures(lines, options);
    },

    CLASS_NAME: "OpenLayers.Layer.PointTrack"
});

/**
 * Constant: OpenLayers.Layer.PointTrack.SOURCE_NODE
 * {Number} value for <OpenLayers.Layer.PointTrack.dataFrom> and
 * <OpenLayers.Layer.PointTrack.styleFrom>
 */
OpenLayers.Layer.PointTrack.SOURCE_NODE = -1;

/**
 * Constant: OpenLayers.Layer.PointTrack.TARGET_NODE
 * {Number} value for <OpenLayers.Layer.PointTrack.dataFrom> and
 * <OpenLayers.Layer.PointTrack.styleFrom>
 */
OpenLayers.Layer.PointTrack.TARGET_NODE = 0;

/**
 * Constant: OpenLayers.Layer.PointTrack.dataFrom
 * {Object} with the following keys - *deprecated*
 * - SOURCE_NODE: take data/attributes from the source node of the line
 * - TARGET_NODE: take data/attributes from the target node of the line
 */
OpenLayers.Layer.PointTrack.dataFrom = {'SOURCE_NODE': -1, 'TARGET_NODE': 0};
<|endoftext|>


<commit_before>require('moonstone');

var
	kind = require('enyo/kind'),
	dev = require('enyo/dev'),
	animation = require('enyo/animation');

var
	Spotlight = require('spotlight');

var
	IconButton = require('../IconButton');

/**
* Fires when page boundary is reached.
*
* @event moon.PagingControl#onPaginate
* @type {Object}
* @property {Number} scrollDelta - The distance of the scroll.
* @public
*/

/**
* Fires when we've determined how large the bounceback effect should be.
*
* @event moon.PagingControl#onPaginateScroll
* @type {Object}
* @property {Number} scrollDelta - The magnitude of the scroll bounceback.
* @public
*/

/**
* {@link moon.PagingControl} is a paging control button derived from
* {@link moon.IconButton}. This control is not intended for use outside of
* {@link moon.Scroller}.
*
* @class moon.PagingControl
* @extends moon.IconButton
* @ui
* @public
*/
module.exports = kind(
	/** @lends moon.PagingControl.prototype */ {

	/**
	* @private
	*/
	name: 'moon.PagingControl',

	/**
	* @private
	*/
	kind: IconButton,

	/**
	* @private
	*/
	classes: 'moon-paging-button no-background',

	/**
	* @private
	*/
	spotlight: true,

	/**
	* @private
	* @lends moon.PagingControl.prototype
	*/
	published: {
		/**
		* The side of the control where the button will be.
		*
		* Supported values are `'top'`, `'right'`, `'bottom'`, and `'left'`.
		*
		* @type {String}
		* @default null
		* @public
		*/
		side: null
	},

	/**
	* @private
	*/
	noBackground: true,

	/**
	* @private
	*/
	handlers: {
		onSpotlightFocused: 'noop',
		onSpotlightKeyDown: 'depress',
		onSpotlightKeyUp: 'undepress',
		ondown: 'down',
		onup: 'endHold',
		onleave: 'endHold',
		onhold: 'hold',
		onActivate: 'noop'
	},

	/**
	* @private
	*/
	events: {
		/**
		* {@link moon.PagingControl#onPaginate}
		*/
		onPaginate: '',

		/**
		* {@link moon.PagingControl#onPaginateScroll}
		*/
		onPaginateScroll: ''
	},

	/**
	* @private
	*/
	downTime: 0,

	/**
	* @private
	*/
	initialDelta: 2.5,

	/**
	* @private
	*/
	delta: 0,

	/**
	* @private
	*/
	maxDelta: 45,

	/**
	* @private
	*/
	tapDelta: 15,

	/**
	* @private
	*/
	bumpDeltaMultiplier: 3,

	/**
	* @private
	*/
	create: function() {
		IconButton.prototype.create.apply(this, arguments);
		this.sideChanged();
	},

	/**
	* Stops scrolling animation and triggers
	* [onPaginate]{@link moon.PagingControl#onPaginate} event with a delta
	* value for the bounceback effect.
	*
	* @fires moon.PagingControl#onPaginate
	* @public
	*/
	hitBoundary: function() {
		this.stopHoldJob();
		this.downTime = null;
		this.doPaginate({scrollDelta: this.delta * this.bumpDeltaMultiplier});
		Spotlight.Accelerator.cancel();
	},

	/**
	* @private
	*/
	_iconMappings: {
		'top': 'arrowlargeup',
		'bottom': 'arrowlargedown',
		'left': 'arrowlargeleft',
		'right': 'arrowlargeright'
	},

	/**
	* Set this control's CSS class based on its [side]{@link moon.PagingControl#side}
	* value.
	*
	* @private
	*/
	sideChanged: function(old) {
		var s = this.side;
		if(old) {
			this.removeClass(old);
		}
		this.addClass(s);
		this.setIcon(this._iconMappings[s]);
	},

	/**
	* @private
	*/
	down: function(sender, event) {
		if (this.disabled) {
			return;
		}

		this.downTime = dev.bench();
		this.delta = this.initialDelta;
	},

	/**
	* @private
	*/
	hold: function(sender, event) {
		if (this.disabled) {
			return;
		}

		this.startHoldJob();
	},

	/**
	* @private
	*/
	depress: function(sender, event) {
		IconButton.prototype.depress.apply(this, arguments);
		// keydown events repeat (while mousedown/hold does not); simulate
		// hold behavior with mouse by catching the second keydown event
		if (event.keyCode === 13) {
			if (!this.downCount) {
				this.down();
				this.downCount = 1;
			} else {
				this.downCount++;
			}
			if (this.downCount == 2) {
				this.hold();
			}
		}
	},

	/**
	* @private
	*/
	undepress: function(sender, event) {
		IconButton.prototype.undepress.apply(this, arguments);
		this.downCount = 0;
		this.endHold(sender, event);
	},

	/**
	* @private
	*/
	endHold: function(sender, event) {
		if (!this.downTime) {
			return;
		}

		this.stopHoldJob();
		this.sendPaginateEvent();
		this.downTime = null;
	},

	/**
	* @fires moon.PagingControl#onPaginateScroll
	* @private
	*/
	startHoldJob: function() {
		this.stopHoldJob();

		var t0 = dev.bench(),
			t = 0
		;

		var fn = this.bindSafely(function() {
			this.job = animation.requestAnimationFrame(fn);

			t = (dev.bench() - t0)/1000;
			this.delta = Math.min(this.maxDelta, this.delta + (0.1 * Math.pow(t, 1.1)));

			this.doPaginateScroll({scrollDelta: this.delta});
		});

		this.job = animation.requestAnimationFrame(fn);
	},

	/**
	* @private
	*/
	stopHoldJob: function() {
		this.job = animation.cancelRequestAnimationFrame(this.job);
	},

	/**
	* @fires moon.PagingControl#onPaginate
	* @private
	*/
	sendPaginateEvent: function() {
		var tapThreshold = 200,
			timeElapsed = dev.bench() - this.downTime,
			delta = (timeElapsed <= tapThreshold) ? this.tapDelta : this.delta;

		this.doPaginate({scrollDelta: delta});
	},

	/**
	* Overrides default focused handling to make sure scroller doesn't scroll to
	* this button.
	*
	* @private
	*/
	noop: function() { return true; }
});<commit_msg>fix utils reference in PagingControl<commit_after>require('moonstone');

var
	kind = require('enyo/kind'),
	utils = require('enyo/utils'),
	animation = require('enyo/animation');

var
	Spotlight = require('spotlight');

var
	IconButton = require('../IconButton');

/**
* Fires when page boundary is reached.
*
* @event moon.PagingControl#onPaginate
* @type {Object}
* @property {Number} scrollDelta - The distance of the scroll.
* @public
*/

/**
* Fires when we've determined how large the bounceback effect should be.
*
* @event moon.PagingControl#onPaginateScroll
* @type {Object}
* @property {Number} scrollDelta - The magnitude of the scroll bounceback.
* @public
*/

/**
* {@link moon.PagingControl} is a paging control button derived from
* {@link moon.IconButton}. This control is not intended for use outside of
* {@link moon.Scroller}.
*
* @class moon.PagingControl
* @extends moon.IconButton
* @ui
* @public
*/
module.exports = kind(
	/** @lends moon.PagingControl.prototype */ {

	/**
	* @private
	*/
	name: 'moon.PagingControl',

	/**
	* @private
	*/
	kind: IconButton,

	/**
	* @private
	*/
	classes: 'moon-paging-button no-background',

	/**
	* @private
	*/
	spotlight: true,

	/**
	* @private
	* @lends moon.PagingControl.prototype
	*/
	published: {
		/**
		* The side of the control where the button will be.
		*
		* Supported values are `'top'`, `'right'`, `'bottom'`, and `'left'`.
		*
		* @type {String}
		* @default null
		* @public
		*/
		side: null
	},

	/**
	* @private
	*/
	noBackground: true,

	/**
	* @private
	*/
	handlers: {
		onSpotlightFocused: 'noop',
		onSpotlightKeyDown: 'depress',
		onSpotlightKeyUp: 'undepress',
		ondown: 'down',
		onup: 'endHold',
		onleave: 'endHold',
		onhold: 'hold',
		onActivate: 'noop'
	},

	/**
	* @private
	*/
	events: {
		/**
		* {@link moon.PagingControl#onPaginate}
		*/
		onPaginate: '',

		/**
		* {@link moon.PagingControl#onPaginateScroll}
		*/
		onPaginateScroll: ''
	},

	/**
	* @private
	*/
	downTime: 0,

	/**
	* @private
	*/
	initialDelta: 2.5,

	/**
	* @private
	*/
	delta: 0,

	/**
	* @private
	*/
	maxDelta: 45,

	/**
	* @private
	*/
	tapDelta: 15,

	/**
	* @private
	*/
	bumpDeltaMultiplier: 3,

	/**
	* @private
	*/
	create: function() {
		IconButton.prototype.create.apply(this, arguments);
		this.sideChanged();
	},

	/**
	* Stops scrolling animation and triggers
	* [onPaginate]{@link moon.PagingControl#onPaginate} event with a delta
	* value for the bounceback effect.
	*
	* @fires moon.PagingControl#onPaginate
	* @public
	*/
	hitBoundary: function() {
		this.stopHoldJob();
		this.downTime = null;
		this.doPaginate({scrollDelta: this.delta * this.bumpDeltaMultiplier});
		Spotlight.Accelerator.cancel();
	},

	/**
	* @private
	*/
	_iconMappings: {
		'top': 'arrowlargeup',
		'bottom': 'arrowlargedown',
		'left': 'arrowlargeleft',
		'right': 'arrowlargeright'
	},

	/**
	* Set this control's CSS class based on its [side]{@link moon.PagingControl#side}
	* value.
	*
	* @private
	*/
	sideChanged: function(old) {
		var s = this.side;
		if(old) {
			this.removeClass(old);
		}
		this.addClass(s);
		this.setIcon(this._iconMappings[s]);
	},

	/**
	* @private
	*/
	down: function(sender, event) {
		if (this.disabled) {
			return;
		}

		this.downTime = utils.perfNow();
		this.delta = this.initialDelta;
	},

	/**
	* @private
	*/
	hold: function(sender, event) {
		if (this.disabled) {
			return;
		}

		this.startHoldJob();
	},

	/**
	* @private
	*/
	depress: function(sender, event) {
		IconButton.prototype.depress.apply(this, arguments);
		// keydown events repeat (while mousedown/hold does not); simulate
		// hold behavior with mouse by catching the second keydown event
		if (event.keyCode === 13) {
			if (!this.downCount) {
				this.down();
				this.downCount = 1;
			} else {
				this.downCount++;
			}
			if (this.downCount == 2) {
				this.hold();
			}
		}
	},

	/**
	* @private
	*/
	undepress: function(sender, event) {
		IconButton.prototype.undepress.apply(this, arguments);
		this.downCount = 0;
		this.endHold(sender, event);
	},

	/**
	* @private
	*/
	endHold: function(sender, event) {
		if (!this.downTime) {
			return;
		}

		this.stopHoldJob();
		this.sendPaginateEvent();
		this.downTime = null;
	},

	/**
	* @fires moon.PagingControl#onPaginateScroll
	* @private
	*/
	startHoldJob: function() {
		this.stopHoldJob();

		var t0 = utils.perfNow(),
			t = 0
		;

		var fn = this.bindSafely(function() {
			this.job = animation.requestAnimationFrame(fn);

			t = (utils.perfNow() - t0)/1000;
			this.delta = Math.min(this.maxDelta, this.delta + (0.1 * Math.pow(t, 1.1)));

			this.doPaginateScroll({scrollDelta: this.delta});
		});

		this.job = animation.requestAnimationFrame(fn);
	},

	/**
	* @private
	*/
	stopHoldJob: function() {
		this.job = animation.cancelRequestAnimationFrame(this.job);
	},

	/**
	* @fires moon.PagingControl#onPaginate
	* @private
	*/
	sendPaginateEvent: function() {
		var tapThreshold = 200,
			timeElapsed = utils.perfNow() - this.downTime,
			delta = (timeElapsed <= tapThreshold) ? this.tapDelta : this.delta;

		this.doPaginate({scrollDelta: delta});
	},

	/**
	* Overrides default focused handling to make sure scroller doesn't scroll to
	* this button.
	*
	* @private
	*/
	noop: function() { return true; }
});<|endoftext|>


<commit_before>
'use strict';

if (typeof simpleboard === 'undefined')
    var simpleboard = require('simpleboard');

var simplechess = (function () {
    var Color = { White: 1, Black: 2 };
    var Piece = { King: 1, Queen: 2, Rook: 3, Bishop: 4, Knight: 5, Pawn: 6 };

    function Game(board) {
        if (!board)
            board = getInitialBoard();

        this.getPositions = function () {
            return board.getPositions();
        };

        this.getSquare = function (x, y) {
            return board.getContent(x, y);
        };

        this.getBoard = function () { return board; }
    }

    Game.prototype.getMoves = function (color) {
        var positions = this.getPositions();
        var n = positions.length;
        var moves = [];
        var board = this.getBoard();

        for (var k = 0; k < n; k++) {
            var position = positions[k];
            if (position.content.color === color)
                moves = moves.concat(getPieceMoves(board, position));
        }

        return moves;
    };

    function getPieceMoves(board, position) {
        if (position.content.piece === Piece.Rook)
            return getRookMoves(board, position.x, position.y, position.content.color);
        if (position.content.piece === Piece.Bishop)
            return getBishopMoves(board, position.x, position.y, position.content.color);
        if (position.content.piece === Piece.Queen)
            return getQueenMoves(board, position.x, position.y, position.content.color);
        if (position.content.piece === Piece.King)
            return getKingMoves(board, position.x, position.y, position.content.color);
        if (position.content.piece === Piece.Knight)
            return getKnightMoves(board, position.x, position.y, position.content.color);
        if (position.content.piece === Piece.Pawn)
            return getPawnMoves(board, position.x, position.y, position.content.color);
    }

    function getRookMoves(board, x, y, color) {
        var moves = [];
        var width = board.getWidth();
        var height = board.getHeight();

        for (var k = x + 1; k < width; k++)
            if (!addMove(board, moves, x, y, k, y, color))
                break;

        for (var k = x - 1; k >= 0; k--)
            if (!addMove(board, moves, x, y, k, y, color))
                break;

        for (var k = y + 1; k < height; k++)
            if (!addMove(board, moves, x, y, x, k, color))
                break;

        for (var k = y - 1; k >= 0; k--)
            if (!addMove(board, moves, x, y, x, k, color))
                break;

        return moves;
    }

    function getBishopMoves(board, x, y, color) {
        var moves = [];
        var width = board.getWidth();
        var height = board.getHeight();

        for (var k = 1; x + k < width && y + k < height; k++)
            if (!addMove(board, moves, x, y, x + k, y + k, color))
                break;

        for (var k = 1; x - k >= 0 && y - k >= 0; k++)
            if (!addMove(board, moves, x, y, x - k, y - k, color))
                break;

        for (var k = 1; x + k < width && y - k >= 0; k++)
            if (!addMove(board, moves, x, y, x + k, y - k, color))
                break;

        for (var k = 1; x - k >= 0 && y + k < height; k++)
            if (!addMove(board, moves, x, y, x - k, y + k, color))
                break;

        return moves;
    }

    function getQueenMoves(board, x, y, color) {
        return getBishopMoves(board, x, y, color).concat(getRookMoves(board, x, y, color));
    }

    function getKingMoves(board, x, y, color) {
        var moves = [];
        var width = board.getWidth();
        var height = board.getHeight();

        for (var k = -1; k <= 1; k++)
            for (var j = -1; j <= 1; j++)
                if ((k || j) && x + k >= 0 && x + k < width && y + j >= 0 && y + j < height)
                    moves.push({ x1: x, y1: y, x2: x + k, y2: y + j });

        return moves;
    }

    function getPawnMoves(board, x, y, color) {
        var moves = [];
        var width = board.getWidth();
        var height = board.getHeight();
        var deltay = color === Color.White ? 1 : -1;
        var y2 = y + deltay;

        if (y2 >= height || y2 < 0)
            return moves;

        if (board.getContent(x, y2) === null) {
            moves.push({ x1: x, y1: y, x2: x, y2: y2 });
            if ((color === Color.White && y === 1) || (color === Color.Black && y === height - 2)) {
                var y3 = y2 + deltay;
                if (board.getContent(x, y3) === null)
                    moves.push({ x1: x, y1: y, x2: x, y2: y3 });
            }
        }

        var content;

        if (x - 1 >= 0) {
            content = board.getContent(x - 1, y2);
            if (content !== null && content.color !== color)
                moves.push({ x1: x, y1: y, x2: x - 1, y2: y2 });
        }

        if (x + 1 < width) {
            content = board.getContent(x + 1, y2);
            if (content !== null && content.color !== color)
                moves.push({ x1: x, y1: y, x2: x + 1, y2: y2 });
        }

        return moves;
    }

    function getKnightMoves(board, x, y, color) {
        var moves = [];
        var width = board.getWidth();
        var height = board.getHeight();

        addValidMove(width, height, moves, x, y, x - 1, y - 2);
        addValidMove(width, height, moves, x, y, x - 1, y + 2);
        addValidMove(width, height, moves, x, y, x + 1, y - 2);
        addValidMove(width, height, moves, x, y, x + 1, y + 2);
        addValidMove(width, height, moves, x, y, x - 2, y - 1);
        addValidMove(width, height, moves, x, y, x - 2, y + 1);
        addValidMove(width, height, moves, x, y, x + 2, y - 1);
        addValidMove(width, height, moves, x, y, x + 2, y + 1);

        return moves;
    }

    function addValidMove(width, height, moves, x1, y1, x2, y2) {
        if (x2 >= 0 && x2 < width && y2 >= 0 && y2 < height)
            moves.push({ x1: x1, y1: y1, x2: x2, y2: y2 });
    }

    function addMove(board, moves, x1, y1, x2, y2, color) {
        var content = board.getContent(x2, y2);

        if (content === null) {
            moves.push({ x1: x1, y1: y1, x2: x2, y2: y2 });
            return true;
        }

        if (content.color === color)
            return false;

        moves.push({ x1: x1, y1: y1, x2: x2, y2: y2 });
        return false;
    }

    function getInitialBoard() {
        var board = simpleboard.createBoard(8, 8);

        putSymmetricPiece(board, 0, 0, Piece.Rook);
        putSymmetricPiece(board, 1, 0, Piece.Knight);
        putSymmetricPiece(board, 2, 0, Piece.Bishop);

        for (var k = 0; k < 4; k++)
            putSymmetricPiece(board, k, 1, Piece.Pawn);

        board.putContent(3, 0, { color: Color.White, piece: Piece.Queen });
        board.putContent(4, 0, { color: Color.White, piece: Piece.King });
        board.putContent(3, 7, { color: Color.Black, piece: Piece.Queen });
        board.putContent(4, 7, { color: Color.Black, piece: Piece.King });

        return board;
    }

    function putSymmetricPiece(board, x, y, piece) {
        board.putContent(x, y, { color: Color.White, piece: piece });
        board.putContent(8-x-1, y, { color: Color.White, piece: piece });
        board.putContent(x, 8-y-1, { color: Color.Black, piece: piece });
        board.putContent(8-x-1, 8-y-1, { color: Color.Black, piece: piece });
    }

    function createBoard() {
        return simpleboard.createBoard(8, 8);
    }

    var result = {
        createBoard: createBoard,
        createGame: function (board) {
            return new Game(board);
        }
    };

    for (var n in Color)
        result[n] = Color[n];
    for (var n in Piece)
        result[n] = Piece[n];

    return result;
})();

if (typeof window === 'undefined') {
	module.exports = simplechess;
}
<commit_msg>Refactor getMoves<commit_after>
'use strict';

if (typeof simpleboard === 'undefined')
    var simpleboard = require('simpleboard');

var simplechess = (function () {
    var Color = { White: 1, Black: 2 };
    var Piece = { King: 1, Queen: 2, Rook: 3, Bishop: 4, Knight: 5, Pawn: 6 };

    function Game(board) {
        if (!board)
            board = getInitialBoard();

        this.getPositions = function () {
            return board.getPositions();
        };

        this.getSquare = function (x, y) {
            return board.getContent(x, y);
        };

        this.getMoves = function (color) {
            var positions = this.getPositions();
            var n = positions.length;
            var moves = [];

            for (var k = 0; k < n; k++) {
                var position = positions[k];
                if (position.content.color === color)
                    moves = moves.concat(getPieceMoves(board, position));
            }

            return moves;
        }
    }

    function getPieceMoves(board, position) {
        if (position.content.piece === Piece.Rook)
            return getRookMoves(board, position.x, position.y, position.content.color);
        if (position.content.piece === Piece.Bishop)
            return getBishopMoves(board, position.x, position.y, position.content.color);
        if (position.content.piece === Piece.Queen)
            return getQueenMoves(board, position.x, position.y, position.content.color);
        if (position.content.piece === Piece.King)
            return getKingMoves(board, position.x, position.y, position.content.color);
        if (position.content.piece === Piece.Knight)
            return getKnightMoves(board, position.x, position.y, position.content.color);
        if (position.content.piece === Piece.Pawn)
            return getPawnMoves(board, position.x, position.y, position.content.color);
    }

    function getRookMoves(board, x, y, color) {
        var moves = [];
        var width = board.getWidth();
        var height = board.getHeight();

        for (var k = x + 1; k < width; k++)
            if (!addMove(board, moves, x, y, k, y, color))
                break;

        for (var k = x - 1; k >= 0; k--)
            if (!addMove(board, moves, x, y, k, y, color))
                break;

        for (var k = y + 1; k < height; k++)
            if (!addMove(board, moves, x, y, x, k, color))
                break;

        for (var k = y - 1; k >= 0; k--)
            if (!addMove(board, moves, x, y, x, k, color))
                break;

        return moves;
    }

    function getBishopMoves(board, x, y, color) {
        var moves = [];
        var width = board.getWidth();
        var height = board.getHeight();

        for (var k = 1; x + k < width && y + k < height; k++)
            if (!addMove(board, moves, x, y, x + k, y + k, color))
                break;

        for (var k = 1; x - k >= 0 && y - k >= 0; k++)
            if (!addMove(board, moves, x, y, x - k, y - k, color))
                break;

        for (var k = 1; x + k < width && y - k >= 0; k++)
            if (!addMove(board, moves, x, y, x + k, y - k, color))
                break;

        for (var k = 1; x - k >= 0 && y + k < height; k++)
            if (!addMove(board, moves, x, y, x - k, y + k, color))
                break;

        return moves;
    }

    function getQueenMoves(board, x, y, color) {
        return getBishopMoves(board, x, y, color).concat(getRookMoves(board, x, y, color));
    }

    function getKingMoves(board, x, y, color) {
        var moves = [];
        var width = board.getWidth();
        var height = board.getHeight();

        for (var k = -1; k <= 1; k++)
            for (var j = -1; j <= 1; j++)
                if ((k || j) && x + k >= 0 && x + k < width && y + j >= 0 && y + j < height)
                    moves.push({ x1: x, y1: y, x2: x + k, y2: y + j });

        return moves;
    }

    function getPawnMoves(board, x, y, color) {
        var moves = [];
        var width = board.getWidth();
        var height = board.getHeight();
        var deltay = color === Color.White ? 1 : -1;
        var y2 = y + deltay;

        if (y2 >= height || y2 < 0)
            return moves;

        if (board.getContent(x, y2) === null) {
            moves.push({ x1: x, y1: y, x2: x, y2: y2 });
            if ((color === Color.White && y === 1) || (color === Color.Black && y === height - 2)) {
                var y3 = y2 + deltay;
                if (board.getContent(x, y3) === null)
                    moves.push({ x1: x, y1: y, x2: x, y2: y3 });
            }
        }

        var content;

        if (x - 1 >= 0) {
            content = board.getContent(x - 1, y2);
            if (content !== null && content.color !== color)
                moves.push({ x1: x, y1: y, x2: x - 1, y2: y2 });
        }

        if (x + 1 < width) {
            content = board.getContent(x + 1, y2);
            if (content !== null && content.color !== color)
                moves.push({ x1: x, y1: y, x2: x + 1, y2: y2 });
        }

        return moves;
    }

    function getKnightMoves(board, x, y, color) {
        var moves = [];
        var width = board.getWidth();
        var height = board.getHeight();

        addValidMove(width, height, moves, x, y, x - 1, y - 2);
        addValidMove(width, height, moves, x, y, x - 1, y + 2);
        addValidMove(width, height, moves, x, y, x + 1, y - 2);
        addValidMove(width, height, moves, x, y, x + 1, y + 2);
        addValidMove(width, height, moves, x, y, x - 2, y - 1);
        addValidMove(width, height, moves, x, y, x - 2, y + 1);
        addValidMove(width, height, moves, x, y, x + 2, y - 1);
        addValidMove(width, height, moves, x, y, x + 2, y + 1);

        return moves;
    }

    function addValidMove(width, height, moves, x1, y1, x2, y2) {
        if (x2 >= 0 && x2 < width && y2 >= 0 && y2 < height)
            moves.push({ x1: x1, y1: y1, x2: x2, y2: y2 });
    }

    function addMove(board, moves, x1, y1, x2, y2, color) {
        var content = board.getContent(x2, y2);

        if (content === null) {
            moves.push({ x1: x1, y1: y1, x2: x2, y2: y2 });
            return true;
        }

        if (content.color === color)
            return false;

        moves.push({ x1: x1, y1: y1, x2: x2, y2: y2 });
        return false;
    }

    function getInitialBoard() {
        var board = simpleboard.createBoard(8, 8);

        putSymmetricPiece(board, 0, 0, Piece.Rook);
        putSymmetricPiece(board, 1, 0, Piece.Knight);
        putSymmetricPiece(board, 2, 0, Piece.Bishop);

        for (var k = 0; k < 4; k++)
            putSymmetricPiece(board, k, 1, Piece.Pawn);

        board.putContent(3, 0, { color: Color.White, piece: Piece.Queen });
        board.putContent(4, 0, { color: Color.White, piece: Piece.King });
        board.putContent(3, 7, { color: Color.Black, piece: Piece.Queen });
        board.putContent(4, 7, { color: Color.Black, piece: Piece.King });

        return board;
    }

    function putSymmetricPiece(board, x, y, piece) {
        board.putContent(x, y, { color: Color.White, piece: piece });
        board.putContent(8-x-1, y, { color: Color.White, piece: piece });
        board.putContent(x, 8-y-1, { color: Color.Black, piece: piece });
        board.putContent(8-x-1, 8-y-1, { color: Color.Black, piece: piece });
    }

    function createBoard() {
        return simpleboard.createBoard(8, 8);
    }

    var result = {
        createBoard: createBoard,
        createGame: function (board) {
            return new Game(board);
        }
    };

    for (var n in Color)
        result[n] = Color[n];
    for (var n in Piece)
        result[n] = Piece[n];

    return result;
})();

if (typeof window === 'undefined') {
	module.exports = simplechess;
}
<|endoftext|>


<commit_before>"use strict";

var siteUtils = require("../site-utils"),
    logger = require("../logger")();

function EBagsSite(uri) {

    // error check to make sure this is a valid uri for eBags
    if (!EBagsSite.isSite(uri)) {
        throw new Error("invalid uri for eBags: " + uri);
    }

    this._uri = uri;

    this.getURIForPageData = function() {
        return this._uri;
    };

    this.isJSON = function() {
        return false;
    };

    this.findPriceOnPage = function($) {
        var selectors, price;

        // the various ways we can find the price on an ebags page
        selectors = [
            "#divPricing h2[itemprop='price']"
        ];

        // find the price on the page
        price = siteUtils.findContentOnPage($, selectors);

        // were we successful?
        if (!price) {
            logger.error($("body").text().trim());
            logger.error("price not found on eBags page, uri: " + this._uri);
            return -1;
        }

        // get the number value (remove dollar sign)
        price = +(price.slice(1));
        logger.log("price: " + price);

        return price;
    };

    this.findCategoryOnPage = function($) {
        var category;

        // we're assuming only luggage on ebags.com
        category = siteUtils.categories.LUGGAGE;

        logger.log("category: " + category);

        return category;
    };

    this.findNameOnPage = function($, category) {
        var name, selectors;

        selectors = [
            "#productCon span[itemprop='name']"
        ];

        // use the selectors to find the name on the page
        name = siteUtils.findContentOnPage($, selectors);

        if (!name) {
            logger.error("name not found on eBags page, uri: " + this._uri);
            return null;
        }

        logger.log("name: " + name);

        return name;
    };
}

EBagsSite.isSite = function(uri) {
    if (uri.indexOf("ebags.com") > -1) {
        return true;
    } else {
        return false;
    }
};

module.exports = EBagsSite;
<commit_msg>Fix eBags price selector<commit_after>"use strict";

var siteUtils = require("../site-utils"),
    logger = require("../logger")();

function EBagsSite(uri) {

    // error check to make sure this is a valid uri for eBags
    if (!EBagsSite.isSite(uri)) {
        throw new Error("invalid uri for eBags: " + uri);
    }

    this._uri = uri;

    this.getURIForPageData = function() {
        return this._uri;
    };

    this.isJSON = function() {
        return false;
    };

    this.findPriceOnPage = function($) {
        var selectors, price;

        // the various ways we can find the price on an ebags page
        selectors = [
            "#divPricing *[itemprop='price']"
        ];

        // find the price on the page
        price = siteUtils.findContentOnPage($, selectors);

        // were we successful?
        if (!price) {
            logger.error($("body").text().trim());
            logger.error("price not found on eBags page, uri: " + this._uri);
            return -1;
        }

        // get the number value (remove dollar sign)
        price = +(price.slice(1));
        logger.log("price: " + price);

        return price;
    };

    this.findCategoryOnPage = function($) {
        var category;

        // we're assuming only luggage on ebags.com
        category = siteUtils.categories.LUGGAGE;

        logger.log("category: " + category);

        return category;
    };

    this.findNameOnPage = function($, category) {
        var name, selectors;

        selectors = [
            "#productCon span[itemprop='name']"
        ];

        // use the selectors to find the name on the page
        name = siteUtils.findContentOnPage($, selectors);

        if (!name) {
            logger.error("name not found on eBags page, uri: " + this._uri);
            return null;
        }

        logger.log("name: " + name);

        return name;
    };
}

EBagsSite.isSite = function(uri) {
    if (uri.indexOf("ebags.com") > -1) {
        return true;
    } else {
        return false;
    }
};

module.exports = EBagsSite;
<|endoftext|>


<commit_before>'use strict';

var request = require('request');

// The class itself
// Stolen from https://github.com/kkamkou/node-akamai-http-api
var solus = Object.create(null, {
        base_config: {
            writable: false,
            value: {
                apiId: null,
                apiKey: null,
                host: null,
                port: 80,
                ssl: false,
                verbose: false
            }
        },
        config: {
            writable: true,
            value: {}
        },
    });

// The string formatter
// Stolen from http://stackoverflow.com/a/4673436
solus.strFormat = function (format) {
    var args = Array.prototype.slice.call(arguments, 1);
    return format.replace(/\{(\d+)\}/g, function (match, number) {
        return args[number] === undefined ? args[number] : match;
    });
};

// Stolen from http://stackoverflow.com/a/1714899
solus.serializeParams = function (obj, prefix) {
    var prop, k, v, str = [];
    for (prop in obj) {
        if (obj.hasOwnProperty(prop)) {
            k = prefix ? prefix + "[" + prop + "]" : prop;
            v = obj[prop];

            if (typeof v === 'object') {
                str.push(solus.serializeParams(v, k));
            } else {
                str.push(encodeURIComponent(k) + "=" + encodeURIComponent(v));
            }
        }
    }
    return str.join("&");
};

solus.generateHostUrl = function (params) {
    if (solus.config.host === null) {
        // "Exception" throwing
        // Stolen from http://stackoverflow.com/a/1137209
        throw {
            name:     "ConfigError",
            level:    "FATAL",
            message:  "No 'host' value provided.",
            toString: function () {return this.name + ": " + this.message; }
        };
    }

    var schema = solus.config.ssl ? 'https' : 'http',
        suffix = 'api/admin/command.php',
        host = solus.config.host,
        port = solus.config.port;

    return solus.strFormat('{0}://{1}:{2}/{3}?{4}',
                           schema, host, port, suffix,
                           solus.serializeParams(params));
};

solus.sQuery = function (params) {
    // Set Query defaults
    params.rdtype = 'json';
    params.id = solus.config.apiId;
    params.key = solus.config.apiKey;

    // execute response
    return request.get(solus.generateHostUrl(params));
};

solus.setConfig = function (conf) {
    var key;

    conf = conf === undefined ? conf : {};

    for (key in this.base_config) {
        if (this.base_config.hasOwnProperty(key)) {
            this.config[key] = this.base_config[key];
        }
    }
    for (key in conf) {
        if (conf.hasOwnProperty(key)) {
            this.config[key] = conf[key];
        }
    }

    return this;
};
<commit_msg>Code cleanup<commit_after>'use strict';

var request = require('request');

// Stolen from https://github.com/kkamkou/node-akamai-http-api
var solus = Object.create(null, {
        base_config: {
            writable: false,
            value: {
                apiId: null,
                apiKey: null,
                host: null,
                port: 80,
                ssl: false,
                verbose: false
            }
        },
        config: {
            writable: true,
            value: {}
        },
    });

// Stolen from http://stackoverflow.com/a/4673436
solus.strFormat = function (format) {
    var args = Array.prototype.slice.call(arguments, 1);
    return format.replace(/\{(\d+)\}/g, function (match, number) {
        return args[number] === undefined ? args[number] : match;
    });
};

// Stolen from http://stackoverflow.com/a/1714899
solus.serializeParams = function (obj, prefix) {
    var prop, k, v, str = [];
    for (prop in obj) {
        if (obj.hasOwnProperty(prop)) {
            k = prefix ? prefix + "[" + prop + "]" : prop;
            v = obj[prop];

            if (typeof v === 'object') {
                str.push(solus.serializeParams(v, k));
            } else {
                str.push(encodeURIComponent(k) + "=" + encodeURIComponent(v));
            }
        }
    }
    return str.join("&");
};

solus.generateHostUrl = function (params) {
    if (solus.config.host === null) {
        // Stolen from http://stackoverflow.com/a/1137209
        throw {
            name:     "ConfigError",
            level:    "FATAL",
            message:  "No 'host' value provided.",
            toString: function () {return this.name + ": " + this.message; }
        };
    }

    var schema = solus.config.ssl ? 'https' : 'http',
        suffix = 'api/admin/command.php',
        host = solus.config.host,
        port = solus.config.port;

    return solus.strFormat('{0}://{1}:{2}/{3}?{4}',
                           schema, host, port, suffix,
                           solus.serializeParams(params));
};

solus.setConfig = function (conf) {
    var key;

    conf = conf === undefined ? conf : {};

    for (key in this.base_config) {
        if (this.base_config.hasOwnProperty(key)) {
            this.config[key] = this.base_config[key];
        }
    }
    for (key in conf) {
        if (conf.hasOwnProperty(key)) {
            this.config[key] = conf[key];
        }
    }

    return this;
};

solus.sQuery = function (params) {
    // Set Query defaults
    params.rdtype = 'json';
    params.id = solus.config.apiId;
    params.key = solus.config.apiKey;

    // execute response
    return request.get(solus.generateHostUrl(params));
};
<|endoftext|>


<commit_before>'use babel';

import clangExpand from './atom-clang-expand';

export default class SourceView {
  constructor(result, onDeath) {
    this.onDeath = onDeath;
    this.element = document.createElement('div');
    this.element.classList.add('clang-expand-source-view-container');

    const lines = result.text.split('\n');
    const code = document.createElement('div');
    code.classList.add('clang-expand-source-view-code');
    code.innerHTML = lines.map(line => `<span>${line}\n</span>`).join('\n');
    this.element.appendChild(code);

    if (lines.length >= 10) {
      code.classList.add('tens');
    }

    const link = document.createElement('div');
    link.classList.add('clang-expand-source-view-info');
    const file = atom.project.getDirectories()[0].relativize(result.location.file);
    link.innerHTML = `<a>${file}:${result.location.line}:${result.location.column}</a>`;
    this.element.appendChild(link);

    let self = this;
    this.element.onclick = () => {
      clangExpand.goTo(result.location);
      this.destroy();
    };

    this.element.onmouseleave = () => self.destroy();
    document.body.onkeydown = () => self.destroy();
  }

  destroy() {
    this.onDeath();
    this.element.remove();
  }

  getElement() {
    return this.element;
  }

}
<commit_msg>Documented SourceView<commit_after>'use babel';

import clangExpand from './atom-clang-expand';

/**
 * Widget displaying a snippet of source code and the file where that code
 * originates from.
 *
 * The widget dies when the user's mouse moves away from the widget (it is
 * initially on it) or the user presses any key.
 */
export default class SourceView {

  /**
   * Constructor, taking the result of clang-expand and a callback to invoke
   * when the widget is destroyed.
   */
  constructor(result, onDeath) {
    this.onDeath = onDeath;
    this.element = document.createElement('div');
    this.element.classList.add('clang-expand-source-view-container');

    const lines = result.text.split('\n');
    const code = document.createElement('div');
    code.classList.add('clang-expand-source-view-code');
    code.innerHTML = lines.map(line => `<span>${line}\n</span>`).join('\n');
    this.element.appendChild(code);

    if (lines.length >= 10) {
      code.classList.add('tens');
    }

    const link = document.createElement('div');
    link.classList.add('clang-expand-source-view-info');
    const file = atom.project.getDirectories()[0].relativize(result.location.file);
    link.innerHTML = `<a>${file}:${result.location.line}:${result.location.column}</a>`;
    this.element.appendChild(link);

    let self = this;
    this.element.onclick = () => {
      clangExpand.goTo(result.location);
      this.destroy();
    };

    this.element.onmouseleave = () => self.destroy();
    document.body.onkeydown = () => self.destroy();
  }

  /**
   * Kills the view, removing it from the DOM and invoking the `onDeath`
   * callback passed in the constructor.
   */
  destroy() {
    this.onDeath();
    this.element.remove();
  }

  /**
   * Returns the element of the source view.
   */
  getElement() {
    return this.element;
  }
}
<|endoftext|>


<commit_before>/*jslint es5: true */

/*
 * #%L
 * %%
 * Copyright (C) 2011 - 2016 BMW Car IT GmbH
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

define(
        "joynr/messaging/websocket/SharedWebSocket",
        [
            "global/Promise",
            "global/WebSocket",
            "joynr/util/Util",
            "joynr/util/JSONSerializer",
            "joynr/util/LongTimer",
            "joynr/system/LoggerFactory"
        ],
        function(Promise, WebSocket, Util, JSONSerializer, LongTimer, LoggerFactory) {
            var log = LoggerFactory.getLogger("joynr.messaging.websocket.SharedWebSocket");
            /**
             * @param address
             * @param {WebSocketAddress}
             *            address to which messages are sent on the clustercontroller.
             * @returns {String} a url
             */
            function webSocketAddressToUrl(address) {
                var url = address.protocol + "://" + address.host + ":" + address.port;
                if (address.path) {
                    url += address.path;
                }
                return url;
            }

            /**
             * @param {WebSocket}
             *            websocket to use for the initialization
             * @param {String}
             *            localAddress address used by the cluster controller to contact this
             *            libjoynr
             */
            function initializeConnection(websocket, localAddress) {
                websocket.send(JSON.stringify(localAddress));
            }

            /**
             * @param {WebSocket}
             *            websocket to use for sending messages
             * @param {Array}
             *            queuedMessages
             */
            function sendQueuedMessages(websocket, queuedMessages) {
                var queued;
                while (queuedMessages.length) {
                    queued = queuedMessages.shift();
                    try {
                        websocket.send(JSONSerializer.stringify(queued.message));
                        queued.resolve();
                        // Error is thrown if the socket is no longer open
                    } catch (e) {
                        // so add the message back to the front of the queue
                        queuedMessages.unshift(queued);
                        throw e;
                    }
                }
            }

            function sendMessage(websocket, joynrMessage, queuedMessages) {
                return new Promise(function(resolve, reject){
                    if (websocket.readyState === WebSocket.OPEN) {
                        try {
                            websocket.send(JSONSerializer.stringify(joynrMessage));
                            resolve();
                            // Error is thrown if the socket is no longer open, so requeue to the front
                        } catch (e) {
                            // add the message back to the front of the queue
                            queuedMessages.unshift({
                                message : joynrMessage,
                                resolve : resolve
                            });
                            throw e;
                        }
                    } else {
                        // push new messages onto the back of the queue
                        queuedMessages.push({
                            message : joynrMessage,
                            resolve : resolve
                        });
                    }
                });
            }

            /**
             * @name SharedWebSocket
             * @constructor
             * @param {Object}
             *            settings
             * @param {WebSocketClientAddress}
             *            settings.localAddress address used by the websocket server to contact this
             *            client. This address is used in in the init phase on the websocket, and
             *            then registered with the message router on the remote side
             * @param {WebSocketAddress}
             *            settings.remoteAddress to which messages are sent on the websocket server.
             * @param {Object} settings.provisioning
             * @param {Number} settings.provisioning.reconnectSleepTimeMs
             */
            var SharedWebSocket =
                    function SharedWebSocket(settings) {
                        Util.checkProperty(settings, "Object", "settings");
                        Util.checkProperty(
                                settings.localAddress,
                                "WebSocketClientAddress",
                                "localAddress");
                        Util.checkProperty(
                                settings.remoteAddress,
                                "WebSocketAddress",
                                "remoteAddress");

                        var websocket = null;
                        var provisioning = settings.provisioning || {};
                        var reconnectSleepTimeMs = provisioning.reconnectSleepTimeMs || 1000; // default value = 1000ms
                        var localAddress = settings.localAddress;
                        var remoteUrl = webSocketAddressToUrl(settings.remoteAddress);
                        var onmessageCallback = null;
                        var queuedMessages = [];
                        var onOpen;
                        var onError;
                        var onClose;
                        var closed = false;
                        var reconnectTimer;

                        var resetConnection = function resetConnection() {
                            reconnectTimer = undefined;
                            if (closed) {
                                return;
                            }
                            websocket = new WebSocket(remoteUrl);
                            websocket.onopen = onOpen;
                            websocket.onclose = onClose;
                            websocket.onerror = onError;
                            if (onmessageCallback !== null) {
                                websocket.onmessage = onmessageCallback;
                            }
                        };

                        onError = function onError(event) {
                            log.error("error in websocket: "
                                    + event.code
                                    + " reason: "
                                    + event.reason
                                    + ". Resetting connection.");
                            if (reconnectTimer !== undefined) {
                                LongTimer.clearTimeout(reconnectTimer);
                            }
                            reconnectTimer = LongTimer.setTimeout(resetConnection, reconnectSleepTimeMs);
                        };

                        onClose = function onClose(event) {
                            if (event.code !== SharedWebSocket.EVENT_CODE_SHUTDOWN ) {
                                log.info("connection closed unexpectedly. code: "
                                    + event.code
                                    + " reason: "
                                    + event.reason
                                    + ". Trying to reconnect...");
                                if (reconnectTimer !== undefined) {
                                    LongTimer.clearTimeout(reconnectTimer);
                                }
                                reconnectTimer = LongTimer.setTimeout(resetConnection, reconnectSleepTimeMs);
                            } else {
                                log.info("connection closed. reason: " + event.reason);
                            }
                        };

                        // send all queued messages, requeuing to the front in case of a problem
                        onOpen = function onOpen() {
                            try {
                                initializeConnection(websocket, localAddress);
                                sendQueuedMessages(websocket, queuedMessages);
                            } catch (e) {
                                resetConnection();
                            }
                        };

                        resetConnection();

                        /**
                         * @name SharedWebSocket#send
                         * @function
                         * @param {JoynrMessage}
                         *            joynrMessage the joynr message to transmit
                         */
                        this.send = function send(joynrMessage) {
                            try {
                                Util.checkProperty(joynrMessage, "JoynrMessage", "joynrMessage");
                            } catch (e) {
                                throw e;
                            }
                            return sendMessage(websocket, joynrMessage, queuedMessages).catch(function(e1) {
                                    resetConnection();
                                });
                        };

                        /**
                         * @name SharedWebSocket#close
                         * @function
                         */
                        this.close = function close() {
                            closed = true;
                            if (reconnectTimer !== undefined) {
                                LongTimer.clearTimeout(reconnectTimer);
                                reconnectTimer = undefined;
                            }
                            if (websocket !== null) {
                                websocket.close(SharedWebSocket.EVENT_CODE_SHUTDOWN, "shutdown");
                            }
                        };

                        // using the defineProperty syntax for onmessage to be able to keep
                        // the same API as WebSocket but have a setter function called when
                        // the attribute is set.
                        Object.defineProperty(this, "onmessage", {
                            set : function(newCallback) {
                                onmessageCallback = newCallback;
                                if (typeof newCallback === "function") {
                                    websocket.onmessage = newCallback;
                                } else {
                                    throw new Error(
                                            "onmessage callback must be a function, but instead was of type "
                                                + typeof newCallback);
                                }
                            },
                            get : function() {
                                return onmessageCallback;
                            },
                            enumerable : false,
                            configurable : false
                        });

                    };
            SharedWebSocket.EVENT_CODE_SHUTDOWN = 4000;
            return SharedWebSocket;
        });
<commit_msg>[JS] SharedWebSocket log error reason only if defined<commit_after>/*jslint es5: true */

/*
 * #%L
 * %%
 * Copyright (C) 2011 - 2016 BMW Car IT GmbH
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

define(
        "joynr/messaging/websocket/SharedWebSocket",
        [
            "global/Promise",
            "global/WebSocket",
            "joynr/util/Util",
            "joynr/util/JSONSerializer",
            "joynr/util/LongTimer",
            "joynr/system/LoggerFactory"
        ],
        function(Promise, WebSocket, Util, JSONSerializer, LongTimer, LoggerFactory) {
            var log = LoggerFactory.getLogger("joynr.messaging.websocket.SharedWebSocket");
            /**
             * @param address
             * @param {WebSocketAddress}
             *            address to which messages are sent on the clustercontroller.
             * @returns {String} a url
             */
            function webSocketAddressToUrl(address) {
                var url = address.protocol + "://" + address.host + ":" + address.port;
                if (address.path) {
                    url += address.path;
                }
                return url;
            }

            /**
             * @param {WebSocket}
             *            websocket to use for the initialization
             * @param {String}
             *            localAddress address used by the cluster controller to contact this
             *            libjoynr
             */
            function initializeConnection(websocket, localAddress) {
                websocket.send(JSON.stringify(localAddress));
            }

            /**
             * @param {WebSocket}
             *            websocket to use for sending messages
             * @param {Array}
             *            queuedMessages
             */
            function sendQueuedMessages(websocket, queuedMessages) {
                var queued;
                while (queuedMessages.length) {
                    queued = queuedMessages.shift();
                    try {
                        websocket.send(JSONSerializer.stringify(queued.message));
                        queued.resolve();
                        // Error is thrown if the socket is no longer open
                    } catch (e) {
                        // so add the message back to the front of the queue
                        queuedMessages.unshift(queued);
                        throw e;
                    }
                }
            }

            function sendMessage(websocket, joynrMessage, queuedMessages) {
                return new Promise(function(resolve, reject){
                    if (websocket.readyState === WebSocket.OPEN) {
                        try {
                            websocket.send(JSONSerializer.stringify(joynrMessage));
                            resolve();
                            // Error is thrown if the socket is no longer open, so requeue to the front
                        } catch (e) {
                            // add the message back to the front of the queue
                            queuedMessages.unshift({
                                message : joynrMessage,
                                resolve : resolve
                            });
                            throw e;
                        }
                    } else {
                        // push new messages onto the back of the queue
                        queuedMessages.push({
                            message : joynrMessage,
                            resolve : resolve
                        });
                    }
                });
            }

            /**
             * @name SharedWebSocket
             * @constructor
             * @param {Object}
             *            settings
             * @param {WebSocketClientAddress}
             *            settings.localAddress address used by the websocket server to contact this
             *            client. This address is used in in the init phase on the websocket, and
             *            then registered with the message router on the remote side
             * @param {WebSocketAddress}
             *            settings.remoteAddress to which messages are sent on the websocket server.
             * @param {Object} settings.provisioning
             * @param {Number} settings.provisioning.reconnectSleepTimeMs
             */
            var SharedWebSocket =
                    function SharedWebSocket(settings) {
                        Util.checkProperty(settings, "Object", "settings");
                        Util.checkProperty(
                                settings.localAddress,
                                "WebSocketClientAddress",
                                "localAddress");
                        Util.checkProperty(
                                settings.remoteAddress,
                                "WebSocketAddress",
                                "remoteAddress");

                        var websocket = null;
                        var provisioning = settings.provisioning || {};
                        var reconnectSleepTimeMs = provisioning.reconnectSleepTimeMs || 1000; // default value = 1000ms
                        var localAddress = settings.localAddress;
                        var remoteUrl = webSocketAddressToUrl(settings.remoteAddress);
                        var onmessageCallback = null;
                        var queuedMessages = [];
                        var onOpen;
                        var onError;
                        var onClose;
                        var closed = false;
                        var reconnectTimer;

                        var resetConnection = function resetConnection() {
                            reconnectTimer = undefined;
                            if (closed) {
                                return;
                            }
                            websocket = new WebSocket(remoteUrl);
                            websocket.onopen = onOpen;
                            websocket.onclose = onClose;
                            websocket.onerror = onError;
                            if (onmessageCallback !== null) {
                                websocket.onmessage = onmessageCallback;
                            }
                        };

                        onError = function onError(event) {
                            log.error("error in websocket: "
                                    + event.code
                                    + (event.reason !== undefined ? " reason: "
                                    + event.reason : "")
                                    + ". Resetting connection.");
                            if (reconnectTimer !== undefined) {
                                LongTimer.clearTimeout(reconnectTimer);
                            }
                            reconnectTimer = LongTimer.setTimeout(resetConnection, reconnectSleepTimeMs);
                        };

                        onClose = function onClose(event) {
                            if (event.code !== SharedWebSocket.EVENT_CODE_SHUTDOWN ) {
                                log.info("connection closed unexpectedly. code: "
                                    + event.code
                                    + " reason: "
                                    + event.reason
                                    + ". Trying to reconnect...");
                                if (reconnectTimer !== undefined) {
                                    LongTimer.clearTimeout(reconnectTimer);
                                }
                                reconnectTimer = LongTimer.setTimeout(resetConnection, reconnectSleepTimeMs);
                            } else {
                                log.info("connection closed. reason: " + event.reason);
                            }
                        };

                        // send all queued messages, requeuing to the front in case of a problem
                        onOpen = function onOpen() {
                            try {
                                initializeConnection(websocket, localAddress);
                                sendQueuedMessages(websocket, queuedMessages);
                            } catch (e) {
                                resetConnection();
                            }
                        };

                        resetConnection();

                        /**
                         * @name SharedWebSocket#send
                         * @function
                         * @param {JoynrMessage}
                         *            joynrMessage the joynr message to transmit
                         */
                        this.send = function send(joynrMessage) {
                            try {
                                Util.checkProperty(joynrMessage, "JoynrMessage", "joynrMessage");
                            } catch (e) {
                                throw e;
                            }
                            return sendMessage(websocket, joynrMessage, queuedMessages).catch(function(e1) {
                                    resetConnection();
                                });
                        };

                        /**
                         * @name SharedWebSocket#close
                         * @function
                         */
                        this.close = function close() {
                            closed = true;
                            if (reconnectTimer !== undefined) {
                                LongTimer.clearTimeout(reconnectTimer);
                                reconnectTimer = undefined;
                            }
                            if (websocket !== null) {
                                websocket.close(SharedWebSocket.EVENT_CODE_SHUTDOWN, "shutdown");
                            }
                        };

                        // using the defineProperty syntax for onmessage to be able to keep
                        // the same API as WebSocket but have a setter function called when
                        // the attribute is set.
                        Object.defineProperty(this, "onmessage", {
                            set : function(newCallback) {
                                onmessageCallback = newCallback;
                                if (typeof newCallback === "function") {
                                    websocket.onmessage = newCallback;
                                } else {
                                    throw new Error(
                                            "onmessage callback must be a function, but instead was of type "
                                                + typeof newCallback);
                                }
                            },
                            get : function() {
                                return onmessageCallback;
                            },
                            enumerable : false,
                            configurable : false
                        });

                    };
            SharedWebSocket.EVENT_CODE_SHUTDOWN = 4000;
            return SharedWebSocket;
        });
<|endoftext|>


<commit_before>'use strict';

const Vinyl = require('vinyl');
const vfs = require('vinyl-fs');
const sfa = require('stream-from-array');
const map = require('map-stream');
const uuid = require('uuid');
const config = require('config');
const fs = require('fs');
const path = require('path');

let adapter = '';
const builtInProps = ['uuid', '_uuid', 'field', '_field', 'type', '_type', 'rel', '_rel'];

try {
  // Need to have the require here so it can be dynamic
  adapter = require(`vinyl-${config.storage.type}`); // eslint-disable-line global-require
}
catch (e) {
  adapter = vfs;
}

class PunchcardFile extends Vinyl {
  constructor(options) {
    super(options);

    this._uuid = uuid.v4();
    this._field = '';
    this._type = '';
    this._rel = '';
  }

  get uuid() {
    return this._uuid;
  }

  get field() {
    return this._field;
  }

  set field(field) {
    if (field) {
      this._field = field;
    }
  }

  get type() {
    return this._type;
  }

  set type(type) {
    if (type) {
      this._type = type;
    }
  }

  get rel() {
    return this._type;
  }

  set rel(path) {
    if (path) {
      this._rel = path;
    }
  }

  static isCustomProp(name) {
    return super.isCustomProp(name) && builtInProps.indexOf(name) === -1;
  }
}

const mapFiles = files => {
  return files.map(file => {
    return new Promise((res, rej) => {
      fs.readFile(file.path, (err, data) => {
        if (err) {
          rej(err);
        }

        const f = new PunchcardFile({
          cwd: '/',
          base: '/',
          path: `/${file.originalFilename}`,
          contents: data,
        });

        f.field = file.fieldName;
        f.type = file.type;
        f.path = `/${f.uuid}${path.extname(file)}`;

        res(f);
      });
    });
  });
};

const punchcardStream = items => {
  return new Promise((res, rej) => {
    const files = {};

    sfa.obj(items)
      .pipe(adapter.dest(config.storage.dest, config.storage.settings))
      .pipe(map((file, cb) => {
        files[file.field] = file;
        cb(null, file);
      }))
      .on('error', e => {
        rej(e);
      })
      .on('end', () => {
        res(files);
      });
  });
};

const put = files => {
  const streams = files.map(mapFiles);

  return Promise.all(streams).then(items => {
    return punchcardStream(items);
  });
};

module.exports = put;
<commit_msg>:bug: Fix Put so it now works<commit_after>'use strict';

const Vinyl = require('vinyl');
const vfs = require('vinyl-fs');
const sfa = require('stream-from-array');
const map = require('map-stream');
const uuid = require('uuid');
const config = require('config');
const fs = require('fs');
const path = require('path');

let adapter = '';
const builtInProps = ['uuid', '_uuid', 'field', '_field', 'type', '_type', 'rel', '_rel'];

try {
  // Need to have the require here so it can be dynamic
  adapter = require(`vinyl-${config.storage.type}`); // eslint-disable-line global-require
}
catch (e) {
  adapter = vfs;
}

class PunchcardFile extends Vinyl {
  constructor(options) {
    super(options);

    this._uuid = uuid.v4();
    this._field = '';
    this._type = '';
    this._rel = '';
  }

  get uuid() {
    return this._uuid;
  }

  get field() {
    return this._field;
  }

  set field(field) {
    if (field) {
      this._field = field;
    }
  }

  get type() {
    return this._type;
  }

  set type(type) {
    if (type) {
      this._type = type;
    }
  }

  get rel() {
    return this._type;
  }

  set rel(path) {
    if (path) {
      this._rel = path;
    }
  }

  static isCustomProp(name) {
    return super.isCustomProp(name) && builtInProps.indexOf(name) === -1;
  }
}

const mapFiles = file => {
  return new Promise((res, rej) => {
    fs.readFile(file.path, (err, data) => {
      if (err) {
        rej(err);
      }

      const f = new PunchcardFile({
        cwd: '/',
        base: '/',
        path: `/${file.originalFilename}`,
        contents: data,
      });

      f.field = file.fieldName;
      f.type = file.type;
      f.path = `/${f.uuid}${path.extname(file.originalFilename)}`;
      f.rel = `${f.uuid}${path.extname(file.originalFilename)}`;

      res(f);
    });
  });
};

const punchcardStream = items => {
  return new Promise((res, rej) => {
    const files = {};

    sfa.obj(items)
      .pipe(adapter.dest(config.storage.dest, config.storage.settings))
      .pipe(map((file, cb) => {
        files[file.field] = file;
        cb(null, file);
      }))
      .on('error', e => {
        rej(e);
      })
      .on('end', () => {
        res(files);
      });
  });
};

const put = files => {
  const streams = files.map(mapFiles);

  return Promise.all(streams).then(items => {
    return punchcardStream(items);
  });
};

module.exports = put;
<|endoftext|>