|
| 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