Skip to content

Commit b5a9269

Browse files
committed
Eid and Exceptions implemented
1 parent 412be22 commit b5a9269

8 files changed

Lines changed: 694 additions & 0 deletions

File tree

‎.gitignore‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,9 @@ build/Release
2525
# Dependency directory
2626
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
2727
node_modules
28+
29+
# Coverage
30+
.coverrun
31+
.coverdata
32+
reports
33+
debug

‎.travis.yml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
---
2+
language: node_js

‎gulpfile.js‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/* eslint-disable no-var, strict, prefer-arrow-callback */
2+
'use strict';
3+
4+
var gulp = require('gulp');
5+
var eslint = require('gulp-eslint');
6+
var mocha = require('gulp-mocha');
7+
var cover = require('gulp-coverage');
8+
9+
var sources = ['./lib/**/*.js'];
10+
var testSources = ['./test/**/*.js'];
11+
12+
gulp.task('lint', function () {
13+
return gulp.src(sources)
14+
.pipe(eslint({
15+
extends: 'eslint:recommended',
16+
ecmaFeatures: {
17+
'modules': true
18+
}
19+
}))
20+
.pipe(eslint.format())
21+
.pipe(eslint.failAfterError());
22+
});
23+
24+
gulp.task('test', [], function (done) {
25+
return gulp.src(testSources, { read: false })
26+
.pipe(cover.instrument({
27+
pattern: sources,
28+
debugDirectory: 'debug'
29+
}))
30+
.pipe(mocha())
31+
.pipe(cover.gather())
32+
.pipe(cover.format())
33+
.pipe(gulp.dest('reports'));
34+
});
35+
gulp.task('watch', function() {
36+
gulp.watch(sources.concat(testSources), ['test']);
37+
});
38+
gulp.task('default', ['lint', 'test']);

‎lib/eid.js‎

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
'use strict';
2+
3+
var Eid = (function() {
4+
5+
function JFormatter(format) {
6+
this.format = function(arr) {
7+
var args = [];
8+
if (arguments.length === 1 && typeof(arr) === 'object') {
9+
args = arr;
10+
} else {
11+
for (var i = 0; i < arguments.length; i++) {
12+
args.push(arguments[i]);
13+
}
14+
}
15+
var regex = /%s/;
16+
var _r = function(p,c) { return p.replace(regex, c); }
17+
return args.reduce(_r, format);
18+
};
19+
}
20+
21+
/**
22+
* <strong>This class shouldn't be used in any public API or library.</strong> It is designed to be used for in-house development
23+
* of end user applications which will report Bugs in standardized error pages or post them to issue tracker.
24+
* <p>
25+
* Exception identifier for all Eid Runtime Exceptions.
26+
* @constructor
27+
* @param {string} id - the exception id, must be unique developer inserted string, from date
28+
* @param {string} ref - an optional reference
29+
*/
30+
function Eid(id, ref) {
31+
var uniq = EidInternal.uniqIdGenerator.generateUniqId();
32+
ref = (ref === null || ref == undefined) ? "" : ref;
33+
34+
/**
35+
* Makes a log message from this EID object
36+
* <p>
37+
* <p>This method is for convenience of usage of EID in logging. You can use it like this:
38+
* <p>
39+
* <pre>
40+
* log.debug(new Eid("20151025:202129").makeLogMessage("A request: %s", request));
41+
* </pre>
42+
* @param {string} logMessageFormat - a log message format as accepted by {@link String#format(String, Object...)}
43+
* @param {Object...} parameters - a parameters for logMessageFormat to by passed to {@link String#format(String, Object...)}
44+
* @return {string} a formatted message
45+
*/
46+
this.makeLogMessage = function(logMessageFormat) {
47+
var parameters = [];
48+
for (var i = 1; i < arguments.length; i++) {
49+
parameters.push(arguments[i]);
50+
}
51+
var message = new JFormatter(logMessageFormat).format(parameters);
52+
return new JFormatter(Eid.getMessageFormat()).format(this.toString(), message);
53+
}
54+
55+
/**
56+
* Standard to string method
57+
*/
58+
this.toString = function() {
59+
if ("" === ref) {
60+
return new JFormatter(EidInternal.format).format(id, uniq);
61+
}
62+
return new JFormatter(EidInternal.refFormat).format(id, ref, uniq);
63+
}
64+
65+
/**
66+
* Getter for constant Exception ID
67+
*
68+
* @return {string} ID of exception
69+
*/
70+
this.getId = function() {
71+
return id;
72+
}
73+
74+
/**
75+
* Get custom ref passed to Exception ID
76+
*
77+
* @return {string} ID of exception
78+
*/
79+
this.getRef = function() {
80+
return ref;
81+
}
82+
83+
/**
84+
* Gets unique generated string for this instance of Eid
85+
*
86+
* @return {string} a unique string
87+
*/
88+
this.getUniq = function() {
89+
return uniq;
90+
}
91+
}
92+
93+
function MathRandom() {
94+
var LONG_MAX = Math.pow(2, 53) - 1;
95+
var LONG_MIN = -1 * Math.pow(2, 53);
96+
this.nextLong = function() {
97+
return random(LONG_MIN, LONG_MAX);
98+
};
99+
this.nextInt = function(max) {
100+
return random(0, max);
101+
};
102+
var random = function(min, max) {
103+
return Math.floor(Math.random() * (max - min + 1)) + min;
104+
};
105+
}
106+
107+
function StdUniqIdGenerator() {
108+
var BASE36 = 36;
109+
var INTEGER_MAX_VALUE = Math.pow(2, 31);
110+
var generator = new MathRandom();
111+
this.generateUniqId = function() {
112+
var first = Math.abs(generator.nextLong() + 1);
113+
var second = Math.abs(generator.nextInt(INTEGER_MAX_VALUE));
114+
var calc = first + second;
115+
return (Math.abs(calc) % INTEGER_MAX_VALUE).toString(BASE36);
116+
};
117+
}
118+
119+
var DEFAULT_FORMAT = "[%s]<%s>";
120+
var DEFAULT_REF_FORMAT = "[%s|%s]<%s>";
121+
var DEFAULT_MESSAGE_FORMAT = "%s => %s";
122+
var DEFAULT_UNIQ_ID_GENERATOR = new StdUniqIdGenerator();
123+
124+
Object.defineProperty(Eid, "DEFAULT_FORMAT", {
125+
get: function() { return DEFAULT_FORMAT; }
126+
});
127+
Object.defineProperty(Eid, "DEFAULT_MESSAGE_FORMAT", {
128+
get: function() { return DEFAULT_MESSAGE_FORMAT; }
129+
});
130+
Object.defineProperty(Eid, "DEFAULT_REF_FORMAT", {
131+
get: function() { return DEFAULT_REF_FORMAT; }
132+
});
133+
Object.defineProperty(Eid, "DEFAULT_UNIQ_ID_GENERATOR", {
134+
get: function() { return DEFAULT_UNIQ_ID_GENERATOR; }
135+
});
136+
137+
var FORMAT_NUM_SPEC = 2;
138+
var REF_FORMAT_NUM_SPEC = 3;
139+
var MESSAGE_FORMAT_NUM_SPEC = 2;
140+
141+
var EidInternal = {
142+
messageFormat: DEFAULT_MESSAGE_FORMAT,
143+
uniqIdGenerator: DEFAULT_UNIQ_ID_GENERATOR,
144+
format: DEFAULT_FORMAT,
145+
refFormat: DEFAULT_REF_FORMAT
146+
};
147+
148+
var validateFormat = function(format, numSpecifiers) {
149+
if (format === null || format === undefined) {
150+
throw new TypeError("Format can't be null, but just received one");
151+
}
152+
var specifiers = [];
153+
for (var i = 0; i < numSpecifiers; i++) {
154+
specifiers.push(i + "-test-id");
155+
}
156+
var formatted = new JFormatter(format).format(specifiers);
157+
for (var specifier in specifiers) {
158+
if (!formatted.includes(specifier)) {
159+
throw new TypeError("Given format contains to little format specifiers, " +
160+
"expected " + numSpecifiers + " but given \"" + format + "\"");
161+
}
162+
}
163+
};
164+
165+
/**
166+
* Sets the actual unique ID generator that will be used to generate IDs for all Eid objects. It will return previously used
167+
* generator.
168+
*
169+
* @param {UniqIdGenerator} uniqIdGenerator - new instance of unique ID generator
170+
* @return {UniqIdGenerator} a previously used unique ID generator
171+
* @throws {TypeError} if given generator was null
172+
*/
173+
Eid.setUniqIdGenerator = function(uniqIdGenerator) {
174+
if (uniqIdGenerator === null || uniqIdGenerator === undefined) {
175+
throw new TypeError("Unique ID generator can't be null, but given one");
176+
}
177+
var previous = EidInternal.uniqIdGenerator;
178+
EidInternal.uniqIdGenerator = uniqIdGenerator;
179+
return previous;
180+
};
181+
182+
/**
183+
* Sets the actual format that will be used in {@link #toString()} method. It will return previously used format.
184+
*
185+
* @param {string} format - a format compliant with {@link String#format(String, Object...)} with 2 object arguments
186+
* @return {string} a previously used format
187+
* @throws {TypeError} if given format hasn't got two format specifiers <tt>"%s"</tt>, or if given format was
188+
* null
189+
*/
190+
Eid.setFormat = function(format) {
191+
validateFormat(format, FORMAT_NUM_SPEC);
192+
var previously = EidInternal.format;
193+
EidInternal.format = format;
194+
return previously;
195+
};
196+
197+
/**
198+
* Sets the actual format that will be used in {@link #toString()} method
199+
*
200+
* @param {string} refFormat - a format compliant with {@link String#format(String, Object...)} with 3 object arguments
201+
* @return {string} a previously used format
202+
* @throws {TypeError} if given format hasn't got tree format specifiers <tt>"%s"</tt>, or if given format was
203+
* null
204+
*/
205+
Eid.setRefFormat = function(refFormat) {
206+
validateFormat(refFormat, REF_FORMAT_NUM_SPEC);
207+
var previously = EidInternal.refFormat;
208+
EidInternal.refFormat = refFormat;
209+
return previously;
210+
};
211+
212+
/**
213+
* Sets a format that will be used for all Eid exceptions when printing a detail message.
214+
* <p>
215+
* Format must be non-null and contain two format specifiers <tt>"%s"</tt>
216+
*
217+
* @param {string} format - a format that will be used, must be non-null and contain two format specifiers <tt>"%s"</tt>
218+
* @return {string} previously used format
219+
* @throws {TypeError} if given format hasn't got two format specifiers <tt>"%s"</tt>, or if given format was
220+
* null
221+
*/
222+
Eid.setMessageFormat = function(format) {
223+
validateFormat(format, MESSAGE_FORMAT_NUM_SPEC);
224+
var oldFormat = EidInternal.messageFormat;
225+
EidInternal.messageFormat = format;
226+
return oldFormat;
227+
};
228+
229+
/**
230+
* Gets actually set message format
231+
*
232+
* @return {string} actually setted message format
233+
*/
234+
Eid.getMessageFormat = function() {
235+
return EidInternal.messageFormat;
236+
};
237+
238+
return Eid;
239+
})();
240+
241+
module.exports = Eid;

0 commit comments

Comments
 (0)