/**
* GPII JournalIdParser.js
*
* Responsible for journalling the state of the system's settings in order to be able to recover from system crashes or corruption of the settings state
*
* Copyright 2016 Raising the Floor - International
*
* Licensed under the New BSD license. You may not use this file except in
* compliance with this License.
*
*/
"use strict";
var fluid = fluid || require("infusion");
var gpii = fluid.registerNamespace("gpii");
fluid.registerNamespace("gpii.journal");
gpii.journal.idFormatError = fluid.freezeRecursive({
isError: true,
message: "The only supported formats for journalId are HEAD, HEAD~, HEAD~2, etc. or <1995-10-9T10:11:12, >2009-11-29T01:02:59, etc."
});
gpii.journal.parseHeadId = function (journalId) {
var index = journalId.substring("HEAD".length), depth = NaN;
if (index.length > 0) {
Eif (index.charAt(0) === "~") {
var depthString = index.substring(1);
depth = depthString.length === 0 ? 1 : fluid.parseInteger(depthString);
} else {
return gpii.journal.idFormatError;
}
} else {
depth = 0;
}
if (Number.isNaN(depth)) {
return gpii.journal.idFormatError;
} else {
return {
type: "HEAD",
depth: depth
};
}
};
gpii.journal.parseDateId = function (journalId) {
var date = Date.parse(journalId.substring(1));
return Number.isNaN(date) ? gpii.journal.idFormatError : {
type: "DATE",
before: journalId.charAt(0) === "<" ? 1 : -1,
date: date
};
};
gpii.journal.idParsers = {
"HEAD": gpii.journal.parseHeadId,
">": gpii.journal.parseDateId,
"<": gpii.journal.parseDateId
};
/** Parse a journalId specification string into a JSON form
* @param journalId {String} A journalId string beginning with HEAD, < or >
* @return {Object} A {ParsedJournalId} holding a field `type` (either "HEAD" or "DATE") and other type-specific fields
*/
gpii.journal.parseId = function (journalId) {
var togo = gpii.journal.idFormatError;
fluid.each(gpii.journal.idParsers, function (func, start) {
if (journalId.startsWith(start)) {
togo = func(journalId);
}
});
return togo;
};
/** Dereference a journalId given an array of journal files
* @param journalFiles {Array of JournalFile} An array of JournalFile objects, sorted into increasing order of age
* @param parsed {Object} A {ParsedJournalId} as returned from `gpii.journal.parseId` which will be used to index into `journalFiles`
* @return {JournalFile|Undefined} One of the JournalFile entries supplied, or undefined if the supplied journalId does not match
*/
gpii.journal.fetchJournal = function (journalFiles, parsed) {
if (parsed.type === "HEAD") {
return journalFiles[parsed.depth];
} else {
var before = parsed.before;
var toSearch = before === 1 ? journalFiles : fluid.makeArray(journalFiles).reverse();
// For "before" - stop on the first one in reverse order (original) which is before
// For "after" - stop on the first one in forward order (reversed) which is after
return fluid.find_if(toSearch, function (journal) {
return journal.createTime * before <= parsed.date * before;
});
}
};
/** Formats a millisecond timestamp into an ISO-8601 date string which is safe to
* appear in a filename
* @param {Number} A millisecond timestamp, as dispensed from `Date.now()`
* @return {String} An ISO-8601 date stamp without colon characters, e.g. 2016-07-05T220712.549Z
*/
gpii.journal.formatTimestamp = function (time) {
var date = new Date(time);
var stamp = date.toISOString();
var safeStamp = stamp.replace(/:/g, ""); // This is still a valid ISO-8601 date string, but Date.parse() will no longer parse it
return safeStamp;
};
|