diff --git a/.gitignore b/.gitignore index 123ae94..05880b6 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,5 @@ build/Release # Dependency directory # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git node_modules + +target/ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..4b643c2 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,2 @@ +--- +language: node_js diff --git a/LICENSE b/LICENSE index 8f71f43..099ac17 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright {yyyy} {name of copyright owner} + Copyright 2015 Wave Software Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index deab844..a238485 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,20 @@ # javascript-eid-exceptions EID Runtime Exceptions and Utilities for JavaScript + +## Getting started + +You'll need [node / npm](https://nodejs.org/) and [tsd](http://definitelytyped.org/tsd/) installed globally. To get up and running just enter: + +``` +npm install +tsd install +npm run test +``` + +This will: + +1. Download the npm packages you need +2. Download the typings from DefinitelyTyped that you need. +3. Compile the code and serve it up at [http://localhost:8080](http://localhost:8080) + +Now you need dev tools. There's a world of choice out there; there's [Atom](https://atom.io/), there's [VS Code](https://www.visualstudio.com/en-us/products/code-vs.aspx), there's [Sublime](http://www.sublimetext.com/). There's even something called [Visual Studio](http://www.visualstudio.com). It's all your choice really. diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..928ded0 --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,63 @@ +/* eslint-disable no-var, strict, prefer-arrow-callback */ +'use strict'; + +var gulp = require('gulp'); +var gutil = require('gulp-util'); +var connect = require('gulp-connect'); +var eslint = require('gulp-eslint'); +var webpack = require('./src/gulp/webpack'); +var tests = require('./src/gulp/tests'); +var staticFiles = require('./src/gulp/staticFiles'); +var inject = require('./src/gulp/inject'); +var clean = require('./src/gulp/clean'); +var karma = require('karma'); + +var lintSrcs = ['./src/gulp/**/*.js']; + +gulp.task('clean-webpack', function (done) { + clean.runOnWebPack(done); +}); + +gulp.task('clean', ['clean-webpack'], function (done) { + clean.run(done); +}); + +gulp.task('build-process.env.NODE_ENV', function () { + process.env.NODE_ENV = 'production'; +}); + +gulp.task('build-js', ['clean-webpack', 'build-process.env.NODE_ENV'], function(done) { + webpack.build().then(function() { done(); }); +}); + +gulp.task('build-other', ['build-process.env.NODE_ENV'], function() { + staticFiles.build(); +}); + +gulp.task('build', ['build-js', 'build-other', 'lint'], function () { + inject.build(); +}); + +gulp.task('lint', function () { + return gulp.src(lintSrcs) + .pipe(eslint()) + .pipe(eslint.format()); +}); + +gulp.task('test', [], function (done) { + new karma.Server({ + configFile: __dirname + '/karma.conf.js', + singleRun: true + }, done).start(); +}); + +gulp.task('watch', ['build'], function() {}); + +gulp.task('serve', ['watch'], function() { + connect.server({ + root: './target', + port: 8080 + }); +}); + +gulp.task('default', ['build', 'test']); diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 0000000..2364e83 --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,70 @@ +/* eslint-disable no-var, strict */ +'use strict'; + +var webpackConfig = require('./webpack.config.js'); + +module.exports = function(config) { + // Documentation: https://karma-runner.github.io/0.13/config/configuration-file.html + config.set({ + browsers: [ 'PhantomJS' ], + + files: [ + 'src/test/ts/import-babel-polyfill.js', // This ensures we have the es6 shims in place from babel + 'src/test/ts/**/*.ts', + 'src/test/ts/**/*.tsx' + ], + + port: 9876, + + frameworks: [ 'jasmine', 'phantomjs-shim' ], + + logLevel: config.LOG_INFO, //config.LOG_DEBUG + + preprocessors: { + 'src/test/ts/import-babel-polyfill.js': [ 'webpack', 'sourcemap' ], + 'src/main/ts/**/*.{ts,tsx}': [ 'webpack', 'sourcemap' ], + 'src/test/ts/**/*.{ts,tsx}': [ 'webpack', 'sourcemap' ] + }, + + reporters: [ 'mocha', 'junit'/*, 'coverage'*/ ], + + webpack: { + devtool: 'inline-source-map', //'inline-source-map', + debug: true, + module: webpackConfig.module, + resolve: webpackConfig.resolve + }, + + webpackMiddleware: { + quiet: true, + stats: { + colors: true + } + }, + + // reporter options + mochaReporter: { + colors: { + success: 'green', + info: 'grey', + warning: 'yellow', + error: 'red' + } + }, + + // the default configuration + junitReporter: { + outputDir: 'target/junit-results', // results will be saved as $outputDir/$browserName.xml + outputFile: undefined, // if included, results will be saved as $outputDir/$browserName/$outputFile + suite: '' + }, + + coverageReporter: { + reporters:[ + {type: 'html', dir:'target/coverage'}, // https://github.com/karma-runner/karma-coverage/issues/123 + {type: 'text'}, + {type: 'text-summary'} + ], + } + }); +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..e65fc19 --- /dev/null +++ b/package.json @@ -0,0 +1,68 @@ +{ + "name": "eid-exceptions", + "version": "0.1.0", + "description": "EID Runtime Exceptions and Utilities for JavaScript", + "babel": {}, + "main": "eid.js", + "scripts": { + "test": "node_modules/.bin/gulp build test", + "serve": "node_modules/.bin/gulp serve", + "watch": "node_modules/.bin/gulp watch", + "build": "node_modules/.bin/gulp build" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/wavesoftware/javascript-eid-exceptions.git" + }, + "devDependencies": { + "babel": "^6.0.0", + "babel-core": "^6.0.0", + "babel-loader": "^6.0.0", + "babel-polyfill": "^6.0.0", + "babel-preset-es2015": "^6.0.0", + "del": "^2.0.2", + "eslint": "^1.6.0", + "glob": "^5.0.15", + "gulp": "^3.9.0", + "gulp-autoprefixer": "^3.1.0", + "gulp-cached": "^1.1.0", + "gulp-connect": "^2.2.0", + "gulp-cssmin": "^0.1.7", + "gulp-debug": "^2.1.2", + "gulp-eslint": "^1.0.0", + "gulp-if": "^2.0.0", + "gulp-inject": "^3.0.0", + "gulp-notify": "^2.2.0", + "gulp-sourcemaps": "^1.5.2", + "gulp-streamify": "1.0.0", + "gulp-uglify": "^1.2.0", + "gulp-util": "^3.0.6", + "jasmine-core": "^2.3.4", + "karma": "^0.13.10", + "karma-coverage": "^0.5.2", + "karma-jasmine": "^0.3.6", + "karma-junit-reporter": "^0.3.7", + "karma-mocha-reporter": "^1.1.1", + "karma-phantomjs-launcher": "^0.2.1", + "karma-phantomjs-shim": "^1.1.1", + "karma-sourcemap-loader": "^0.3.6", + "karma-webpack": "^1.7.0", + "phantomjs": "^1.9.17", + "ts-loader": "^0.7.1", + "typescript": "^1.7.5", + "webpack": "^1.12.2", + "webpack-notifier": "^1.2.1" + }, + "keywords": [ + "exception", + "errorcodes", + "error", + "handling" + ], + "author": "Krzysztof Suszyński", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/wavesoftware/javascript-eid-exceptions/issues" + }, + "homepage": "https://github.com/wavesoftware/javascript-eid-exceptions" +} diff --git a/src/gulp/.eslintrc b/src/gulp/.eslintrc new file mode 100644 index 0000000..0d32281 --- /dev/null +++ b/src/gulp/.eslintrc @@ -0,0 +1,59 @@ +{ + "root": true, + "env": { + "commonjs": true, + }, + "rules": { + "no-alert": 2, + "no-array-constructor": 2, + "no-caller": 2, + "no-catch-shadow": 2, + "no-empty-label": 2, + "no-eval": 2, + "no-extend-native": 2, + "no-extra-bind": 2, + "no-implied-eval": 2, + "no-iterator": 2, + "no-label-var": 2, + "no-labels": 2, + "no-lone-blocks": 2, + "no-loop-func": 2, + "no-multi-str": 2, + "no-native-reassign": 2, + "no-new": 2, + "no-new-func": 2, + "no-new-object": 2, + "no-new-wrappers": 2, + "no-octal-escape": 2, + "no-proto": 2, + "no-return-assign": 2, + "no-script-url": 2, + "no-sequences": 2, + "no-shadow": 2, + "no-shadow-restricted-names": 2, + "no-spaced-func": 2, + "no-trailing-spaces": 2, + "no-undef-init": 2, + "no-unused-expressions": 2, + "no-use-before-define": [2, "nofunc"], + "no-with": 2, + "camelcase": 2, + "comma-spacing": 1, + "consistent-return": 2, + "curly": [2, "all"], + "dot-notation": [2, { "allowKeywords": true }], + "eol-last": 2, + "no-extra-parens": [2, "functions"], + "eqeqeq": 2, + "new-cap": 2, + "new-parens": 2, + "quotes": [1, "single"], + "semi": 2, + "semi-spacing": [2, {"before": false, "after": true}], + "space-infix-ops": 2, + "space-return-throw-case": 2, + "space-unary-ops": [2, { "words": true, "nonwords": false }], + "strict": [2, "global"], + "yoda": [2, "never"] + } +} diff --git a/src/gulp/clean.js b/src/gulp/clean.js new file mode 100644 index 0000000..b7b3c37 --- /dev/null +++ b/src/gulp/clean.js @@ -0,0 +1,30 @@ +'use strict'; + +var del = require('del'); +var gutil = require('gulp-util'); +var fs = require('fs'); + +function run(directory, done) { + fs.stat(directory, function(err){ + if (err) { + // Never existed + done(); + } + else { + del([directory], { force: true }) + .then(function(paths) { + gutil.log('Deleted files/folders:\n', paths.join('\n')); + done(); + }) + .catch(function(error) { + gutil.log('Problem deleting:\n', error); + done(); + }); + } + }); +} + +module.exports = { + run: function(done) { return run('./target', done); }, + runOnWebPack: function(done) { return run('./target/webpack', done); } +}; diff --git a/src/gulp/inject.js b/src/gulp/inject.js new file mode 100644 index 0000000..59ba566 --- /dev/null +++ b/src/gulp/inject.js @@ -0,0 +1,36 @@ +'use strict'; + +var gulp = require('gulp'); +var inject = require('gulp-inject'); +var glob = require('glob'); + +function injectIndex(options) { + function run() { + var target = gulp.src('./src/test/html/index.html'); + var sources = gulp.src([ + './target/webpack/vendor*.js', + './target/webpack/main*.js' + ], { read: false }); + var injectOptions = { ignorePath: '/target/', addRootSlash: false }; + return target + .pipe(inject(sources, injectOptions)) + .pipe(gulp.dest('./target')); + } + + var jsCssGlob = './target/**/*.{js,css}'; + + if (options.shouldWatch) { + gulp.watch(jsCssGlob, function(evt) { + if (evt.path && evt.type === 'changed') { + run(evt.path); + } + }); + } else { + run('initial build'); + } +} + +module.exports = { + build: function() { return injectIndex({ shouldWatch: false }); }, + watch: function() { return injectIndex({ shouldWatch: true }); } +}; diff --git a/src/gulp/staticFiles.js b/src/gulp/staticFiles.js new file mode 100644 index 0000000..846a5f1 --- /dev/null +++ b/src/gulp/staticFiles.js @@ -0,0 +1,31 @@ +'use strict'; + +var gulp = require('gulp'); +var cache = require('gulp-cached'); + +var targets = [ + { description: 'INDEX', src: './src/test/html/index.html', dest: './target' } +]; + +function copy(options) { + function run(target) { + gulp.src(target.src) + .pipe(cache(target.description)) + .pipe(gulp.dest(target.dest)); + } + + function watch(target) { + gulp.watch(target.src, function() { run(target); }); + } + + targets.forEach(run); + + if (options.shouldWatch) { + targets.forEach(watch); + } +} + +module.exports = { + build: function() { return copy({ shouldWatch: false }); }, + watch: function() { return copy({ shouldWatch: true }); } +}; diff --git a/src/gulp/tests.js b/src/gulp/tests.js new file mode 100644 index 0000000..1b0b47a --- /dev/null +++ b/src/gulp/tests.js @@ -0,0 +1,35 @@ +'use strict'; + +var Server = require('karma').Server; +var path = require('path'); +var gutil = require('gulp-util'); + +module.exports = { + watch: function() { + // Documentation: https://karma-runner.github.io/0.13/dev/public-api.html + var karmaConfig = { + configFile: path.join(__dirname, '../../karma.conf.js'), + singleRun: false, + + // Fancy runner + plugins: [ + 'karma-webpack', + 'karma-jasmine', + 'karma-mocha-reporter', + 'karma-junit-reporter', + 'karma-coverage', + 'karma-sourcemap-loader', + 'karma-phantomjs-launcher', + 'karma-phantomjs-shim' + ], // karma-phantomjs-shim only in place until PhantomJS hits 2.0 and has function.bind + reporters: ['mocha'] + }; + + new Server(karmaConfig, karmaCompleted).start(); + + function karmaCompleted(exitCode) { + gutil.log('Karma has exited with:', exitCode); + process.exit(exitCode); + } + } +}; diff --git a/src/gulp/webpack.js b/src/gulp/webpack.js new file mode 100644 index 0000000..1c5bb5f --- /dev/null +++ b/src/gulp/webpack.js @@ -0,0 +1,91 @@ +'use strict'; + +var gulp = require('gulp'); +var gutil = require('gulp-util'); +var webpack = require('webpack'); +var WebpackNotifierPlugin = require('webpack-notifier'); +var webpackConfig = require('../../webpack.config.js'); + +function buildProduction(done) { + // modify some webpack config options + var myProdConfig = Object.create(webpackConfig); + myProdConfig.output.filename = '[name].[hash].js'; + + myProdConfig.plugins = myProdConfig.plugins.concat( + new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', filename: 'vendor.[hash].js' }), + new webpack.optimize.DedupePlugin(), + new webpack.optimize.UglifyJsPlugin() + ); + + // run webpack + webpack(myProdConfig, function(err, stats) { + if(err) { throw new gutil.PluginError('webpack:build', err); } + gutil.log('[webpack:build]', stats.toString({ + colors: true + })); + + if (done) { done(); } + }); +} + +function createDevCompiler() { + // modify some webpack config options + var myDevConfig = Object.create(webpackConfig); + myDevConfig.devtool = 'inline-source-map'; + myDevConfig.debug = true; + + myDevConfig.plugins = myDevConfig.plugins.concat( + new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', filename: 'vendor.js' }), + new WebpackNotifierPlugin({ title: 'Webpack build', excludeWarnings: true }) + ); + + // create a single instance of the compiler to allow caching + return webpack(myDevConfig); +} + +function buildDevelopment(done, devCompiler) { + // run webpack + devCompiler.run(function(err, stats) { + if(err) { throw new gutil.PluginError('webpack:build-dev', err); } + gutil.log('[webpack:build-dev]', stats.toString({ + chunks: false, + colors: true + })); + + if (done) { done(); } + }); +} + + +function bundle(options) { + var devCompiler; + + function build(done) { + if (options.shouldWatch) { + buildDevelopment(done, devCompiler); + } else { + buildProduction(done); + } + } + + if (options.shouldWatch) { + devCompiler = createDevCompiler(); + + gulp.watch('src/main/ts/**/*', function() { build(); }); + } + + return new Promise(function(resolve, reject) { + build(function (err) { + if (err) { + reject(err); + } else { + resolve('webpack built'); + } + }); + }); +} + +module.exports = { + build: function() { return bundle({ shouldWatch: false }); }, + watch: function() { return bundle({ shouldWatch: true }); } +}; diff --git a/src/main/ts/eid.ts b/src/main/ts/eid.ts new file mode 100644 index 0000000..242af26 --- /dev/null +++ b/src/main/ts/eid.ts @@ -0,0 +1,4 @@ +import 'babel-polyfill'; +import Eid from './eid/exceptions/Eid'; + +export default Eid; diff --git a/src/main/ts/eid/exceptions/Eid.ts b/src/main/ts/eid/exceptions/Eid.ts new file mode 100644 index 0000000..bf46590 --- /dev/null +++ b/src/main/ts/eid/exceptions/Eid.ts @@ -0,0 +1,208 @@ + +import JFormatter from './internal/JFormatter'; +import MathRandom from './internal/MathRandom'; + +export module Eid { + /** + * It is used to generate unique ID for each EID object. It's mustn't be secure because it just indicate EID object while + * logging. + */ + export interface UniqIdGenerator { + /** + * Generates a unique string ID + * + * @return a generated unique ID + */ + generateUniqId(): string; + } +} + +class StdUniqIdGenerator implements Eid.UniqIdGenerator { + private static BASE36 = 36; + private static INTEGER_MAX_VALUE = Math.pow(2, 31); + private static generator : MathRandom = new MathRandom(); + generateUniqId(): string { + var first : number = Math.abs(StdUniqIdGenerator.generator.nextLong() + 1); + var second : number = Math.abs(StdUniqIdGenerator.generator.nextInt(StdUniqIdGenerator.INTEGER_MAX_VALUE)); + var calc = first + second; + return (Math.abs(calc) % StdUniqIdGenerator.INTEGER_MAX_VALUE).toString(StdUniqIdGenerator.BASE36); + } +} +/** + * This class shouldn't be used in any public API or library. It is designed to be used for in-house development + * of end user applications which will report Bugs in standardized error pages or post them to issue tracker. + *
+ * Exception identifier for all Eid Runtime Exceptions.
+ *
+ * @author Krzysztof Suszyński
+ * Format must be non-null and contain two format specifiers "%s"
+ *
+ * @param format a format that will be used, must be non-null and contain two format specifiers "%s"
+ * @return previously used format
+ * @throws IllegalArgumentException if given format hasn't got two format specifiers "%s", or if given format was
+ * null
+ */
+ public static setMessageFormat(format : string) : string {
+ Eid.validateFormat(format, Eid.MESSAGE_FORMAT_NUM_SPEC);
+ var oldFormat : string = Eid.messageFormat;
+ Eid.messageFormat = format;
+ return oldFormat;
+ }
+
+ /**
+ * Gets actually set message format
+ *
+ * @return actually set message format
+ */
+ public static getMessageFormat() : string {
+ return Eid.messageFormat;
+ }
+
+ /**
+ * Sets the actual format that will be used in {@link #toString()} method. It will return previously used format.
+ *
+ * @param format a format compliant with {@link JFormatter#format(String, Object...)} with 2 object arguments
+ * @return a previously used format
+ * @throws TypeError if given format hasn't got two format specifiers "%s", or if given format was
+ * null
+ */
+ public static setFormat(format : string) : string {
+ Eid.validateFormat(format, Eid.FORMAT_NUM_SPEC);
+ var previously:string = Eid.format;
+ Eid.format = format;
+ return previously;
+ }
+
+ /**
+ * Sets the actual format that will be used in {@link #toString()} method
+ *
+ * @param refFormat a format compliant with {@link JFormatter#format(String, Object...)} with 3 object arguments
+ * @return a previously used format
+ * @throws TypeError if given format hasn't got tree format specifiers "%s", or if given format was
+ * null
+ */
+ public static setRefFormat(refFormat : string) : string {
+ Eid.validateFormat(refFormat, Eid.REF_FORMAT_NUM_SPEC);
+ var previously : string = Eid.refFormat;
+ Eid.refFormat = refFormat;
+ return previously;
+ }
+
+ /**
+ * Makes a log message from this EID object
+ *
+ * This method is for convenience of usage of EID in logging. You can use it like this:
+ *
+ *
+ * log.debug(new Eid("20151025:202129").makeLogMessage("A request: %s", request));
+ *
+ * @param logMessageFormat a log message format as accepted by {@link JFormatter#format(String, Object...)}
+ * @param parameters a parameters for logMessageFormat to by passed to {@link JFormatter#format(String, Object...)}
+ * @return a formatted message
+ */
+ public makeLogMessage(logMessageFormat : string, ...parameters : any[]) {
+ var message : string = JFormatter.format(logMessageFormat, parameters);
+ return JFormatter.format(Eid.getMessageFormat(), this.toString(), message);
+ }
+
+ public toString() : string {
+ if ("" === this.ref || null === this.ref) {
+ return JFormatter.format(Eid.format, this.id, this.uniq);
+ }
+ return JFormatter.format(Eid.refFormat, this.id, this.ref, this.uniq);
+ }
+
+ /**
+ * Getter for constant Exception ID
+ *
+ * @return ID of exception
+ */
+ public getId() : string {
+ return this.id;
+ }
+
+ /**
+ * Get custom ref passed to Exception ID
+ *
+ * @return ID of exception
+ */
+ public getRef() : string {
+ return this.ref;
+ }
+
+ /**
+ * Gets unique generated string for this instance of Eid
+ *
+ * @return a unique string
+ */
+ public getUniq() : string {
+ return this.uniq;
+ }
+
+ private static validateFormat(format : string, numSpecifiers : number) : void {
+ if (format == null) {
+ throw new TypeError("Format can't be null, but just received one");
+ }
+ var specifiers:string[] = [];
+ for (var i:number = 0; i < numSpecifiers; i++) {
+ specifiers.push(i + "-test-id");
+ }
+ var formatted : string = JFormatter.format(format, specifiers);
+ for (var specifier in specifiers) {
+ if (!formatted.includes(specifier)) {
+ throw new TypeError("Given format contains to little format specifiers, "
+ + "expected " + numSpecifiers + " but given \"" + format + "\"");
+ }
+ }
+ }
+
+}
diff --git a/src/main/ts/eid/exceptions/internal/JFormatter.ts b/src/main/ts/eid/exceptions/internal/JFormatter.ts
new file mode 100644
index 0000000..1df7beb
--- /dev/null
+++ b/src/main/ts/eid/exceptions/internal/JFormatter.ts
@@ -0,0 +1,12 @@
+
+/**
+ * Internal class, do not use it.
+ * @internal
+ */
+export default class JFormatter {
+ static format(format : string, ...args : any[]) : string {
+ var regex = /%s/;
+ var _r = function(p,c) { return p.replace(regex, c); }
+ return args.reduce(_r, format);
+ }
+}
diff --git a/src/main/ts/eid/exceptions/internal/MathRandom.ts b/src/main/ts/eid/exceptions/internal/MathRandom.ts
new file mode 100644
index 0000000..336f8e7
--- /dev/null
+++ b/src/main/ts/eid/exceptions/internal/MathRandom.ts
@@ -0,0 +1,17 @@
+/**
+ * This is internal package, do not use it externally
+ */
+
+export default class MathRandom {
+ private static get LONG_MAX(): number { return Math.pow(2, 53) - 1 };
+ private static get LONG_MIN(): number { return -1 * Math.pow(2, 53) };
+ nextLong() : number {
+ return this.random(MathRandom.LONG_MIN, MathRandom.LONG_MAX);
+ };
+ nextInt(max : number) : number {
+ return this.random(0, max);
+ };
+ private random(min : number, max: number) : number {
+ return Math.floor(Math.random() * (max - min + 1)) + min
+ };
+}
diff --git a/src/main/ts/eid/utils/EidPreconditions.ts b/src/main/ts/eid/utils/EidPreconditions.ts
new file mode 100644
index 0000000..6449673
--- /dev/null
+++ b/src/main/ts/eid/utils/EidPreconditions.ts
@@ -0,0 +1,89 @@
+
+
+/**
+ * This class shouldn't be used in any public API or library. It is designed to be used for in-house development
+ * of end user applications which will report Bugs in standardized error pages or post them to issue tracker.
+ *
+ * Static convenience methods that help a method or constructor check whether it was invoked correctly (whether its
+ * preconditions
+ * have been met). These methods generally accept a {@code boolean} expression which is expected to be {@code true} (or in the
+ * case of {@code
+ * checkNotNull}, an object reference which is expected to be non-null). When {@code false} (or {@code null}) is passed instead,
+ * the {@code EidPreconditions} method throws an unchecked exception, which helps the calling method communicate to its
+ * caller that
+ * that caller has made a mistake.
+ *
+ * Each method accepts a EID String or {@link Eid} object, which is designed to ease of use and provide strict ID for given
+ * Exception usage. This approach speed up development of large application and helps support teams to by giving the both static
+ * and random ID for each possible unpredicted bug.
+ *
+ * This is best to use with tools and plugins like
+ * EidGenerator for Netbeans IDE
+ *
+ * Example:
+ * {@code
+ *
+ * /**
+ * * Returns the positive square root of the given value.
+ * *
+ * * @throws EidIllegalArgumentException if the value is negative
+ * *}{@code /
+ * public static double sqrt(double value) {
+ * EidPreconditions.checkArgument(value >= 0.0, "20150718:012333");
+ * // calculate the square root
+ * }
+ *
+ * void exampleBadCaller() {
+ * double d = sqrt(-1.0);
+ * }
+ * }
+ *
+ * In this example, {@code checkArgument} throws an {@code EidIllegalArgumentException} to indicate that {@code exampleBadCaller}
+ * made an error in its call to {@code sqrt}. Exception, when it will be printed will contain user given Eid and also
+ * Randomly generated ID. Those fields can be displayed to user on error page on posted directly to issue tracker.
+ *
+ * Example:
+ *
+ *
+ *
+ * {@code
+ * // Main application class for ex.: http servlet
+ * try {
+ * performRequest(request, response);
+ * } catch (EidRuntimeException ex) {
+ * issuesTracker.put(ex);
+ * throw ex;
+ * }
+ * }
+ *
+ *
+ * Functional try to execute blocks
+ *
+ *
+ * Using functional blocks to handle operations, that are intended to operate properly, simplify the code and makes it more
+ * readable. It's also good way to deal with untested, uncovered {@code catch} blocks. It's easy and gives developers nice way of
+ * dealing with countless operations that suppose to work as intended.
+ *
+ *
+ * Example:
+ *
+ *
+ * @author Krzysztof Suszyński
+ *
+ * InputStream is = EidPreconditions.tryToExecute({@code new UnsafeSupplier