<commit_before>"use strict";

var Timeout = require("../common/Timeout");
var vector = require("../common/vector");

var mouseWheelRange = 1000;
var mouseWheelDelay = 50;

function mouse($element, boundingBox, onStart, onInput, onEnd) {
    var config = {
        activated: true,
        dispose: function () {
            this.activated = false;
            $element.removeEventListener("mousedown", mousedown);
            $element.removeEventListener("mousemove", mousemove);
            $element.removeEventListener("mouseup", mouseup);
            $element.removeEventListener("mousewheel", mousewheel);
            $element.removeEventListener("wheel", wheel);
            document.body.removeEventListener("mousemove", cancelInput); // mouse left container
            document.body.removeEventListener("mouseout", mouseout); // mouse left window
        }
    };

    var isInAction = false;
    var previousPosition = vector.create();
    var currentPosition = vector.create();
    var inputVector = vector.create();

    $element.addEventListener("mousedown", mousedown);
    $element.addEventListener("mousemove", mousemove);
    $element.addEventListener("mouseup", mouseup);
    $element.addEventListener("mousewheel", mousewheel);
    $element.addEventListener("wheel", wheel);
    document.body.addEventListener("mousemove", cancelInput); // mouse left container
    document.body.addEventListener("mouseout", mouseout); // mouse left window

    function mousedown(event) {
        if (isInAction === true) {
            return;
        }

        isInAction = true;

        if (config.activated === false) {
            return;
        }

        var x = event.pageX - boundingBox.left;
        var y = event.pageY - boundingBox.top;

        event.preventDefault();

        currentPosition.setValues(x, y, currentPosition.z);
        onStart(currentPosition);
    }

    function mousemove(event) {
        if (isInAction === false || config.activated === false) {
            return;
        }

        var x = event.pageX - boundingBox.left;
        var y = event.pageY - boundingBox.top;

        event.preventDefault();
        event.stopPropagation(); // stop event to bubble to document.body, which aborts dragging

        previousPosition.set(currentPosition);
        currentPosition.setValues(x, y, currentPosition.z);
        inputVector.setDelta(currentPosition, previousPosition);
        // convert position to scale
        inputVector.z = 1;

        onInput(inputVector, currentPosition);
    }

    function mouseup(event) {
        if (isInAction === false) {
            return;
        }

        isInAction = false;
        onEnd(event);
    }

    var wheelTimeout = new Timeout(function () {
        if (isInAction === false) {
            return;
        }

        isInAction = false;
        onEnd();
    }, mouseWheelDelay);

    function mousewheel(event) {
        if (config.activated === false) {
            return;
        }

        event.preventDefault();

        var x = event.pageX - boundingBox.left;
        var y = event.pageY - boundingBox.top;
        var z = event.wheelDelta;

        if (isInAction === false) {
            isInAction = true;

            wheelTimeout.start();
            currentPosition.set(x, y, z);
            onStart(currentPosition);

        } else {

            wheelTimeout.keepAlive();
            previousPosition.set(currentPosition);
            currentPosition.set(x, y, currentPosition.z + z);
            inputVector.setDelta(currentPosition, previousPosition);
            // convert position to scale
            inputVector.z = 1 + inputVector.z / mouseWheelRange;
            onInput(inputVector, currentPosition);
        }
    }

    function wheel(event) {
        if (config.activated === false) {
            return;
        }

        event.preventDefault();

        var x = event.pageX - boundingBox.left;
        var y = event.pageY - boundingBox.top;
        var z = event.deltaY;

        // ! need offset x, inconsistent across browser. any chance to derive position without bounding box?

        if (isInAction === false) {
            isInAction = true;

            wheelTimeout.start();
            currentPosition.setValues(x, y, z);
            onStart(currentPosition);

        } else {

            wheelTimeout.keepAlive();
            previousPosition.set(currentPosition);
            currentPosition.setValues(x, y, currentPosition.z + z);
            inputVector.setDelta(currentPosition, previousPosition);
            // convert position to scale
            inputVector.z = 1 + inputVector.z / mouseWheelRange;
            onInput(inputVector, currentPosition);
        }
    }

    function cancelInput(event) {
        if (isInAction === false) {
            return;
        }

        isInAction = false;
        onEnd();
    }

    function mouseout(event) {
        event = event ? event : window.event;
        var from = event.relatedTarget || event.toElement;
        if (!from || from.nodeName === "HTML") {
            cancelInput();
        }
    }

    return config;
}

module.exports = mouse;

<commit_msg>Fix missing click event-object for mouse actions<commit_after>"use strict";

var Timeout = require("../common/Timeout");
var vector = require("../common/vector");

var mouseWheelRange = 1000;
var mouseWheelDelay = 50;

function mouse($element, boundingBox, onStart, onInput, onEnd) {
    var config = {
        activated: true,
        dispose: function () {
            this.activated = false;
            $element.removeEventListener("mousedown", mousedown);
            $element.removeEventListener("mousemove", mousemove);
            $element.removeEventListener("mouseup", mouseup);
            $element.removeEventListener("mousewheel", mousewheel);
            $element.removeEventListener("wheel", wheel);
            document.body.removeEventListener("mousemove", cancelInput); // mouse left container
            document.body.removeEventListener("mouseout", mouseout); // mouse left window
        }
    };

    var isInAction = false;
    var previousPosition = vector.create();
    var currentPosition = vector.create();
    var inputVector = vector.create();

    $element.addEventListener("mousedown", mousedown);
    $element.addEventListener("mousemove", mousemove);
    $element.addEventListener("mouseup", mouseup);
    $element.addEventListener("mousewheel", mousewheel);
    $element.addEventListener("wheel", wheel);
    document.body.addEventListener("mousemove", cancelInput); // mouse left container
    document.body.addEventListener("mouseout", mouseout); // mouse left window

    function mousedown(event) {
        if (isInAction === true) {
            return;
        }

        isInAction = true;

        if (config.activated === false) {
            return;
        }

        var x = event.pageX - boundingBox.left;
        var y = event.pageY - boundingBox.top;

        event.preventDefault();

        currentPosition.setValues(x, y, currentPosition.z);
        onStart(currentPosition);
    }

    function mousemove(event) {
        if (isInAction === false || config.activated === false) {
            return;
        }

        var x = event.pageX - boundingBox.left;
        var y = event.pageY - boundingBox.top;

        event.preventDefault();
        event.stopPropagation(); // stop event to bubble to document.body, which aborts dragging

        previousPosition.set(currentPosition);
        currentPosition.setValues(x, y, currentPosition.z);
        inputVector.setDelta(currentPosition, previousPosition);
        // convert position to scale
        inputVector.z = 1;

        onInput(inputVector, currentPosition);
    }

    function mouseup(event) {
        if (isInAction === false) {
            return;
        }

        isInAction = false;
        onEnd(event);
    }

    var wheelTimeout = new Timeout(function () {
        if (isInAction === false) {
            return;
        }

        isInAction = false;
        onEnd();
    }, mouseWheelDelay);

    function mousewheel(event) {
        if (config.activated === false) {
            return;
        }

        event.preventDefault();

        var x = event.pageX - boundingBox.left;
        var y = event.pageY - boundingBox.top;
        var z = event.wheelDelta;

        if (isInAction === false) {
            isInAction = true;

            wheelTimeout.start();
            currentPosition.set(x, y, z);
            onStart(currentPosition);

        } else {

            wheelTimeout.keepAlive();
            previousPosition.set(currentPosition);
            currentPosition.set(x, y, currentPosition.z + z);
            inputVector.setDelta(currentPosition, previousPosition);
            // convert position to scale
            inputVector.z = 1 + inputVector.z / mouseWheelRange;
            onInput(inputVector, currentPosition);
        }
    }

    function wheel(event) {
        if (config.activated === false) {
            return;
        }

        event.preventDefault();

        var x = event.pageX - boundingBox.left;
        var y = event.pageY - boundingBox.top;
        var z = event.deltaY;

        // ! need offset x, inconsistent across browser. any chance to derive position without bounding box?

        if (isInAction === false) {
            isInAction = true;

            wheelTimeout.start();
            currentPosition.setValues(x, y, z);
            onStart(currentPosition);

        } else {

            wheelTimeout.keepAlive();
            previousPosition.set(currentPosition);
            currentPosition.setValues(x, y, currentPosition.z + z);
            inputVector.setDelta(currentPosition, previousPosition);
            // convert position to scale
            inputVector.z = 1 + inputVector.z / mouseWheelRange;
            onInput(inputVector, currentPosition);
        }
    }

    function cancelInput(event) {
        if (isInAction === false) {
            return;
        }

        isInAction = false;
        onEnd(event);
    }

    function mouseout(event) {
        event = event ? event : window.event;
        var from = event.relatedTarget || event.toElement;
        if (!from || from.nodeName === "HTML") {
            cancelInput(event);
        }
    }

    return config;
}

module.exports = mouse;

<|endoftext|>


<commit_before>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const { SyncHook, AsyncSeriesHook } = require("tapable");

const QUEUED_STATE = 0;
const PROCESSING_STATE = 1;
const DONE_STATE = 2;

/**
 * @template T
 * @callback Callback<T>
 * @param {Error=} err
 * @param {T=} result
 */

/**
 * @template T
 * @template K
 * @template R
 */
class AsyncQueueEntry {
	/**
	 * @param {T} item the item
	 * @param {Callback<R>} callback the callback
	 */
	constructor(item, callback) {
		this.item = item;
		/** @type {typeof QUEUED_STATE | typeof PROCESSING_STATE | typeof DONE_STATE} */
		this.state = QUEUED_STATE;
		this.callback = callback;
		/** @type {Callback<R>[] | undefined} */
		this.callbacks = undefined;
		this.result = undefined;
		this.error = undefined;
	}
}

/**
 * @template T
 * @template K
 * @template R
 */
class AsyncQueue {
	/**
	 * @param {Object} options options object
	 * @param {string=} options.name name of the queue
	 * @param {number} options.parallelism how many items should be processed at once
	 * @param {function(T): K=} options.getKey extract key from item
	 * @param {function(T, Callback<R>): void} options.processor async function to process items
	 */
	constructor({ name, parallelism, processor, getKey }) {
		this._name = name;
		this._parallelism = parallelism;
		this._processor = processor;
		this._getKey =
			getKey || /** @type {(T) => K} */ (item => /** @type {any} */ (item));
		/** @type {Map<K, AsyncQueueEntry<T, K, R>>} */
		this._entries = new Map();
		/** @type {AsyncQueueEntry<T, K, R>[]} */
		this._queued = [];
		this._activeTasks = 0;
		this._willEnsureProcessing = false;
		this._stopped = false;

		this.hooks = {
			beforeAdd: new AsyncSeriesHook(["item"]),
			added: new SyncHook(["item"]),
			beforeStart: new AsyncSeriesHook(["item"]),
			started: new SyncHook(["item"]),
			result: new SyncHook(["item", "error", "result"])
		};

		this._ensureProcessing = this._ensureProcessing.bind(this);
	}

	/**
	 * @param {T} item a item
	 * @param {Callback<R>} callback callback function
	 * @returns {void}
	 */
	add(item, callback) {
		if (this._stopped) return callback(new Error("Queue was stopped"));
		this.hooks.beforeAdd.callAsync(item, err => {
			if (err) {
				callback(err);
				return;
			}
			const key = this._getKey(item);
			const entry = this._entries.get(key);
			if (entry !== undefined) {
				if (entry.state === DONE_STATE) {
					process.nextTick(() => callback(entry.error, entry.result));
				} else if (entry.callbacks === undefined) {
					entry.callbacks = [callback];
				} else {
					entry.callbacks.push(callback);
				}
				return;
			}
			const newEntry = new AsyncQueueEntry(item, callback);
			if (this._stopped) {
				this.hooks.added.call(item);
				this._activeTasks++;
				this._handleResult(newEntry, new Error("Queue was stopped"));
			} else {
				this._entries.set(key, newEntry);
				this._queued.push(newEntry);
				if (this._willEnsureProcessing === false) {
					this._willEnsureProcessing = true;
					process.nextTick(this._ensureProcessing);
				}
				this.hooks.added.call(item);
			}
		});
	}

	/**
	 * @param {T} item a item
	 * @returns {void}
	 */
	invalidate(item) {
		const key = this._getKey(item);
		this._entries.delete(key);
	}

	/**
	 * @returns {void}
	 */
	stop() {
		this._stopped = true;
		const queue = this._queued;
		this._queued = [];
		for (const entry of queue) {
			this._entries.delete(this._getKey(entry.item));
			this._activeTasks++;
			this._handleResult(entry, new Error("Queue was stopped"));
		}
	}

	/**
	 * @returns {void}
	 */
	increaseParallelism() {
		this._parallelism++;
		if (this._willEnsureProcessing === false && this._queued.length > 0) {
			this._willEnsureProcessing = true;
			process.nextTick(this._ensureProcessing);
		}
	}

	/**
	 * @returns {void}
	 */
	decreaseParallelism() {
		this._parallelism--;
	}

	/**
	 * @param {T} item an item
	 * @returns {boolean} true, if the item is currently being processed
	 */
	isProcessing(item) {
		const key = this._getKey(item);
		const entry = this._entries.get(key);
		return entry !== undefined && entry.state === PROCESSING_STATE;
	}

	/**
	 * @param {T} item an item
	 * @returns {boolean} true, if the item is currently queued
	 */
	isQueued(item) {
		const key = this._getKey(item);
		const entry = this._entries.get(key);
		return entry !== undefined && entry.state === QUEUED_STATE;
	}

	/**
	 * @param {T} item an item
	 * @returns {boolean} true, if the item is currently queued
	 */
	isDone(item) {
		const key = this._getKey(item);
		const entry = this._entries.get(key);
		return entry !== undefined && entry.state === DONE_STATE;
	}

	/**
	 * @returns {void}
	 */
	_ensureProcessing() {
		while (this._activeTasks < this._parallelism && this._queued.length > 0) {
			const entry = this._queued.pop();
			this._activeTasks++;
			entry.state = PROCESSING_STATE;
			this._startProcessing(entry);
		}
		this._willEnsureProcessing = false;
	}

	/**
	 * @param {AsyncQueueEntry<T, K, R>} entry the entry
	 * @returns {void}
	 */
	_startProcessing(entry) {
		this.hooks.beforeStart.callAsync(entry.item, err => {
			if (err) {
				this._handleResult(entry, err);
				return;
			}
			try {
				this._processor(entry.item, (e, r) => {
					this._handleResult(entry, e, r);
				});
			} catch (err) {
				this._handleResult(entry, err, null);
			}
			this.hooks.started.call(entry.item);
		});
	}

	/**
	 * @param {AsyncQueueEntry<T, K, R>} entry the entry
	 * @param {Error=} err error, if any
	 * @param {R=} result result, if any
	 * @returns {void}
	 */
	_handleResult(entry, err, result) {
		this.hooks.result.callAsync(entry.item, err, result, hookError => {
			const error = hookError || err;

			const callback = entry.callback;
			const callbacks = entry.callbacks;
			entry.state = DONE_STATE;
			entry.callback = undefined;
			entry.callbacks = undefined;
			entry.result = result;
			entry.error = error;
			this._activeTasks--;

			if (this._willEnsureProcessing === false && this._queued.length > 0) {
				this._willEnsureProcessing = true;
				process.nextTick(this._ensureProcessing);
			}

			callback(error, result);
			if (callbacks !== undefined) {
				for (const callback of callbacks) {
					callback(error, result);
				}
			}
		});
	}
}

module.exports = AsyncQueue;
<commit_msg>removed queue entry from AsyncQueue on invalidate<commit_after>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const { SyncHook, AsyncSeriesHook } = require("tapable");

const QUEUED_STATE = 0;
const PROCESSING_STATE = 1;
const DONE_STATE = 2;

/**
 * @template T
 * @callback Callback<T>
 * @param {Error=} err
 * @param {T=} result
 */

/**
 * @template T
 * @template K
 * @template R
 */
class AsyncQueueEntry {
	/**
	 * @param {T} item the item
	 * @param {Callback<R>} callback the callback
	 */
	constructor(item, callback) {
		this.item = item;
		/** @type {typeof QUEUED_STATE | typeof PROCESSING_STATE | typeof DONE_STATE} */
		this.state = QUEUED_STATE;
		this.callback = callback;
		/** @type {Callback<R>[] | undefined} */
		this.callbacks = undefined;
		this.result = undefined;
		this.error = undefined;
	}
}

/**
 * @template T
 * @template K
 * @template R
 */
class AsyncQueue {
	/**
	 * @param {Object} options options object
	 * @param {string=} options.name name of the queue
	 * @param {number} options.parallelism how many items should be processed at once
	 * @param {function(T): K=} options.getKey extract key from item
	 * @param {function(T, Callback<R>): void} options.processor async function to process items
	 */
	constructor({ name, parallelism, processor, getKey }) {
		this._name = name;
		this._parallelism = parallelism;
		this._processor = processor;
		this._getKey =
			getKey || /** @type {(T) => K} */ (item => /** @type {any} */ (item));
		/** @type {Map<K, AsyncQueueEntry<T, K, R>>} */
		this._entries = new Map();
		/** @type {AsyncQueueEntry<T, K, R>[]} */
		this._queued = [];
		this._activeTasks = 0;
		this._willEnsureProcessing = false;
		this._stopped = false;

		this.hooks = {
			beforeAdd: new AsyncSeriesHook(["item"]),
			added: new SyncHook(["item"]),
			beforeStart: new AsyncSeriesHook(["item"]),
			started: new SyncHook(["item"]),
			result: new SyncHook(["item", "error", "result"])
		};

		this._ensureProcessing = this._ensureProcessing.bind(this);
	}

	/**
	 * @param {T} item a item
	 * @param {Callback<R>} callback callback function
	 * @returns {void}
	 */
	add(item, callback) {
		if (this._stopped) return callback(new Error("Queue was stopped"));
		this.hooks.beforeAdd.callAsync(item, err => {
			if (err) {
				callback(err);
				return;
			}
			const key = this._getKey(item);
			const entry = this._entries.get(key);
			if (entry !== undefined) {
				if (entry.state === DONE_STATE) {
					process.nextTick(() => callback(entry.error, entry.result));
				} else if (entry.callbacks === undefined) {
					entry.callbacks = [callback];
				} else {
					entry.callbacks.push(callback);
				}
				return;
			}
			const newEntry = new AsyncQueueEntry(item, callback);
			if (this._stopped) {
				this.hooks.added.call(item);
				this._activeTasks++;
				this._handleResult(newEntry, new Error("Queue was stopped"));
			} else {
				this._entries.set(key, newEntry);
				this._queued.push(newEntry);
				if (this._willEnsureProcessing === false) {
					this._willEnsureProcessing = true;
					process.nextTick(this._ensureProcessing);
				}
				this.hooks.added.call(item);
			}
		});
	}

	/**
	 * @param {T} item a item
	 * @returns {void}
	 */
	invalidate(item) {
		const key = this._getKey(item);
		const entry = this._entries.get(key);
		this._entries.delete(key);
		if (entry.state === QUEUED_STATE) {
			const idx = this._queued.indexOf(entry);
			if (idx >= 0) {
				this._queued.splice(idx, 1);
			}
		}
	}

	/**
	 * @returns {void}
	 */
	stop() {
		this._stopped = true;
		const queue = this._queued;
		this._queued = [];
		for (const entry of queue) {
			this._entries.delete(this._getKey(entry.item));
			this._activeTasks++;
			this._handleResult(entry, new Error("Queue was stopped"));
		}
	}

	/**
	 * @returns {void}
	 */
	increaseParallelism() {
		this._parallelism++;
		if (this._willEnsureProcessing === false && this._queued.length > 0) {
			this._willEnsureProcessing = true;
			process.nextTick(this._ensureProcessing);
		}
	}

	/**
	 * @returns {void}
	 */
	decreaseParallelism() {
		this._parallelism--;
	}

	/**
	 * @param {T} item an item
	 * @returns {boolean} true, if the item is currently being processed
	 */
	isProcessing(item) {
		const key = this._getKey(item);
		const entry = this._entries.get(key);
		return entry !== undefined && entry.state === PROCESSING_STATE;
	}

	/**
	 * @param {T} item an item
	 * @returns {boolean} true, if the item is currently queued
	 */
	isQueued(item) {
		const key = this._getKey(item);
		const entry = this._entries.get(key);
		return entry !== undefined && entry.state === QUEUED_STATE;
	}

	/**
	 * @param {T} item an item
	 * @returns {boolean} true, if the item is currently queued
	 */
	isDone(item) {
		const key = this._getKey(item);
		const entry = this._entries.get(key);
		return entry !== undefined && entry.state === DONE_STATE;
	}

	/**
	 * @returns {void}
	 */
	_ensureProcessing() {
		while (this._activeTasks < this._parallelism && this._queued.length > 0) {
			const entry = this._queued.pop();
			this._activeTasks++;
			entry.state = PROCESSING_STATE;
			this._startProcessing(entry);
		}
		this._willEnsureProcessing = false;
	}

	/**
	 * @param {AsyncQueueEntry<T, K, R>} entry the entry
	 * @returns {void}
	 */
	_startProcessing(entry) {
		this.hooks.beforeStart.callAsync(entry.item, err => {
			if (err) {
				this._handleResult(entry, err);
				return;
			}
			try {
				this._processor(entry.item, (e, r) => {
					this._handleResult(entry, e, r);
				});
			} catch (err) {
				this._handleResult(entry, err, null);
			}
			this.hooks.started.call(entry.item);
		});
	}

	/**
	 * @param {AsyncQueueEntry<T, K, R>} entry the entry
	 * @param {Error=} err error, if any
	 * @param {R=} result result, if any
	 * @returns {void}
	 */
	_handleResult(entry, err, result) {
		this.hooks.result.callAsync(entry.item, err, result, hookError => {
			const error = hookError || err;

			const callback = entry.callback;
			const callbacks = entry.callbacks;
			entry.state = DONE_STATE;
			entry.callback = undefined;
			entry.callbacks = undefined;
			entry.result = result;
			entry.error = error;
			this._activeTasks--;

			if (this._willEnsureProcessing === false && this._queued.length > 0) {
				this._willEnsureProcessing = true;
				process.nextTick(this._ensureProcessing);
			}

			callback(error, result);
			if (callbacks !== undefined) {
				for (const callback of callbacks) {
					callback(error, result);
				}
			}
		});
	}
}

module.exports = AsyncQueue;
<|endoftext|>


<commit_before>/*! @license ©2014 Ruben Verborgh - Multimedia Lab / iMinds / Ghent University */

var Iterator = require('../iterators/Iterator'),
    request = require('request'),
    Logger = require('../util/Logger.js'),
    zlib = require('zlib'),
    _ = require('lodash');

/**
 * Creates a new `HttpClient`.
 * @classdesc An `HttpClient` retrieves representations of resources through HTTP
 * and offers them through an iterator interface.
 * @param {String} [options.request=(the request npm module)] The HTTP request module
 * @param {String} [options.contentType=* / *] The desired content type of representations
 * @constructor
 */
function HttpClient(options) {
  if (!(this instanceof HttpClient))
    return new HttpClient(options);

  options = options || {};
  this._request = options.request || request;
  this._contentType = options.contentType || '*/*';
  this._logger = options.logger || Logger('HttpClient');
}

/**
 * Retrieves a representation of the resource with the given URL.
 * @param {string} url The URL of the resource
 * @param {Object} [headers] Additional HTTP headers to add
 * @param {Object} [options] Additional options for the HTTP request
 * @returns {Iterator} An iterator of the representation
 */
HttpClient.prototype.get = function (url, headers, options) {
  return this.request(url, 'GET', headers, options);
};

/**
 * Retrieves a representation of the resource with the given URL.
 * @param {string} url The URL of the resource
 * @param {string} [method='GET'] method The HTTP method to use
 * @param {Object} [headers] Additional HTTP headers to add
 * @param {Object} [options] Additional options for the HTTP request
 * @returns {Iterator} An iterator of the representation
 */
HttpClient.prototype.request = function (url, method, headers, options) {
  var responseIterator = new Iterator.PassthroughIterator(true), startTime = new Date(),
      acceptHeaders = { accept: this._contentType, 'accept-encoding': 'gzip,deflate' };

  // Try to perform the request
  this._logger.info('Requesting', url);
  var requestOptions = {
    url: url,
    method: method || 'GET',
    headers: headers ? _.assign(acceptHeaders, headers) : acceptHeaders,
    timeout: 5000,
    followRedirect: true,
  }, request;
  try { request = this._request(options ? _.assign(requestOptions, options) : requestOptions); }
  catch (error) { return setImmediate(emitError, error), responseIterator; }
  function emitError(error) { responseIterator._error(error); }

  // React to a possible response
  request.on('response', function (response) {
    var statusCode = response.statusCode, headers = response.headers,
        responseTime = new Date() - startTime, encoding, contentType;

    // Decompress the response when necessary
    switch (encoding = headers['content-encoding'] || '') {
    case 'gzip':
      response.pipe(response = zlib.createGunzip());
      break;
    case 'deflate':
      response.pipe(response = zlib.createInflate());
      break;
    case '':
      break;
    default:
      return responseIterator._error(new Error('Unsupported encoding: ' + encoding));
    }
    response.on('error', emitError);

    // Redirect output to the iterator
    response.setEncoding && response.setEncoding('utf8');
    response.pause && response.pause();
    responseIterator.setSource(response);
    // Responses _must_ be entirely consumed,
    // or they can lead to out-of-memory errors (http://nodejs.org/api/http.html)
    responseIterator._bufferAll();

    // Emit the metadata
    contentType = (headers['content-type'] || '').replace(/\s*(?:;.*)?$/, '');
    responseIterator.setProperty('statusCode', statusCode);
    responseIterator.setProperty('contentType', contentType);
    responseIterator.setProperty('responseTime', responseTime);
  })
  .on('error', emitError);

  return responseIterator;
};

module.exports = HttpClient;
<commit_msg>Set a configurable maximum of concurrent requests.<commit_after>/*! @license ©2014 Ruben Verborgh - Multimedia Lab / iMinds / Ghent University */

var Iterator = require('../iterators/Iterator'),
    request = require('request'),
    Logger = require('../util/Logger.js'),
    zlib = require('zlib'),
    _ = require('lodash');

/**
 * Creates a new `HttpClient`.
 * @classdesc An `HttpClient` retrieves representations of resources through HTTP
 * and offers them through an iterator interface.
 * @param {String} [options.request=(the request npm module)] The HTTP request module
 * @param {String} [options.contentType=* / *] The desired content type of representations
 * @constructor
 */
function HttpClient(options) {
  if (!(this instanceof HttpClient))
    return new HttpClient(options);

  options = options || {};
  this._request = options.request || request;
  this._contentType = options.contentType || '*/*';
  this._queue = [];
  this._activeRequests = 0;
  this._maxActiveRequests = options.concurrentRequests || 20;
  this._logger = options.logger || Logger('HttpClient');
}

/**
 * Retrieves a representation of the resource with the given URL.
 * @param {string} url The URL of the resource
 * @param {Object} [headers] Additional HTTP headers to add
 * @param {Object} [options] Additional options for the HTTP request
 * @returns {Iterator} An iterator of the representation
 */
HttpClient.prototype.get = function (url, headers, options) {
  return this.request(url, 'GET', headers, options);
};

/**
 * Retrieves a representation of the resource with the given URL.
 * @param {string} url The URL of the resource
 * @param {string} [method='GET'] method The HTTP method to use
 * @param {Object} [headers] Additional HTTP headers to add
 * @param {Object} [options] Additional options for the HTTP request
 * @returns {Iterator} An iterator of the representation
 */
HttpClient.prototype.request = function (url, method, headers, options) {
  var responseIterator = new Iterator.PassthroughIterator(true), self = this;

  function performRequest() {
    self._logger.info('Requesting', url);
    self._activeRequests++;

    // Create the request
    var acceptHeaders = { accept: self._contentType, 'accept-encoding': 'gzip,deflate' };
    var requestOptions = {
      url: url,
      method: method || 'GET',
      headers: headers ? _.assign(acceptHeaders, headers) : acceptHeaders,
      timeout: 5000,
      followRedirect: true,
    }, request, startTime = new Date();
    try { request = self._request(options ? _.assign(requestOptions, options) : requestOptions); }
    catch (error) { return setImmediate(emitError, error), responseIterator; }
    function emitError(error) { responseIterator._error(error); }

    // React to a possible response
    request.on('response', function (response) {
      var statusCode = response.statusCode, headers = response.headers,
          responseTime = new Date() - startTime, encoding, contentType, nextRequest;
      // Start a possible pending request
      self._activeRequests--;
      (nextRequest = self._queue.shift()) && nextRequest();

      // Decompress the response when necessary
      switch (encoding = headers['content-encoding'] || '') {
      case 'gzip':
        response.pipe(response = zlib.createGunzip());
        break;
      case 'deflate':
        response.pipe(response = zlib.createInflate());
        break;
      case '':
        break;
      default:
        return responseIterator._error(new Error('Unsupported encoding: ' + encoding));
      }
      response.on('error', emitError);

      // Redirect output to the iterator
      response.setEncoding && response.setEncoding('utf8');
      response.pause && response.pause();
      responseIterator.setSource(response);
      // Responses _must_ be entirely consumed,
      // or they can lead to out-of-memory errors (http://nodejs.org/api/http.html)
      responseIterator._bufferAll();

      // Emit the metadata
      contentType = (headers['content-type'] || '').replace(/\s*(?:;.*)?$/, '');
      responseIterator.setProperty('statusCode', statusCode);
      responseIterator.setProperty('contentType', contentType);
      responseIterator.setProperty('responseTime', responseTime);
    })
    .on('error', emitError);
  }

  // Start or enqueue the request
  if (this._activeRequests < this._maxActiveRequests)
    performRequest();
  else
    this._queue.push(performRequest);

  return responseIterator;
};

module.exports = HttpClient;
<|endoftext|>


<commit_before>(function () {
  'use strict';
  /*jshint camelcase:false */
  describe('ProductController', function () {
    var ctrl,
      $q,
      $controller,
      dependencies,
      $scope,
      $state,
      WishlistsService,
      CartService,
      ErrorHandlerService,
      ModalService,
      deferGetWishlist,
      deferUpdateWishlist,
      deferCreateWishlist;

    beforeEach(module('porttare.controllers'));
    beforeEach(module('porttare.services', function ($provide) {
      $provide.factory('CartService', function () {
        return {};
      });
      $provide.factory('WishlistsService', function ($q) {
        deferGetWishlist = $q.defer();
        deferUpdateWishlist = $q.defer();
        deferCreateWishlist = $q.defer();
        return {
          getWishlists: sinon.stub().returns(deferGetWishlist.promise),
          updateWishlist: sinon.stub().returns(deferUpdateWishlist.promise),
          createWishlist: sinon.stub().returns(deferCreateWishlist.promise),
        };
      });
      $provide.factory('ModalService', function () {
        return {
          showModal: sinon.stub(),
          closeModal: sinon.stub()
        };
      });
      $provide.factory('$auth', function () {
        return {};
      });
      $provide.factory('ErrorHandlerService', function () {
        return {};
      });
      $provide.value('providerItem', {
        id: 1,
        precio_cents: 100
      });
      $provide.factory('$ionicPopup', function () {
        return {};
      });
      $provide.factory('$state', function ($q) {
        return {
          go: sinon.stub().returns($q.defer().promise),
          params: {
            categoryId: 1,
            providerId: 1
          }
        };
      });
      $provide.factory('$ionicLoading', function () {
        return {
          show: sinon.stub(),
          hide: sinon.stub()
        };
      });
      $provide.factory('$ionicScrollDelegate', function (){
        return {
          resize: sinon.stub()
        };
      });
    }));

    beforeEach(inject(function (_$q_, _$rootScope_, _$controller_,
      _WishlistsService_, _providerItem_, _CartService_, _$ionicPopup_,
      _$state_, _ModalService_, _ErrorHandlerService_, _$ionicLoading_, _$auth_, _$ionicScrollDelegate_) {

      $scope = _$rootScope_.$new();
      $q = _$q_;
      $controller = _$controller_;
      $state = _$state_;
      CartService = _CartService_;
      WishlistsService = _WishlistsService_;
      ModalService = _ModalService_;
      ErrorHandlerService = _ErrorHandlerService_;

      dependencies = {
        WishlistsService: WishlistsService,
        $scope: $scope,
        CartService: CartService,
        ModalService: ModalService,
        ErrorHandlerService: ErrorHandlerService,
        providerItem: _providerItem_,
        $ionicPopup: _$ionicPopup_,
        $state: $state,
        $ionicLoading: _$ionicLoading_,
        $auth: _$auth_,
        $ionicScrollDelegate: _$ionicScrollDelegate_
      };

      ctrl = $controller('ProductController', dependencies);
    }));

    describe('Add Items to wishlist', function () {
      it('Should get the wishlists', function () {
        ctrl.runAction(ctrl.actions.wishlist);
        sinon.assert.calledOnce(WishlistsService.getWishlists);
        $scope.$digest();
      });

      it('Should show Modal', function () {
        ctrl.runAction(ctrl.actions.wishlist);
        sinon.assert.calledOnce(ModalService.showModal);
        sinon.assert.calledWith(ModalService.showModal, {
          parentScope: $scope,
          fromTemplateUrl: 'templates/product/add-to-wishlist.html'
        });

      });

      it('Should add item to wishlist', function () {
        ctrl.item.provider_item_id = 60;
        var wlist = {
          id: 2,
          provider_items: [{
            id: 50
          }]
        };
        var dataExpect = {
          id: 2,
          provider_items: [{
            id: 50
          }],
          provider_items_ids: [50, 60]
        };

        ctrl.onWishlistSelect(wlist);
        sinon.assert.calledWith(WishlistsService.updateWishlist, dataExpect);
      });

      it('Should redirect to product view', function () {
        var wlist = {
          id: 2,
          provider_items: [{
            id: 50
          }]
        };
        var providerRoute = 'app.categories.provider';
        var params = {
          categoryId: 1,
          providerId: 1
        };
        ctrl.onWishlistSelect(wlist);
        deferUpdateWishlist.resolve();
        $scope.$digest();
        sinon.assert.calledWith($state.go, providerRoute, params);
      });
    });

    describe('Create wishlist', function () {
      it('Should create wishlist', function () {
        ctrl.wishlistName = 'test';
        ctrl.createNewWishlist();
        sinon.assert.calledWith(WishlistsService.createWishlist, {
          nombre: 'test'
        });
      });

      it('Add wishlist to list', function () {
        ctrl.wishlists = [{
          id: 2
        }];
        ctrl.createNewWishlist();
        deferCreateWishlist.resolve({
          customer_wishlist: {
            id: 1
          }
        });
        $scope.$digest();
        expect(ctrl.wishlists.length).to.be.equal(2);
      });
    });
  });
})();
<commit_msg>specs user en auth<commit_after>(function () {
  'use strict';
  /*jshint camelcase:false */
  describe('ProductController', function () {
    var ctrl,
      $q,
      $controller,
      dependencies,
      $scope,
      $state,
      WishlistsService,
      CartService,
      ErrorHandlerService,
      ModalService,
      deferGetWishlist,
      deferUpdateWishlist,
      deferCreateWishlist;

    beforeEach(module('porttare.controllers'));
    beforeEach(module('porttare.services', function ($provide) {
      $provide.factory('CartService', function () {
        return {};
      });
      $provide.factory('WishlistsService', function ($q) {
        deferGetWishlist = $q.defer();
        deferUpdateWishlist = $q.defer();
        deferCreateWishlist = $q.defer();
        return {
          getWishlists: sinon.stub().returns(deferGetWishlist.promise),
          updateWishlist: sinon.stub().returns(deferUpdateWishlist.promise),
          createWishlist: sinon.stub().returns(deferCreateWishlist.promise),
        };
      });
      $provide.factory('ModalService', function () {
        return {
          showModal: sinon.stub(),
          closeModal: sinon.stub()
        };
      });
      $provide.factory('$auth', function () {
        return { user: {} };
      });
      $provide.factory('ErrorHandlerService', function () {
        return {};
      });
      $provide.value('providerItem', {
        id: 1,
        precio_cents: 100
      });
      $provide.factory('$ionicPopup', function () {
        return {};
      });
      $provide.factory('$state', function ($q) {
        return {
          go: sinon.stub().returns($q.defer().promise),
          params: {
            categoryId: 1,
            providerId: 1
          }
        };
      });
      $provide.factory('$ionicLoading', function () {
        return {
          show: sinon.stub(),
          hide: sinon.stub()
        };
      });
      $provide.factory('$ionicScrollDelegate', function (){
        return {
          resize: sinon.stub()
        };
      });
    }));

    beforeEach(inject(function (_$q_, _$rootScope_, _$controller_,
      _WishlistsService_, _providerItem_, _CartService_, _$ionicPopup_,
      _$state_, _ModalService_, _ErrorHandlerService_, _$ionicLoading_, _$auth_, _$ionicScrollDelegate_) {

      $scope = _$rootScope_.$new();
      $q = _$q_;
      $controller = _$controller_;
      $state = _$state_;
      CartService = _CartService_;
      WishlistsService = _WishlistsService_;
      ModalService = _ModalService_;
      ErrorHandlerService = _ErrorHandlerService_;

      dependencies = {
        WishlistsService: WishlistsService,
        $scope: $scope,
        CartService: CartService,
        ModalService: ModalService,
        ErrorHandlerService: ErrorHandlerService,
        providerItem: _providerItem_,
        $ionicPopup: _$ionicPopup_,
        $state: $state,
        $ionicLoading: _$ionicLoading_,
        $auth: _$auth_,
        $ionicScrollDelegate: _$ionicScrollDelegate_
      };

      ctrl = $controller('ProductController', dependencies);
    }));

    describe('Add Items to wishlist', function () {
      it('Should get the wishlists', function () {
        ctrl.runAction(ctrl.actions.wishlist);
        sinon.assert.calledOnce(WishlistsService.getWishlists);
        $scope.$digest();
      });

      it('Should show Modal', function () {
        ctrl.runAction(ctrl.actions.wishlist);
        sinon.assert.calledOnce(ModalService.showModal);
        sinon.assert.calledWith(ModalService.showModal, {
          parentScope: $scope,
          fromTemplateUrl: 'templates/product/add-to-wishlist.html'
        });

      });

      it('Should add item to wishlist', function () {
        ctrl.item.provider_item_id = 60;
        var wlist = {
          id: 2,
          provider_items: [{
            id: 50
          }]
        };
        var dataExpect = {
          id: 2,
          provider_items: [{
            id: 50
          }],
          provider_items_ids: [50, 60]
        };

        ctrl.onWishlistSelect(wlist);
        sinon.assert.calledWith(WishlistsService.updateWishlist, dataExpect);
      });

      it('Should redirect to product view', function () {
        var wlist = {
          id: 2,
          provider_items: [{
            id: 50
          }]
        };
        var providerRoute = 'app.categories.provider';
        var params = {
          categoryId: 1,
          providerId: 1
        };
        ctrl.onWishlistSelect(wlist);
        deferUpdateWishlist.resolve();
        $scope.$digest();
        sinon.assert.calledWith($state.go, providerRoute, params);
      });
    });

    describe('Create wishlist', function () {
      it('Should create wishlist', function () {
        ctrl.wishlistName = 'test';
        ctrl.createNewWishlist();
        sinon.assert.calledWith(WishlistsService.createWishlist, {
          nombre: 'test'
        });
      });

      it('Add wishlist to list', function () {
        ctrl.wishlists = [{
          id: 2
        }];
        ctrl.createNewWishlist();
        deferCreateWishlist.resolve({
          customer_wishlist: {
            id: 1
          }
        });
        $scope.$digest();
        expect(ctrl.wishlists.length).to.be.equal(2);
      });
    });
  });
})();
<|endoftext|>


<commit_before>/**
 * @fileoverview Utility functions to help efficiently explore the Abstract Syntax Tree
 * @author Raghav Dua <duaraghav8@gmail.com>
 */

'use strict';

var Ajv = require ('ajv'),
	astNodeSchema = require ('../../config/schemas/ast-node');

var nodeSchemaValidator = new Ajv ({ allErrors: true }),
	validateASTNode = nodeSchemaValidator.compile (astNodeSchema);

var sourceCodeText = '';

/**
 * Initialization method - provide all the necessary information astUtils functions could require in order to work
 * @param {String} sourceCodeText The source code being linted
 */
exports.init = function (sourceCode) {
	sourceCodeText = sourceCode;
};

/**
 * Check if given argument is an AST Node
 * @param {Object} possibleObject Argument to check for validity
 * @returns {Boolean} isAValidASTNode true if given argument is an AST node, false otherwise
 */
exports.isASTNode = function (possibleNode) {
	return validateASTNode (possibleNode);
};

/**
 * Get the parent node of the specified node
 * @param {Object} node The AST Node to retrieve the parent of
 * @returns {Object} nodeParent Parent node of the given node
 */
exports.getParent = function (node) {
	if (!exports.isASTNode (node)) {
		throw new Error (JSON.stringify (node) + ' is not a valid AST node');
	}
	return node.parent;
};

/**
 * Retrieve the line number on which the code for provided node STARTS
 * @param {Object} node The AST Node to retrieve the line number of
 * @returns {Integer} lineNumber Line number of code of the specified node. (LINES BEGIN FROM 1)
 */
exports.getLine = function (node) {
	if (!exports.isASTNode (node)) {
		throw new Error (JSON.stringify (node) + ' is not a valid AST node');
	}

	var newLineCharsBefore = sourceCodeText
		.slice (0, node.start)
		.match (/\n/g);

	return (
		(newLineCharsBefore ? newLineCharsBefore.length : 0) + 1
	);
};

/**
 * Retrieve the column number of the first character of the given node
 * @param {Object} node The AST Node to retrieve the column number of
 * @returns {Integer} columnNumber Column number of code of the specified node (COLUMNS BEGIN FROM 0)
 */
exports.getColumn = function (node) {
	if (!exports.isASTNode (node)) {
		throw new Error (JSON.stringify (node) + ' is not a valid AST node');
	}

	//start looking from sourceCodeText [node.start] and stop upon encountering the first linebreak character
	for (var i = node.start; i >= 0; i--) {
		if (sourceCodeText [i] === '\n') {
			return node.start - i - 1;
		}
	}

	return node.start;
};

/**
 * Retrieve the line number on which the code for provided node ENDS
 * @param {Object} node The AST Node to retrieve the line number of
 * @returns {Integer} lineNumber Line number of code ending of the specified node. (LINES BEGIN FROM 1)
 */
exports.getEndingLine = function (node) {
	if (!exports.isASTNode (node)) {
		throw new Error (JSON.stringify (node) + ' is not a valid AST node');
	}

	var newLineCharsBefore = sourceCodeText
		.slice (0, node.end)
		.trim ()
		.match (/\n/g);

	return (
		(newLineCharsBefore ? newLineCharsBefore.length : 0) + 1
	);
}

/**
 * Retrieve the column number of the last character that is part of the given node
 * @param {Object} node The AST Node to retrieve the ending column number of
 * @returns {Integer} columnNumber Column number of last char of the specified node (COLUMNS BEGIN FROM 0)
 */
exports.getEndingColumn = function (node) {
	if (!exports.isASTNode (node)) {
		throw new Error (JSON.stringify (node) + ' is not a valid AST node');
	}

	//start looking from 1 character before node.start and stop upon encountering the first linebreak character
	for (var i = node.end - 1; i >= 0; i--) {
		if (sourceCodeText [i] === '\n') {
			return node.end - i - 2;
		}
	}

	return node.end - 1;
};<commit_msg>ast-utils.js: refactor<commit_after>/**
 * @fileoverview Utility functions to help efficiently explore the Abstract Syntax Tree
 * @author Raghav Dua <duaraghav8@gmail.com>
 */

'use strict';

var Ajv = require ('ajv'),
	astNodeSchema = require ('../../config/schemas/ast-node');
var nodeSchemaValidator = new Ajv ({ allErrors: true }), sourceCodeText = '';

/**
 * Initialization method - provide all the necessary information astUtils functions could require in order to work
 * @param {String} sourceCodeText The source code being linted
 */
exports.init = function (sourceCode) {
	sourceCodeText = sourceCode;
};

/**
 * Check if given argument is an AST Node
 * @param {Object} possibleObject Argument to check for validity
 * @returns {Boolean} isAValidASTNode true if given argument is an AST node, false otherwise
 */
exports.isASTNode = nodeSchemaValidator.compile (astNodeSchema);

/**
 * Get the parent node of the specified node
 * @param {Object} node The AST Node to retrieve the parent of
 * @returns {Object} nodeParent Parent node of the given node
 */
exports.getParent = function (node) {
	if (!exports.isASTNode (node)) {
		throw new Error (JSON.stringify (node) + ' is not a valid AST node');
	}
	return node.parent;
};

/**
 * Retrieve the line number on which the code for provided node STARTS
 * @param {Object} node The AST Node to retrieve the line number of
 * @returns {Integer} lineNumber Line number of code of the specified node. (LINES BEGIN FROM 1)
 */
exports.getLine = function (node) {
	if (!exports.isASTNode (node)) {
		throw new Error (JSON.stringify (node) + ' is not a valid AST node');
	}

	var newLineCharsBefore = sourceCodeText
		.slice (0, node.start)
		.match (/\n/g);

	return (
		(newLineCharsBefore ? newLineCharsBefore.length : 0) + 1
	);
};

/**
 * Retrieve the column number of the first character of the given node
 * @param {Object} node The AST Node to retrieve the column number of
 * @returns {Integer} columnNumber Column number of code of the specified node (COLUMNS BEGIN FROM 0)
 */
exports.getColumn = function (node) {
	if (!exports.isASTNode (node)) {
		throw new Error (JSON.stringify (node) + ' is not a valid AST node');
	}

	//start looking from sourceCodeText [node.start] and stop upon encountering the first linebreak character
	for (var i = node.start; i >= 0; i--) {
		if (sourceCodeText [i] === '\n') {
			return node.start - i - 1;
		}
	}

	return node.start;
};

/**
 * Retrieve the line number on which the code for provided node ENDS
 * @param {Object} node The AST Node to retrieve the line number of
 * @returns {Integer} lineNumber Line number of code ending of the specified node. (LINES BEGIN FROM 1)
 */
exports.getEndingLine = function (node) {
	if (!exports.isASTNode (node)) {
		throw new Error (JSON.stringify (node) + ' is not a valid AST node');
	}

	var newLineCharsBefore = sourceCodeText
		.slice (0, node.end)
		.trim ()
		.match (/\n/g);

	return (
		(newLineCharsBefore ? newLineCharsBefore.length : 0) + 1
	);
}

/**
 * Retrieve the column number of the last character that is part of the given node
 * @param {Object} node The AST Node to retrieve the ending column number of
 * @returns {Integer} columnNumber Column number of last char of the specified node (COLUMNS BEGIN FROM 0)
 */
exports.getEndingColumn = function (node) {
	if (!exports.isASTNode (node)) {
		throw new Error (JSON.stringify (node) + ' is not a valid AST node');
	}

	//start looking from 1 character before node.start and stop upon encountering the first linebreak character
	for (var i = node.end - 1; i >= 0; i--) {
		if (sourceCodeText [i] === '\n') {
			return node.end - i - 2;
		}
	}

	return node.end - 1;
};<|endoftext|>


<commit_before>function ConstraintManipulator(host){
    this.id = "mdConstraints";
    this.title = "Constraints";

    this.width = 224;
    this.height = 290;
    this.posx = 800;
    this.posy = 312;

    this.host = host;

	this.constraints = {};
}

ConstraintManipulator.method("getInitContent", function(){
	var ret = '<form id="SaveConstraints" enctype="multipart/form-data" method="post" action="/Constraint" style="display: block">';
	ret += '<input type="hidden" id="windowKey" name="windowKey" value="' + this.host.key + '">';
	ret += '<input type="hidden" id="constraintCont" name="constraints" value="' + this.host.key + '">';
	ret += '<input type="hidden" id="instanceName" name="instName" value="' + this.host.key + '">';
	ret += '<input type="submit" class="inputButton" id="Save" value="Save New Constraints"></form>';
	ret += '<text id="constraintDisplay" style="white-space: pre;"></text>';
	return ret;

});

ConstraintManipulator.method("onInitRendered", function(){
    var that = this;
    $("#Save").click(function(){
    	$("#constraintCont").val(that.getClaferConstraints(false));
    	$("#instanceName").val(that.instanceProcessor.getInstanceName().replace(/c[0-9]_/g, "") + " : " + that.instanceProcessor.getInstanceSuperClafer().replace(/c[0-9]_/g ""));
    });
});

ConstraintManipulator.method("onDataLoaded", function(data){
	this.Processor = new ClaferProcessor(data.claferXML);
	this.instanceProcessor = new InstanceProcessor(data.instancesXML);

	this.constraints = {};
	this.updateContent();
});

ConstraintManipulator.method("addConstraint", function(feature, require){
	this.constraints[feature] = require;
	this.updateContent();
});

ConstraintManipulator.method("removeConstraint", function(feature){
	delete this.constraints[feature];
	this.updateContent();
});

ConstraintManipulator.method("getConstraints", function(){
	var array = [];
	for(var constraint in this.constraints){
		array.push(constraint);
	}
	return array;
})

ConstraintManipulator.method("getClaferConstraints", function(includeOriginalConstraints){
	var ret = "";

	if(includeOriginalConstraints){ //pull from original model
		var list = this.Processor.getConstraints();
		for (var i=0; i<list.length; i++){
			ret += "\n" + list[i];
		}
	}

	var constraints = this.getConstraints();
	for (i=0; i<constraints.length; i++){
		ret += "\n[";
		if (!this.constraints[constraints[i]]){
			ret += "!";
		}
		ret += constraints[i];
		ret += "]";
	}
	console.log(ret)
	return ret;
});

ConstraintManipulator.method("updateContent", function(){
	var content = this.getClaferConstraints(true);
	$("#constraintDisplay").text(content);
});<commit_msg>Fixed typo brought on by fix of last typo... -_-<commit_after>function ConstraintManipulator(host){
    this.id = "mdConstraints";
    this.title = "Constraints";

    this.width = 224;
    this.height = 290;
    this.posx = 800;
    this.posy = 312;

    this.host = host;

	this.constraints = {};
}

ConstraintManipulator.method("getInitContent", function(){
	var ret = '<form id="SaveConstraints" enctype="multipart/form-data" method="post" action="/Constraint" style="display: block">';
	ret += '<input type="hidden" id="windowKey" name="windowKey" value="' + this.host.key + '">';
	ret += '<input type="hidden" id="constraintCont" name="constraints" value="' + this.host.key + '">';
	ret += '<input type="hidden" id="instanceName" name="instName" value="' + this.host.key + '">';
	ret += '<input type="submit" class="inputButton" id="Save" value="Save New Constraints"></form>';
	ret += '<text id="constraintDisplay" style="white-space: pre;"></text>';
	return ret;

});

ConstraintManipulator.method("onInitRendered", function(){
    var that = this;
    $("#Save").click(function(){
    	$("#constraintCont").val(that.getClaferConstraints(false));
    	$("#instanceName").val(that.instanceProcessor.getInstanceName().replace(/c[0-9]{1,}_/g, "") + " : " + that.instanceProcessor.getInstanceSuperClafer().replace(/c[0-9]{1,}_/g, ""));
    });
});

ConstraintManipulator.method("onDataLoaded", function(data){
	this.Processor = new ClaferProcessor(data.claferXML);
	this.instanceProcessor = new InstanceProcessor(data.instancesXML);

	this.constraints = {};
	this.updateContent();
});

ConstraintManipulator.method("addConstraint", function(feature, require){
	this.constraints[feature] = require;
	this.updateContent();
});

ConstraintManipulator.method("removeConstraint", function(feature){
	delete this.constraints[feature];
	this.updateContent();
});

ConstraintManipulator.method("getConstraints", function(){
	var array = [];
	for(var constraint in this.constraints){
		array.push(constraint);
	}
	return array;
})

ConstraintManipulator.method("getClaferConstraints", function(includeOriginalConstraints){
	var ret = "";

	if(includeOriginalConstraints){ //pull from original model
		var list = this.Processor.getConstraints();
		for (var i=0; i<list.length; i++){
			ret += "\n" + list[i];
		}
	}

	var constraints = this.getConstraints();
	for (i=0; i<constraints.length; i++){
		ret += "\n[";
		if (!this.constraints[constraints[i]]){
			ret += "!";
		}
		ret += constraints[i];
		ret += "]";
	}
	console.log(ret)
	return ret;
});

ConstraintManipulator.method("updateContent", function(){
	var content = this.getClaferConstraints(true);
	$("#constraintDisplay").text(content);
});<|endoftext|>


<commit_before>/*globals require, describe, it, before, after, WebGMEGlobal*/
/**
 * @author lattmann / https://github.com/lattmann
 */

require('../_globals.js');
var should = require('chai').should(),
    WebGME = require('../../webgme'),
    requirejs = require('requirejs'),
    config = WebGMEGlobal.getConfig(),

    http = require('http'),
    server,
    serverBaseUrl;

config.port = 9001;
config.debug = true;
WebGMEGlobal.setConfig(config);

describe('webgme http server', function () {
    'use strict';

    before(function (done) {
        this.timeout(3000);

        server = WebGME.standaloneServer();
        server.start();

        // TODO: would be nice to get this dynamically from server
        serverBaseUrl = 'http://127.0.0.1:' + config.port;

        setTimeout(done, 2000);
    });

    after(function () {
        server.stop();
    });

    describe('/', function () {
        it('should return 200 /', function (done) {
            http.get(serverBaseUrl + '/', function (res) {
                should.equal(200, res.statusCode);
                done();
            }).on('error', function (err) {
                done(err);
            });
        });

        it('should return 404 /doesnotexist', function (done) {
            http.get(serverBaseUrl + '/doesnotexist', function (res) {
                should.equal(404, res.statusCode);
                done();
            }).on('error', function (err) {
                done(err);
            });
        });

        it('should return 404 /asdf', function (done) {
            http.get(serverBaseUrl + '/asdf', function (res) {
                should.equal(404, res.statusCode);
                done();
            }).on('error', function (err) {
                done(err);
            });
        });

        it('should return 404 /doesnotexist.js', function (done) {
            http.get(serverBaseUrl + '/doesnotexist.js', function (res) {
                should.equal(404, res.statusCode);
                done();
            }).on('error', function (err) {
                done(err);
            });
        });
    });

});
<commit_msg>#60 fix config interference with other test<commit_after>/*globals require, describe, it, before, after, WebGMEGlobal*/
/**
 * @author lattmann / https://github.com/lattmann
 */

require('../_globals.js');
var should = require('chai').should(),
    WebGME = require('../../webgme'),
    requirejs = require('requirejs'),
    config = WebGMEGlobal.getConfig(),

    http = require('http'),
    server,
    serverBaseUrl;

describe('webgme http server', function () {
    'use strict';

    before(function () {
        // we have to set the config here
        config.port = 9001;
        WebGMEGlobal.setConfig(config);

        server = WebGME.standaloneServer();
        server.start();

        // TODO: would be nice to get this dynamically from server
        serverBaseUrl = 'http://127.0.0.1:' + config.port;
    });

    after(function () {
        server.stop();
    });

    describe('/', function () {
        it('should return 200 /', function (done) {
            http.get(serverBaseUrl + '/', function (res) {
                should.equal(200, res.statusCode);
                done();
            }).on('error', function (err) {
                done(err);
            });
        });

        it('should return 404 /doesnotexist', function (done) {
            http.get(serverBaseUrl + '/doesnotexist', function (res) {
                should.equal(404, res.statusCode);
                done();
            }).on('error', function (err) {
                done(err);
            });
        });

        it('should return 404 /asdf', function (done) {
            http.get(serverBaseUrl + '/asdf', function (res) {
                should.equal(404, res.statusCode);
                done();
            }).on('error', function (err) {
                done(err);
            });
        });

        it('should return 404 /doesnotexist.js', function (done) {
            http.get(serverBaseUrl + '/doesnotexist.js', function (res) {
                should.equal(404, res.statusCode);
                done();
            }).on('error', function (err) {
                done(err);
            });
        });
    });

});
<|endoftext|>


<commit_before>'use strict';

/**
 * Handle APIG resources.
 * Keep all resources that are used somewhere and remove the ones that are not
 * referenced anymore.
 */

const _ = require('lodash');
const BbPromise = require('bluebird');
const utils = require('../utils');

module.exports = function(currentTemplate, aliasStackTemplates, currentAliasStackTemplate) {
	const stackName = this._provider.naming.getStackName();
	const stageStack = this._serverless.service.provider.compiledCloudFormationTemplate;
	const aliasStack = this._serverless.service.provider.compiledCloudFormationAliasTemplate;
	const userResources = _.get(this._serverless.service, 'resources', { Resources: {}, Outputs: {} });

	// Check if our current deployment includes an API deployment
	let exposeApi = _.includes(_.keys(stageStack.Resources), 'ApiGatewayRestApi');
	const aliasResources = [];

	if (!exposeApi) {
		// Check if we have any aliases deployed that reference the API.
		if (_.some(aliasStackTemplates, template => _.find(template.Resources, [ 'Type', 'AWS::ApiGateway::Deployment' ]))) {
			// Fetch the Api resource from the current stack
			stageStack.Resources.ApiGatewayRestApi = currentTemplate.Resources.ApiGatewayRestApi;
			exposeApi = true;
		}
	}

	if (exposeApi) {

		this.options.verbose && this._serverless.cli.log('Processing API');

		// Export the API for the alias stacks
		stageStack.Outputs.ApiGatewayRestApi = {
			Description: 'API Gateway API',
			Value: { Ref: 'ApiGatewayRestApi' },
			Export: {
				Name: `${stackName}-ApiGatewayRestApi`
			}
		};

		// Export the root resource for the API
		stageStack.Outputs.ApiGatewayRestApiRootResource = {
			Description: 'API Gateway API root resource',
			Value: { 'Fn::GetAtt': [ 'ApiGatewayRestApi', 'RootResourceId' ] },
			Export: {
				Name: `${stackName}-ApiGatewayRestApiRootResource`
			}
		};

		// FIXME: Upgrade warning. Should be removed after some time has passed.
		if (_.some(_.reduce(aliasStackTemplates, (result, template) => {
			_.merge(result, template.Resources);
			return result;
		}, {}), [ 'Type', 'AWS::ApiGateway::Method' ]) ||
			_.find(currentAliasStackTemplate.Resources, [ 'Type', 'AWS::ApiGateway::Method' ])) {
			throw new this._serverless.classes.Error('ALIAS PLUGIN ALPHA CHANGE: APIG deployment had to be changed. Please remove the alias stacks and the APIG stage for the alias in CF (AWS console) and redeploy. Sorry!');
		}

		// Move the API deployment into the alias stack. The alias is the owner of the APIG stage.
		const deployment = _.assign({}, _.pickBy(stageStack.Resources, [ 'Type', 'AWS::ApiGateway::Deployment' ]));
		if (!_.isEmpty(deployment)) {
			const deploymentName = _.keys(deployment)[0];
			const obj = deployment[deploymentName];

			delete obj.Properties.StageName;
			obj.Properties.RestApiId = { 'Fn::ImportValue': `${stackName}-ApiGatewayRestApi` };
			obj.DependsOn = [];

			aliasResources.push(deployment);
			delete stageStack.Resources[deploymentName];

			// Create stage resource
			const stageResource = {
				Type: 'AWS::ApiGateway::Stage',
				Properties: {
					StageName: this._alias,
					DeploymentId: {
						Ref: deploymentName
					},
					RestApiId: {
						'Fn::ImportValue': `${stackName}-ApiGatewayRestApi`
					},
					Variables: {
						SERVERLESS_ALIAS: this._alias,
						SERVERLESS_STAGE: this._stage
					}
				},
				DependsOn: [ deploymentName ]
			};
			aliasResources.push({ ApiGatewayStage: stageResource });

		}

		// Fetch lambda permissions, methods and resources. These have to be updated later to allow the aliased functions.
		const apiLambdaPermissions =
				_.assign({},
					_.pickBy(_.pickBy(stageStack.Resources, [ 'Type', 'AWS::Lambda::Permission' ]),
					['Properties.Principal', 'apigateway.amazonaws.com']));

		const apiMethods = _.assign({}, _.pickBy(stageStack.Resources, [ 'Type', 'AWS::ApiGateway::Method' ]));
		const authorizers = _.assign({}, _.pickBy(stageStack.Resources, [ 'Type', 'AWS::ApiGateway::Authorizer' ]));
		const aliases = _.assign({}, _.pickBy(aliasStack.Resources, [ 'Type', 'AWS::Lambda::Alias' ]));
		const versions = _.assign({}, _.pickBy(aliasStack.Resources, [ 'Type', 'AWS::Lambda::Version' ]));

		// Adjust method API and target function
		_.forOwn(apiMethods, (method, name) => {
			// Relink to function alias in case we have a lambda endpoint
			if (_.includes([ 'AWS', 'AWS_PROXY' ], _.get(method, 'Properties.Integration.Type'))) {
				// For methods it is a bit tricky to find the related function name. There is no direct link.
				const uriParts = method.Properties.Integration.Uri['Fn::Join'][1];
				const funcIndex = _.findIndex(uriParts, part => _.has(part, 'Fn::GetAtt'));

				// Use the SERVERLESS_ALIAS stage variable to determine the called function alias
				uriParts.splice(funcIndex + 1, 0, ':${stageVariables.SERVERLESS_ALIAS}');
			}

			// Check for user resource overrides
			if (_.has(userResources.Resources, name)) {
				_.merge(method, userResources.Resources[name]);
				delete userResources.Resources[name];
			}

			stageStack.Resources[name] = method;
		});

		// Audjust authorizer Uri and name (stage variables are not allowed in Uris here)
		_.forOwn(authorizers, (authorizer, name) => {
			const uriParts = authorizer.Properties.AuthorizerUri['Fn::Join'][1];
			const funcIndex = _.findIndex(uriParts, part => _.has(part, 'Fn::GetAtt'));

			// Use the SERVERLESS_ALIAS stage variable to determine the called function alias
			uriParts.splice(funcIndex + 1, 0, `:${this._alias}`);

			authorizer.Properties.Name = `${authorizer.Properties.Name}-${this._alias}`;

			// Check for user resource overrides
			if (_.has(userResources.Resources, name)) {
				_.merge(authorizer, userResources.Resources[name]);
				delete userResources.Resources[name];
			}

			const aliasedName = `${name}${this._alias}`;
			const authorizerRefs = utils.findReferences(stageStack.Resources, name);
			_.forEach(authorizerRefs, ref => {
				_.set(stageStack.Resources, ref, { Ref: aliasedName });
			});

			// Replace dependencies
			_.forOwn(stageStack.Resources, resource => {
				if (_.isString(resource.DependsOn) && resource.DependsOn === name) {
					resource.DependsOn = aliasedName;
				} else if (_.isArray(resource.DependsOn) && _.includes(resource.DependsOn, name)) {
					_.pull(resource.DependsOn, name);
					resource.DependsOn.push(aliasedName);
				}
			});

			// Rename authorizer to be unique per alias
			stageStack.Resources[aliasedName] = authorizer;
			delete stageStack.Resources[name];
		});

		// Adjust permission to reference the function aliases
		_.forOwn(apiLambdaPermissions, (permission, name) => {
			const functionName = _.replace(name, /LambdaPermissionApiGateway$/, '');
			const versionName = _.find(_.keys(versions), version => _.startsWith(version, functionName));
			const aliasName = _.find(_.keys(aliases), alias => _.startsWith(alias, functionName));

			// Adjust references and alias permissions
			permission.Properties.FunctionName = { Ref: aliasName };
			if (permission.Properties.SourceArn) {
				// Authorizers do not set the SourceArn property
				permission.Properties.SourceArn = {
					'Fn::Join': [
						'',
						[
							'arn:aws:execute-api:',
							{ Ref: 'AWS::Region' },
							':',
							{ Ref: 'AWS::AccountId' },
							':',
							{ 'Fn::ImportValue': `${stackName}-ApiGatewayRestApi` },
							'/*/*'
						]
					]
				};
			}

			// Add dependency on function version
			permission.DependsOn = [ versionName, aliasName ];

			delete stageStack.Resources[name];
		});

		// Add all alias stack owned resources
		aliasResources.push(apiLambdaPermissions);

	}

	_.forEach(aliasResources, resource => _.assign(aliasStack.Resources, resource));

	return BbPromise.resolve([ currentTemplate, aliasStackTemplates, currentAliasStackTemplate ]);
};
<commit_msg>fix authorizer Uri<commit_after>'use strict';

/**
 * Handle APIG resources.
 * Keep all resources that are used somewhere and remove the ones that are not
 * referenced anymore.
 */

const _ = require('lodash');
const BbPromise = require('bluebird');
const utils = require('../utils');

module.exports = function(currentTemplate, aliasStackTemplates, currentAliasStackTemplate) {
	const stackName = this._provider.naming.getStackName();
	const stageStack = this._serverless.service.provider.compiledCloudFormationTemplate;
	const aliasStack = this._serverless.service.provider.compiledCloudFormationAliasTemplate;
	const userResources = _.get(this._serverless.service, 'resources', { Resources: {}, Outputs: {} });

	// Check if our current deployment includes an API deployment
	let exposeApi = _.includes(_.keys(stageStack.Resources), 'ApiGatewayRestApi');
	const aliasResources = [];

	if (!exposeApi) {
		// Check if we have any aliases deployed that reference the API.
		if (_.some(aliasStackTemplates, template => _.find(template.Resources, [ 'Type', 'AWS::ApiGateway::Deployment' ]))) {
			// Fetch the Api resource from the current stack
			stageStack.Resources.ApiGatewayRestApi = currentTemplate.Resources.ApiGatewayRestApi;
			exposeApi = true;
		}
	}

	if (exposeApi) {

		this.options.verbose && this._serverless.cli.log('Processing API');

		// Export the API for the alias stacks
		stageStack.Outputs.ApiGatewayRestApi = {
			Description: 'API Gateway API',
			Value: { Ref: 'ApiGatewayRestApi' },
			Export: {
				Name: `${stackName}-ApiGatewayRestApi`
			}
		};

		// Export the root resource for the API
		stageStack.Outputs.ApiGatewayRestApiRootResource = {
			Description: 'API Gateway API root resource',
			Value: { 'Fn::GetAtt': [ 'ApiGatewayRestApi', 'RootResourceId' ] },
			Export: {
				Name: `${stackName}-ApiGatewayRestApiRootResource`
			}
		};

		// FIXME: Upgrade warning. Should be removed after some time has passed.
		if (_.some(_.reduce(aliasStackTemplates, (result, template) => {
			_.merge(result, template.Resources);
			return result;
		}, {}), [ 'Type', 'AWS::ApiGateway::Method' ]) ||
			_.find(currentAliasStackTemplate.Resources, [ 'Type', 'AWS::ApiGateway::Method' ])) {
			throw new this._serverless.classes.Error('ALIAS PLUGIN ALPHA CHANGE: APIG deployment had to be changed. Please remove the alias stacks and the APIG stage for the alias in CF (AWS console) and redeploy. Sorry!');
		}

		// Move the API deployment into the alias stack. The alias is the owner of the APIG stage.
		const deployment = _.assign({}, _.pickBy(stageStack.Resources, [ 'Type', 'AWS::ApiGateway::Deployment' ]));
		if (!_.isEmpty(deployment)) {
			const deploymentName = _.keys(deployment)[0];
			const obj = deployment[deploymentName];

			delete obj.Properties.StageName;
			obj.Properties.RestApiId = { 'Fn::ImportValue': `${stackName}-ApiGatewayRestApi` };
			obj.DependsOn = [];

			aliasResources.push(deployment);
			delete stageStack.Resources[deploymentName];

			// Create stage resource
			const stageResource = {
				Type: 'AWS::ApiGateway::Stage',
				Properties: {
					StageName: this._alias,
					DeploymentId: {
						Ref: deploymentName
					},
					RestApiId: {
						'Fn::ImportValue': `${stackName}-ApiGatewayRestApi`
					},
					Variables: {
						SERVERLESS_ALIAS: this._alias,
						SERVERLESS_STAGE: this._stage
					}
				},
				DependsOn: [ deploymentName ]
			};
			aliasResources.push({ ApiGatewayStage: stageResource });

		}

		// Fetch lambda permissions, methods and resources. These have to be updated later to allow the aliased functions.
		const apiLambdaPermissions =
				_.assign({},
					_.pickBy(_.pickBy(stageStack.Resources, [ 'Type', 'AWS::Lambda::Permission' ]),
					['Properties.Principal', 'apigateway.amazonaws.com']));

		const apiMethods = _.assign({}, _.pickBy(stageStack.Resources, [ 'Type', 'AWS::ApiGateway::Method' ]));
		const authorizers = _.assign({}, _.pickBy(stageStack.Resources, [ 'Type', 'AWS::ApiGateway::Authorizer' ]));
		const aliases = _.assign({}, _.pickBy(aliasStack.Resources, [ 'Type', 'AWS::Lambda::Alias' ]));
		const versions = _.assign({}, _.pickBy(aliasStack.Resources, [ 'Type', 'AWS::Lambda::Version' ]));

		// Adjust method API and target function
		_.forOwn(apiMethods, (method, name) => {
			// Relink to function alias in case we have a lambda endpoint
			if (_.includes([ 'AWS', 'AWS_PROXY' ], _.get(method, 'Properties.Integration.Type'))) {
				// For methods it is a bit tricky to find the related function name. There is no direct link.
				const uriParts = method.Properties.Integration.Uri['Fn::Join'][1];
				const funcIndex = _.findIndex(uriParts, part => _.has(part, 'Fn::GetAtt'));

				// Use the SERVERLESS_ALIAS stage variable to determine the called function alias
				uriParts.splice(funcIndex + 1, 0, ':${stageVariables.SERVERLESS_ALIAS}');
			}

			// Check for user resource overrides
			if (_.has(userResources.Resources, name)) {
				_.merge(method, userResources.Resources[name]);
				delete userResources.Resources[name];
			}

			stageStack.Resources[name] = method;
		});

		// Audjust authorizer Uri and name (stage variables are not allowed in Uris here)
		_.forOwn(authorizers, (authorizer, name) => {
			const uriParts = authorizer.Properties.AuthorizerUri['Fn::Join'][1];
			const funcIndex = _.findIndex(uriParts, part => _.has(part, 'Fn::GetAtt'));

			// Use the SERVERLESS_ALIAS stage variable to determine the called function alias
			uriParts.splice(funcIndex + 1, 0, ':${stageVariables.SERVERLESS_ALIAS}');

			authorizer.Properties.Name = `${authorizer.Properties.Name}-${this._alias}`;

			// Check for user resource overrides
			if (_.has(userResources.Resources, name)) {
				_.merge(authorizer, userResources.Resources[name]);
				delete userResources.Resources[name];
			}

			const aliasedName = `${name}${this._alias}`;
			const authorizerRefs = utils.findReferences(stageStack.Resources, name);
			_.forEach(authorizerRefs, ref => {
				_.set(stageStack.Resources, ref, { Ref: aliasedName });
			});

			// Replace dependencies
			_.forOwn(stageStack.Resources, resource => {
				if (_.isString(resource.DependsOn) && resource.DependsOn === name) {
					resource.DependsOn = aliasedName;
				} else if (_.isArray(resource.DependsOn) && _.includes(resource.DependsOn, name)) {
					_.pull(resource.DependsOn, name);
					resource.DependsOn.push(aliasedName);
				}
			});

			// Rename authorizer to be unique per alias
			stageStack.Resources[aliasedName] = authorizer;
			delete stageStack.Resources[name];
		});

		// Adjust permission to reference the function aliases
		_.forOwn(apiLambdaPermissions, (permission, name) => {
			const functionName = _.replace(name, /LambdaPermissionApiGateway$/, '');
			const versionName = _.find(_.keys(versions), version => _.startsWith(version, functionName));
			const aliasName = _.find(_.keys(aliases), alias => _.startsWith(alias, functionName));

			// Adjust references and alias permissions
			permission.Properties.FunctionName = { Ref: aliasName };
			if (permission.Properties.SourceArn) {
				// Authorizers do not set the SourceArn property
				permission.Properties.SourceArn = {
					'Fn::Join': [
						'',
						[
							'arn:aws:execute-api:',
							{ Ref: 'AWS::Region' },
							':',
							{ Ref: 'AWS::AccountId' },
							':',
							{ 'Fn::ImportValue': `${stackName}-ApiGatewayRestApi` },
							'/*/*'
						]
					]
				};
			}

			// Add dependency on function version
			permission.DependsOn = [ versionName, aliasName ];

			delete stageStack.Resources[name];
		});

		// Add all alias stack owned resources
		aliasResources.push(apiLambdaPermissions);

	}

	_.forEach(aliasResources, resource => _.assign(aliasStack.Resources, resource));

	return BbPromise.resolve([ currentTemplate, aliasStackTemplates, currentAliasStackTemplate ]);
};
<|endoftext|>


<commit_before>/* global describe, it, beforeEach, afterEach */
'use strict';
const join = require('path').join;
const readFileSync = require('fs').readFileSync;
const InstanceManager = require('../../InstanceManager');
const endpointToUrl = require('../../common.js').endpointToUrl;
const arangojs = require('arangojs');
const aql = arangojs.aql;
const expect = require('chai').expect;
const service1 = readFileSync(
  join(__dirname, '..', '..', 'fixtures', 'service1.zip')
);
const service2 = readFileSync(
  join(__dirname, '..', '..', 'fixtures', 'service2.zip')
);
const utilService = readFileSync(join(__dirname, '..', '..', 'fixtures', 'util.zip'));
const UTIL_MOUNT = '/util';
const SERVICE_1_CHECKSUM = '69d01a5c';
const SERVICE_1_RESULT = 'service1';
const MOUNT_1 = '/resiliencetestservice1';

const sleep = (ms= 1000) => new Promise(resolve => setTimeout(resolve, ms));

describe('Foxx service', async function() {
  const instanceManager = new InstanceManager('foxx-resilience');

  const serviceInfos = [{
    mount: MOUNT_1,
    service: service1,
    checksum: SERVICE_1_CHECKSUM,
    result: SERVICE_1_RESULT
  }];

  beforeEach(async function() {
    await instanceManager.startAgency({agencySize:1});
  });

  afterEach(function() {
    instanceManager.moveServerLogs(this.currentTest);
    return instanceManager.cleanup().catch(() => {});
  });

  async function generateData(db, num) {
    let coll = await db.collection("testcollection");
    await coll.create();
    return Promise.all(Array.apply(0, Array(num))
          .map( (x, i) =>  i)
          .map(i => coll.save({test:i})));
  }

  it('survives leader failover', async function() {

    await instanceManager.startSingleServer('single', 2);
    await instanceManager.waitForAllInstances();

    let uuid = await instanceManager.asyncReplicationLeaderSelected();
    let leader = await instanceManager.asyncReplicationLeaderInstance();

    console.log('installing foxx app on %s', leader.endpoint);
    await installUtilService(leader.endpoint);
    await installAndCheckServices({
      endpointUrl: endpointToUrl(leader.endpoint),
      serviceInfos: serviceInfos
    });

    // wait for followers to get in sync
    const inSync = await instanceManager.asyncReplicationTicksInSync(60.0);
    expect(inSync).to.equal(true, "followers did not get in sync before timeout");

    console.log('killing leader %s', leader.endpoint);
    await instanceManager.kill(leader);

    uuid = await instanceManager.asyncReplicationLeaderSelected(uuid);
    leader = await instanceManager.asyncReplicationLeaderInstance();

    // just to be sure the foxx queue got a chance to run
    await sleep(3000);

    console.log('checking service on new leader %s', leader.endpoint);
    await checkAllServices({
      endpointUrl: endpointToUrl(leader.endpoint),
      serviceInfos: serviceInfos
    });
  });

  it('survives leader failover with data', async function() {

    await instanceManager.startSingleServer('single', 2);
    await instanceManager.waitForAllInstances();

    let uuid = await instanceManager.asyncReplicationLeaderSelected();
    let leader = await instanceManager.asyncReplicationLeaderInstance();

    console.log('installing foxx app on %s', leader.endpoint);
    let leaderUrl = endpointToUrl(leader.endpoint);
    await installUtilService(leader.endpoint);
    await installAndCheckServices({
      endpointUrl: leaderUrl,
      serviceInfos: serviceInfos
    });

    let db = arangojs({ url: leaderUrl, databaseName: '_system' });
    let coll = await db.collection("testcollection");
    await coll.create();
    await Promise.all(Array.apply(0, Array(1000))
                      .map( (x, i) =>  i)
                      .map(i => coll.save({test:i})));
    let cc = await coll.count();
    console.log(cc)
    expect(cc.count).to.be.eq(1000);

    // wait for followers to get in sync
    const inSync = await instanceManager.asyncReplicationTicksInSync(60.0);
    expect(inSync).to.equal(true, "followers did not get in sync before timeout");

    console.log('killing leader %s', leader.endpoint);
    await instanceManager.kill(leader);

    uuid = await instanceManager.asyncReplicationLeaderSelected(uuid);
    leader = await instanceManager.asyncReplicationLeaderInstance();

    // just to be sure the foxx queue got a chance to run
    await sleep(3000);

    leaderUrl = endpointToUrl(leader.endpoint);
    console.log('checking service on new leader %s', leader.endpoint);
    await checkAllServices({
      endpointUrl: endpointToUrl(leader.endpoint),
      serviceInfos: serviceInfos
    });

    db = arangojs({ url: leaderUrl, databaseName: '_system' });
    cc = await db.collection("testcollection").count();
    expect(cc.count).to.be.eq(1000);
  });
});

async function installAndCheckServices(services) {
  await crudAndCheckServices(services, async function(db, mount, service) {
    await db.installService(mount, service);
  });
}

async function crudAndCheckServices(services, crud) {
  await crudAllServices(services, crud);
  await checkAllServices(services);
}

async function crudAllServices(services, crud) {
  const servicePerMount = new Map(
    services.serviceInfos.map(info => [info.mount, info.service])
  );
  await crudServices(services.endpointUrl, servicePerMount, crud);
}

async function checkAllServices(services) {
  const resultPerMount = new Map(
    services.serviceInfos.map(info => [info.mount, info.result])
  );
  await checkServices(services.endpointUrl, resultPerMount, checkBundleExists);
  await checkServices(services.endpointUrl, resultPerMount, checkServiceAvailable);
  const checksumPerMount = new Map(
    services.serviceInfos.map(info => [info.mount, info.checksum])
  );
  await checkServices(
    services.endpointUrl,
    checksumPerMount,
    checkBundleChecksumInCollection
  );
  await checkServices(services.endpointUrl, checksumPerMount, checkBundleChecksum);
  const configPerMount = new Map(
    services.serviceInfos.map(info => [info.mount, info.config])
  );
  await checkServices(services.endpointUrl, configPerMount, checkServiceConfig);
  const dependenciesPerMount = new Map(
    services.serviceInfos.map(info => [info.mount, info.dependencies])
  );
  await checkServices(
    services.endpointUrl,
    dependenciesPerMount,
    checkServiceDependencies
  );
}

async function crudServices(endpointUrl, services, crud) {
  const db = arangojs(endpointUrl);
  for (const [mount, service] of services) {
    await crud(db, mount, service);
  }
}

async function configServices(endpointUrl, configs, urConfig) {
  const db = arangojs(endpointUrl);
  for (const [mount, config] of configs) {
    await urConfig(db, mount, config);
  }
}

async function checkServices(endpointUrl, services, check) {
  for (const [mount, expectedResult] of services) {
    if (expectedResult != undefined)
      await check(endpointUrl, mount, expectedResult);
  }
}

async function checkServiceAvailable(endpointUrl, mount, expectedResult) {
  if (expectedResult !== undefined) {
    let response;
    const db = await arangojs(endpointUrl);
    try {
      response = await db.route(mount).get();
    } catch (e) {
      if (expectedResult === null) {
        expect(e.code).to.equal(404);
        const collection = db.collection('_apps');
        const cursor = await db.query(
          aql`FOR s IN ${collection}
              FILTER s.mount == ${service.mount}
              RETURN s`
        );
        expect(await cursor.hasNext()).to.equal(false);
        return;
      }
      throw e;
    }
    expect(response).to.have.property('body', expectedResult);
  }
}

async function checkBundleExists(endpointUrl, mount, expectedResult) {
  if (expectedResult !== undefined) {
    let response;
    try {
      response = await arangojs(endpointUrl).route(UTIL_MOUNT).head({mount});
    } catch (e) {
      if (expectedResult === null) {
        expect(e.code).to.equal(404);
        return;
      }
      throw new Error("Exception during bundle check: %s", JSON.stringify(e));
    }
    expect(response.statusCode).to.equal(200);
  }
}

async function checkBundleChecksum(endpointUrl, mount, expectedChecksum) {
  const response = await arangojs(endpointUrl)
    .route(UTIL_MOUNT)
    .get('/checksums', {mount});
  expect(response).to.have.property('body');
  if (expectedChecksum === null) {
    expect(response.body).to.eql({});
  } else {
    expect(response.body).to.eql({[mount]: expectedChecksum});
  }
}

async function checkBundleChecksumInCollection(
  endpointUrl,
  mount,
  expectedChecksum
) {
  if (expectedChecksum !== null) {
    const db = await arangojs(endpointUrl);
    const collection = db.collection('_apps');
    const cursor = await db.query(
      aql`FOR service IN ${collection}
          FILTER service.mount == ${mount}
          RETURN service.checksum`
    );
    expect(await cursor.next()).to.be.equal(expectedChecksum);
  }
}

async function checkServiceConfig(endpointUrl, mount, expectedConfig) {
  const response = await arangojs(endpointUrl).getServiceConfiguration(mount);
  checkConfig(response, expectedConfig);
}

async function checkServiceDependencies(
  endpointUrl,
  mount,
  expectedDependencies
) {
  const response = await arangojs(endpointUrl).getServiceDependencies(mount);
  checkConfig(response, expectedDependencies);
}

function checkConfig(response, expectedConfig) {
  if (expectedConfig === null) {
    expect(response).to.eq({});
  } else {
    for (const key of Object.keys(expectedConfig)) {
      expect(response[key].current).to.be.equal(expectedConfig[key]);
    }
  }
}

async function installUtilService(endpoint) {
  await crudServices(endpointToUrl(endpoint),
    [[UTIL_MOUNT, utilService]],
    async function(db, mount, service) {
      await db.installService(mount, service);
    }
  );
}
<commit_msg>requested changes<commit_after>/* global describe, it, beforeEach, afterEach */
'use strict';
const join = require('path').join;
const readFileSync = require('fs').readFileSync;
const InstanceManager = require('../../InstanceManager');
const endpointToUrl = require('../../common.js').endpointToUrl;
const arangojs = require('arangojs');
const aql = arangojs.aql;
const expect = require('chai').expect;
const service1 = readFileSync(
  join(__dirname, '..', '..', 'fixtures', 'service1.zip')
);
const service2 = readFileSync(
  join(__dirname, '..', '..', 'fixtures', 'service2.zip')
);
const utilService = readFileSync(join(__dirname, '..', '..', 'fixtures', 'util.zip'));
const UTIL_MOUNT = '/util';
const SERVICE_1_CHECKSUM = '69d01a5c';
const SERVICE_1_RESULT = 'service1';
const MOUNT_1 = '/resiliencetestservice1';

const sleep = (ms= 1000) => new Promise(resolve => setTimeout(resolve, ms));

describe('Foxx service', async function() {
  const instanceManager = new InstanceManager('foxx-resilience');

  const serviceInfos = [{
    mount: MOUNT_1,
    service: service1,
    checksum: SERVICE_1_CHECKSUM,
    result: SERVICE_1_RESULT
  }];

  beforeEach(async function() {
    await instanceManager.startAgency({agencySize:1});
  });

  afterEach(function() {
    instanceManager.moveServerLogs(this.currentTest);
    return instanceManager.cleanup().catch(() => {});
  });

  async function generateData(db, num) {
    let coll = await db.collection("testcollection");
    await coll.create();
    return Promise.all(Array.apply(0, Array(num))
          .map( (x, i) =>  i)
          .map(i => coll.save({test:i})));
  }

  it('survives leader failover', async function() {

    await instanceManager.startSingleServer('single', 2);
    await instanceManager.waitForAllInstances();

    let uuid = await instanceManager.asyncReplicationLeaderSelected();
    let leader = await instanceManager.asyncReplicationLeaderInstance();

    console.log('installing foxx app on %s', leader.endpoint);
    await installUtilService(leader.endpoint);
    await installAndCheckServices({
      endpointUrl: endpointToUrl(leader.endpoint),
      serviceInfos: serviceInfos
    });

    // wait for followers to get in sync
    const inSync = await instanceManager.asyncReplicationTicksInSync(60.0);
    expect(inSync).to.equal(true, "followers did not get in sync before timeout");

    console.log('killing leader %s', leader.endpoint);
    await instanceManager.kill(leader);

    uuid = await instanceManager.asyncReplicationLeaderSelected(uuid);
    leader = await instanceManager.asyncReplicationLeaderInstance();

    // just to be sure the foxx queue got a chance to run
    await sleep(3000);

    console.log('checking service on new leader %s', leader.endpoint);
    await checkAllServices({
      endpointUrl: endpointToUrl(leader.endpoint),
      serviceInfos: serviceInfos
    });
  });

  it('survives leader failover with data', async function() {

    await instanceManager.startSingleServer('single', 2);
    await instanceManager.waitForAllInstances();

    let uuid = await instanceManager.asyncReplicationLeaderSelected();
    let leader = await instanceManager.asyncReplicationLeaderInstance();

    console.log('installing foxx app on %s', leader.endpoint);
    let leaderUrl = endpointToUrl(leader.endpoint);
    await installUtilService(leader.endpoint);
    await installAndCheckServices({
      endpointUrl: leaderUrl,
      serviceInfos: serviceInfos
    });

    let db = arangojs({ url: leaderUrl, databaseName: '_system' });
    let coll = await db.collection("testcollection");
    await coll.create();
    await Promise.all(Array.apply(0, Array(1000))
                      .map( (x, i) =>  i)
                      .map(i => coll.save({test:i})));
    let cc = await coll.count();
    console.log(cc)
    expect(cc.count).to.be.eq(1000);

    // wait for followers to get in sync
    const inSync = await instanceManager.asyncReplicationTicksInSync(60.0);
    expect(inSync).to.equal(true, "followers did not get in sync before timeout");

    console.log('killing leader %s', leader.endpoint);
    await instanceManager.kill(leader);

    uuid = await instanceManager.asyncReplicationLeaderSelected(uuid);
    leader = await instanceManager.asyncReplicationLeaderInstance();

    // just to be sure the foxx queue got a chance to run
    await sleep(3000);

    leaderUrl = endpointToUrl(leader.endpoint);
    console.log('checking service on new leader %s', leader.endpoint);
    await checkAllServices({
      endpointUrl: endpointToUrl(leader.endpoint),
      serviceInfos: serviceInfos
    });

    db = arangojs({ url: leaderUrl, databaseName: '_system' });
    cc = await db.collection("testcollection").count();
    expect(cc.count).to.be.eq(1000);
  });
});

async function installAndCheckServices(services) {
  await crudAndCheckServices(services, async function(db, mount, service) {
    await db.installService(mount, service);
  });
}

async function crudAndCheckServices(services, crud) {
  await crudAllServices(services, crud);
  await checkAllServices(services);
}

async function crudAllServices(services, crud) {
  const servicePerMount = new Map(
    services.serviceInfos.map(info => [info.mount, info.service])
  );
  await crudServices(services.endpointUrl, servicePerMount, crud);
}

async function checkAllServices(services) {
  const resultPerMount = new Map(
    services.serviceInfos.map(info => [info.mount, info.result])
  );
  await checkServices(services.endpointUrl, resultPerMount, checkBundleExists);
  await checkServices(services.endpointUrl, resultPerMount, checkServiceAvailable);
  const checksumPerMount = new Map(
    services.serviceInfos.map(info => [info.mount, info.checksum])
  );
  await checkServices(
    services.endpointUrl,
    checksumPerMount,
    checkBundleChecksumInCollection
  );
  await checkServices(services.endpointUrl, checksumPerMount, checkBundleChecksum);
  const configPerMount = new Map(
    services.serviceInfos.map(info => [info.mount, info.config])
  );
  await checkServices(services.endpointUrl, configPerMount, checkServiceConfig);
  const dependenciesPerMount = new Map(
    services.serviceInfos.map(info => [info.mount, info.dependencies])
  );
  await checkServices(
    services.endpointUrl,
    dependenciesPerMount,
    checkServiceDependencies
  );
}

async function crudServices(endpointUrl, services, crud) {
  const db = arangojs(endpointUrl);
  for (const [mount, service] of services) {
    await crud(db, mount, service);
  }
}

async function configServices(endpointUrl, configs, urConfig) {
  const db = arangojs(endpointUrl);
  for (const [mount, config] of configs) {
    await urConfig(db, mount, config);
  }
}

async function checkServices(endpointUrl, services, check) {
  for (const [mount, expectedResult] of services) {
    if (expectedResult != undefined)
      await check(endpointUrl, mount, expectedResult);
  }
}

async function checkServiceAvailable(endpointUrl, mount, expectedResult) {
  if (expectedResult !== undefined) {
    let response;
    const db = await arangojs(endpointUrl);
    try {
      response = await db.route(mount).get();
    } catch (e) {
      if (expectedResult === null) {
        expect(e.code).to.equal(404);
        const collection = db.collection('_apps');
        const cursor = await db.query(
          aql`FOR s IN ${collection}
              FILTER s.mount == ${service.mount}
              RETURN s`
        );
        expect(await cursor.hasNext()).to.equal(false);
        return;
      }
      throw e;
    }
    expect(response).to.have.property('body', expectedResult);
  }
}

async function checkBundleExists(endpointUrl, mount, expectedResult) {
  if (expectedResult !== undefined) {
    let response;
    try {
      response = await arangojs(endpointUrl).route(UTIL_MOUNT).head({mount});
    } catch (e) {
      if (expectedResult === null) {
        expect(e.code).to.equal(404);
        return;
      }
      throw new Error("Exception during bundle check: %s", e.errorMessage || e.errorNum);
    }
    expect(response.statusCode).to.equal(200);
  }
}

async function checkBundleChecksum(endpointUrl, mount, expectedChecksum) {
  const response = await arangojs(endpointUrl)
    .route(UTIL_MOUNT)
    .get('/checksums', {mount});
  expect(response).to.have.property('body');
  if (expectedChecksum === null) {
    expect(response.body).to.eql({});
  } else {
    expect(response.body).to.eql({[mount]: expectedChecksum});
  }
}

async function checkBundleChecksumInCollection(
  endpointUrl,
  mount,
  expectedChecksum
) {
  if (expectedChecksum !== null) {
    const db = await arangojs(endpointUrl);
    const collection = db.collection('_apps');
    const cursor = await db.query(
      aql`FOR service IN ${collection}
          FILTER service.mount == ${mount}
          RETURN service.checksum`
    );
    expect(await cursor.next()).to.be.equal(expectedChecksum);
  }
}

async function checkServiceConfig(endpointUrl, mount, expectedConfig) {
  const response = await arangojs(endpointUrl).getServiceConfiguration(mount);
  checkConfig(response, expectedConfig);
}

async function checkServiceDependencies(
  endpointUrl,
  mount,
  expectedDependencies
) {
  const response = await arangojs(endpointUrl).getServiceDependencies(mount);
  checkConfig(response, expectedDependencies);
}

function checkConfig(response, expectedConfig) {
  if (expectedConfig === null) {
    expect(response).to.eq({});
  } else {
    for (const key of Object.keys(expectedConfig)) {
      expect(response[key].current).to.be.equal(expectedConfig[key]);
    }
  }
}

async function installUtilService(endpoint) {
  await crudServices(endpointToUrl(endpoint),
    [[UTIL_MOUNT, utilService]],
    async function(db, mount, service) {
      await db.installService(mount, service);
    }
  );
}
<|endoftext|>


<commit_before>'use babel'

import * as util from './util'

/* A Suggestionprovider for Atom's autocompelte+;
  See also: https://github.com/atom/autocomplete-plus/wiki/Provider-API
*/
export default {
  setClient(client) {
    this.client = client
    console.log("setting client in provider")
  },

  //scope for suggestions; taken from language-modelica package
  selector: '.source.modelica',
  //don't activate in comment sections
  disableForSelector: '.comment',
  getSuggestions(options) {
    const {editor, bufferPosition, scopeDescriptor, prefix} = options
    const self = this
    const word = prefix
    return new Promise(resolve => {
      if(self.client === undefined) {
        //client not connected; do nothing
        resolve([])
      } else {
        //ask server for suggestions
        const position = new util.FilePosition(bufferPosition.row, bufferPosition.column)
        const filepath = editor.getPath()
        self.client.codeCompletion(filepath, position, prefix, (data) => {
          //map to autocomplete+ "suggestion-object"
          const suggestions = data.map(x => {
            const suggestion = {
              text: x.name,
              snippet: x.name,
              type: x.completionType.toLowerCase()
            }
            return suggestion
          })
          resolve(suggestions)
        }, (xhr, status, error) => {
          atom.notifications.addError(xhr.responseText)
          this.statusView.error("server-error")
          resolve([])
        })
      }
    })
  }
}
<commit_msg>Update providing of suggestions<commit_after>'use babel'

import * as util from './util'

/* A Suggestionprovider for Atom's autocompelte+;
  See also: https://github.com/atom/autocomplete-plus/wiki/Provider-API
*/
export default {
  setClient(client) {
    this.client = client
    console.log("setting client in provider")
  },

  //scope for suggestions; taken from language-modelica package
  selector: '.source.modelica',
  //don't activate in comment sections
  disableForSelector: '.comment',
  getSuggestions(options) {
    const {editor, bufferPosition, scopeDescriptor, prefix} = options
    const self = this
    const word = util.wordBelowCursor()
    return new Promise(resolve => {
      if(self.client === undefined) {
        //client not connected; do nothing
        resolve([])
      } else {
        //ask server for suggestions
        const position = new util.FilePosition(bufferPosition.row, bufferPosition.column)
        const filepath = editor.getPath()
        self.client.codeCompletion(filepath, position, word, (data) => {
          //map to autocomplete+ "suggestion-object"
          const suggestions = data.map(x => self.createSuggestion(prefix, x))
          resolve(suggestions)
        }, (xhr, status, error) => {
          atom.notifications.addError(xhr.responseText)
          this.statusView.error("server-error")
          resolve([])
        })
      }
    })
  },

  createSuggestion(prefix, dataObj) {
    const text =
      (prefix === '.') ?
      dataObj.name.substring(dataObj.name.lastIndexOf('.')+1) :
      dataObj.name
    console.log("text", text)
    return {
      text: text,
      type: this.getType(dataObj.completionType.toLowerCase())
    };
  },

  getType(completionType) {
    if(completionType == 'model')
      return 'class'
    else if(completionType == 'package')
      return 'import'
    else
      return completionType
  }
}
<|endoftext|>