<commit_before>"use strict";
var _ = require('lodash'),
  redis = require('redis'),
  when = require('when'),
  moment = require('moment'),
  url = require('url'),
  redisClient, redisURL;

if (process.env.NODE_ENV === 'production') {
  redisURL = url.parse(process.env.REDISCLOUD_URL);
  redisClient = redis.createClient(redisURL.port, redisURL.hostname, {no_ready_check: true});
  redisClient.auth(redisURL.auth.split(":")[1]);
} else {
  redisClient = redis.createClient();
}

/**
 * Class to represent a single transaction
 */

function Transaction(obj, client) {
  this.client = client || redisClient;

  this.key = (obj) ? obj.key : null;
  this.date = (obj) ? obj.date : null;
  this.time = (obj) ? obj.time : null;
  this.name = (obj) ? obj.name : null;
  this.amount = (obj) ? obj.amount : null;
}

Transaction.prototype.save = function() {

  if (_.any([this.time, this.date, this.amount, this.name], function (item) {
    return _.isNull(item);
  })) {
    return when.reject(new Error('Transaction fields must be set before saving.'));
  }

  var promise, multi = this.client.multi(),
    week = 'w' + moment().isoWeek();

  promise = when.promise(function (resolve, reject) {
    this.client.incr('tkey', function (err, reply) {
      if (err || (reply === null)) reject(new Error('No trans key?'));

      this.key = reply;

      multi.hmset(this.key, {
        key: this.key,
        date: this.date,
        time: this.time,
        name: this.name,
        amount: this.amount
      });
      multi.rpush(week, this.key);

      multi.exec(function (err, replies) {
        console.log(replies);
        if (err) {
          console.log('save trans ' + this.key + ': FAIL');
          reject(new Error(err));
          return false;
        }
        console.log('save trans ' + this.key + ': SUCCESS');
        resolve(replies);
        return true;
      }.bind(this));
    }.bind(this));
  }.bind(this));

  return promise;
}

Transaction.prototype.set = function (obj) {
  this.date = obj.date;
  this.time = obj.time;
  this.name = obj.name;
  this.amount = obj.amount;
}

/**
 * Class to facilitate the representation of many transactions
 */

function TransactionList(client) {
  this.client = client || redisClient;
  this.key = null;
  this.transactions = [];
}

TransactionList.prototype.sum = function () {
  var promise, sum = 0;

  promise = when.promise(function (resolve, reject) {
    _.forEach(this.transactions, function (trans) {
      sum += +trans.amount;
    });
    resolve(sum);
  }.bind(this));

  return promise;
}

TransactionList.prototype.save = function () {
  var promise, actions = [];

  promise = when.promise(function (resolve, reject) {
    _.forEach(this.transactions, function (trans) {
      actions.push(trans.save());
    });

    when.all(actions)
    .then(resolve)
    .catch(reject);
  }.bind(this));

  return promise;

}

TransactionList.prototype.fetch = function (week) {
  var promise, actions = [];
  this.transactions = [];

  promise = when.promise(function (resolve, reject) {
    this.client.lrange(week, 0, -1, function (err, replies) {

      if (err) {
        console.log(err);
        reject(err);
      }

      if (_.isEmpty(replies)) {
        resolve(false);
      }

      _.forEach(replies, (function (reply) {

        actions.push(when.promise(function (resolve, reject) {
          this.client.hgetall(reply, function (err, reply) {
            if (err) reject(err);
            this.transactions.push(new Transaction(reply));
            resolve(true);
          }.bind(this));
        }.bind(this)));

      }.bind(this)));

      when.all(actions)
      .then(function () {
        resolve(true);
      });

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

  return promise;
}

TransactionList.prototype.delete = function (week) {
  console.log('attemping delete of ' + week);
  return this.fetch(week)
  .then(function () {

    return when.promise(function (resolve, reject) {
      _.forEach(this.transactions, function (transaction) {
        this.client.del(transaction.key, function (err, reply) {
          if (err) {
            reject(err);
            return;
          }

          console.log('del trans ' + transaction.key + ': SUCCESS');
          resolve(true);
        });
      }.bind(this));
      this.client.del('w' + week);
    }.bind(this));

  }.bind(this))
  .catch(function (err) {
    // grace
  });
}

module.exports = {
  list: TransactionList,
  item: Transaction,
  client: redisClient
};<commit_msg>introduce the list.delete() function<commit_after>"use strict";
var _ = require('lodash'),
  redis = require('redis'),
  when = require('when'),
  moment = require('moment'),
  url = require('url'),
  redisClient, redisURL;

if (process.env.NODE_ENV === 'production') {
  redisURL = url.parse(process.env.REDISCLOUD_URL);
  redisClient = redis.createClient(redisURL.port, redisURL.hostname, {no_ready_check: true});
  redisClient.auth(redisURL.auth.split(":")[1]);
} else {
  redisClient = redis.createClient();
}

/**
 * Class to represent a single transaction
 */

function Transaction(obj, client) {
  this.client = client || redisClient;

  this.key = (obj) ? obj.key : null;
  this.date = (obj) ? obj.date : null;
  this.time = (obj) ? obj.time : null;
  this.name = (obj) ? obj.name : null;
  this.amount = (obj) ? obj.amount : null;
}

Transaction.prototype.save = function() {

  if (_.any([this.time, this.date, this.amount, this.name], function (item) {
    return _.isNull(item);
  })) {
    return when.reject(new Error('Transaction fields must be set before saving.'));
  }

  var promise, multi = this.client.multi(),
    week = 'w' + moment().isoWeek();

  promise = when.promise(function (resolve, reject) {
    this.client.incr('tkey', function (err, reply) {
      if (err || (reply === null)) reject(new Error('No trans key?'));

      this.key = reply;

      multi.hmset(this.key, {
        key: this.key,
        date: this.date,
        time: this.time,
        name: this.name,
        amount: this.amount
      });
      multi.rpush(week, this.key);

      multi.exec(function (err, replies) {
        console.log(replies);
        if (err) {
          console.log('save trans ' + this.key + ': FAIL');
          reject(new Error(err));
          return false;
        }
        console.log('save trans ' + this.key + ': SUCCESS');
        resolve(replies);
        return true;
      }.bind(this));
    }.bind(this));
  }.bind(this));

  return promise;
}

Transaction.prototype.set = function (obj) {
  this.date = obj.date;
  this.time = obj.time;
  this.name = obj.name;
  this.amount = obj.amount;
}

/**
 * Class to facilitate the representation of many transactions
 */

function TransactionList(client) {
  this.client = client || redisClient;
  this.key = null;
  this.transactions = [];
}

TransactionList.prototype.sum = function () {
  var promise, sum = 0;

  promise = when.promise(function (resolve, reject) {
    _.forEach(this.transactions, function (trans) {
      sum += +trans.amount;
    });
    resolve(sum);
  }.bind(this));

  return promise;
}

TransactionList.prototype.save = function () {
  var promise, actions = [];

  promise = when.promise(function (resolve, reject) {
    _.forEach(this.transactions, function (trans) {
      actions.push(trans.save());
    });

    when.all(actions)
    .then(resolve)
    .catch(reject);
  }.bind(this));

  return promise;

}

TransactionList.prototype.fetch = function (week) {
  var promise, actions = [];
  this.transactions = [];

  promise = when.promise(function (resolve, reject) {
    this.client.lrange(week, 0, -1, function (err, replies) {

      if (err) {
        console.log(err);
        reject(err);
      }

      if (_.isEmpty(replies)) {
        resolve(false);
      }

      _.forEach(replies, (function (reply) {

        actions.push(when.promise(function (resolve, reject) {
          this.client.hgetall(reply, function (err, reply) {
            if (err) reject(err);
            this.transactions.push(new Transaction(reply));
            resolve(true);
          }.bind(this));
        }.bind(this)));

      }.bind(this)));

      when.all(actions)
      .then(function () {
        resolve(true);
      });

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

  return promise;
}

TransactionList.prototype.delete = function (week) {
  console.log('attemping delete of ' + week);

  return this.fetch(week)
  .then(function () {

    return when.promise(function (resolve, reject) {
      _.forEach(this.transactions, function (transaction) {
        this.client.del(transaction.key, function (err, reply) {
          if (err) {
            reject(err);
            return;
          }

          console.log('del trans ' + transaction.key + ': SUCCESS');
          resolve(true);
        });
      }.bind(this));
      this.client.del('w' + week);
    }.bind(this));

  }.bind(this))
  .catch(function (err) {
    // grace
  });
}

module.exports = {
  list: TransactionList,
  item: Transaction,
  client: redisClient
};<|endoftext|>


<commit_before>/**
 * Download landsat products.
 *
 * Command-line arguments are interpreted as scene ids.
 * If arguments are provided, then only download those scenes.
 *
 * If no arguments are provided, download available scenes 10 at a time.
 *
 */

/////////////////////////////////////////////////////////////////////

// Libraries
var yaml = require('yamljs')
var pg = require('pg')
var fs = require('fs')
var winston = require('winston')
var axios = require('axios')
var request = require('request')
var Promise = require('bluebird')
Promise.longStackTraces()

// Modules
var usgs_constants = require("./lib/usgs_api/usgs_constants.js")
var usgs_functions = require("./lib/usgs_api/usgs_functions.js")
var usgs_helpers = require("./lib/usgs_api/usgs_helpers.js")
var pg_handler = require('./lib/postgres/postgres_handlers.js')
var app_helpers = require('./lib/helpers/app_helpers.js')()

// Settings for USGS
const CONFIG_YAML = yaml.load('./lib/usgs_api/config.yaml')

// Base URL for http promise library
axios.defaults.baseURL = usgs_constants.USGS_URL

// USGS API key promise
var api_key_promise = usgs_helpers.get_api_key()

// Database connection
const db_config = yaml.load("./lib/postgres/config.yaml")
var pg_pool = pg_handler.pg_pool(db_config)

// Logging
const TODAY_DATE = app_helpers.get_date_string()
const LOG_LEVEL_INFO = 'info'
const LOG_LEVEL_ERROR = 'error'
const LOG_FILE = 'download_landsat_data'

app_helpers.delete_old_files(LOG_FILE, 'logs/', '.log')
app_helpers.set_logger_level('debug')
app_helpers.set_logfile(LOG_FILE)
app_helpers.write_message(LOG_LEVEL_INFO, 'START '+LOG_FILE, '')

// SQL queries
const last_days_scenes_query_text = "SELECT * FROM vw_last_days_scenes "
  + "LIMIT 10"

const custom_request_query_template = ""
  + "SELECT * FROM landsat_metadata "
  + "WHERE needs_ordering = 'NO' "
  + "AND scene_id in "

// Constants for handling the USGS API
const USGS_DL_RESPONSE_CODE = usgs_helpers.get_usgs_response_code('download')
const CONCURRENT_DL_LIMIT = 5
const USGS_DL_PRODUCTS = ['STANDARD']
const DL_DIR = CONFIG_YAML.download_directory

// The number of concurrent downloads in progress
var active_downloads = 0

///////////////////////////////////////////////////////////////////////////////////

const main = function() {
  var query_text = make_initial_query()
  var dataset_names = usgs_constants.LANDSAT_DATASETS
  pg_handler.pool_query_db(pg_pool, query_text, [], function (query_result) {
    var scenes_by_dataset = usgs_helpers.sort_scene_records_by_dataset(query_result.rows)
    usgs_helpers.process_scenes_by_dataset(
      dataset_names,
      scenes_by_dataset,
      process_scenes_for_dataset
    )
  })

}

const make_initial_query = function () {
  if (process.argv[2]) {
    const scenes = process.argv.slice(2)
    return custom_request_query_template + app_helpers.list_array_to_sql_list(scenes)
  }
  else {
    return last_days_scenes_query_text
  }
}

/**
 * Process scenes belonging to the same landsat dataset.
 * Limit concurrent downloads so we don't overload the USGS server.
 *
 */
const process_scenes_for_dataset = function (dataset_name, scenes) {
  if (scenes && scenes.length && active_downloads < CONCURRENT_DL_LIMIT) {
    return api_key_promise.then(function (apiKey) {
      const scene_id = scenes.pop()
      return process_scene(dataset_name, scene_id, apiKey)
    }).catch(function (err) {
      app_helpers.write_message(
        LOG_LEVEL_ERROR,
        'ERROR retrieving api key',
        err.stack
      )
    }).then(function() {
      if (active_downloads < CONCURRENT_DL_LIMIT) {
        return process_scenes_for_dataset(dataset_name, scenes)
      }
      else {
        app_helpers.write_message(
          LOG_LEVEL_INFO,
          'Rate limit for attempted downloads reached',
          CONCURRENT_DL_LIMIT
        )
      }
    })
  }
}

/**
 * Get the download link for a scene and start the download.
 *
 */
const process_scene = function (dataset_name, scene_id, apiKey) {
  const request_body = usgs_functions.usgsapi_download(
    apiKey,
    usgs_constants.NODE_EE,
    dataset_name,
    USGS_DL_PRODUCTS,
    [scene_id]
  )
  return usgs_helpers.get_usgsapi_response(
    USGS_DL_RESPONSE_CODE,
    request_body
  ).catch(function (err) {
    app_helpers.write_message(LOG_LEVEL_ERROR, err.stack)
  }).then(function (response) {
    if (response && response.length) {
      app_helpers.write_message(
        LOG_LEVEL_INFO,
        'START downloading ',
        scene_id + '.tar.gz'
      )
      return start_download(scene_id, response[0])
    }
  })

}

/**
 * Start a download for a scene's products.
 *
 * @param scene_id of the product we are downloading
 * @param url is the download link generated by the USGS API
 */
const start_download = function (scene_id, url) {
  const filename = make_filename(scene_id)
  const path = DL_DIR + filename
  if (fs.existsSync(path)) {
    app_helpers.write_message(
      LOG_LEVEL_INFO,
      'File already exists. Deleting old file.'
    )
    fs.unlinkSync(path)
  }
  const file = fs.createWriteStream(path)
  request
    .get(url)
    .on('error', function (err) {
      app_helpers.write_message(LOG_LEVEL_ERROR, err)
    })
    .on('response', function (response) {
      handle_response(response, scene_id)
    })
    .pipe(file)
    .on('finish', function () {
      active_downloads -= 1
      update_record(scene_id)
      app_helpers.write_message(
        LOG_LEVEL_INFO,
        'DONE downloading',
        filename
      )
    })
  return Promise.resolve(active_downloads += 1)
}

/**
 * Check the http response from a download url.
 *
 * @param response is an instance of http.incomingMessage
 * @param scene_id is the id of the scene being downloaded
 *
 */
const handle_response = function (response, scene_id) {
  if (response.statusCode > 200) {
    app_helpers.write_message(
      LOG_LEVEL_ERROR,
      'USGS responded with status code '
      + response.statusCode
      + ' while attempting to download archive for '
      + scene_id
    )
  }
}

/**
 * Update a scene record to reflect that
 * the scene's products were successfully downloaded.
 *
 */
const update_record = function (scene_id) {
  const query_text = ""
    + "UPDATE * FROM landsat_metadata "
    + "WHERE scene_id in ("+scene_id+") "
    + "SET "
      + "needs_ordering = 'NO', "
      + "ordered = 'YES', "
      + "download_available = 'YES', "
      + "needs_downloading = 'NO', "
      + "downloaded = 'YES', "
      + "needs_processing = 'YES'"
  pg_handler.pool_query_db(pg_pool, query_text, [], function () {
    app_helpers.write_message(
      LOG_LEVEL_INFO,
      'Updated database record for scene ' + scene_id
    )
  })
}

const make_filename = function (scene_id) {
  return scene_id + '.tar.gz'
}

main()<commit_msg>Update description for download script; change max concurrent downloads to 10 to reflect actual usgs download rate limit (10)<commit_after>/**
 * Download landsat products.
 *
 * Command-line arguments are interpreted as scene ids.
 * If arguments are provided, then only download those scenes.
 *
 * If no arguments are provided, download 10 scenes from
 * the last days scenes sql view.
 *
 */

/////////////////////////////////////////////////////////////////////

// Libraries
var yaml = require('yamljs')
var pg = require('pg')
var fs = require('fs')
var winston = require('winston')
var axios = require('axios')
var request = require('request')
var Promise = require('bluebird')
Promise.longStackTraces()

// Modules
var usgs_constants = require("./lib/usgs_api/usgs_constants.js")
var usgs_functions = require("./lib/usgs_api/usgs_functions.js")
var usgs_helpers = require("./lib/usgs_api/usgs_helpers.js")
var pg_handler = require('./lib/postgres/postgres_handlers.js')
var app_helpers = require('./lib/helpers/app_helpers.js')()

// Settings for USGS
const CONFIG_YAML = yaml.load('./lib/usgs_api/config.yaml')

// Base URL for http promise library
axios.defaults.baseURL = usgs_constants.USGS_URL

// USGS API key promise
var api_key_promise = usgs_helpers.get_api_key()

// Database connection
const db_config = yaml.load("./lib/postgres/config.yaml")
var pg_pool = pg_handler.pg_pool(db_config)

// Logging
const TODAY_DATE = app_helpers.get_date_string()
const LOG_LEVEL_INFO = 'info'
const LOG_LEVEL_ERROR = 'error'
const LOG_FILE = 'download_landsat_data'

app_helpers.delete_old_files(LOG_FILE, 'logs/', '.log')
app_helpers.set_logger_level('debug')
app_helpers.set_logfile(LOG_FILE)
app_helpers.write_message(LOG_LEVEL_INFO, 'START '+LOG_FILE, '')

// SQL queries
const last_days_scenes_query_text = "SELECT * FROM vw_last_days_scenes "
  + "LIMIT 10"

const custom_request_query_template = ""
  + "SELECT * FROM landsat_metadata "
  + "WHERE needs_ordering = 'NO' "
  + "AND scene_id in "

// Constants for handling the USGS API
const USGS_DL_RESPONSE_CODE = usgs_helpers.get_usgs_response_code('download')
const CONCURRENT_DL_LIMIT = 10
const USGS_DL_PRODUCTS = ['STANDARD']
const DL_DIR = CONFIG_YAML.download_directory

// The number of concurrent downloads in progress
var active_downloads = 0

///////////////////////////////////////////////////////////////////////////////////

const main = function() {
  var query_text = make_initial_query()
  var dataset_names = usgs_constants.LANDSAT_DATASETS
  pg_handler.pool_query_db(pg_pool, query_text, [], function (query_result) {
    var scenes_by_dataset = usgs_helpers.sort_scene_records_by_dataset(query_result.rows)
    usgs_helpers.process_scenes_by_dataset(
      dataset_names,
      scenes_by_dataset,
      process_scenes_for_dataset
    )
  })

}

const make_initial_query = function () {
  if (process.argv[2]) {
    const scenes = process.argv.slice(2)
    return custom_request_query_template + app_helpers.list_array_to_sql_list(scenes)
  }
  else {
    return last_days_scenes_query_text
  }
}

/**
 * Process scenes belonging to the same landsat dataset.
 * Limit concurrent downloads so we don't overload the USGS server.
 *
 */
const process_scenes_for_dataset = function (dataset_name, scenes) {
  if (scenes && scenes.length && active_downloads < CONCURRENT_DL_LIMIT) {
    return api_key_promise.then(function (apiKey) {
      const scene_id = scenes.pop()
      return process_scene(dataset_name, scene_id, apiKey)
    }).catch(function (err) {
      app_helpers.write_message(
        LOG_LEVEL_ERROR,
        'ERROR retrieving api key',
        err.stack
      )
    }).then(function() {
      if (active_downloads < CONCURRENT_DL_LIMIT) {
        return process_scenes_for_dataset(dataset_name, scenes)
      }
      else {
        app_helpers.write_message(
          LOG_LEVEL_INFO,
          'Rate limit for attempted downloads reached',
          CONCURRENT_DL_LIMIT
        )
      }
    })
  }
}

/**
 * Get the download link for a scene and start the download.
 *
 */
const process_scene = function (dataset_name, scene_id, apiKey) {
  const request_body = usgs_functions.usgsapi_download(
    apiKey,
    usgs_constants.NODE_EE,
    dataset_name,
    USGS_DL_PRODUCTS,
    [scene_id]
  )
  return usgs_helpers.get_usgsapi_response(
    USGS_DL_RESPONSE_CODE,
    request_body
  ).catch(function (err) {
    app_helpers.write_message(LOG_LEVEL_ERROR, err.stack)
  }).then(function (response) {
    if (response && response.length) {
      app_helpers.write_message(
        LOG_LEVEL_INFO,
        'START downloading ',
        scene_id + '.tar.gz'
      )
      return start_download(scene_id, response[0])
    }
  })

}

/**
 * Start a download for a scene's products.
 *
 * @param scene_id of the product we are downloading
 * @param url is the download link generated by the USGS API
 */
const start_download = function (scene_id, url) {
  const filename = make_filename(scene_id)
  const path = DL_DIR + filename
  if (fs.existsSync(path)) {
    app_helpers.write_message(
      LOG_LEVEL_INFO,
      'File already exists. Deleting old file.'
    )
    fs.unlinkSync(path)
  }
  const file = fs.createWriteStream(path)
  request
    .get(url)
    .on('error', function (err) {
      app_helpers.write_message(LOG_LEVEL_ERROR, err)
    })
    .on('response', function (response) {
      handle_response(response, scene_id)
    })
    .pipe(file)
    .on('finish', function () {
      active_downloads -= 1
      update_record(scene_id)
      app_helpers.write_message(
        LOG_LEVEL_INFO,
        'DONE downloading',
        filename
      )
    })
  return Promise.resolve(active_downloads += 1)
}

/**
 * Check the http response from a download url.
 *
 * @param response is an instance of http.incomingMessage
 * @param scene_id is the id of the scene being downloaded
 *
 */
const handle_response = function (response, scene_id) {
  if (response.statusCode > 200) {
    app_helpers.write_message(
      LOG_LEVEL_ERROR,
      'USGS responded with status code '
      + response.statusCode
      + ' while attempting to download archive for '
      + scene_id
    )
  }
}

/**
 * Update a scene record to reflect that
 * the scene's products were successfully downloaded.
 *
 */
const update_record = function (scene_id) {
  const query_text = ""
    + "UPDATE * FROM landsat_metadata "
    + "WHERE scene_id in ("+scene_id+") "
    + "SET "
      + "needs_ordering = 'NO', "
      + "ordered = 'YES', "
      + "download_available = 'YES', "
      + "needs_downloading = 'NO', "
      + "downloaded = 'YES', "
      + "needs_processing = 'YES'"
  pg_handler.pool_query_db(pg_pool, query_text, [], function () {
    app_helpers.write_message(
      LOG_LEVEL_INFO,
      'Updated database record for scene ' + scene_id
    )
  })
}

const make_filename = function (scene_id) {
  return scene_id + '.tar.gz'
}

main()<|endoftext|>


<commit_before>(module.exports = function(flow){
  var fconsole = flow.console;
  var idMap = flow.css.idMap;
  var classMap = flow.css.classMap;
  var warnCount = 0;

  //
  // warnings
  //

  var warnNoStyle = [];
  var warnNoHtml = [];
  for (var name in classMap)
  {
    var list = classMap[name];
    var inHtml = list.sources.html || list.sources.tmpl;
    var inCss = list.sources.style;

    if (inHtml && !inCss)
      warnNoStyle.push('class: ' + name);

    if (!inHtml && inCss)
    {
      warnNoHtml.push('class: ' + name);

      if (flow.options.cssCutUnused)
        for (var i = 0, item; item = list[i]; i++)
          if (item.type == 'style-class')
            deleteSelector(item.token);
    }
  }

  for (var name in idMap)
  {
    var list = idMap[name];
    var inHtml = list.sources.html || list.sources.tmpl;
    var inCss = list.sources.style;

    if (inHtml && !inCss)
      warnNoStyle.push('id: ' + name);

    if (!inHtml && inCss)
    {
      warnNoHtml.push('id: ' + name);

      if (flow.options.cssCutUnused)
        for (var i = 0, item; item = list[i]; i++)
          if (item.type == 'style-id')
            deleteSelector(item.token);
    }
  }

  if (warnNoHtml.length)
  {
    fconsole.log('[!] Never used in html & templates');
    fconsole.list(warnNoHtml, ' ');
    fconsole.log();
  }

  if (warnNoStyle.length)
  {
    fconsole.log('[!] No styles for');
    fconsole.list(warnNoStyle, ' ');
    fconsole.log();
  }

  if (warnCount)
    fconsole.log('[WARN] ' + warnCount + ' problem(s) detected, name optimizing may breakdown app\n');

}).handlerName = '[css] Validate names';

function deleteSelector(token){
  var simpleselector = token.stack[0];
  var selector = token.stack[1];
  var rule = token.stack[2];
  var stylesheet = token.stack[3];
  var idx;

  idx = selector.indexOf(simpleselector);
  if (idx != -1)
  {
    // delete simple selector from selector
    selector.splice(idx > 2 ? idx - 1 : idx, 2);
  }

  if (selector.length == 2)
  { // no more simple selectors
    idx = stylesheet.indexOf(rule);
    if (idx != -1)
    {
      // delete rule from stylesheet
      stylesheet.splice(idx, 1);
      if (stylesheet[idx][1] == 's')
        stylesheet.splice(idx, 1);
    }
  }
}
<commit_msg>fix whitespace cut<commit_after>(module.exports = function(flow){
  var fconsole = flow.console;
  var idMap = flow.css.idMap;
  var classMap = flow.css.classMap;
  var warnCount = 0;

  //
  // warnings
  //

  var warnNoStyle = [];
  var warnNoHtml = [];
  for (var name in classMap)
  {
    var list = classMap[name];
    var inHtml = list.sources.html || list.sources.tmpl;
    var inCss = list.sources.style;

    if (inHtml && !inCss)
      warnNoStyle.push('class: ' + name);

    if (!inHtml && inCss)
    {
      warnNoHtml.push('class: ' + name);

      if (flow.options.cssCutUnused)
        for (var i = 0, item; item = list[i]; i++)
          if (item.type == 'style-class')
            deleteSelector(item.token);
    }
  }

  for (var name in idMap)
  {
    var list = idMap[name];
    var inHtml = list.sources.html || list.sources.tmpl;
    var inCss = list.sources.style;

    if (inHtml && !inCss)
      warnNoStyle.push('id: ' + name);

    if (!inHtml && inCss)
    {
      warnNoHtml.push('id: ' + name);

      if (flow.options.cssCutUnused)
        for (var i = 0, item; item = list[i]; i++)
          if (item.type == 'style-id')
            deleteSelector(item.token);
    }
  }

  if (warnNoHtml.length)
  {
    fconsole.log('[!] Never used in html & templates');
    fconsole.list(warnNoHtml, ' ');
    fconsole.log();
  }

  if (warnNoStyle.length)
  {
    fconsole.log('[!] No styles for');
    fconsole.list(warnNoStyle, ' ');
    fconsole.log();
  }

  if (warnCount)
    fconsole.log('[WARN] ' + warnCount + ' problem(s) detected, name optimizing may breakdown app\n');

}).handlerName = '[css] Validate names';

function deleteSelector(token){
  var simpleselector = token.stack[0];
  var selector = token.stack[1];
  var rule = token.stack[2];
  var stylesheet = token.stack[3];
  var idx;

  idx = selector.indexOf(simpleselector);
  if (idx != -1)
  {
    // delete simple selector from selector
    selector.splice(idx > 2 ? idx - 1 : idx, 2);
  }

  if (selector.length == 2)
  { // no more simple selectors
    idx = stylesheet.indexOf(rule);
    if (idx != -1)
    {
      // delete rule from stylesheet
      stylesheet.splice(idx, 1);
      if (stylesheet[idx] && stylesheet[idx][1] == 's')
        stylesheet.splice(idx, 1);
    }
  }
}
<|endoftext|>


<commit_before>var fs = require('../core/fs.js');
var path = require('path');
var utils = require('../utils/utils.js');

var TemplateGenerator = function(templateName) {
  this.templateName = templateName;
};

TemplateGenerator.prototype.generate = function(destinationFolder, name) {
  var templatePath = fs.embarkPath(this.templateName);
  console.log('Initializing Embark Template....'.green);

  fs.copySync(templatePath, path.join(destinationFolder, name));
  utils.cd(path.join(destinationFolder, name));
  utils.sed('package.json', '%APP_NAME%', name);

  console.log('Installing packages.. this can take a few seconds'.green);
  utils.runCmd('npm install');
  console.log('Init complete'.green);
  console.log('\nApp ready at '.green + path.join(destinationFolder, name));

  if (name === 'embark_demo') {
    console.log('-------------------'.yellow);
    console.log('Next steps:'.green);
    console.log(('-> ' + ('cd ' + path.join(destinationFolder, name)).bold.cyan).green);
    console.log('-> '.green + 'embark blockchain'.bold.cyan + ' or '.green + 'embark simulator'.bold.cyan);
    console.log('open another console in the same directory and run'.green);
    console.log('-> '.green + 'embark run'.bold.cyan);
    console.log('For more info go to http://github.com/iurimatias/embark-framework'.green);
  }
};

module.exports = TemplateGenerator;
<commit_msg>call path.join once and store in fspath var<commit_after>var fs = require('../core/fs.js');
var path = require('path');
var utils = require('../utils/utils.js');

var TemplateGenerator = function(templateName) {
  this.templateName = templateName;
};

TemplateGenerator.prototype.generate = function(destinationFolder, name) {
  var templatePath = fs.embarkPath(this.templateName);
  console.log('Initializing Embark Template....'.green);
  var fspath = path.join(destinationFolder, name);

  fs.copySync(templatePath, fspath);
  utils.cd(fspath);
  utils.sed('package.json', '%APP_NAME%', name);

  console.log('Installing packages.. this can take a few seconds'.green);
  utils.runCmd('npm install');
  console.log('Init complete'.green);
  console.log('\nApp ready at '.green + fspath);

  if (name === 'embark_demo') {
    console.log('-------------------'.yellow);
    console.log('Next steps:'.green);
    console.log(('-> ' + ('cd ' + fspath).bold.cyan).green);
    console.log('-> '.green + 'embark blockchain'.bold.cyan + ' or '.green + 'embark simulator'.bold.cyan);
    console.log('open another console in the same directory and run'.green);
    console.log('-> '.green + 'embark run'.bold.cyan);
    console.log('For more info go to http://github.com/iurimatias/embark-framework'.green);
  }
};

module.exports = TemplateGenerator;
<|endoftext|>


<commit_before>var _ = require('../util').lodash,
    Property = require('./property').Property,
    VariableList = require('./variable-list').VariableList,

    RequestAuth;

/**
 * This defines the definition of the authentication method to be used.
 *
 * @typedef RequestAuth~definition
 * @property {String=} type The Auth type to use. Check the names in {@link AuthTypes}
 *
 * @example
Sample auth definition for Basic Auth

 * {
 *   "type": "basic",
 *   "basic": [
 *     { "key": "username", "value": "postman" },
 *     { "key": "password", "value": "secrets" }
 *   ]
 * }
 */
_.inherit((

    /**
     * A Postman Auth definition that comprehensively represents different types of auth mechanisms available.
     *
     * @constructor
     * @extends {Property}
     *
     * @param {RequestAuth~definition} options Pass the initial definition of the Auth.
     *
     * @example
Creating a request with two auth data and one selected

     * var auth = new RequestAuth({
     *   type: 'digest',
     *
     *   basic: [
     *     { key: "username", value: "postman" },
     *     { key: "password", value: "secrets" }
     *   ],
     *   digest: [
     *     { key: "nonce", value: "aef54cde" },
     *     { key: "realm", value: "items.x" }
     *   ]
     * });
     *
     * // change the selected auth
     * auth.use('basic');
     */
    RequestAuth = function PostmanRequestAuth (options) {
        // this constructor is intended to inherit and as such the super constructor is required to be executed
        RequestAuth.super_.call(this, options);

        if (_.has(options, 'type')) {
            this.use(options.type);
        }

        // load all possible auth parameters from options
        _.forEach(_.omit(options, 'type'), this.update.bind(this));
    }), Property);

_.assign(RequestAuth.prototype, /** @lends RequestAuth.prototype */ {
    /**
     * Update the parameters of a specific authentication type. If none is provided then it uses the one marked as to be
     * used.
     *
     * @param {VariableList|Array|Object} options
     * @param {String=} [type=this.type]
     */
    update: function (options, type) {
        // update must have options
        if (!_.isObject(options)) { return; }
        // validate type parameter and/or choose default from existing type.
        if (!_.isString(type) || (type === 'type')) { type = this.type; }

        var parameters = this[type];

        // in case the type holder is not created, we create one and send the population variables
        if (!VariableList.isVariableList(parameters)) {
            // @todo optimise the handling of legacy object type auth parameters
            parameters = this[type] = new VariableList(this);
            parameters._postman_requestAuthType = type;
        }

        // we simply assimilate the new options either it is an array or an object
        if (_.isArray(options) || VariableList.isVariableList(options)) {
            parameters.assimilate(options);
        }
        else {
            parameters.syncFromObject(options, false, false); // params: no need to track and no need to prune
        }
    },

    /**
     * Sets the authentication type to be used by this item.
     *
     * @param {String} type
     * @param {Object=} options - note that options set here would replace all existing options for the particular auth
     */
    use: function (type, options) {
        // no auth name can be "type", else will have namespace collision with type selector
        if (!_.isString(type) || type === 'type') {
            return;
        }

        this.type = type; // set the type

        // if options is provided or a variable list was not created for the type, we create one
        if (!VariableList.isVariableList(this[type]) || options) {
            this[type] = new VariableList(this, options);
            this[type]._postman_requestAuthType = type;
        }
    },

    /**
     * Fetches the currently selected AuthType.
     *
     * @return {Object|undefined}
     * @deprecated Use .parameters() instead
     */
    current: function () {
        return this[this.type] ? this[this.type].toObject() : undefined;
    },

    /**
     * Returns the parameters of the selected auth type
     *
     * @returns {VariableList}
     */
    parameters: function () {
        return this[this.type];
    }
});

_.assign(RequestAuth, /** @lends RequestAuth */ {
    /**
     * Defines the name of this property for internal use.
     * @private
     * @readOnly
     * @type {String}
     */
    _postman_propertyName: 'RequestAuth'
});

module.exports = {
    RequestAuth: RequestAuth
};
<commit_msg>Consolidated request auth type name verification to a static function<commit_after>var _ = require('../util').lodash,
    Property = require('./property').Property,
    VariableList = require('./variable-list').VariableList,

    RequestAuth;

/**
 * This defines the definition of the authentication method to be used.
 *
 * @typedef RequestAuth~definition
 * @property {String=} type The Auth type to use. Check the names in {@link AuthTypes}
 *
 * @example
Sample auth definition for Basic Auth

 * {
 *   "type": "basic",
 *   "basic": [
 *     { "key": "username", "value": "postman" },
 *     { "key": "password", "value": "secrets" }
 *   ]
 * }
 */
_.inherit((

    /**
     * A Postman Auth definition that comprehensively represents different types of auth mechanisms available.
     *
     * @constructor
     * @extends {Property}
     *
     * @param {RequestAuth~definition} options Pass the initial definition of the Auth.
     *
     * @example
Creating a request with two auth data and one selected

     * var auth = new RequestAuth({
     *   type: 'digest',
     *
     *   basic: [
     *     { key: "username", value: "postman" },
     *     { key: "password", value: "secrets" }
     *   ],
     *   digest: [
     *     { key: "nonce", value: "aef54cde" },
     *     { key: "realm", value: "items.x" }
     *   ]
     * });
     *
     * // change the selected auth
     * auth.use('basic');
     */
    RequestAuth = function PostmanRequestAuth (options) {
        // this constructor is intended to inherit and as such the super constructor is required to be executed
        RequestAuth.super_.call(this, options);

        if (_.has(options, 'type')) {
            this.use(options.type);
        }

        // load all possible auth parameters from options
        _.forEach(_.omit(options, 'type'), this.update.bind(this));
    }), Property);

_.assign(RequestAuth.prototype, /** @lends RequestAuth.prototype */ {
    /**
     * Update the parameters of a specific authentication type. If none is provided then it uses the one marked as to be
     * used.
     *
     * @param {VariableList|Array|Object} options
     * @param {String=} [type=this.type]
     */
    update: function (options, type) {
        // update must have options
        if (!_.isObject(options)) { return; }
        // validate type parameter and/or choose default from existing type.
        if (!RequestAuth.isValidType(type)) { type = this.type; }

        var parameters = this[type];

        // in case the type holder is not created, we create one and send the population variables
        if (!VariableList.isVariableList(parameters)) {
            // @todo optimise the handling of legacy object type auth parameters
            parameters = this[type] = new VariableList(this);
            parameters._postman_requestAuthType = type;
        }

        // we simply assimilate the new options either it is an array or an object
        if (_.isArray(options) || VariableList.isVariableList(options)) {
            parameters.assimilate(options);
        }
        else {
            parameters.syncFromObject(options, false, false); // params: no need to track and no need to prune
        }
    },

    /**
     * Sets the authentication type to be used by this item.
     *
     * @param {String} type
     * @param {Object=} options - note that options set here would replace all existing options for the particular auth
     */
    use: function (type, options) {
        if (!RequestAuth.isValidType(type)) { return; }

        this.type = type; // set the type

        // if options is provided or a variable list was not created for the type, we create one
        if (!VariableList.isVariableList(this[type]) || options) {
            this[type] = new VariableList(this, options);
            this[type]._postman_requestAuthType = type;
        }
    },

    /**
     * Fetches the currently selected AuthType.
     *
     * @return {Object|undefined}
     * @deprecated Use .parameters() instead
     */
    current: function () {
        return this[this.type] ? this[this.type].toObject() : undefined;
    },

    /**
     * Returns the parameters of the selected auth type
     *
     * @returns {VariableList}
     */
    parameters: function () {
        return this[this.type];
    }
});

_.assign(RequestAuth, /** @lends RequestAuth */ {
    /**
     * Defines the name of this property for internal use.
     * @private
     * @readOnly
     * @type {String}
     */
    _postman_propertyName: 'RequestAuth',

    /**
     * Determines whether an authentication type name is valid or not
     *
     * @param {String} type
     *
     * @returns {Boolean}
     */
    isValidType: function (type) {
        // no auth name can be "type", else will have namespace collision with type selector
        return _.isString(type) && (type !== 'type');
    }
});

module.exports = {
    RequestAuth: RequestAuth
};
<|endoftext|>


<commit_before>'use strict'

var path = require('path')
var fs = require('fs')
var Promise = require('bluebird')
var install = require('npm-install-package')

function initializeApp (cwd, force) {
  return new Promise(function (resolve, reject) {
    var existsPackageJson = fs.existsSync(path.join(cwd, './package.json'))
    var jsreportModule
    var jsreportVersion
    var isMainJsreport = false

    checkOrInstallJsreport(cwd, existsPackageJson, function (err, detectedJsreport) {
      var errorToReject

      if (err) {
        errorToReject = new Error('Unexpected error happened')
        errorToReject.originalError = err
        return reject(errorToReject)
      }

      isMainJsreport = (detectedJsreport === 'jsreport')

      try {
        jsreportModule = require(path.join(cwd, 'node_modules/' + detectedJsreport + '/package.json'))
        jsreportVersion = jsreportModule.version
      } catch (err) {
        errorToReject = new Error('Unexpected error happened')
        errorToReject.originalError = err
        return reject(errorToReject)
      }

      if (!fs.existsSync(path.join(cwd, './server.js')) || force) {
        console.log('Creating server.js')
        fs.writeFileSync(
          path.join(cwd, './server.js'),
          fs.readFileSync(
            path.join(__dirname, '../../example.server.js')
          ).toString().replace('$moduleName$', detectedJsreport)
        )
      }

      if (!existsPackageJson || force) {
        console.log('Creating package.json')

        var serverPackageJson = {
          'name': 'jsreport-server',
          'main': 'server.js',
          'scripts': {
            'start': 'node server'
          },
          'jsreport': {
            'entryPoint': 'server.js'
          },
          'dependencies': {
          }
        }

        serverPackageJson.dependencies[detectedJsreport] = jsreportVersion

        if (isMainJsreport) {
          serverPackageJson.scripts.jsreport = 'jsreport'
        }

        fs.writeFileSync(path.join(cwd, './package.json'), JSON.stringify(serverPackageJson, null, 2))
      }

      if ((!fs.existsSync(path.join(cwd, './prod.config.json')) || force) && isMainJsreport) {
        console.log('Creating prod.config.json (applied on npm start --production)')
        fs.writeFileSync(path.join(cwd, './prod.config.json'), fs.readFileSync(path.join(__dirname, '../../example.config.json')))
        console.log('Creating dev.config.json (applied on npm start)')
        fs.writeFileSync(path.join(cwd, './dev.config.json'), fs.readFileSync(path.join(__dirname, '../../example.config.json')))
      }

      console.log('Initialized')

      resolve({
        name: detectedJsreport,
        version: jsreportVersion
      })
    })
  })
}

function checkOrInstallJsreport (cwd, existsPackageJson, cb) {
  var detectedJsreport
  var userPkg
  var userDependencies
  var originalCWD = process.cwd()

  if (existsPackageJson) {
    userPkg = require(path.join(cwd, './package.json'))
    userDependencies = userPkg.dependencies || {}

    if (userDependencies['jsreport']) {
      detectedJsreport = 'jsreport'
    } else if (userDependencies['jsreport-core']) {
      detectedJsreport = 'jsreport-core'
    }
  }

  if (!detectedJsreport) {
    if (fs.existsSync(path.join(cwd, 'node_modules/jsreport'))) {
      detectedJsreport = 'jsreport'
    } else if (fs.existsSync(path.join(cwd, 'node_modules/jsreport-core'))) {
      detectedJsreport = 'jsreport-core'
    }
  }

  if (!detectedJsreport) {
    console.log('jsreport installation not found, intalling it now, wait a moment...')

    detectedJsreport = 'jsreport'

    process.chdir(cwd)

    // creating basic package.json in order to make npm install
    // work normally in current directory, later the real package.json
    // will be created
    if (!existsPackageJson) {
      fs.writeFileSync(
        path.join(cwd, './package.json'),
        JSON.stringify({
          name: 'jsreport-server'
        }, null, 2))
    }

    install(detectedJsreport, function (installErr) {
      process.chdir(originalCWD)

      if (installErr) {
        return cb(installErr)
      }

      console.log('jsreport installation finished..')
      cb(null, detectedJsreport)
    })
  } else {
    cb(null, detectedJsreport)
  }
}

module.exports = initializeApp
<commit_msg>save jsreport package dependency in package.json when installing it<commit_after>'use strict'

var path = require('path')
var fs = require('fs')
var Promise = require('bluebird')
var install = require('npm-install-package')

function initializeApp (cwd, force) {
  return new Promise(function (resolve, reject) {
    var existsPackageJson = fs.existsSync(path.join(cwd, './package.json'))
    var jsreportModule
    var jsreportVersion
    var isMainJsreport = false

    checkOrInstallJsreport(cwd, existsPackageJson, function (err, detectedJsreport) {
      var errorToReject

      if (err) {
        errorToReject = new Error('Unexpected error happened')
        errorToReject.originalError = err
        return reject(errorToReject)
      }

      isMainJsreport = (detectedJsreport === 'jsreport')

      try {
        jsreportModule = require(path.join(cwd, 'node_modules/' + detectedJsreport + '/package.json'))
        jsreportVersion = jsreportModule.version
      } catch (err) {
        errorToReject = new Error('Unexpected error happened')
        errorToReject.originalError = err
        return reject(errorToReject)
      }

      if (!fs.existsSync(path.join(cwd, './server.js')) || force) {
        console.log('Creating server.js')
        fs.writeFileSync(
          path.join(cwd, './server.js'),
          fs.readFileSync(
            path.join(__dirname, '../../example.server.js')
          ).toString().replace('$moduleName$', detectedJsreport)
        )
      }

      if (!existsPackageJson || force) {
        console.log('Creating package.json')

        var serverPackageJson = {
          'name': 'jsreport-server',
          'main': 'server.js',
          'scripts': {
            'start': 'node server'
          },
          'jsreport': {
            'entryPoint': 'server.js'
          },
          'dependencies': {
          }
        }

        serverPackageJson.dependencies[detectedJsreport] = jsreportVersion

        if (isMainJsreport) {
          serverPackageJson.scripts.jsreport = 'jsreport'
        }

        fs.writeFileSync(path.join(cwd, './package.json'), JSON.stringify(serverPackageJson, null, 2))
      }

      if ((!fs.existsSync(path.join(cwd, './prod.config.json')) || force) && isMainJsreport) {
        console.log('Creating prod.config.json (applied on npm start --production)')
        fs.writeFileSync(path.join(cwd, './prod.config.json'), fs.readFileSync(path.join(__dirname, '../../example.config.json')))
        console.log('Creating dev.config.json (applied on npm start)')
        fs.writeFileSync(path.join(cwd, './dev.config.json'), fs.readFileSync(path.join(__dirname, '../../example.config.json')))
      }

      console.log('Initialized')

      resolve({
        name: detectedJsreport,
        version: jsreportVersion
      })
    })
  })
}

function checkOrInstallJsreport (cwd, existsPackageJson, cb) {
  var detectedJsreport
  var userPkg
  var userDependencies
  var originalCWD = process.cwd()

  if (existsPackageJson) {
    userPkg = require(path.join(cwd, './package.json'))
    userDependencies = userPkg.dependencies || {}

    if (userDependencies['jsreport']) {
      detectedJsreport = 'jsreport'
    } else if (userDependencies['jsreport-core']) {
      detectedJsreport = 'jsreport-core'
    }
  }

  if (!detectedJsreport) {
    if (fs.existsSync(path.join(cwd, 'node_modules/jsreport'))) {
      detectedJsreport = 'jsreport'
    } else if (fs.existsSync(path.join(cwd, 'node_modules/jsreport-core'))) {
      detectedJsreport = 'jsreport-core'
    }
  }

  if (!detectedJsreport) {
    console.log('jsreport installation not found, intalling it now, wait a moment...')

    detectedJsreport = 'jsreport'

    process.chdir(cwd)

    // creating basic package.json in order to make npm install
    // work normally in current directory, later the real package.json
    // will be created
    if (!existsPackageJson) {
      fs.writeFileSync(
        path.join(cwd, './package.json'),
        JSON.stringify({
          name: 'jsreport-server'
        }, null, 2))
    }

    install(detectedJsreport, { save: true }, function (installErr) {
      process.chdir(originalCWD)

      if (installErr) {
        return cb(installErr)
      }

      console.log('jsreport installation finished..')
      cb(null, detectedJsreport)
    })
  } else {
    cb(null, detectedJsreport)
  }
}

module.exports = initializeApp
<|endoftext|>


<commit_before>"use strict";

var clc = require('cli-color');
var fs = require('fs');
var rek = require('rekuire');
var path = require('path');
var moment = require('moment');

var getCwd = rek('getCwd');

module.exports = {
    format: format,
    varify: varify,
    stringify: stringify,
    stringifyList: stringifyList,
    tablifyList: tablifyList
};

/////// GENERAL ///////////////////

function format(link) {
    link.source = formatFolder(link.source);
    link.target = formatFolder(link.target);
    return varify(link);
}

function varify(link) {
    return varifyFolder(link.source) && varifyFolder(link.target) && link;
}

/////// CLI ///////////////////////

function stringify(link) {
    return printedData(link).join(' ');
}

function stringifyList(list) {
    var table = list.map(printedData);
    var maxLengths = [];
    for (var key in table) {
      for (var i in table[key]) {
        maxLengths[i] = Math.max(maxLengths[i] || 0, realLength(table[key][i]));
      }
    }
    // Another way to calculate maxLength; more fun, but heckish as hell. This is here as an example for the curious reader:
    // var maxLengths = table[0].map(function(v,columnIndex) { return table.reduce(function(max, row) { return Math.max(max, realLength(row[columnIndex])); }, 0); });
    return table.map(function(row) {
      return row.map(function(val,i) {
        return pad(val,maxLengths[i]);
      }).join(' ');
    }).join('\n');
}

/////// GUI ///////////////////////

function tablifyList(list) {
  var table = "
";

  list.map(function(v, i) {
    table += "
";
    table += "" + v.id + "	";
    table += "" + v.source + "	";
    table += "" + v.target + "	";
    table += "(" + getTimeAgoString(v.lastSynced) + ")	";
    table += "Dry Wet Delete	";
    table += "
";
  });

  table += "
";

  return table;
}

////////////////////////////////////////////////////////////////////////////////

/////// GENERAL ///////////////////

function getTimeAgoString(unixTimeStamp) {
    return unixTimeStamp ? moment(unixTimeStamp).fromNow() : "Never";
}

function getTimeAgoStyle(unixTimeStamp) {
    var secondsAgo = moment().diff(moment(unixTimeStamp || 0)) / 1000;
    if (secondsAgo > 60*60*24*7) { //TODO: this time period (week) should be configurable.
      return 'old';
    } else if (secondsAgo > 60*60*24) { //TODO: this time period (day) should be configurable.
      return 'semi';
    }
    return 'new';
}

function formatFolder(folder) {
    if (remoteFolder(folder)) {
      if (folder[folder.length-1] != '/') {
        folder += '/';
      }
      return folder;
    }
    return path.resolve(folder) + '/';
}

function varifyFolder(folder) {
    return folder && (folder[0] == '/' || remoteFolder(folder)) && folder[folder.length-1] == '/' && folderExists(folder);
}

function folderExists(folder) {
  return remoteFolder(folder) || fs.existsSync(folder);
}

function remoteFolder(folder) {
  return !!folder.match(/[^\/]+:/);
}

function foldersStatus(folder) {
  if (remoteFolder(folder)) {
    return 'remote';
  } else if (fs.existsSync(folder)) {
    return 'exists';
  } else {
    return 'missing';
  }

}

/////// CLI ///////////////////////

function printedData(link) {
  return [link.id+":", cliColorFolder(link.source), "-->", cliColorFolder(link.target), cliTimeAgo(link.lastSynced)];
}

function realLength(str) {
  return str.replace(/.\[[0-9;]+m/g,'').length; //This removes color codes;
}

function pad(str, len) {
  for (var cur = realLength(str); cur < len; cur++) {
    str += '.';
  }
  return str;
}

function cliTimeAgo(unixTimeStamp) {
    var timeAgo = ["(",getTimeAgoString(unixTimeStamp),")"].join("");
    var style = getTimeAgoStyle(unixTimeStamp);

    if (style == 'old') {
      return clc.red(timeAgo);
    } else if (style == 'semi') {
      return clc.yellow(timeAgo);
    } else if (style == 'new') {
      return timeAgo;
    }
}

function cliColorFolder(folder) {
  var color = foldersStatus(folder);
  if (color == 'remote') {
    return clc.yellow(folder);
  } else if (color == 'exists') {
    return clc.green(folder);
  } else if (color == 'missing') {
    return clc.xterm(52)(folder);
  } else {
    return folder;
  }
}

/////// GUI ///////////////////////

<commit_msg>refactored linksDataUtils and enabled adding links to files<commit_after>"use strict";

var clc = require('cli-color');
var fs = require('fs');
// var rek = require('rekuire');
var pathResolve = require('path').resolve;
var moment = require('moment');

module.exports = {
    format: format,
    varify: varify,
    stringify: stringify,
    stringifyList: stringifyList
};

/////// Exported ///////////////////

function format(link) {
    link.source = formatPath(link.source);
    link.target = formatPath(link.target);
    return varify(link);
}

function varify(link) {
    var sourceType = pathType(link.source);
    var targetType = pathType(link.target);
    if (sourceType == PathType.REMOTE && targetType == PathType.REMOTE) return false;
    if (sourceType == PathType.NONE) return false;
    if (targetType == PathType.NONE) return false;
    return link;
}

function stringify(link) {
    return printedData(link).join(' ');
}

function stringifyList(list) {
    var table = list.map(printedData);
    var maxLengths = [];
    for (var key in table) {
      for (var i in table[key]) {
        maxLengths[i] = Math.max(maxLengths[i] || 0, realLength(table[key][i]));
      }
    }
    // Another way to calculate maxLength; more fun, but heckish as hell. This is here as an example for the curious reader:
    // var maxLengths = table[0].map(function(v,columnIndex) { return table.reduce(function(max, row) { return Math.max(max, realLength(row[columnIndex])); }, 0); });
    return table.map(function(row) {
      return row.map(function(val,i) {
        return pad(val,maxLengths[i]);
      }).join(' ');
    }).join('\n');
}

////////////////////////////////////////////////////////////////////////////////

/////// Private ///////////////////

var PathType = {
  NONE: 'none',
  FILE: 'file',
  DIR: 'dir',
  DIRECTORY: 'dir',
  REMOTE: 'remote'
}

var PathStatus = {
  MISSING: 'missing',
  REMOTE: 'remote',
  EXISTS: 'exists'
}

var LinkUpdateStatus = {
  NEW: 'new',
  SEMI: 'semi',
  OLD: 'old'
}

function pathType(path) {
  if (remotePath(path)) return PathType.REMOTE;
  if (fs.existsSync(path)) {
    if (fs.lstatSync(path).isDirectory()) return PathType.DIR;
    if (fs.lstatSync(path).isFile()) return PathType.FILE;
  }
  return PathType.NONE;
}

function getTimeAgoString(unixTimeStamp) {
    return unixTimeStamp ? moment(unixTimeStamp).fromNow() : "Never";
}

function getUpdateStatus(unixTimeStamp) {
    var secondsAgo = moment().diff(moment(unixTimeStamp || 0)) / 1000;
    if (secondsAgo > 60*60*24*7) { //TODO: this time period (week) should be configurable.
      return LinkUpdateStatus.OLD;
    } else if (secondsAgo > 60*60*24) { //TODO: this time period (day) should be configurable.
      return LinkUpdateStatus.SEMI;
    }
    return LinkUpdateStatus.NEW;
}

function formatPath(path) {
    var type = pathType(path);
    if (type == PathType.REMOTE) {
      if (/[\/:][^\.\/]+$/.test(path)) { //does path end in name without '.' not sufixed by '/'
        path += '/';
      }
      return path;
    } else {
      path = pathResolve(path);
      if (type == PathType.DIR) {
        path += '/';
      }
      return path;
    }
}

function remotePath(path) {
  return /[^\/]+:/.test(path);
}

function pathStatus(path) {
  var type = pathType(path);
  if (type == PathType.REMOTE) return PathStatus.REMOTE;
  if (type == PathType.DIR) return PathStatus.EXISTS;
  if (type == PathType.FILE) return PathStatus.EXISTS;
  return PathStatus.MISSING;
}

function printedData(link) { //TODO: this should return array of {str:"...","colorFunk":clc.red}, so that string maipulation be easier
  return [link.id+":", cliColorPath(link.source), "-->", cliColorPath(link.target), cliTimeAgo(link.lastSynced)];
}

function realLength(path) { //TODO: this should be removed, see comment on printedData
  return path.replace(/.\[[0-9;]+m/g,'').length;
}

function pad(path, len) {
  return path + multiplyString('.', len - realLength(path));
}

function multiplyString(str,n) {
  return Array.apply(null, Array(n)).map(function(){return str;}).join('');
}

function cliTimeAgo(unixTimeStamp) {
    var timeAgo = ["(",getTimeAgoString(unixTimeStamp),")"].join("");
    var updateStatus = getUpdateStatus(unixTimeStamp);
    if (updateStatus == LinkUpdateStatus.OLD) return clc.red(timeAgo);
    if (updateStatus == LinkUpdateStatus.SEMI) return clc.yellow(timeAgo);
    if (updateStatus == LinkUpdateStatus.NEW) return timeAgo;
    return timeAgo;
}

function cliColorPath(path) {
  var status = pathStatus(path);
  if (status == PathStatus.REMOTE) return clc.yellow(path);
  if (status == PathStatus.EXISTS) return clc.green(path);
  if (status == PathStatus.MISSING) return clc.xterm(52)(path);
  return path;
}

<|endoftext|>


<commit_before>var isEqual = require('../../helpers/is-equal');

module.exports = {
  ready: function() {

    var inForm = this.inForm();

    if (!this.$parent.options.sendOnlyDirtyFields)
      this.$parent.fields.push(this);

    if (inForm) {

      if (this.$parent.options.sendOnlyDirtyFields) {
      this.$watch('dirty', function(isDirty) {
        var method = isDirty?'push':'$remove';
          this.$parent.fields[method](this);
      });
      }

      var form = this.$parent;
      var v = this.$parent.validation;

      if (v.rules && v.rules.hasOwnProperty(this.name))
        this.rules = v.rules[this.name];

      if (typeof v.messages!='undefined' &&  v.messages.hasOwnProperty(this.name))
        this.messages = v.messages[this.name];

      this.validate();

      if (form.relatedFields.hasOwnProperty(this.name))
       var foreignField = form.getField(form.relatedFields[this.name]);

   }

   this.$watch('value', function(newVal, oldVal) {

    this.$dispatch('vue-formular.change::' + this.name, {value:newVal, oldValue:oldVal});

    if (typeof foreignField!='undefined') {
     foreignField.validate();
   }

   this.dirty = !isEqual(this.value,this.initialValue);
   this.pristine = false;

   if (inForm) {

    this.validate();

  }

},{deep:true});

 }

}
<commit_msg>move fields pushing to inForm<commit_after>var isEqual = require('../../helpers/is-equal');

module.exports = {
  ready: function() {

    var inForm = this.inForm();

    if (inForm) {

      if (!this.$parent.options.sendOnlyDirtyFields)
      this.$parent.fields.push(this);

      if (this.$parent.options.sendOnlyDirtyFields) {
      this.$watch('dirty', function(isDirty) {
        var method = isDirty?'push':'$remove';
          this.$parent.fields[method](this);
      });
      }

      var form = this.$parent;
      var v = this.$parent.validation;

      if (v.rules && v.rules.hasOwnProperty(this.name))
        this.rules = v.rules[this.name];

      if (typeof v.messages!='undefined' &&  v.messages.hasOwnProperty(this.name))
        this.messages = v.messages[this.name];

      this.validate();

      if (form.relatedFields.hasOwnProperty(this.name))
       var foreignField = form.getField(form.relatedFields[this.name]);

   }

   this.$watch('value', function(newVal, oldVal) {

    this.$dispatch('vue-formular.change::' + this.name, {value:newVal, oldValue:oldVal});

    if (typeof foreignField!='undefined') {
     foreignField.validate();
   }

   this.dirty = !isEqual(this.value,this.initialValue);
   this.pristine = false;

   if (inForm) {

    this.validate();

  }

},{deep:true});

 }

}
<|endoftext|>


<commit_before>/* See license.txt for terms of usage */

"use strict";

var main = require("../main.js");

const { Cu } = require("chrome");
const { Trace, TraceError } = require("../core/trace.js");
const { Domplate } = require("../core/domplate.js");
const { Dom } = require("../core/dom.js");
const { Events } = require("../core/events.js");
const { Reps } = require("../reps/reps.js");

// API for custom console messages
const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
const consoleOutputPath = "devtools/webconsole/console-output";
const { Messages, Widgets } = devtools.require(consoleOutputPath);
const ConsoleGeneric = Messages.ConsoleGeneric;
const Heritage = require("sdk/core/heritage");

// Devtools API
const utilsPath = "devtools/toolkit/webconsole/utils";
let WebConsoleUtils = devtools.require(utilsPath).Utils;

// Domplate
const { SPAN, A, domplate } = Domplate;

/**
 * TODO: description
 * @param msg {JSON} The packet received from the back-end.
 */
function ConsoleMessage(msg) {
  Messages.ConsoleGeneric.call(this, msg);

  this.message = msg;
};

ConsoleMessage.prototype = Heritage.extend(ConsoleGeneric.prototype,
/** @lends ConsoleMessage */
{
  // Render console message using registered reps.
  render: function() {
    let render = ConsoleGeneric.prototype.render.bind(this);

    let element = render().element;
    let parentNode = element.querySelector(".message-body");
    Dom.clearNode(parentNode);

    let args = this.message.arguments;
    for (let i = 0; i < args.length; i++) {
      let grip = args[i];
      this.appendObject(args[i], parentNode);
    }

    return this;
  },

  appendObject: function(object, parentNode) {
    try {
      let rep = Reps.getRep(object, this.context);

      // xxxHonza: Hack until we get IF support in domplate
      // (or bug 116083 gets fixed).
      let tag = rep.tag;
      if (rep === Reps.Text)
          tag = rep.getWhitespaceCorrectedTag(object);

      let node = tag.append({object: object}, parentNode, rep);

      // xxxHonza: hack FIX ME, the listener must be registered
      // by {@Chrome} for all panel contents.
      node.addEventListener("click", (event) => {
        this.output.openVariablesView({
          label: "",
          objectActor: Reps.getRepObject(event.target),
          autofocus: true,
        });
      }, true);

      return node;
    }
    catch (e) {
      TraceError.sysout("consoleMessage.appendObject; EXCEPTION " + e, e);
    }
  }
});

function logConsoleAPIMessage(aMessage) {
  Trace.sysout("logConsoleAPIMessage ", this);

  let body = null;
  let clipboardText = null;
  let sourceURL = aMessage.filename;
  let sourceLine = aMessage.lineNumber;
  let level = aMessage.level;
  let args = aMessage.arguments;
  let objectActors = new Set();
  let node = null;

  // Gather the actor IDs.
  args.forEach((aValue) => {
    if (WebConsoleUtils.isActorGrip(aValue)) {
      objectActors.add(aValue.actor);
    }
  });

  let msg = new ConsoleMessage(aMessage);
  node = msg.init(this.output).render().element;

  if (objectActors.size > 0) {
    node._objectActors = objectActors;

    if (!node._messageObject) {
      let repeatNode = node.getElementsByClassName("message-repeats")[0];
      repeatNode._uid += [...objectActors].join("-");
    }
  }

  return node;
}

exports.ConsoleMessage = ConsoleMessage;
exports.logConsoleAPIMessage = logConsoleAPIMessage;
<commit_msg>Create separator for objects rendered by console.log<commit_after>/* See license.txt for terms of usage */

"use strict";

var main = require("../main.js");

const { Cu } = require("chrome");
const { Trace, TraceError } = require("../core/trace.js");
const { Domplate } = require("../core/domplate.js");
const { Dom } = require("../core/dom.js");
const { Events } = require("../core/events.js");
const { Reps } = require("../reps/reps.js");

// API for custom console messages
const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
const consoleOutputPath = "devtools/webconsole/console-output";
const { Messages, Widgets } = devtools.require(consoleOutputPath);
const ConsoleGeneric = Messages.ConsoleGeneric;
const Heritage = require("sdk/core/heritage");

// Devtools API
const utilsPath = "devtools/toolkit/webconsole/utils";
let WebConsoleUtils = devtools.require(utilsPath).Utils;

// Domplate
const { SPAN, A, domplate } = Domplate;

/**
 * TODO: description
 * @param msg {JSON} The packet received from the back-end.
 */
function ConsoleMessage(msg) {
  Messages.ConsoleGeneric.call(this, msg);

  this.message = msg;
};

ConsoleMessage.prototype = Heritage.extend(ConsoleGeneric.prototype,
/** @lends ConsoleMessage */
{
  // Render console message using registered reps.
  render: function() {
    let render = ConsoleGeneric.prototype.render.bind(this);

    let element = render().element;
    let parentNode = element.querySelector(".message-body");
    Dom.clearNode(parentNode);

    let args = this.message.arguments;
    for (let i = 0; i < args.length; i++) {
      let grip = args[i];
      this.appendObject(args[i], parentNode);
      this.appendSeparator(parentNode);
    }

    return this;
  },

  appendObject: function(object, parentNode) {
    try {
      let rep = Reps.getRep(object, this.context);

      // xxxHonza: Hack until we get IF support in domplate
      // (or bug 116083 gets fixed).
      let tag = rep.tag;
      if (rep === Reps.Text)
          tag = rep.getWhitespaceCorrectedTag(object);

      let node = tag.append({object: object}, parentNode, rep);

      // xxxHonza: hack FIX ME, the listener must be registered
      // by {@Chrome} for all panel contents.
      node.addEventListener("click", (event) => {
        this.output.openVariablesView({
          label: "",
          objectActor: Reps.getRepObject(event.target),
          autofocus: true,
        });
      }, true);

      return node;
    }
    catch (e) {
      TraceError.sysout("consoleMessage.appendObject; EXCEPTION " + e, e);
    }
  },

  appendSeparator: function(parentNode) {
    let tag = SPAN(" ");
    return tag.append({}, parentNode);
  }
});

function logConsoleAPIMessage(aMessage) {
  Trace.sysout("logConsoleAPIMessage ", this);

  let body = null;
  let clipboardText = null;
  let sourceURL = aMessage.filename;
  let sourceLine = aMessage.lineNumber;
  let level = aMessage.level;
  let args = aMessage.arguments;
  let objectActors = new Set();
  let node = null;

  // Gather the actor IDs.
  args.forEach((aValue) => {
    if (WebConsoleUtils.isActorGrip(aValue)) {
      objectActors.add(aValue.actor);
    }
  });

  let msg = new ConsoleMessage(aMessage);
  node = msg.init(this.output).render().element;

  if (objectActors.size > 0) {
    node._objectActors = objectActors;

    if (!node._messageObject) {
      let repeatNode = node.getElementsByClassName("message-repeats")[0];
      repeatNode._uid += [...objectActors].join("-");
    }
  }

  return node;
}

exports.ConsoleMessage = ConsoleMessage;
exports.logConsoleAPIMessage = logConsoleAPIMessage;
<|endoftext|>


<commit_before>// ---------------------------------------------------------------------------------------------------------------------
// SyncService
//
// @module sync.js
// ---------------------------------------------------------------------------------------------------------------------

var _ = require('lodash');
var now = require('rfi-physics').now;

// ---------------------------------------------------------------------------------------------------------------------

function SyncServiceFactory($rootScope, socket)
{
    function SyncService()
    {
        this.windowSize = 10;
        this.pingInterval = 5000;
        this.pingTimes = [];
        this.latency = 0;
        this.running = false;
    } // end SyncService

    SyncService.prototype._ping = function()
    {
        var self = this;
        var startTime = now();
        socket.request('ping').then(function()
        {
            var pingTime = now() - startTime;
            self.pingTimes.push(pingTime);

            // Stay inside our window size
            while(self.pingTimes.length > self.windowSize)
            {
                self.pingTimes.shift();
            } // end while

            // Recalculate average latency (one-way) from accumulated ping measurements (round-trip).
            var sumOfPingTimes = _.reduce(this.pingTimes,
                function(sum, ping) { return sum + ping; },
                0);
            var lastLatency = this.latency;
            this.latency = ((sumOfPingTimes / this.pingTimes.length) / 2).toFixed(2);

            if(this.latency != lastLatency)
            {
                $rootScope.$broadcast('syncService.latencyChanged');
            } // end if

            if(self.running)
            {
                self.timeoutHandle = setTimeout(this._ping.bind(this), this.pingInterval);
            } // end if
        });
    }; // end _ping

    SyncService.prototype.start = function()
    {
        if(!this.running)
        {
            this.running = true;
            this.timeoutHandle = setTimeout(this._ping.bind(this), this.pingInterval);
        } // end if
    }; // end start

    SyncService.prototype.stop = function()
    {
        this.running = false;
        if(this.timeoutHandle)
        {
            clearTimeout(this.timeoutHandle);
        } // end if
    }; // end stop

    return new SyncService();
} // end SyncServiceFactory

// ---------------------------------------------------------------------------------------------------------------------

angular.module('rfi-client.services').service('SyncService', [
    'SocketService',
    SyncServiceFactory
]);

// ---------------------------------------------------------------------------------------------------------------------
<commit_msg>Corrected `this` vs. `self` mismatches, and added missing `` dependency.<commit_after>// ---------------------------------------------------------------------------------------------------------------------
// SyncService
//
// @module sync.js
// ---------------------------------------------------------------------------------------------------------------------

var _ = require('lodash');
var now = require('rfi-physics').now;

// ---------------------------------------------------------------------------------------------------------------------

function SyncServiceFactory($rootScope, socket)
{
    function SyncService()
    {
        this.windowSize = 10;
        this.pingInterval = 5000;
        this.pingTimes = [];
        this.latency = 0;
        this.running = false;
    } // end SyncService

    SyncService.prototype._ping = function()
    {
        var self = this;
        var startTime = now();
        socket.request('ping').then(function()
        {
            var pingTime = now() - startTime;
            self.pingTimes.push(pingTime);

            // Stay inside our window size
            while(self.pingTimes.length > self.windowSize)
            {
                self.pingTimes.shift();
            } // end while

            // Recalculate average latency (one-way) from accumulated ping measurements (round-trip).
            var sumOfPingTimes = _.reduce(self.pingTimes,
                function(sum, ping) { return sum + ping; },
                0);
            var lastLatency = self.latency;
            self.latency = ((sumOfPingTimes / self.pingTimes.length) / 2).toFixed(2);

            if(self.latency != lastLatency)
            {
                $rootScope.$broadcast('syncService.latencyChanged');
            } // end if

            if(self.running)
            {
                self.timeoutHandle = setTimeout(self._ping.bind(self), self.pingInterval);
            } // end if
        });
    }; // end _ping

    SyncService.prototype.start = function()
    {
        if(!this.running)
        {
            this.running = true;
            this.timeoutHandle = setTimeout(this._ping.bind(this), this.pingInterval);
        } // end if
    }; // end start

    SyncService.prototype.stop = function()
    {
        this.running = false;
        if(this.timeoutHandle)
        {
            clearTimeout(this.timeoutHandle);
        } // end if
    }; // end stop

    return new SyncService();
} // end SyncServiceFactory

// ---------------------------------------------------------------------------------------------------------------------

angular.module('rfi-client.services').service('SyncService', [
    '$rootScope',
    'SocketService',
    SyncServiceFactory
]);

// ---------------------------------------------------------------------------------------------------------------------
<|endoftext|>


<commit_before>/*jshint node: true, -W106 */
'use strict';

/*
* Name : graphModel.js
* Module : Lib::DataTier::FlowModel
* Location : /lib/dataTier/flow
*
* History :
*
* Version   Date         Programmer         Description
* =========================================================
* 0.0.1     2015-05-14   Filippo Rampado    Initial code
* =========================================================
*/

var FilterModel = require('./filterModel.js');
var Helper = require('../../helpers/functionHelper.js');

function FlowModel(params) {
	if(params===undefined || params.ID===undefined || typeof params.ID !== 'string'|| params.ID.trim() === ''){ // ID field is required
		console.log('Error: 251');
		return;
	}

	this._ID=params.ID;
	this._name='';
	this._type='';
	this._filters=null;
	this._records=[];

	if(typeof params.type === 'string' && (params.type==='BarChartFlow' || params.type==='LineChartFlow' || params.type==='MapChartFlow' || params.type==='TableFlow')){
        this._type=params.type;
    }
	this.updateProperties(params);
}

FlowModel.prototype.generateNorrisRecordID = function(number){
	var date = new Date();
	if (number !== undefined && typeof number === 'number'){
		return this._ID.concat(date.getTime()).concat(number);
	}
	return this._ID.concat(date.getTime()).concat(0);
};

FlowModel.prototype.getProperties = function(){
	var f=null;
	if (this._filters!==null){
		f=this._filters.getFilterText();
	}
	return {
		ID: this._ID,
		name: this._name,
		filters: f
	};
};

FlowModel.prototype.getData = function(){
	var flowData=[];
	var records= this._records.length;

	for(var i=0; i<records; i++){
		flowData[i]=this._records[i];
	}//for records

	return flowData;
};

FlowModel.prototype.validateData = function(){
	if (this._filters !== null){
		var records= this._records.length;
		for (var i=0; i<records; i++){
			this.validateRecord(i);
		}
	}
};

FlowModel.prototype.validateRecord = function(index){
	if (this._filters !== null && typeof index === 'number' && index>=0 && index<this._records.length){
		if (this._filters.validateRecord(this._records[index]) === true){
			this._records[index].norrisRecordIsValid = true;
		}
		if (this._filters.validateRecord(this._records[index]) === false){
			this._records[index].norrisRecordIsValid = false;
		}
	}
};

FlowModel.prototype.updateProperties = function(params) {
	if (params !== undefined){
		//ID field can't be modified
		var prop={};
		if(params.name!==undefined && typeof params.name === 'string'){
			this._name=prop.name=params.name;
		}

		if(typeof params.filters === 'string'){
			var filter=new FilterModel(params.filters);
			if (filter.hasOwnProperty('_filterText')){	//valid FilterModel
				this._filters = filter;
				prop.filters=params.filters;
				this.validateData();
			}
		}
		return prop;
	}
	return 252;
};

FlowModel.prototype.converter = function(record, key, format) {
	return Helper.converter(record,key,format);
};

module.exports = FlowModel;
<commit_msg>fix validateRecord<commit_after>/*jshint node: true, -W106 */
'use strict';

/*
* Name : graphModel.js
* Module : Lib::DataTier::FlowModel
* Location : /lib/dataTier/flow
*
* History :
*
* Version   Date         Programmer         Description
* =========================================================
* 0.0.1     2015-05-14   Filippo Rampado    Initial code
* =========================================================
*/

var FilterModel = require('./filterModel.js');
var Helper = require('../../helpers/functionHelper.js');

function FlowModel(params) {
	if(params===undefined || params.ID===undefined || typeof params.ID !== 'string'|| params.ID.trim() === ''){ // ID field is required
		console.log('Error: 251');
		return;
	}

	this._ID=params.ID;
	this._name='';
	this._type='';
	this._filters=null;
	this._records=[];

	if(typeof params.type === 'string' && (params.type==='BarChartFlow' || params.type==='LineChartFlow' || params.type==='MapChartFlow' || params.type==='TableFlow')){
        this._type=params.type;
    }
	this.updateProperties(params);
}

FlowModel.prototype.generateNorrisRecordID = function(number){
	var date = new Date();
	if (number !== undefined && typeof number === 'number'){
		return this._ID.concat(date.getTime()).concat(number);
	}
	return this._ID.concat(date.getTime()).concat(0);
};

FlowModel.prototype.getProperties = function(){
	var f=null;
	if (this._filters!==null){
		f=this._filters.getFilterText();
	}
	return {
		ID: this._ID,
		name: this._name,
		filters: f
	};
};

FlowModel.prototype.getData = function(){
	var flowData=[];
	var records= this._records.length;

	for(var i=0; i<records; i++){
		flowData[i]=this._records[i];
	}//for records

	return flowData;
};

FlowModel.prototype.validateData = function(){
	if (this._filters !== null){
		var records= this._records.length;
		for (var i=0; i<records; i++){
			this.validateRecord(i);
		}
	}
};

FlowModel.prototype.validateRecord = function(index){
	if (this._filters === null){
		this._records[index].norrisRecordIsValid = true;
	}
	if (this._filters !== null && typeof index === 'number' && index>=0 && index<this._records.length){
		if (this._filters.validateRecord(this._records[index]) === true){
			this._records[index].norrisRecordIsValid = true;
		}
		if (this._filters.validateRecord(this._records[index]) === false){
			this._records[index].norrisRecordIsValid = false;
		}
	}
};

FlowModel.prototype.updateProperties = function(params) {
	if (params !== undefined){
		//ID field can't be modified
		var prop={};
		if(params.name!==undefined && typeof params.name === 'string'){
			this._name=prop.name=params.name;
		}

		if(typeof params.filters === 'string'){
			var filter=new FilterModel(params.filters);
			if (filter.hasOwnProperty('_filterText')){	//valid FilterModel
				this._filters = filter;
				prop.filters=params.filters;
				this.validateData();
			}
		}
		return prop;
	}
	return 252;
};

FlowModel.prototype.converter = function(record, key, format) {
	return Helper.converter(record,key,format);
};

module.exports = FlowModel;
<|endoftext|>