<commit_before>var http = require('http');
var querystring = require('querystring');
var util = require('util');
var events = require('events');

var DEFAULTS = {
  host: '127.0.0.1',
  port: '8983',
  core: '', // if defined, should begin with a slash
  path: '/solr' // should also begin with a slash
};

function Client(options) {
  options = options || {};
  this.options = merge(options, DEFAULTS);
}

exports.Client = Client;

util.inherits(Client, events.EventEmitter);

Client.prototype.request = function(options, callback) {
  var client = this;
  options = options || {};
  options = merge(options, client.options);
  if (!options.headers) options.headers = {};
  options.headers.host = options.host + ':' + options.port;
  var buffer = '';
  var request = http.request(options, function(response) {
    response.on('data', function(chunk) {
      buffer += chunk;
    });
    response.on('end', function() {
      if (response.statusCode !== 200) {
        var err = new Error(exports.getError(buffer));
        err.headers = { status: response.statusCode };
        callback(err);
      } else {
        callback(null, buffer);
      }
    });
  });
  request.on('error', function (e) {
    client.emit('error', e);
    callback(e);
  });
  if (options.data) {
    request.write(options.data, options.requestEncoding || 'utf8');
  }
  request.end();
};

Client.prototype.get = function(getPath, callback) {
  var options = {
    method: 'GET',
    path: this.options.path + this.options.core + '/' + getPath
  };
  this.request(options, callback || noop);
};

Client.prototype.post = function(postPath, data, callback) {
  var options = {
    method: 'POST',
    path: this.options.path + this.options.core + '/' + postPath,
    headers: {
      'Content-Length': Buffer.byteLength(data),
      'Content-Type': 'text/xml'
    },
    data: data
  };
  this.request(options, callback || noop);
};

Client.prototype.update = function(data, callback) {
  this.post("update", data, callback);
};

Client.prototype.add = function(doc, options, callback) {
  if (callback === undefined) {
    callback = options;
    options = {};
  }
  options = options || {};
  var addParams = {};
  if (options.overwrite !== undefined) {
    addParams["overwrite"] = Boolean(options.overwrite);
  }
  if (options.commitWithin !== undefined) {
    addParams["commitWithin"] = options.commitWithin;
  }
  if (options.commit !== undefined) {
    addParams["commit"] = Boolean(options.commit);
  }
  var data = "<add>";
  var docs = Array.isArray(doc) ? doc : [doc];
  for (var i = 0; i < docs.length; i++) {
    data += "<doc>";
    var doc = docs[i];
    for (var field in doc) if (doc.hasOwnProperty(field)) {
      var value = doc[field];
      var params = null;
      switch(true) {
        case (!Array.isArray(value) && typeof value !== "object") :
          data += serializeScalar(field, value);
          break;
        case (!Array.isArray(value) && typeof value === "object") :
          // "value" should have "{params:{k:v,..},value:xx}"
          params = value.params;
          if (Array.isArray(value.value)) {
            data += serializeList(field, value, params);
          } else {
            data += serializeScalar(field, value, params);
          }
          break;
        default :
          data += serializeList(field, value);
      }
    }
    data += "</doc>";
  }
  data += "</add>";
  this.update(data, callback);
};

Client.prototype.del = function(id, query, callback) {
  var data = "<delete>";
  if (id) {
    if (Array.isArray(id)) {
      for (var i=0; i<id.length; i++) {
        data = data + "<id>" + id[i] + "</id>";
      }
    } else {
      data = data + "<id>" + id + "</id>";
    }
  }
  if (query) {
    if (Array.isArray(query)) {
      for (var i=0; i<query.length; i++) {
        data = data + "<query>" + query[i] + "</query>";
      }
    } else {
      data = data + "<query>" + query + "</query>";
    }
  }
  data = data + "</delete>";
  this.update(data, callback);
};

Client.prototype.query = function(query, options, callback) {
  if (callback === undefined) {
    callback = options;
    options = {};
  }
  var queryParams = options || {};
  queryParams.q = query;
  queryParams.wt = "json";
  this.get("select?" + querystring.stringify(queryParams), callback);
};

Client.prototype.commit = function(callback) {
  var data = "<commit/>";
  this.update(data, callback);
};

Client.prototype.optimize = function(callback) {
  var data = "<optimize/>";
  this.update(data, callback);
};

Client.prototype.rollback = function(callback) {
  var data = "<rollback/>";
  this.update(data, callback);
};

// parse status from xml response
exports.getStatus = function(statusMessage) {
  if (!statusMessage) {
    return 1;
  }
  var statusTag = '<int name="status">';
  return statusMessage.charAt(statusMessage.indexOf(statusTag) +
      statusTag.length);
};

// parse error from html response
exports.getError = function(errorMessage) {
  var err = errorMessage.match(/<pre>([\s\S]+)<\/pre>/);
  return (err || ['', errorMessage])[1].trim();
};

// escape dangerous characters in query values
exports.valueEscape = function(query) {
  return query.replace(/\\?([&|+\-!(){}[\]^"~*?\:]{1})/g, function(str, c) {
    return '\\' + c;
  });
};

// main export function
exports.createClient = function(options) {
  var client = new Client(options);
  return client;
};

// Helper functions

// callback || noop borrowed from node/lib/fs.js
function noop() {}

function escapeXml(str) {
  return str.replace(/&/gm, '&')
            .replace(/</gm, '<')
            .replace(/>/gm, '>')
            .replace(/\'/gm, ''')
            .replace(/\"/gm, '"');
}

function merge(a, b){
  if (a && b) {
    for (var key in b) {
      if (typeof a[key] == 'undefined') {
        a[key] = b[key];
      } else if (typeof a[key] == 'object' && typeof b[key] == 'object') {
        a[key] = merge(a[key], b[key]);
      }
    }
  }
  return a;
}

/**
 * Convert the field, value and params into an XML entity
 * @param  {string} field  Name of the field
 * @param  {string} value  Field value
 * @param  {Object} params Optional set of paramaters, key/value set
 * @return {string}        String with the field to be added to the XML document
 */
function serializeScalar(field, value, params) {
  var fieldParams = "";
  params = (typeof params !== 'undefined') ? params : "";

  if (typeof params === "object") {
    for (var key in params) {
      if (params.hasOwnProperty(key)) {
        fieldParams += ' ' + key + '="' + params[key] + '"'
      }
    }
  }
  value = '' + value;
  return '<field name= "' + field + '"' + fieldParams + '>' + escapeXml(value) + '</field>';
}

/**
 * Convert a list of values into a string to be added to the XML main document
 * @param  {string} field Field name
 * @param  {Array} list   List or sub-values
 * @param  {Object} params Optional set of paramaters, key/value set
 * @return {string}       XML elements to be added to the main XML document
 */
function serializeList(field, list, params) {
  var data = '';
  list.forEach(function(value) {
    if (!Array.isArray(value)) {
      data += serializeScalar(field, value, params);
    }
  });
  return data;
}
<commit_msg>Fixing value parameter<commit_after>var http = require('http');
var querystring = require('querystring');
var util = require('util');
var events = require('events');

var DEFAULTS = {
  host: '127.0.0.1',
  port: '8983',
  core: '', // if defined, should begin with a slash
  path: '/solr' // should also begin with a slash
};

function Client(options) {
  options = options || {};
  this.options = merge(options, DEFAULTS);
}

exports.Client = Client;

util.inherits(Client, events.EventEmitter);

Client.prototype.request = function(options, callback) {
  var client = this;
  options = options || {};
  options = merge(options, client.options);
  if (!options.headers) options.headers = {};
  options.headers.host = options.host + ':' + options.port;
  var buffer = '';
  var request = http.request(options, function(response) {
    response.on('data', function(chunk) {
      buffer += chunk;
    });
    response.on('end', function() {
      if (response.statusCode !== 200) {
        var err = new Error(exports.getError(buffer));
        err.headers = { status: response.statusCode };
        callback(err);
      } else {
        callback(null, buffer);
      }
    });
  });
  request.on('error', function (e) {
    client.emit('error', e);
    callback(e);
  });
  if (options.data) {
    request.write(options.data, options.requestEncoding || 'utf8');
  }
  request.end();
};

Client.prototype.get = function(getPath, callback) {
  var options = {
    method: 'GET',
    path: this.options.path + this.options.core + '/' + getPath
  };
  this.request(options, callback || noop);
};

Client.prototype.post = function(postPath, data, callback) {
  var options = {
    method: 'POST',
    path: this.options.path + this.options.core + '/' + postPath,
    headers: {
      'Content-Length': Buffer.byteLength(data),
      'Content-Type': 'text/xml'
    },
    data: data
  };
  this.request(options, callback || noop);
};

Client.prototype.update = function(data, callback) {
  this.post("update", data, callback);
};

Client.prototype.add = function(doc, options, callback) {
  if (callback === undefined) {
    callback = options;
    options = {};
  }
  options = options || {};
  var addParams = {};
  if (options.overwrite !== undefined) {
    addParams["overwrite"] = Boolean(options.overwrite);
  }
  if (options.commitWithin !== undefined) {
    addParams["commitWithin"] = options.commitWithin;
  }
  if (options.commit !== undefined) {
    addParams["commit"] = Boolean(options.commit);
  }
  var data = "<add>";
  var docs = Array.isArray(doc) ? doc : [doc];
  for (var i = 0; i < docs.length; i++) {
    data += "<doc>";
    var doc = docs[i];
    for (var field in doc) if (doc.hasOwnProperty(field)) {
      var value = doc[field];
      var params = null;
      switch(true) {
        case (!Array.isArray(value) && typeof value !== "object") :
          data += serializeScalar(field, value);
          break;
        case (!Array.isArray(value) && typeof value === "object") :
          // "value" should have "{params:{k:v,..},value:xx}"
          params = value.params;
          if (Array.isArray(value.value)) {
            data += serializeList(field, value.value, params);
          } else {
            data += serializeScalar(field, value.value, params);
          }
          break;
        default :
          data += serializeList(field, value);
      }
    }
    data += "</doc>";
  }
  data += "</add>";
  this.update(data, callback);
};

Client.prototype.del = function(id, query, callback) {
  var data = "<delete>";
  if (id) {
    if (Array.isArray(id)) {
      for (var i=0; i<id.length; i++) {
        data = data + "<id>" + id[i] + "</id>";
      }
    } else {
      data = data + "<id>" + id + "</id>";
    }
  }
  if (query) {
    if (Array.isArray(query)) {
      for (var i=0; i<query.length; i++) {
        data = data + "<query>" + query[i] + "</query>";
      }
    } else {
      data = data + "<query>" + query + "</query>";
    }
  }
  data = data + "</delete>";
  this.update(data, callback);
};

Client.prototype.query = function(query, options, callback) {
  if (callback === undefined) {
    callback = options;
    options = {};
  }
  var queryParams = options || {};
  queryParams.q = query;
  queryParams.wt = "json";
  this.get("select?" + querystring.stringify(queryParams), callback);
};

Client.prototype.commit = function(callback) {
  var data = "<commit/>";
  this.update(data, callback);
};

Client.prototype.optimize = function(callback) {
  var data = "<optimize/>";
  this.update(data, callback);
};

Client.prototype.rollback = function(callback) {
  var data = "<rollback/>";
  this.update(data, callback);
};

// parse status from xml response
exports.getStatus = function(statusMessage) {
  if (!statusMessage) {
    return 1;
  }
  var statusTag = '<int name="status">';
  return statusMessage.charAt(statusMessage.indexOf(statusTag) +
      statusTag.length);
};

// parse error from html response
exports.getError = function(errorMessage) {
  var err = errorMessage.match(/<pre>([\s\S]+)<\/pre>/);
  return (err || ['', errorMessage])[1].trim();
};

// escape dangerous characters in query values
exports.valueEscape = function(query) {
  return query.replace(/\\?([&|+\-!(){}[\]^"~*?\:]{1})/g, function(str, c) {
    return '\\' + c;
  });
};

// main export function
exports.createClient = function(options) {
  var client = new Client(options);
  return client;
};

// Helper functions

// callback || noop borrowed from node/lib/fs.js
function noop() {}

function escapeXml(str) {
  return str.replace(/&/gm, '&')
            .replace(/</gm, '<')
            .replace(/>/gm, '>')
            .replace(/\'/gm, ''')
            .replace(/\"/gm, '"');
}

function merge(a, b){
  if (a && b) {
    for (var key in b) {
      if (typeof a[key] == 'undefined') {
        a[key] = b[key];
      } else if (typeof a[key] == 'object' && typeof b[key] == 'object') {
        a[key] = merge(a[key], b[key]);
      }
    }
  }
  return a;
}

/**
 * Convert the field, value and params into an XML entity
 * @param  {string} field  Name of the field
 * @param  {string} value  Field value
 * @param  {Object} params Optional set of paramaters, key/value set
 * @return {string}        String with the field to be added to the XML document
 */
function serializeScalar(field, value, params) {
  var fieldParams = "";
  params = (typeof params !== 'undefined') ? params : "";
  if (typeof params === "object") {
    for (var key in params) {
      if (params.hasOwnProperty(key)) {
        fieldParams += ' ' + key + '="' + params[key] + '"';
      }
    }
  }

  value = '' + value;
  return '<field name="' + field + '"' + fieldParams + '>' + escapeXml(value) + '</field>';
}

/**
 * Convert a list of values into a string to be added to the XML main document
 * @param  {string} field Field name
 * @param  {Array} list   List or sub-values
 * @param  {Object} params Optional set of paramaters, key/value set
 * @return {string}       XML elements to be added to the main XML document
 */
function serializeList(field, list, params) {
  var data = '';
  list.forEach(function(value) {
    if (!Array.isArray(value)) {
      data += serializeScalar(field, value, params);
    }
  });
  return data;
}
<|endoftext|>


<commit_before>/**
 * Load dependencies
 */

var http = require('http'),
   errorParser = require('./error/parser'),
   query = require('./query'),
   format = require('./util/format');

/**
 * Factory to create an instance of Client (Exposed)
 *
 * @param {Object} host - IP address or host address of the Solr Server
 * @param {Object} port - port of the Solr Server
 * @param {Object} core - name of the Solr Core requested
 * @param {Object} path - path used for send requests to the Solr Server
 *
 * @return {Client Object}
 */
exports.createClient = function(host, port, core, path){
  var options = {
      host : host || '127.0.0.1',
      port : port || '8983',
      core : core || '',
      path : path || '/solr'
   };
  return new Client(options);
}

/**
 *
 * @constructor
 * @this {Client}
 * @param {Object} options - Set of parameters used for the connection to the Solr Server
 *
 */

var Client = function(options){
   this.options = options;
   this.data = {};
   this.adds = [];
   this.autoCommit = false;
   this.updateEach = 1;
}

/**
 * Add (a) document(s) to the Solr Database
 *
 * @param {Object} doc - Document added to the Solr Database
 * @param {Function} callback - Function to execute when the Solr Server responds or an error occurs
 *
 * @return {Client Object}
 */

Client.prototype.add = function(doc,callback){
   var self = this;
   doc = format.friendlyze(doc); // Format Date object into string understable for Solr as a date.
   this.adds.push(doc);
   if(this.adds.length >= this.updateEach){
      this.update(this.adds,callback);
      this.adds.splice(0,this.adds.length); // Remove every elements
   }
   return self;
}

/**
 * Add last documents to the Solr Database still kept in the array of added document (usefull when you ask the client to    updateEach X documents, call this function to be sure every single document add are now update on the Solr Database)
 *
 * @param {Function} callback - Function to execute when the Sorl's Server responds or an error occurs
 *
 * @return {Client Object}
 */
Client.prototype.flashAdd =
Client.prototype.purgeAdd =
Client.prototype.flushAdd = function(callback){
   var self = this;
   if(this.adds.length > 0){
      this.update(this.adds,callback);
      this.adds.splice(0,this.adds.length); // Remove every elements
   }else{
      var res = {"responseHeader":{"status":0,"QTime":1}}; // Emulated Solr response
      var err = null;
      callback(err,res);
   }
   return self;
}

/**
 * Commit last added and removed documents in the Solr Database, it's mean your documents are now indexed.
 *
 * @param {Object} options -
 * @param {Function} callback - Function to execute when the Solr Server responds or an error occurs
 *
 * @return {Client Object}
 */

Client.prototype.commit = function(options,callback){
   if(callback === undefined){
      callback = options;
      options = undefined;
   }
   this.data = {};
   this.data['commit'] = {};

   if( options !== undefined ){
      var availableAttributes = ['waitFlush','waitSeacher'];
      for ( var i = 0; i < availableAttributes.length ; i++){
         if ( options[availableAttributes [i]] !== undefined ){
            this.data['commit'][availableAttributes[i]] = options[availableAttributes[i]];
         }
      }
   }
   this.update(this.data,callback);
}

/**
 * Delete a document present in the Solr Database
 *
 * @param {Object} field -
 * @param {Object} text -
 * @param {Function} callback - Function to execute when the Solr Server responds or an error occurs
 *
 * @return {Client Object}
 */

Client.prototype.delete = function(field,text,callback) {
   var self = this;
   text = format.friendlyze(text);
   this.data = {};
   this.data['delete'] =  {query : field +  ':'  + text};
   this.update(this.data,callback);
   return self;
}

/**
 * Delete a range of documents present in the Solr Database
 *
 * @param {Object} field -
 * @param {Object} start - Format expected for a date: yyyy-mm-ddThh:mm:ss.mmmZ (ex:2011-09-06T11:00:25.083Z)
 * @param {Object} stop -
 * @param {Function} callback - Function to execute when the Solr Server responds or an error occurs
 *
 * @return {Client Object}
 */

Client.prototype.deleteByRange = function(field,start,stop,callback){
   var self = this;
   start = format.friendlyze(start);
   stop = format.friendlyze(stop);
   this.data = {};
   this.data['delete'] = { query : field + ':[' + start + ' TO ' + stop + ']' };
   this.update(this.data,callback);
   return self;
}

/**
 * Delete a document present in the Solr Database regarding of the id field.
 *
 * @param {Object} id - ID of the document you want to delete
 * @param {Function} callback - Function to execute when the Solr Server responds or an error occurs
 *
 * @return {Client Object}
 */

Client.prototype.deleteByID = function(id,callback){
   var self = this;
   this.data = {};
   this.data['delete'] =  {id : id.toString()};
   this.update(this.data,callback);
   return self;
}

/**
 * Optimize the index of the Solr Database
 *
 * @param {Object} options -
 * @param {Function} callback - Function to execute when the Solr Server responds or an error occurs
 *
 * @return {Client Object}
 */

Client.prototype.optimize = function(options,callback){
   if(callback === undefined){
      callback = options;
      options = undefined;
   }
   this.data = {};
   this.data['optimize'] = {};
   if( options !== undefined ){
      var availableAttributes = ['waitFlush','waitSearcher'];
      for ( var i = 0; i < availableAttributes.length ; i++){
         if ( options[availableAttributes [i]] !== undefined ){
            this.data['optimize'][availableAttributes[i]] = options[availableAttributes[i]];
         }
      }
   }
   this.update(this.data,callback);
}

/**
 * Rollbacks all add/deletes made to the index since the last commit.
 *
 * @param {Function} callback - Function to execute when the Solr Server responds or an error occurs
 *
 * @return {Client Object}
 */

Client.prototype.rollback = function(callback){
   this.data = {};
   this.data['rollback'] = {};
   this.update(this.data,callback);
}

/**
 * Update document(s) with the parameter `data` in the Solr Database
 *
 * @param {Object} data - object send to the Solr Database
 * @param {Function} callback - Function to execute when the Solr Server responds or an error occurs
 *
 * @return {Client Object}
 */

Client.prototype.update = function(data,callback){
   var self = this;
   this.options.json = JSON.stringify(data);
   this.options.fullPath = [this.options.path,this.options.core,'update/json?commit='+ this.autoCommit +'&wt=json']
                              .filter(function(element){
                                 if(element) return true;
                                 return false;
                              })
                              .join('/');
   console.log(this.options.fullPath);
   updateRequest(this.options,callback);
   return self;
}

/**
 * Query the Solr Database
 *
 * @param {Object} field - Field used for the research
 * @param {Object} text - Text that the research will try to match
 * @param {Number} start - Index of the first document retrieved
 * @param {Number} rows - Number of rows retrieved by the query
 * @param {Function} callback - Function to execute when the Solr Server responds or an error occurs
 *
 * @return {Client Object}
 */

Client.prototype.query = function(query,callback){
   var self = this;
   this.options.fullPath = [this.options.path,this.options.core,'select?' + query.build() + '&wt=json']
                              .filter(function(element){
                                 if(element) return true;
                                 return false;
                              })
                              .join('/'); ;
   queryRequest(this.options,callback);
   return self;
}

/**
 * Query the Solr Database using the Dismax Request Handler
 *
 * @param
 *
 * @return {Query Object}
 */

Client.prototype.createQuery = function(){
   return query.createQuery();
}

/**
 * HTTP POST Request to handle Update of the Solr Database (commit, add, delete, optimize)
 *
 * @param {Object} configs - Set of parameters for the connection to the Solr Server and data sent.
 * @param {Function} callback - Function to execute when the Solr Server responds or an error occurs
 */

var updateRequest = function(configs,callback){
   var headers = {
      "content-type" : "application/json",
      "charset" : "utf-8",
      "content-length":  Buffer.byteLength(configs.json)
   }
   var options = {
      host : configs.host,
      port : configs.port,
      method : 'POST',
      headers : headers,
      path : configs.fullPath
   }
   var callbackResponse = function(res){
      var err = res.statusCode === 200 ? null : res.statusCode;
      var buffer = '';
      res.on('data',function(chunk){
         buffer += chunk;
      });

      res.on('end',function(){
         if(err){
            errorParser.report(buffer,function(msg){
               err = new Error(msg);
            });
         }
         if (callback)  callback(err,buffer);
      });
   }
   var request = http.request(options,callbackResponse);

   request.on('error',function(err){
      if (callback) callback(err,null);
   });
   request.write(configs.json);
   request.end();
}

/**
 * HTTP GET Request to handle Query(ies) on the Solr Database (query)
 *
 * @param {Object} configs - Set of parameters for the connection to the Solr Server and data sent.
 * @param {Function} callback - Function to execute when the Solr Server responds or an error occurs
 */

var queryRequest = function(configs,callback){
   var options = {
      host : configs.host,
      port : configs.port,
      path : configs.fullPath
   }

    var callbackResponse = function(res){
      var err = res.statusCode === 200 ? null : res.statusCode;
      var buffer = '';
      res.on('data',function(chunk){
         buffer += chunk;
      });

      res.on('end',function(){
         if(err){
            errorParser.report(buffer,function(msg){
               err = new Error(msg);
            });
         }
         if (callback)  callback(err,buffer);
      });
   }

   var request = http.get(options,callbackResponse);

   request.on('error',function(err){
      if (callback) callback(err,null);
   });
}
<commit_msg>FIX: Remove console.log() in the Client function update()<commit_after>/**
 * Load dependencies
 */

var http = require('http'),
   errorParser = require('./error/parser'),
   query = require('./query'),
   format = require('./util/format');

/**
 * Factory to create an instance of Client (Exposed)
 *
 * @param {Object} host - IP address or host address of the Solr Server
 * @param {Object} port - port of the Solr Server
 * @param {Object} core - name of the Solr Core requested
 * @param {Object} path - path used for send requests to the Solr Server
 *
 * @return {Client Object}
 */
exports.createClient = function(host, port, core, path){
  var options = {
      host : host || '127.0.0.1',
      port : port || '8983',
      core : core || '',
      path : path || '/solr'
   };
  return new Client(options);
}

/**
 *
 * @constructor
 * @this {Client}
 * @param {Object} options - Set of parameters used for the connection to the Solr Server
 *
 */

var Client = function(options){
   this.options = options;
   this.data = {};
   this.adds = [];
   this.autoCommit = false;
   this.updateEach = 1;
}

/**
 * Add (a) document(s) to the Solr Database
 *
 * @param {Object} doc - Document added to the Solr Database
 * @param {Function} callback - Function to execute when the Solr Server responds or an error occurs
 *
 * @return {Client Object}
 */

Client.prototype.add = function(doc,callback){
   var self = this;
   doc = format.friendlyze(doc); // Format Date object into string understable for Solr as a date.
   this.adds.push(doc);
   if(this.adds.length >= this.updateEach){
      this.update(this.adds,callback);
      this.adds.splice(0,this.adds.length); // Remove every elements
   }
   return self;
}

/**
 * Add last documents to the Solr Database still kept in the array of added document (usefull when you ask the client to    updateEach X documents, call this function to be sure every single document add are now update on the Solr Database)
 *
 * @param {Function} callback - Function to execute when the Sorl's Server responds or an error occurs
 *
 * @return {Client Object}
 */
Client.prototype.flashAdd =
Client.prototype.purgeAdd =
Client.prototype.flushAdd = function(callback){
   var self = this;
   if(this.adds.length > 0){
      this.update(this.adds,callback);
      this.adds.splice(0,this.adds.length); // Remove every elements
   }else{
      var res = {"responseHeader":{"status":0,"QTime":1}}; // Emulated Solr response
      var err = null;
      callback(err,res);
   }
   return self;
}

/**
 * Commit last added and removed documents in the Solr Database, it's mean your documents are now indexed.
 *
 * @param {Object} options -
 * @param {Function} callback - Function to execute when the Solr Server responds or an error occurs
 *
 * @return {Client Object}
 */

Client.prototype.commit = function(options,callback){
   if(callback === undefined){
      callback = options;
      options = undefined;
   }
   this.data = {};
   this.data['commit'] = {};

   if( options !== undefined ){
      var availableAttributes = ['waitFlush','waitSeacher'];
      for ( var i = 0; i < availableAttributes.length ; i++){
         if ( options[availableAttributes [i]] !== undefined ){
            this.data['commit'][availableAttributes[i]] = options[availableAttributes[i]];
         }
      }
   }
   this.update(this.data,callback);
}

/**
 * Delete a document present in the Solr Database
 *
 * @param {Object} field -
 * @param {Object} text -
 * @param {Function} callback - Function to execute when the Solr Server responds or an error occurs
 *
 * @return {Client Object}
 */

Client.prototype.delete = function(field,text,callback) {
   var self = this;
   text = format.friendlyze(text);
   this.data = {};
   this.data['delete'] =  {query : field +  ':'  + text};
   this.update(this.data,callback);
   return self;
}

/**
 * Delete a range of documents present in the Solr Database
 *
 * @param {Object} field -
 * @param {Object} start - Format expected for a date: yyyy-mm-ddThh:mm:ss.mmmZ (ex:2011-09-06T11:00:25.083Z)
 * @param {Object} stop -
 * @param {Function} callback - Function to execute when the Solr Server responds or an error occurs
 *
 * @return {Client Object}
 */

Client.prototype.deleteByRange = function(field,start,stop,callback){
   var self = this;
   start = format.friendlyze(start);
   stop = format.friendlyze(stop);
   this.data = {};
   this.data['delete'] = { query : field + ':[' + start + ' TO ' + stop + ']' };
   this.update(this.data,callback);
   return self;
}

/**
 * Delete a document present in the Solr Database regarding of the id field.
 *
 * @param {Object} id - ID of the document you want to delete
 * @param {Function} callback - Function to execute when the Solr Server responds or an error occurs
 *
 * @return {Client Object}
 */

Client.prototype.deleteByID = function(id,callback){
   var self = this;
   this.data = {};
   this.data['delete'] =  {id : id.toString()};
   this.update(this.data,callback);
   return self;
}

/**
 * Optimize the index of the Solr Database
 *
 * @param {Object} options -
 * @param {Function} callback - Function to execute when the Solr Server responds or an error occurs
 *
 * @return {Client Object}
 */

Client.prototype.optimize = function(options,callback){
   if(callback === undefined){
      callback = options;
      options = undefined;
   }
   this.data = {};
   this.data['optimize'] = {};
   if( options !== undefined ){
      var availableAttributes = ['waitFlush','waitSearcher'];
      for ( var i = 0; i < availableAttributes.length ; i++){
         if ( options[availableAttributes [i]] !== undefined ){
            this.data['optimize'][availableAttributes[i]] = options[availableAttributes[i]];
         }
      }
   }
   this.update(this.data,callback);
}

/**
 * Rollbacks all add/deletes made to the index since the last commit.
 *
 * @param {Function} callback - Function to execute when the Solr Server responds or an error occurs
 *
 * @return {Client Object}
 */

Client.prototype.rollback = function(callback){
   this.data = {};
   this.data['rollback'] = {};
   this.update(this.data,callback);
}

/**
 * Update document(s) with the parameter `data` in the Solr Database
 *
 * @param {Object} data - object send to the Solr Database
 * @param {Function} callback - Function to execute when the Solr Server responds or an error occurs
 *
 * @return {Client Object}
 */

Client.prototype.update = function(data,callback){
   var self = this;
   this.options.json = JSON.stringify(data);
   this.options.fullPath = [this.options.path,this.options.core,'update/json?commit='+ this.autoCommit +'&wt=json']
                              .filter(function(element){
                                 if(element) return true;
                                 return false;
                              })
                              .join('/');
   updateRequest(this.options,callback);
   return self;
}

/**
 * Query the Solr Database
 *
 * @param {Object} field - Field used for the research
 * @param {Object} text - Text that the research will try to match
 * @param {Number} start - Index of the first document retrieved
 * @param {Number} rows - Number of rows retrieved by the query
 * @param {Function} callback - Function to execute when the Solr Server responds or an error occurs
 *
 * @return {Client Object}
 */

Client.prototype.query = function(query,callback){
   var self = this;
   this.options.fullPath = [this.options.path,this.options.core,'select?' + query.build() + '&wt=json']
                              .filter(function(element){
                                 if(element) return true;
                                 return false;
                              })
                              .join('/'); ;
   queryRequest(this.options,callback);
   return self;
}

/**
 * Query the Solr Database using the Dismax Request Handler
 *
 * @param
 *
 * @return {Query Object}
 */

Client.prototype.createQuery = function(){
   return query.createQuery();
}

/**
 * HTTP POST Request to handle Update of the Solr Database (commit, add, delete, optimize)
 *
 * @param {Object} configs - Set of parameters for the connection to the Solr Server and data sent.
 * @param {Function} callback - Function to execute when the Solr Server responds or an error occurs
 */

var updateRequest = function(configs,callback){
   var headers = {
      "content-type" : "application/json",
      "charset" : "utf-8",
      "content-length":  Buffer.byteLength(configs.json)
   }
   var options = {
      host : configs.host,
      port : configs.port,
      method : 'POST',
      headers : headers,
      path : configs.fullPath
   }
   var callbackResponse = function(res){
      var err = res.statusCode === 200 ? null : res.statusCode;
      var buffer = '';
      res.on('data',function(chunk){
         buffer += chunk;
      });

      res.on('end',function(){
         if(err){
            errorParser.report(buffer,function(msg){
               err = new Error(msg);
            });
         }
         if (callback)  callback(err,buffer);
      });
   }
   var request = http.request(options,callbackResponse);

   request.on('error',function(err){
      if (callback) callback(err,null);
   });
   request.write(configs.json);
   request.end();
}

/**
 * HTTP GET Request to handle Query(ies) on the Solr Database (query)
 *
 * @param {Object} configs - Set of parameters for the connection to the Solr Server and data sent.
 * @param {Function} callback - Function to execute when the Solr Server responds or an error occurs
 */

var queryRequest = function(configs,callback){
   var options = {
      host : configs.host,
      port : configs.port,
      path : configs.fullPath
   }

    var callbackResponse = function(res){
      var err = res.statusCode === 200 ? null : res.statusCode;
      var buffer = '';
      res.on('data',function(chunk){
         buffer += chunk;
      });

      res.on('end',function(){
         if(err){
            errorParser.report(buffer,function(msg){
               err = new Error(msg);
            });
         }
         if (callback)  callback(err,buffer);
      });
   }

   var request = http.get(options,callbackResponse);

   request.on('error',function(err){
      if (callback) callback(err,null);
   });
}
<|endoftext|>


<commit_before>/* jslint node: true, esnext: true */

"use strict";

const myScopeReporter = require('scope-reporter'),
	states = require('./states'),
	outEndpoint = require('./endpointOut'),
	inEndpoint = require('./endpointIn'),
	llm = require('loglevel-mixin'),
	scopeDefinitions = require('./scopeDefinitions');

// Steps plain attributes without special handling
// may be extended by some properties like writable,...
const ATTRIBUTES = ['description'];

const BaseStep = {
	"name": "kronos-step",
	"description": "This step is the base class for step implementations",

	/**
	 * Creates the properties for a given object
	 * @param {Object} manager The kronos service manager
	 * @param {String} (mandatory) name The Name of the step
	 * @param {Object} (mandatory) endpoints the pre-populated endpoints
	 * @param {Object} (optional) stepDefinition The step definition
	 *
	 */
	prepareProperties(manager, scopeReporter, name, stepConfiguration, endpoints) {
		let state = "stopped";

		if (!endpoints) {
			endpoints = {};
		}

		// TODO ther is no better way ?
		const type = stepConfiguration.type ? stepConfiguration.type : this.name;

		const props = {
			name: {
				value: name
			},
			type: {
				value: type
			},
			endpoints: {
				value: endpoints
			},
			manager: {
				value: manager
			},
			state: {
				get: function () {
					return state;
				},
				set: function (newState) {
					if (state != newState) {
						const oldState = state;
						state = newState;
						this._stateChanged(oldState, newState);
					}
				}
			},
			/**
			 * @return {Boolean} if step is in a running state
			 */
			isRunning: {
				get: function () {
					return state === 'running' || state === 'starting';
				}
			}
		};

		ATTRIBUTES.forEach(a => {
			if (stepConfiguration[a] !== undefined) {
				props[a] = {
					value: stepConfiguration[a]
				};
			}
		});

		return props;
	},

	/**
	 * Called to initialize step
	 * Please note 'this' is not jet present
	 */
	initialize(manager, scopeReporter, name, stepConfiguration, endpoints, props) {},

	/**
	 * Called when step instance properties are present.
	 *
	 */
	finalize(manager, scopeReporter, stepConfiguration) {},

	/**
	 * This method could be overwritten by a derived object to setup default endpoints.
	 * This method may be overwritten by derived classes.
	 * This will be called by the initialize method
	 * @param {Object} scopeReporter This reporter is used to report parsing errors
	 * @param {Object} stepConfiguration The default step configuration
	 * @api protected
	 */
	createPredefinedEndpoints(manager, scopeReporter, stepConfiguration) {
		const logEndpoint = outEndpoint.createEndpointOut("log", {
			"description": "logging endpoint. All logging goes through this endpoint",
			"out": true,
			"active": true,
			"default": true
		});

		// log endpoint already present
		if (this.endpoints && this.endpoints.log) return;

		this.endpoints.log = logEndpoint;

		// get the default loglevel for this step
		let logLevel = llm.defaultLogLevels[stepConfiguration.logLevel] || llm.defaultLogLevels.info;

		// create the properties to store the loglevel
		llm.defineLogLevelProperties(this, llm.defaultLogLevels, logLevel);

		this.log = function (level, args) {
			if (logEndpoint.isConnected()) {
				logEndpoint.send(args);
			} else {
				console.log(`${level}: ${args}`);
			}
		};
	},

	/**
	 * Creates the endpoint objects defined as a combination from
	 * implementation and definition
	 * @param {Object} manager The service manager
	 * @param {Object} scopeReporter This reporter is used to report parsing errors
	 * @param {Object} impl The json step implementations definition
	 * @param {Object} def The step configuration
	 * @return {Object} endpoints A hash containing the endpoints stored by its name
	 * @api protected
	 */
	createEndpoints(manager, scopeReporter, impl, def) {
		const endpoints = {};

		/*
		 * The definition defines how to use endpoints provided by the implementation.
		 * So it must not be possible to add new endpoints via the definition.
		 * First create the endpoints of the implementation, then configure the
		 * endpoints with the definition
		 */

		let endpointConfiguration;
		for (const endpointName in impl.endpoints) {
			const endpointImplementationDefinition = impl.endpoints[endpointName];

			endpointConfiguration = undefined;
			if (def && def.endpoints && def.endpoints[endpointName]) {
				endpointConfiguration = def.endpoints[endpointName];
				if (typeof endpointConfiguration === 'string') {
					// in this case rebuild the configuration
					endpointConfiguration = {
						"target": endpointConfiguration
					};
					endpointConfiguration = Object.assign({}, endpointImplementationDefinition, endpointConfiguration);
				}
			}

			if (endpointConfiguration) {
				if (endpointConfiguration.in) {
					endpoints[endpointName] = inEndpoint.createEndpointIn(endpointName, endpointConfiguration,
						endpointImplementationDefinition);
				} else {
					endpoints[endpointName] = outEndpoint.createEndpointOut(endpointName, endpointConfiguration,
						endpointImplementationDefinition);
				}

			} else {
				if (endpointImplementationDefinition.in) {
					endpoints[endpointName] = inEndpoint.createEndpointIn(endpointName, endpointImplementationDefinition);
				} else {
					endpoints[endpointName] = outEndpoint.createEndpointOut(endpointName, endpointImplementationDefinition);
				}

				if (endpoints[endpointName].mandatory) {
					scopeReporter.error('Mandatory endpoint not defined', 'endpoint', endpointName);
				}
			}
		}
		return endpoints;
	},

	/**
	 * Sends a 'stepStateChanged' event to the manager.
	 * arguments are:
	 *  step,oldState,newState
	 * @param {String} oldState
	 * @param {String} newState
	 */
	_stateChanged(oldState, newState) {
		this.manager.emit('stepStateChanged', this, oldState, newState);
	},

	/**
	 * Called when state transition is not allowed
	 * @param {String} action
	 * @return {Promise} rejecting with an Error
	 */
	rejectWrongState(action) {
		return Promise.reject(new Error(`Can't ${action} ${this} in ${this.state} state`));
	},

	/**
	 * To be overwritten
	 * Overwrite to implement the functionality to bring the step into the running state.
	 * @return {Promise} default implementation always fullfills with the receiving step
	 */
	_start() {
		return Promise.resolve(this);
	},

	/**
	 * To be overwritten
	 * Overwrite to implement the functionality to bring the step into the stopped state.
	 * @return {Promise} default implementation always fullfills with the receiving step
	 */
	_stop() {
		return Promise.resolve(this);
	},

	/**
	 * To be overwritten.
	 * Tear down every resource as a final step if the the step removal
	 * @return {Promise} default implementation always fullfills with the receiving step
	 */
	_remove() {
		return Promise.resolve(this);
	},

	/**
	 * Returns the string representation of this step
	 * @return {String} human readable name
	 */
	toString() {
		return this.name;
	},

	/**
	 * Deliver json representation
	 * @param {Objects} options
	 *  with the following flags:
	 *    includeRuntimeInfo - include runtime informtion like state
	 *    includeName - name of the step
	 *    includeDefaults - include all properties also the inherited and not overwittern ones
	 * @return json representation
	 */
	toJSONWithOptions(options) {
		const json = {
			type: this.type,
			endpoints: {}
		};

		if (options.includeName) {
			json.name = this.name;
		}

		if (options.includeRuntimeInfo) {
			json.state = this.state;
		}

		for (const endpointName in this.endpoints) {
			if (!this.endpoints[endpointName].default || options.includeDefaults) {
				json.endpoints[endpointName] = this.endpoints[endpointName].toJSON();
			}
		}

		ATTRIBUTES.forEach(a => {
			json[a] = this[a];
		});

		return json;
	},

	toJSON() {
		return this.toJSONWithOptions({
			includeRuntimeInfo: false,
			includeDefaults: false,
			includeName: false
		});
	},

	/**
	 * The endpoints need to know there step. This Function
	 * set all the endpoints the step there are in.
	 */
	updateEndpoints() {
		for (const endpointName in this.endpoints) {
			this.endpoints[endpointName].step = this;
		}
	},

	/**
	 * @return {Step} newly created step
	 */
	createInstance(manager, scopeReporter, stepDefinition) {
		const endpoints = this.createEndpoints(manager, scopeReporter, this, stepDefinition);
		const props = this.prepareProperties(manager, scopeReporter, stepDefinition.name, stepDefinition, endpoints);
		this.initialize(manager, scopeReporter, stepDefinition.name, stepDefinition, endpoints, props);
		const newInstance = Object.create(this, props);
		newInstance.createPredefinedEndpoints(manager, scopeReporter, stepDefinition);
		newInstance.finalize(manager, scopeReporter, stepDefinition);
		newInstance.updateEndpoints();
		return newInstance;
	}
};

/**
 * Adding a start function
 * Brings a step into the running state.
 * @return {Promise} that fullfills with the step in the running state
 */
BaseStep.start = states.transitionFunction(states.transitions.start);

/**
 * Adding a stop function
 * Brings the step into the stopped state
 * @return {Promise} that fullfills with the step in the stopped state
 */
BaseStep.stop = states.transitionFunction(states.transitions.stop);

/**
 * Adding a remove function
 * Brings the step into the removed state
 * @return {Promise} that fullfills with the step in the removed state
 */
BaseStep.remove = states.transitionFunction(states.transitions.remove);

// define the logger methods
llm.defineLoggerMethods(BaseStep, llm.defaultLogLevels, createLogfunction());

/**
 * Returns a logger function.
 */
function createLogfunction() {

	// Set an own function for preparing the stacktrace.
	// this is needed to get the some details later on
	Error.prepareStackTrace = function (err, stackObj) {
		return stackObj[0];
	};

	/**
	 * This function will create the logs.
	 * Uses the GELF log format
	 */
	return function (level, arg) {

		const ll = llm.defaultLogLevels[level];

		const logevent = {
			// "version": "1.1",	Done by the logger step
			// "host": "example.org", Done by the logger step
			//"short_message": "A short message that helps you identify what is going on",
			//"full_message": "Backtrace here\n\nmore stuff",
			"timestamp": Date.now(),
			"level": level,
			// "line": xxxxx, Only available if the 'arg' is an Error object
			"_step-type": this.type,
			"_step-name": this.name,
			"_priority": ll.priority
		};

		if (typeof arg === 'string') {
			logevent.short_message = arg;
		} else if (typeof arg === 'object') {
			if (arg instanceof Error) {
				// The 'arg' is an Error Object
				const stack = arg.stack;

				logevent.line = stack.getLineNumber();
				logevent._file_name = stack.getFileName();
				logevent._error_name = arg.name;
				logevent.short_message = arg.message;
			} else {
				// The 'arg' is a normal object. Copy all the properties

				if (arg.short_message !== undefined) {
					logevent.short_message = arg.short_message;
					delete(arg.short_message);
				}
				if (arg.full_message !== undefined) {
					logevent.full_message = arg.full_message;
					delete(arg.full_message);
				}

				let key;
				for (key in arg) {
					logevent['_' + key] = arg[key];
				}

			}
		}
		if (this.endpoints.log.isConnected()) {
			this.endpoints.log.send(logevent);
		} else {
			console.log(logevent);
		}

	};
}

module.exports.BaseStep = BaseStep;
<commit_msg>fix(debug): disabled Error.prepareStackTrace otherwise moche does not work (for several modules)<commit_after>/* jslint node: true, esnext: true */

"use strict";

const myScopeReporter = require('scope-reporter'),
	states = require('./states'),
	outEndpoint = require('./endpointOut'),
	inEndpoint = require('./endpointIn'),
	llm = require('loglevel-mixin'),
	scopeDefinitions = require('./scopeDefinitions');

// Steps plain attributes without special handling
// may be extended by some properties like writable,...
const ATTRIBUTES = ['description'];

const BaseStep = {
	"name": "kronos-step",
	"description": "This step is the base class for step implementations",

	/**
	 * Creates the properties for a given object
	 * @param {Object} manager The kronos service manager
	 * @param {String} (mandatory) name The Name of the step
	 * @param {Object} (mandatory) endpoints the pre-populated endpoints
	 * @param {Object} (optional) stepDefinition The step definition
	 *
	 */
	prepareProperties(manager, scopeReporter, name, stepConfiguration, endpoints) {
		let state = "stopped";

		if (!endpoints) {
			endpoints = {};
		}

		// TODO ther is no better way ?
		const type = stepConfiguration.type ? stepConfiguration.type : this.name;

		const props = {
			name: {
				value: name
			},
			type: {
				value: type
			},
			endpoints: {
				value: endpoints
			},
			manager: {
				value: manager
			},
			state: {
				get: function () {
					return state;
				},
				set: function (newState) {
					if (state != newState) {
						const oldState = state;
						state = newState;
						this._stateChanged(oldState, newState);
					}
				}
			},
			/**
			 * @return {Boolean} if step is in a running state
			 */
			isRunning: {
				get: function () {
					return state === 'running' || state === 'starting';
				}
			}
		};

		ATTRIBUTES.forEach(a => {
			if (stepConfiguration[a] !== undefined) {
				props[a] = {
					value: stepConfiguration[a]
				};
			}
		});

		return props;
	},

	/**
	 * Called to initialize step
	 * Please note 'this' is not jet present
	 */
	initialize(manager, scopeReporter, name, stepConfiguration, endpoints, props) {},

	/**
	 * Called when step instance properties are present.
	 *
	 */
	finalize(manager, scopeReporter, stepConfiguration) {},

	/**
	 * This method could be overwritten by a derived object to setup default endpoints.
	 * This method may be overwritten by derived classes.
	 * This will be called by the initialize method
	 * @param {Object} scopeReporter This reporter is used to report parsing errors
	 * @param {Object} stepConfiguration The default step configuration
	 * @api protected
	 */
	createPredefinedEndpoints(manager, scopeReporter, stepConfiguration) {
		const logEndpoint = outEndpoint.createEndpointOut("log", {
			"description": "logging endpoint. All logging goes through this endpoint",
			"out": true,
			"active": true,
			"default": true
		});

		// log endpoint already present
		if (this.endpoints && this.endpoints.log) return;

		this.endpoints.log = logEndpoint;

		// get the default loglevel for this step
		let logLevel = llm.defaultLogLevels[stepConfiguration.logLevel] || llm.defaultLogLevels.info;

		// create the properties to store the loglevel
		llm.defineLogLevelProperties(this, llm.defaultLogLevels, logLevel);

		this.log = function (level, args) {
			if (logEndpoint.isConnected()) {
				logEndpoint.send(args);
			} else {
				console.log(`${level}: ${args}`);
			}
		};
	},

	/**
	 * Creates the endpoint objects defined as a combination from
	 * implementation and definition
	 * @param {Object} manager The service manager
	 * @param {Object} scopeReporter This reporter is used to report parsing errors
	 * @param {Object} impl The json step implementations definition
	 * @param {Object} def The step configuration
	 * @return {Object} endpoints A hash containing the endpoints stored by its name
	 * @api protected
	 */
	createEndpoints(manager, scopeReporter, impl, def) {
		const endpoints = {};

		/*
		 * The definition defines how to use endpoints provided by the implementation.
		 * So it must not be possible to add new endpoints via the definition.
		 * First create the endpoints of the implementation, then configure the
		 * endpoints with the definition
		 */

		let endpointConfiguration;
		for (const endpointName in impl.endpoints) {
			const endpointImplementationDefinition = impl.endpoints[endpointName];

			endpointConfiguration = undefined;
			if (def && def.endpoints && def.endpoints[endpointName]) {
				endpointConfiguration = def.endpoints[endpointName];
				if (typeof endpointConfiguration === 'string') {
					// in this case rebuild the configuration
					endpointConfiguration = {
						"target": endpointConfiguration
					};
					endpointConfiguration = Object.assign({}, endpointImplementationDefinition, endpointConfiguration);
				}
			}

			if (endpointConfiguration) {
				if (endpointConfiguration.in) {
					endpoints[endpointName] = inEndpoint.createEndpointIn(endpointName, endpointConfiguration,
						endpointImplementationDefinition);
				} else {
					endpoints[endpointName] = outEndpoint.createEndpointOut(endpointName, endpointConfiguration,
						endpointImplementationDefinition);
				}

			} else {
				if (endpointImplementationDefinition.in) {
					endpoints[endpointName] = inEndpoint.createEndpointIn(endpointName, endpointImplementationDefinition);
				} else {
					endpoints[endpointName] = outEndpoint.createEndpointOut(endpointName, endpointImplementationDefinition);
				}

				if (endpoints[endpointName].mandatory) {
					scopeReporter.error('Mandatory endpoint not defined', 'endpoint', endpointName);
				}
			}
		}
		return endpoints;
	},

	/**
	 * Sends a 'stepStateChanged' event to the manager.
	 * arguments are:
	 *  step,oldState,newState
	 * @param {String} oldState
	 * @param {String} newState
	 */
	_stateChanged(oldState, newState) {
		this.manager.emit('stepStateChanged', this, oldState, newState);
	},

	/**
	 * Called when state transition is not allowed
	 * @param {String} action
	 * @return {Promise} rejecting with an Error
	 */
	rejectWrongState(action) {
		return Promise.reject(new Error(`Can't ${action} ${this} in ${this.state} state`));
	},

	/**
	 * To be overwritten
	 * Overwrite to implement the functionality to bring the step into the running state.
	 * @return {Promise} default implementation always fullfills with the receiving step
	 */
	_start() {
		return Promise.resolve(this);
	},

	/**
	 * To be overwritten
	 * Overwrite to implement the functionality to bring the step into the stopped state.
	 * @return {Promise} default implementation always fullfills with the receiving step
	 */
	_stop() {
		return Promise.resolve(this);
	},

	/**
	 * To be overwritten.
	 * Tear down every resource as a final step if the the step removal
	 * @return {Promise} default implementation always fullfills with the receiving step
	 */
	_remove() {
		return Promise.resolve(this);
	},

	/**
	 * Returns the string representation of this step
	 * @return {String} human readable name
	 */
	toString() {
		return this.name;
	},

	/**
	 * Deliver json representation
	 * @param {Objects} options
	 *  with the following flags:
	 *    includeRuntimeInfo - include runtime informtion like state
	 *    includeName - name of the step
	 *    includeDefaults - include all properties also the inherited and not overwittern ones
	 * @return json representation
	 */
	toJSONWithOptions(options) {
		const json = {
			type: this.type,
			endpoints: {}
		};

		if (options.includeName) {
			json.name = this.name;
		}

		if (options.includeRuntimeInfo) {
			json.state = this.state;
		}

		for (const endpointName in this.endpoints) {
			if (!this.endpoints[endpointName].default || options.includeDefaults) {
				json.endpoints[endpointName] = this.endpoints[endpointName].toJSON();
			}
		}

		ATTRIBUTES.forEach(a => {
			json[a] = this[a];
		});

		return json;
	},

	toJSON() {
		return this.toJSONWithOptions({
			includeRuntimeInfo: false,
			includeDefaults: false,
			includeName: false
		});
	},

	/**
	 * The endpoints need to know there step. This Function
	 * set all the endpoints the step there are in.
	 */
	updateEndpoints() {
		for (const endpointName in this.endpoints) {
			this.endpoints[endpointName].step = this;
		}
	},

	/**
	 * @return {Step} newly created step
	 */
	createInstance(manager, scopeReporter, stepDefinition) {
		const endpoints = this.createEndpoints(manager, scopeReporter, this, stepDefinition);
		const props = this.prepareProperties(manager, scopeReporter, stepDefinition.name, stepDefinition, endpoints);
		this.initialize(manager, scopeReporter, stepDefinition.name, stepDefinition, endpoints, props);
		const newInstance = Object.create(this, props);
		newInstance.createPredefinedEndpoints(manager, scopeReporter, stepDefinition);
		newInstance.finalize(manager, scopeReporter, stepDefinition);
		newInstance.updateEndpoints();
		return newInstance;
	}
};

/**
 * Adding a start function
 * Brings a step into the running state.
 * @return {Promise} that fullfills with the step in the running state
 */
BaseStep.start = states.transitionFunction(states.transitions.start);

/**
 * Adding a stop function
 * Brings the step into the stopped state
 * @return {Promise} that fullfills with the step in the stopped state
 */
BaseStep.stop = states.transitionFunction(states.transitions.stop);

/**
 * Adding a remove function
 * Brings the step into the removed state
 * @return {Promise} that fullfills with the step in the removed state
 */
BaseStep.remove = states.transitionFunction(states.transitions.remove);

// define the logger methods
llm.defineLoggerMethods(BaseStep, llm.defaultLogLevels, createLogfunction());

/**
 * Returns a logger function.
 */
function createLogfunction() {

	// Set an own function for preparing the stacktrace.
	// this is needed to get the some details later on
	/* MF disabled for now prevents mocha from functioning
		Error.prepareStackTrace = function (err, stackObj) {
			return stackObj[0];
		};
	*/

	/**
	 * This function will create the logs.
	 * Uses the GELF log format
	 */
	return function (level, arg) {

		const ll = llm.defaultLogLevels[level];

		const logevent = {
			// "version": "1.1",	Done by the logger step
			// "host": "example.org", Done by the logger step
			//"short_message": "A short message that helps you identify what is going on",
			//"full_message": "Backtrace here\n\nmore stuff",
			"timestamp": Date.now(),
			"level": level,
			// "line": xxxxx, Only available if the 'arg' is an Error object
			"_step-type": this.type,
			"_step-name": this.name,
			"_priority": ll.priority
		};

		if (typeof arg === 'string') {
			logevent.short_message = arg;
		} else if (typeof arg === 'object') {
			if (arg instanceof Error) {
				// The 'arg' is an Error Object
				const stack = arg.stack;

				logevent.line = stack.getLineNumber();
				logevent._file_name = stack.getFileName();
				logevent._error_name = arg.name;
				logevent.short_message = arg.message;
			} else {
				// The 'arg' is a normal object. Copy all the properties

				if (arg.short_message !== undefined) {
					logevent.short_message = arg.short_message;
					delete(arg.short_message);
				}
				if (arg.full_message !== undefined) {
					logevent.full_message = arg.full_message;
					delete(arg.full_message);
				}

				let key;
				for (key in arg) {
					logevent['_' + key] = arg[key];
				}

			}
		}
		if (this.endpoints.log.isConnected()) {
			this.endpoints.log.send(logevent);
		} else {
			console.log(logevent);
		}

	};
}

module.exports.BaseStep = BaseStep;
<|endoftext|>


<commit_before>/*
 * barcode generator - code39
 */

var gm = require('gm');

const bmap = {
	' ': [0,1,1,0,0,0,1,0,0],
	'$': [0,1,0,1,0,1,0,0,0],
	'%': [0,0,0,1,0,1,0,1,0],
	'*': [0,1,0,0,1,0,1,0,0], // Start/stop marker
	'+': [0,1,0,0,0,1,0,1,0],
	'|': [0,1,0,0,0,0,1,0,1],
	'.': [1,1,0,0,0,0,1,0,0],
	'/': [0,1,0,1,0,0,0,1,0],
	'-': [0,1,0,0,0,0,1,0,1],
	'0': [0,0,0,1,1,0,1,0,0],
	'1': [1,0,0,1,0,0,0,0,1],
	'2': [0,0,1,1,0,0,0,0,1],
	'3': [1,0,1,1,0,0,0,0,0],
	'4': [0,0,0,1,1,0,0,0,1],
	'5': [1,0,0,1,1,0,0,0,0],
	'6': [0,0,1,1,1,0,0,0,0],
	'7': [0,0,0,1,0,0,1,0,1],
	'8': [1,0,0,1,0,0,1,0,0],
	'9': [0,0,1,1,0,0,1,0,0],
	'A': [1,0,0,0,0,1,0,0,1],
	'B': [0,0,1,0,0,1,0,0,1],
	'C': [1,0,1,0,0,1,0,0,0],
	'D': [0,0,0,0,1,1,0,0,1],
	'E': [1,0,0,0,1,1,0,0,0],
	'F': [0,0,1,0,1,1,0,0,0],
	'G': [0,0,0,0,0,1,1,0,1],
	'H': [1,0,0,0,0,1,1,0,0],
	'I': [0,0,1,0,0,1,1,0,0],
	'J': [0,0,0,0,1,1,1,0,0],
	'K': [1,0,0,0,0,0,0,1,1],
	'L': [0,0,1,0,0,0,0,1,1],
	'M': [1,0,1,0,0,0,0,1,0],
	'N': [0,0,0,0,1,0,0,1,1],
	'O': [1,0,0,0,1,0,0,1,0],
	'P': [0,0,1,0,1,0,0,1,0],
	'Q': [0,0,0,0,0,0,1,1,1],
	'R': [1,0,0,0,0,0,1,1,0],
	'S': [0,0,1,0,0,0,1,1,0],
	'T': [0,0,0,0,1,0,1,1,0],
	'U': [1,1,0,0,0,0,0,0,1],
	'V': [0,1,1,0,0,0,0,0,1],
	'W': [1,1,1,0,0,0,0,0,0],
	'X': [0,1,0,0,1,0,0,0,1],
	'Y': [1,1,0,0,1,0,0,0,0],
	'Z': [0,1,1,0,1,0,0,0,0]
};

const NARROW_BAR = 20;
const WIDE_BAR = 55;
const QUIET_BAR = 35;
const SYM_LEN = 6 * NARROW_BAR + 3 * WIDE_BAR + QUIET_BAR;

function Code39(data, options) {
  this.options = {
    w: options.width || 0,
    h: options.height || 0,
    bcolor: options.barcolor || '#000000',
    qcolor: options.quietcolor || '#FFFFFF'
  }

  if (!this.options.w || !this.options.h) {
    throw new Error('Width and Height must be non-zero');
  }

  this.data = ('*' + data + '*').toUpperCase();
  var wQuotient = this.options.w / (this.data.length * SYM_LEN - QUIET_BAR);

  this.nBarWidth = NARROW_BAR * wQuotient >> 0;
	this.wBarWidth = WIDE_BAR * wQuotient >> 0;
	this.qBarWidth = QUIET_BAR * wQuotient >> 0;

  console.log("nbar: " + this.nBarWidth);
  console.log("wbar: " + this.wBarWidth);
  console.log("qbar: " + this.qBarWidth);

  if (this.nBarWidth < 1 || this.qBarWidth == this.nBarWidth) {
    throw new Error('Current settings will result in a degenerate barcode');
  }
}

Code39.prototype.saveImage = function (outfile, callback) {
  var img = gm(this.options.w, this.options.h, this.options.qcolor),
    count = 0,
    pos = 0,
    ch,
    w;

  for(var k in this.data) {
    if (count++) {
      pos += this.qBarWidth;
    }

    ch = bmap[this.data[k]] || bmap[' '];
    for(var j in ch) {
      w = ch[j] ? this.wBarWidth : this.nBarWidth;

      if ( !(j % 2) ) {
        img.strokeWidth(1);
        // workaround for GM - cannot set gravity on stroke
        for (var m = 0; m < w; m++) {
          img.drawLine(pos + m, 0, pos + m, this.options.h);
        }
      }

      pos += w;
    }
  }

  img.write(outfile, function (err) {
    callback(err, outfile);
  });
}

Code39.prototype.getBase64 = function (callback) {
}

Code39.prototype.getStream = function (callback) {
}

module.exports = Code39;
<commit_msg>Functional interface, need to abstract the three methods now<commit_after>/*
 * barcode generator - code39
 */

var gm = require('gm'),
  os = require('os'),
  crypto = require('crypto'),
  path = require('path'),
  fs = require('fs');

const bmap = {
	' ': [0,1,1,0,0,0,1,0,0],
	'$': [0,1,0,1,0,1,0,0,0],
	'%': [0,0,0,1,0,1,0,1,0],
	'*': [0,1,0,0,1,0,1,0,0], // Start/stop marker
	'+': [0,1,0,0,0,1,0,1,0],
	'|': [0,1,0,0,0,0,1,0,1],
	'.': [1,1,0,0,0,0,1,0,0],
	'/': [0,1,0,1,0,0,0,1,0],
	'-': [0,1,0,0,0,0,1,0,1],
	'0': [0,0,0,1,1,0,1,0,0],
	'1': [1,0,0,1,0,0,0,0,1],
	'2': [0,0,1,1,0,0,0,0,1],
	'3': [1,0,1,1,0,0,0,0,0],
	'4': [0,0,0,1,1,0,0,0,1],
	'5': [1,0,0,1,1,0,0,0,0],
	'6': [0,0,1,1,1,0,0,0,0],
	'7': [0,0,0,1,0,0,1,0,1],
	'8': [1,0,0,1,0,0,1,0,0],
	'9': [0,0,1,1,0,0,1,0,0],
	'A': [1,0,0,0,0,1,0,0,1],
	'B': [0,0,1,0,0,1,0,0,1],
	'C': [1,0,1,0,0,1,0,0,0],
	'D': [0,0,0,0,1,1,0,0,1],
	'E': [1,0,0,0,1,1,0,0,0],
	'F': [0,0,1,0,1,1,0,0,0],
	'G': [0,0,0,0,0,1,1,0,1],
	'H': [1,0,0,0,0,1,1,0,0],
	'I': [0,0,1,0,0,1,1,0,0],
	'J': [0,0,0,0,1,1,1,0,0],
	'K': [1,0,0,0,0,0,0,1,1],
	'L': [0,0,1,0,0,0,0,1,1],
	'M': [1,0,1,0,0,0,0,1,0],
	'N': [0,0,0,0,1,0,0,1,1],
	'O': [1,0,0,0,1,0,0,1,0],
	'P': [0,0,1,0,1,0,0,1,0],
	'Q': [0,0,0,0,0,0,1,1,1],
	'R': [1,0,0,0,0,0,1,1,0],
	'S': [0,0,1,0,0,0,1,1,0],
	'T': [0,0,0,0,1,0,1,1,0],
	'U': [1,1,0,0,0,0,0,0,1],
	'V': [0,1,1,0,0,0,0,0,1],
	'W': [1,1,1,0,0,0,0,0,0],
	'X': [0,1,0,0,1,0,0,0,1],
	'Y': [1,1,0,0,1,0,0,0,0],
	'Z': [0,1,1,0,1,0,0,0,0]
};

const NARROW_BAR = 20;
const WIDE_BAR = 55;
const QUIET_BAR = 35;
const SYM_LEN = 6 * NARROW_BAR + 3 * WIDE_BAR + QUIET_BAR;

function Code39(data, options) {
  this.options = {
    w: options.width || 0,
    h: options.height || 0,
    bcolor: options.barcolor || '#000000',
    qcolor: options.quietcolor || '#FFFFFF',
    type: options.type || 'PNG'
  }

  if (!this.options.w || !this.options.h) {
    throw new Error('Width and Height must be non-zero');
  }

  this.data = ('*' + data + '*').toUpperCase();
  var wQuotient = this.options.w / (this.data.length * SYM_LEN - QUIET_BAR);

  this.nBarWidth = NARROW_BAR * wQuotient >> 0;
	this.wBarWidth = WIDE_BAR * wQuotient >> 0;
	this.qBarWidth = QUIET_BAR * wQuotient >> 0;

  if (this.nBarWidth < 1 || this.qBarWidth == this.nBarWidth) {
    throw new Error('Current settings will result in a degenerate barcode');
  }
}

Code39.prototype.saveImage = function (outfile, callback) {
  this.getStream(function (err, stream) {
    if (err) return callback(err);

    var ws = fs.createWriteStream(outfile);
    stream.pipe(ws);

    stream.on('end', function () {
      callback(false, outfile);
    });

    // @todo, proper error hanlding here
    stream.on('error', function () {
      callback('error', '')
    });
  });
}

Code39.prototype.getBase64 = function (callback) {
  this.getStream(function (err, stream) {
    if (err) return callback(err, '');

    var imgBufs = [];
    stream.on('data', function (chunk) {
      imgBufs.push(chunk);
    });

    stream.on('end', function () {
      callback(false, Buffer.concat(imgBufs).toString('base64'));
    });

    stream.on('error', function (err) {
      callback(err, '')
    });
  });
}

Code39.prototype.getStream = function (callback) {
  var img = gm(this.options.w, this.options.h, this.options.qcolor),
    count = 0,
    pos = 0,
    ch,
    w;

  img.stroke(this.options.bcolor, 1);

  for(var k in this.data) {
    if (count++) {
      pos += this.qBarWidth;
    }

    ch = bmap[this.data[k]] || bmap[' '];
    for(var j in ch) {
      w = ch[j] ? this.wBarWidth : this.nBarWidth;

      if ( !(j % 2) ) {
        // workaround for GM - cannot set gravity on stroke
        for (var m = 0; m < w; m++) {
          img.drawLine(pos + m, 0, pos + m, this.options.h);
        }
      }

      pos += w;
    }
  }

  img.stream(this.options.type, function (err, stdout, stderr) {
    callback(err, stdout);
  });
  //img.write(outfile, function (err) {
  //  callback(err, outfile);
  //});
}

module.exports = Code39;
<|endoftext|>


<commit_before>// Generated by CoffeeScript 1.9.2
(function() {
  var CloudFormationTemplateContext, CoffeeScript, fs, path, vm,
    bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
    slice = [].slice;

  fs = require('fs');

  vm = require('vm');

  path = require('path');

  CoffeeScript = require('coffee-script');

  CloudFormationTemplateContext = (function() {
    function CloudFormationTemplateContext() {
      this.Description = bind(this.Description, this);
      this.Output = bind(this.Output, this);
      this.Mapping = bind(this.Mapping, this);
      this._resourceByType = bind(this._resourceByType, this);
      this.DeclareResource = bind(this.DeclareResource, this);
      this._buildCall = bind(this._buildCall, this);
      this._paramByType = bind(this._paramByType, this);
      this._resources = {};
      this._parameters = {};
      this._mappings = null;
      this._outputs = {};
      this._description = null;
      this.Params = {};
      this.Resources = {};
      this.Mappings = {};
      this.AWS = {
        AutoScaling: {
          AutoScalingGroup: null,
          LaunchConfiguration: null,
          ScalingPolicy: null,
          LifecycleHook: null,
          ScheduledAction: null,
          Trigger: null
        },
        CloudFormation: {
          Authentication: null,
          CustomResource: null,
          Stack: null,
          WaitCondition: null,
          WaitConditionHandle: null
        },
        CloudFront: {
          Distribution: null
        },
        CloudWatch: {
          Alarm: null
        },
        DynamoDB: {
          Table: null
        },
        EC2: {
          CustomerGateway: null,
          DHCPOptions: null,
          EIP: null,
          EIPAssociation: null,
          Instance: null,
          InternetGateway: null,
          NetworkAcl: null,
          NetworkAclEntry: null,
          NetworkInterface: null,
          Route: null,
          RouteTable: null,
          SecurityGroup: null,
          SecurityGroupIngress: null,
          SecurityGroupEgress: null,
          Subnet: null,
          SubnetNetworkAclAssociation: null,
          SubnetRouteTableAssociation: null,
          Volume: null,
          VolumeAttachment: null,
          VPC: null,
          VPCDHCPOptionsAssociation: null,
          VPCGatewayAttachment: null,
          VPNConnection: null,
          VPNGateway: null
        },
        ElastiCache: {
          CacheCluster: null,
          ParameterGroup: null,
          SecurityGroup: null,
          SecurityGroupIngress: null
        },
        ElasticBeanstalk: {
          Application: null,
          Environment: null
        },
        ElasticLoadBalancing: {
          LoadBalancer: null
        },
        IAM: {
          AccessKey: null,
          Group: null,
          InstanceProfile: null,
          Policy: null,
          Role: null,
          User: null,
          UserToGroupAddition: null
        },
        RDS: {
          DBInstance: null,
          DBParameterGroup: null,
          DBSubnetGroup: null,
          DBSecurityGroup: null,
          DBSecurityGroupIngress: null
        },
        Route53: {
          RecordSet: null,
          RecordSetGroup: null
        },
        SDB: {
          Domain: null
        },
        S3: {
          Bucket: null,
          BucketPolicy: null
        },
        SNS: {
          Topic: null,
          TopicPolicy: null
        },
        SQS: {
          Queue: null,
          QueuePolicy: null
        }
      };
      this.Param = {
        String: (function(_this) {
          return function(name, arg1, arg2) {
            return _this._paramByType('String', name, arg1, arg2);
          };
        })(this),
        Number: (function(_this) {
          return function(name, arg1, arg2) {
            return _this._paramByType('Number', name, arg1, arg2);
          };
        })(this),
        CommaDelimitedList: (function(_this) {
          return function(name, arg1, arg2) {
            return _this._paramByType('CommaDelimitedList', name, arg1, arg2);
          };
        })(this)
      };
      this._buildCall(null, null, 'AWS', this.AWS);
    }

    CloudFormationTemplateContext.prototype._paramByType = function(type, name, arg1, arg2) {
      var result;
      result = {};
      if (arg1 == null) {
        result[name] = {};
      } else if (arg2 == null) {
        result[name] = typeof arg1 === 'string' ? {
          Description: arg1
        } : arg1;
      } else {
        result[name] = arg2;
        result[name].Description = arg1;
      }
      result[name].Type = type;
      this._set(result, this._parameters);
      return this.Params[name] = {
        Ref: name
      };
    };

    CloudFormationTemplateContext.prototype._buildCall = function(parent, lastKey, awsType, leaf) {
      var key, val;
      if (leaf != null) {
        for (key in leaf) {
          val = leaf[key];
          this._buildCall(leaf, key, awsType + "::" + key, val);
        }
        return;
      }
      return parent[lastKey] = (function(_this) {
        return function(name, props) {
          return _this._resourceByType(awsType, name, props);
        };
      })(this);
    };

    CloudFormationTemplateContext.prototype.DeclareResource = function(name) {
      var base;
      return (base = this.Resources)[name] != null ? base[name] : base[name] = {
        Ref: name
      };
    };

    CloudFormationTemplateContext.prototype._resourceByType = function(type, name, props) {
      var result;
      result = {};
      if (((props != null ? props.Metadata : void 0) != null) || ((props != null ? props.Properties : void 0) != null) || ((props != null ? props.DependsOn : void 0) != null) || ((props != null ? props.UpdatePolicy : void 0) != null)) {
        result[name] = props;
        result[name].Type = type;
      } else {
        result[name] = {
          Type: type,
          Properties: props
        };
      }
      this._set(result, this._resources);
      return this.DeclareResource(name);
    };

    CloudFormationTemplateContext.prototype._set = function(source, target) {
      var key, results, val;
      results = [];
      for (key in source) {
        val = source[key];
        results.push(target[key] = val);
      }
      return results;
    };

    CloudFormationTemplateContext.prototype.Mapping = function(name, map) {
      var result;
      if (this._mappings == null) {
        this._mappings = {};
      }
      result = {};
      result[name] = map;
      return this._set(result, this._mappings);
    };

    CloudFormationTemplateContext.prototype.Output = function() {
      var args, name, result;
      name = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
      result = {};
      if (args.length === 1) {
        result[name] = {
          Value: args[0]
        };
      }
      if (args.length === 2) {
        result[name] = {
          Description: args[0],
          Value: args[1]
        };
      }
      return this._set(result, this._outputs);
    };

    CloudFormationTemplateContext.prototype.Description = function(d) {
      return this._description = d;
    };

    CloudFormationTemplateContext.prototype.Tag = function(key, val) {
      return {
        Key: key,
        Value: val
      };
    };

    CloudFormationTemplateContext.prototype.Join = function() {
      var args, delimiter;
      delimiter = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
      if (args.length === 1 && (args[0] instanceof Array)) {
        return {
          'Fn::Join': [delimiter, args[0]]
        };
      } else {
        return {
          'Fn::Join': [delimiter, args]
        };
      }
    };

    CloudFormationTemplateContext.prototype.FindInMap = function() {
      var args;
      args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
      return {
        'Fn::FindInMap': args
      };
    };

    CloudFormationTemplateContext.prototype.GetAtt = function() {
      var args;
      args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
      return {
        'Fn::GetAtt': args
      };
    };

    CloudFormationTemplateContext.prototype.Base64 = function(arg) {
      return {
        'Fn::Base64': arg
      };
    };

    CloudFormationTemplateContext.prototype.GetAZs = function(arg) {
      return {
        'Fn::GetAZs': arg
      };
    };

    CloudFormationTemplateContext.prototype.AccountId = {
      Ref: 'AWS::AccountId'
    };

    CloudFormationTemplateContext.prototype.NotificationARNs = {
      Ref: 'AWS::NotificationARNs'
    };

    CloudFormationTemplateContext.prototype.NoValue = {
      Ref: 'AWS::NoValue'
    };

    CloudFormationTemplateContext.prototype.Region = {
      Ref: 'AWS::Region'
    };

    CloudFormationTemplateContext.prototype.StackId = {
      Ref: 'AWS::StackId'
    };

    CloudFormationTemplateContext.prototype.StackName = {
      Ref: 'AWS::StackName'
    };

    CloudFormationTemplateContext.prototype.InitScript = function(arg) {
      var chunks, compiled, existsSyncFunc, match, pattern, text;
      existsSyncFunc = fs.existsSync != null ? fs.existsSync : path.existsSync;
      if (!existsSyncFunc(arg)) {
        text = arg;
      } else {
        text = fs.readFileSync(arg).toString();
      }
      chunks = [];
      pattern = /((.|\n)*?)%{([^}?]+)}?((.|\n)*)/;
      match = text.match(pattern);
      while (match) {
        chunks.push(match[1]);
        compiled = CoffeeScript.compile(match[3], {
          bare: true
        });
        chunks.push(eval(compiled));
        text = match[4];
        match = text.match(pattern);
      }
      if (text && text.length > 0) {
        chunks.push(text);
      }
      return this.Base64(this.Join('', chunks));
    };

    return CloudFormationTemplateContext;

  })();

  module.exports.CloudFormationTemplateContext = CloudFormationTemplateContext;

  module.exports = function(func) {
    var context, template;
    context = new CloudFormationTemplateContext;
    func.apply(context, [context]);
    template = {
      AWSTemplateFormatVersion: '2010-09-09'
    };
    if (context._description != null) {
      template.Description = context._description;
    }
    template.Parameters = context._parameters;
    if (context._mappings != null) {
      template.Mappings = context._mappings;
    }
    template.Resources = context._resources;
    template.Outputs = context._outputs;
    return template;
  };

  require('pkginfo')(module, 'version');

}).call(this);
<commit_msg>update bin<commit_after>// Generated by CoffeeScript 1.9.2
(function() {
  var CloudFormationTemplateContext, CoffeeScript, fs, path, vm,
    bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
    slice = [].slice;

  fs = require('fs');

  vm = require('vm');

  path = require('path');

  CoffeeScript = require('coffee-script');

  CloudFormationTemplateContext = (function() {
    function CloudFormationTemplateContext() {
      this.Description = bind(this.Description, this);
      this.Output = bind(this.Output, this);
      this.Mapping = bind(this.Mapping, this);
      this._resourceByType = bind(this._resourceByType, this);
      this.DeclareResource = bind(this.DeclareResource, this);
      this._buildCall = bind(this._buildCall, this);
      this._paramByType = bind(this._paramByType, this);
      this._resources = {};
      this._parameters = {};
      this._mappings = null;
      this._outputs = {};
      this._description = null;
      this.Params = {};
      this.Resources = {};
      this.Mappings = {};
      this.AWS = {
        AutoScaling: {
          AutoScalingGroup: null,
          LaunchConfiguration: null,
          ScalingPolicy: null,
          LifecycleHook: null,
          ScheduledAction: null,
          Trigger: null
        },
        CloudFormation: {
          Authentication: null,
          CustomResource: null,
          Stack: null,
          WaitCondition: null,
          WaitConditionHandle: null
        },
        CloudFront: {
          Distribution: null
        },
        CloudWatch: {
          Alarm: null
        },
        DynamoDB: {
          Table: null
        },
        EC2: {
          CustomerGateway: null,
          DHCPOptions: null,
          EIP: null,
          EIPAssociation: null,
          Instance: null,
          InternetGateway: null,
          NetworkAcl: null,
          NetworkAclEntry: null,
          NetworkInterface: null,
          Route: null,
          RouteTable: null,
          SecurityGroup: null,
          SecurityGroupIngress: null,
          SecurityGroupEgress: null,
          Subnet: null,
          SubnetNetworkAclAssociation: null,
          SubnetRouteTableAssociation: null,
          Volume: null,
          VolumeAttachment: null,
          VPC: null,
          VPCDHCPOptionsAssociation: null,
          VPCGatewayAttachment: null,
          VPNConnection: null,
          VPNGateway: null
        },
        ElastiCache: {
          CacheCluster: null,
          ParameterGroup: null,
          SecurityGroup: null,
          SecurityGroupIngress: null
        },
        ElasticBeanstalk: {
          Application: null,
          Environment: null
        },
        ElasticLoadBalancing: {
          LoadBalancer: null
        },
        IAM: {
          AccessKey: null,
          Group: null,
          InstanceProfile: null,
          Policy: null,
          Role: null,
          User: null,
          UserToGroupAddition: null
        },
        Kinesis: {
          Stream: null
        },
        Logs: {
          LogGroup: null,
          MetricFilter: null
        },
        RDS: {
          DBInstance: null,
          DBParameterGroup: null,
          DBSubnetGroup: null,
          DBSecurityGroup: null,
          DBSecurityGroupIngress: null
        },
        Route53: {
          RecordSet: null,
          RecordSetGroup: null
        },
        SDB: {
          Domain: null
        },
        S3: {
          Bucket: null,
          BucketPolicy: null
        },
        SNS: {
          Topic: null,
          TopicPolicy: null
        },
        SQS: {
          Queue: null,
          QueuePolicy: null
        }
      };
      this.Param = {
        String: (function(_this) {
          return function(name, arg1, arg2) {
            return _this._paramByType('String', name, arg1, arg2);
          };
        })(this),
        Number: (function(_this) {
          return function(name, arg1, arg2) {
            return _this._paramByType('Number', name, arg1, arg2);
          };
        })(this),
        CommaDelimitedList: (function(_this) {
          return function(name, arg1, arg2) {
            return _this._paramByType('CommaDelimitedList', name, arg1, arg2);
          };
        })(this)
      };
      this._buildCall(null, null, 'AWS', this.AWS);
    }

    CloudFormationTemplateContext.prototype._paramByType = function(type, name, arg1, arg2) {
      var result;
      result = {};
      if (arg1 == null) {
        result[name] = {};
      } else if (arg2 == null) {
        result[name] = typeof arg1 === 'string' ? {
          Description: arg1
        } : arg1;
      } else {
        result[name] = arg2;
        result[name].Description = arg1;
      }
      result[name].Type = type;
      this._set(result, this._parameters);
      return this.Params[name] = {
        Ref: name
      };
    };

    CloudFormationTemplateContext.prototype._buildCall = function(parent, lastKey, awsType, leaf) {
      var key, val;
      if (leaf != null) {
        for (key in leaf) {
          val = leaf[key];
          this._buildCall(leaf, key, awsType + "::" + key, val);
        }
        return;
      }
      return parent[lastKey] = (function(_this) {
        return function(name, props) {
          return _this._resourceByType(awsType, name, props);
        };
      })(this);
    };

    CloudFormationTemplateContext.prototype.DeclareResource = function(name) {
      var base;
      return (base = this.Resources)[name] != null ? base[name] : base[name] = {
        Ref: name
      };
    };

    CloudFormationTemplateContext.prototype._resourceByType = function(type, name, props) {
      var result;
      result = {};
      if (((props != null ? props.Metadata : void 0) != null) || ((props != null ? props.Properties : void 0) != null) || ((props != null ? props.DependsOn : void 0) != null) || ((props != null ? props.UpdatePolicy : void 0) != null)) {
        result[name] = props;
        result[name].Type = type;
      } else {
        result[name] = {
          Type: type,
          Properties: props
        };
      }
      this._set(result, this._resources);
      return this.DeclareResource(name);
    };

    CloudFormationTemplateContext.prototype._set = function(source, target) {
      var key, results, val;
      results = [];
      for (key in source) {
        val = source[key];
        results.push(target[key] = val);
      }
      return results;
    };

    CloudFormationTemplateContext.prototype.Mapping = function(name, map) {
      var result;
      if (this._mappings == null) {
        this._mappings = {};
      }
      result = {};
      result[name] = map;
      return this._set(result, this._mappings);
    };

    CloudFormationTemplateContext.prototype.Output = function() {
      var args, name, result;
      name = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
      result = {};
      if (args.length === 1) {
        result[name] = {
          Value: args[0]
        };
      }
      if (args.length === 2) {
        result[name] = {
          Description: args[0],
          Value: args[1]
        };
      }
      return this._set(result, this._outputs);
    };

    CloudFormationTemplateContext.prototype.Description = function(d) {
      return this._description = d;
    };

    CloudFormationTemplateContext.prototype.Tag = function(key, val) {
      return {
        Key: key,
        Value: val
      };
    };

    CloudFormationTemplateContext.prototype.Join = function() {
      var args, delimiter;
      delimiter = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
      if (args.length === 1 && (args[0] instanceof Array)) {
        return {
          'Fn::Join': [delimiter, args[0]]
        };
      } else {
        return {
          'Fn::Join': [delimiter, args]
        };
      }
    };

    CloudFormationTemplateContext.prototype.FindInMap = function() {
      var args;
      args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
      return {
        'Fn::FindInMap': args
      };
    };

    CloudFormationTemplateContext.prototype.GetAtt = function() {
      var args;
      args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
      return {
        'Fn::GetAtt': args
      };
    };

    CloudFormationTemplateContext.prototype.Base64 = function(arg) {
      return {
        'Fn::Base64': arg
      };
    };

    CloudFormationTemplateContext.prototype.GetAZs = function(arg) {
      return {
        'Fn::GetAZs': arg
      };
    };

    CloudFormationTemplateContext.prototype.AccountId = {
      Ref: 'AWS::AccountId'
    };

    CloudFormationTemplateContext.prototype.NotificationARNs = {
      Ref: 'AWS::NotificationARNs'
    };

    CloudFormationTemplateContext.prototype.NoValue = {
      Ref: 'AWS::NoValue'
    };

    CloudFormationTemplateContext.prototype.Region = {
      Ref: 'AWS::Region'
    };

    CloudFormationTemplateContext.prototype.StackId = {
      Ref: 'AWS::StackId'
    };

    CloudFormationTemplateContext.prototype.StackName = {
      Ref: 'AWS::StackName'
    };

    CloudFormationTemplateContext.prototype.InitScript = function(arg) {
      var chunks, compiled, existsSyncFunc, match, pattern, text;
      existsSyncFunc = fs.existsSync != null ? fs.existsSync : path.existsSync;
      if (!existsSyncFunc(arg)) {
        text = arg;
      } else {
        text = fs.readFileSync(arg).toString();
      }
      chunks = [];
      pattern = /((.|\n)*?)%{([^}?]+)}?((.|\n)*)/;
      match = text.match(pattern);
      while (match) {
        chunks.push(match[1]);
        compiled = CoffeeScript.compile(match[3], {
          bare: true
        });
        chunks.push(eval(compiled));
        text = match[4];
        match = text.match(pattern);
      }
      if (text && text.length > 0) {
        chunks.push(text);
      }
      return this.Base64(this.Join('', chunks));
    };

    return CloudFormationTemplateContext;

  })();

  module.exports.CloudFormationTemplateContext = CloudFormationTemplateContext;

  module.exports = function(func) {
    var context, template;
    context = new CloudFormationTemplateContext;
    func.apply(context, [context]);
    template = {
      AWSTemplateFormatVersion: '2010-09-09'
    };
    if (context._description != null) {
      template.Description = context._description;
    }
    template.Parameters = context._parameters;
    if (context._mappings != null) {
      template.Mappings = context._mappings;
    }
    template.Resources = context._resources;
    template.Outputs = context._outputs;
    return template;
  };

  require('pkginfo')(module, 'version');

}).call(this);
<|endoftext|>