<commit_before>var _ = require('underscore')
, Emitter = require('okdoki/lib/Emitter').Emitter
;

var ALL_SPACES = / /g;

// ****************************************************************
// ****************** NOTES: **************************************
// ****************************************************************
// Emitters are used only for logging and introspection and inspection.
// They should not be used for adding functionality to error handling
//   and flow control.

// ****************************************************************
// ****************** Helpers *************************************
// ****************************************************************

function throw_it(msg) {
  if (!msg)
    throw new Error('Unknown error');
  if (msg && msg.message)
    throw msg;
  throw new Error("" + msg);
}

function find_job(args) { // ie find job in arguments array
  return _.find(_.flatten(_.toArray(args)), function (v) {
    return v && v.is_job;
  });
}

function origin(unk) {
  return _.last(parents(unk));
};

function parent(unk) {
  return unk.parent_job || unk.river;
}

function parents(unk) {
  if (!parent(unk))
    return [];

  var anc     = [];
  var current = parent(unk);

  while(!current) {
    anc.push(current);
    current = parent(current);
  }

  return parents;
}

function find_parent_in_error(unk) {
  return _.find(parents(unk), function (p) {
    return p && p.has_error();
  });
}

function chain_has_error(unk) {
  return unk.has_error() || !!( find_parent_in_error(unk) );
}

// ****************************************************************
// ****************** Job *****************************************
// ****************************************************************

var Job = function () { this.is_job = true; };
var ERROR_NAMES = ['not_found', 'not_valid', 'error'];

Job.new = function (vals) {
  var me      = new Job();
  me.replys   = [];
  me.result   = undefined;
  me.ON_ERROR = {not_valid: undefined, not_found: undefined, error: undefined};
  me.is_fin   = false;

  // save propertys to job: eg group, id, etc.
  _.each(vals, function (v, k) {
    if (k === 'func' && !_.isFunction(v)) {
      me[k] = function (j) {
        var args = _.toArray(v);
        var obj  = args.shift();
        var meth = args.shift();
        args.push(j);
        return obj[meth].apply( obj, args );
      }
    } else {
      me[k] = v;
    }
  });

  me.finish = function () {
    if (me.is_fin || parent(me).is_finished())
      return null;

    me.is_fin = true;
    var args = arguments;
    var l = args.length;

    if (l > 0)
      me.reply.apply(me, arguments);

    if (!me.has_error())
      return parent(me).finish(me);

    var err  = me.about_error;
    var type = err.type;
    var msg  = err.msg;

    var err_func = me.ON_ERROR[type];
    if (!err_func)
      return parent(me).finish(me);

    var fin = {
      job    : me,
      finish : function () {
        if (arguments.length > 0)
          me.reply.apply(me, arguments);
        return parent(me).finish(me);
      }
    };

    me.ON_ERROR[type] = null;
    return err_func(fin);

  };

  return me;
};

Job.prototype.is_finished = function () {
  return !!this.is_fin;
};

Job.prototype.on = function (type, f) {
  var me = this;
  if (type === 'invalid')
    type = 'not_valid';

  if (type === 'finish') {
    me.FINISHS.push(f);
  } else {
    me.ON_ERROR[type] = f;
  }
  return me;
};

Job.prototype.reply = function () {
  var a = arguments;
  var l = a.length;
  if (l === 1) {
    var rep = a[0];
    if (rep && rep.has_error && rep.has_error()) {
      var err = rep.about_error;
      this.has_error(err.type, err.msg);
    } else {
      this.replys.push(rep);
      this.result = rep;
    }
  } else if (l > 1) {
    var type = arguments[0], msg = arguments[1];
    if (type === 'invalid')
      type = 'not_valid';

    if(!type)
      type = 'error';
    if (!msg)
      msg = 'Unknown error.';

    this.has_error(type, msg);
  }
  return this;
};

Job.prototype.has_error = function (type, msg) {
  var me = this;

  if (!arguments.length)
    return !!me.about_error;

  me.about_error = { msg: msg, type: type };
  return me;
};

Job.prototype.final_finish = function () {
};

// ****************************************************************
// ****************** River ***************************************
// ****************************************************************

function River() {}
exports.River = River;
River.uniq_id = 0;

River.new = function () {

  var me = new River;
  me.job_list     = [];
  me.waits        = [];
  me.ON_ERROR     = {};
  me.FINISHS      = [];
  me.replys       = [];
  me.data         = {};
  me.uniq_job_id  = 0;
  me.is_river     = true;
  me.emitter      = Emitter.new( 'job' );
  me.emitter.delegate(me, 'emit');
  me.parent_job   = find_job(arguments);

  return me;
};

River.prototype.set = function (name, val) {
  this.data[name] = val;
  return this;
};

River.prototype.get = function (name, defut) {
  if (this.data.hasOwnProperty(name))
    return this.data[name];
  return defut;
};

River.prototype.has_error = function (type, msg, job) {
  var me = this;

  if (!arguments.length)
    return !!me.about_error;

  me.is_fin = true;

  me.about_error = {type: type, msg: msg, job: job};
  return me;
};

River.prototype.on = function (type, func) {
  var me = this;
  if (type === 'finish') {
    me.ON_FINISH = func;
  } else if (type.indexOf('job') > -1 || arguments.length === 3) {
    me.emitter.on.apply(me.emitter, arguments);
  } else {
    me.ON_ERROR[type] = func;
  }

  return me;
};

River.prototype.on_next = function (type, func) {
  if (!this.for_next_job)
    this.for_next_job = [];
  this.for_next_job.push([type,func]);
  return this;
};

River.prototype.next_empty = function (raw_f) {
  if (!this.rel_jobs)
    this.rel_jobs = []

  this.rel_jobs.push([ null, null, function (j, last_reply) {
    if (last_reply)
      j.finish(last_reply);
    else
      raw_f.apply(null, arguments);
  }]);
  return this;
};

River.prototype.job = function () {

  var me     = this;
  var args   = _.toArray(arguments);
  var args_l = args.length;
  var job    = null;

  switch (args_l) {
    case 2:
      var func  = args.pop();
      var group = args.pop();
      var id    = args.pop();
      break;
    default:
      var func  = args.pop();
      var id    = args.pop();
      var group = args.pop();
  };

  if (group === undefined)
    group = 'no group';
  if (id === undefined)
    id = ++this.uniq_job_id;

  job = Job.new({
    group     : group,
    id        : id,
    func      : func,
    river     : me,
  });

  _.each((me.for_next_job || []), function (pair) {
    job.on.apply(job, pair);
  });

  me.for_next_job = null;

  me.job_list.push(job);

  var rel_jobs = me.rel_jobs || [];
  me.rel_jobs = null;

  _.each(rel_jobs, function (triple) {
    var args = triple.slice();
    if (!args[0])
      args[0] = job.group;
    if (!args[1])
      args[1] = job.id + '-empty';
    me.job.apply(me, triple);
  });

  return me;
};
River.prototype.reply_counter = -1;
River.prototype.reply = function () {
  var me = this;

  var group = 'save reply', id = ++me.reply_counter, func;
  _.each(arguments, function (v) {
    if (_.isString(v)) {
      if (group)
        id = v;
      else
        group = v;
    } else {
      func = v;
    }
  });

  me.job(group, id, function (j) {
    j.finish(func(j.river.last_reply(), me));
  });

  return me;
};

River.prototype.reply_for = function (group, id) {
  var me = this;
  var reply = me.reply_s_for(group, id);
  return reply[0];
};

River.prototype.replys_for = function (group, id) {
  var me = this;
  var replys = [];
  var use_both = _.compact([group, id]).length === 2;
  _.find(me.replys, function (hash) {
    var name = hash.name;
    if (use_both) {
      if (name === group+':'+id) {
        replys.push(hash.val);
        return true;
      }
    } else {
      if (name.index_of(group+':') > -1)
        replys.push(hash.val);
    }
    return false;
  });

  return replys;
};

River.prototype.first_reply = function () {
  return ( _.first(this.replys) || {} ).val;
};

River.prototype.last_reply = function () {
  return ( _.last(this.replys) || {} ).val;
};

River.prototype.job_finish = function (job) {
  var me = this;

  if (job.has_error()) {
    return me.has_error(job.about_error.type, job.about_error.msg);
  }

  me.replys.push({group: job.group, id: job.id, val: job.result});

  me.emit('after', 'job', job);

  if (!me.waits.length) {
    return me.finish();
  }

  if (me.waits.length)
    me.run_job();

  return null;
};

River.prototype.is_finished = function () {
  var me = this;
  return !!this.is_fin || (parent(me) && parent(me).is_finished());
};

River.prototype.finish = function (j, unk) {
  var me     = this;

  if (me.is_fin)
    return null;

  if (j && j.is_job && !j.has_error())
    return me.job_finish(j);

  me.is_fin = true;

  var args = arguments;

  var fin = {
    river: me,
    finish: function () {
      var args = arguments;
      if (args.length === 2) {
        me.has_error(args[0], args[1]);
      } else if (args.length !== 0) {
        me.has_error('error', 'Unknown arguments: ' + _.toArray(arguments));
      }

      if (parent(me))
        return parent(me).finish(me);

      if (me.has_error())
        throw new Error(me.about_error.type + ': ' + me.about_error.msg);

      return me;
    }
  };

  if (!args.length && !me.waits.length && !me.has_error()) {

    if (me.ON_FINISH) {
      var func = me.ON_FINISH;
      me.ON_FINISH = null;
      return func(fin);
    }

    if (parent(me))
      return parent(me).finish(me.last_reply());

    return null;
  }

  if ((j && j.is_job && j.has_error()) || args.length === 2) {
    if (j && j.is_job)
      me.has_error(j.about_error.type, j.about_error.msg);
    else
      me.has_error(j, unk);

    if (me.ON_ERROR[me.about_error.type]) {
      var func = me.ON_ERROR[me.about_error.type];
      me.ON_ERROR[me.about_error.type] = null;
      return func(fin);
    }
  }

  return fin.finish();
};

River.prototype.verbose = function () {
  this.on('before', 'job', function (j) {
    console['log'](j.group, j.id);
  });
  return this;
};

River.prototype.run_job = function () {
  if (this.has_error())
    return this;
  var me          = this;
  var job = me.job_list[me.waits.shift()];

  me.emit('before', 'job', job);
  job.func(job, me.last_reply());

  // Very little is reached below this line...
  // because:
  //   run_job
  //    finish
  //      run_job
  //        finish
};

River.prototype.run = function (f) {
  if (this.is_running)
    return this.error('Already running.');
  this.is_running = true;

  if (f)
    this.ON_FINISH = f;

  var me     = this;
  this.waits = _.map(this.job_list, function (j, i) {
    return i;
  });

  if ( !this.waits.length ) {
    return this;
  }

  me.run_job();
  return me;
};

River.prototype.error = function (err_or_msg, job) {
  var err= null;
  var me = this;

  if (_.isString(err_or_msg))
    err = new Error(err_or_msg);
  else
    err = err_or_msg;

  var job_had_no_events = (!job || !job.about_error || (job.emitter.events_for(job.about_error.type, 'middle').length === 0));
  if (!origin(me) && !this.emitter.events_for('error', 'middle').length) {
    if (job_had_no_events)
      throw (err || new Error('Unknown error.'));
  }

  if (job_had_no_events)
    this.emit('error', err, job);

  return this;
};

<commit_msg>Fixed: .next_empty runs on whitespace strings.<commit_after>var _ = require('underscore')
, Emitter = require('okdoki/lib/Emitter').Emitter
;

var ALL_SPACES = / /g;

// ****************************************************************
// ****************** NOTES: **************************************
// ****************************************************************
// Emitters are used only for logging and introspection and inspection.
// They should not be used for adding functionality to error handling
//   and flow control.

// ****************************************************************
// ****************** Helpers *************************************
// ****************************************************************

function throw_it(msg) {
  if (!msg)
    throw new Error('Unknown error');
  if (msg && msg.message)
    throw msg;
  throw new Error("" + msg);
}

function find_job(args) { // ie find job in arguments array
  return _.find(_.flatten(_.toArray(args)), function (v) {
    return v && v.is_job;
  });
}

function origin(unk) {
  return _.last(parents(unk));
};

function parent(unk) {
  return unk.parent_job || unk.river;
}

function parents(unk) {
  if (!parent(unk))
    return [];

  var anc     = [];
  var current = parent(unk);

  while(!current) {
    anc.push(current);
    current = parent(current);
  }

  return parents;
}

function find_parent_in_error(unk) {
  return _.find(parents(unk), function (p) {
    return p && p.has_error();
  });
}

function chain_has_error(unk) {
  return unk.has_error() || !!( find_parent_in_error(unk) );
}

// ****************************************************************
// ****************** Job *****************************************
// ****************************************************************

var Job = function () { this.is_job = true; };
var ERROR_NAMES = ['not_found', 'not_valid', 'error'];

Job.new = function (vals) {
  var me      = new Job();
  me.replys   = [];
  me.result   = undefined;
  me.ON_ERROR = {not_valid: undefined, not_found: undefined, error: undefined};
  me.is_fin   = false;

  // save propertys to job: eg group, id, etc.
  _.each(vals, function (v, k) {
    if (k === 'func' && !_.isFunction(v)) {
      me[k] = function (j) {
        var args = _.toArray(v);
        var obj  = args.shift();
        var meth = args.shift();
        args.push(j);
        return obj[meth].apply( obj, args );
      }
    } else {
      me[k] = v;
    }
  });

  me.finish = function () {
    if (me.is_fin || parent(me).is_finished())
      return null;

    me.is_fin = true;
    var args = arguments;
    var l = args.length;

    if (l > 0)
      me.reply.apply(me, arguments);

    if (!me.has_error())
      return parent(me).finish(me);

    var err  = me.about_error;
    var type = err.type;
    var msg  = err.msg;

    var err_func = me.ON_ERROR[type];
    if (!err_func)
      return parent(me).finish(me);

    var fin = {
      job    : me,
      finish : function () {
        if (arguments.length > 0)
          me.reply.apply(me, arguments);
        return parent(me).finish(me);
      }
    };

    me.ON_ERROR[type] = null;
    return err_func(fin);

  };

  return me;
};

Job.prototype.is_finished = function () {
  return !!this.is_fin;
};

Job.prototype.on = function (type, f) {
  var me = this;
  if (type === 'invalid')
    type = 'not_valid';

  if (type === 'finish') {
    me.FINISHS.push(f);
  } else {
    me.ON_ERROR[type] = f;
  }
  return me;
};

Job.prototype.reply = function () {
  var a = arguments;
  var l = a.length;
  if (l === 1) {
    var rep = a[0];
    if (rep && rep.has_error && rep.has_error()) {
      var err = rep.about_error;
      this.has_error(err.type, err.msg);
    } else {
      this.replys.push(rep);
      this.result = rep;
    }
  } else if (l > 1) {
    var type = arguments[0], msg = arguments[1];
    if (type === 'invalid')
      type = 'not_valid';

    if(!type)
      type = 'error';
    if (!msg)
      msg = 'Unknown error.';

    this.has_error(type, msg);
  }
  return this;
};

Job.prototype.has_error = function (type, msg) {
  var me = this;

  if (!arguments.length)
    return !!me.about_error;

  me.about_error = { msg: msg, type: type };
  return me;
};

Job.prototype.final_finish = function () {
};

// ****************************************************************
// ****************** River ***************************************
// ****************************************************************

function River() {}
exports.River = River;
River.uniq_id = 0;

River.new = function () {

  var me = new River;
  me.job_list     = [];
  me.waits        = [];
  me.ON_ERROR     = {};
  me.FINISHS      = [];
  me.replys       = [];
  me.data         = {};
  me.uniq_job_id  = 0;
  me.is_river     = true;
  me.emitter      = Emitter.new( 'job' );
  me.emitter.delegate(me, 'emit');
  me.parent_job   = find_job(arguments);

  return me;
};

River.prototype.set = function (name, val) {
  this.data[name] = val;
  return this;
};

River.prototype.get = function (name, defut) {
  if (this.data.hasOwnProperty(name))
    return this.data[name];
  return defut;
};

River.prototype.has_error = function (type, msg, job) {
  var me = this;

  if (!arguments.length)
    return !!me.about_error;

  me.is_fin = true;

  me.about_error = {type: type, msg: msg, job: job};
  return me;
};

River.prototype.on = function (type, func) {
  var me = this;
  if (type === 'finish') {
    me.ON_FINISH = func;
  } else if (type.indexOf('job') > -1 || arguments.length === 3) {
    me.emitter.on.apply(me.emitter, arguments);
  } else {
    me.ON_ERROR[type] = func;
  }

  return me;
};

River.prototype.on_next = function (type, func) {
  if (!this.for_next_job)
    this.for_next_job = [];
  this.for_next_job.push([type,func]);
  return this;
};

River.prototype.next_empty = function (raw_f) {
  if (!this.rel_jobs)
    this.rel_jobs = []

  this.rel_jobs.push([ null, null, function (j, last_reply) {
    if (!last_reply || (_.isString(last_reply) && last_reply.trim() === '') )
      raw_f.apply(null, arguments);
    else
      j.finish(last_reply);
  }]);
  return this;
};

River.prototype.job = function () {

  var me     = this;
  var args   = _.toArray(arguments);
  var args_l = args.length;
  var job    = null;

  switch (args_l) {
    case 2:
      var func  = args.pop();
      var group = args.pop();
      var id    = args.pop();
      break;
    default:
      var func  = args.pop();
      var id    = args.pop();
      var group = args.pop();
  };

  if (group === undefined)
    group = 'no group';
  if (id === undefined)
    id = ++this.uniq_job_id;

  job = Job.new({
    group     : group,
    id        : id,
    func      : func,
    river     : me,
  });

  _.each((me.for_next_job || []), function (pair) {
    job.on.apply(job, pair);
  });

  me.for_next_job = null;

  me.job_list.push(job);

  var rel_jobs = me.rel_jobs || [];
  me.rel_jobs = null;

  _.each(rel_jobs, function (triple) {
    var args = triple.slice();
    if (!args[0])
      args[0] = job.group;
    if (!args[1])
      args[1] = job.id + '-empty';
    me.job.apply(me, triple);
  });

  return me;
};
River.prototype.reply_counter = -1;
River.prototype.reply = function () {
  var me = this;

  var group = 'save reply', id = ++me.reply_counter, func;
  _.each(arguments, function (v) {
    if (_.isString(v)) {
      if (group)
        id = v;
      else
        group = v;
    } else {
      func = v;
    }
  });

  me.job(group, id, function (j) {
    j.finish(func(j.river.last_reply(), me));
  });

  return me;
};

River.prototype.reply_for = function (group, id) {
  var me = this;
  var reply = me.reply_s_for(group, id);
  return reply[0];
};

River.prototype.replys_for = function (group, id) {
  var me = this;
  var replys = [];
  var use_both = _.compact([group, id]).length === 2;
  _.find(me.replys, function (hash) {
    var name = hash.name;
    if (use_both) {
      if (name === group+':'+id) {
        replys.push(hash.val);
        return true;
      }
    } else {
      if (name.index_of(group+':') > -1)
        replys.push(hash.val);
    }
    return false;
  });

  return replys;
};

River.prototype.first_reply = function () {
  return ( _.first(this.replys) || {} ).val;
};

River.prototype.last_reply = function () {
  return ( _.last(this.replys) || {} ).val;
};

River.prototype.job_finish = function (job) {
  var me = this;

  if (job.has_error()) {
    return me.has_error(job.about_error.type, job.about_error.msg);
  }

  me.replys.push({group: job.group, id: job.id, val: job.result});

  me.emit('after', 'job', job);

  if (!me.waits.length) {
    return me.finish();
  }

  if (me.waits.length)
    me.run_job();

  return null;
};

River.prototype.is_finished = function () {
  var me = this;
  return !!this.is_fin || (parent(me) && parent(me).is_finished());
};

River.prototype.finish = function (j, unk) {
  var me     = this;

  if (me.is_fin)
    return null;

  if (j && j.is_job && !j.has_error())
    return me.job_finish(j);

  me.is_fin = true;

  var args = arguments;

  var fin = {
    river: me,
    finish: function () {
      var args = arguments;
      if (args.length === 2) {
        me.has_error(args[0], args[1]);
      } else if (args.length !== 0) {
        me.has_error('error', 'Unknown arguments: ' + _.toArray(arguments));
      }

      if (parent(me))
        return parent(me).finish(me);

      if (me.has_error())
        throw new Error(me.about_error.type + ': ' + me.about_error.msg);

      return me;
    }
  };

  if (!args.length && !me.waits.length && !me.has_error()) {

    if (me.ON_FINISH) {
      var func = me.ON_FINISH;
      me.ON_FINISH = null;
      return func(fin);
    }

    if (parent(me))
      return parent(me).finish(me.last_reply());

    return null;
  }

  if ((j && j.is_job && j.has_error()) || args.length === 2) {
    if (j && j.is_job)
      me.has_error(j.about_error.type, j.about_error.msg);
    else
      me.has_error(j, unk);

    if (me.ON_ERROR[me.about_error.type]) {
      var func = me.ON_ERROR[me.about_error.type];
      me.ON_ERROR[me.about_error.type] = null;
      return func(fin);
    }
  }

  return fin.finish();
};

River.prototype.verbose = function () {
  this.on('before', 'job', function (j) {
    console['log'](j.group, j.id);
  });
  return this;
};

River.prototype.run_job = function () {
  if (this.has_error())
    return this;
  var me          = this;
  var job = me.job_list[me.waits.shift()];

  me.emit('before', 'job', job);
  job.func(job, me.last_reply());

  // Very little is reached below this line...
  // because:
  //   run_job
  //    finish
  //      run_job
  //        finish
};

River.prototype.run = function (f) {
  if (this.is_running)
    return this.error('Already running.');
  this.is_running = true;

  if (f)
    this.ON_FINISH = f;

  var me     = this;
  this.waits = _.map(this.job_list, function (j, i) {
    return i;
  });

  if ( !this.waits.length ) {
    return this;
  }

  me.run_job();
  return me;
};

River.prototype.error = function (err_or_msg, job) {
  var err= null;
  var me = this;

  if (_.isString(err_or_msg))
    err = new Error(err_or_msg);
  else
    err = err_or_msg;

  var job_had_no_events = (!job || !job.about_error || (job.emitter.events_for(job.about_error.type, 'middle').length === 0));
  if (!origin(me) && !this.emitter.events_for('error', 'middle').length) {
    if (job_had_no_events)
      throw (err || new Error('Unknown error.'));
  }

  if (job_had_no_events)
    this.emit('error', err, job);

  return this;
};

<|endoftext|>


<commit_before>(function() {
    angular
        .module("bibframeEditor")
        .directive("scribePopover", ["$q", "$timeout", "$document", "$position", "Resolver", ScribePopoverDirective]);

    function ScribePopoverDirective($q, $timeout, $document, $position, Resolver) {
        function resolve(uri) {
            var deferred = $q.defer();
            Resolver.resolve({"uri": uri}).$promise.then(function(data) {
                deferred.resolve(data.raw);
            }).catch(function(data) {
                deferred.reject("No additional data could be found.");
            });
            return deferred.promise;
        }

        function getAttr(attrs, name) {
            var prefix = "scribePopover";
            if (angular.isDefined(attrs[prefix + name])) {
                return attrs[prefix + name];
            } else {
                return null;
            }
        }

        return {
            restrict: "A",
            link: function(scope, el, atts) {
                var delay, trigger, cancel, to, tt, ttClick, docClick, docType, show, stop, destroy;

                delay = parseInt(getAttr(atts, "Delay"), 10);
                trigger = getAttr(atts, "Trigger");
                cancel = getAttr(atts, "Cancel");
                to = null;

                show = function() {
                    if (!to) {
                        to = $timeout(function() {
                            resolve(getAttr(atts, "Resource")).then(function(h) {
                                var esc, pos;
                                $document.triggerHandler("scribePopoverOpened");
                                esc = h.replace(/</g,"<").replace(/>/g,">");
                                // @@@ make this a template?
                                tt = angular.element('

<' + getAttr(atts, "Resource") + '>

' + esc + '

');
                                $document.find("body").append(tt);
                                tt.css({ top: 0, left: 0, display: "block" });
                                pos = $position.positionElements(el, tt, "right", true);
                                pos.top += "px";
                                pos.left += "px";
                                tt.css(pos);
                                // do not destroy if tt clicked directly
                                ttClick = tt.on("click", function(evt) {
                                    evt.stopPropagation();
                                });
                            });
                        }, delay, false);
                    }
                };

                stop = function() {
                    if (to) {
                        $timeout.cancel(to);
                        to = null;
                    }
                };

                destroy = function() {
                    if (tt) {
                        tt.unbind("click", ttClick);
                        $document.unbind("click", docClick);
                        $document.unbind("keypress", docType);
                        tt.remove();
                        tt = null
                    }
                };

                if (trigger !== null) {
                    el.bind(trigger, show);
                }

                if (cancel !== null) {
                    el.bind(cancel, stop);
                }

                /**
                 * Remove popover on:
                 *  autocomplete change (cancel, changing query)
                 */
                docClick = $document.on("click", destroy);
                docType = $document.on("keypress", destroy);
                $document.on("scribePopoverOpened", destroy);
            }
        };
    }
})();
<commit_msg>also stop in destroy<commit_after>(function() {
    angular
        .module("bibframeEditor")
        .directive("scribePopover", ["$q", "$timeout", "$document", "$position", "Resolver", ScribePopoverDirective]);

    function ScribePopoverDirective($q, $timeout, $document, $position, Resolver) {
        function resolve(uri) {
            var deferred = $q.defer();
            Resolver.resolve({"uri": uri}).$promise.then(function(data) {
                deferred.resolve(data.raw);
            }).catch(function(data) {
                deferred.reject("No additional data could be found.");
            });
            return deferred.promise;
        }

        function getAttr(attrs, name) {
            var prefix = "scribePopover";
            if (angular.isDefined(attrs[prefix + name])) {
                return attrs[prefix + name];
            } else {
                return null;
            }
        }

        return {
            restrict: "A",
            link: function(scope, el, atts) {
                var delay, trigger, cancel, to, tt, ttClick, docClick, docType, show, stop, destroy;

                delay = parseInt(getAttr(atts, "Delay"), 10);
                trigger = getAttr(atts, "Trigger");
                cancel = getAttr(atts, "Cancel");
                to = null;

                show = function() {
                    if (!to) {
                        to = $timeout(function() {
                            resolve(getAttr(atts, "Resource")).then(function(h) {
                                var esc, pos;
                                $document.triggerHandler("scribePopoverOpened");
                                esc = h.replace(/</g,"<").replace(/>/g,">");
                                // @@@ make this a template?
                                tt = angular.element('

<' + getAttr(atts, "Resource") + '>

' + esc + '

');
                                $document.find("body").append(tt);
                                tt.css({ top: 0, left: 0, display: "block" });
                                pos = $position.positionElements(el, tt, "right", true);
                                pos.top += "px";
                                pos.left += "px";
                                tt.css(pos);
                                // do not destroy if tt clicked directly
                                ttClick = tt.on("click", function(evt) {
                                    evt.stopPropagation();
                                });
                            });
                        }, delay, false);
                    }
                };

                stop = function() {
                    if (to) {
                        $timeout.cancel(to);
                        to = null;
                    }
                };

                destroy = function() {
                    stop();
                    if (tt) {
                        tt.unbind("click", ttClick);
                        $document.unbind("click", docClick);
                        $document.unbind("keypress", docType);
                        tt.remove();
                        tt = null
                    }
                };

                if (trigger !== null) {
                    el.bind(trigger, show);
                }

                if (cancel !== null) {
                    el.bind(cancel, stop);
                }

                docClick = $document.on("click", destroy);
                docType = $document.on("keypress", destroy);
                $document.on("scribePopoverOpened", destroy);
            }
        };
    }
})();
<|endoftext|>


<commit_before>'use strict';
module.exports = function (app) {
	var path = require('path');
	var bodyParser = require('body-parser');
	var publishedPages = require('./middleware/publishedPages');
	var queuedPages = require('./middleware/queuedPages');
	var draftPages = require('./middleware/draftPages');
	var deletedPages = require('./middleware/deletedPages');

	var jsonParser = bodyParser.json();

	app.get('/admin/', function (req,res) {

		var file = path.normalize(path.join(__dirname, '../templates/index.html'));
		res.status(200).sendFile(file);
	});

	app.get('/admin/login', function (req, res) {

	});
	app.post('/admin/login', function (req, res) {

	});

	app.get('/admin/logout', function (req, res) {

	});

	app.get('/admin/css/style.css', function (req, res) {
		var path = require('path');
		var file = path.normalize(path.join(__dirname, '../templates/css/style.css' ));
		res.status(200).sendFile(file);
	});
	app.get('/admin/fonts/fontawesome-webfont.woff2', function (req, res) {
		var path = require('path');
		var file = path.normalize(path.join(__dirname, '../node_modules/font-awesome/fonts/fontawesome-webfont.woff2' ));
		res.status(200).sendFile(file);
	});
	app.get('/admin/fonts/fontawesome-webfont.woff', function (req, res) {
		var path = require('path');
		var file = path.normalize(path.join(__dirname,'../node_modules/font-awesome/fonts/fontawesome-webfont.woff' ));
		res.status(200).sendFile(file);
	});
		app.get('/admin/fonts/fontawesome-webfont.ttf', function (req, res) {
		var path = require('path');
		var file = path.normalize(path.join(__dirname, '../node_modules/font-awesome/fonts/fontawesome-webfont.ttf' ));
		res.status(200).sendFile(file);
	});
	app.get('/admin/js/app.js', function (req, res) {
		var path = require('path');
		var file = path.normalize(path.join(__dirname, '../templates/js/app.js' ));
		res.status(200).sendFile(file);
	});
	app.get('/admin/js/react.js', function (req, res) {
		var path = require('path');
		var file = path.normalize(path.join(__dirname, '../templates/js/app.js' ));
		res.status(200).sendFile(file);
	});
	app.get('/admin/js/app.js.map', function (req, res) {
		var path = require('path');
		var file = path.normalize(path.join(__dirname, '../templates/js/app.js.map' ));
		res.status(200).sendFile(file);
	});

	app.get('/xms/api/pages/published', publishedPages, function (req, res) {
		res.send(req.xmsData.publishedPages);
	});
	app.get('/xms/api/pages/queued', queuedPages, function (req, res) {
		res.send(req.xmsData.queuedPages);
	});
	app.get('/xms/api/pages/draft', draftPages, function (req, res) {
		res.send(req.xmsData.draftPages);
	});
	app.get('/xms/api/pages/deleted', deletedPages, function (req, res) {
		res.send(req.xmsData.deletedPages);
	});
	app.get('/xms/api/settings', function (req, res) {
		var settings = require('mongo-start')('settings');

		settings.find(function (err, docs) {
			res.send(docs);
		})
	});
	app.post('/xms/api/pages', jsonParser, function (req, res) {
		console.log('yup up:');
		var pages = require('mongo-start')('pages');
		var Joi = require('joi');

		var schema = Joi.object().keys({
		    title: Joi.string().min(3).max(50).required(),
		    view: Joi.string().min(3).max(50).required(),
		    route: Joi.string().min(1).max(50).required(),
		    description: Joi.string().min(0).max(75),
		    content: Joi.string().min(5).max(5050).required(),
		    createdBy: Joi.string().min(3).max(50).required(),
		    createdOn: Joi.date(),
		});
		var cheerio = require('cheerio');
		var $c = cheerio.load(req.body.content);

		var content = $c.removeAttr('data-reactid').html();

		var newpage = {
			title: req.body.title,
			view: req.body.view,
			description:req.body.description,
			content: content,
			route: req.body.route,
			createdBy: 'some user',
			createdOn: Date.now()
		};
		console.log(newpage);
		Joi.validate(newpage, schema, function (err, value) {
			console.log('validated');
			console.log(err);
			if(err) {
				res.json(err);//validation errors, handle that clientside
			}
			console.log(pages);

			pages.save(newpage, function (err, docs) {
				console.log(err);
				res.sendStatus(200);
			});
		});

	});
	app.post('/xms/api/pages/:id', function (req, res) {
		var pages = require('mongo-start')('pages');
		pages.findOne({
			    _id:mongojs.ObjectId(req.params._id)
			},function (err, doc) {
			res.json(doc);
		})
	});
	app.get('/xms/api/pages/:id', function (req, res) {
		var pages = require('mongo-start')('pages');
		pages.findOne({
			    _id:mongojs.ObjectId(req.params._id)
			},function (err, doc) {
			res.json(doc);
		})
	});

};<commit_msg>Passport Authentication<commit_after>'use strict';
module.exports = function (app) {

    var session = require('express-session');
    var mongojs = require('mongo-start').mongojs;
    var MongoSession = require('express-mongo-session');
    app.use(session({
        secret: 'xms is the name',
        resave: false,
        saveUninitialized: false,
        store: new MongoSession()
    }));

    var flash = require('connect-flash');
    app.use(flash());
    var path = require('path');
    var bodyParser = require('body-parser');
    var publishedPages = require('./middleware/publishedPages');
    var queuedPages = require('./middleware/queuedPages');
    var draftPages = require('./middleware/draftPages');
    var deletedPages = require('./middleware/deletedPages');
    var auth = require('./middleware/auth');
    var config = require('xtconf')();
    var passport = require('passport');
    var LocalStrategy = require('passport-local').Strategy;
    app.use(passport.initialize());
    app.use(passport.session());
    passport.serializeUser(function(user, done) {
        console.log(user);
        console.log('serializeUser');
        done(null, user.username);
    });

    passport.deserializeUser(function(username, done) {
      done(null, {username:username, isAdmin:true});
    });

    passport.use(new LocalStrategy(
      function(username, password, done) {
          console.log('in the local strategy check function');
          console.log('username', username);
          console.log('password', password);

        if(config.get('admin-username') === username && config.get('admin-password') === password) {
          return done(null, {username:username, isAdmin :true });
        } else {
            return done(null, false, { message: 'Incorrect username or password.' });
        }
      }
    ));

    var jsonParser = bodyParser.json();
    // parse application/x-www-form-urlencoded
    app.use(bodyParser.urlencoded({ extended: false }));
    app.use(bodyParser.json());
    //app.use(auth);
    app.get('/admin/', auth, function (req,res) {
        var message = { message: req.flash()};
        console.log('message', message);
        var file = path.normalize(path.join(__dirname, '../templates/index.ejs'));
        res.render(file, { message: message });
    });

    app.get('/admin/login', function (req, res) {
        console.log('login get');

        console.log('flash',message);

        var file = path.normalize(path.join(__dirname, '../templates/login.ejs'));
        //res.status(200).sendFile(file);
        res.render(file, { message: message });
    });

    app.post('/admin/login', jsonParser, passport.authenticate('local', { successRedirect: '/admin/',
        failureRedirect: '/admin/login',
        failureFlash: true }));

    app.get('/admin/logout', function (req, res) {
        req.logout();
        res.redirect('/');
    });

    app.get('/admin/css/style.css', function (req, res) {
        var path = require('path');
        var file = path.normalize(path.join(__dirname, '../templates/css/style.css' ));
        res.status(200).sendFile(file);
    });
    app.get('/admin/fonts/:font', function (req, res) {
        var path = require('path');
        var file = path.normalize(path.join(__dirname, '../node_modules/font-awesome/fonts/', req.params.font ));
        res.status(200).sendFile(file);
    });
    app.get('/admin/js/:js', function (req, res) {
        var path = require('path');
        var file = path.normalize(path.join(__dirname, '../templates/js/', req.params.js ));
        res.status(200).sendFile(file);
    });

    app.get('/xms/api/pages/published', publishedPages, function (req, res) {
        res.send(req.xmsData.publishedPages);
    });
    app.get('/xms/api/pages/queued', queuedPages, function (req, res) {
        res.send(req.xmsData.queuedPages);
    });
    app.get('/xms/api/pages/draft', draftPages, function (req, res) {
        res.send(req.xmsData.draftPages);
    });
    app.get('/xms/api/pages/deleted', deletedPages, function (req, res) {
        res.send(req.xmsData.deletedPages);
    });

    app.get('/xms/api/settings', function (req, res) {
        var settings = require('mongo-start')('settings');

        settings.find(function (err, docs) {
            res.send(docs);
        })
    });

    app.post('/xms/api/pages', auth, jsonParser, function (req, res) {
        console.log('yup up:');
        console.log(req.body);
        var pages = require('mongo-start')('pages');
        var Joi = require('joi');

        var schema = Joi.object().keys({
            title: Joi.string().min(3).max(50).required(),
            subtitle: Joi.string().min(3).max(50),
            view: Joi.string().min(3).max(50).required(),
            route: Joi.string().min(1).max(50).required(),
            description: Joi.string().min(0).max(75),
            intro: Joi.string().min(0).max(155),
            content: Joi.string().min(5).max(5050).required(),
            createdBy: Joi.string().min(3).max(50).required(),
            createdOn: Joi.date()
        });

        var newpage = {
            title: req.body.title,
            view: req.body.view,
            description:req.body.description,
            content: req.body.content,
            route: req.body.route,
            createdBy: req.user.username,
            createdOn: Date.now()
        };
        Joi.validate(newpage, schema, function (err, value) {
            console.log('validated');
            console.log(err);
            if(err) {
                res.json(err);//validation errors, handle that clientside
            }

            pages.save(newpage, function (err, docs) {
                console.log(err);
                res.sendStatus(200);
            });
        });

    });
    app.post('/xms/api/pages/:id', auth, function (req, res) {
        var pages = require('mongo-start')('pages');
        pages.findOne({
                _id:mongojs.ObjectId(req.params._id)
            },function (err, doc) {
            res.json(doc);
        });
    });
    app.get('/xms/api/pages/:id', function (req, res) {
        var pages = require('mongo-start')('pages');
        pages.findOne({
                _id:mongojs.ObjectId(req.params._id)
            },function (err, doc) {
            res.json(doc);
        })
    });

    app.get('/xms/api/users', function (req, res) {

    });

};<|endoftext|>


<commit_before>/**
 * @fileOverview A partical object for agents.
 * @author kclv@ermitejo.com (MORIYA Masaki, alias Gardejo)
 * @license The MIT license (See LICENSE file)
 */

'use strict';

// ================================================================
// Agents
// ================================================================

// ----------------------------------------------------------------
// Namespace for Agents
// ----------------------------------------------------------------

/**
 * A namespace for agents.
 * @public
 */
kclv.Agent = {};

// ----------------------------------------------------------------
// Base Agent
// ----------------------------------------------------------------

/**
 * A base agent.
 *     An agent (a.k.a. the game client, a dedicated browser (an user agent),
 *     or a dedicated proxy) has its own format of log files. Their concrete
 *     operations are delegeted to a tokenizer object.
 *     Note: If you want to add a tokenizer for an other agent object into the
 *     library, please send a specification (an actual log file, path of a log
 *     file, etc.).
 * @public
 * @param {string} name A name of the agent.
 * @param {string} characterSet A character set of agent's log.
 * @constructor
 */
kclv.Agent.Base = function(name, characterSet) {
    /**
     * A name of the agent.
     *     It's to be used as a part of key in a configuration object tree.
     * @protected {string}
     * @const
     */
    this.name = name;

    /**
     * A character set of agent's log.
     * @protected {string}
     * @const
     */
    this.CHARACTER_SET = characterSet;

    /**
     * A delegated file reader object to read a log file.
     * @protected {kclv.Stream}
     * @const
     */
    this.stream = new kclv.Stream();

    return;
};

/**
 * Build a relation object and get it.
 * @public
 * @param {string} relationName A name of relation.
 * @returns {kclv.Relation.Base} A relation object.
 */
kclv.Agent.Base.prototype.buildRelation = function(relationName) {
    var relation = kclv.Factory.getInstance(kclv.Relation, relationName).
                   insert( this.buildRelationalArray(relationName) );

    // TODO: Strategy
    if (relationName === 'Materials') {
        relation.select( this.getSelector() );
    }

    return relation;
};

/**
 * Build two-dimensional array representing a log file.
 * @protected
 * @param {!string} relationName A name of relation.
 *     (ex. {@code Materials}, {@code Ships})
 * @param {string=} opt_concreteRelationName A name of concrete relation.
 *     (ex. {@code Fuel}, {@code Repair})
 * @returns {Array.<Array>} Two-dimensional array representing contents of a
 *     log file.
 * @nosideeffects
 */
kclv.Agent.Base.prototype.buildRelationalArray = function(
    relationName, opt_concreteRelationName
) {
    opt_concreteRelationName = opt_concreteRelationName || relationName;
    var tokenizer =
        kclv.Factory.getInstance(kclv.Tokenizer, [this.name, relationName]);

    return tokenizer.toRelationalArray(
        this.stream.readFile(
            this.getPathOf_(opt_concreteRelationName), this.CHARACTER_SET
        )
    );
};

/**
 * Build a tuple seleector object and get it.
 * @protected
 * @returns {kclv.Selector.Base} A tuple selector object.
 * @nosideeffects
 */
kclv.Agent.Base.prototype.getSelector = function() {
    var configuration = kclv.Configuration.get('relation');

    return typeof configuration.duration === 'number' ?
        new kclv.Selector.Retrospection(
            configuration.duration
        ) :
        new kclv.Selector.Period(
            configuration.inception,
            configuration.expiration
        );
};

/**
 * (Abstract) Build an attribute projector object and get it.
 * @protected
 * @throws {kclv.Exception.AbstractMethod} Always.
 */
kclv.Agent.Base.prototype.getProjector = function() {
    throw new kclv.Exception.AbstractMethod();
};

/**
 * Get a path string of the specified relation name.
 * @private
 * @param {!string} relationName A name of relation.
 * @returns {string} A path string of the specified log file.
 * @nosideeffects
 */
kclv.Agent.Base.prototype.getPathOf_ = function(relationName) {
    return kclv.Configuration.get(['agent', this.name, 'path', relationName]);
};

// ----------------------------------------------------------------
// Agent "KCRDB"
// ----------------------------------------------------------------

/**
 * An agent for "KCRDB".
 * @public
 * @constructor
 * @extends {kclv.Agent.Base}
 * @see http://hetaregrammer.blog.fc2.com/
 */
kclv.Agent.KCRDB = function() {
    kclv.Agent.Base.call(this, 'KCRDB', 'Shift_JIS');

    return;
};
kclv.Agent.KCRDB.prototype = Object.create(kclv.Agent.Base.prototype);
kclv.Agent.KCRDB.prototype.constructor = kclv.Agent.Base.prototype;

/**
 * Build a relation object and get it.
 * @public
 * @override
 * @param {string} relationName A name of relation.
 * @returns {kclv.Relation.Base} A relation object.
 */
kclv.Agent.KCRDB.prototype.buildRelation = function(relationName) {
    var relation =
            kclv.Agent.Base.prototype.buildRelation.call(this, relationName);

    // TODO: Strategy
    if (relationName === 'Materials') {
        relation.project( this.getProjector() );
    }

    return relation;
};

/**
 * Build an attribute projector object by the configurated kind and get it.
 *     Note: The default kind is 'Low'.
 * @protected
 * @override
 * @returns {kclv.Projector.Base} An attribute projector object.
 * @nosideeffects
 */
kclv.Agent.KCRDB.prototype.getProjector = function() {
    var kind = kclv.Configuration.get('relation.values', true) || 'Low';

    return kclv.Factory.getInstance(kclv.Projector.Materials, kind);
};

// ----------------------------------------------------------------
// Agent "Logbook"
// ----------------------------------------------------------------

/**
 * An agent for "Logbook".
 *     It is a simple subtype of {@code kclv.Agent.Base} at the moment.
 * @public
 * @constructor
 * @extends {kclv.Agent.Base}
 * @see http://kancolle.sanaechan.net/
 */
kclv.Agent.Logbook = function() {
    kclv.Agent.Base.call(this, 'Logbook', 'Shift_JIS');

    return;
};
kclv.Agent.Logbook.prototype = Object.create(kclv.Agent.Base.prototype);
kclv.Agent.Logbook.prototype.constructor = kclv.Agent.Base;

// ----------------------------------------------------------------
// Agent "Sandanshiki Kanpan" (Three Flight Decks)
// ----------------------------------------------------------------

/**
 * An agent for "Sandanshiki Kanpan" (Three Flight Decks).
 * @public
 * @constructor
 * @extends {kclv.Agent.Base}
 * @see http://3dan.preflight.cc/
 */
kclv.Agent.SandanshikiKanpan = function() {
    kclv.Agent.Base.call(this, 'SandanshikiKanpan', 'Shift_JIS');

    return;
};
kclv.Agent.SandanshikiKanpan.prototype =
    Object.create(kclv.Agent.Base.prototype);
kclv.Agent.SandanshikiKanpan.prototype.constructor = kclv.Agent.Base;

/**
 * Build a relation object and get it.
 * @public
 * @override
 * @param {string} relationName A name of relation.
 * @returns {kclv.Relation.Base} A relation object.
 */
kclv.Agent.SandanshikiKanpan.prototype.buildRelation = function(relationName) {
    var contents = {},
        materials = [
            'Fuel', 'Ammunition', 'Steel', 'Bauxite',
            'Repair', 'Construction', 'Development'
        ],
        gap = materials.slice().fill(null),
        radix = 10;

    if (relationName !== 'Materials') {
        throw new Error(
            'Specified relation name (' + relationName +
            ') is not "Materials".'
        );
    }

    materials.forEach( function(material, index) {
        // [["date0", value0], ["date1", value0], ...]
        this.buildRelationalArray(relationName, material).forEach( function(
            tuple
        ) {
            // { "date0" : [value0, value1, ...], "date1": ... }
            var date = tuple[0].getTime();
            contents[date] = contents[date] || gap.slice();
            contents[date][index] = tuple[1];
        }, this );
    }, this );

    return kclv.Factory.getInstance(kclv.Relation, relationName).
        insert(
            // [ [date0, value0, value1, ...], [date1, value0, ...], ... ]
            Object.keys(contents).
            map( function(date) {
                return [ new Date(parseInt(date, radix)) ].
                    concat(contents[date]);
            }, this ).
            sort( function(a, b) {
                return a[0] - b[0];
            } )
        ).
        select( this.getSelector() );
};
<commit_msg>Tidy a code<commit_after>/**
 * @fileOverview A partical object for agents.
 * @author kclv@ermitejo.com (MORIYA Masaki, alias Gardejo)
 * @license The MIT license (See LICENSE file)
 */

'use strict';

// ================================================================
// Agents
// ================================================================

// ----------------------------------------------------------------
// Namespace for Agents
// ----------------------------------------------------------------

/**
 * A namespace for agents.
 * @public
 */
kclv.Agent = {};

// ----------------------------------------------------------------
// Base Agent
// ----------------------------------------------------------------

/**
 * A base agent.
 *     An agent (a.k.a. the game client, a dedicated browser (an user agent),
 *     or a dedicated proxy) has its own format of log files. Their concrete
 *     operations are delegeted to a tokenizer object.
 *     Note: If you want to add a tokenizer for an other agent object into the
 *     library, please send a specification (an actual log file, path of a log
 *     file, etc.).
 * @public
 * @param {string} name A name of the agent.
 * @param {string} characterSet A character set of agent's log.
 * @constructor
 */
kclv.Agent.Base = function(name, characterSet) {
    /**
     * A name of the agent.
     *     It's to be used as a part of key in a configuration object tree.
     * @protected {string}
     * @const
     */
    this.name = name;

    /**
     * A character set of agent's log.
     * @protected {string}
     * @const
     */
    this.CHARACTER_SET = characterSet;

    /**
     * A delegated file reader object to read a log file.
     * @protected {kclv.Stream}
     * @const
     */
    this.stream = new kclv.Stream();

    return;
};

/**
 * Build a relation object and get it.
 * @public
 * @param {string} relationName A name of relation.
 * @returns {kclv.Relation.Base} A relation object.
 */
kclv.Agent.Base.prototype.buildRelation = function(relationName) {
    var relation = kclv.Factory.getInstance(kclv.Relation, relationName).
                   insert( this.buildRelationalArray(relationName) );

    // TODO: Strategy
    if (relationName === 'Materials') {
        relation.select( this.getSelector() );
    }

    return relation;
};

/**
 * Build two-dimensional array representing a log file.
 * @protected
 * @param {!string} relationName A name of relation.
 *     (ex. {@code Materials}, {@code Ships})
 * @param {string=} opt_concreteRelationName A name of concrete relation.
 *     (ex. {@code Fuel}, {@code Repair})
 * @returns {Array.<Array>} Two-dimensional array representing contents of a
 *     log file.
 * @nosideeffects
 */
kclv.Agent.Base.prototype.buildRelationalArray = function(
    relationName, opt_concreteRelationName
) {
    opt_concreteRelationName = opt_concreteRelationName || relationName;
    var tokenizer =
        kclv.Factory.getInstance(kclv.Tokenizer, [this.name, relationName]);

    return tokenizer.toRelationalArray(
        this.stream.readFile(
            this.getPathOf_(opt_concreteRelationName), this.CHARACTER_SET
        )
    );
};

/**
 * Build a tuple seleector object and get it.
 * @protected
 * @returns {kclv.Selector.Base} A tuple selector object.
 * @nosideeffects
 */
kclv.Agent.Base.prototype.getSelector = function() {
    var configuration = kclv.Configuration.get('relation');

    return typeof configuration.duration === 'number' ?
        new kclv.Selector.Retrospection(
            configuration.duration
        ) :
        new kclv.Selector.Period(
            configuration.inception,
            configuration.expiration
        );
};

/**
 * (Abstract) Build an attribute projector object and get it.
 * @protected
 * @throws {kclv.Exception.AbstractMethod} Always.
 */
kclv.Agent.Base.prototype.getProjector = function() {
    throw new kclv.Exception.AbstractMethod();
};

/**
 * Get a path string of the specified relation name.
 * @private
 * @param {!string} relationName A name of relation.
 * @returns {string} A path string of the specified log file.
 * @nosideeffects
 */
kclv.Agent.Base.prototype.getPathOf_ = function(relationName) {
    return kclv.Configuration.get(['agent', this.name, 'path', relationName]);
};

// ----------------------------------------------------------------
// Agent "KCRDB"
// ----------------------------------------------------------------

/**
 * An agent for "KCRDB".
 * @public
 * @constructor
 * @extends {kclv.Agent.Base}
 * @see http://hetaregrammer.blog.fc2.com/
 */
kclv.Agent.KCRDB = function() {
    kclv.Agent.Base.call(this, 'KCRDB', 'Shift_JIS');

    return;
};
kclv.Agent.KCRDB.prototype = Object.create(kclv.Agent.Base.prototype);
kclv.Agent.KCRDB.prototype.constructor = kclv.Agent.Base.prototype;

/**
 * Build a relation object and get it.
 * @public
 * @override
 * @param {string} relationName A name of relation.
 * @returns {kclv.Relation.Base} A relation object.
 */
kclv.Agent.KCRDB.prototype.buildRelation = function(relationName) {
    var relation =
            kclv.Agent.Base.prototype.buildRelation.call(this, relationName);

    // TODO: Strategy
    if (relationName === 'Materials') {
        relation.project( this.getProjector() );
    }

    return relation;
};

/**
 * Build an attribute projector object by the configurated kind and get it.
 *     Note: The default kind is 'Low'.
 * @protected
 * @override
 * @returns {kclv.Projector.Base} An attribute projector object.
 * @nosideeffects
 */
kclv.Agent.KCRDB.prototype.getProjector = function() {
    var kind = kclv.Configuration.get('relation.values', true) || 'Low';

    return kclv.Factory.getInstance(kclv.Projector.Materials, kind);
};

// ----------------------------------------------------------------
// Agent "Logbook"
// ----------------------------------------------------------------

/**
 * An agent for "Logbook".
 *     It is a simple subtype of {@code kclv.Agent.Base} at the moment.
 * @public
 * @constructor
 * @extends {kclv.Agent.Base}
 * @see http://kancolle.sanaechan.net/
 */
kclv.Agent.Logbook = function() {
    kclv.Agent.Base.call(this, 'Logbook', 'Shift_JIS');

    return;
};
kclv.Agent.Logbook.prototype = Object.create(kclv.Agent.Base.prototype);
kclv.Agent.Logbook.prototype.constructor = kclv.Agent.Base;

// ----------------------------------------------------------------
// Agent "Sandanshiki Kanpan" (Three Flight Decks)
// ----------------------------------------------------------------

/**
 * An agent for "Sandanshiki Kanpan" (Three Flight Decks).
 * @public
 * @constructor
 * @extends {kclv.Agent.Base}
 * @see http://3dan.preflight.cc/
 */
kclv.Agent.SandanshikiKanpan = function() {
    kclv.Agent.Base.call(this, 'SandanshikiKanpan', 'Shift_JIS');

    return;
};
kclv.Agent.SandanshikiKanpan.prototype =
    Object.create(kclv.Agent.Base.prototype);
kclv.Agent.SandanshikiKanpan.prototype.constructor = kclv.Agent.Base;

/**
 * Build a relation object and get it.
 * @public
 * @override
 * @param {string} relationName A name of relation.
 * @returns {kclv.Relation.Base} A relation object.
 */
kclv.Agent.SandanshikiKanpan.prototype.buildRelation = function(relationName) {
    var contents = {},
        materials = [
            'Fuel', 'Ammunition', 'Steel', 'Bauxite',
            'Repair', 'Construction', 'Development'
        ],
        gap = materials.slice().fill(null),
        radix = 10;

    if (relationName !== 'Materials') {
        throw new Error(
            'Specified relation name (' + relationName +
            ') is not "Materials".'
        );
    }

    materials.forEach( function(material, index) {
        // [["date0", value0], ["date1", value0], ...]
        this.buildRelationalArray(relationName, material).forEach( function(
            tuple
        ) {
            // { "date0" : [value0, value1, ...], "date1": ... }
            var date = tuple[0].getTime();
            contents[date] = contents[date] || gap.slice();
            contents[date][index] = tuple[1];
        }, this );
    }, this );

    return kclv.Factory.getInstance(kclv.Relation, relationName).
        insert(
            // [ [date0, value0, value1, ...], [date1, value0, ...], ... ]
            Object.keys(contents).
            map( function(date) {
                return [ new Date(parseInt(date, radix)) ].
                    concat(contents[date]);
            }, this ).
            sort( function(a, b) { return a[0] - b[0]; } )
        ).
        select( this.getSelector() );
};
<|endoftext|>


<commit_before>var url_parser = require('./lib/url_parser'),
  sig_listener = require('./lib/sig_listener').sig_listener,
  events = require('events'),
  util = require('util'),
  path = require('path'),
  async = require('async'),
  logger = require('log4node');

function LogstashAgent() {
  events.EventEmitter.call(this);
  this.setMaxListeners(0);
  this.modules = [];
  this.first_filter = new events.EventEmitter();
  this.first_filter.setMaxListeners(0);
  this.last_filter_output_func = function(data) {
    this.emit('last_filter', data);
  }.bind(this);
  this.first_filter.on('output', this.last_filter_output_func);
  this.on('first_filter', function(data) {
    this.first_filter.emit('output', data);
  }.bind(this));
  this.last_filter = this.first_filter;
  this.sig_listener = function() {
    if (this.closed_inputs) {
      logger.info('Starting inputs plugins');
      this.start_inputs();
    }
    else {
      logger.info('Closing inputs plugins');
      this.close_inputs();
    }
  }.bind(this);
  sig_listener.on('SIGUSR1', this.sig_listener);
  this.alarm_count = 0;
  this.on('alarm', function(mode, module) {
    if (mode) {
      this.alarm_count += 1;
      logger.warning('Alarm on for module', module, 'number of alarms', this.alarm_count);
      if (this.closed_inputs === false) {
        logger.warning('Alarm, closing inputs plugins');
        this.close_inputs();
        this.emit('alarm_mode', true);
      }
    }
    if (!mode) {
      this.alarm_count -= 1;
      logger.warning('Alarm off for module', module, 'number of alarms', this.alarm_count);
      if (this.alarm_count === 0 && this.closed_inputs === true) {
        logger.warning('Alarm off, starting inputs plugins');
        this.start_inputs();
        this.emit('alarm_mode', false);
      }
    }
  });
}

util.inherits(LogstashAgent, events.EventEmitter);

LogstashAgent.prototype.close = function(callback) {
  this.close_inputs(function() {
    this.close_filters(function() {
      this.close_outputs(function() {
        logger.info('Closing agent');
        if (this.sig_listener) {
          sig_listener.removeListener('SIGUSR1', this.sig_listener);
        }
        return callback();
      }.bind(this));
    }.bind(this));
  }.bind(this));
};

LogstashAgent.prototype.close_modules = function(l, callback) {
  async.eachSeries(l, function(m, callback) {
    if (m.module) {
      m.module.close(function() {
        delete m.module;
        callback();
      }.bind(this));
    }
    else {
      callback();
    }
  }.bind(this), callback);
};

LogstashAgent.prototype.close_inputs = function(callback) {
  if (!callback) {
    callback = function(err) {
      if (err) {
        logger.error('Unable to close plugins', err);
      }
      else {
        logger.info('All plugins closed');
      }
    };
  }
  this.close_modules(this.modules.inputs, function(err) {
    if (err) {
      return callback(err);
    }
    this.closed_inputs = true;
    callback();
  }.bind(this));
};

LogstashAgent.prototype.close_filters = function(callback) {
  this.close_modules(this.modules.filters, callback);
};

LogstashAgent.prototype.close_outputs = function(callback) {
  this.close_modules(this.modules.outputs, callback);
};

LogstashAgent.prototype.configure = function(url, type, callback) {
  var parsed = url_parser.extractProtocol(url);
  if (!parsed) {
    return callback(new Error('Unable to extract plugin name from ' + url));
  }
  try {
    logger.debug('Initializing module', type);
    var directory = type + 's';
    var module_name = type + '_' + parsed.protocol;
    var module_npm = '@pastash/'+module_name;
    var module;
    try {
      module = require('./' + path.join(directory, module_name));
    }
    catch(e) {
	    try {
	      module = require(path.join(directory, module_name));
	    }
	    catch(e) {
		    logger.debug(e);
		    try {
		      console.log('Loading npm module...', module_npm)
		      module = require(module_npm);
		    } catch(e) { logger.debug(e); }
	    }
    }
    module = module.create();
    var callback_called = false;
    var on_error = function(err) {
      if (!callback_called) {
        callback_called = true;
        callback(err, module);
      }
    };
    module.once('error', on_error);
    module.init(parsed.next, function(err) {
      module.removeListener('error', on_error);
      if (!callback_called) {
        callback_called = true;
        callback(err, module);
      }
      module.on('error', function(err) {
        this.emit('error', module_name, err);
      }.bind(this));
    }.bind(this));
  }
  catch (err) {
    callback(err);
  }
};

LogstashAgent.prototype.start = function(urls, callback) {
  this.modules = {
    inputs: [],
    filters: [],
    outputs: [],
  };
  logger.debug('Loading urls', urls);
  for (var k in urls) {
    var url = urls[k];
    var parsed = url_parser.extractProtocol(url);
    if (!parsed) {
      return callback(new Error('Unable to extract protocol from ' + url));
    }
    if (parsed.protocol === 'input') {
      this.modules.inputs.push({
        url: parsed.next
      });
    }
    else if (parsed.protocol === 'output') {
      this.modules.outputs.push({
        url: parsed.next
      });
    }
    else if (parsed.protocol === 'filter') {
      this.modules.filters.push({
        url: parsed.next
      });
    }
    else {
      return callback(new Error('Unknown protocol : ' + parsed.protocol));
    }
  }
  this.start_outputs(function(err) {
    if (err) {
      return callback(err);
    }
    this.start_filters(function(err) {
      if (err) {
        return callback(err);
      }
      this.start_inputs(callback);
    }.bind(this));
  }.bind(this));
};

LogstashAgent.prototype.start_modules = function(l, callback, type, module_callback) {
  async.eachSeries(l, function(m, callback) {
    this.configure(m.url, type, function(err, module) {
      if (err) {
        return callback(err);
      }
      m.module = module;
      module_callback(module, callback);
    }.bind(this));
  }.bind(this), callback);
};

LogstashAgent.prototype.start_inputs = function(callback) {
  if (!callback) {
    callback = function(err) {
      if (err) {
        logger.error('Unable to start plugins', err);
      }
      else {
        logger.info('All plugins started');
      }
    };
  }
  this.start_modules(this.modules.inputs, function(err) {
    if (err) {
      return callback(err);
    }
    this.closed_inputs = false;
    callback();
  }.bind(this), 'input', function(module, module_callback) {

    module.on('data', function(data) {
      module.add_tags_function(data, 'tags');
      module.add_fields_function(data);
      this.emit('first_filter', data);
    }.bind(this));

    module_callback();
  }.bind(this));
};

LogstashAgent.prototype.start_filters = function(callback) {
  this.start_modules(this.modules.filters, callback, 'filter', function(module, module_callback) {

    module.on('output', this.last_filter_output_func);
    this.last_filter.removeListener('output', this.last_filter_output_func);
    this.last_filter.on('output', function(data) {
      module.emit('input', data);
    });

    this.last_filter = module;

    module_callback();
  }.bind(this));
};

LogstashAgent.prototype.start_outputs = function(callback) {
  this.start_modules(this.modules.outputs, callback, 'output', function(module, module_callback) {

    this.on('last_filter', function(data) {
      module.emit('data', data);
    });

    module.on('alarm', function(mode, name) {
      this.emit('alarm', mode, name);
    }.bind(this));

    module_callback();
  }.bind(this));
};

exports.create = function() {
  return new LogstashAgent();
};

/* Plugin Functionality */
exports.base_input = require('./lib/base_input');
exports.base_output = require('./lib/base_output');
exports.base_filter = require('./lib/base_filter');
exports.logger = logger;
<commit_msg>Update agent.js<commit_after>var url_parser = require('./lib/url_parser'),
  sig_listener = require('./lib/sig_listener').sig_listener,
  events = require('events'),
  util = require('util'),
  path = require('path'),
  async = require('async'),
  logger = require('log4node');

function LogstashAgent() {
  events.EventEmitter.call(this);
  this.setMaxListeners(0);
  this.modules = [];
  this.first_filter = new events.EventEmitter();
  this.first_filter.setMaxListeners(0);
  this.last_filter_output_func = function(data) {
    this.emit('last_filter', data);
  }.bind(this);
  this.first_filter.on('output', this.last_filter_output_func);
  this.on('first_filter', function(data) {
    this.first_filter.emit('output', data);
  }.bind(this));
  this.last_filter = this.first_filter;
  this.sig_listener = function() {
    if (this.closed_inputs) {
      logger.info('Starting inputs plugins');
      this.start_inputs();
    }
    else {
      logger.info('Closing inputs plugins');
      this.close_inputs();
    }
  }.bind(this);
  sig_listener.on('SIGUSR1', this.sig_listener);
  this.alarm_count = 0;
  this.on('alarm', function(mode, module) {
    if (mode) {
      this.alarm_count += 1;
      logger.warning('Alarm on for module', module, 'number of alarms', this.alarm_count);
      if (this.closed_inputs === false) {
        logger.warning('Alarm, closing inputs plugins');
        this.close_inputs();
        this.emit('alarm_mode', true);
      }
    }
    if (!mode) {
      this.alarm_count -= 1;
      logger.warning('Alarm off for module', module, 'number of alarms', this.alarm_count);
      if (this.alarm_count === 0 && this.closed_inputs === true) {
        logger.warning('Alarm off, starting inputs plugins');
        this.start_inputs();
        this.emit('alarm_mode', false);
      }
    }
  });
}

util.inherits(LogstashAgent, events.EventEmitter);

LogstashAgent.prototype.close = function(callback) {
  this.close_inputs(function() {
    this.close_filters(function() {
      this.close_outputs(function() {
        logger.info('Closing agent');
        if (this.sig_listener) {
          sig_listener.removeListener('SIGUSR1', this.sig_listener);
        }
        return callback();
      }.bind(this));
    }.bind(this));
  }.bind(this));
};

LogstashAgent.prototype.close_modules = function(l, callback) {
  async.eachSeries(l, function(m, callback) {
    if (m.module) {
      m.module.close(function() {
        delete m.module;
        callback();
      }.bind(this));
    }
    else {
      callback();
    }
  }.bind(this), callback);
};

LogstashAgent.prototype.close_inputs = function(callback) {
  if (!callback) {
    callback = function(err) {
      if (err) {
        logger.error('Unable to close plugins', err);
      }
      else {
        logger.info('All plugins closed');
      }
    };
  }
  this.close_modules(this.modules.inputs, function(err) {
    if (err) {
      return callback(err);
    }
    this.closed_inputs = true;
    callback();
  }.bind(this));
};

LogstashAgent.prototype.close_filters = function(callback) {
  this.close_modules(this.modules.filters, callback);
};

LogstashAgent.prototype.close_outputs = function(callback) {
  this.close_modules(this.modules.outputs, callback);
};

LogstashAgent.prototype.configure = function(url, type, callback) {
  var parsed = url_parser.extractProtocol(url);
  if (!parsed) {
    return callback(new Error('Unable to extract plugin name from ' + url));
  }
  try {
    logger.debug('Initializing module', type);
    var directory = type + 's';
    var module_name = type + '_' + parsed.protocol;
    var module_npm = '@pastash/'+module_name;
    var module;
    try {
      module = require('./' + path.join(directory, module_name));
    }
    catch(e) {
	    try {
	      module = require(path.join(directory, module_name));
	    }
	    catch(e) {
		    logger.debug(e);
		    try {
		      console.log('Loading npm module...', module_npm)
		      module = require(module_npm);
		    } catch(e) { logger.debug(e); }
	    }
    }
    module = module.create();
    var callback_called = false;
    var on_error = function(err) {
      if (!callback_called) {
        callback_called = true;
        callback(err, module);
      }
    };
    module.once('error', on_error);
    module.init(parsed.next, function(err) {
      module.removeListener('error', on_error);
      if (!callback_called) {
        callback_called = true;
        callback(err, module);
      }
      module.on('error', function(err) {
        this.emit('error', module_name, err);
      }.bind(this));
    }.bind(this));
  }
  catch (err) {
    callback(err);
  }
};

LogstashAgent.prototype.start = function(urls, callback) {
  this.modules = {
    inputs: [],
    filters: [],
    outputs: [],
  };
  logger.debug('Loading urls', urls);
  for (var k in urls) {
    var url = urls[k];
    var parsed = url_parser.extractProtocol(url);
    if (!parsed) {
      return callback(new Error('Unable to extract protocol from ' + url));
    }
    if (parsed.protocol === 'input') {
      this.modules.inputs.push({
        url: parsed.next
      });
    }
    else if (parsed.protocol === 'output') {
      this.modules.outputs.push({
        url: parsed.next
      });
    }
    else if (parsed.protocol === 'filter') {
      this.modules.filters.push({
        url: parsed.next
      });
    }
    else {
      return callback(new Error('Unknown protocol : ' + parsed.protocol));
    }
  }
  this.start_outputs(function(err) {
    if (err) {
      return callback(err);
    }
    this.start_filters(function(err) {
      if (err) {
        return callback(err);
      }
      this.start_inputs(callback);
    }.bind(this));
  }.bind(this));
};

LogstashAgent.prototype.start_modules = function(l, callback, type, module_callback) {
  async.eachSeries(l, function(m, callback) {
    this.configure(m.url, type, function(err, module) {
      if (err) {
        return callback(err);
      }
      m.module = module;
      module_callback(module, callback);
    }.bind(this));
  }.bind(this), callback);
};

LogstashAgent.prototype.start_inputs = function(callback) {
  if (!callback) {
    callback = function(err) {
      if (err) {
        logger.error('Unable to start plugins', err);
      }
      else {
        logger.info('All plugins started');
      }
    };
  }
  this.start_modules(this.modules.inputs, function(err) {
    if (err) {
      return callback(err);
    }
    this.closed_inputs = false;
    callback();
  }.bind(this), 'input', function(module, module_callback) {

    module.on('data', function(data) {
      module.add_tags_function(data, 'tags');
      module.add_fields_function(data);
      this.emit('first_filter', data);
    }.bind(this));

    module_callback();
  }.bind(this));
};

LogstashAgent.prototype.start_filters = function(callback) {
  this.start_modules(this.modules.filters, callback, 'filter', function(module, module_callback) {

    module.on('output', this.last_filter_output_func);
    this.last_filter.removeListener('output', this.last_filter_output_func);
    this.last_filter.on('output', function(data) {
      module.emit('input', data);
    });

    this.last_filter = module;

    module_callback();
  }.bind(this));
};

LogstashAgent.prototype.start_outputs = function(callback) {
  this.start_modules(this.modules.outputs, callback, 'output', function(module, module_callback) {

    this.on('last_filter', function(data) {
      module.emit('data', data);
    });

    module.on('alarm', function(mode, name) {
      this.emit('alarm', mode, name);
    }.bind(this));

    module_callback();
  }.bind(this));
};

exports.create = function() {
  return new LogstashAgent();
};

/* Plugin Functionality */
exports.base_input = require('./lib/base_input');
exports.base_output = require('./lib/base_output');
exports.base_filter = require('./lib/base_filter');
exports.cache_helper = require('./lib/cache_helper');
exports.logger = logger;
<|endoftext|>