<commit_before>var jsonfile = require('jsonfile');
var fs = require('fs');
var readline = require('readline');
var nodeUtil = require('util');
var utils = require('./utils.js');

module.exports = function(opts, cards, callback){

    var deckManager = {};

    deckManager.decks = {};

    deckManager.manifest = {};

    callback(deckManager);

    /* Public Methods */

    deckManager.bindListeners = function(opts, socket){
        if(opts.debug) console.log("Binding Deck Listeners");
        socket.on("deck:save", function(name){
            deckManager.save(name);
        });

        // Adds a card to a deck
        socket.on("deck:add", function(obj){
            deckManager.add(obj.name, obj.card);
        });

        // Removes a card from a deck
        socket.on("deck:remove", function(obj){
            deckManager.remove(obj.name, obj.card);
        });

        // Create a new deck
        socket.on("deck:create", function(name){
            console.log("Creating deck: \"" + name + "\".")
            deckManager.manifest[name] = {
                tags: []
            };
            deckManager.decks[name] = [];
            deckManager.save(name);
            socket.emit("deck:create::response", true);
        });

        // Deletes a deck
        socket.on("deck:delete", function(name){
            deckManager.delete(name);
            socket.emit("deck:delete::response", true);
        });

        // Moves a deck
        // NOTE: this should be updated to rename
        //socket.on("deck:move", function(obj){
        //    var oldPath = deckManager.manifest[obj.name];
        //    deckManager.manifest[obj.name] = obj.path;
        //    deckManager.delete(oldPath, name);
        //    deckManager.save();
        //    socket.emit("deck:move::response", true);
        //});

        socket.on("deck:get:all", function(){
            socket.emit("deck:get:all::response",
                 Object.keys(deckManager.decks)
            );
        });

        socket.on("deck:get:one", function(name){
            console.log("Getting \"" + name + "\".");
            socket.emit("deck:get:one::response",
                deckManager.decks[name]
            );
        });

        socket.on("deck:import", function(obj){
            if(opts.debug) console.log("Importing Bulk Cards to Deck \"" + obj.name + "\".");
            console.log(obj);
            var cards = deckManager._inflate(obj.cards.split("\n"));
            for(var i=0; i<cards.length; i++){
                var card = cards[i];
                deckManager.decks[obj.name].push(card);
            }
            console.log("Finished Importing Cards.");
            socket.emit("deck:import::response", true);
        });
    };

    deckManager.delete = function(name){
        delete deckManager.decks[name];
        delete deckManager.manifest[name];
        var fullPath = opts.data + "/decks/" + name + ".mbc";
        console.log("Deleting file \"" + fullPath + "\".");
        fs.unlinkSync(fullPath);
    };

    deckManager.save = function(name, callback){
        var deck = deckManager.decks[name];
        var timestamp = new Date();

        if(opts.debug) console.log("Saving Deck \"" + name + "\".");
        fs.writeFileSync(opts.data + "/decks/manifest.json", JSON.stringify(deckManager.manifest));

        var out = deckManager._deflate(name).join("\n") + "\n";
        fs.writeFileSync(opts.data + "/decks/" + name.replace("/", "\\\/") + ".mbc", out);

        if(opts.debug) console.log("Deck \"" + name + "\" Saved.");

        if(typeof callback === 'function'){
            callback();
        }
    };

    deckManager.add = function(name, card){
        console.log("Adding card " + card.name + " to deck " + name + ".");
        deckManager.decks[name].push(card);
    };

    deckManager.remove = function(name, card){
        console.log("Removing card " + card.name + " from deck " + name + ".");
        for(var i=0; i<deckManager.decks[name].length; i++){
            var deckCard = deckManager.decks[name][i];
            if(deckCard.name === card.name){
                deckManager.deck[name].splice(i, 1);
                break;
            }
        };

    };

    /* Private Methods */

    deckManager._loadDecks = function(callback){
        if(opts.debug) console.log("Loading Decks");

        deckManager.manifest = JSON.parse(fs.readFileSync(opts.data + "/decks/manifest.json").toString());

        var deckNames = Object.keys(deckManager.manifest);
        for(var i=0; i<deckNames.length; i++){
            var deckName = deckNames[i];
            var deckInfo = deckManager.manifest[deckName];

            if(opts.debug) console.log("Loading deck \"" + deckName + "\".");

            try{
                var deckString = fs.readFileSync(opts.data + "/decks/" + deckName + ".mbc").toString()
            }
            catch (e){
                console.log("Failed to load deck: \"" + deckName + "\".");
                delete deckManager.manifest[deckName];
                continue;
            }

            var inflated = deckManager._inflate(deckString.split("\n"));
            deckManager.decks[deckName] = inflated;
        }
        if(opts.debug) console.log("Loaded decks: " + Object.keys(deckManager.decks));

        if(typeof callback === 'function'){
            callback(deckManager.decks);
        }
        else{
            return deckManager.decks;
        }
    };

    deckManager._deflate = function(name, callback){
        if(opts.debug) console.log("Defalting Cards");
        var cardNames = [];

        for(var i=0; i<deckManager.decks[name].length; i++){
            var card = deckManager.decks[name][i];
            cardNames.push(card.name);
        }
        var cardCounts = {};
        cardNames.forEach(function(x){ cardCounts[x] = (cardCounts[x] || 0)+1; });

        var deflated = [];
        for(var i=0; i<Object.keys(cardCounts).length; i++){
            var card = Object.keys(cardCounts)[i];
            var count = cardCounts[card];
            deflated.push(nodeUtil.format("%s %s", count, card));
        }

        if(typeof callback === 'function'){
            callback(deflated);
        }
        else{
            return deflated;
        }
    };

    deckManager._inflate = function(deflatedCards, callback){
        if(opts.debug) console.log("Inflating Cards");

        var inflated = [];
        for(var i=0; i<deflatedCards.length; i++){
            var str = deflatedCards[i];
            var count = str.substr(0, str.indexOf(' '));
            var card = str.substr(str.indexOf(' ')+1);
            var fullCard = cards.get(card);

            for(var j=0; j<count; j++){
                inflated.push(fullCard);
            }
        }

        if(typeof callback === 'function'){
            callback(inflated);
        }
        else{
            return inflated;
        }

    };

    /* Load Decks */
    if(!fs.existsSync(opts.data + "/decks")){
        utils.mkdirSync(opts.data + "/decks");
    }
    if(!fs.existsSync(opts.data + "/decks/manifest.json")){
        fs.writeFileSync(opts.data + "/decks/manifest.json", JSON.stringify({}));
    }
    deckManager._loadDecks();
    return deckManager;
}
<commit_msg>fix card removal in decks<commit_after>var jsonfile = require('jsonfile');
var fs = require('fs');
var readline = require('readline');
var nodeUtil = require('util');
var utils = require('./utils.js');

module.exports = function(opts, cards, callback){

    var deckManager = {};

    deckManager.decks = {};

    deckManager.manifest = {};

    callback(deckManager);

    /* Public Methods */

    deckManager.bindListeners = function(opts, socket){
        if(opts.debug) console.log("Binding Deck Listeners");
        socket.on("deck:save", function(name){
            deckManager.save(name);
        });

        // Adds a card to a deck
        socket.on("deck:add", function(obj){
            deckManager.add(obj.name, obj.card);
        });

        // Removes a card from a deck
        socket.on("deck:remove", function(obj){
            deckManager.remove(obj.name, obj.card);
        });

        // Create a new deck
        socket.on("deck:create", function(name){
            console.log("Creating deck: \"" + name + "\".")
            deckManager.manifest[name] = {
                tags: []
            };
            deckManager.decks[name] = [];
            deckManager.save(name);
            socket.emit("deck:create::response", true);
        });

        // Deletes a deck
        socket.on("deck:delete", function(name){
            deckManager.delete(name);
            socket.emit("deck:delete::response", true);
        });

        // Moves a deck
        // NOTE: this should be updated to rename
        //socket.on("deck:move", function(obj){
        //    var oldPath = deckManager.manifest[obj.name];
        //    deckManager.manifest[obj.name] = obj.path;
        //    deckManager.delete(oldPath, name);
        //    deckManager.save();
        //    socket.emit("deck:move::response", true);
        //});

        socket.on("deck:get:all", function(){
            socket.emit("deck:get:all::response",
                 Object.keys(deckManager.decks)
            );
        });

        socket.on("deck:get:one", function(name){
            console.log("Getting \"" + name + "\".");
            socket.emit("deck:get:one::response",
                deckManager.decks[name]
            );
        });

        socket.on("deck:import", function(obj){
            if(opts.debug) console.log("Importing Bulk Cards to Deck \"" + obj.name + "\".");
            console.log(obj);
            var cards = deckManager._inflate(obj.cards.split("\n"));
            for(var i=0; i<cards.length; i++){
                var card = cards[i];
                deckManager.decks[obj.name].push(card);
            }
            console.log("Finished Importing Cards.");
            socket.emit("deck:import::response", true);
        });
    };

    deckManager.delete = function(name){
        delete deckManager.decks[name];
        delete deckManager.manifest[name];
        var fullPath = opts.data + "/decks/" + name + ".mbc";
        console.log("Deleting file \"" + fullPath + "\".");
        fs.unlinkSync(fullPath);
    };

    deckManager.save = function(name, callback){
        var deck = deckManager.decks[name];
        var timestamp = new Date();

        if(opts.debug) console.log("Saving Deck \"" + name + "\".");
        fs.writeFileSync(opts.data + "/decks/manifest.json", JSON.stringify(deckManager.manifest));

        var out = deckManager._deflate(name).join("\n") + "\n";
        fs.writeFileSync(opts.data + "/decks/" + name.replace("/", "\\\/") + ".mbc", out);

        if(opts.debug) console.log("Deck \"" + name + "\" Saved.");

        if(typeof callback === 'function'){
            callback();
        }
    };

    deckManager.add = function(name, card){
        console.log("Adding card " + card.name + " to deck " + name + ".");
        deckManager.decks[name].push(card);
    };

    deckManager.remove = function(name, card){
        console.log("Removing card " + card.name + " from deck " + name + ".");
        for(var i=0; i<deckManager.decks[name].length; i++){
            var deckCard = deckManager.decks[name][i];
            if(deckCard.name === card.name){
                deckManager.decks[name].splice(i, 1);
                break;
            }
        };

    };

    /* Private Methods */

    deckManager._loadDecks = function(callback){
        if(opts.debug) console.log("Loading Decks");

        deckManager.manifest = JSON.parse(fs.readFileSync(opts.data + "/decks/manifest.json").toString());

        var deckNames = Object.keys(deckManager.manifest);
        for(var i=0; i<deckNames.length; i++){
            var deckName = deckNames[i];
            var deckInfo = deckManager.manifest[deckName];

            if(opts.debug) console.log("Loading deck \"" + deckName + "\".");

            try{
                var deckString = fs.readFileSync(opts.data + "/decks/" + deckName + ".mbc").toString()
            }
            catch (e){
                console.log("Failed to load deck: \"" + deckName + "\".");
                delete deckManager.manifest[deckName];
                continue;
            }

            var inflated = deckManager._inflate(deckString.split("\n"));
            deckManager.decks[deckName] = inflated;
        }
        if(opts.debug) console.log("Loaded decks: " + Object.keys(deckManager.decks));

        if(typeof callback === 'function'){
            callback(deckManager.decks);
        }
        else{
            return deckManager.decks;
        }
    };

    deckManager._deflate = function(name, callback){
        if(opts.debug) console.log("Defalting Cards");
        var cardNames = [];

        for(var i=0; i<deckManager.decks[name].length; i++){
            var card = deckManager.decks[name][i];
            cardNames.push(card.name);
        }
        var cardCounts = {};
        cardNames.forEach(function(x){ cardCounts[x] = (cardCounts[x] || 0)+1; });

        var deflated = [];
        for(var i=0; i<Object.keys(cardCounts).length; i++){
            var card = Object.keys(cardCounts)[i];
            var count = cardCounts[card];
            deflated.push(nodeUtil.format("%s %s", count, card));
        }

        if(typeof callback === 'function'){
            callback(deflated);
        }
        else{
            return deflated;
        }
    };

    deckManager._inflate = function(deflatedCards, callback){
        if(opts.debug) console.log("Inflating Cards");

        var inflated = [];
        for(var i=0; i<deflatedCards.length; i++){
            var str = deflatedCards[i];
            var count = str.substr(0, str.indexOf(' '));
            var card = str.substr(str.indexOf(' ')+1);
            var fullCard = cards.get(card);

            for(var j=0; j<count; j++){
                inflated.push(fullCard);
            }
        }

        if(typeof callback === 'function'){
            callback(inflated);
        }
        else{
            return inflated;
        }

    };

    /* Load Decks */
    if(!fs.existsSync(opts.data + "/decks")){
        utils.mkdirSync(opts.data + "/decks");
    }
    if(!fs.existsSync(opts.data + "/decks/manifest.json")){
        fs.writeFileSync(opts.data + "/decks/manifest.json", JSON.stringify({}));
    }
    deckManager._loadDecks();
    return deckManager;
}
<|endoftext|>


<commit_before>/* globals it, describe, require */

(function() {
    "use strict";

    var js2xmlparser = require("../lib/js2xmlparser");
    var should = require("should");

    describe("the XML parser", function () {

        describe("when prettyPrinting is disabled", function () {
            var opts = {
                prettyPrinting: {
                    enabled : false
                }
            };

            it("should correctly serialize a simple object", function () {
                var res = js2xmlparser("root", {"hello":"world"}, opts);
                res.should.eql("<?xml version=\"1.0\" encoding=\"UTF-8\"?><root><hello>world</hello></root>");
            });

            it("should correctly serialize an empty object", function () {
                var res = js2xmlparser("root", {}, opts);
                res.should.eql("<?xml version=\"1.0\" encoding=\"UTF-8\"?><root/>");
            });

            it("should raise an error when no root is provided", function () {
                var res;
                try {
                    res = js2xmlparser(undefined, {}, opts);
                } catch (e) {
                    e.should.match(/root element must be a string/);
                }
                should.not.exist(res);
            });

            it("should correctly serialize an array", function () {
                var res = js2xmlparser("root",
                    {"name": [ "1", "2", "3", "4" ] },
                    opts);
                var expected =  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
                expected += "<root><name>1</name><name>2</name><name>3</name><name>4</name></root>";
                res.should.eql(expected);
            });

            it("should correctly serialize an array of string", function () {
                var res = js2xmlparser("root", {"item": [ "Hello", "World" ] }, opts);
                var expected =  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
                expected += "<root><item>Hello</item><item>World</item></root>";
                res.should.eql(expected);
            });
        });
    });
})();<commit_msg>Additions to tests<commit_after>/* globals it, describe, require */

(function() {
    "use strict";

    var js2xmlparser = require("../lib/js2xmlparser");
    var should = require("should");

    var opts = {
        prettyPrinting: {
            enabled : false
        }
    };

    describe("js2xmlparser", function () {

        describe("data", function() {
            it("should correctly serialize an empty object", function () {
                var res = js2xmlparser("root", {}, opts);
                res.should.eql("<?xml version=\"1.0\" encoding=\"UTF-8\"?><root/>");
            });

            it("should correctly convert a simple object", function () {
                var res = js2xmlparser("root", {"hello":"world"}, opts);
                res.should.eql("<?xml version=\"1.0\" encoding=\"UTF-8\"?><root><hello>world</hello></root>");
            });

            it("should correctly serialize an array", function () {
                var res = js2xmlparser("root",
                    {"name": [ "1", "2", "3", "4" ] },
                    opts);
                var expected =  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
                expected += "<root><name>1</name><name>2</name><name>3</name><name>4</name></root>";
                res.should.eql(expected);
            });

            it("should correctly serialize an array of string", function () {
                var res = js2xmlparser("root", {"item": [ "Hello", "World" ] }, opts);
                var expected =  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
                expected += "<root><item>Hello</item><item>World</item></root>";
                res.should.eql(expected);
            });
        });

        describe("root", function() {
            it("should raise an error when root is undefined", function () {
                var res;
                try {
                    res = js2xmlparser(undefined, {
                        "hello": "world"
                    }, opts);
                } catch (e) {
                    e.should.match(/root element must be a string/);
                }
                should.not.exist(res);
            });

            it("should raise an error when root is null", function () {
                var res;
                try {
                    res = js2xmlparser(null, {
                        "hello": "world"
                    }, opts);
                } catch (e) {
                    e.should.match(/root element must be a string/);
                }
                should.not.exist(res);
            });

            it("should raise an error when root is an empty string", function () {
                var res;
                try {
                    res = js2xmlparser("", {
                        "hello": "world"
                    }, opts);
                } catch (e) {
                    e.should.match(/root element cannot be empty/);
                }
                should.not.exist(res);
            });

            it("should raise an error when root is a random object", function () {
                var res;
                try {
                    res = js2xmlparser({}, {
                        "hello": "world"
                    }, opts);
                } catch (e) {
                    e.should.match(/root element must be a string/);
                }
                should.not.exist(res);
            });
        });

        describe("options", function() {

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


<commit_before>'use strict';
const path = require('path');
const inherits = require('util').inherits;
const AppBase = require('./app_base');

const App = function(opts) {
  AppBase.call(this, opts);
  this.modules = path.join(process.cwd(), 'node_modules');
};
inherits(App, AppBase);

App.prototype.willInit = function() {
  const settings = this.units.require('core.settings');
  !settings.core.debug && settings.core.uncaught && this.addUncaught(settings.core.uncaught);
  this.addExtensions(settings.extensions);
  this.addTransports();
  this.addResources();
  this.addCommands();
};

App.prototype.start = function() {
  this.ensureInited();
  this.addApi();
  this.startTransports();
  this.didStart();
  this.reportStartupTime('Worker');
  return this;
};

App.prototype.addTransports = function() {
  const transport = this.units.require('core.transport');

  if (transport.http) {
    this.root = transport.http.root;
  }
};

App.prototype.startTransports = function() {
  this.units.require('core.transport').start();
};

App.prototype.addUncaught = function() {
  this.units.require('core.uncaught');
};

App.prototype.addApi = function() {
  this.units.require('core.api');
};

App.prototype.addResources = function() {
  const units = this.loader.tryRequire(path.join(process.cwd(), 'lib', 'resources', 'units'));
  units && this.units.add('resources', units);
};

App.prototype.addCommands = function() {
  const cmds = this.loader.tryRequire(path.join(process.cwd(), 'lib', 'commands'));
  cmds && this.units.add('commands', cmds);
};

App.prototype.addExtensions = function(extensions = [], pre = 'mm-') {
  extensions.forEach(name => {
    const extension = this.require(pre + name);
    this.units.add(extension);
  });
};

App.prototype.require = function(name) {
  return require(path.join(this.modules, name));
};

App.prototype.add = function(name, units) {
  this.units.add(name, units);

  if (name === 'contract' && this.root) {
    this.use(units);
  }

  return this;
};

App.prototype.use = function(path, contract) {
  if (!this.root) {
    throw new Error('There is no http transport defined');
  }

  if (!contract) {
    contract = path;
    path = '/';
  }

  if (contract.handle) {
    this.root.use(path, (req, res, next) => {
      contract.handle(req, res, next)
    });
  } else {
    this.root.use(path, contract);
  }
  return this;
};

App.prototype.console = function() {
  this.ensureInited();
  global.app = this;
  const repl = require('repl');
  const r = repl.start({ useGlobal: true });
  r.on('exit', function() {
    process.exit();
  });
};

App.prototype.call = function(f) {
  this.ensureInited();
  f.call(this);
};

module.exports = App;
<commit_msg>Fixed back root contract support<commit_after>'use strict';
const path = require('path');
const inherits = require('util').inherits;
const AppBase = require('./app_base');

const App = function(opts) {
  AppBase.call(this, opts);
  this.modules = path.join(process.cwd(), 'node_modules');
};
inherits(App, AppBase);

App.prototype.willInit = function() {
  const settings = this.units.require('core.settings');
  !settings.core.debug && settings.core.uncaught && this.addUncaught(settings.core.uncaught);
  this.addExtensions(settings.extensions);
  this.addTransports();
  this.addResources();
  this.addCommands();
};

App.prototype.start = function() {
  this.ensureInited();
  this.addApi();
  this.startTransports();
  this.didStart();
  this.reportStartupTime('Worker');
  return this;
};

App.prototype.addTransports = function() {
  const transport = this.units.require('core.transport');

  if (transport.http) {
    this.root = transport.http.root;
  }
};

App.prototype.startTransports = function() {
  this.units.require('core.transport').start();
};

App.prototype.addUncaught = function() {
  this.units.require('core.uncaught');
};

App.prototype.addApi = function() {
  this.units.require('core.api');
};

App.prototype.addResources = function() {
  const units = this.loader.tryRequire(path.join(process.cwd(), 'lib', 'resources', 'units'));
  units && this.units.add('resources', units);
};

App.prototype.addCommands = function() {
  const cmds = this.loader.tryRequire(path.join(process.cwd(), 'lib', 'commands'));
  cmds && this.units.add('commands', cmds);
};

App.prototype.addExtensions = function(extensions = [], pre = 'mm-') {
  extensions.forEach(name => {
    const extension = this.require(pre + name);
    this.units.add(extension);
  });
};

App.prototype.require = function(name) {
  return require(path.join(this.modules, name));
};

App.prototype.add = function(name, units) {
  if (typeof name === 'object') {
    for (var n in name) {
      this.add(n, name[n]);
    }
    return;
  }

  this.units.add(name, units);
  if (name === 'contract' && this.root) {
    this.use(units);
  }

  return this;
};

App.prototype.use = function(path, contract) {
  if (!this.root) {
    throw new Error('There is no http transport defined');
  }

  if (!contract) {
    contract = path;
    path = '/';
  }

  if (contract.handle) {
    this.root.use(path, (req, res, next) => {
      contract.handle(req, res, next)
    });
  } else {
    this.root.use(path, contract);
  }
  return this;
};

App.prototype.console = function() {
  this.ensureInited();
  global.app = this;
  const repl = require('repl');
  const r = repl.start({ useGlobal: true });
  r.on('exit', function() {
    process.exit();
  });
};

App.prototype.call = function(f) {
  this.ensureInited();
  f.call(this);
};

module.exports = App;
<|endoftext|>


<commit_before>'use strict';

var _ = require('underscore'),
  http = require('http'),
  querystring = require('querystring'),
  url = require('url'),
  Command = require('./command'),
  NameMap = require('./name-map'),
  SlackBot = require('./slackbot');

var App = function(config) {
  if (!(this instanceof App)) {
    return new App(config);
  }

  this.config = _.defaults(config, {
    fileName: './map.json',
    token: '',
    port: 80
  });

  this.nameMap = NameMap(this.config.fileName);
  this.command = Command(this.nameMap);
  this.slackBot = SlackBot(this.config);
  this.validSubCommand = ['create', 'update', 'delete', 'list'];

  this.nameMap.setMappigQuota(this.config.mappigQuota);
};

App.prototype._server = function() {
  var server = http.createServer(function(req, res) {
    if (req.method === 'GET') {
      this._getHandler(req, res);
    } else if (req.method === 'POST') {
      this._postHandler(req, res);
    } else {
      res.end('Error! InvalidMethod');
    }
  }.bind(this));

  return server;
};

App.prototype._getHandler = function(req, res) {
  try {
    var token = url.parse(req.url, true).query.token;

    if (token !== this.config.token) {
      throw 'InvalidToken';
    }
    res.end(JSON.stringify(this.nameMap.getMap()));
  } catch(e) {
    res.end('Error! ' + e);
  }
};

App.prototype._postHandler = function(req, res) {
  req.on('data', function(data) {
    try {
      var
      payload = this._payloadHandler(querystring.parse(data.toString())),
      action = '_' + payload.subCommand;

      this.nameMap.setSlackName(payload.user_name);
      this.command[action](payload.args);
      this._response(payload);
      res.end('Done!');
    } catch(e) {
      var message = '"/ircname" command error! ' + e;
      this._errorResponse(payload, message);
      res.end(message);
    }
  }.bind(this));
};

App.prototype._payloadHandler = function(payload) {
  payload = _.defaults(payload, {
    token: '',
    user_name: '',
    text: ''
  });

  payload.args = payload.text.split(' ');
  payload.subCommand = payload.args[0];
  payload.args.shift();

  if (_.isEmpty(payload.user_name)) {
    throw 'EmptyUsername';
  } else if (payload.token !== this.config.token) {
    throw 'InvalidToken';
  } else if (payload.command !== '/ircname') {
    throw 'InvalidCommand';
  } else if (this.validSubCommand.indexOf(payload.subCommand) === -1) {
    throw 'InvalidSubCommand';
  }

  return payload;
};

App.prototype.listen = function() {
  this._server().listen(this.config.port);
  console.log('Server running at ' +
               'http://localhost:' + this.config.port + '/');
};

App.prototype._response = function(payload) {
  var args = payload.args;
  var message;

  switch (payload.subCommand) {
    case 'create':
      message = 'You CREATE a irc name "' + args[0] + '"" mapping!';
      break;
    case 'update':
      message = 'You UPDATE irc name mapping from "' + args[0] + '" to "' + args[1] + '"!';
      break;
    case 'delete':
      message = 'You DELETE a irc name "' + args[0] + '"" mapping!';
      break;
    case 'list':
      message = 'Your IRC Nick LIST: ' + this.command._list(args).join(', ');
      break;
  }

  this.slackBot.initMessage()
    .setAttachmentsFallback(message)
    .setAttachmentsColor('#2ab27b')
    .setAttachmentsFields('IRC Nick Action', message)
    .send('chat.postMessage', {
      channel: '@' + payload.user_name,
      username: 'nameMapServer'
    });
};

App.prototype._errorResponse = function(payload, message) {
  this.slackBot.initMessage()
    .setAttachmentsFallback(message)
    .setAttachmentsColor('#D00000')
    .setAttachmentsFields('Command Error', message)
    .send('chat.postMessage', {
      channel: '@' + payload.user_name,
      username: 'nameMapServer'
    });
};

module.exports = App;
<commit_msg>Fixed bug of command error handler<commit_after>'use strict';

var _ = require('underscore'),
  http = require('http'),
  querystring = require('querystring'),
  url = require('url'),
  Command = require('./command'),
  NameMap = require('./name-map'),
  SlackBot = require('./slackbot');

var App = function(config) {
  if (!(this instanceof App)) {
    return new App(config);
  }

  this.config = _.defaults(config, {
    fileName: './map.json',
    token: '',
    port: 80
  });

  this.nameMap = NameMap(this.config.fileName);
  this.command = Command(this.nameMap);
  this.slackBot = SlackBot(this.config);
  this.validSubCommand = ['create', 'update', 'delete', 'list'];

  this.nameMap.setMappigQuota(this.config.mappigQuota);
};

App.prototype._server = function() {
  var server = http.createServer(function(req, res) {
    if (req.method === 'GET') {
      this._getHandler(req, res);
    } else if (req.method === 'POST') {
      this._postHandler(req, res);
    } else {
      res.end('Error! InvalidMethod');
    }
  }.bind(this));

  return server;
};

App.prototype._getHandler = function(req, res) {
  try {
    var token = url.parse(req.url, true).query.token;

    if (token !== this.config.token) {
      throw 'InvalidToken';
    }
    res.end(JSON.stringify(this.nameMap.getMap()));
  } catch(e) {
    res.end('Error! ' + e);
  }
};

App.prototype._postHandler = function(req, res) {
  req.on('data', function(data) {
    try {
      var
      payload = this._payloadHandler(querystring.parse(data.toString())),
      action = '_' + payload.subCommand;

      if (payload.command !== '/ircname') {
        throw 'InvalidCommand';
      } else if (this.validSubCommand.indexOf(payload.subCommand) === -1) {
        throw 'InvalidSubCommand';
      }

      this.nameMap.setSlackName(payload.user_name);
      this.command[action](payload.args);
      this._response(payload);
      res.end('Done!');
    } catch(e) {
      var message = '"/ircname" command error! ' + e;
      this._errorResponse(payload, message);
      res.end(message);
    }
  }.bind(this));
};

App.prototype._payloadHandler = function(payload) {
  payload = _.defaults(payload, {
    token: '',
    user_name: '',
    text: ''
  });

  payload.args = payload.text.split(' ');
  payload.subCommand = payload.args[0];
  payload.args.shift();
  try {
    if (_.isEmpty(payload.user_name)) {
      throw 'EmptyUsername';
    } else if (payload.token !== this.config.token) {
      throw 'InvalidToken';
    }
  } catch(e) {
    res.end('Error! ' + e);
  }

  return payload;
};

App.prototype.listen = function() {
  this._server().listen(this.config.port);
  console.log('Server running at ' +
               'http://localhost:' + this.config.port + '/');
};

App.prototype._response = function(payload) {
  var args = payload.args;
  var message;

  switch (payload.subCommand) {
    case 'create':
      message = 'You CREATE a irc name "' + args[0] + '"" mapping!';
      break;
    case 'update':
      message = 'You UPDATE irc name mapping from "' + args[0] + '" to "' + args[1] + '"!';
      break;
    case 'delete':
      message = 'You DELETE a irc name "' + args[0] + '"" mapping!';
      break;
    case 'list':
      message = 'Your IRC Nick LIST: ' + this.command._list(args).join(', ');
      break;
  }

  this.slackBot.initMessage()
    .setAttachmentsFallback(message)
    .setAttachmentsColor('#2ab27b')
    .setAttachmentsFields('IRC Nick Action', message)
    .send('chat.postMessage', {
      channel: '@' + payload.user_name,
      username: 'nameMapServer'
    });
};

App.prototype._errorResponse = function(payload, message) {
  this.slackBot.initMessage()
    .setAttachmentsFallback(message)
    .setAttachmentsColor('#D00000')
    .setAttachmentsFields('Command Error', message)
    .send('chat.postMessage', {
      channel: '@' + payload.user_name,
      username: 'nameMapServer'
    });
};

module.exports = App;
<|endoftext|>


<commit_before>//
// utility functions for modules
//

function appendAll_internal2(modules, name, property, seenValues)
{
    var result = []
    for (var m in modules) {
        if (m == name) {
            var value = modules[m][property]
            if (value) {
                if (!seenValues[value]) {
                    seenValues[value] = true
                    result = result.concat(value)
                }
            }
        } else {
            var values = appendAll_internal2(modules[m].modules, name, property, seenValues)
            if (values && values.length > 0)
                result = result.concat(values)
        }
    }
    return result
}

function appendAll_internal(modules, name, property)
{
    var seenValues = []
    return appendAll_internal2(modules, name, property, seenValues)
}

function appendAll(config, property)
{
    return appendAll_internal(config.modules, config.module.name, property)
}

function appendAllFromArtifacts(product, artifacts, moduleName, propertyName)
{
    var seenValues = []
    var result = appendAll_internal2(product.modules, moduleName, propertyName, seenValues)
    for (var i in artifacts)
        result = result.concat(appendAll_internal2(artifacts[i].modules, moduleName, propertyName, seenValues))
    return result
}

function findFirst(modules, name, property)
{
    var value;
    var module;
    for (var moduleName in modules) {
        module = modules[moduleName];
        if (moduleName === name) {
            value = module[property];
            if (value !== undefined)
                return value;
        }
        value = findFirst(module.modules, name, property);
        if (value !== undefined)
            return value;
    }
    return undefined;
}

function dumpProperty(key, value, level)
{
    var indent = ''
    for (var k=0; k < level; ++k)
        indent += '  '
    print(indent + key + ': ' + value)
}

function traverseObject(obj, func, level)
{
    if (!level)
        level = 0
    var children = {}
    for (var i in obj) {
        if (typeof(obj[i]) == "object" && !(obj[i] instanceof Array))
            children[i] = obj[i]
        else
            func.apply(this, [i, obj[i], level])
    }
    level++
    for (var i in children) {
        func.apply(this, [i, children[i], level - 1])
        traverseObject(children[i], func, level)
    }
    level--
}

function dumpObject(obj, description)
{
    if (!description)
        description = 'object dump'
    print('+++++++++ ' + description + ' +++++++++')
    traverseObject(obj, dumpProperty)
}

//////////////////////////////////////////////////////////
// The EnvironmentVariable class
//
function EnvironmentVariable(name, separator, convertPathSeparators)
{
    if (!name)
        throw "EnvironmentVariable c'tor needs a name as first argument."
    this.name = name
    this.value = getenv(name).toString()
    this.separator = separator || ''
    this.convertPathSeparators = convertPathSeparators || false
}

EnvironmentVariable.prototype.prepend = function(v)
{
    if (this.value.length > 0 && this.value.charAt(0) != this.separator)
        this.value = this.separator + this.value
    if (this.convertPathSeparators)
        v = FileInfo.toWindowsSeparators(v)
    this.value = v + this.value
}

EnvironmentVariable.prototype.append = function(v)
{
    if (this.value.length > 0)
        this.value += this.separator
    if (this.convertPathSeparators)
        v = FileInfo.toWindowsSeparators(v)
    this.value += v
}

EnvironmentVariable.prototype.set = function()
{
    putenv(this.name, this.value)
}

<commit_msg>ModUtils.appendAll fix duplicate values<commit_after>//
// utility functions for modules
//

function appendAll_internal_recursive(modules, name, key, seenValues)
{
    var result = []
    var propertyValue
    var m, k
    for (m in modules) {
        if (m === name) {
            propertyValue = modules[m][key]
            if (propertyValue instanceof Array) {
                k = propertyValue.length
                while (k--) {
                    var value = propertyValue[k]
                    if (!seenValues[value]) {
                        seenValues[value] = true
                        result.push(value)
                    }
                }
            } else if (propertyValue) {
                if (!seenValues[propertyValue]) {
                    seenValues[propertyValue] = true
                    result.push(propertyValue)
                }
            }
        } else {
            propertyValue = appendAll_internal_recursive(modules[m].modules, name, key, seenValues)
            if (propertyValue.length > 0) {
                result = result.concat(propertyValue)
            }
        }
    }
    return result
}

function appendAll_internal(modules, name, key, seenValues)
{
    if (!seenValues)
        seenValues = []
    return appendAll_internal_recursive(modules, name, key, seenValues)
}

function appendAll(config, key)
{
    return appendAll_internal(config.modules, config.module.name, key)
}

function appendAllFromArtifacts(product, artifacts, moduleName, propertyName)
{
    var seenValues = []
    var result = appendAll_internal(product.modules, moduleName, propertyName, seenValues)
    for (var i in artifacts)
        result = result.concat(appendAll_internal(artifacts[i].modules, moduleName, propertyName, seenValues))
    return result
}

function findFirst(modules, name, property)
{
    var value;
    var module;
    for (var moduleName in modules) {
        module = modules[moduleName];
        if (moduleName === name) {
            value = module[property];
            if (value !== undefined)
                return value;
        }
        value = findFirst(module.modules, name, property);
        if (value !== undefined)
            return value;
    }
    return undefined;
}

function dumpProperty(key, value, level)
{
    var indent = ''
    for (var k=0; k < level; ++k)
        indent += '  '
    print(indent + key + ': ' + value)
}

function traverseObject(obj, func, level)
{
    if (!level)
        level = 0
    var children = {}
    for (var i in obj) {
        if (typeof(obj[i]) == "object" && !(obj[i] instanceof Array))
            children[i] = obj[i]
        else
            func.apply(this, [i, obj[i], level])
    }
    level++
    for (var i in children) {
        func.apply(this, [i, children[i], level - 1])
        traverseObject(children[i], func, level)
    }
    level--
}

function dumpObject(obj, description)
{
    if (!description)
        description = 'object dump'
    print('+++++++++ ' + description + ' +++++++++')
    traverseObject(obj, dumpProperty)
}

//////////////////////////////////////////////////////////
// The EnvironmentVariable class
//
function EnvironmentVariable(name, separator, convertPathSeparators)
{
    if (!name)
        throw "EnvironmentVariable c'tor needs a name as first argument."
    this.name = name
    this.value = getenv(name).toString()
    this.separator = separator || ''
    this.convertPathSeparators = convertPathSeparators || false
}

EnvironmentVariable.prototype.prepend = function(v)
{
    if (this.value.length > 0 && this.value.charAt(0) != this.separator)
        this.value = this.separator + this.value
    if (this.convertPathSeparators)
        v = FileInfo.toWindowsSeparators(v)
    this.value = v + this.value
}

EnvironmentVariable.prototype.append = function(v)
{
    if (this.value.length > 0)
        this.value += this.separator
    if (this.convertPathSeparators)
        v = FileInfo.toWindowsSeparators(v)
    this.value += v
}

EnvironmentVariable.prototype.set = function()
{
    putenv(this.name, this.value)
}

<|endoftext|>


<commit_before>define([
        '../Core/Color',
        '../Core/defaultValue',
        '../Core/defined',
        '../Core/defineProperties',
        '../Core/Event',
        '../Core/GeographicTilingScheme',
        '../ThirdParty/when'
    ], function(
        Color,
        defaultValue,
        defined,
        defineProperties,
        Event,
        GeographicTilingScheme,
        when) {
    'use strict';

    /**
     * An {@link ImageryProvider} that draws a box around every rendered tile in the tiling scheme, and draws
     * a label inside it indicating the X, Y, Level coordinates of the tile.  This is mostly useful for
     * debugging terrain and imagery rendering problems.
     *
     * @alias TileCoordinatesImageryProvider
     * @constructor
     *
     * @param {Object} [options] Object with the following properties:
     * @param {TilingScheme} [options.tilingScheme=new GeographicTilingScheme()] The tiling scheme for which to draw tiles.
     * @param {Ellipsoid} [options.ellipsoid] The ellipsoid.  If the tilingScheme is specified,
     *                    this parameter is ignored and the tiling scheme's ellipsoid is used instead. If neither
     *                    parameter is specified, the WGS84 ellipsoid is used.
     * @param {Color} [options.color=Color.YELLOW] The color to draw the tile box and label.
     * @param {Number} [options.tileWidth=256] The width of the tile for level-of-detail selection purposes.
     * @param {Number} [options.tileHeight=256] The height of the tile for level-of-detail selection purposes.
     */
    function TileCoordinatesImageryProvider(options) {
        options = defaultValue(options, defaultValue.EMPTY_OBJECT);

        this._tilingScheme = defined(options.tilingScheme) ? options.tilingScheme : new GeographicTilingScheme({ ellipsoid : options.ellipsoid });
        this._color = defaultValue(options.color, Color.YELLOW);
        this._errorEvent = new Event();
        this._tileWidth = defaultValue(options.tileWidth, 256);
        this._tileHeight = defaultValue(options.tileHeight, 256);
        this._readyPromise = when.resolve(true);
    }

    defineProperties(TileCoordinatesImageryProvider.prototype, {
        /**
         * Gets the proxy used by this provider.
         * @memberof TileCoordinatesImageryProvider.prototype
         * @type {Proxy}
         * @readonly
         */
        proxy : {
            get : function() {
                return undefined;
            }
        },

        /**
         * Gets the width of each tile, in pixels. This function should
         * not be called before {@link TileCoordinatesImageryProvider#ready} returns true.
         * @memberof TileCoordinatesImageryProvider.prototype
         * @type {Number}
         * @readonly
         */
        tileWidth : {
            get : function() {
                return this._tileWidth;
            }
        },

        /**
         * Gets the height of each tile, in pixels.  This function should
         * not be called before {@link TileCoordinatesImageryProvider#ready} returns true.
         * @memberof TileCoordinatesImageryProvider.prototype
         * @type {Number}
         * @readonly
         */
        tileHeight: {
            get : function() {
                return this._tileHeight;
            }
        },

        /**
         * Gets the maximum level-of-detail that can be requested.  This function should
         * not be called before {@link TileCoordinatesImageryProvider#ready} returns true.
         * @memberof TileCoordinatesImageryProvider.prototype
         * @type {Number}
         * @readonly
         */
        maximumLevel : {
            get : function() {
                return undefined;
            }
        },

        /**
         * Gets the minimum level-of-detail that can be requested.  This function should
         * not be called before {@link TileCoordinatesImageryProvider#ready} returns true.
         * @memberof TileCoordinatesImageryProvider.prototype
         * @type {Number}
         * @readonly
         */
        minimumLevel : {
            get : function() {
                return undefined;
            }
        },

        /**
         * Gets the tiling scheme used by this provider.  This function should
         * not be called before {@link TileCoordinatesImageryProvider#ready} returns true.
         * @memberof TileCoordinatesImageryProvider.prototype
         * @type {TilingScheme}
         * @readonly
         */
        tilingScheme : {
            get : function() {
                return this._tilingScheme;
            }
        },

        /**
         * Gets the rectangle, in radians, of the imagery provided by this instance.  This function should
         * not be called before {@link TileCoordinatesImageryProvider#ready} returns true.
         * @memberof TileCoordinatesImageryProvider.prototype
         * @type {Rectangle}
         * @readonly
         */
        rectangle : {
            get : function() {
                return this._tilingScheme.rectangle;
            }
        },

        /**
         * Gets the tile discard policy.  If not undefined, the discard policy is responsible
         * for filtering out "missing" tiles via its shouldDiscardImage function.  If this function
         * returns undefined, no tiles are filtered.  This function should
         * not be called before {@link TileCoordinatesImageryProvider#ready} returns true.
         * @memberof TileCoordinatesImageryProvider.prototype
         * @type {TileDiscardPolicy}
         * @readonly
         */
        tileDiscardPolicy : {
            get : function() {
                return undefined;
            }
        },

        /**
         * Gets an event that is raised when the imagery provider encounters an asynchronous error.  By subscribing
         * to the event, you will be notified of the error and can potentially recover from it.  Event listeners
         * are passed an instance of {@link TileProviderError}.
         * @memberof TileCoordinatesImageryProvider.prototype
         * @type {Event}
         * @readonly
         */
        errorEvent : {
            get : function() {
                return this._errorEvent;
            }
        },

        /**
         * Gets a value indicating whether or not the provider is ready for use.
         * @memberof TileCoordinatesImageryProvider.prototype
         * @type {Boolean}
         * @readonly
         */
        ready : {
            get : function() {
                return true;
            }
        },

        /**
         * Gets a promise that resolves to true when the provider is ready for use.
         * @memberof TileCoordinatesImageryProvider.prototype
         * @type {Promise.<Boolean>}
         * @readonly
         */
        readyPromise : {
            get : function() {
                return this._readyPromise;
            }
        },

        /**
         * Gets the credit to display when this imagery provider is active.  Typically this is used to credit
         * the source of the imagery.  This function should not be called before {@link TileCoordinatesImageryProvider#ready} returns true.
         * @memberof TileCoordinatesImageryProvider.prototype
         * @type {Credit}
         * @readonly
         */
        credit : {
            get : function() {
                return undefined;
            }
        },

        /**
         * Gets a value indicating whether or not the images provided by this imagery provider
         * include an alpha channel.  If this property is false, an alpha channel, if present, will
         * be ignored.  If this property is true, any images without an alpha channel will be treated
         * as if their alpha is 1.0 everywhere.  Setting this property to false reduces memory usage
         * and texture upload time.
         * @memberof TileCoordinatesImageryProvider.prototype
         * @type {Boolean}
         * @readonly
         */
        hasAlphaChannel : {
            get : function() {
                return true;
            }
        }
    });

    /**
     * Gets the credits to be displayed when a given tile is displayed.
     *
     * @param {Number} x The tile X coordinate.
     * @param {Number} y The tile Y coordinate.
     * @param {Number} level The tile level;
     * @returns {Credit[]} The credits to be displayed when the tile is displayed.
     *
     * @exception {DeveloperError} getTileCredits must not be called before the imagery provider is ready.
     */
    TileCoordinatesImageryProvider.prototype.getTileCredits = function(x, y, level) {
        return undefined;
    };

    /**
     * Requests the image for a given tile.  This function should
     * not be called before {@link TileCoordinatesImageryProvider#ready} returns true.
     *
     * @param {Number} x The tile X coordinate.
     * @param {Number} y The tile Y coordinate.
     * @param {Number} level The tile level.
     * @param {Request} [request] The request object. Intended for internal use only.
     * @returns {Promise.<Image|Canvas>|undefined} A promise for the image that will resolve when the image is available, or
     *          undefined if there are too many active requests to the server, and the request
     *          should be retried later.  The resolved image may be either an
     *          Image or a Canvas DOM object.
     */
    TileCoordinatesImageryProvider.prototype.requestImage = function(x, y, level, request) {
        var canvas = document.createElement('canvas');
        canvas.width = 256;
        canvas.height = 256;
        var context = canvas.getContext('2d');

        var cssColor = this._color.toCssColorString();

        context.strokeStyle = cssColor;
        context.lineWidth = 2;
        context.strokeRect(1, 1, 255, 255);

        var label = 'L' + level + 'X' + x + 'Y' + y;
        context.font = 'bold 25px Arial';
        context.fillText(label, 127, 127);
        context.fillStyle = cssColor;
        context.fillText(label, 124, 124);

        return canvas;
    };

    /**
     * Picking features is not currently supported by this imagery provider, so this function simply returns
     * undefined.
     *
     * @param {Number} x The tile X coordinate.
     * @param {Number} y The tile Y coordinate.
     * @param {Number} level The tile level.
     * @param {Number} longitude The longitude at which to pick features.
     * @param {Number} latitude  The latitude at which to pick features.
     * @return {Promise.<ImageryLayerFeatureInfo[]>|undefined} A promise for the picked features that will resolve when the asynchronous
     *                   picking completes.  The resolved value is an array of {@link ImageryLayerFeatureInfo}
     *                   instances.  The array may be empty if no features are found at the given location.
     *                   It may also be undefined if picking is not supported.
     */
    TileCoordinatesImageryProvider.prototype.pickFeatures = function(x, y, level, longitude, latitude) {
        return undefined;
    };

    return TileCoordinatesImageryProvider;
});
<commit_msg>separate coordinates onto different lines<commit_after>define([
        '../Core/Color',
        '../Core/defaultValue',
        '../Core/defined',
        '../Core/defineProperties',
        '../Core/Event',
        '../Core/GeographicTilingScheme',
        '../ThirdParty/when'
    ], function(
        Color,
        defaultValue,
        defined,
        defineProperties,
        Event,
        GeographicTilingScheme,
        when) {
    'use strict';

    /**
     * An {@link ImageryProvider} that draws a box around every rendered tile in the tiling scheme, and draws
     * a label inside it indicating the X, Y, Level coordinates of the tile.  This is mostly useful for
     * debugging terrain and imagery rendering problems.
     *
     * @alias TileCoordinatesImageryProvider
     * @constructor
     *
     * @param {Object} [options] Object with the following properties:
     * @param {TilingScheme} [options.tilingScheme=new GeographicTilingScheme()] The tiling scheme for which to draw tiles.
     * @param {Ellipsoid} [options.ellipsoid] The ellipsoid.  If the tilingScheme is specified,
     *                    this parameter is ignored and the tiling scheme's ellipsoid is used instead. If neither
     *                    parameter is specified, the WGS84 ellipsoid is used.
     * @param {Color} [options.color=Color.YELLOW] The color to draw the tile box and label.
     * @param {Number} [options.tileWidth=256] The width of the tile for level-of-detail selection purposes.
     * @param {Number} [options.tileHeight=256] The height of the tile for level-of-detail selection purposes.
     */
    function TileCoordinatesImageryProvider(options) {
        options = defaultValue(options, defaultValue.EMPTY_OBJECT);

        this._tilingScheme = defined(options.tilingScheme) ? options.tilingScheme : new GeographicTilingScheme({ ellipsoid : options.ellipsoid });
        this._color = defaultValue(options.color, Color.YELLOW);
        this._errorEvent = new Event();
        this._tileWidth = defaultValue(options.tileWidth, 256);
        this._tileHeight = defaultValue(options.tileHeight, 256);
        this._readyPromise = when.resolve(true);
    }

    defineProperties(TileCoordinatesImageryProvider.prototype, {
        /**
         * Gets the proxy used by this provider.
         * @memberof TileCoordinatesImageryProvider.prototype
         * @type {Proxy}
         * @readonly
         */
        proxy : {
            get : function() {
                return undefined;
            }
        },

        /**
         * Gets the width of each tile, in pixels. This function should
         * not be called before {@link TileCoordinatesImageryProvider#ready} returns true.
         * @memberof TileCoordinatesImageryProvider.prototype
         * @type {Number}
         * @readonly
         */
        tileWidth : {
            get : function() {
                return this._tileWidth;
            }
        },

        /**
         * Gets the height of each tile, in pixels.  This function should
         * not be called before {@link TileCoordinatesImageryProvider#ready} returns true.
         * @memberof TileCoordinatesImageryProvider.prototype
         * @type {Number}
         * @readonly
         */
        tileHeight: {
            get : function() {
                return this._tileHeight;
            }
        },

        /**
         * Gets the maximum level-of-detail that can be requested.  This function should
         * not be called before {@link TileCoordinatesImageryProvider#ready} returns true.
         * @memberof TileCoordinatesImageryProvider.prototype
         * @type {Number}
         * @readonly
         */
        maximumLevel : {
            get : function() {
                return undefined;
            }
        },

        /**
         * Gets the minimum level-of-detail that can be requested.  This function should
         * not be called before {@link TileCoordinatesImageryProvider#ready} returns true.
         * @memberof TileCoordinatesImageryProvider.prototype
         * @type {Number}
         * @readonly
         */
        minimumLevel : {
            get : function() {
                return undefined;
            }
        },

        /**
         * Gets the tiling scheme used by this provider.  This function should
         * not be called before {@link TileCoordinatesImageryProvider#ready} returns true.
         * @memberof TileCoordinatesImageryProvider.prototype
         * @type {TilingScheme}
         * @readonly
         */
        tilingScheme : {
            get : function() {
                return this._tilingScheme;
            }
        },

        /**
         * Gets the rectangle, in radians, of the imagery provided by this instance.  This function should
         * not be called before {@link TileCoordinatesImageryProvider#ready} returns true.
         * @memberof TileCoordinatesImageryProvider.prototype
         * @type {Rectangle}
         * @readonly
         */
        rectangle : {
            get : function() {
                return this._tilingScheme.rectangle;
            }
        },

        /**
         * Gets the tile discard policy.  If not undefined, the discard policy is responsible
         * for filtering out "missing" tiles via its shouldDiscardImage function.  If this function
         * returns undefined, no tiles are filtered.  This function should
         * not be called before {@link TileCoordinatesImageryProvider#ready} returns true.
         * @memberof TileCoordinatesImageryProvider.prototype
         * @type {TileDiscardPolicy}
         * @readonly
         */
        tileDiscardPolicy : {
            get : function() {
                return undefined;
            }
        },

        /**
         * Gets an event that is raised when the imagery provider encounters an asynchronous error.  By subscribing
         * to the event, you will be notified of the error and can potentially recover from it.  Event listeners
         * are passed an instance of {@link TileProviderError}.
         * @memberof TileCoordinatesImageryProvider.prototype
         * @type {Event}
         * @readonly
         */
        errorEvent : {
            get : function() {
                return this._errorEvent;
            }
        },

        /**
         * Gets a value indicating whether or not the provider is ready for use.
         * @memberof TileCoordinatesImageryProvider.prototype
         * @type {Boolean}
         * @readonly
         */
        ready : {
            get : function() {
                return true;
            }
        },

        /**
         * Gets a promise that resolves to true when the provider is ready for use.
         * @memberof TileCoordinatesImageryProvider.prototype
         * @type {Promise.<Boolean>}
         * @readonly
         */
        readyPromise : {
            get : function() {
                return this._readyPromise;
            }
        },

        /**
         * Gets the credit to display when this imagery provider is active.  Typically this is used to credit
         * the source of the imagery.  This function should not be called before {@link TileCoordinatesImageryProvider#ready} returns true.
         * @memberof TileCoordinatesImageryProvider.prototype
         * @type {Credit}
         * @readonly
         */
        credit : {
            get : function() {
                return undefined;
            }
        },

        /**
         * Gets a value indicating whether or not the images provided by this imagery provider
         * include an alpha channel.  If this property is false, an alpha channel, if present, will
         * be ignored.  If this property is true, any images without an alpha channel will be treated
         * as if their alpha is 1.0 everywhere.  Setting this property to false reduces memory usage
         * and texture upload time.
         * @memberof TileCoordinatesImageryProvider.prototype
         * @type {Boolean}
         * @readonly
         */
        hasAlphaChannel : {
            get : function() {
                return true;
            }
        }
    });

    /**
     * Gets the credits to be displayed when a given tile is displayed.
     *
     * @param {Number} x The tile X coordinate.
     * @param {Number} y The tile Y coordinate.
     * @param {Number} level The tile level;
     * @returns {Credit[]} The credits to be displayed when the tile is displayed.
     *
     * @exception {DeveloperError} getTileCredits must not be called before the imagery provider is ready.
     */
    TileCoordinatesImageryProvider.prototype.getTileCredits = function(x, y, level) {
        return undefined;
    };

    /**
     * Requests the image for a given tile.  This function should
     * not be called before {@link TileCoordinatesImageryProvider#ready} returns true.
     *
     * @param {Number} x The tile X coordinate.
     * @param {Number} y The tile Y coordinate.
     * @param {Number} level The tile level.
     * @param {Request} [request] The request object. Intended for internal use only.
     * @returns {Promise.<Image|Canvas>|undefined} A promise for the image that will resolve when the image is available, or
     *          undefined if there are too many active requests to the server, and the request
     *          should be retried later.  The resolved image may be either an
     *          Image or a Canvas DOM object.
     */
    TileCoordinatesImageryProvider.prototype.requestImage = function(x, y, level, request) {
        var canvas = document.createElement('canvas');
        canvas.width = 256;
        canvas.height = 256;
        var context = canvas.getContext('2d');

        var cssColor = this._color.toCssColorString();

        context.strokeStyle = cssColor;
        context.lineWidth = 2;
        context.strokeRect(1, 1, 255, 255);

        context.font = 'bold 25px Arial';
        context.fillStyle = cssColor;
        context.fillText('L: ' + level, 100, 86);
        context.fillText('X: ' + x, 100, 136);
        context.fillText('Y: ' + y, 100, 186);

        return canvas;
    };

    /**
     * Picking features is not currently supported by this imagery provider, so this function simply returns
     * undefined.
     *
     * @param {Number} x The tile X coordinate.
     * @param {Number} y The tile Y coordinate.
     * @param {Number} level The tile level.
     * @param {Number} longitude The longitude at which to pick features.
     * @param {Number} latitude  The latitude at which to pick features.
     * @return {Promise.<ImageryLayerFeatureInfo[]>|undefined} A promise for the picked features that will resolve when the asynchronous
     *                   picking completes.  The resolved value is an array of {@link ImageryLayerFeatureInfo}
     *                   instances.  The array may be empty if no features are found at the given location.
     *                   It may also be undefined if picking is not supported.
     */
    TileCoordinatesImageryProvider.prototype.pickFeatures = function(x, y, level, longitude, latitude) {
        return undefined;
    };

    return TileCoordinatesImageryProvider;
});
<|endoftext|>


<commit_before>import { createStore, applyMiddleware } from 'redux'
import rootReducer from '../reducers'

import { browserHistory } from 'react-router'
import { routerMiddleware } from 'react-router-redux'
import thunkMiddleware from 'redux-thunk'

const myMiddleware = store => next => action => {
  if (action.type === '@@router/LOCATION_CHANGE') {
    // scroll up when vising new page
    window.scrollTo(0, 0)
  }
  return next(action)
}

const middleware = applyMiddleware(
  thunkMiddleware, // allows dispatching of functions
  routerMiddleware(browserHistory), // keeps url in sync with app
  myMiddleware // scroll up when vising new page
)

const enhancer = middleware

export default function configureStore (initialState) {
  return createStore(rootReducer, initialState, enhancer)
};
<commit_msg>Added live logging to production build, for now<commit_after>import { createStore, applyMiddleware } from 'redux'
import rootReducer from '../reducers'

import { browserHistory } from 'react-router'
import { routerMiddleware } from 'react-router-redux'
import thunkMiddleware from 'redux-thunk'

// useful in production (atleast in this stage of development)
import createLogger from 'redux-logger'

const myMiddleware = store => next => action => {
  if (action.type === '@@router/LOCATION_CHANGE') {
    // scroll up when vising new page
    window.scrollTo(0, 0)
  }
  return next(action)
}

const middleware = applyMiddleware(
  thunkMiddleware, // allows dispatching of functions
  routerMiddleware(browserHistory), // keeps url in sync with app
  myMiddleware, // scroll up when vising new page
  createLogger() // useful logging
)

const enhancer = middleware

export default function configureStore (initialState) {
  return createStore(rootReducer, initialState, enhancer)
};
<|endoftext|>


<commit_before>$(function()
{
	var dfdManager =
	{
		add: function(parentDfd, childDfd)
		{
			childDfd.children = [];
			if(typeof parentDfd.children == 'undefined') parentDfd.children = [];
			parentDfd.children.push(childDfd);
		},
		stop: function(dfd)
		{
			if(typeof dfd.children != 'undefined')
				for(var i in dfd.children)
					dfdManager.stop(dfd.children[i]);
			dfd.reject();
		}
	};

	function chainable(fn, name)
	{
		this.deferred = $.Deferred();
		//this.deferred.progress(function(){ console.log('progress '+this.name+' with', arguments) })
		this.fn = fn;
		this.name = name;
	};
	chainable.prototype.promise = function()
	{
		return this.deferred.promise();
	};
	chainable.prototype.invoke = function()
	{
		this.fn.apply(this, arguments)
		return this;
	};

	/*!
	 * construct
	 */
	function resource()
	{
		var self = this;

		//this.uniqueId = (new Date).getTime();

		this._ = '';

		this.getData = [];
		this.lastAdded = {};
		this.lastUrl = '';
		this.job = [];
		this.initXFrom = false;
		this.respArgs = null;
		this.dataChanged = false;

		this.requestOptions =
		{
			dataType: 'json',
			type: 'get',
			headers: { 'Accept' : 'text/json' }
		};

		var extractListData = function(data)
		{
			var ret = data;
			if( !Array.isArray(data) ) for( i in data )
			{
				if( Array.isArray(data[i]) )
					ret = data[i];
				break;
			}
			return ret;
		};
		this.extractListData = extractListData;

		if( typeof arguments[0] == 'string' )
		{
			self.lastUrl = arguments[0];
			self.request({url : arguments[0] });
			var resolve = null;
			self.initData = new chainable( function()
			{
				if( resolve && !self.dataChanged )
				{
					this.deferred.resolve(resolve);
					return ret;
				};

				if( typeof this.request != 'undefined' ) self.request(this.request);
				return self.doRequest()
					.pipe(function(data)
					{
					    resolve = extractListData(data);
                        self.dataChanged = false;
                        return resolve;
					})
					.then(this.deferred.resolve, this.deferred.reject);
			}, 'initData from ajax');
		}
		else
		{
			var ret = extractListData(arguments[0]);
			this.initData = new chainable(function()
			{
				this.deferred.resolve(ret); return ret;
			}, 'initData with data');
		}

		this.lastAdded = this.initData;

		this.fromData = new chainable(function(data){ this.deferred.resolve(data); }, 'fromInit');
		var fromData = this.fromData,
			self = this;

		fromData.promise().always(function(){ self.initXFrom = false; })
		self.initXFrom = true;
		$.when(this.initData).then(function()
		{
			fromData.invoke.apply(fromData, arguments);
		}, fromData.deferred.reject );

		if(arguments[1]) this.name = arguments[1];

	};

	resource.prototype =
	{
		chainable: chainable,

		/*!
		 * get item from the already existing list
		 */
		from: function(key)
		{
			var self = this,
				args = arguments;

			this.fromData = new chainable( function(list)
			{
				var found = false;
				for( var item in list )
				{
					if( typeof key != 'object' && item != key ) continue;
					found = list[item];
					// for each key check if exists and is the value
					for( keyName in key )
						if(!(keyName in list[item]) || list[item][keyName] != key[keyName])
						{
							found = false;
							break;
						}
					if( found ) break;
				}

				if( !found || typeof found.href == 'undefined' ) return this.deferred.reject();
				var fromUrl = found.href;

				if( args.length > 1 )
				{
					if(typeof args[1] == 'function')
						fromUrl = args[1](found); // filter function for complex structures
					if(typeof args[1] == 'object')
						self.request(args[1]);
					if(typeof args[2] == 'object')
						self.request(args[2]);
				}

				if( typeof this.request != 'undefined' )
					self.request(this.request);

				self.lastUrl = fromUrl;
				return self
					.doRequest(fromUrl)
					.pipe(function(data)
					{
						self.fromData.fn = function()
						{
							this.deferred.resolve(data);
							return data;
						};
						return data;
					})
					.then(this.deferred.resolve, this.deferred.reject);

			}, "from "+key);

			var fromData = this.fromData;
			this.lastAdded = fromData;

			if(!self.initXFrom)
			{
				self.iniXFrom = true;
				$.when(this.initData).then(function(){ fromData.invoke.apply(fromData, arguments); }, fromData.deferred.reject );
			}

			if( typeof this.insideJob != 'undefined' )
				this.insideJob.push(fromData);

			return this;
		},

		/*!
		 * register an operation to obtain a key value from an object node
		 * obtained by the last operation either from or construct
		 */
		get: function(key)
		{
			var self = this;
			var args = arguments;
			var getData = new chainable( function(data)
			{
				var node;
				if( !Array.isArray(data) )
					if( Object.keys(data).length == 1 )
					{
						for( var i in data )
							if( key in data[i] )
								node = data[i][key]
					}
					else if(typeof data[key] != 'undefined') node = data[key];

				if(typeof node == 'undefined')
				{
				    this.deferred.resolve(null);
					return false;
				}

				// assume that we only have a href property provided and we need to follow it to get the entity
				if(typeof node.href == 'string' && Object.keys(node).length == 1)
				{
					var dfd = this.deferred;
					if(typeof args[1] != 'undefined' )
						self.request(args[1]);

					if( typeof this.request != 'undefined' )
						self.request(this.request);

					self.lastUrl = node.href;
					var ajax = self.doRequest(node.href)
						.then(this.deferred.resolve, this.deferred.reject);
					return ajax;
				}
				// assume we have all/the filtered properties
				else
					return this.deferred.resolve(node);
			}, "get "+key);

			this.getData.push(getData);
			this.lastAdded = getData;

			$.when(this.fromData).then(function(){ getData.invoke.apply(getData, arguments); }, getData.deferred.reject );

			if( typeof this.insideJob != 'undefined' )
				this.insideJob.push(getData);

			return this;
		},

		/*!
		 * execute operations and optionally execute a callback
		 */
		done: function()
		{
			if( !this.getData.length )
			{
				var getInit = new chainable(function(data)
				{
					this.deferred.resolve(data);
				}, 'getInit');
				getInit.isInit = true;
				this.getData = [getInit];
				$.when(this.fromData).then(function(){ getInit.invoke.apply(getInit, arguments); }, getInit.deferred.reject );
			}

			var self = this,
				name = arguments[1];

			if( typeof arguments[0] == 'function' )
			{
				var callback = arguments[0],
					failCallback = $.noop;

				if(typeof arguments[1] == 'function')
					failCallback = arguments[1];

				$.when.apply($, this.getData).then(function()
				{
					var args = $.makeArray(arguments);
					if( typeof self.spawned != 'undefined' )
						args = args.concat(self.spawned);
					var result = callback.apply(self, args);
				},
				function()
				{
					failCallback.apply(self, arguments);
				})
				.always(function() // we need to reset at least initData for future chains..
				{
					self.initData = new chainable(self.initData.fn, 'reset');
					self.fromData = new chainable(self.fromData.fn, 'reset');
					self.initXFrom = true;
					$.when(self.initData).then(function()
					{
						self.fromData.invoke.apply(self.fromData, arguments);
					}, self.fromData.deferred.reject );
				});
			}

			var trigger = $.Deferred();
			trigger.resolve();
			var initData = this.initData;
			$.when(trigger).then(function(){ initData.invoke.apply( initData, arguments ); });
			self.getData = [];
			return this;
		},

		resetJob: function()
		{
			if(typeof this.job == 'undefined') return this;
			for(var i in this.job)
				this.job[i].deferred.reject();
			this.job = [];
			return this;
		},

		registerToJob: function(job)
		{
			this.insideJob = job;
			return this;
		},

		/*!
		 * execute this callback regardless of fail or done get operations
		 */
		always: function(callback)
		{
			var self = this;
			var dfd = $.Deferred();
			$.when(dfd).then(function(data)
			{
				if(typeof callback == 'function')
					callback.apply(self, data);
			});
			var progress = this.getData.length;
			var args = [];
			$(this.getData).each(function(i, fn)
			{
				fn.promise().always(function()
				{
					progress--;
					if(arguments.length > 1) // if more than 1 argument put them in an array
						args.splice(i, 0, arguments);
					else // else just the single one
						args.splice(i, 0, arguments[0]);
					if(!progress)
						dfd.resolve(args);
				});
			})
			return this;
		},

		/*!
		 * spawn a new resource rom the last get method called
		 */
		spawn: function()
		{
			var self = this;
			$.when(this.lastAdded).pipe(function(data)
			{
				self.spawned = new resource(data, 'spawned');
				self.spawned.lastUrl = self.lastUrl;
				// TODO add backreference or not?
				return data;
			});
			return this;
		},

		/*!
		 * make the request
		 * @param string url
		 */
		doRequest: function()
		{
			if(typeof arguments[0] == 'string') this.request({url: arguments[0]});
			var self = this,
				ajax = $.ajax(this.requestOptions)
				.always(function(){ self.respArgs = arguments[0]; });
			if(!this.keepXFilter)
				delete this.requestOptions.headers['X-Filter'];
			return ajax;
		},
		responseArgs: function()
		{
			return this.respArgs;
		},
		/*!
		 *
		 */
		update: function(data, url)
		{
			this.request({type: 'post', headers: {'X-HTTP-Method-Override': 'PUT'}, data: data});
			return this.doRequest(url ? url : this.lastUrl);
		},
		/*!
		 *
		 */
		insert: function(data, url)
		{
			this.request({type: 'post', data: data});
			return this.doRequest(url ? url : this.lastUrl);
		},
		/*!
		 *
		 */
		delete: function(data, url)
		{
			this.request({type: 'post', headers: {'X-HTTP-Method-Override': 'DELETE'}, data: data});
			return this.doRequest(url ? url : this.lastUrl);
		},

		/*!
		 * extend request options
		 */
		request: function(options)
		{
			if( options.hasOwnProperty('data') ) this.dataChanged = true;
			$.extend(true, this.requestOptions, options);
			return this;
		},

		/*!
		 * reset request option data, optionally by key
		 */
		resetData: function(key)
		{
			if( !this.requestOptions.data ) return this;
			if( typeof key == 'undefined' ) {
				delete this.requestOptions.data;
				return this;
			}
			delete this.requestOptions.data[key];
			return this;
		},

		/*!
		 *
		 */
		xfilter: function(value)
		{
			this.lastAdded.request = { headers: { 'X-Filter' : value } };
			return this;
		}
	};

	$.extend($, {rest : resource});
});<commit_msg>NR-75 : GUI core plugin refactoring<commit_after>$(function()
{
	var dfdManager =
	{
		add: function(parentDfd, childDfd)
		{
			childDfd.children = [];
			if(typeof parentDfd.children == 'undefined') parentDfd.children = [];
			parentDfd.children.push(childDfd);
		},
		stop: function(dfd)
		{
			if(typeof dfd.children != 'undefined')
				for(var i in dfd.children)
					dfdManager.stop(dfd.children[i]);
			dfd.reject();
		}
	};

	function chainable(fn, name)
	{
		this.deferred = $.Deferred();
		//this.deferred.progress(function(){ console.log('progress '+this.name+' with', arguments) })
		this.fn = fn;
		this.name = name;
	};
	chainable.prototype.promise = function()
	{
		return this.deferred.promise();
	};
	chainable.prototype.invoke = function()
	{
		this.fn.apply(this, arguments)
		return this;
	};

	/*!
	 * construct
	 */
	function resource()
	{
		var self = this;

		//this.uniqueId = (new Date).getTime();

		this._ = '';

		this.getData = [];
		this.lastAdded = {};
		this.lastUrl = '';
		this.job = [];
		this.initXFrom = false;
		this.respArgs = null;
		this.dataChanged = false;

		this.requestOptions =
		{
			dataType: 'json',
			type: 'get',
			headers: { 'Accept' : 'text/json' }
		};

		var extractListData = function(data)
		{
			var ret = data;
			if( !Array.isArray(data) ) for( i in data )
			{
				if( Array.isArray(data[i]) )
					ret = data[i];
				break;
			}
			return ret;
		};
		this.extractListData = extractListData;

		if( typeof arguments[0] == 'string' )
		{
			self.lastUrl = arguments[0];
			self.request({url : arguments[0] });
			var resolve = null;
			self.initData = new chainable( function()
			{
				if( resolve && !self.dataChanged )
				{
					this.deferred.resolve(resolve);
					return ret;
				};

				if( typeof this.request != 'undefined' ) self.request(this.request);
				return self.doRequest()
					.pipe(function(data)
					{
					    resolve = extractListData(data);
                        self.dataChanged = false;
                        return resolve;
					})
					.then(this.deferred.resolve, this.deferred.reject);
			}, 'initData from ajax');
		}
		else
		{
			var ret = extractListData(arguments[0]);
			this.initData = new chainable(function()
			{
				this.deferred.resolve(ret); return ret;
			}, 'initData with data');
		}

		this.lastAdded = this.initData;

		this.fromData = new chainable(function(data){ this.deferred.resolve(data); }, 'fromInit');
		var fromData = this.fromData,
			self = this;

		fromData.promise().always(function(){ self.initXFrom = false; })
		self.initXFrom = true;
		$.when(this.initData).then(function()
		{
			fromData.invoke.apply(fromData, arguments);
		}, fromData.deferred.reject );

		if(arguments[1]) this.name = arguments[1];

	};

	resource.prototype =
	{
		chainable: chainable,

		/*!
		 * get item from the already existing list
		 */
		from: function(key)
		{
			var self = this,
				args = arguments;

			this.fromData = new chainable( function(list)
			{
				var found = false;
				for( var item in list )
				{
					if( typeof key != 'object' && item != key ) continue;
					found = list[item];
					// for each key check if exists and is the value
					for( keyName in key )
						if(!(keyName in list[item]) || list[item][keyName] != key[keyName])
						{
							found = false;
							break;
						}
					if( found ) break;
				}

				if( !found || typeof found.href == 'undefined' ) return this.deferred.reject();
				var fromUrl = found.href;

				if( args.length > 1 )
				{
					if(typeof args[1] == 'function')
						fromUrl = args[1](found); // filter function for complex structures
					if(typeof args[1] == 'object')
						self.request(args[1]);
					if(typeof args[2] == 'object')
						self.request(args[2]);
				}

				if( typeof this.request != 'undefined' )
					self.request(this.request);

				self.lastUrl = fromUrl;
				return self
					.doRequest(fromUrl)
					.pipe(function(data)
					{
						self.fromData.fn = function()
						{
							this.deferred.resolve(data);
							return data;
						};
						return data;
					})
					.then(this.deferred.resolve, this.deferred.reject);

			}, "from "+key);

			var fromData = this.fromData;
			this.lastAdded = fromData;

			if(!self.initXFrom)
			{
				self.iniXFrom = true;
				$.when(this.initData).then(function(){ fromData.invoke.apply(fromData, arguments); }, fromData.deferred.reject );
			}

			if( typeof this.insideJob != 'undefined' )
				this.insideJob.push(fromData);

			return this;
		},

		/*!
		 * register an operation to obtain a key value from an object node
		 * obtained by the last operation either from or construct
		 */
		get: function(key, followHref)
		{
		    var self = this,
                args = arguments;

		    var getData = new chainable( function(data)
			{
				var node;
				if( !Array.isArray(data) )
					if( Object.keys(data).length == 1 )
					{
						for( var i in data )
							if( key in data[i] )
								node = data[i][key]
					}
					else if(typeof data[key] != 'undefined') node = data[key];

				if(typeof node == 'undefined')
				{
				    this.deferred.resolve(null);
					return false;
				}

				// assume that we only have a href property provided and we need to follow it to get the entity
				if( (typeof node.href == 'string' && Object.keys(node).length == 1) || followHref)
				{
					var dfd = this.deferred;
					if(typeof args[1] != 'undefined' )
						self.request(args[1]);

					if( typeof this.request != 'undefined' )
						self.request(this.request);

					self.lastUrl = node.href;
					var ajax = self.doRequest(node.href)
					    .pipe(function(){ return arguments[0] })
						.then(this.deferred.resolve, this.deferred.reject);
					return ajax;
				}
				// assume we have all/the filtered properties
				else
					return this.deferred.resolve(node);
			}, "get "+key);

			this.getData.push(getData);
			this.lastAdded = getData;

			$.when(this.fromData).then(function(){ getData.invoke.apply(getData, arguments); }, getData.deferred.reject );

			if( typeof this.insideJob != 'undefined' )
				this.insideJob.push(getData);

			return this;
		},

		/*!
		 * execute operations and optionally execute a callback
		 */
		done: function()
		{
			if( !this.getData.length )
			{
				var getInit = new chainable(function(data)
				{
					this.deferred.resolve(data);
				}, 'getInit');
				getInit.isInit = true;
				this.getData = [getInit];
				$.when(this.fromData).then(function(){ getInit.invoke.apply(getInit, arguments); }, getInit.deferred.reject );
			}

			var self = this,
				name = arguments[1];

			if( typeof arguments[0] == 'function' )
			{
				var callback = arguments[0],
					failCallback = $.noop;

				if(typeof arguments[1] == 'function')
					failCallback = arguments[1];

				$.when.apply($, this.getData).then(function()
				{
					var args = $.makeArray(arguments);
					if( typeof self.spawned != 'undefined' )
						args = args.concat(self.spawned);
					var result = callback.apply(self, args);
				},
				function()
				{
					failCallback.apply(self, arguments);
				})
				.always(function() // we need to reset at least initData for future chains..
				{
					self.initData = new chainable(self.initData.fn, 'reset');
					self.fromData = new chainable(self.fromData.fn, 'reset');
					self.initXFrom = true;
					$.when(self.initData).then(function()
					{
						self.fromData.invoke.apply(self.fromData, arguments);
					}, self.fromData.deferred.reject );
				});
			}

			var trigger = $.Deferred();
			trigger.resolve();
			var initData = this.initData;
			$.when(trigger).then(function(){ initData.invoke.apply( initData, arguments ); });
			self.getData = [];
			return this;
		},

		resetJob: function()
		{
			if(typeof this.job == 'undefined') return this;
			for(var i in this.job)
				this.job[i].deferred.reject();
			this.job = [];
			return this;
		},

		registerToJob: function(job)
		{
			this.insideJob = job;
			return this;
		},

		/*!
		 * execute this callback regardless of fail or done get operations
		 */
		always: function(callback)
		{
			var self = this;
			var dfd = $.Deferred();
			$.when(dfd).then(function(data)
			{
				if(typeof callback == 'function')
					callback.apply(self, data);
			});
			var progress = this.getData.length;
			var args = [];
			$(this.getData).each(function(i, fn)
			{
				fn.promise().always(function()
				{
					progress--;
					if(arguments.length > 1) // if more than 1 argument put them in an array
						args.splice(i, 0, arguments);
					else // else just the single one
						args.splice(i, 0, arguments[0]);
					if(!progress)
						dfd.resolve(args);
				});
			})
			return this;
		},

		/*!
		 * spawn a new resource rom the last get method called
		 */
		spawn: function()
		{
			var self = this;
			$.when(this.lastAdded).pipe(function(data)
			{
				self.spawned = new resource(data, 'spawned');
				self.spawned.lastUrl = self.lastUrl;
				// TODO add backreference or not?
				return data;
			});
			return this;
		},

		/*!
		 * make the request
		 * @param string url
		 */
		doRequest: function()
		{
			if(typeof arguments[0] == 'string') this.request({url: arguments[0]});
			var self = this,
				ajax = $.ajax(this.requestOptions)
				.always(function(){ self.respArgs = arguments[0]; });
			if(!this.keepXFilter)
				delete this.requestOptions.headers['X-Filter'];
			return ajax;
		},
		responseArgs: function()
		{
			return this.respArgs;
		},
		/*!
		 *
		 */
		update: function(data, url)
		{
			this.request({type: 'post', headers: {'X-HTTP-Method-Override': 'PUT'}, data: data});
			return this.doRequest(url ? url : this.lastUrl);
		},
		/*!
		 *
		 */
		insert: function(data, url)
		{
			this.request({type: 'post', data: data});
			return this.doRequest(url ? url : this.lastUrl);
		},
		/*!
		 *
		 */
		delete: function(data, url)
		{
			this.request({type: 'post', headers: {'X-HTTP-Method-Override': 'DELETE'}, data: data});
			return this.doRequest(url ? url : this.lastUrl);
		},

		/*!
		 * extend request options
		 */
		request: function(options)
		{
			if( options.hasOwnProperty('data') ) this.dataChanged = true;
			$.extend(true, this.requestOptions, options);
			return this;
		},

		/*!
		 * reset request option data, optionally by key
		 */
		resetData: function(key)
		{
			if( !this.requestOptions.data ) return this;
			if( typeof key == 'undefined' ) {
				delete this.requestOptions.data;
				return this;
			}
			delete this.requestOptions.data[key];
			return this;
		},

		/*!
		 *
		 */
		xfilter: function(value)
		{
			this.lastAdded.request = { headers: { 'X-Filter' : value } };
			return this;
		}
	};

	$.extend($, {rest : resource});
});<|endoftext|>