- Ember.View.extend({
- attributeBindings: ['type'],
- type: 'button'
- });
- ```
-
- If the value of the property is a Boolean, the name of that property is
- added as an attribute.
-
- ```javascript
- // Renders something like
- Ember.View.extend({
- attributeBindings: ['enabled'],
- enabled: true
- });
- ```
-
- @property attributeBindings
- */
- attributeBindings: EMPTY_ARRAY,
-
- // .......................................................
- // CORE DISPLAY METHODS
- //
-
- /**
- Setup a view, but do not finish waking it up.
-
- * configure `childViews`
- * register the view with the global views hash, which is used for event
- dispatch
-
- @method init
- @private
- */
- init: function() {
- this.elementId = this.elementId || guidFor(this);
-
- this._super();
-
- // setup child views. be sure to clone the child views array first
- this._childViews = this._childViews.slice();
-
- this.classNameBindings = emberA(this.classNameBindings.slice());
-
- this.classNames = emberA(this.classNames.slice());
- },
-
- appendChild: function(view, options) {
- return this.currentState.appendChild(this, view, options);
- },
-
- /**
- Removes the child view from the parent view.
-
- @method removeChild
- @param {Ember.View} view
- @return {Ember.View} receiver
- */
- removeChild: function(view) {
- // If we're destroying, the entire subtree will be
- // freed, and the DOM will be handled separately,
- // so no need to mess with childViews.
- if (this.isDestroying) { return; }
-
- // update parent node
- set(view, '_parentView', null);
-
- // remove view from childViews array.
- var childViews = this._childViews;
-
- removeObject(childViews, view);
-
- this.propertyDidChange('childViews'); // HUH?! what happened to will change?
-
- return this;
- },
-
- /**
- Removes all children from the `parentView`.
-
- @method removeAllChildren
- @return {Ember.View} receiver
- */
- removeAllChildren: function() {
- return this.mutateChildViews(function(parentView, view) {
- parentView.removeChild(view);
- });
- },
-
- destroyAllChildren: function() {
- return this.mutateChildViews(function(parentView, view) {
- view.destroy();
- });
- },
-
- /**
- Removes the view from its `parentView`, if one is found. Otherwise
- does nothing.
-
- @method removeFromParent
- @return {Ember.View} receiver
- */
- removeFromParent: function() {
- var parent = this._parentView;
-
- // Remove DOM element from parent
- this.remove();
-
- if (parent) { parent.removeChild(this); }
- return this;
- },
-
- /**
- You must call `destroy` on a view to destroy the view (and all of its
- child views). This will remove the view from any parent node, then make
- sure that the DOM element managed by the view can be released by the
- memory manager.
-
- @method destroy
- */
- destroy: function() {
- var childViews = this._childViews,
- // get parentView before calling super because it'll be destroyed
- nonVirtualParentView = get(this, 'parentView'),
- viewName = this.viewName,
- childLen, i;
-
- if (!this._super()) { return; }
-
- childLen = childViews.length;
- for (i=childLen-1; i>=0; i--) {
- childViews[i].removedFromDOM = true;
- }
-
- // remove from non-virtual parent view if viewName was specified
- if (viewName && nonVirtualParentView) {
- nonVirtualParentView.set(viewName, null);
- }
-
- childLen = childViews.length;
- for (i=childLen-1; i>=0; i--) {
- childViews[i].destroy();
- }
-
- return this;
- },
-
- /**
- Instantiates a view to be added to the childViews array during view
- initialization. You generally will not call this method directly unless
- you are overriding `createChildViews()`. Note that this method will
- automatically configure the correct settings on the new view instance to
- act as a child of the parent.
-
- @method createChildView
- @param {Class|String} viewClass
- @param {Hash} [attrs] Attributes to add
- @return {Ember.View} new instance
- */
- createChildView: function(view, attrs) {
- if (!view) {
- throw new TypeError("createChildViews first argument must exist");
- }
-
- if (view.isView && view._parentView === this && view.container === this.container) {
- return view;
- }
-
- attrs = attrs || {};
- attrs._parentView = this;
-
- if (CoreView.detect(view)) {
- attrs.templateData = attrs.templateData || get(this, 'templateData');
-
- attrs.container = this.container;
- view = view.create(attrs);
-
- // don't set the property on a virtual view, as they are invisible to
- // consumers of the view API
- if (view.viewName) {
- set(get(this, 'concreteView'), view.viewName, view);
- }
- } else if ('string' === typeof view) {
- var fullName = 'view:' + view;
- var ViewKlass = this.container.lookupFactory(fullName);
-
-
- attrs.templateData = get(this, 'templateData');
- view = ViewKlass.create(attrs);
- } else {
- attrs.container = this.container;
-
- if (!get(view, 'templateData')) {
- attrs.templateData = get(this, 'templateData');
- }
-
- setProperties(view, attrs);
-
- }
-
- return view;
- },
-
- becameVisible: Ember.K,
- becameHidden: Ember.K,
-
- /**
- When the view's `isVisible` property changes, toggle the visibility
- element of the actual DOM element.
-
- @method _isVisibleDidChange
- @private
- */
- _isVisibleDidChange: observer('isVisible', function() {
- if (this._isVisible === get(this, 'isVisible')) { return ; }
- run.scheduleOnce('render', this, this._toggleVisibility);
- }),
-
- _toggleVisibility: function() {
- var $el = this.$();
- if (!$el) { return; }
-
- var isVisible = get(this, 'isVisible');
-
- if (this._isVisible === isVisible) { return ; }
-
- $el.toggle(isVisible);
-
- this._isVisible = isVisible;
-
- if (this._isAncestorHidden()) { return; }
-
- if (isVisible) {
- this._notifyBecameVisible();
- } else {
- this._notifyBecameHidden();
- }
- },
-
- _notifyBecameVisible: function() {
- this.trigger('becameVisible');
-
- this.forEachChildView(function(view) {
- var isVisible = get(view, 'isVisible');
-
- if (isVisible || isVisible === null) {
- view._notifyBecameVisible();
- }
- });
- },
-
- _notifyBecameHidden: function() {
- this.trigger('becameHidden');
- this.forEachChildView(function(view) {
- var isVisible = get(view, 'isVisible');
-
- if (isVisible || isVisible === null) {
- view._notifyBecameHidden();
- }
- });
- },
-
- _isAncestorHidden: function() {
- var parent = get(this, 'parentView');
-
- while (parent) {
- if (get(parent, 'isVisible') === false) { return true; }
-
- parent = get(parent, 'parentView');
- }
-
- return false;
- },
-
- clearBuffer: function() {
- this.invokeRecursively(nullViewsBuffer);
- },
- transitionTo: function(state, children) {
- this._transitionTo(state, children);
- },
- _transitionTo: function(state, children) {
- var priorState = this.currentState;
- var currentState = this.currentState = this._states[state];
-
- this._state = state;
-
- if (priorState && priorState.exit) { priorState.exit(this); }
- if (currentState.enter) { currentState.enter(this); }
- if (state === 'inDOM') { meta(this).cache.element = undefined; }
-
- if (children !== false) {
- this.forEachChildView(function(view) {
- view._transitionTo(state);
- });
- }
- },
-
- // .......................................................
- // EVENT HANDLING
- //
-
- /**
- Handle events from `Ember.EventDispatcher`
-
- @method handleEvent
- @param eventName {String}
- @param evt {Event}
- @private
- */
- handleEvent: function(eventName, evt) {
- return this.currentState.handleEvent(this, eventName, evt);
- },
-
- registerObserver: function(root, path, target, observer) {
- if (!observer && 'function' === typeof target) {
- observer = target;
- target = null;
- }
-
- if (!root || typeof root !== 'object') {
- return;
- }
-
- var view = this,
- stateCheckedObserver = function() {
- view.currentState.invokeObserver(this, observer);
- },
- scheduledObserver = function() {
- run.scheduleOnce('render', this, stateCheckedObserver);
- };
-
- addObserver(root, path, target, scheduledObserver);
-
- this.one('willClearRender', function() {
- removeObserver(root, path, target, scheduledObserver);
- });
- }
-
- });
-
- /*
- Describe how the specified actions should behave in the various
- states that a view can exist in. Possible states:
-
- * preRender: when a view is first instantiated, and after its
- element was destroyed, it is in the preRender state
- * inBuffer: once a view has been rendered, but before it has
- been inserted into the DOM, it is in the inBuffer state
- * hasElement: the DOM representation of the view is created,
- and is ready to be inserted
- * inDOM: once a view has been inserted into the DOM it is in
- the inDOM state. A view spends the vast majority of its
- existence in this state.
- * destroyed: once a view has been destroyed (using the destroy
- method), it is in this state. No further actions can be invoked
- on a destroyed view.
- */
-
- // in the destroyed state, everything is illegal
-
- // before rendering has begun, all legal manipulations are noops.
-
- // inside the buffer, legal manipulations are done on the buffer
-
- // once the view has been inserted into the DOM, legal manipulations
- // are done on the DOM element.
-
- function notifyMutationListeners() {
- run.once(View, 'notifyMutationListeners');
- }
-
- var DOMManager = {
- prepend: function(view, html) {
- view.$().prepend(html);
- notifyMutationListeners();
- },
-
- after: function(view, html) {
- view.$().after(html);
- notifyMutationListeners();
- },
-
- html: function(view, html) {
- view.$().html(html);
- notifyMutationListeners();
- },
-
- replace: function(view) {
- var element = get(view, 'element');
-
- set(view, 'element', null);
-
- view._insertElementLater(function() {
- jQuery(element).replaceWith(get(view, 'element'));
- notifyMutationListeners();
- });
- },
-
- remove: function(view) {
- view.$().remove();
- notifyMutationListeners();
- },
-
- empty: function(view) {
- view.$().empty();
- notifyMutationListeners();
- }
- };
-
- View.reopen({
- domManager: DOMManager
- });
-
- View.reopenClass({
-
- /**
- Parse a path and return an object which holds the parsed properties.
-
- For example a path like "content.isEnabled:enabled:disabled" will return the
- following object:
-
- ```javascript
- {
- path: "content.isEnabled",
- className: "enabled",
- falsyClassName: "disabled",
- classNames: ":enabled:disabled"
- }
- ```
-
- @method _parsePropertyPath
- @static
- @private
- */
- _parsePropertyPath: function(path) {
- var split = path.split(':'),
- propertyPath = split[0],
- classNames = "",
- className,
- falsyClassName;
-
- // check if the property is defined as prop:class or prop:trueClass:falseClass
- if (split.length > 1) {
- className = split[1];
- if (split.length === 3) { falsyClassName = split[2]; }
-
- classNames = ':' + className;
- if (falsyClassName) { classNames += ":" + falsyClassName; }
- }
-
- return {
- path: propertyPath,
- classNames: classNames,
- className: (className === '') ? undefined : className,
- falsyClassName: falsyClassName
- };
- },
-
- /**
- Get the class name for a given value, based on the path, optional
- `className` and optional `falsyClassName`.
-
- - if a `className` or `falsyClassName` has been specified:
- - if the value is truthy and `className` has been specified,
- `className` is returned
- - if the value is falsy and `falsyClassName` has been specified,
- `falsyClassName` is returned
- - otherwise `null` is returned
- - if the value is `true`, the dasherized last part of the supplied path
- is returned
- - if the value is not `false`, `undefined` or `null`, the `value`
- is returned
- - if none of the above rules apply, `null` is returned
-
- @method _classStringForValue
- @param path
- @param val
- @param className
- @param falsyClassName
- @static
- @private
- */
- _classStringForValue: function(path, val, className, falsyClassName) {
- if(isArray(val)) {
- val = get(val, 'length') !== 0;
- }
-
- // When using the colon syntax, evaluate the truthiness or falsiness
- // of the value to determine which className to return
- if (className || falsyClassName) {
- if (className && !!val) {
- return className;
-
- } else if (falsyClassName && !val) {
- return falsyClassName;
-
- } else {
- return null;
- }
-
- // If value is a Boolean and true, return the dasherized property
- // name.
- } else if (val === true) {
- // Normalize property path to be suitable for use
- // as a class name. For exaple, content.foo.barBaz
- // becomes bar-baz.
- var parts = path.split('.');
- return dasherize(parts[parts.length-1]);
-
- // If the value is not false, undefined, or null, return the current
- // value of the property.
- } else if (val !== false && val != null) {
- return val;
-
- // Nothing to display. Return null so that the old class is removed
- // but no new class is added.
- } else {
- return null;
- }
- }
- });
-
- var mutation = EmberObject.extend(Evented).create();
-
- View.addMutationListener = function(callback) {
- mutation.on('change', callback);
- };
-
- View.removeMutationListener = function(callback) {
- mutation.off('change', callback);
- };
-
- View.notifyMutationListeners = function() {
- mutation.trigger('change');
- };
-
- /**
- Global views hash
-
- @property views
- @static
- @type Hash
- */
- View.views = {};
-
- // If someone overrides the child views computed property when
- // defining their class, we want to be able to process the user's
- // supplied childViews and then restore the original computed property
- // at view initialization time. This happens in Ember.ContainerView's init
- // method.
- View.childViewsProperty = childViewsProperty;
-
- View.applyAttributeBindings = function(elem, name, value) {
- var type = typeOf(value);
-
- // if this changes, also change the logic in ember-handlebars/lib/helpers/binding.js
- if (name !== 'value' && (type === 'string' || (type === 'number' && !isNaN(value)))) {
- if (value !== elem.attr(name)) {
- elem.attr(name, value);
- }
- } else if (name === 'value' || type === 'boolean') {
- if (isNone(value) || value === false) {
- // `null`, `undefined` or `false` should remove attribute
- elem.removeAttr(name);
- // In IE8 `prop` couldn't remove attribute when name is `required`.
- if (name === 'required') {
- elem.removeProp(name);
- } else {
- elem.prop(name, '');
- }
- } else if (value !== elem.prop(name)) {
- // value should always be properties
- elem.prop(name, value);
- }
- } else if (!value) {
- elem.removeAttr(name);
- }
- };
-
- __exports__["default"] = View;
- });
-define("ember-views/views/view_collection",
- ["ember-metal/enumerable_utils","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var forEach = __dependency1__.forEach;
-
- function ViewCollection(initialViews) {
- var views = this.views = initialViews || [];
- this.length = views.length;
- }
-
- ViewCollection.prototype = {
- length: 0,
-
- trigger: function(eventName) {
- var views = this.views, view;
- for (var i = 0, l = views.length; i < l; i++) {
- view = views[i];
- if (view.trigger) { view.trigger(eventName); }
- }
- },
-
- triggerRecursively: function(eventName) {
- var views = this.views;
- for (var i = 0, l = views.length; i < l; i++) {
- views[i].triggerRecursively(eventName);
- }
- },
-
- invokeRecursively: function(fn) {
- var views = this.views, view;
-
- for (var i = 0, l = views.length; i < l; i++) {
- view = views[i];
- fn(view);
- }
- },
-
- transitionTo: function(state, children) {
- var views = this.views;
- for (var i = 0, l = views.length; i < l; i++) {
- views[i]._transitionTo(state, children);
- }
- },
-
- push: function() {
- this.length += arguments.length;
- var views = this.views;
- return views.push.apply(views, arguments);
- },
-
- objectAt: function(idx) {
- return this.views[idx];
- },
-
- forEach: function(callback) {
- var views = this.views;
- return forEach(views, callback);
- },
-
- clear: function() {
- this.length = 0;
- this.views.length = 0;
- }
- };
-
- __exports__["default"] = ViewCollection;
- });
-define("ember",
- ["ember-metal","ember-runtime","ember-handlebars","ember-views","ember-routing","ember-routing-handlebars","ember-application","ember-extension-support"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__) {
- "use strict";
- // require the main entry points for each of these packages
- // this is so that the global exports occur properly
-
- // do this to ensure that Ember.Test is defined properly on the global
- // if it is present.
- if (Ember.__loader.registry['ember-testing']) {
- requireModule('ember-testing');
- }
-
- /**
- Ember
-
- @module ember
- */
-
- function throwWithMessage(msg) {
- return function() {
- throw new Ember.Error(msg);
- };
- }
-
- function generateRemovedClass(className) {
- var msg = " has been moved into a plugin: https://github.com/emberjs/ember-states";
-
- return {
- extend: throwWithMessage(className + msg),
- create: throwWithMessage(className + msg)
- };
- }
-
- Ember.StateManager = generateRemovedClass("Ember.StateManager");
-
- /**
- This was exported to ember-states plugin for v 1.0.0 release. See: https://github.com/emberjs/ember-states
-
- @class StateManager
- @namespace Ember
- */
-
- Ember.State = generateRemovedClass("Ember.State");
-
- /**
- This was exported to ember-states plugin for v 1.0.0 release. See: https://github.com/emberjs/ember-states
-
- @class State
- @namespace Ember
- */
- });
-define("metamorph",
- [],
- function() {
- "use strict";
- // ==========================================================================
- // Project: metamorph
- // Copyright: ©2014 Tilde, Inc. All rights reserved.
- // ==========================================================================
-
- var K = function() {},
- guid = 0,
- disableRange = (function(){
- if ('undefined' !== typeof MetamorphENV) {
- return MetamorphENV.DISABLE_RANGE_API;
- } else if ('undefined' !== ENV) {
- return ENV.DISABLE_RANGE_API;
- } else {
- return false;
- }
- })(),
-
- // Feature-detect the W3C range API, the extended check is for IE9 which only partially supports ranges
- supportsRange = (!disableRange) && typeof document !== 'undefined' && ('createRange' in document) && (typeof Range !== 'undefined') && Range.prototype.createContextualFragment,
-
- // Internet Explorer prior to 9 does not allow setting innerHTML if the first element
- // is a "zero-scope" element. This problem can be worked around by making
- // the first node an invisible text node. We, like Modernizr, use
- needsShy = typeof document !== 'undefined' && (function() {
- var testEl = document.createElement('div');
- testEl.innerHTML = "
";
- testEl.firstChild.innerHTML = "";
- return testEl.firstChild.innerHTML === '';
- })(),
-
-
- // IE 8 (and likely earlier) likes to move whitespace preceeding
- // a script tag to appear after it. This means that we can
- // accidentally remove whitespace when updating a morph.
- movesWhitespace = document && (function() {
- var testEl = document.createElement('div');
- testEl.innerHTML = "Test: Value";
- return testEl.childNodes[0].nodeValue === 'Test:' &&
- testEl.childNodes[2].nodeValue === ' Value';
- })();
-
- // Constructor that supports either Metamorph('foo') or new
- // Metamorph('foo');
- //
- // Takes a string of HTML as the argument.
-
- var Metamorph = function(html) {
- var self;
-
- if (this instanceof Metamorph) {
- self = this;
- } else {
- self = new K();
- }
-
- self.innerHTML = html;
- var myGuid = 'metamorph-'+(guid++);
- self.start = myGuid + '-start';
- self.end = myGuid + '-end';
-
- return self;
- };
-
- K.prototype = Metamorph.prototype;
-
- var rangeFor, htmlFunc, removeFunc, outerHTMLFunc, appendToFunc, afterFunc, prependFunc, startTagFunc, endTagFunc;
-
- outerHTMLFunc = function() {
- return this.startTag() + this.innerHTML + this.endTag();
- };
-
- startTagFunc = function() {
- /*
- * We replace chevron by its hex code in order to prevent escaping problems.
- * Check this thread for more explaination:
- * http://stackoverflow.com/questions/8231048/why-use-x3c-instead-of-when-generating-html-from-javascript
- */
- return "
hi ";
- * div.firstChild.firstChild.tagName //=> ""
- *
- * If our script markers are inside such a node, we need to find that
- * node and use *it* as the marker.
- */
- var realNode = function(start) {
- while (start.parentNode.tagName === "") {
- start = start.parentNode;
- }
-
- return start;
- };
-
- /*
- * When automatically adding a tbody, Internet Explorer inserts the
- * tbody immediately before the first
. Other browsers create it
- * before the first node, no matter what.
- *
- * This means the the following code:
- *
- * div = document.createElement("div");
- * div.innerHTML = "
- *
- * Generates the following DOM in IE:
- *
- * + div
- * + table
- * - script id='first'
- * + tbody
- * + tr
- * + td
- * - "hi"
- * - script id='last'
- *
- * Which means that the two script tags, even though they were
- * inserted at the same point in the hierarchy in the original
- * HTML, now have different parents.
- *
- * This code reparents the first script tag by making it the tbody's
- * first child.
- *
- */
- var fixParentage = function(start, end) {
- if (start.parentNode !== end.parentNode) {
- end.parentNode.insertBefore(start, end.parentNode.firstChild);
- }
- };
-
- htmlFunc = function(html, outerToo) {
- // get the real starting node. see realNode for details.
- var start = realNode(document.getElementById(this.start));
- var end = document.getElementById(this.end);
- var parentNode = end.parentNode;
- var node, nextSibling, last;
-
- // make sure that the start and end nodes share the same
- // parent. If not, fix it.
- fixParentage(start, end);
-
- // remove all of the nodes after the starting placeholder and
- // before the ending placeholder.
- node = start.nextSibling;
- while (node) {
- nextSibling = node.nextSibling;
- last = node === end;
-
- // if this is the last node, and we want to remove it as well,
- // set the `end` node to the next sibling. This is because
- // for the rest of the function, we insert the new nodes
- // before the end (note that insertBefore(node, null) is
- // the same as appendChild(node)).
- //
- // if we do not want to remove it, just break.
- if (last) {
- if (outerToo) { end = node.nextSibling; } else { break; }
- }
-
- node.parentNode.removeChild(node);
-
- // if this is the last node and we didn't break before
- // (because we wanted to remove the outer nodes), break
- // now.
- if (last) { break; }
-
- node = nextSibling;
- }
-
- // get the first node for the HTML string, even in cases like
- // tables and lists where a simple innerHTML on a div would
- // swallow some of the content.
- node = firstNodeFor(start.parentNode, html);
-
- if (outerToo) {
- start.parentNode.removeChild(start);
- }
-
- // copy the nodes for the HTML between the starting and ending
- // placeholder.
- while (node) {
- nextSibling = node.nextSibling;
- parentNode.insertBefore(node, end);
- node = nextSibling;
- }
- };
-
- // remove the nodes in the DOM representing this metamorph.
- //
- // this includes the starting and ending placeholders.
- removeFunc = function() {
- var start = realNode(document.getElementById(this.start));
- var end = document.getElementById(this.end);
-
- this.html('');
- start.parentNode.removeChild(start);
- end.parentNode.removeChild(end);
- };
-
- appendToFunc = function(parentNode) {
- var node = firstNodeFor(parentNode, this.outerHTML());
- var nextSibling;
-
- while (node) {
- nextSibling = node.nextSibling;
- parentNode.appendChild(node);
- node = nextSibling;
- }
- };
-
- afterFunc = function(html) {
- // get the real starting node. see realNode for details.
- var end = document.getElementById(this.end);
- var insertBefore = end.nextSibling;
- var parentNode = end.parentNode;
- var nextSibling;
- var node;
-
- // get the first node for the HTML string, even in cases like
- // tables and lists where a simple innerHTML on a div would
- // swallow some of the content.
- node = firstNodeFor(parentNode, html);
-
- // copy the nodes for the HTML between the starting and ending
- // placeholder.
- while (node) {
- nextSibling = node.nextSibling;
- parentNode.insertBefore(node, insertBefore);
- node = nextSibling;
- }
- };
-
- prependFunc = function(html) {
- var start = document.getElementById(this.start);
- var parentNode = start.parentNode;
- var nextSibling;
- var node;
-
- node = firstNodeFor(parentNode, html);
- var insertBefore = start.nextSibling;
-
- while (node) {
- nextSibling = node.nextSibling;
- parentNode.insertBefore(node, insertBefore);
- node = nextSibling;
- }
- };
- }
-
- Metamorph.prototype.html = function(html) {
- this.checkRemoved();
- if (html === undefined) { return this.innerHTML; }
-
- htmlFunc.call(this, html);
-
- this.innerHTML = html;
- };
-
- Metamorph.prototype.replaceWith = function(html) {
- this.checkRemoved();
- htmlFunc.call(this, html, true);
- };
-
- Metamorph.prototype.remove = removeFunc;
- Metamorph.prototype.outerHTML = outerHTMLFunc;
- Metamorph.prototype.appendTo = appendToFunc;
- Metamorph.prototype.after = afterFunc;
- Metamorph.prototype.prepend = prependFunc;
- Metamorph.prototype.startTag = startTagFunc;
- Metamorph.prototype.endTag = endTagFunc;
-
- Metamorph.prototype.isRemoved = function() {
- var before = document.getElementById(this.start);
- var after = document.getElementById(this.end);
-
- return !before || !after;
- };
-
- Metamorph.prototype.checkRemoved = function() {
- if (this.isRemoved()) {
- throw new Error("Cannot perform operations on a Metamorph that is not in the DOM.");
- }
- };
-
- return Metamorph;
- });
-
-define("route-recognizer",
- ["route-recognizer/dsl","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var map = __dependency1__["default"];
-
- var specials = [
- '/', '.', '*', '+', '?', '|',
- '(', ')', '[', ']', '{', '}', '\\'
- ];
-
- var escapeRegex = new RegExp('(\\' + specials.join('|\\') + ')', 'g');
-
- function isArray(test) {
- return Object.prototype.toString.call(test) === "[object Array]";
- }
-
- // A Segment represents a segment in the original route description.
- // Each Segment type provides an `eachChar` and `regex` method.
- //
- // The `eachChar` method invokes the callback with one or more character
- // specifications. A character specification consumes one or more input
- // characters.
- //
- // The `regex` method returns a regex fragment for the segment. If the
- // segment is a dynamic of star segment, the regex fragment also includes
- // a capture.
- //
- // A character specification contains:
- //
- // * `validChars`: a String with a list of all valid characters, or
- // * `invalidChars`: a String with a list of all invalid characters
- // * `repeat`: true if the character specification can repeat
-
- function StaticSegment(string) { this.string = string; }
- StaticSegment.prototype = {
- eachChar: function(callback) {
- var string = this.string, ch;
-
- for (var i=0, l=string.length; i " + n.nextStates.map(function(s) { return s.debug() }).join(" or ") + " )";
- }).join(", ")
- }
- END IF **/
-
- // This is a somewhat naive strategy, but should work in a lot of cases
- // A better strategy would properly resolve /posts/:id/new and /posts/edit/:id.
- //
- // This strategy generally prefers more static and less dynamic matching.
- // Specifically, it
- //
- // * prefers fewer stars to more, then
- // * prefers using stars for less of the match to more, then
- // * prefers fewer dynamic segments to more, then
- // * prefers more static segments to more
- function sortSolutions(states) {
- return states.sort(function(a, b) {
- if (a.types.stars !== b.types.stars) { return a.types.stars - b.types.stars; }
-
- if (a.types.stars) {
- if (a.types.statics !== b.types.statics) { return b.types.statics - a.types.statics; }
- if (a.types.dynamics !== b.types.dynamics) { return b.types.dynamics - a.types.dynamics; }
- }
-
- if (a.types.dynamics !== b.types.dynamics) { return a.types.dynamics - b.types.dynamics; }
- if (a.types.statics !== b.types.statics) { return b.types.statics - a.types.statics; }
-
- return 0;
- });
- }
-
- function recognizeChar(states, ch) {
- var nextStates = [];
-
- for (var i=0, l=states.length; i 2 && key.slice(keyLength -2) === '[]') {
- isArray = true;
- key = key.slice(0, keyLength - 2);
- if(!queryParams[key]) {
- queryParams[key] = [];
- }
- }
- value = pair[1] ? decodeURIComponent(pair[1]) : '';
- }
- if (isArray) {
- queryParams[key].push(value);
- } else {
- queryParams[key] = value;
- }
- }
- return queryParams;
- },
-
- recognize: function(path) {
- var states = [ this.rootState ],
- pathLen, i, l, queryStart, queryParams = {},
- isSlashDropped = false;
-
- queryStart = path.indexOf('?');
- if (queryStart !== -1) {
- var queryString = path.substr(queryStart + 1, path.length);
- path = path.substr(0, queryStart);
- queryParams = this.parseQueryString(queryString);
- }
-
- path = decodeURI(path);
-
- // DEBUG GROUP path
-
- if (path.charAt(0) !== "/") { path = "/" + path; }
-
- pathLen = path.length;
- if (pathLen > 1 && path.charAt(pathLen - 1) === "/") {
- path = path.substr(0, pathLen - 1);
- isSlashDropped = true;
- }
-
- for (i=0, l=path.length; i= 0 && proceed; --i) {
- var route = routes[i];
- recognizer.add(routes, { as: route.handler });
- proceed = route.path === '/' || route.path === '' || route.handler.slice(-6) === '.index';
- }
- });
- },
-
- hasRoute: function(route) {
- return this.recognizer.hasRoute(route);
- },
-
- queryParamsTransition: function(changelist, wasTransitioning, oldState, newState) {
- var router = this;
-
- fireQueryParamDidChange(this, newState, changelist);
-
- if (!wasTransitioning && this.activeTransition) {
- // One of the handlers in queryParamsDidChange
- // caused a transition. Just return that transition.
- return this.activeTransition;
- } else {
- // Running queryParamsDidChange didn't change anything.
- // Just update query params and be on our way.
-
- // We have to return a noop transition that will
- // perform a URL update at the end. This gives
- // the user the ability to set the url update
- // method (default is replaceState).
- var newTransition = new Transition(this);
- newTransition.queryParamsOnly = true;
-
- oldState.queryParams = finalizeQueryParamChange(this, newState.handlerInfos, newState.queryParams, newTransition);
-
- newTransition.promise = newTransition.promise.then(function(result) {
- updateURL(newTransition, oldState, true);
- if (router.didTransition) {
- router.didTransition(router.currentHandlerInfos);
- }
- return result;
- }, null, promiseLabel("Transition complete"));
- return newTransition;
- }
- },
-
- // NOTE: this doesn't really belong here, but here
- // it shall remain until our ES6 transpiler can
- // handle cyclical deps.
- transitionByIntent: function(intent, isIntermediate) {
-
- var wasTransitioning = !!this.activeTransition;
- var oldState = wasTransitioning ? this.activeTransition.state : this.state;
- var newTransition;
- var router = this;
-
- try {
- var newState = intent.applyToState(oldState, this.recognizer, this.getHandler, isIntermediate);
- var queryParamChangelist = getChangelist(oldState.queryParams, newState.queryParams);
-
- if (handlerInfosEqual(newState.handlerInfos, oldState.handlerInfos)) {
-
- // This is a no-op transition. See if query params changed.
- if (queryParamChangelist) {
- newTransition = this.queryParamsTransition(queryParamChangelist, wasTransitioning, oldState, newState);
- if (newTransition) {
- return newTransition;
- }
- }
-
- // No-op. No need to create a new transition.
- return new Transition(this);
- }
-
- if (isIntermediate) {
- setupContexts(this, newState);
- return;
- }
-
- // Create a new transition to the destination route.
- newTransition = new Transition(this, intent, newState);
-
- // Abort and usurp any previously active transition.
- if (this.activeTransition) {
- this.activeTransition.abort();
- }
- this.activeTransition = newTransition;
-
- // Transition promises by default resolve with resolved state.
- // For our purposes, swap out the promise to resolve
- // after the transition has been finalized.
- newTransition.promise = newTransition.promise.then(function(result) {
- return finalizeTransition(newTransition, result.state);
- }, null, promiseLabel("Settle transition promise when transition is finalized"));
-
- if (!wasTransitioning) {
- notifyExistingHandlers(this, newState, newTransition);
- }
-
- fireQueryParamDidChange(this, newState, queryParamChangelist);
-
- return newTransition;
- } catch(e) {
- return new Transition(this, intent, null, e);
- }
- },
-
- /**
- Clears the current and target route handlers and triggers exit
- on each of them starting at the leaf and traversing up through
- its ancestors.
- */
- reset: function() {
- if (this.state) {
- forEach(this.state.handlerInfos.slice().reverse(), function(handlerInfo) {
- var handler = handlerInfo.handler;
- callHook(handler, 'exit');
- });
- }
-
- this.state = new TransitionState();
- this.currentHandlerInfos = null;
- },
-
- activeTransition: null,
-
- /**
- var handler = handlerInfo.handler;
- The entry point for handling a change to the URL (usually
- via the back and forward button).
-
- Returns an Array of handlers and the parameters associated
- with those parameters.
-
- @param {String} url a URL to process
-
- @return {Array} an Array of `[handler, parameter]` tuples
- */
- handleURL: function(url) {
- // Perform a URL-based transition, but don't change
- // the URL afterward, since it already happened.
- var args = slice.call(arguments);
- if (url.charAt(0) !== '/') { args[0] = '/' + url; }
-
- return doTransition(this, args).method(null);
- },
-
- /**
- Hook point for updating the URL.
-
- @param {String} url a URL to update to
- */
- updateURL: function() {
- throw new Error("updateURL is not implemented");
- },
-
- /**
- Hook point for replacing the current URL, i.e. with replaceState
-
- By default this behaves the same as `updateURL`
-
- @param {String} url a URL to update to
- */
- replaceURL: function(url) {
- this.updateURL(url);
- },
-
- /**
- Transition into the specified named route.
-
- If necessary, trigger the exit callback on any handlers
- that are no longer represented by the target route.
-
- @param {String} name the name of the route
- */
- transitionTo: function(name) {
- return doTransition(this, arguments);
- },
-
- intermediateTransitionTo: function(name) {
- return doTransition(this, arguments, true);
- },
-
- refresh: function(pivotHandler) {
- var state = this.activeTransition ? this.activeTransition.state : this.state;
- var handlerInfos = state.handlerInfos;
- var params = {};
- for (var i = 0, len = handlerInfos.length; i < len; ++i) {
- var handlerInfo = handlerInfos[i];
- params[handlerInfo.name] = handlerInfo.params || {};
- }
-
- log(this, "Starting a refresh transition");
- var intent = new NamedTransitionIntent({
- name: handlerInfos[handlerInfos.length - 1].name,
- pivotHandler: pivotHandler || handlerInfos[0].handler,
- contexts: [], // TODO collect contexts...?
- queryParams: this._changedQueryParams || state.queryParams || {}
- });
-
- return this.transitionByIntent(intent, false);
- },
-
- /**
- Identical to `transitionTo` except that the current URL will be replaced
- if possible.
-
- This method is intended primarily for use with `replaceState`.
-
- @param {String} name the name of the route
- */
- replaceWith: function(name) {
- return doTransition(this, arguments).method('replace');
- },
-
- /**
- Take a named route and context objects and generate a
- URL.
-
- @param {String} name the name of the route to generate
- a URL for
- @param {...Object} objects a list of objects to serialize
-
- @return {String} a URL
- */
- generate: function(handlerName) {
-
- var partitionedArgs = extractQueryParams(slice.call(arguments, 1)),
- suppliedParams = partitionedArgs[0],
- queryParams = partitionedArgs[1];
-
- // Construct a TransitionIntent with the provided params
- // and apply it to the present state of the router.
- var intent = new NamedTransitionIntent({ name: handlerName, contexts: suppliedParams });
- var state = intent.applyToState(this.state, this.recognizer, this.getHandler);
- var params = {};
-
- for (var i = 0, len = state.handlerInfos.length; i < len; ++i) {
- var handlerInfo = state.handlerInfos[i];
- var handlerParams = handlerInfo.serialize();
- merge(params, handlerParams);
- }
- params.queryParams = queryParams;
-
- return this.recognizer.generate(handlerName, params);
- },
-
- applyIntent: function(handlerName, contexts) {
- var intent = new NamedTransitionIntent({
- name: handlerName,
- contexts: contexts
- });
-
- var state = this.activeTransition && this.activeTransition.state || this.state;
- return intent.applyToState(state, this.recognizer, this.getHandler);
- },
-
- isActiveIntent: function(handlerName, contexts, queryParams) {
- var targetHandlerInfos = this.state.handlerInfos,
- found = false, names, object, handlerInfo, handlerObj, i, len;
-
- if (!targetHandlerInfos.length) { return false; }
-
- var targetHandler = targetHandlerInfos[targetHandlerInfos.length - 1].name;
- var recogHandlers = this.recognizer.handlersFor(targetHandler);
-
- var index = 0;
- for (len = recogHandlers.length; index < len; ++index) {
- handlerInfo = targetHandlerInfos[index];
- if (handlerInfo.name === handlerName) { break; }
- }
-
- if (index === recogHandlers.length) {
- // The provided route name isn't even in the route hierarchy.
- return false;
- }
-
- var state = new TransitionState();
- state.handlerInfos = targetHandlerInfos.slice(0, index + 1);
- recogHandlers = recogHandlers.slice(0, index + 1);
-
- var intent = new NamedTransitionIntent({
- name: targetHandler,
- contexts: contexts
- });
-
- var newState = intent.applyToHandlers(state, recogHandlers, this.getHandler, targetHandler, true, true);
-
- var handlersEqual = handlerInfosEqual(newState.handlerInfos, state.handlerInfos);
- if (!queryParams || !handlersEqual) {
- return handlersEqual;
- }
-
- // Get a hash of QPs that will still be active on new route
- var activeQPsOnNewHandler = {};
- merge(activeQPsOnNewHandler, queryParams);
-
- var activeQueryParams = this.state.queryParams;
- for (var key in activeQueryParams) {
- if (activeQueryParams.hasOwnProperty(key) &&
- activeQPsOnNewHandler.hasOwnProperty(key)) {
- activeQPsOnNewHandler[key] = activeQueryParams[key];
- }
- }
-
- return handlersEqual && !getChangelist(activeQPsOnNewHandler, queryParams);
- },
-
- isActive: function(handlerName) {
- var partitionedArgs = extractQueryParams(slice.call(arguments, 1));
- return this.isActiveIntent(handlerName, partitionedArgs[0], partitionedArgs[1]);
- },
-
- trigger: function(name) {
- var args = slice.call(arguments);
- trigger(this, this.currentHandlerInfos, false, args);
- },
-
- /**
- Hook point for logging transition status updates.
-
- @param {String} message The message to log.
- */
- log: null,
-
- _willChangeContextEvent: 'willChangeContext',
- _triggerWillChangeContext: function(handlerInfos, newTransition) {
- trigger(this, handlerInfos, true, [this._willChangeContextEvent, newTransition]);
- },
-
- _triggerWillLeave: function(handlerInfos, newTransition, leavingChecker) {
- trigger(this, handlerInfos, true, ['willLeave', newTransition, leavingChecker]);
- }
- };
-
- /**
- @private
-
- Fires queryParamsDidChange event
- */
- function fireQueryParamDidChange(router, newState, queryParamChangelist) {
- // If queryParams changed trigger event
- if (queryParamChangelist) {
-
- // This is a little hacky but we need some way of storing
- // changed query params given that no activeTransition
- // is guaranteed to have occurred.
- router._changedQueryParams = queryParamChangelist.all;
- trigger(router, newState.handlerInfos, true, ['queryParamsDidChange', queryParamChangelist.changed, queryParamChangelist.all, queryParamChangelist.removed]);
- router._changedQueryParams = null;
- }
- }
-
- /**
- @private
-
- Takes an Array of `HandlerInfo`s, figures out which ones are
- exiting, entering, or changing contexts, and calls the
- proper handler hooks.
-
- For example, consider the following tree of handlers. Each handler is
- followed by the URL segment it handles.
-
- ```
- |~index ("/")
- | |~posts ("/posts")
- | | |-showPost ("/:id")
- | | |-newPost ("/new")
- | | |-editPost ("/edit")
- | |~about ("/about/:id")
- ```
-
- Consider the following transitions:
-
- 1. A URL transition to `/posts/1`.
- 1. Triggers the `*model` callbacks on the
- `index`, `posts`, and `showPost` handlers
- 2. Triggers the `enter` callback on the same
- 3. Triggers the `setup` callback on the same
- 2. A direct transition to `newPost`
- 1. Triggers the `exit` callback on `showPost`
- 2. Triggers the `enter` callback on `newPost`
- 3. Triggers the `setup` callback on `newPost`
- 3. A direct transition to `about` with a specified
- context object
- 1. Triggers the `exit` callback on `newPost`
- and `posts`
- 2. Triggers the `serialize` callback on `about`
- 3. Triggers the `enter` callback on `about`
- 4. Triggers the `setup` callback on `about`
-
- @param {Router} transition
- @param {TransitionState} newState
- */
- function setupContexts(router, newState, transition) {
- var partition = partitionHandlers(router.state, newState);
-
- forEach(partition.exited, function(handlerInfo) {
- var handler = handlerInfo.handler;
- delete handler.context;
-
- callHook(handler, 'reset', true, transition);
- callHook(handler, 'exit', transition);
- });
-
- var oldState = router.oldState = router.state;
- router.state = newState;
- var currentHandlerInfos = router.currentHandlerInfos = partition.unchanged.slice();
-
- try {
- forEach(partition.reset, function(handlerInfo) {
- var handler = handlerInfo.handler;
- callHook(handler, 'reset', false, transition);
- });
-
- forEach(partition.updatedContext, function(handlerInfo) {
- return handlerEnteredOrUpdated(currentHandlerInfos, handlerInfo, false, transition);
- });
-
- forEach(partition.entered, function(handlerInfo) {
- return handlerEnteredOrUpdated(currentHandlerInfos, handlerInfo, true, transition);
- });
- } catch(e) {
- router.state = oldState;
- router.currentHandlerInfos = oldState.handlerInfos;
- throw e;
- }
-
- router.state.queryParams = finalizeQueryParamChange(router, currentHandlerInfos, newState.queryParams, transition);
- }
-
-
- /**
- @private
-
- Helper method used by setupContexts. Handles errors or redirects
- that may happen in enter/setup.
- */
- function handlerEnteredOrUpdated(currentHandlerInfos, handlerInfo, enter, transition) {
-
- var handler = handlerInfo.handler,
- context = handlerInfo.context;
-
- callHook(handler, 'enter', transition);
- if (transition && transition.isAborted) {
- throw new TransitionAborted();
- }
-
- handler.context = context;
- callHook(handler, 'contextDidChange');
-
- callHook(handler, 'setup', context, transition);
- if (transition && transition.isAborted) {
- throw new TransitionAborted();
- }
-
- currentHandlerInfos.push(handlerInfo);
-
- return true;
- }
-
-
- /**
- @private
-
- This function is called when transitioning from one URL to
- another to determine which handlers are no longer active,
- which handlers are newly active, and which handlers remain
- active but have their context changed.
-
- Take a list of old handlers and new handlers and partition
- them into four buckets:
-
- * unchanged: the handler was active in both the old and
- new URL, and its context remains the same
- * updated context: the handler was active in both the
- old and new URL, but its context changed. The handler's
- `setup` method, if any, will be called with the new
- context.
- * exited: the handler was active in the old URL, but is
- no longer active.
- * entered: the handler was not active in the old URL, but
- is now active.
-
- The PartitionedHandlers structure has four fields:
-
- * `updatedContext`: a list of `HandlerInfo` objects that
- represent handlers that remain active but have a changed
- context
- * `entered`: a list of `HandlerInfo` objects that represent
- handlers that are newly active
- * `exited`: a list of `HandlerInfo` objects that are no
- longer active.
- * `unchanged`: a list of `HanderInfo` objects that remain active.
-
- @param {Array[HandlerInfo]} oldHandlers a list of the handler
- information for the previous URL (or `[]` if this is the
- first handled transition)
- @param {Array[HandlerInfo]} newHandlers a list of the handler
- information for the new URL
-
- @return {Partition}
- */
- function partitionHandlers(oldState, newState) {
- var oldHandlers = oldState.handlerInfos;
- var newHandlers = newState.handlerInfos;
-
- var handlers = {
- updatedContext: [],
- exited: [],
- entered: [],
- unchanged: []
- };
-
- var handlerChanged, contextChanged = false, i, l;
-
- for (i=0, l=newHandlers.length; i= 0; --i) {
- var handlerInfo = handlerInfos[i];
- merge(params, handlerInfo.params);
- if (handlerInfo.handler.inaccessibleByURL) {
- urlMethod = null;
- }
- }
-
- if (urlMethod) {
- params.queryParams = transition._visibleQueryParams || state.queryParams;
- var url = router.recognizer.generate(handlerName, params);
-
- if (urlMethod === 'replace') {
- router.replaceURL(url);
- } else {
- router.updateURL(url);
- }
- }
- }
-
- /**
- @private
-
- Updates the URL (if necessary) and calls `setupContexts`
- to update the router's array of `currentHandlerInfos`.
- */
- function finalizeTransition(transition, newState) {
-
- try {
- log(transition.router, transition.sequence, "Resolved all models on destination route; finalizing transition.");
-
- var router = transition.router,
- handlerInfos = newState.handlerInfos,
- seq = transition.sequence;
-
- // Run all the necessary enter/setup/exit hooks
- setupContexts(router, newState, transition);
-
- // Check if a redirect occurred in enter/setup
- if (transition.isAborted) {
- // TODO: cleaner way? distinguish b/w targetHandlerInfos?
- router.state.handlerInfos = router.currentHandlerInfos;
- return Promise.reject(logAbort(transition));
- }
-
- updateURL(transition, newState, transition.intent.url);
-
- transition.isActive = false;
- router.activeTransition = null;
-
- trigger(router, router.currentHandlerInfos, true, ['didTransition']);
-
- if (router.didTransition) {
- router.didTransition(router.currentHandlerInfos);
- }
-
- log(router, transition.sequence, "TRANSITION COMPLETE.");
-
- // Resolve with the final handler.
- return handlerInfos[handlerInfos.length - 1].handler;
- } catch(e) {
- if (!((e instanceof TransitionAborted))) {
- //var erroneousHandler = handlerInfos.pop();
- var infos = transition.state.handlerInfos;
- transition.trigger(true, 'error', e, transition, infos[infos.length-1].handler);
- transition.abort();
- }
-
- throw e;
- }
- }
-
- /**
- @private
-
- Begins and returns a Transition based on the provided
- arguments. Accepts arguments in the form of both URL
- transitions and named transitions.
-
- @param {Router} router
- @param {Array[Object]} args arguments passed to transitionTo,
- replaceWith, or handleURL
- */
- function doTransition(router, args, isIntermediate) {
- // Normalize blank transitions to root URL transitions.
- var name = args[0] || '/';
-
- var lastArg = args[args.length-1];
- var queryParams = {};
- if (lastArg && lastArg.hasOwnProperty('queryParams')) {
- queryParams = pop.call(args).queryParams;
- }
-
- var intent;
- if (args.length === 0) {
-
- log(router, "Updating query params");
-
- // A query param update is really just a transition
- // into the route you're already on.
- var handlerInfos = router.state.handlerInfos;
- intent = new NamedTransitionIntent({
- name: handlerInfos[handlerInfos.length - 1].name,
- contexts: [],
- queryParams: queryParams
- });
-
- } else if (name.charAt(0) === '/') {
-
- log(router, "Attempting URL transition to " + name);
- intent = new URLTransitionIntent({ url: name });
-
- } else {
-
- log(router, "Attempting transition to " + name);
- intent = new NamedTransitionIntent({
- name: args[0],
- contexts: slice.call(args, 1),
- queryParams: queryParams
- });
- }
-
- return router.transitionByIntent(intent, isIntermediate);
- }
-
- function handlerInfosEqual(handlerInfos, otherHandlerInfos) {
- if (handlerInfos.length !== otherHandlerInfos.length) {
- return false;
- }
-
- for (var i = 0, len = handlerInfos.length; i < len; ++i) {
- if (handlerInfos[i] !== otherHandlerInfos[i]) {
- return false;
- }
- }
- return true;
- }
-
- function finalizeQueryParamChange(router, resolvedHandlers, newQueryParams, transition) {
- // We fire a finalizeQueryParamChange event which
- // gives the new route hierarchy a chance to tell
- // us which query params it's consuming and what
- // their final values are. If a query param is
- // no longer consumed in the final route hierarchy,
- // its serialized segment will be removed
- // from the URL.
-
- for (var k in newQueryParams) {
- if (newQueryParams.hasOwnProperty(k) &&
- newQueryParams[k] === null) {
- delete newQueryParams[k];
- }
- }
-
- var finalQueryParamsArray = [];
- trigger(router, resolvedHandlers, true, ['finalizeQueryParamChange', newQueryParams, finalQueryParamsArray, transition]);
-
- if (transition) {
- transition._visibleQueryParams = {};
- }
-
- var finalQueryParams = {};
- for (var i = 0, len = finalQueryParamsArray.length; i < len; ++i) {
- var qp = finalQueryParamsArray[i];
- finalQueryParams[qp.key] = qp.value;
- if (transition && qp.visible !== false) {
- transition._visibleQueryParams[qp.key] = qp.value;
- }
- }
- return finalQueryParams;
- }
-
- function notifyExistingHandlers(router, newState, newTransition) {
- var oldHandlers = router.state.handlerInfos,
- changing = [],
- leavingIndex = null,
- leaving, leavingChecker, i, oldHandlerLen, oldHandler, newHandler;
-
- oldHandlerLen = oldHandlers.length;
- for (i = 0; i < oldHandlerLen; i++) {
- oldHandler = oldHandlers[i];
- newHandler = newState.handlerInfos[i];
-
- if (!newHandler || oldHandler.name !== newHandler.name) {
- leavingIndex = i;
- break;
- }
-
- if (!newHandler.isResolved) {
- changing.push(oldHandler);
- }
- }
-
- if (leavingIndex !== null) {
- leaving = oldHandlers.slice(leavingIndex, oldHandlerLen);
- leavingChecker = function(name) {
- for (var h = 0, len = leaving.length; h < len; h++) {
- if (leaving[h].name === name) {
- return true;
- }
- }
- return false;
- };
-
- router._triggerWillLeave(leaving, newTransition, leavingChecker);
- }
-
- if (changing.length > 0) {
- router._triggerWillChangeContext(changing, newTransition);
- }
-
- trigger(router, oldHandlers, true, ['willTransition', newTransition]);
- }
-
- __exports__["default"] = Router;
- });
-define("router/transition-intent",
- ["./utils","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var merge = __dependency1__.merge;
-
- function TransitionIntent(props) {
- this.initialize(props);
-
- // TODO: wat
- this.data = this.data || {};
- }
-
- TransitionIntent.prototype = {
- initialize: null,
- applyToState: null
- };
-
- __exports__["default"] = TransitionIntent;
- });
-define("router/transition-intent/named-transition-intent",
- ["../transition-intent","../transition-state","../handler-info/factory","../utils","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- var TransitionIntent = __dependency1__["default"];
- var TransitionState = __dependency2__["default"];
- var handlerInfoFactory = __dependency3__["default"];
- var isParam = __dependency4__.isParam;
- var extractQueryParams = __dependency4__.extractQueryParams;
- var merge = __dependency4__.merge;
- var subclass = __dependency4__.subclass;
-
- __exports__["default"] = subclass(TransitionIntent, {
- name: null,
- pivotHandler: null,
- contexts: null,
- queryParams: null,
-
- initialize: function(props) {
- this.name = props.name;
- this.pivotHandler = props.pivotHandler;
- this.contexts = props.contexts || [];
- this.queryParams = props.queryParams;
- },
-
- applyToState: function(oldState, recognizer, getHandler, isIntermediate) {
-
- var partitionedArgs = extractQueryParams([this.name].concat(this.contexts)),
- pureArgs = partitionedArgs[0],
- queryParams = partitionedArgs[1],
- handlers = recognizer.handlersFor(pureArgs[0]);
-
- var targetRouteName = handlers[handlers.length-1].handler;
-
- return this.applyToHandlers(oldState, handlers, getHandler, targetRouteName, isIntermediate);
- },
-
- applyToHandlers: function(oldState, handlers, getHandler, targetRouteName, isIntermediate, checkingIfActive) {
-
- var i, len;
- var newState = new TransitionState();
- var objects = this.contexts.slice(0);
-
- var invalidateIndex = handlers.length;
-
- // Pivot handlers are provided for refresh transitions
- if (this.pivotHandler) {
- for (i = 0, len = handlers.length; i < len; ++i) {
- if (getHandler(handlers[i].handler) === this.pivotHandler) {
- invalidateIndex = i;
- break;
- }
- }
- }
-
- var pivotHandlerFound = !this.pivotHandler;
-
- for (i = handlers.length - 1; i >= 0; --i) {
- var result = handlers[i];
- var name = result.handler;
- var handler = getHandler(name);
-
- var oldHandlerInfo = oldState.handlerInfos[i];
- var newHandlerInfo = null;
-
- if (result.names.length > 0) {
- if (i >= invalidateIndex) {
- newHandlerInfo = this.createParamHandlerInfo(name, handler, result.names, objects, oldHandlerInfo);
- } else {
- newHandlerInfo = this.getHandlerInfoForDynamicSegment(name, handler, result.names, objects, oldHandlerInfo, targetRouteName, i);
- }
- } else {
- // This route has no dynamic segment.
- // Therefore treat as a param-based handlerInfo
- // with empty params. This will cause the `model`
- // hook to be called with empty params, which is desirable.
- newHandlerInfo = this.createParamHandlerInfo(name, handler, result.names, objects, oldHandlerInfo);
- }
-
- if (checkingIfActive) {
- // If we're performing an isActive check, we want to
- // serialize URL params with the provided context, but
- // ignore mismatches between old and new context.
- newHandlerInfo = newHandlerInfo.becomeResolved(null, newHandlerInfo.context);
- var oldContext = oldHandlerInfo && oldHandlerInfo.context;
- if (result.names.length > 0 && newHandlerInfo.context === oldContext) {
- // If contexts match in isActive test, assume params also match.
- // This allows for flexibility in not requiring that every last
- // handler provide a `serialize` method
- newHandlerInfo.params = oldHandlerInfo && oldHandlerInfo.params;
- }
- newHandlerInfo.context = oldContext;
- }
-
- var handlerToUse = oldHandlerInfo;
- if (i >= invalidateIndex || newHandlerInfo.shouldSupercede(oldHandlerInfo)) {
- invalidateIndex = Math.min(i, invalidateIndex);
- handlerToUse = newHandlerInfo;
- }
-
- if (isIntermediate && !checkingIfActive) {
- handlerToUse = handlerToUse.becomeResolved(null, handlerToUse.context);
- }
-
- newState.handlerInfos.unshift(handlerToUse);
- }
-
- if (objects.length > 0) {
- throw new Error("More context objects were passed than there are dynamic segments for the route: " + targetRouteName);
- }
-
- if (!isIntermediate) {
- this.invalidateChildren(newState.handlerInfos, invalidateIndex);
- }
-
- merge(newState.queryParams, this.queryParams || {});
-
- return newState;
- },
-
- invalidateChildren: function(handlerInfos, invalidateIndex) {
- for (var i = invalidateIndex, l = handlerInfos.length; i < l; ++i) {
- var handlerInfo = handlerInfos[i];
- handlerInfos[i] = handlerInfos[i].getUnresolved();
- }
- },
-
- getHandlerInfoForDynamicSegment: function(name, handler, names, objects, oldHandlerInfo, targetRouteName, i) {
-
- var numNames = names.length;
- var objectToUse;
- if (objects.length > 0) {
-
- // Use the objects provided for this transition.
- objectToUse = objects[objects.length - 1];
- if (isParam(objectToUse)) {
- return this.createParamHandlerInfo(name, handler, names, objects, oldHandlerInfo);
- } else {
- objects.pop();
- }
- } else if (oldHandlerInfo && oldHandlerInfo.name === name) {
- // Reuse the matching oldHandlerInfo
- return oldHandlerInfo;
- } else {
- if (this.preTransitionState) {
- var preTransitionHandlerInfo = this.preTransitionState.handlerInfos[i];
- objectToUse = preTransitionHandlerInfo && preTransitionHandlerInfo.context;
- } else {
- // Ideally we should throw this error to provide maximal
- // information to the user that not enough context objects
- // were provided, but this proves too cumbersome in Ember
- // in cases where inner template helpers are evaluated
- // before parent helpers un-render, in which cases this
- // error somewhat prematurely fires.
- //throw new Error("Not enough context objects were provided to complete a transition to " + targetRouteName + ". Specifically, the " + name + " route needs an object that can be serialized into its dynamic URL segments [" + names.join(', ') + "]");
- return oldHandlerInfo;
- }
- }
-
- return handlerInfoFactory('object', {
- name: name,
- handler: handler,
- context: objectToUse,
- names: names
- });
- },
-
- createParamHandlerInfo: function(name, handler, names, objects, oldHandlerInfo) {
- var params = {};
-
- // Soak up all the provided string/numbers
- var numNames = names.length;
- while (numNames--) {
-
- // Only use old params if the names match with the new handler
- var oldParams = (oldHandlerInfo && name === oldHandlerInfo.name && oldHandlerInfo.params) || {};
-
- var peek = objects[objects.length - 1];
- var paramName = names[numNames];
- if (isParam(peek)) {
- params[paramName] = "" + objects.pop();
- } else {
- // If we're here, this means only some of the params
- // were string/number params, so try and use a param
- // value from a previous handler.
- if (oldParams.hasOwnProperty(paramName)) {
- params[paramName] = oldParams[paramName];
- } else {
- throw new Error("You didn't provide enough string/numeric parameters to satisfy all of the dynamic segments for route " + name);
- }
- }
- }
-
- return handlerInfoFactory('param', {
- name: name,
- handler: handler,
- params: params
- });
- }
- });
- });
-define("router/transition-intent/url-transition-intent",
- ["../transition-intent","../transition-state","../handler-info/factory","../utils","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- var TransitionIntent = __dependency1__["default"];
- var TransitionState = __dependency2__["default"];
- var handlerInfoFactory = __dependency3__["default"];
- var oCreate = __dependency4__.oCreate;
- var merge = __dependency4__.merge;
- var subclass = __dependency4__.subclass;
-
- __exports__["default"] = subclass(TransitionIntent, {
- url: null,
-
- initialize: function(props) {
- this.url = props.url;
- },
-
- applyToState: function(oldState, recognizer, getHandler) {
- var newState = new TransitionState();
-
- var results = recognizer.recognize(this.url),
- queryParams = {},
- i, len;
-
- if (!results) {
- throw new UnrecognizedURLError(this.url);
- }
-
- var statesDiffer = false;
-
- for (i = 0, len = results.length; i < len; ++i) {
- var result = results[i];
- var name = result.handler;
- var handler = getHandler(name);
-
- if (handler.inaccessibleByURL) {
- throw new UnrecognizedURLError(this.url);
- }
-
- var newHandlerInfo = handlerInfoFactory('param', {
- name: name,
- handler: handler,
- params: result.params
- });
-
- var oldHandlerInfo = oldState.handlerInfos[i];
- if (statesDiffer || newHandlerInfo.shouldSupercede(oldHandlerInfo)) {
- statesDiffer = true;
- newState.handlerInfos[i] = newHandlerInfo;
- } else {
- newState.handlerInfos[i] = oldHandlerInfo;
- }
- }
-
- merge(newState.queryParams, results.queryParams);
-
- return newState;
- }
- });
-
- /**
- Promise reject reasons passed to promise rejection
- handlers for failed transitions.
- */
- function UnrecognizedURLError(message) {
- this.message = (message || "UnrecognizedURLError");
- this.name = "UnrecognizedURLError";
- }
- });
-define("router/transition-state",
- ["./handler-info","./utils","rsvp/promise","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var ResolvedHandlerInfo = __dependency1__.ResolvedHandlerInfo;
- var forEach = __dependency2__.forEach;
- var promiseLabel = __dependency2__.promiseLabel;
- var callHook = __dependency2__.callHook;
- var Promise = __dependency3__["default"];
-
- function TransitionState(other) {
- this.handlerInfos = [];
- this.queryParams = {};
- this.params = {};
- }
-
- TransitionState.prototype = {
- handlerInfos: null,
- queryParams: null,
- params: null,
-
- promiseLabel: function(label) {
- var targetName = '';
- forEach(this.handlerInfos, function(handlerInfo) {
- if (targetName !== '') {
- targetName += '.';
- }
- targetName += handlerInfo.name;
- });
- return promiseLabel("'" + targetName + "': " + label);
- },
-
- resolve: function(shouldContinue, payload) {
- var self = this;
- // First, calculate params for this state. This is useful
- // information to provide to the various route hooks.
- var params = this.params;
- forEach(this.handlerInfos, function(handlerInfo) {
- params[handlerInfo.name] = handlerInfo.params || {};
- });
-
- payload = payload || {};
- payload.resolveIndex = 0;
-
- var currentState = this;
- var wasAborted = false;
-
- // The prelude RSVP.resolve() asyncs us into the promise land.
- return Promise.resolve(null, this.promiseLabel("Start transition"))
- .then(resolveOneHandlerInfo, null, this.promiseLabel('Resolve handler'))['catch'](handleError, this.promiseLabel('Handle error'));
-
- function innerShouldContinue() {
- return Promise.resolve(shouldContinue(), currentState.promiseLabel("Check if should continue"))['catch'](function(reason) {
- // We distinguish between errors that occurred
- // during resolution (e.g. beforeModel/model/afterModel),
- // and aborts due to a rejecting promise from shouldContinue().
- wasAborted = true;
- return Promise.reject(reason);
- }, currentState.promiseLabel("Handle abort"));
- }
-
- function handleError(error) {
- // This is the only possible
- // reject value of TransitionState#resolve
- var handlerInfos = currentState.handlerInfos;
- var errorHandlerIndex = payload.resolveIndex >= handlerInfos.length ?
- handlerInfos.length - 1 : payload.resolveIndex;
- return Promise.reject({
- error: error,
- handlerWithError: currentState.handlerInfos[errorHandlerIndex].handler,
- wasAborted: wasAborted,
- state: currentState
- });
- }
-
- function proceed(resolvedHandlerInfo) {
- var wasAlreadyResolved = currentState.handlerInfos[payload.resolveIndex].isResolved;
-
- // Swap the previously unresolved handlerInfo with
- // the resolved handlerInfo
- currentState.handlerInfos[payload.resolveIndex++] = resolvedHandlerInfo;
-
- if (!wasAlreadyResolved) {
- // Call the redirect hook. The reason we call it here
- // vs. afterModel is so that redirects into child
- // routes don't re-run the model hooks for this
- // already-resolved route.
- var handler = resolvedHandlerInfo.handler;
- callHook(handler, 'redirect', resolvedHandlerInfo.context, payload);
- }
-
- // Proceed after ensuring that the redirect hook
- // didn't abort this transition by transitioning elsewhere.
- return innerShouldContinue().then(resolveOneHandlerInfo, null, currentState.promiseLabel('Resolve handler'));
- }
-
- function resolveOneHandlerInfo() {
- if (payload.resolveIndex === currentState.handlerInfos.length) {
- // This is is the only possible
- // fulfill value of TransitionState#resolve
- return {
- error: null,
- state: currentState
- };
- }
-
- var handlerInfo = currentState.handlerInfos[payload.resolveIndex];
-
- return handlerInfo.resolve(innerShouldContinue, payload)
- .then(proceed, null, currentState.promiseLabel('Proceed'));
- }
- }
- };
-
- __exports__["default"] = TransitionState;
- });
-define("router/transition",
- ["rsvp/promise","./handler-info","./utils","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var Promise = __dependency1__["default"];
- var ResolvedHandlerInfo = __dependency2__.ResolvedHandlerInfo;
- var trigger = __dependency3__.trigger;
- var slice = __dependency3__.slice;
- var log = __dependency3__.log;
- var promiseLabel = __dependency3__.promiseLabel;
-
- /**
- @private
-
- A Transition is a thennable (a promise-like object) that represents
- an attempt to transition to another route. It can be aborted, either
- explicitly via `abort` or by attempting another transition while a
- previous one is still underway. An aborted transition can also
- be `retry()`d later.
- */
- function Transition(router, intent, state, error) {
- var transition = this;
- this.state = state || router.state;
- this.intent = intent;
- this.router = router;
- this.data = this.intent && this.intent.data || {};
- this.resolvedModels = {};
- this.queryParams = {};
-
- if (error) {
- this.promise = Promise.reject(error);
- return;
- }
-
- if (state) {
- this.params = state.params;
- this.queryParams = state.queryParams;
- this.handlerInfos = state.handlerInfos;
-
- var len = state.handlerInfos.length;
- if (len) {
- this.targetName = state.handlerInfos[len-1].name;
- }
-
- for (var i = 0; i < len; ++i) {
- var handlerInfo = state.handlerInfos[i];
-
- // TODO: this all seems hacky
- if (!handlerInfo.isResolved) { break; }
- this.pivotHandler = handlerInfo.handler;
- }
-
- this.sequence = Transition.currentSequence++;
- this.promise = state.resolve(checkForAbort, this)['catch'](function(result) {
- if (result.wasAborted || transition.isAborted) {
- return Promise.reject(logAbort(transition));
- } else {
- transition.trigger('error', result.error, transition, result.handlerWithError);
- transition.abort();
- return Promise.reject(result.error);
- }
- }, promiseLabel('Handle Abort'));
- } else {
- this.promise = Promise.resolve(this.state);
- this.params = {};
- }
-
- function checkForAbort() {
- if (transition.isAborted) {
- return Promise.reject(undefined, promiseLabel("Transition aborted - reject"));
- }
- }
- }
-
- Transition.currentSequence = 0;
-
- Transition.prototype = {
- targetName: null,
- urlMethod: 'update',
- intent: null,
- params: null,
- pivotHandler: null,
- resolveIndex: 0,
- handlerInfos: null,
- resolvedModels: null,
- isActive: true,
- state: null,
- queryParamsOnly: false,
-
- isTransition: true,
-
- isExiting: function(handler) {
- var handlerInfos = this.handlerInfos;
- for (var i = 0, len = handlerInfos.length; i < len; ++i) {
- var handlerInfo = handlerInfos[i];
- if (handlerInfo.name === handler || handlerInfo.handler === handler) {
- return false;
- }
- }
- return true;
- },
-
- /**
- @public
-
- The Transition's internal promise. Calling `.then` on this property
- is that same as calling `.then` on the Transition object itself, but
- this property is exposed for when you want to pass around a
- Transition's promise, but not the Transition object itself, since
- Transition object can be externally `abort`ed, while the promise
- cannot.
- */
- promise: null,
-
- /**
- @public
-
- Custom state can be stored on a Transition's `data` object.
- This can be useful for decorating a Transition within an earlier
- hook and shared with a later hook. Properties set on `data` will
- be copied to new transitions generated by calling `retry` on this
- transition.
- */
- data: null,
-
- /**
- @public
-
- A standard promise hook that resolves if the transition
- succeeds and rejects if it fails/redirects/aborts.
-
- Forwards to the internal `promise` property which you can
- use in situations where you want to pass around a thennable,
- but not the Transition itself.
-
- @param {Function} onFulfilled
- @param {Function} onRejected
- @param {String} label optional string for labeling the promise.
- Useful for tooling.
- @return {Promise}
- */
- then: function(onFulfilled, onRejected, label) {
- return this.promise.then(onFulfilled, onRejected, label);
- },
-
- /**
- @public
-
- Forwards to the internal `promise` property which you can
- use in situations where you want to pass around a thennable,
- but not the Transition itself.
-
- @method catch
- @param {Function} onRejection
- @param {String} label optional string for labeling the promise.
- Useful for tooling.
- @return {Promise}
- */
- "catch": function(onRejection, label) {
- return this.promise["catch"](onRejection, label);
- },
-
- /**
- @public
-
- Forwards to the internal `promise` property which you can
- use in situations where you want to pass around a thennable,
- but not the Transition itself.
-
- @method finally
- @param {Function} callback
- @param {String} label optional string for labeling the promise.
- Useful for tooling.
- @return {Promise}
- */
- "finally": function(callback, label) {
- return this.promise["finally"](callback, label);
- },
-
- /**
- @public
-
- Aborts the Transition. Note you can also implicitly abort a transition
- by initiating another transition while a previous one is underway.
- */
- abort: function() {
- if (this.isAborted) { return this; }
- log(this.router, this.sequence, this.targetName + ": transition was aborted");
- this.intent.preTransitionState = this.router.state;
- this.isAborted = true;
- this.isActive = false;
- this.router.activeTransition = null;
- return this;
- },
-
- /**
- @public
-
- Retries a previously-aborted transition (making sure to abort the
- transition if it's still active). Returns a new transition that
- represents the new attempt to transition.
- */
- retry: function() {
- // TODO: add tests for merged state retry()s
- this.abort();
- return this.router.transitionByIntent(this.intent, false);
- },
-
- /**
- @public
-
- Sets the URL-changing method to be employed at the end of a
- successful transition. By default, a new Transition will just
- use `updateURL`, but passing 'replace' to this method will
- cause the URL to update using 'replaceWith' instead. Omitting
- a parameter will disable the URL change, allowing for transitions
- that don't update the URL at completion (this is also used for
- handleURL, since the URL has already changed before the
- transition took place).
-
- @param {String} method the type of URL-changing method to use
- at the end of a transition. Accepted values are 'replace',
- falsy values, or any other non-falsy value (which is
- interpreted as an updateURL transition).
-
- @return {Transition} this transition
- */
- method: function(method) {
- this.urlMethod = method;
- return this;
- },
-
- /**
- @public
-
- Fires an event on the current list of resolved/resolving
- handlers within this transition. Useful for firing events
- on route hierarchies that haven't fully been entered yet.
-
- Note: This method is also aliased as `send`
-
- @param {Boolean} [ignoreFailure=false] a boolean specifying whether unhandled events throw an error
- @param {String} name the name of the event to fire
- */
- trigger: function (ignoreFailure) {
- var args = slice.call(arguments);
- if (typeof ignoreFailure === 'boolean') {
- args.shift();
- } else {
- // Throw errors on unhandled trigger events by default
- ignoreFailure = false;
- }
- trigger(this.router, this.state.handlerInfos.slice(0, this.resolveIndex + 1), ignoreFailure, args);
- },
-
- /**
- @public
-
- Transitions are aborted and their promises rejected
- when redirects occur; this method returns a promise
- that will follow any redirects that occur and fulfill
- with the value fulfilled by any redirecting transitions
- that occur.
-
- @return {Promise} a promise that fulfills with the same
- value that the final redirecting transition fulfills with
- */
- followRedirects: function() {
- var router = this.router;
- return this.promise['catch'](function(reason) {
- if (router.activeTransition) {
- return router.activeTransition.followRedirects();
- }
- return Promise.reject(reason);
- });
- },
-
- toString: function() {
- return "Transition (sequence " + this.sequence + ")";
- },
-
- /**
- @private
- */
- log: function(message) {
- log(this.router, this.sequence, message);
- }
- };
-
- // Alias 'trigger' as 'send'
- Transition.prototype.send = Transition.prototype.trigger;
-
- /**
- @private
-
- Logs and returns a TransitionAborted error.
- */
- function logAbort(transition) {
- log(transition.router, transition.sequence, "detected abort.");
- return new TransitionAborted();
- }
-
- function TransitionAborted(message) {
- this.message = (message || "TransitionAborted");
- this.name = "TransitionAborted";
- }
-
- __exports__.Transition = Transition;
- __exports__.logAbort = logAbort;
- __exports__.TransitionAborted = TransitionAborted;
- });
-define("router/utils",
- ["exports"],
- function(__exports__) {
- "use strict";
- var slice = Array.prototype.slice;
-
- var _isArray;
- if (!Array.isArray) {
- _isArray = function (x) {
- return Object.prototype.toString.call(x) === "[object Array]";
- };
- } else {
- _isArray = Array.isArray;
- }
-
- var isArray = _isArray;
- __exports__.isArray = isArray;
- function merge(hash, other) {
- for (var prop in other) {
- if (other.hasOwnProperty(prop)) { hash[prop] = other[prop]; }
- }
- }
-
- var oCreate = Object.create || function(proto) {
- function F() {}
- F.prototype = proto;
- return new F();
- };
- __exports__.oCreate = oCreate;
- /**
- @private
-
- Extracts query params from the end of an array
- **/
- function extractQueryParams(array) {
- var len = (array && array.length), head, queryParams;
-
- if(len && len > 0 && array[len - 1] && array[len - 1].hasOwnProperty('queryParams')) {
- queryParams = array[len - 1].queryParams;
- head = slice.call(array, 0, len - 1);
- return [head, queryParams];
- } else {
- return [array, null];
- }
- }
-
- __exports__.extractQueryParams = extractQueryParams;/**
- @private
-
- Coerces query param properties and array elements into strings.
- **/
- function coerceQueryParamsToString(queryParams) {
- for (var key in queryParams) {
- if (typeof queryParams[key] === 'number') {
- queryParams[key] = '' + queryParams[key];
- } else if (isArray(queryParams[key])) {
- for (var i = 0, l = queryParams[key].length; i < l; i++) {
- queryParams[key][i] = '' + queryParams[key][i];
- }
- }
- }
- }
- /**
- @private
- */
- function log(router, sequence, msg) {
- if (!router.log) { return; }
-
- if (arguments.length === 3) {
- router.log("Transition #" + sequence + ": " + msg);
- } else {
- msg = sequence;
- router.log(msg);
- }
- }
-
- __exports__.log = log;function bind(context, fn) {
- var boundArgs = arguments;
- return function(value) {
- var args = slice.call(boundArgs, 2);
- args.push(value);
- return fn.apply(context, args);
- };
- }
-
- __exports__.bind = bind;function isParam(object) {
- return (typeof object === "string" || object instanceof String || typeof object === "number" || object instanceof Number);
- }
-
-
- function forEach(array, callback) {
- for (var i=0, l=array.length; i=0; i--) {
- var handlerInfo = handlerInfos[i],
- handler = handlerInfo.handler;
-
- if (handler.events && handler.events[name]) {
- if (handler.events[name].apply(handler, args) === true) {
- eventWasHandled = true;
- } else {
- return;
- }
- }
- }
-
- if (!eventWasHandled && !ignoreFailure) {
- throw new Error("Nothing handled the event '" + name + "'.");
- }
- }
-
- __exports__.trigger = trigger;function getChangelist(oldObject, newObject) {
- var key;
- var results = {
- all: {},
- changed: {},
- removed: {}
- };
-
- merge(results.all, newObject);
-
- var didChange = false;
- coerceQueryParamsToString(oldObject);
- coerceQueryParamsToString(newObject);
-
- // Calculate removals
- for (key in oldObject) {
- if (oldObject.hasOwnProperty(key)) {
- if (!newObject.hasOwnProperty(key)) {
- didChange = true;
- results.removed[key] = oldObject[key];
- }
- }
- }
-
- // Calculate changes
- for (key in newObject) {
- if (newObject.hasOwnProperty(key)) {
- if (isArray(oldObject[key]) && isArray(newObject[key])) {
- if (oldObject[key].length !== newObject[key].length) {
- results.changed[key] = newObject[key];
- didChange = true;
- } else {
- for (var i = 0, l = oldObject[key].length; i < l; i++) {
- if (oldObject[key][i] !== newObject[key][i]) {
- results.changed[key] = newObject[key];
- didChange = true;
- }
- }
- }
- }
- else {
- if (oldObject[key] !== newObject[key]) {
- results.changed[key] = newObject[key];
- didChange = true;
- }
- }
- }
- }
-
- return didChange && results;
- }
-
- __exports__.getChangelist = getChangelist;function promiseLabel(label) {
- return 'Router: ' + label;
- }
-
- __exports__.promiseLabel = promiseLabel;function subclass(parentConstructor, proto) {
- function C(props) {
- parentConstructor.call(this, props || {});
- }
- C.prototype = oCreate(parentConstructor.prototype);
- merge(C.prototype, proto);
- return C;
- }
-
- __exports__.subclass = subclass;function resolveHook(obj, hookName) {
- if (!obj) { return; }
- var underscored = "_" + hookName;
- return obj[underscored] && underscored ||
- obj[hookName] && hookName;
- }
-
- function callHook(obj, hookName) {
- var args = slice.call(arguments, 2);
- return applyHook(obj, hookName, args);
- }
-
- function applyHook(obj, _hookName, args) {
- var hookName = resolveHook(obj, _hookName);
- if (hookName) {
- return obj[hookName].apply(obj, args);
- }
- }
-
- __exports__.merge = merge;
- __exports__.slice = slice;
- __exports__.isParam = isParam;
- __exports__.coerceQueryParamsToString = coerceQueryParamsToString;
- __exports__.callHook = callHook;
- __exports__.resolveHook = resolveHook;
- __exports__.applyHook = applyHook;
- });
-define("router",
- ["./router/router","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var Router = __dependency1__["default"];
-
- __exports__["default"] = Router;
- });
-
-define("rsvp",
- ["./rsvp/promise","./rsvp/events","./rsvp/node","./rsvp/all","./rsvp/all-settled","./rsvp/race","./rsvp/hash","./rsvp/hash-settled","./rsvp/rethrow","./rsvp/defer","./rsvp/config","./rsvp/map","./rsvp/resolve","./rsvp/reject","./rsvp/filter","./rsvp/asap","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __dependency15__, __dependency16__, __exports__) {
- "use strict";
- var Promise = __dependency1__["default"];
- var EventTarget = __dependency2__["default"];
- var denodeify = __dependency3__["default"];
- var all = __dependency4__["default"];
- var allSettled = __dependency5__["default"];
- var race = __dependency6__["default"];
- var hash = __dependency7__["default"];
- var hashSettled = __dependency8__["default"];
- var rethrow = __dependency9__["default"];
- var defer = __dependency10__["default"];
- var config = __dependency11__.config;
- var configure = __dependency11__.configure;
- var map = __dependency12__["default"];
- var resolve = __dependency13__["default"];
- var reject = __dependency14__["default"];
- var filter = __dependency15__["default"];
- var asap = __dependency16__["default"];
-
- config.async = asap; // default async is asap;
- var cast = resolve;
- function async(callback, arg) {
- config.async(callback, arg);
- }
-
- function on() {
- config.on.apply(config, arguments);
- }
-
- function off() {
- config.off.apply(config, arguments);
- }
-
- // Set up instrumentation through `window.__PROMISE_INTRUMENTATION__`
- if (typeof window !== 'undefined' && typeof window['__PROMISE_INSTRUMENTATION__'] === 'object') {
- var callbacks = window['__PROMISE_INSTRUMENTATION__'];
- configure('instrument', true);
- for (var eventName in callbacks) {
- if (callbacks.hasOwnProperty(eventName)) {
- on(eventName, callbacks[eventName]);
- }
- }
- }
-
- __exports__.cast = cast;
- __exports__.Promise = Promise;
- __exports__.EventTarget = EventTarget;
- __exports__.all = all;
- __exports__.allSettled = allSettled;
- __exports__.race = race;
- __exports__.hash = hash;
- __exports__.hashSettled = hashSettled;
- __exports__.rethrow = rethrow;
- __exports__.defer = defer;
- __exports__.denodeify = denodeify;
- __exports__.configure = configure;
- __exports__.on = on;
- __exports__.off = off;
- __exports__.resolve = resolve;
- __exports__.reject = reject;
- __exports__.async = async;
- __exports__.map = map;
- __exports__.filter = filter;
- });
-define("rsvp.umd",
- ["./rsvp"],
- function(__dependency1__) {
- "use strict";
- var Promise = __dependency1__.Promise;
- var allSettled = __dependency1__.allSettled;
- var hash = __dependency1__.hash;
- var hashSettled = __dependency1__.hashSettled;
- var denodeify = __dependency1__.denodeify;
- var on = __dependency1__.on;
- var off = __dependency1__.off;
- var map = __dependency1__.map;
- var filter = __dependency1__.filter;
- var resolve = __dependency1__.resolve;
- var reject = __dependency1__.reject;
- var rethrow = __dependency1__.rethrow;
- var all = __dependency1__.all;
- var defer = __dependency1__.defer;
- var EventTarget = __dependency1__.EventTarget;
- var configure = __dependency1__.configure;
- var race = __dependency1__.race;
- var async = __dependency1__.async;
-
- var RSVP = {
- 'race': race,
- 'Promise': Promise,
- 'allSettled': allSettled,
- 'hash': hash,
- 'hashSettled': hashSettled,
- 'denodeify': denodeify,
- 'on': on,
- 'off': off,
- 'map': map,
- 'filter': filter,
- 'resolve': resolve,
- 'reject': reject,
- 'all': all,
- 'rethrow': rethrow,
- 'defer': defer,
- 'EventTarget': EventTarget,
- 'configure': configure,
- 'async': async
- };
-
- /* global define:true module:true window: true */
- if (typeof define === 'function' && define.amd) {
- define(function() { return RSVP; });
- } else if (typeof module !== 'undefined' && module.exports) {
- module.exports = RSVP;
- } else if (typeof this !== 'undefined') {
- this['RSVP'] = RSVP;
- }
- });
-define("rsvp/-internal",
- ["./utils","./instrument","./config","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var objectOrFunction = __dependency1__.objectOrFunction;
- var isFunction = __dependency1__.isFunction;
-
- var instrument = __dependency2__["default"];
-
- var config = __dependency3__.config;
-
- function noop() {}
-
- var PENDING = void 0;
- var FULFILLED = 1;
- var REJECTED = 2;
-
- var GET_THEN_ERROR = new ErrorObject();
-
- function getThen(promise) {
- try {
- return promise.then;
- } catch(error) {
- GET_THEN_ERROR.error = error;
- return GET_THEN_ERROR;
- }
- }
-
- function tryThen(then, value, fulfillmentHandler, rejectionHandler) {
- try {
- then.call(value, fulfillmentHandler, rejectionHandler);
- } catch(e) {
- return e;
- }
- }
-
- function handleForeignThenable(promise, thenable, then) {
- config.async(function(promise) {
- var sealed = false;
- var error = tryThen(then, thenable, function(value) {
- if (sealed) { return; }
- sealed = true;
- if (thenable !== value) {
- resolve(promise, value);
- } else {
- fulfill(promise, value);
- }
- }, function(reason) {
- if (sealed) { return; }
- sealed = true;
-
- reject(promise, reason);
- }, 'Settle: ' + (promise._label || ' unknown promise'));
-
- if (!sealed && error) {
- sealed = true;
- reject(promise, error);
- }
- }, promise);
- }
-
- function handleOwnThenable(promise, thenable) {
- if (thenable._state === FULFILLED) {
- fulfill(promise, thenable._result);
- } else if (promise._state === REJECTED) {
- reject(promise, thenable._result);
- } else {
- subscribe(thenable, undefined, function(value) {
- if (thenable !== value) {
- resolve(promise, value);
- } else {
- fulfill(promise, value);
- }
- }, function(reason) {
- reject(promise, reason);
- });
- }
- }
-
- function handleMaybeThenable(promise, maybeThenable) {
- if (maybeThenable.constructor === promise.constructor) {
- handleOwnThenable(promise, maybeThenable);
- } else {
- var then = getThen(maybeThenable);
-
- if (then === GET_THEN_ERROR) {
- reject(promise, GET_THEN_ERROR.error);
- } else if (then === undefined) {
- fulfill(promise, maybeThenable);
- } else if (isFunction(then)) {
- handleForeignThenable(promise, maybeThenable, then);
- } else {
- fulfill(promise, maybeThenable);
- }
- }
- }
-
- function resolve(promise, value) {
- if (promise === value) {
- fulfill(promise, value);
- } else if (objectOrFunction(value)) {
- handleMaybeThenable(promise, value);
- } else {
- fulfill(promise, value);
- }
- }
-
- function publishRejection(promise) {
- if (promise._onerror) {
- promise._onerror(promise._result);
- }
-
- publish(promise);
- }
-
- function fulfill(promise, value) {
- if (promise._state !== PENDING) { return; }
-
- promise._result = value;
- promise._state = FULFILLED;
-
- if (promise._subscribers.length === 0) {
- if (config.instrument) {
- instrument('fulfilled', promise);
- }
- } else {
- config.async(publish, promise);
- }
- }
-
- function reject(promise, reason) {
- if (promise._state !== PENDING) { return; }
- promise._state = REJECTED;
- promise._result = reason;
-
- config.async(publishRejection, promise);
- }
-
- function subscribe(parent, child, onFulfillment, onRejection) {
- var subscribers = parent._subscribers;
- var length = subscribers.length;
-
- parent._onerror = null;
-
- subscribers[length] = child;
- subscribers[length + FULFILLED] = onFulfillment;
- subscribers[length + REJECTED] = onRejection;
-
- if (length === 0 && parent._state) {
- config.async(publish, parent);
- }
- }
-
- function publish(promise) {
- var subscribers = promise._subscribers;
- var settled = promise._state;
-
- if (config.instrument) {
- instrument(settled === FULFILLED ? 'fulfilled' : 'rejected', promise);
- }
-
- if (subscribers.length === 0) { return; }
-
- var child, callback, detail = promise._result;
-
- for (var i = 0; i < subscribers.length; i += 3) {
- child = subscribers[i];
- callback = subscribers[i + settled];
-
- if (child) {
- invokeCallback(settled, child, callback, detail);
- } else {
- callback(detail);
- }
- }
-
- promise._subscribers.length = 0;
- }
-
- function ErrorObject() {
- this.error = null;
- }
-
- var TRY_CATCH_ERROR = new ErrorObject();
-
- function tryCatch(callback, detail) {
- try {
- return callback(detail);
- } catch(e) {
- TRY_CATCH_ERROR.error = e;
- return TRY_CATCH_ERROR;
- }
- }
-
- function invokeCallback(settled, promise, callback, detail) {
- var hasCallback = isFunction(callback),
- value, error, succeeded, failed;
-
- if (hasCallback) {
- value = tryCatch(callback, detail);
-
- if (value === TRY_CATCH_ERROR) {
- failed = true;
- error = value.error;
- value = null;
- } else {
- succeeded = true;
- }
-
- if (promise === value) {
- reject(promise, new TypeError('A promises callback cannot return that same promise.'));
- return;
- }
-
- } else {
- value = detail;
- succeeded = true;
- }
-
- if (promise._state !== PENDING) {
- // noop
- } else if (hasCallback && succeeded) {
- resolve(promise, value);
- } else if (failed) {
- reject(promise, error);
- } else if (settled === FULFILLED) {
- fulfill(promise, value);
- } else if (settled === REJECTED) {
- reject(promise, value);
- }
- }
-
- function initializePromise(promise, resolver) {
- try {
- resolver(function resolvePromise(value){
- resolve(promise, value);
- }, function rejectPromise(reason) {
- reject(promise, reason);
- });
- } catch(e) {
- reject(promise, e);
- }
- }
-
- __exports__.noop = noop;
- __exports__.resolve = resolve;
- __exports__.reject = reject;
- __exports__.fulfill = fulfill;
- __exports__.subscribe = subscribe;
- __exports__.publish = publish;
- __exports__.publishRejection = publishRejection;
- __exports__.initializePromise = initializePromise;
- __exports__.invokeCallback = invokeCallback;
- __exports__.FULFILLED = FULFILLED;
- __exports__.REJECTED = REJECTED;
- __exports__.PENDING = PENDING;
- });
-define("rsvp/all-settled",
- ["./enumerator","./promise","./utils","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var Enumerator = __dependency1__["default"];
- var makeSettledResult = __dependency1__.makeSettledResult;
- var Promise = __dependency2__["default"];
- var o_create = __dependency3__.o_create;
-
- function AllSettled(Constructor, entries, label) {
- this._superConstructor(Constructor, entries, false /* don't abort on reject */, label);
- }
-
- AllSettled.prototype = o_create(Enumerator.prototype);
- AllSettled.prototype._superConstructor = Enumerator;
- AllSettled.prototype._makeResult = makeSettledResult;
- AllSettled.prototype._validationError = function() {
- return new Error('allSettled must be called with an array');
- };
-
- /**
- `RSVP.allSettled` is similar to `RSVP.all`, but instead of implementing
- a fail-fast method, it waits until all the promises have returned and
- shows you all the results. This is useful if you want to handle multiple
- promises' failure states together as a set.
-
- Returns a promise that is fulfilled when all the given promises have been
- settled. The return promise is fulfilled with an array of the states of
- the promises passed into the `promises` array argument.
-
- Each state object will either indicate fulfillment or rejection, and
- provide the corresponding value or reason. The states will take one of
- the following formats:
-
- ```javascript
- { state: 'fulfilled', value: value }
- or
- { state: 'rejected', reason: reason }
- ```
-
- Example:
-
- ```javascript
- var promise1 = RSVP.Promise.resolve(1);
- var promise2 = RSVP.Promise.reject(new Error('2'));
- var promise3 = RSVP.Promise.reject(new Error('3'));
- var promises = [ promise1, promise2, promise3 ];
-
- RSVP.allSettled(promises).then(function(array){
- // array == [
- // { state: 'fulfilled', value: 1 },
- // { state: 'rejected', reason: Error },
- // { state: 'rejected', reason: Error }
- // ]
- // Note that for the second item, reason.message will be '2', and for the
- // third item, reason.message will be '3'.
- }, function(error) {
- // Not run. (This block would only be called if allSettled had failed,
- // for instance if passed an incorrect argument type.)
- });
- ```
-
- @method allSettled
- @static
- @for RSVP
- @param {Array} promises
- @param {String} label - optional string that describes the promise.
- Useful for tooling.
- @return {Promise} promise that is fulfilled with an array of the settled
- states of the constituent promises.
- */
-
- __exports__["default"] = function allSettled(entries, label) {
- return new AllSettled(Promise, entries, label).promise;
- }
- });
-define("rsvp/all",
- ["./promise","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var Promise = __dependency1__["default"];
-
- /**
- This is a convenient alias for `RSVP.Promise.all`.
-
- @method all
- @static
- @for RSVP
- @param {Array} array Array of promises.
- @param {String} label An optional label. This is useful
- for tooling.
- */
- __exports__["default"] = function all(array, label) {
- return Promise.all(array, label);
- }
- });
-define("rsvp/asap",
- ["exports"],
- function(__exports__) {
- "use strict";
- var len = 0;
-
- __exports__["default"] = function asap(callback, arg) {
- queue[len] = callback;
- queue[len + 1] = arg;
- len += 2;
- if (len === 2) {
- // If len is 1, that means that we need to schedule an async flush.
- // If additional callbacks are queued before the queue is flushed, they
- // will be processed by this flush that we are scheduling.
- scheduleFlush();
- }
- }
-
- var browserGlobal = (typeof window !== 'undefined') ? window : {};
- var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
-
- // test for web worker but not in IE10
- var isWorker = typeof Uint8ClampedArray !== 'undefined' &&
- typeof importScripts !== 'undefined' &&
- typeof MessageChannel !== 'undefined';
-
- // node
- function useNextTick() {
- return function() {
- process.nextTick(flush);
- };
- }
-
- function useMutationObserver() {
- var iterations = 0;
- var observer = new BrowserMutationObserver(flush);
- var node = document.createTextNode('');
- observer.observe(node, { characterData: true });
-
- return function() {
- node.data = (iterations = ++iterations % 2);
- };
- }
-
- // web worker
- function useMessageChannel() {
- var channel = new MessageChannel();
- channel.port1.onmessage = flush;
- return function () {
- channel.port2.postMessage(0);
- };
- }
-
- function useSetTimeout() {
- return function() {
- setTimeout(flush, 1);
- };
- }
-
- var queue = new Array(1000);
- function flush() {
- for (var i = 0; i < len; i+=2) {
- var callback = queue[i];
- var arg = queue[i+1];
-
- callback(arg);
-
- queue[i] = undefined;
- queue[i+1] = undefined;
- }
-
- len = 0;
- }
-
- var scheduleFlush;
-
- // Decide what async method to use to triggering processing of queued callbacks:
- if (typeof process !== 'undefined' && {}.toString.call(process) === '[object process]') {
- scheduleFlush = useNextTick();
- } else if (BrowserMutationObserver) {
- scheduleFlush = useMutationObserver();
- } else if (isWorker) {
- scheduleFlush = useMessageChannel();
- } else {
- scheduleFlush = useSetTimeout();
- }
- });
-define("rsvp/config",
- ["./events","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var EventTarget = __dependency1__["default"];
-
- var config = {
- instrument: false
- };
-
- EventTarget.mixin(config);
-
- function configure(name, value) {
- if (name === 'onerror') {
- // handle for legacy users that expect the actual
- // error to be passed to their function added via
- // `RSVP.configure('onerror', someFunctionHere);`
- config.on('error', value);
- return;
- }
-
- if (arguments.length === 2) {
- config[name] = value;
- } else {
- return config[name];
- }
- }
-
- __exports__.config = config;
- __exports__.configure = configure;
- });
-define("rsvp/defer",
- ["./promise","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var Promise = __dependency1__["default"];
-
- /**
- `RSVP.defer` returns an object similar to jQuery's `$.Deferred`.
- `RSVP.defer` should be used when porting over code reliant on `$.Deferred`'s
- interface. New code should use the `RSVP.Promise` constructor instead.
-
- The object returned from `RSVP.defer` is a plain object with three properties:
-
- * promise - an `RSVP.Promise`.
- * reject - a function that causes the `promise` property on this object to
- become rejected
- * resolve - a function that causes the `promise` property on this object to
- become fulfilled.
-
- Example:
-
- ```javascript
- var deferred = RSVP.defer();
-
- deferred.resolve("Success!");
-
- defered.promise.then(function(value){
- // value here is "Success!"
- });
- ```
-
- @method defer
- @static
- @for RSVP
- @param {String} label optional string for labeling the promise.
- Useful for tooling.
- @return {Object}
- */
-
- __exports__["default"] = function defer(label) {
- var deferred = { };
-
- deferred.promise = new Promise(function(resolve, reject) {
- deferred.resolve = resolve;
- deferred.reject = reject;
- }, label);
-
- return deferred;
- }
- });
-define("rsvp/enumerator",
- ["./utils","./-internal","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var isArray = __dependency1__.isArray;
- var isMaybeThenable = __dependency1__.isMaybeThenable;
-
- var noop = __dependency2__.noop;
- var reject = __dependency2__.reject;
- var fulfill = __dependency2__.fulfill;
- var subscribe = __dependency2__.subscribe;
- var FULFILLED = __dependency2__.FULFILLED;
- var REJECTED = __dependency2__.REJECTED;
- var PENDING = __dependency2__.PENDING;
-
- function makeSettledResult(state, position, value) {
- if (state === FULFILLED) {
- return {
- state: 'fulfilled',
- value: value
- };
- } else {
- return {
- state: 'rejected',
- reason: value
- };
- }
- }
-
- __exports__.makeSettledResult = makeSettledResult;function Enumerator(Constructor, input, abortOnReject, label) {
- this._instanceConstructor = Constructor;
- this.promise = new Constructor(noop, label);
- this._abortOnReject = abortOnReject;
-
- if (this._validateInput(input)) {
- this._input = input;
- this.length = input.length;
- this._remaining = input.length;
-
- this._init();
-
- if (this.length === 0) {
- fulfill(this.promise, this._result);
- } else {
- this.length = this.length || 0;
- this._enumerate();
- if (this._remaining === 0) {
- fulfill(this.promise, this._result);
- }
- }
- } else {
- reject(this.promise, this._validationError());
- }
- }
-
- Enumerator.prototype._validateInput = function(input) {
- return isArray(input);
- };
-
- Enumerator.prototype._validationError = function() {
- return new Error('Array Methods must be provided an Array');
- };
-
- Enumerator.prototype._init = function() {
- this._result = new Array(this.length);
- };
-
- __exports__["default"] = Enumerator;
-
- Enumerator.prototype._enumerate = function() {
- var length = this.length;
- var promise = this.promise;
- var input = this._input;
-
- for (var i = 0; promise._state === PENDING && i < length; i++) {
- this._eachEntry(input[i], i);
- }
- };
-
- Enumerator.prototype._eachEntry = function(entry, i) {
- var c = this._instanceConstructor;
- if (isMaybeThenable(entry)) {
- if (entry.constructor === c && entry._state !== PENDING) {
- entry._onerror = null;
- this._settledAt(entry._state, i, entry._result);
- } else {
- this._willSettleAt(c.resolve(entry), i);
- }
- } else {
- this._remaining--;
- this._result[i] = this._makeResult(FULFILLED, i, entry);
- }
- };
-
- Enumerator.prototype._settledAt = function(state, i, value) {
- var promise = this.promise;
-
- if (promise._state === PENDING) {
- this._remaining--;
-
- if (this._abortOnReject && state === REJECTED) {
- reject(promise, value);
- } else {
- this._result[i] = this._makeResult(state, i, value);
- }
- }
-
- if (this._remaining === 0) {
- fulfill(promise, this._result);
- }
- };
-
- Enumerator.prototype._makeResult = function(state, i, value) {
- return value;
- };
-
- Enumerator.prototype._willSettleAt = function(promise, i) {
- var enumerator = this;
-
- subscribe(promise, undefined, function(value) {
- enumerator._settledAt(FULFILLED, i, value);
- }, function(reason) {
- enumerator._settledAt(REJECTED, i, reason);
- });
- };
- });
-define("rsvp/events",
- ["exports"],
- function(__exports__) {
- "use strict";
- function indexOf(callbacks, callback) {
- for (var i=0, l=callbacks.length; i 1;
- };
-
- RSVP.filter(promises, filterFn).then(function(result){
- // result is [ 2, 3 ]
- });
- ```
-
- If any of the `promises` given to `RSVP.filter` are rejected, the first promise
- that is rejected will be given as an argument to the returned promise's
- rejection handler. For example:
-
- ```javascript
- var promise1 = RSVP.resolve(1);
- var promise2 = RSVP.reject(new Error('2'));
- var promise3 = RSVP.reject(new Error('3'));
- var promises = [ promise1, promise2, promise3 ];
-
- var filterFn = function(item){
- return item > 1;
- };
-
- RSVP.filter(promises, filterFn).then(function(array){
- // Code here never runs because there are rejected promises!
- }, function(reason) {
- // reason.message === '2'
- });
- ```
-
- `RSVP.filter` will also wait for any promises returned from `filterFn`.
- For instance, you may want to fetch a list of users then return a subset
- of those users based on some asynchronous operation:
-
- ```javascript
-
- var alice = { name: 'alice' };
- var bob = { name: 'bob' };
- var users = [ alice, bob ];
-
- var promises = users.map(function(user){
- return RSVP.resolve(user);
- });
-
- var filterFn = function(user){
- // Here, Alice has permissions to create a blog post, but Bob does not.
- return getPrivilegesForUser(user).then(function(privs){
- return privs.can_create_blog_post === true;
- });
- };
- RSVP.filter(promises, filterFn).then(function(users){
- // true, because the server told us only Alice can create a blog post.
- users.length === 1;
- // false, because Alice is the only user present in `users`
- users[0] === bob;
- });
- ```
-
- @method filter
- @static
- @for RSVP
- @param {Array} promises
- @param {Function} filterFn - function to be called on each resolved value to
- filter the final results.
- @param {String} label optional string describing the promise. Useful for
- tooling.
- @return {Promise}
- */
- __exports__["default"] = function filter(promises, filterFn, label) {
- return Promise.all(promises, label).then(function(values) {
- if (!isFunction(filterFn)) {
- throw new TypeError("You must pass a function as filter's second argument.");
- }
-
- var length = values.length;
- var filtered = new Array(length);
-
- for (var i = 0; i < length; i++) {
- filtered[i] = filterFn(values[i]);
- }
-
- return Promise.all(filtered, label).then(function(filtered) {
- var results = new Array(length);
- var newLength = 0;
-
- for (var i = 0; i < length; i++) {
- if (filtered[i]) {
- results[newLength] = values[i];
- newLength++;
- }
- }
-
- results.length = newLength;
-
- return results;
- });
- });
- }
- });
-define("rsvp/hash-settled",
- ["./promise","./enumerator","./promise-hash","./utils","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
- "use strict";
- var Promise = __dependency1__["default"];
- var makeSettledResult = __dependency2__.makeSettledResult;
- var PromiseHash = __dependency3__["default"];
- var Enumerator = __dependency2__["default"];
- var o_create = __dependency4__.o_create;
-
- function HashSettled(Constructor, object, label) {
- this._superConstructor(Constructor, object, false, label);
- }
-
- HashSettled.prototype = o_create(PromiseHash.prototype);
- HashSettled.prototype._superConstructor = Enumerator;
- HashSettled.prototype._makeResult = makeSettledResult;
-
- HashSettled.prototype._validationError = function() {
- return new Error('hashSettled must be called with an object');
- };
-
- /**
- `RSVP.hashSettled` is similar to `RSVP.allSettled`, but takes an object
- instead of an array for its `promises` argument.
-
- Unlike `RSVP.all` or `RSVP.hash`, which implement a fail-fast method,
- but like `RSVP.allSettled`, `hashSettled` waits until all the
- constituent promises have returned and then shows you all the results
- with their states and values/reasons. This is useful if you want to
- handle multiple promises' failure states together as a set.
-
- Returns a promise that is fulfilled when all the given promises have been
- settled, or rejected if the passed parameters are invalid.
-
- The returned promise is fulfilled with a hash that has the same key names as
- the `promises` object argument. If any of the values in the object are not
- promises, they will be copied over to the fulfilled object and marked with state
- 'fulfilled'.
-
- Example:
-
- ```javascript
- var promises = {
- myPromise: RSVP.Promise.resolve(1),
- yourPromise: RSVP.Promise.resolve(2),
- theirPromise: RSVP.Promise.resolve(3),
- notAPromise: 4
- };
-
- RSVP.hashSettled(promises).then(function(hash){
- // hash here is an object that looks like:
- // {
- // myPromise: { state: 'fulfilled', value: 1 },
- // yourPromise: { state: 'fulfilled', value: 2 },
- // theirPromise: { state: 'fulfilled', value: 3 },
- // notAPromise: { state: 'fulfilled', value: 4 }
- // }
- });
- ```
-
- If any of the `promises` given to `RSVP.hash` are rejected, the state will
- be set to 'rejected' and the reason for rejection provided.
-
- Example:
-
- ```javascript
- var promises = {
- myPromise: RSVP.Promise.resolve(1),
- rejectedPromise: RSVP.Promise.reject(new Error('rejection')),
- anotherRejectedPromise: RSVP.Promise.reject(new Error('more rejection')),
- };
-
- RSVP.hashSettled(promises).then(function(hash){
- // hash here is an object that looks like:
- // {
- // myPromise: { state: 'fulfilled', value: 1 },
- // rejectedPromise: { state: 'rejected', reason: Error },
- // anotherRejectedPromise: { state: 'rejected', reason: Error },
- // }
- // Note that for rejectedPromise, reason.message == 'rejection',
- // and for anotherRejectedPromise, reason.message == 'more rejection'.
- });
- ```
-
- An important note: `RSVP.hashSettled` is intended for plain JavaScript objects that
- are just a set of keys and values. `RSVP.hashSettled` will NOT preserve prototype
- chains.
-
- Example:
-
- ```javascript
- function MyConstructor(){
- this.example = RSVP.Promise.resolve('Example');
- }
-
- MyConstructor.prototype = {
- protoProperty: RSVP.Promise.resolve('Proto Property')
- };
-
- var myObject = new MyConstructor();
-
- RSVP.hashSettled(myObject).then(function(hash){
- // protoProperty will not be present, instead you will just have an
- // object that looks like:
- // {
- // example: { state: 'fulfilled', value: 'Example' }
- // }
- //
- // hash.hasOwnProperty('protoProperty'); // false
- // 'undefined' === typeof hash.protoProperty
- });
- ```
-
- @method hashSettled
- @for RSVP
- @param {Object} promises
- @param {String} label optional string that describes the promise.
- Useful for tooling.
- @return {Promise} promise that is fulfilled when when all properties of `promises`
- have been settled.
- @static
- */
- __exports__["default"] = function hashSettled(object, label) {
- return new HashSettled(Promise, object, label).promise;
- }
- });
-define("rsvp/hash",
- ["./promise","./promise-hash","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var Promise = __dependency1__["default"];
- var PromiseHash = __dependency2__["default"];
-
- /**
- `RSVP.hash` is similar to `RSVP.all`, but takes an object instead of an array
- for its `promises` argument.
-
- Returns a promise that is fulfilled when all the given promises have been
- fulfilled, or rejected if any of them become rejected. The returned promise
- is fulfilled with a hash that has the same key names as the `promises` object
- argument. If any of the values in the object are not promises, they will
- simply be copied over to the fulfilled object.
-
- Example:
-
- ```javascript
- var promises = {
- myPromise: RSVP.resolve(1),
- yourPromise: RSVP.resolve(2),
- theirPromise: RSVP.resolve(3),
- notAPromise: 4
- };
-
- RSVP.hash(promises).then(function(hash){
- // hash here is an object that looks like:
- // {
- // myPromise: 1,
- // yourPromise: 2,
- // theirPromise: 3,
- // notAPromise: 4
- // }
- });
- ````
-
- If any of the `promises` given to `RSVP.hash` are rejected, the first promise
- that is rejected will be given as the reason to the rejection handler.
-
- Example:
-
- ```javascript
- var promises = {
- myPromise: RSVP.resolve(1),
- rejectedPromise: RSVP.reject(new Error('rejectedPromise')),
- anotherRejectedPromise: RSVP.reject(new Error('anotherRejectedPromise')),
- };
-
- RSVP.hash(promises).then(function(hash){
- // Code here never runs because there are rejected promises!
- }, function(reason) {
- // reason.message === 'rejectedPromise'
- });
- ```
-
- An important note: `RSVP.hash` is intended for plain JavaScript objects that
- are just a set of keys and values. `RSVP.hash` will NOT preserve prototype
- chains.
-
- Example:
-
- ```javascript
- function MyConstructor(){
- this.example = RSVP.resolve('Example');
- }
-
- MyConstructor.prototype = {
- protoProperty: RSVP.resolve('Proto Property')
- };
-
- var myObject = new MyConstructor();
-
- RSVP.hash(myObject).then(function(hash){
- // protoProperty will not be present, instead you will just have an
- // object that looks like:
- // {
- // example: 'Example'
- // }
- //
- // hash.hasOwnProperty('protoProperty'); // false
- // 'undefined' === typeof hash.protoProperty
- });
- ```
-
- @method hash
- @static
- @for RSVP
- @param {Object} promises
- @param {String} label optional string that describes the promise.
- Useful for tooling.
- @return {Promise} promise that is fulfilled when all properties of `promises`
- have been fulfilled, or rejected if any of them become rejected.
- */
- __exports__["default"] = function hash(object, label) {
- return new PromiseHash(Promise, object, label).promise;
- }
- });
-define("rsvp/instrument",
- ["./config","./utils","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var config = __dependency1__.config;
- var now = __dependency2__.now;
-
- var queue = [];
-
- __exports__["default"] = function instrument(eventName, promise, child) {
- if (1 === queue.push({
- name: eventName,
- payload: {
- guid: promise._guidKey + promise._id,
- eventName: eventName,
- detail: promise._result,
- childGuid: child && promise._guidKey + child._id,
- label: promise._label,
- timeStamp: now(),
- stack: new Error(promise._label).stack
- }})) {
-
- setTimeout(function() {
- var entry;
- for (var i = 0; i < queue.length; i++) {
- entry = queue[i];
- config.trigger(entry.name, entry.payload);
- }
- queue.length = 0;
- }, 50);
- }
- }
- });
-define("rsvp/map",
- ["./promise","./utils","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var Promise = __dependency1__["default"];
- var isFunction = __dependency2__.isFunction;
-
- /**
- `RSVP.map` is similar to JavaScript's native `map` method, except that it
- waits for all promises to become fulfilled before running the `mapFn` on
- each item in given to `promises`. `RSVP.map` returns a promise that will
- become fulfilled with the result of running `mapFn` on the values the promises
- become fulfilled with.
-
- For example:
-
- ```javascript
-
- var promise1 = RSVP.resolve(1);
- var promise2 = RSVP.resolve(2);
- var promise3 = RSVP.resolve(3);
- var promises = [ promise1, promise2, promise3 ];
-
- var mapFn = function(item){
- return item + 1;
- };
-
- RSVP.map(promises, mapFn).then(function(result){
- // result is [ 2, 3, 4 ]
- });
- ```
-
- If any of the `promises` given to `RSVP.map` are rejected, the first promise
- that is rejected will be given as an argument to the returned promise's
- rejection handler. For example:
-
- ```javascript
- var promise1 = RSVP.resolve(1);
- var promise2 = RSVP.reject(new Error('2'));
- var promise3 = RSVP.reject(new Error('3'));
- var promises = [ promise1, promise2, promise3 ];
-
- var mapFn = function(item){
- return item + 1;
- };
-
- RSVP.map(promises, mapFn).then(function(array){
- // Code here never runs because there are rejected promises!
- }, function(reason) {
- // reason.message === '2'
- });
- ```
-
- `RSVP.map` will also wait if a promise is returned from `mapFn`. For example,
- say you want to get all comments from a set of blog posts, but you need
- the blog posts first because they contain a url to those comments.
-
- ```javscript
-
- var mapFn = function(blogPost){
- // getComments does some ajax and returns an RSVP.Promise that is fulfilled
- // with some comments data
- return getComments(blogPost.comments_url);
- };
-
- // getBlogPosts does some ajax and returns an RSVP.Promise that is fulfilled
- // with some blog post data
- RSVP.map(getBlogPosts(), mapFn).then(function(comments){
- // comments is the result of asking the server for the comments
- // of all blog posts returned from getBlogPosts()
- });
- ```
-
- @method map
- @static
- @for RSVP
- @param {Array} promises
- @param {Function} mapFn function to be called on each fulfilled promise.
- @param {String} label optional string for labeling the promise.
- Useful for tooling.
- @return {Promise} promise that is fulfilled with the result of calling
- `mapFn` on each fulfilled promise or value when they become fulfilled.
- The promise will be rejected if any of the given `promises` become rejected.
- @static
- */
- __exports__["default"] = function map(promises, mapFn, label) {
- return Promise.all(promises, label).then(function(values) {
- if (!isFunction(mapFn)) {
- throw new TypeError("You must pass a function as map's second argument.");
- }
-
- var length = values.length;
- var results = new Array(length);
-
- for (var i = 0; i < length; i++) {
- results[i] = mapFn(values[i]);
- }
-
- return Promise.all(results, label);
- });
- }
- });
-define("rsvp/node",
- ["./promise","./-internal","./utils","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var Promise = __dependency1__["default"];
- var noop = __dependency2__.noop;
- var resolve = __dependency2__.resolve;
- var reject = __dependency2__.reject;
- var isArray = __dependency3__.isArray;
-
- function Result() {
- this.value = undefined;
- }
-
- var ERROR = new Result();
- var GET_THEN_ERROR = new Result();
-
- function getThen(obj) {
- try {
- return obj.then;
- } catch(error) {
- ERROR.value= error;
- return ERROR;
- }
- }
-
-
- function tryApply(f, s, a) {
- try {
- f.apply(s, a);
- } catch(error) {
- ERROR.value = error;
- return ERROR;
- }
- }
-
- function makeObject(_, argumentNames) {
- var obj = {};
- var name;
- var i;
- var length = _.length;
- var args = new Array(length);
-
- for (var x = 0; x < length; x++) {
- args[x] = _[x];
- }
-
- for (i = 0; i < argumentNames.length; i++) {
- name = argumentNames[i];
- obj[name] = args[i + 1];
- }
-
- return obj;
- }
-
- function arrayResult(_) {
- var length = _.length;
- var args = new Array(length - 1);
-
- for (var i = 1; i < length; i++) {
- args[i - 1] = _[i];
- }
-
- return args;
- }
-
- function wrapThenable(then, promise) {
- return {
- then: function(onFulFillment, onRejection) {
- return then.call(promise, onFulFillment, onRejection);
- }
- };
- }
-
- /**
- `RSVP.denodeify` takes a 'node-style' function and returns a function that
- will return an `RSVP.Promise`. You can use `denodeify` in Node.js or the
- browser when you'd prefer to use promises over using callbacks. For example,
- `denodeify` transforms the following:
-
- ```javascript
- var fs = require('fs');
-
- fs.readFile('myfile.txt', function(err, data){
- if (err) return handleError(err);
- handleData(data);
- });
- ```
-
- into:
-
- ```javascript
- var fs = require('fs');
- var readFile = RSVP.denodeify(fs.readFile);
-
- readFile('myfile.txt').then(handleData, handleError);
- ```
-
- If the node function has multiple success parameters, then `denodeify`
- just returns the first one:
-
- ```javascript
- var request = RSVP.denodeify(require('request'));
-
- request('http://example.com').then(function(res) {
- // ...
- });
- ```
-
- However, if you need all success parameters, setting `denodeify`'s
- second parameter to `true` causes it to return all success parameters
- as an array:
-
- ```javascript
- var request = RSVP.denodeify(require('request'), true);
-
- request('http://example.com').then(function(result) {
- // result[0] -> res
- // result[1] -> body
- });
- ```
-
- Or if you pass it an array with names it returns the parameters as a hash:
-
- ```javascript
- var request = RSVP.denodeify(require('request'), ['res', 'body']);
-
- request('http://example.com').then(function(result) {
- // result.res
- // result.body
- });
- ```
-
- Sometimes you need to retain the `this`:
-
- ```javascript
- var app = require('express')();
- var render = RSVP.denodeify(app.render.bind(app));
- ```
-
- The denodified function inherits from the original function. It works in all
- environments, except IE 10 and below. Consequently all properties of the original
- function are available to you. However, any properties you change on the
- denodeified function won't be changed on the original function. Example:
-
- ```javascript
- var request = RSVP.denodeify(require('request')),
- cookieJar = request.jar(); // <- Inheritance is used here
-
- request('http://example.com', {jar: cookieJar}).then(function(res) {
- // cookieJar.cookies holds now the cookies returned by example.com
- });
- ```
-
- Using `denodeify` makes it easier to compose asynchronous operations instead
- of using callbacks. For example, instead of:
-
- ```javascript
- var fs = require('fs');
-
- fs.readFile('myfile.txt', function(err, data){
- if (err) { ... } // Handle error
- fs.writeFile('myfile2.txt', data, function(err){
- if (err) { ... } // Handle error
- console.log('done')
- });
- });
- ```
-
- you can chain the operations together using `then` from the returned promise:
-
- ```javascript
- var fs = require('fs');
- var readFile = RSVP.denodeify(fs.readFile);
- var writeFile = RSVP.denodeify(fs.writeFile);
-
- readFile('myfile.txt').then(function(data){
- return writeFile('myfile2.txt', data);
- }).then(function(){
- console.log('done')
- }).catch(function(error){
- // Handle error
- });
- ```
-
- @method denodeify
- @static
- @for RSVP
- @param {Function} nodeFunc a 'node-style' function that takes a callback as
- its last argument. The callback expects an error to be passed as its first
- argument (if an error occurred, otherwise null), and the value from the
- operation as its second argument ('function(err, value){ }').
- @param {Boolean|Array} argumentNames An optional paramter that if set
- to `true` causes the promise to fulfill with the callback's success arguments
- as an array. This is useful if the node function has multiple success
- paramters. If you set this paramter to an array with names, the promise will
- fulfill with a hash with these names as keys and the success parameters as
- values.
- @return {Function} a function that wraps `nodeFunc` to return an
- `RSVP.Promise`
- @static
- */
- __exports__["default"] = function denodeify(nodeFunc, options) {
- var fn = function() {
- var self = this;
- var l = arguments.length;
- var args = new Array(l + 1);
- var arg;
- var promiseInput = false;
-
- for (var i = 0; i < l; ++i) {
- arg = arguments[i];
-
- if (!promiseInput) {
- // TODO: clean this up
- promiseInput = needsPromiseInput(arg);
- if (promiseInput === GET_THEN_ERROR) {
- var p = new Promise(noop);
- reject(p, GET_THEN_ERROR.value);
- return p;
- } else if (promiseInput && promiseInput !== true) {
- arg = wrapThenable(promiseInput, arg);
- }
- }
- args[i] = arg;
- }
-
- var promise = new Promise(noop);
-
- args[l] = function(err, val) {
- if (err)
- reject(promise, err);
- else if (options === undefined)
- resolve(promise, val);
- else if (options === true)
- resolve(promise, arrayResult(arguments));
- else if (isArray(options))
- resolve(promise, makeObject(arguments, options));
- else
- resolve(promise, val);
- };
-
- if (promiseInput) {
- return handlePromiseInput(promise, args, nodeFunc, self);
- } else {
- return handleValueInput(promise, args, nodeFunc, self);
- }
- };
-
- fn.__proto__ = nodeFunc;
-
- return fn;
- }
-
- function handleValueInput(promise, args, nodeFunc, self) {
- var result = tryApply(nodeFunc, self, args);
- if (result === ERROR) {
- reject(promise, result.value);
- }
- return promise;
- }
-
- function handlePromiseInput(promise, args, nodeFunc, self){
- return Promise.all(args).then(function(args){
- var result = tryApply(nodeFunc, self, args);
- if (result === ERROR) {
- reject(promise, result.value);
- }
- return promise;
- });
- }
-
- function needsPromiseInput(arg) {
- if (arg && typeof arg === 'object') {
- if (arg.constructor === Promise) {
- return true;
- } else {
- return getThen(arg);
- }
- } else {
- return false;
- }
- }
- });
-define("rsvp/promise-hash",
- ["./enumerator","./-internal","./utils","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
- "use strict";
- var Enumerator = __dependency1__["default"];
- var PENDING = __dependency2__.PENDING;
- var o_create = __dependency3__.o_create;
-
- function PromiseHash(Constructor, object, label) {
- this._superConstructor(Constructor, object, true, label);
- }
-
- __exports__["default"] = PromiseHash;
-
- PromiseHash.prototype = o_create(Enumerator.prototype);
- PromiseHash.prototype._superConstructor = Enumerator;
- PromiseHash.prototype._init = function() {
- this._result = {};
- };
-
- PromiseHash.prototype._validateInput = function(input) {
- return input && typeof input === 'object';
- };
-
- PromiseHash.prototype._validationError = function() {
- return new Error('Promise.hash must be called with an object');
- };
-
- PromiseHash.prototype._enumerate = function() {
- var promise = this.promise;
- var input = this._input;
- var results = [];
-
- for (var key in input) {
- if (promise._state === PENDING && input.hasOwnProperty(key)) {
- results.push({
- position: key,
- entry: input[key]
- });
- }
- }
-
- var length = results.length;
- this._remaining = length;
- var result;
-
- for (var i = 0; promise._state === PENDING && i < length; i++) {
- result = results[i];
- this._eachEntry(result.entry, result.position);
- }
- };
- });
-define("rsvp/promise",
- ["./config","./instrument","./utils","./-internal","./promise/all","./promise/race","./promise/resolve","./promise/reject","exports"],
- function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __exports__) {
- "use strict";
- var config = __dependency1__.config;
- var instrument = __dependency2__["default"];
-
- var isFunction = __dependency3__.isFunction;
- var now = __dependency3__.now;
-
- var noop = __dependency4__.noop;
- var subscribe = __dependency4__.subscribe;
- var initializePromise = __dependency4__.initializePromise;
- var invokeCallback = __dependency4__.invokeCallback;
- var FULFILLED = __dependency4__.FULFILLED;
- var REJECTED = __dependency4__.REJECTED;
-
- var all = __dependency5__["default"];
- var race = __dependency6__["default"];
- var Resolve = __dependency7__["default"];
- var Reject = __dependency8__["default"];
-
- var guidKey = 'rsvp_' + now() + '-';
- var counter = 0;
-
- function needsResolver() {
- throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');
- }
-
- function needsNew() {
- throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");
- }
- __exports__["default"] = Promise;
- /**
- Promise objects represent the eventual result of an asynchronous operation. The
- primary way of interacting with a promise is through its `then` method, which
- registers callbacks to receive either a promise’s eventual value or the reason
- why the promise cannot be fulfilled.
-
- Terminology
- -----------
-
- - `promise` is an object or function with a `then` method whose behavior conforms to this specification.
- - `thenable` is an object or function that defines a `then` method.
- - `value` is any legal JavaScript value (including undefined, a thenable, or a promise).
- - `exception` is a value that is thrown using the throw statement.
- - `reason` is a value that indicates why a promise was rejected.
- - `settled` the final resting state of a promise, fulfilled or rejected.
-
- A promise can be in one of three states: pending, fulfilled, or rejected.
-
- Promises that are fulfilled have a fulfillment value and are in the fulfilled
- state. Promises that are rejected have a rejection reason and are in the
- rejected state. A fulfillment value is never a thenable.
-
- Promises can also be said to *resolve* a value. If this value is also a
- promise, then the original promise's settled state will match the value's
- settled state. So a promise that *resolves* a promise that rejects will
- itself reject, and a promise that *resolves* a promise that fulfills will
- itself fulfill.
-
-
- Basic Usage:
- ------------
-
- ```js
- var promise = new Promise(function(resolve, reject) {
- // on success
- resolve(value);
-
- // on failure
- reject(reason);
- });
-
- promise.then(function(value) {
- // on fulfillment
- }, function(reason) {
- // on rejection
- });
- ```
-
- Advanced Usage:
- ---------------
-
- Promises shine when abstracting away asynchronous interactions such as
- `XMLHttpRequest`s.
-
- ```js
- function getJSON(url) {
- return new Promise(function(resolve, reject){
- var xhr = new XMLHttpRequest();
-
- xhr.open('GET', url);
- xhr.onreadystatechange = handler;
- xhr.responseType = 'json';
- xhr.setRequestHeader('Accept', 'application/json');
- xhr.send();
-
- function handler() {
- if (this.readyState === this.DONE) {
- if (this.status === 200) {
- resolve(this.response);
- } else {
- reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']'));
- }
- }
- };
- });
- }
-
- getJSON('/posts.json').then(function(json) {
- // on fulfillment
- }, function(reason) {
- // on rejection
- });
- ```
-
- Unlike callbacks, promises are great composable primitives.
-
- ```js
- Promise.all([
- getJSON('/posts'),
- getJSON('/comments')
- ]).then(function(values){
- values[0] // => postsJSON
- values[1] // => commentsJSON
-
- return values;
- });
- ```
-
- @class RSVP.Promise
- @param {function} resolver
- @param {String} label optional string for labeling the promise.
- Useful for tooling.
- @constructor
- */
- function Promise(resolver, label) {
- this._id = counter++;
- this._label = label;
- this._state = undefined;
- this._result = undefined;
- this._subscribers = [];
-
- if (config.instrument) {
- instrument('created', this);
- }
-
- if (noop !== resolver) {
- if (!isFunction(resolver)) {
- needsResolver();
- }
-
- if (!(this instanceof Promise)) {
- needsNew();
- }
-
- initializePromise(this, resolver);
- }
- }
-
- Promise.cast = Resolve; // deprecated
- Promise.all = all;
- Promise.race = race;
- Promise.resolve = Resolve;
- Promise.reject = Reject;
-
- Promise.prototype = {
- constructor: Promise,
-
- _guidKey: guidKey,
-
- _onerror: function (reason) {
- config.trigger('error', reason);
- },
-
- /**
- The primary way of interacting with a promise is through its `then` method,
- which registers callbacks to receive either a promise's eventual value or the
- reason why the promise cannot be fulfilled.
-
- ```js
- findUser().then(function(user){
- // user is available
- }, function(reason){
- // user is unavailable, and you are given the reason why
- });
- ```
-
- Chaining
- --------
-
- The return value of `then` is itself a promise. This second, 'downstream'
- promise is resolved with the return value of the first promise's fulfillment
- or rejection handler, or rejected if the handler throws an exception.
-
- ```js
- findUser().then(function (user) {
- return user.name;
- }, function (reason) {
- return 'default name';
- }).then(function (userName) {
- // If `findUser` fulfilled, `userName` will be the user's name, otherwise it
- // will be `'default name'`
- });
-
- findUser().then(function (user) {
- throw new Error('Found user, but still unhappy');
- }, function (reason) {
- throw new Error('`findUser` rejected and we're unhappy');
- }).then(function (value) {
- // never reached
- }, function (reason) {
- // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.
- // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.
- });
- ```
- If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.
-
- ```js
- findUser().then(function (user) {
- throw new PedagogicalException('Upstream error');
- }).then(function (value) {
- // never reached
- }).then(function (value) {
- // never reached
- }, function (reason) {
- // The `PedgagocialException` is propagated all the way down to here
- });
- ```
-
- Assimilation
- ------------
-
- Sometimes the value you want to propagate to a downstream promise can only be
- retrieved asynchronously. This can be achieved by returning a promise in the
- fulfillment or rejection handler. The downstream promise will then be pending
- until the returned promise is settled. This is called *assimilation*.
-
- ```js
- findUser().then(function (user) {
- return findCommentsByAuthor(user);
- }).then(function (comments) {
- // The user's comments are now available
- });
- ```
-
- If the assimliated promise rejects, then the downstream promise will also reject.
-
- ```js
- findUser().then(function (user) {
- return findCommentsByAuthor(user);
- }).then(function (comments) {
- // If `findCommentsByAuthor` fulfills, we'll have the value here
- }, function (reason) {
- // If `findCommentsByAuthor` rejects, we'll have the reason here
- });
- ```
-
- Simple Example
- --------------
-
- Synchronous Example
-
- ```javascript
- var result;
-
- try {
- result = findResult();
- // success
- } catch(reason) {
- // failure
- }
- ```
-
- Errback Example
-
- ```js
- findResult(function(result, err){
- if (err) {
- // failure
- } else {
- // success
- }
- });
- ```
-
- Promise Example;
-
- ```javascript
- findResult().then(function(result){
- // success
- }, function(reason){
- // failure
- });
- ```
-
- Advanced Example
- --------------
-
- Synchronous Example
-
- ```javascript
- var author, books;
-
- try {
- author = findAuthor();
- books = findBooksByAuthor(author);
- // success
- } catch(reason) {
- // failure
- }
- ```
-
- Errback Example
-
- ```js
-
- function foundBooks(books) {
-
- }
-
- function failure(reason) {
-
- }
-
- findAuthor(function(author, err){
- if (err) {
- failure(err);
- // failure
- } else {
- try {
- findBoooksByAuthor(author, function(books, err) {
- if (err) {
- failure(err);
- } else {
- try {
- foundBooks(books);
- } catch(reason) {
- failure(reason);
- }
- }
- });
- } catch(error) {
- failure(err);
- }
- // success
- }
- });
- ```
-
- Promise Example;
-
- ```javascript
- findAuthor().
- then(findBooksByAuthor).
- then(function(books){
- // found books
- }).catch(function(reason){
- // something went wrong
- });
- ```
-
- @method then
- @param {Function} onFulfilled
- @param {Function} onRejected
- @param {String} label optional string for labeling the promise.
- Useful for tooling.
- @return {Promise}
- */
- then: function(onFulfillment, onRejection, label) {
- var parent = this;
- var state = parent._state;
-
- if (state === FULFILLED && !onFulfillment || state === REJECTED && !onRejection) {
- if (config.instrument) {
- instrument('chained', this, this);
- }
- return this;
- }
-
- parent._onerror = null;
-
- var child = new this.constructor(noop, label);
- var result = parent._result;
-
- if (config.instrument) {
- instrument('chained', parent, child);
- }
-
- if (state) {
- var callback = arguments[state - 1];
- config.async(function(){
- invokeCallback(state, child, callback, result);
- });
- } else {
- subscribe(parent, child, onFulfillment, onRejection);
- }
-
- return child;
- },
-
- /**
- `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same
- as the catch block of a try/catch statement.
-
- ```js
- function findAuthor(){
- throw new Error('couldn't find that author');
- }
-
- // synchronous
- try {
- findAuthor();
- } catch(reason) {
- // something went wrong
- }
-
- // async with promises
- findAuthor().catch(function(reason){
- // something went wrong
- });
- ```
-
- @method catch
- @param {Function} onRejection
- @param {String} label optional string for labeling the promise.
- Useful for tooling.
- @return {Promise}
- */
- 'catch': function(onRejection, label) {
- return this.then(null, onRejection, label);
- },
-
- /**
- `finally` will be invoked regardless of the promise's fate just as native
- try/catch/finally behaves
-
- Synchronous example:
-
- ```js
- findAuthor() {
- if (Math.random() > 0.5) {
- throw new Error();
- }
- return new Author();
- }
-
- try {
- return findAuthor(); // succeed or fail
- } catch(error) {
- return findOtherAuther();
- } finally {
- // always runs
- // doesn't affect the return value
- }
- ```
-
- Asynchronous example:
-
- ```js
- findAuthor().catch(function(reason){
- return findOtherAuther();
- }).finally(function(){
- // author was either found, or not
- });
- ```
-
- @method finally
- @param {Function} callback
- @param {String} label optional string for labeling the promise.
- Useful for tooling.
- @return {Promise}
- */
- 'finally': function(callback, label) {
- var constructor = this.constructor;
-
- return this.then(function(value) {
- return constructor.resolve(callback()).then(function(){
- return value;
- });
- }, function(reason) {
- return constructor.resolve(callback()).then(function(){
- throw reason;
- });
- }, label);
- }
- };
- });
-define("rsvp/promise/all",
- ["../enumerator","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var Enumerator = __dependency1__["default"];
-
- /**
- `RSVP.Promise.all` accepts an array of promises, and returns a new promise which
- is fulfilled with an array of fulfillment values for the passed promises, or
- rejected with the reason of the first passed promise to be rejected. It casts all
- elements of the passed iterable to promises as it runs this algorithm.
-
- Example:
-
- ```javascript
- var promise1 = RSVP.resolve(1);
- var promise2 = RSVP.resolve(2);
- var promise3 = RSVP.resolve(3);
- var promises = [ promise1, promise2, promise3 ];
-
- RSVP.Promise.all(promises).then(function(array){
- // The array here would be [ 1, 2, 3 ];
- });
- ```
-
- If any of the `promises` given to `RSVP.all` are rejected, the first promise
- that is rejected will be given as an argument to the returned promises's
- rejection handler. For example:
-
- Example:
-
- ```javascript
- var promise1 = RSVP.resolve(1);
- var promise2 = RSVP.reject(new Error("2"));
- var promise3 = RSVP.reject(new Error("3"));
- var promises = [ promise1, promise2, promise3 ];
-
- RSVP.Promise.all(promises).then(function(array){
- // Code here never runs because there are rejected promises!
- }, function(error) {
- // error.message === "2"
- });
- ```
-
- @method all
- @static
- @param {Array} entries array of promises
- @param {String} label optional string for labeling the promise.
- Useful for tooling.
- @return {Promise} promise that is fulfilled when all `promises` have been
- fulfilled, or rejected if any of them become rejected.
- @static
- */
- __exports__["default"] = function all(entries, label) {
- return new Enumerator(this, entries, true /* abort on reject */, label).promise;
- }
- });
-define("rsvp/promise/race",
- ["../utils","../-internal","exports"],
- function(__dependency1__, __dependency2__, __exports__) {
- "use strict";
- var isArray = __dependency1__.isArray;
-
- var noop = __dependency2__.noop;
- var resolve = __dependency2__.resolve;
- var reject = __dependency2__.reject;
- var subscribe = __dependency2__.subscribe;
- var PENDING = __dependency2__.PENDING;
-
- /**
- `RSVP.Promise.race` returns a new promise which is settled in the same way as the
- first passed promise to settle.
-
- Example:
-
- ```javascript
- var promise1 = new RSVP.Promise(function(resolve, reject){
- setTimeout(function(){
- resolve('promise 1');
- }, 200);
- });
-
- var promise2 = new RSVP.Promise(function(resolve, reject){
- setTimeout(function(){
- resolve('promise 2');
- }, 100);
- });
-
- RSVP.Promise.race([promise1, promise2]).then(function(result){
- // result === 'promise 2' because it was resolved before promise1
- // was resolved.
- });
- ```
-
- `RSVP.Promise.race` is deterministic in that only the state of the first
- settled promise matters. For example, even if other promises given to the
- `promises` array argument are resolved, but the first settled promise has
- become rejected before the other promises became fulfilled, the returned
- promise will become rejected:
-
- ```javascript
- var promise1 = new RSVP.Promise(function(resolve, reject){
- setTimeout(function(){
- resolve('promise 1');
- }, 200);
- });
-
- var promise2 = new RSVP.Promise(function(resolve, reject){
- setTimeout(function(){
- reject(new Error('promise 2'));
- }, 100);
- });
-
- RSVP.Promise.race([promise1, promise2]).then(function(result){
- // Code here never runs
- }, function(reason){
- // reason.message === 'promise 2' because promise 2 became rejected before
- // promise 1 became fulfilled
- });
- ```
-
- An example real-world use case is implementing timeouts:
-
- ```javascript
- RSVP.Promise.race([ajax('foo.json'), timeout(5000)])
- ```
-
- @method race
- @static
- @param {Array} promises array of promises to observe
- @param {String} label optional string for describing the promise returned.
- Useful for tooling.
- @return {Promise} a promise which settles in the same way as the first passed
- promise to settle.
- */
- __exports__["default"] = function race(entries, label) {
- /*jshint validthis:true */
- var Constructor = this;
-
- var promise = new Constructor(noop, label);
-
- if (!isArray(entries)) {
- reject(promise, new TypeError('You must pass an array to race.'));
- return promise;
- }
-
- var length = entries.length;
-
- function onFulfillment(value) {
- resolve(promise, value);
- }
-
- function onRejection(reason) {
- reject(promise, reason);
- }
-
- for (var i = 0; promise._state === PENDING && i < length; i++) {
- subscribe(Constructor.resolve(entries[i]), undefined, onFulfillment, onRejection);
- }
-
- return promise;
- }
- });
-define("rsvp/promise/reject",
- ["../-internal","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var noop = __dependency1__.noop;
- var _reject = __dependency1__.reject;
-
- /**
- `RSVP.Promise.reject` returns a promise rejected with the passed `reason`.
- It is shorthand for the following:
-
- ```javascript
- var promise = new RSVP.Promise(function(resolve, reject){
- reject(new Error('WHOOPS'));
- });
-
- promise.then(function(value){
- // Code here doesn't run because the promise is rejected!
- }, function(reason){
- // reason.message === 'WHOOPS'
- });
- ```
-
- Instead of writing the above, your code now simply becomes the following:
-
- ```javascript
- var promise = RSVP.Promise.reject(new Error('WHOOPS'));
-
- promise.then(function(value){
- // Code here doesn't run because the promise is rejected!
- }, function(reason){
- // reason.message === 'WHOOPS'
- });
- ```
-
- @method reject
- @static
- @param {Any} reason value that the returned promise will be rejected with.
- @param {String} label optional string for identifying the returned promise.
- Useful for tooling.
- @return {Promise} a promise rejected with the given `reason`.
- */
- __exports__["default"] = function reject(reason, label) {
- /*jshint validthis:true */
- var Constructor = this;
- var promise = new Constructor(noop, label);
- _reject(promise, reason);
- return promise;
- }
- });
-define("rsvp/promise/resolve",
- ["../-internal","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var noop = __dependency1__.noop;
- var _resolve = __dependency1__.resolve;
-
- /**
- `RSVP.Promise.resolve` returns a promise that will become resolved with the
- passed `value`. It is shorthand for the following:
-
- ```javascript
- var promise = new RSVP.Promise(function(resolve, reject){
- resolve(1);
- });
-
- promise.then(function(value){
- // value === 1
- });
- ```
-
- Instead of writing the above, your code now simply becomes the following:
-
- ```javascript
- var promise = RSVP.Promise.resolve(1);
-
- promise.then(function(value){
- // value === 1
- });
- ```
-
- @method resolve
- @static
- @param {Any} value value that the returned promise will be resolved with
- @param {String} label optional string for identifying the returned promise.
- Useful for tooling.
- @return {Promise} a promise that will become fulfilled with the given
- `value`
- */
- __exports__["default"] = function resolve(object, label) {
- /*jshint validthis:true */
- var Constructor = this;
-
- if (object && typeof object === 'object' && object.constructor === Constructor) {
- return object;
- }
-
- var promise = new Constructor(noop, label);
- _resolve(promise, object);
- return promise;
- }
- });
-define("rsvp/race",
- ["./promise","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var Promise = __dependency1__["default"];
-
- /**
- This is a convenient alias for `RSVP.Promise.race`.
-
- @method race
- @static
- @for RSVP
- @param {Array} array Array of promises.
- @param {String} label An optional label. This is useful
- for tooling.
- */
- __exports__["default"] = function race(array, label) {
- return Promise.race(array, label);
- }
- });
-define("rsvp/reject",
- ["./promise","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var Promise = __dependency1__["default"];
-
- /**
- This is a convenient alias for `RSVP.Promise.reject`.
-
- @method reject
- @static
- @for RSVP
- @param {Any} reason value that the returned promise will be rejected with.
- @param {String} label optional string for identifying the returned promise.
- Useful for tooling.
- @return {Promise} a promise rejected with the given `reason`.
- */
- __exports__["default"] = function reject(reason, label) {
- return Promise.reject(reason, label);
- }
- });
-define("rsvp/resolve",
- ["./promise","exports"],
- function(__dependency1__, __exports__) {
- "use strict";
- var Promise = __dependency1__["default"];
-
- /**
- This is a convenient alias for `RSVP.Promise.resolve`.
-
- @method resolve
- @static
- @for RSVP
- @param {Any} value value that the returned promise will be resolved with
- @param {String} label optional string for identifying the returned promise.
- Useful for tooling.
- @return {Promise} a promise that will become fulfilled with the given
- `value`
- */
- __exports__["default"] = function resolve(value, label) {
- return Promise.resolve(value, label);
- }
- });
-define("rsvp/rethrow",
- ["exports"],
- function(__exports__) {
- "use strict";
- /**
- `RSVP.rethrow` will rethrow an error on the next turn of the JavaScript event
- loop in order to aid debugging.
-
- Promises A+ specifies that any exceptions that occur with a promise must be
- caught by the promises implementation and bubbled to the last handler. For
- this reason, it is recommended that you always specify a second rejection
- handler function to `then`. However, `RSVP.rethrow` will throw the exception
- outside of the promise, so it bubbles up to your console if in the browser,
- or domain/cause uncaught exception in Node. `rethrow` will also throw the
- error again so the error can be handled by the promise per the spec.
-
- ```javascript
- function throws(){
- throw new Error('Whoops!');
- }
-
- var promise = new RSVP.Promise(function(resolve, reject){
- throws();
- });
-
- promise.catch(RSVP.rethrow).then(function(){
- // Code here doesn't run because the promise became rejected due to an
- // error!
- }, function (err){
- // handle the error here
- });
- ```
-
- The 'Whoops' error will be thrown on the next turn of the event loop
- and you can watch for it in your console. You can also handle it using a
- rejection handler given to `.then` or `.catch` on the returned promise.
-
- @method rethrow
- @static
- @for RSVP
- @param {Error} reason reason the promise became rejected.
- @throws Error
- @static
- */
- __exports__["default"] = function rethrow(reason) {
- setTimeout(function() {
- throw reason;
- });
- throw reason;
- }
- });
-define("rsvp/utils",
- ["exports"],
- function(__exports__) {
- "use strict";
- function objectOrFunction(x) {
- return typeof x === 'function' || (typeof x === 'object' && x !== null);
- }
-
- __exports__.objectOrFunction = objectOrFunction;function isFunction(x) {
- return typeof x === 'function';
- }
-
- __exports__.isFunction = isFunction;function isMaybeThenable(x) {
- return typeof x === 'object' && x !== null;
- }
-
- __exports__.isMaybeThenable = isMaybeThenable;var _isArray;
- if (!Array.isArray) {
- _isArray = function (x) {
- return Object.prototype.toString.call(x) === '[object Array]';
- };
- } else {
- _isArray = Array.isArray;
- }
-
- var isArray = _isArray;
- __exports__.isArray = isArray;
- // Date.now is not available in browsers < IE9
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now#Compatibility
- var now = Date.now || function() { return new Date().getTime(); };
- __exports__.now = now;
- function F() { }
-
- var o_create = (Object.create || function (o) {
- if (arguments.length > 1) {
- throw new Error('Second argument not supported');
- }
- if (typeof o !== 'object') {
- throw new TypeError('Argument must be an object');
- }
- F.prototype = o;
- return new F();
- });
- __exports__.o_create = o_create;
- });
-requireModule("ember");
-
-})();
\ No newline at end of file
diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoWithSpecialField.java b/jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoWithSpecialField.java
new file mode 100644
index 0000000000..58293c0562
--- /dev/null
+++ b/jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoWithSpecialField.java
@@ -0,0 +1,54 @@
+package com.baeldung.jackson.dtos;
+
+public class MyDtoWithSpecialField {
+
+ private String[] stringValue;
+ private int intValue;
+ private boolean booleanValue;
+
+ public MyDtoWithSpecialField() {
+ super();
+ }
+
+ public MyDtoWithSpecialField(final String[] stringValue, final int intValue, final boolean booleanValue) {
+ super();
+
+ this.stringValue = stringValue;
+ this.intValue = intValue;
+ this.booleanValue = booleanValue;
+ }
+
+ // API
+
+ public String[] getStringValue() {
+ return stringValue;
+ }
+
+ public void setStringValue(final String[] stringValue) {
+ this.stringValue = stringValue;
+ }
+
+ public int getIntValue() {
+ return intValue;
+ }
+
+ public void setIntValue(final int intValue) {
+ this.intValue = intValue;
+ }
+
+ public boolean isBooleanValue() {
+ return booleanValue;
+ }
+
+ public void setBooleanValue(final boolean booleanValue) {
+ this.booleanValue = booleanValue;
+ }
+
+ //
+
+ @Override
+ public String toString() {
+ return "MyDto [stringValue=" + stringValue + ", intValue=" + intValue + ", booleanValue=" + booleanValue + "]";
+ }
+
+}
diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/MyMixInForString.java b/jackson/src/test/java/com/baeldung/jackson/dtos/MyMixInForIgnoreType.java
similarity index 76%
rename from jackson/src/test/java/com/baeldung/jackson/dtos/MyMixInForString.java
rename to jackson/src/test/java/com/baeldung/jackson/dtos/MyMixInForIgnoreType.java
index b386541df6..ca29c98b9a 100644
--- a/jackson/src/test/java/com/baeldung/jackson/dtos/MyMixInForString.java
+++ b/jackson/src/test/java/com/baeldung/jackson/dtos/MyMixInForIgnoreType.java
@@ -3,6 +3,6 @@ package com.baeldung.jackson.dtos;
import com.fasterxml.jackson.annotation.JsonIgnoreType;
@JsonIgnoreType
-public class MyMixInForString {
+public class MyMixInForIgnoreType {
//
}
diff --git a/jackson/src/test/java/com/baeldung/jackson/test/JacksonAnnotationTest.java b/jackson/src/test/java/com/baeldung/jackson/test/JacksonAnnotationTest.java
index 74fbd021a0..d854d89b5f 100644
--- a/jackson/src/test/java/com/baeldung/jackson/test/JacksonAnnotationTest.java
+++ b/jackson/src/test/java/com/baeldung/jackson/test/JacksonAnnotationTest.java
@@ -12,11 +12,8 @@ import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
-import com.baeldung.jackson.bidirection.ItemWithIdentity;
-import com.baeldung.jackson.bidirection.ItemWithRef;
-import com.baeldung.jackson.bidirection.UserWithRef;
-import com.baeldung.jackson.dtos.User;
-import com.baeldung.jackson.dtos.withEnum.TypeEnumWithValue;
+import org.junit.Test;
+
import com.baeldung.jackson.annotation.BeanWithCreator;
import com.baeldung.jackson.annotation.BeanWithCustomAnnotation;
import com.baeldung.jackson.annotation.BeanWithFilter;
@@ -30,16 +27,17 @@ import com.baeldung.jackson.annotation.RawBean;
import com.baeldung.jackson.annotation.UnwrappedUser;
import com.baeldung.jackson.annotation.UserWithIgnoreType;
import com.baeldung.jackson.annotation.Zoo;
+import com.baeldung.jackson.bidirection.ItemWithIdentity;
+import com.baeldung.jackson.bidirection.ItemWithRef;
import com.baeldung.jackson.bidirection.UserWithIdentity;
+import com.baeldung.jackson.bidirection.UserWithRef;
import com.baeldung.jackson.date.EventWithFormat;
import com.baeldung.jackson.date.EventWithSerializer;
-import com.baeldung.jackson.dtos.MyMixInForString;
+import com.baeldung.jackson.dtos.MyMixInForIgnoreType;
+import com.baeldung.jackson.dtos.withEnum.TypeEnumWithValue;
import com.baeldung.jackson.exception.UserWithRoot;
import com.baeldung.jackson.jsonview.Item;
import com.baeldung.jackson.jsonview.Views;
-import org.junit.Ignore;
-import org.junit.Test;
-
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.InjectableValues;
@@ -127,7 +125,7 @@ public class JacksonAnnotationTest {
public void whenDeserializingUsingJsonCreator_thenCorrect() throws JsonProcessingException, IOException {
final String json = "{\"id\":1,\"theName\":\"My bean\"}";
- final BeanWithCreator bean = new ObjectMapper().reader(BeanWithCreator.class).readValue(json);
+ final BeanWithCreator bean = new ObjectMapper().readerFor(BeanWithCreator.class).readValue(json);
assertEquals("My bean", bean.name);
}
@@ -136,7 +134,7 @@ public class JacksonAnnotationTest {
final String json = "{\"name\":\"My bean\"}";
final InjectableValues inject = new InjectableValues.Std().addValue(int.class, 1);
- final BeanWithInject bean = new ObjectMapper().reader(inject).withType(BeanWithInject.class).readValue(json);
+ final BeanWithInject bean = new ObjectMapper().reader(inject).forType(BeanWithInject.class).readValue(json);
assertEquals("My bean", bean.name);
assertEquals(1, bean.id);
}
@@ -145,7 +143,7 @@ public class JacksonAnnotationTest {
public void whenDeserializingUsingJsonAnySetter_thenCorrect() throws JsonProcessingException, IOException {
final String json = "{\"name\":\"My bean\",\"attr2\":\"val2\",\"attr1\":\"val1\"}";
- final ExtendableBean bean = new ObjectMapper().reader(ExtendableBean.class).readValue(json);
+ final ExtendableBean bean = new ObjectMapper().readerFor(ExtendableBean.class).readValue(json);
assertEquals("My bean", bean.name);
assertEquals("val2", bean.getProperties().get("attr2"));
}
@@ -154,7 +152,7 @@ public class JacksonAnnotationTest {
public void whenDeserializingUsingJsonSetter_thenCorrect() throws JsonProcessingException, IOException {
final String json = "{\"id\":1,\"name\":\"My bean\"}";
- final BeanWithGetter bean = new ObjectMapper().reader(BeanWithGetter.class).readValue(json);
+ final BeanWithGetter bean = new ObjectMapper().readerFor(BeanWithGetter.class).readValue(json);
assertEquals("My bean", bean.getTheName());
}
@@ -164,7 +162,7 @@ public class JacksonAnnotationTest {
final SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
- final EventWithSerializer event = new ObjectMapper().reader(EventWithSerializer.class).readValue(json);
+ final EventWithSerializer event = new ObjectMapper().readerFor(EventWithSerializer.class).readValue(json);
assertEquals("20-12-2014 02:30:00", df.format(event.eventDate));
}
@@ -235,7 +233,7 @@ public class JacksonAnnotationTest {
public void whenDeserializingPolymorphic_thenCorrect() throws JsonProcessingException, IOException {
final String json = "{\"animal\":{\"name\":\"lacy\",\"type\":\"cat\"}}";
- final Zoo zoo = new ObjectMapper().reader().withType(Zoo.class).readValue(json);
+ final Zoo zoo = new ObjectMapper().readerFor(Zoo.class).readValue(json);
assertEquals("lacy", zoo.animal.name);
assertEquals(Zoo.Cat.class, zoo.animal.getClass());
@@ -250,7 +248,7 @@ public class JacksonAnnotationTest {
assertThat(result, containsString("My bean"));
assertThat(result, containsString("1"));
- final BeanWithGetter resultBean = new ObjectMapper().reader(BeanWithGetter.class).readValue(result);
+ final BeanWithGetter resultBean = new ObjectMapper().readerFor(BeanWithGetter.class).readValue(result);
assertEquals("My bean", resultBean.getTheName());
}
@@ -338,19 +336,19 @@ public class JacksonAnnotationTest {
assertThat(result, not(containsString("dateCreated")));
}
- @Ignore("Jackson 2.7.1-1 seems to have changed the API regarding mixins")
+ // @Ignore("Jackson 2.7.1-1 seems to have changed the API regarding mixins")
@Test
public void whenSerializingUsingMixInAnnotation_thenCorrect() throws JsonProcessingException {
- final User user = new User(1, "John");
+ final com.baeldung.jackson.dtos.Item item = new com.baeldung.jackson.dtos.Item(1, "book", null);
- String result = new ObjectMapper().writeValueAsString(user);
- assertThat(result, containsString("John"));
+ String result = new ObjectMapper().writeValueAsString(item);
+ assertThat(result, containsString("owner"));
final ObjectMapper mapper = new ObjectMapper();
- mapper.addMixIn(String.class, MyMixInForString.class);
+ mapper.addMixIn(com.baeldung.jackson.dtos.User.class, MyMixInForIgnoreType.class);
- result = mapper.writeValueAsString(user);
- assertThat(result, not(containsString("John")));
+ result = mapper.writeValueAsString(item);
+ assertThat(result, not(containsString("owner")));
}
@Test
diff --git a/jackson/src/test/java/com/baeldung/jackson/test/JacksonBidirectionRelationTest.java b/jackson/src/test/java/com/baeldung/jackson/test/JacksonBidirectionRelationTest.java
index 971b40406a..db8507a4b0 100644
--- a/jackson/src/test/java/com/baeldung/jackson/test/JacksonBidirectionRelationTest.java
+++ b/jackson/src/test/java/com/baeldung/jackson/test/JacksonBidirectionRelationTest.java
@@ -7,6 +7,8 @@ import static org.junit.Assert.assertThat;
import java.io.IOException;
+import org.junit.Test;
+
import com.baeldung.jackson.bidirection.Item;
import com.baeldung.jackson.bidirection.ItemWithIdentity;
import com.baeldung.jackson.bidirection.ItemWithIgnore;
@@ -20,8 +22,6 @@ import com.baeldung.jackson.bidirection.UserWithRef;
import com.baeldung.jackson.bidirection.UserWithSerializer;
import com.baeldung.jackson.bidirection.UserWithView;
import com.baeldung.jackson.jsonview.Views;
-import org.junit.Test;
-
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -93,7 +93,7 @@ public class JacksonBidirectionRelationTest {
public void givenBidirectionRelation_whenDeserializingUsingIdentity_thenCorrect() throws JsonProcessingException, IOException {
final String json = "{\"id\":2,\"itemName\":\"book\",\"owner\":{\"id\":1,\"name\":\"John\",\"userItems\":[2]}}";
- final ItemWithIdentity item = new ObjectMapper().reader(ItemWithIdentity.class).readValue(json);
+ final ItemWithIdentity item = new ObjectMapper().readerFor(ItemWithIdentity.class).readValue(json);
assertEquals(2, item.id);
assertEquals("book", item.itemName);
@@ -104,7 +104,7 @@ public class JacksonBidirectionRelationTest {
public void givenBidirectionRelation_whenUsingCustomDeserializer_thenCorrect() throws JsonProcessingException, IOException {
final String json = "{\"id\":2,\"itemName\":\"book\",\"owner\":{\"id\":1,\"name\":\"John\",\"userItems\":[2]}}";
- final ItemWithSerializer item = new ObjectMapper().reader(ItemWithSerializer.class).readValue(json);
+ final ItemWithSerializer item = new ObjectMapper().readerFor(ItemWithSerializer.class).readValue(json);
assertEquals(2, item.id);
assertEquals("book", item.itemName);
assertEquals("John", item.owner.name);
diff --git a/jackson/src/test/java/com/baeldung/jackson/test/JacksonDateTest.java b/jackson/src/test/java/com/baeldung/jackson/test/JacksonDateTest.java
index 50ec50b668..d8357f8500 100644
--- a/jackson/src/test/java/com/baeldung/jackson/test/JacksonDateTest.java
+++ b/jackson/src/test/java/com/baeldung/jackson/test/JacksonDateTest.java
@@ -11,15 +11,15 @@ import java.time.LocalDateTime;
import java.util.Date;
import java.util.TimeZone;
-import com.baeldung.jackson.date.EventWithLocalDateTime;
-import com.baeldung.jackson.date.Event;
-import com.baeldung.jackson.date.EventWithFormat;
-import com.baeldung.jackson.date.EventWithJodaTime;
-import com.baeldung.jackson.date.EventWithSerializer;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.junit.Test;
+import com.baeldung.jackson.date.Event;
+import com.baeldung.jackson.date.EventWithFormat;
+import com.baeldung.jackson.date.EventWithJodaTime;
+import com.baeldung.jackson.date.EventWithLocalDateTime;
+import com.baeldung.jackson.date.EventWithSerializer;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
@@ -128,7 +128,7 @@ public class JacksonDateTest {
final ObjectMapper mapper = new ObjectMapper();
mapper.setDateFormat(df);
- final Event event = mapper.reader(Event.class).readValue(json);
+ final Event event = mapper.readerFor(Event.class).readValue(json);
assertEquals("20-12-2014 02:30:00", df.format(event.eventDate));
}
@@ -139,7 +139,7 @@ public class JacksonDateTest {
final SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
final ObjectMapper mapper = new ObjectMapper();
- final EventWithSerializer event = mapper.reader(EventWithSerializer.class).readValue(json);
+ final EventWithSerializer event = mapper.readerFor(EventWithSerializer.class).readValue(json);
assertEquals("20-12-2014 02:30:00", df.format(event.eventDate));
}
diff --git a/jackson/src/test/java/com/baeldung/jackson/test/JacksonExceptionsTest.java b/jackson/src/test/java/com/baeldung/jackson/test/JacksonExceptionsTest.java
index 90317848ce..d9b8d1cc18 100644
--- a/jackson/src/test/java/com/baeldung/jackson/test/JacksonExceptionsTest.java
+++ b/jackson/src/test/java/com/baeldung/jackson/test/JacksonExceptionsTest.java
@@ -7,9 +7,13 @@ import static org.junit.Assert.assertThat;
import java.io.IOException;
import java.util.List;
-import com.baeldung.jackson.exception.*;
import org.junit.Test;
+import com.baeldung.jackson.exception.User;
+import com.baeldung.jackson.exception.UserWithPrivateFields;
+import com.baeldung.jackson.exception.UserWithRoot;
+import com.baeldung.jackson.exception.Zoo;
+import com.baeldung.jackson.exception.ZooConfigured;
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonFactory;
@@ -30,7 +34,7 @@ public class JacksonExceptionsTest {
final String json = "{\"animal\":{\"name\":\"lacy\"}}";
final ObjectMapper mapper = new ObjectMapper();
- mapper.reader().withType(Zoo.class).readValue(json);
+ mapper.reader().forType(Zoo.class).readValue(json);
}
@Test
@@ -38,7 +42,7 @@ public class JacksonExceptionsTest {
final String json = "{\"animal\":{\"name\":\"lacy\"}}";
final ObjectMapper mapper = new ObjectMapper();
- mapper.reader().withType(ZooConfigured.class).readValue(json);
+ mapper.reader().forType(ZooConfigured.class).readValue(json);
}
// JsonMappingException: No serializer found for class
@@ -67,7 +71,7 @@ public class JacksonExceptionsTest {
final String json = "{\"id\":1,\"name\":\"John\"}";
final ObjectMapper mapper = new ObjectMapper();
- mapper.reader().withType(User.class).readValue(json);
+ mapper.reader().forType(User.class).readValue(json);
}
@Test
@@ -75,7 +79,7 @@ public class JacksonExceptionsTest {
final String json = "{\"id\":1,\"name\":\"John\"}";
final ObjectMapper mapper = new ObjectMapper();
- final com.baeldung.jackson.dtos.User user = mapper.reader().withType(com.baeldung.jackson.dtos.User.class).readValue(json);
+ final com.baeldung.jackson.dtos.User user = mapper.reader().forType(com.baeldung.jackson.dtos.User.class).readValue(json);
assertEquals("John", user.name);
}
@@ -87,7 +91,7 @@ public class JacksonExceptionsTest {
final ObjectMapper mapper = new ObjectMapper();
mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);
- mapper.reader().withType(com.baeldung.jackson.dtos.User.class).readValue(json);
+ mapper.reader().forType(com.baeldung.jackson.dtos.User.class).readValue(json);
}
@Test
@@ -97,7 +101,7 @@ public class JacksonExceptionsTest {
final ObjectMapper mapper = new ObjectMapper();
mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);
- final UserWithRoot user = mapper.reader().withType(UserWithRoot.class).readValue(json);
+ final UserWithRoot user = mapper.reader().forType(UserWithRoot.class).readValue(json);
assertEquals("John", user.name);
}
@@ -107,7 +111,7 @@ public class JacksonExceptionsTest {
final String json = "[{\"id\":1,\"name\":\"John\"},{\"id\":2,\"name\":\"Adam\"}]";
final ObjectMapper mapper = new ObjectMapper();
- mapper.reader().withType(com.baeldung.jackson.dtos.User.class).readValue(json);
+ mapper.reader().forType(com.baeldung.jackson.dtos.User.class).readValue(json);
}
@Test
@@ -115,7 +119,7 @@ public class JacksonExceptionsTest {
final String json = "[{\"id\":1,\"name\":\"John\"},{\"id\":2,\"name\":\"Adam\"}]";
final ObjectMapper mapper = new ObjectMapper();
- final List users = mapper.reader().withType(new TypeReference>() {
+ final List users = mapper.reader().forType(new TypeReference>() {
}).readValue(json);
assertEquals(2, users.size());
@@ -127,7 +131,7 @@ public class JacksonExceptionsTest {
final String json = "{\"id\":1,\"name\":\"John\", \"checked\":true}";
final ObjectMapper mapper = new ObjectMapper();
- mapper.reader().withType(com.baeldung.jackson.dtos.User.class).readValue(json);
+ mapper.reader().forType(com.baeldung.jackson.dtos.User.class).readValue(json);
}
@Test
@@ -137,7 +141,7 @@ public class JacksonExceptionsTest {
final ObjectMapper mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
- final com.baeldung.jackson.dtos.User user = mapper.reader().withType(com.baeldung.jackson.dtos.User.class).readValue(json);
+ final com.baeldung.jackson.dtos.User user = mapper.reader().forType(com.baeldung.jackson.dtos.User.class).readValue(json);
assertEquals("John", user.name);
}
@@ -147,7 +151,7 @@ public class JacksonExceptionsTest {
final String json = "{'id':1,'name':'John'}";
final ObjectMapper mapper = new ObjectMapper();
- mapper.reader().withType(com.baeldung.jackson.dtos.User.class).readValue(json);
+ mapper.reader().forType(com.baeldung.jackson.dtos.User.class).readValue(json);
}
@Test
@@ -158,7 +162,7 @@ public class JacksonExceptionsTest {
factory.enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES);
final ObjectMapper mapper = new ObjectMapper(factory);
- final com.baeldung.jackson.dtos.User user = mapper.reader().withType(com.baeldung.jackson.dtos.User.class).readValue(json);
+ final com.baeldung.jackson.dtos.User user = mapper.reader().forType(com.baeldung.jackson.dtos.User.class).readValue(json);
assertEquals("John", user.name);
}
diff --git a/jackson/src/test/java/com/baeldung/jackson/test/JacksonJsonViewTest.java b/jackson/src/test/java/com/baeldung/jackson/test/JacksonJsonViewTest.java
index 61fa2919ac..477b0132e2 100644
--- a/jackson/src/test/java/com/baeldung/jackson/test/JacksonJsonViewTest.java
+++ b/jackson/src/test/java/com/baeldung/jackson/test/JacksonJsonViewTest.java
@@ -7,12 +7,12 @@ import static org.junit.Assert.assertThat;
import java.io.IOException;
-import com.baeldung.jackson.jsonview.Item;
-import com.baeldung.jackson.jsonview.User;
-import com.baeldung.jackson.jsonview.MyBeanSerializerModifier;
-import com.baeldung.jackson.jsonview.Views;
import org.junit.Test;
+import com.baeldung.jackson.jsonview.Item;
+import com.baeldung.jackson.jsonview.MyBeanSerializerModifier;
+import com.baeldung.jackson.jsonview.User;
+import com.baeldung.jackson.jsonview.Views;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -66,7 +66,7 @@ public class JacksonJsonViewTest {
final ObjectMapper mapper = new ObjectMapper();
- final User user = mapper.readerWithView(Views.Public.class).withType(User.class).readValue(json);
+ final User user = mapper.readerWithView(Views.Public.class).forType(User.class).readValue(json);
assertEquals(1, user.getId());
assertEquals("John", user.getName());
}
diff --git a/jackson/src/test/java/com/baeldung/jackson/test/JacksonSerializationIgnoreUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/test/JacksonSerializationIgnoreUnitTest.java
index 4c01ec9333..71499b8a24 100644
--- a/jackson/src/test/java/com/baeldung/jackson/test/JacksonSerializationIgnoreUnitTest.java
+++ b/jackson/src/test/java/com/baeldung/jackson/test/JacksonSerializationIgnoreUnitTest.java
@@ -8,17 +8,17 @@ import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
-import com.baeldung.jackson.dtos.MyDtoIncludeNonDefault;
-import com.baeldung.jackson.dtos.MyDtoWithFilter;
-import com.baeldung.jackson.dtos.ignore.MyDtoIgnoreNull;
-import com.baeldung.jackson.dtos.MyDto;
-import com.baeldung.jackson.dtos.MyMixInForString;
-import com.baeldung.jackson.dtos.ignore.MyDtoIgnoreField;
-import com.baeldung.jackson.dtos.ignore.MyDtoIgnoreFieldByName;
-import com.baeldung.jackson.serialization.MyDtoNullKeySerializer;
-import org.junit.Ignore;
import org.junit.Test;
+import com.baeldung.jackson.dtos.MyDto;
+import com.baeldung.jackson.dtos.MyDtoIncludeNonDefault;
+import com.baeldung.jackson.dtos.MyDtoWithFilter;
+import com.baeldung.jackson.dtos.MyDtoWithSpecialField;
+import com.baeldung.jackson.dtos.MyMixInForIgnoreType;
+import com.baeldung.jackson.dtos.ignore.MyDtoIgnoreField;
+import com.baeldung.jackson.dtos.ignore.MyDtoIgnoreFieldByName;
+import com.baeldung.jackson.dtos.ignore.MyDtoIgnoreNull;
+import com.baeldung.jackson.serialization.MyDtoNullKeySerializer;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParseException;
@@ -85,12 +85,12 @@ public class JacksonSerializationIgnoreUnitTest {
System.out.println(dtoAsString);
}
- @Ignore("Jackson 2.7.1-1 seems to have changed the API for this case")
+ // @Ignore("Jackson 2.7.1-1 seems to have changed the API for this case")
@Test
public final void givenFieldTypeIsIgnored_whenDtoIsSerialized_thenCorrect() throws JsonParseException, IOException {
final ObjectMapper mapper = new ObjectMapper();
- mapper.addMixIn(String.class, MyMixInForString.class);
- final MyDto dtoObject = new MyDto();
+ mapper.addMixIn(String[].class, MyMixInForIgnoreType.class);
+ final MyDtoWithSpecialField dtoObject = new MyDtoWithSpecialField();
dtoObject.setBooleanValue(true);
final String dtoAsString = mapper.writeValueAsString(dtoObject);
diff --git a/jsf/pom.xml b/jsf/pom.xml
index c4801996de..b80bcfb416 100644
--- a/jsf/pom.xml
+++ b/jsf/pom.xml
@@ -25,6 +25,19 @@
jsf-impl
${com.sun.faces.version}
+
+ javax.el
+ el-api
+ ${javax.el.version}
+
+
+
+
+
+ javax.servlet
+ jstl
+ 1.2
+
@@ -114,6 +127,7 @@
2.1.7
+ 2.2
1.7.13
diff --git a/jsf/src/main/java/com/baeldung/springintegration/controllers/ELSampleBean.java b/jsf/src/main/java/com/baeldung/springintegration/controllers/ELSampleBean.java
new file mode 100644
index 0000000000..a13f0890b5
--- /dev/null
+++ b/jsf/src/main/java/com/baeldung/springintegration/controllers/ELSampleBean.java
@@ -0,0 +1,110 @@
+package com.baeldung.springintegration.controllers;
+
+import java.util.Random;
+import javax.annotation.PostConstruct;
+import javax.faces.application.Application;
+import javax.faces.application.FacesMessage;
+import javax.faces.bean.ManagedBean;
+import javax.faces.bean.ViewScoped;
+import javax.faces.component.html.HtmlInputText;
+import javax.faces.context.FacesContext;
+
+@ManagedBean(name = "ELBean")
+@ViewScoped
+public class ELSampleBean {
+
+ private String firstName;
+ private String lastName;
+ private String pageDescription = "This page demos JSF EL Basics";
+ private int pageCounter;
+ private Random randomIntGen = new Random();
+
+ @PostConstruct
+ public void init() {
+ pageCounter = randomIntGen.nextInt();
+ }
+
+ public void save() {
+
+ }
+
+ public void saveFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+
+ public void saveByELEvaluation() {
+ firstName = (String) evaluateEL("#{firstName.value}", String.class);
+ FacesContext ctx = FacesContext.getCurrentInstance();
+ FacesMessage theMessage = new FacesMessage("Name component Evaluated: " + firstName);
+ theMessage.setSeverity(FacesMessage.SEVERITY_INFO);
+ ctx.addMessage(null, theMessage);
+
+ }
+
+ private Object evaluateEL(String elExpression, Class> clazz) {
+ Object toReturn = null;
+ FacesContext ctx = FacesContext.getCurrentInstance();
+ Application app = ctx.getApplication();
+ toReturn = app.evaluateExpressionGet(ctx, elExpression, clazz);
+
+ return toReturn;
+
+ }
+
+ /**
+ * @return the firstName
+ */
+ public String getFirstName() {
+ return firstName;
+ }
+
+ /**
+ * @param firstName the firstName to set
+ */
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ /**
+ * @return the lastName
+ */
+ public String getLastName() {
+ return lastName;
+ }
+
+ /**
+ * @param lastName the lastName to set
+ */
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ /**
+ * @return the pageDescription
+ */
+ public String getPageDescription() {
+ return pageDescription;
+ }
+
+ /**
+ * @param pageDescription the pageDescription to set
+ */
+ public void setPageDescription(String pageDescription) {
+ this.pageDescription = pageDescription;
+ }
+
+ /**
+ * @return the pageCounter
+ */
+ public int getPageCounter() {
+ return pageCounter;
+ }
+
+ /**
+ * @param pageCounter the pageCounter to set
+ */
+ public void setPageCounter(int pageCounter) {
+ this.pageCounter = pageCounter;
+ }
+}
diff --git a/jsf/src/main/webapp/el_intro.xhtml b/jsf/src/main/webapp/el_intro.xhtml
new file mode 100644
index 0000000000..446647497f
--- /dev/null
+++ b/jsf/src/main/webapp/el_intro.xhtml
@@ -0,0 +1,52 @@
+
+
+
+
+ Baeldung | The EL Intro
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Key
+ Value
+
+
+ #{header.key}
+ #{header.value}
+
+
+
+
+
+
+
+
diff --git a/json/pom.xml b/json/pom.xml
new file mode 100644
index 0000000000..47f1f25aa2
--- /dev/null
+++ b/json/pom.xml
@@ -0,0 +1,25 @@
+
+ 4.0.0
+ org.baeldung
+ json
+ 0.0.1-SNAPSHOT
+
+
+
+
+ org.everit.json
+ org.everit.json.schema
+ 1.3.0
+
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+
+
+
diff --git a/json/src/test/java/org/baeldung/json/schema/JSONSchemaTest.java b/json/src/test/java/org/baeldung/json/schema/JSONSchemaTest.java
new file mode 100644
index 0000000000..273fd48bac
--- /dev/null
+++ b/json/src/test/java/org/baeldung/json/schema/JSONSchemaTest.java
@@ -0,0 +1,31 @@
+package org.baeldung.json.schema;
+
+import org.everit.json.schema.Schema;
+import org.everit.json.schema.loader.SchemaLoader;
+
+import org.json.JSONObject;
+import org.json.JSONTokener;
+import org.junit.Test;
+
+public class JSONSchemaTest {
+
+ @Test
+ public void givenInvalidInput_whenValidating_thenInvalid() {
+
+ JSONObject jsonSchema = new JSONObject(new JSONTokener(JSONSchemaTest.class.getResourceAsStream("/schema.json")));
+ JSONObject jsonSubject = new JSONObject(new JSONTokener(JSONSchemaTest.class.getResourceAsStream("/product_invalid.json")));
+
+ Schema schema = SchemaLoader.load(jsonSchema);
+ schema.validate(jsonSubject);
+ }
+
+ @Test
+ public void givenValidInput_whenValidating_thenValid() {
+
+ JSONObject jsonSchema = new JSONObject(new JSONTokener(JSONSchemaTest.class.getResourceAsStream("/schema.json")));
+ JSONObject jsonSubject = new JSONObject(new JSONTokener(JSONSchemaTest.class.getResourceAsStream("/product_valid.json")));
+
+ Schema schema = SchemaLoader.load(jsonSchema);
+ schema.validate(jsonSubject);
+ }
+}
diff --git a/json/src/test/resources/product_invalid.json b/json/src/test/resources/product_invalid.json
new file mode 100644
index 0000000000..7c55d8c7a5
--- /dev/null
+++ b/json/src/test/resources/product_invalid.json
@@ -0,0 +1,5 @@
+{
+ "id": 1,
+ "name": "Lampshade",
+ "price": 0
+}
diff --git a/json/src/test/resources/product_valid.json b/json/src/test/resources/product_valid.json
new file mode 100644
index 0000000000..e0697dc4c2
--- /dev/null
+++ b/json/src/test/resources/product_valid.json
@@ -0,0 +1,5 @@
+{
+ "id": 1,
+ "name": "Lampshade",
+ "price": 10
+}
diff --git a/json/src/test/resources/schema.json b/json/src/test/resources/schema.json
new file mode 100644
index 0000000000..7cf99d76e0
--- /dev/null
+++ b/json/src/test/resources/schema.json
@@ -0,0 +1,22 @@
+{
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "title": "Product",
+ "description": "A product from the catalog",
+ "type": "object",
+ "properties": {
+ "id": {
+ "description": "The unique identifier for a product",
+ "type": "integer"
+ },
+ "name": {
+ "description": "Name of the product",
+ "type": "string"
+ },
+ "price": {
+ "type": "number",
+ "minimum": 0,
+ "exclusiveMinimum": true
+ }
+ },
+ "required": ["id", "name", "price"]
+}
diff --git a/log4j/pom.xml b/log4j/pom.xml
new file mode 100644
index 0000000000..76c05b36c1
--- /dev/null
+++ b/log4j/pom.xml
@@ -0,0 +1,66 @@
+
+
+ 4.0.0
+
+ com.baeldung
+ log4j
+ 1.0-SNAPSHOT
+
+
+
+
+ log4j
+ log4j
+ 1.2.17
+
+
+
+
+
+ org.apache.logging.log4j
+ log4j-api
+ 2.6
+
+
+ org.apache.logging.log4j
+ log4j-core
+ 2.6
+
+
+
+
+ com.lmax
+ disruptor
+ 3.3.4
+
+
+
+
+
+
+ ch.qos.logback
+ logback-classic
+ 1.1.7
+
+
+
+
+
+ maven-compiler-plugin
+ 3.3
+
+ true
+ true
+ 1.8
+ 1.8
+ UTF-8
+ true
+ true
+
+
+
+
+
+
\ No newline at end of file
diff --git a/log4j/src/main/java/com/baeldung/log4j/Log4jExample.java b/log4j/src/main/java/com/baeldung/log4j/Log4jExample.java
new file mode 100644
index 0000000000..e53fdd4881
--- /dev/null
+++ b/log4j/src/main/java/com/baeldung/log4j/Log4jExample.java
@@ -0,0 +1,17 @@
+package com.baeldung.log4j;
+
+
+import org.apache.log4j.Logger;
+
+public class Log4jExample {
+
+ private final static Logger logger = Logger.getLogger(Log4jExample.class);
+
+ public static void main(String[] args) {
+ logger.trace("Trace log message");
+ logger.debug("Debug log message");
+ logger.info("Info log message");
+ logger.error("Error log message");
+ }
+
+}
diff --git a/log4j/src/main/java/com/baeldung/log4j2/Log4j2Example.java b/log4j/src/main/java/com/baeldung/log4j2/Log4j2Example.java
new file mode 100644
index 0000000000..60acc3a774
--- /dev/null
+++ b/log4j/src/main/java/com/baeldung/log4j2/Log4j2Example.java
@@ -0,0 +1,16 @@
+package com.baeldung.log4j2;
+
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.LogManager;
+
+public class Log4j2Example {
+
+ private static final Logger logger = LogManager.getLogger(Log4j2Example.class);
+
+ public static void main(String[] args) {
+ logger.debug("Debug log message");
+ logger.info("Info log message");
+ logger.error("Error log message");
+ }
+
+}
diff --git a/log4j/src/main/java/com/baeldung/logback/LogbackExample.java b/log4j/src/main/java/com/baeldung/logback/LogbackExample.java
new file mode 100644
index 0000000000..536aa78ec9
--- /dev/null
+++ b/log4j/src/main/java/com/baeldung/logback/LogbackExample.java
@@ -0,0 +1,16 @@
+package com.baeldung.logback;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class LogbackExample {
+
+ private static final Logger logger = LoggerFactory.getLogger(LogbackExample.class);
+
+ public static void main(String[] args) {
+ logger.debug("Debug log message");
+ logger.info("Info log message");
+ logger.error("Error log message");
+ }
+
+}
diff --git a/log4j/src/main/resources/log4j.xml b/log4j/src/main/resources/log4j.xml
new file mode 100644
index 0000000000..58a924f970
--- /dev/null
+++ b/log4j/src/main/resources/log4j.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/log4j/src/main/resources/log4j2.xml b/log4j/src/main/resources/log4j2.xml
new file mode 100644
index 0000000000..76a20bcd61
--- /dev/null
+++ b/log4j/src/main/resources/log4j2.xml
@@ -0,0 +1,26 @@
+
+
+
+ # Console appender
+
+ # Pattern of log message for console appender
+
+
+
+ # File appender
+
+ # Pattern of log message for file appender
+
+
+
+
+
+ # Override log level for specified package
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/log4j/src/main/resources/logback.xml b/log4j/src/main/resources/logback.xml
new file mode 100644
index 0000000000..fc66d560aa
--- /dev/null
+++ b/log4j/src/main/resources/logback.xml
@@ -0,0 +1,28 @@
+
+ # Console appender
+
+
+ # Pattern of log message for console appender
+ %d{yyyy-MM-dd HH:mm:ss} %p %m%n
+
+
+
+ # File appender
+
+ # Name of a log file
+ log4j/target/baeldung-logback.log
+ false
+
+ # Pattern of log message for file appender
+ %d{yyyy-MM-dd HH:mm:ss} %p %m%n
+
+
+
+ # Override log level for specified package
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mocks/jmockit/README.md b/mocks/jmockit/README.md
new file mode 100644
index 0000000000..c310463c26
--- /dev/null
+++ b/mocks/jmockit/README.md
@@ -0,0 +1,7 @@
+=========
+
+## JMockit related tutorials
+
+
+### Relevant Articles:
+- [JMockit 101](http://www.baeldung.com/jmockit-101)
diff --git a/mocks/jmockit/pom.xml b/mocks/jmockit/pom.xml
new file mode 100644
index 0000000000..8b03313a51
--- /dev/null
+++ b/mocks/jmockit/pom.xml
@@ -0,0 +1,68 @@
+
+ 4.0.0
+
+
+ com.baeldung
+ mocks
+ 1.0.0-SNAPSHOT
+ ../pom.xml
+
+
+ jmockit
+ jmockit
+
+
+ 4.12
+ 1.24
+
+
+ 3.3
+ 2.18.1
+
+
+
+
+ junit
+ junit
+ ${junit.version}
+ test
+
+
+
+ org.jmockit
+ jmockit
+ ${jmockit.version}
+ test
+
+
+
+
+ jmockit
+
+
+ src/main/resources
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+ 1.8
+ 1.8
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ ${maven-surefire-plugin.version}
+
+
+
+
+
\ No newline at end of file
diff --git a/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/Collaborator.java b/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/Collaborator.java
new file mode 100644
index 0000000000..ef271b9aff
--- /dev/null
+++ b/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/Collaborator.java
@@ -0,0 +1,10 @@
+package org.baeldung.mocks.jmockit;
+
+public class Collaborator {
+ public boolean collaborate(String string){
+ return false;
+ }
+ public void receive(boolean bool){
+ //NOOP
+ }
+}
diff --git a/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/Model.java b/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/Model.java
new file mode 100644
index 0000000000..54249dcd1d
--- /dev/null
+++ b/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/Model.java
@@ -0,0 +1,7 @@
+package org.baeldung.mocks.jmockit;
+
+public class Model {
+ public String getInfo(){
+ return "info";
+ }
+}
diff --git a/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/Performer.java b/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/Performer.java
new file mode 100644
index 0000000000..4f8e8adb24
--- /dev/null
+++ b/mocks/jmockit/src/main/java/org/baeldung/mocks/jmockit/Performer.java
@@ -0,0 +1,10 @@
+package org.baeldung.mocks.jmockit;
+
+public class Performer {
+ private Collaborator collaborator;
+
+ public void perform(Model model){
+ boolean value = collaborator.collaborate(model.getInfo());
+ collaborator.receive(value);
+ }
+}
diff --git a/mocks/jmockit/src/test/java/org/baeldung/mocks/jmockit/PerformerTest.java b/mocks/jmockit/src/test/java/org/baeldung/mocks/jmockit/PerformerTest.java
new file mode 100644
index 0000000000..c99ae844c3
--- /dev/null
+++ b/mocks/jmockit/src/test/java/org/baeldung/mocks/jmockit/PerformerTest.java
@@ -0,0 +1,30 @@
+package org.baeldung.mocks.jmockit;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import mockit.*;
+import mockit.integration.junit4.JMockit;
+
+@RunWith(JMockit.class)
+public class PerformerTest {
+
+ @Injectable
+ private Collaborator collaborator;
+
+ @Tested
+ private Performer performer;
+
+ @Test
+ public void testThePerformMethod(@Mocked Model model) {
+ new Expectations() {{
+ model.getInfo();result = "bar";
+ collaborator.collaborate("bar"); result = true;
+ }};
+ performer.perform(model);
+ new Verifications() {{
+ collaborator.receive(true);
+ }};
+ }
+
+}
diff --git a/mock-comparisons/README.md b/mocks/mock-comparisons/README.md
similarity index 100%
rename from mock-comparisons/README.md
rename to mocks/mock-comparisons/README.md
diff --git a/mock-comparisons/pom.xml b/mocks/mock-comparisons/pom.xml
similarity index 90%
rename from mock-comparisons/pom.xml
rename to mocks/mock-comparisons/pom.xml
index c5424d262d..692bfffd53 100644
--- a/mock-comparisons/pom.xml
+++ b/mocks/mock-comparisons/pom.xml
@@ -1,11 +1,16 @@
4.0.0
- org.baeldung
- mock-comparisons
- 0.1-SNAPSHOT
- mockito
+
+ com.baeldung
+ mocks
+ 1.0.0-SNAPSHOT
+ ../pom.xml
+
+
+ mock-comparisons
+ mock-comparisons
4.12
diff --git a/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginController.java b/mocks/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginController.java
similarity index 100%
rename from mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginController.java
rename to mocks/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginController.java
diff --git a/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginDao.java b/mocks/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginDao.java
similarity index 100%
rename from mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginDao.java
rename to mocks/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginDao.java
diff --git a/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginService.java b/mocks/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginService.java
similarity index 100%
rename from mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginService.java
rename to mocks/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/LoginService.java
diff --git a/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/UserForm.java b/mocks/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/UserForm.java
similarity index 100%
rename from mock-comparisons/src/main/java/org/baeldung/mocks/testCase/UserForm.java
rename to mocks/mock-comparisons/src/main/java/org/baeldung/mocks/testCase/UserForm.java
diff --git a/mock-comparisons/src/test/java/org/baeldung/mocks/easymock/LoginControllerTest.java b/mocks/mock-comparisons/src/test/java/org/baeldung/mocks/easymock/LoginControllerTest.java
similarity index 100%
rename from mock-comparisons/src/test/java/org/baeldung/mocks/easymock/LoginControllerTest.java
rename to mocks/mock-comparisons/src/test/java/org/baeldung/mocks/easymock/LoginControllerTest.java
diff --git a/mock-comparisons/src/test/java/org/baeldung/mocks/jmockit/LoginControllerTest.java b/mocks/mock-comparisons/src/test/java/org/baeldung/mocks/jmockit/LoginControllerTest.java
similarity index 100%
rename from mock-comparisons/src/test/java/org/baeldung/mocks/jmockit/LoginControllerTest.java
rename to mocks/mock-comparisons/src/test/java/org/baeldung/mocks/jmockit/LoginControllerTest.java
diff --git a/mock-comparisons/src/test/java/org/baeldung/mocks/mockito/LoginControllerTest.java b/mocks/mock-comparisons/src/test/java/org/baeldung/mocks/mockito/LoginControllerTest.java
similarity index 100%
rename from mock-comparisons/src/test/java/org/baeldung/mocks/mockito/LoginControllerTest.java
rename to mocks/mock-comparisons/src/test/java/org/baeldung/mocks/mockito/LoginControllerTest.java
diff --git a/mocks/pom.xml b/mocks/pom.xml
new file mode 100644
index 0000000000..ec02c255ef
--- /dev/null
+++ b/mocks/pom.xml
@@ -0,0 +1,20 @@
+
+ 4.0.0
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+ ../pom.xml
+
+
+ mocks
+ mocks
+ pom
+
+
+ mock-comparisons
+ jmockit
+
+
+
diff --git a/mutation-testing/README.md b/mutation-testing/README.md
new file mode 100644
index 0000000000..e1314d98da
--- /dev/null
+++ b/mutation-testing/README.md
@@ -0,0 +1,6 @@
+=========
+
+## Mutation Testing
+
+### Relevant Articles:
+- [Introduction to Mutation Testing Using the PITest Library](http://www.baeldung.com/introduction-to-mutation-testing-with-pitest)
diff --git a/mutation-testing/pom.xml b/mutation-testing/pom.xml
new file mode 100644
index 0000000000..83012ab8fe
--- /dev/null
+++ b/mutation-testing/pom.xml
@@ -0,0 +1,38 @@
+
+ 4.0.0
+ com.baeldung
+ mutation-testing
+ 0.1-SNAPSHOT
+ mutation-testing
+
+
+ org.pitest
+ pitest-parent
+ 1.1.10
+ pom
+
+
+ junit
+ junit
+ 4.9
+
+
+
+
+
+ org.pitest
+ pitest-maven
+ 1.1.10
+
+
+ com.baeldung.testing.mutation.*
+
+
+ com.baeldung.mutation.test.*
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mutation-testing/src/main/java/com/baeldung/testing/mutation/Palindrome.java b/mutation-testing/src/main/java/com/baeldung/testing/mutation/Palindrome.java
new file mode 100644
index 0000000000..0b166f1557
--- /dev/null
+++ b/mutation-testing/src/main/java/com/baeldung/testing/mutation/Palindrome.java
@@ -0,0 +1,15 @@
+package com.baeldung.testing.mutation;
+
+public class Palindrome {
+
+ public boolean isPalindrome(String inputString) {
+ if (inputString.length() == 0) {
+ return true;
+ } else {
+ char firstChar = inputString.charAt(0);
+ char lastChar = inputString.charAt(inputString.length() - 1);
+ String mid = inputString.substring(1, inputString.length() - 1);
+ return (firstChar == lastChar) && isPalindrome(mid);
+ }
+ }
+}
diff --git a/mutation-testing/src/test/java/com/baeldung/mutation/test/TestPalindrome.java b/mutation-testing/src/test/java/com/baeldung/mutation/test/TestPalindrome.java
new file mode 100644
index 0000000000..1410135883
--- /dev/null
+++ b/mutation-testing/src/test/java/com/baeldung/mutation/test/TestPalindrome.java
@@ -0,0 +1,29 @@
+package com.baeldung.mutation.test;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import com.baeldung.testing.mutation.Palindrome;
+
+public class TestPalindrome {
+
+ @Test
+ public void acceptsPalindrome() {
+ Palindrome palindromeTester = new Palindrome();
+ assertTrue(palindromeTester.isPalindrome("noon"));
+ }
+
+ @Test
+ public void rejectsNonPalindrome(){
+ Palindrome palindromeTester = new Palindrome();
+ assertFalse(palindromeTester.isPalindrome("box"));
+ }
+
+ @Test
+ public void rejectsNearPalindrome(){
+ Palindrome palindromeTester = new Palindrome();
+ assertFalse(palindromeTester.isPalindrome("neon"));
+ }
+}
diff --git a/pom.xml b/pom.xml
index 75281ce80d..562aaf896b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,10 +7,14 @@
parent-modules
pom
-
- apache-fop
- assertj
+
+ UTF-8
+
+
+
+ assertj
+ apache-cxf
core-java
core-java-8
gson
@@ -25,13 +29,14 @@
jooq-spring
json-path
mockito
- mock-comparisons
+ mocks
jee7schedule
querydsl
rest-testing
resteasy
+ log4j
spring-all
spring-apache-camel
@@ -74,6 +79,9 @@
xml
lombok
+ redis
+
+ mutation-testing
diff --git a/querydsl/pom.xml b/querydsl/pom.xml
index cf50144d3f..bed0cf90e5 100644
--- a/querydsl/pom.xml
+++ b/querydsl/pom.xml
@@ -14,30 +14,25 @@
UTF-8
- 1.6
- 4.10
- 3.1.0.RELEASE
- 4.3.11.Final
- 2.5.0
- 1.5.10
+ 1.8
+ 4.12
+ 4.3.1.RELEASE
+ 5.2.1.Final
+ 4.1.3
+ 1.7.21
-
- com.mysema.querydsl
- querydsl-core
- ${querydsl.version}
-
- com.mysema.querydsl
+ com.querydsl
querydsl-jpa
${querydsl.version}
- com.mysema.querydsl
+ com.querydsl
querydsl-apt
${querydsl.version}
provided
@@ -53,7 +48,7 @@
org.hibernate.javax.persistence
- hibernate-jpa-2.0-api
+ hibernate-jpa-2.1-api
1.0.0.Final
compile
@@ -69,7 +64,7 @@
commons-pool
commons-pool
- 1.5.5
+ 1.6
jar
compile
@@ -77,8 +72,8 @@
org.hsqldb
- hsqldb-j5
- 2.2.4
+ hsqldb
+ 2.3.4
@@ -118,9 +113,9 @@
- org.slf4j
- slf4j-api
- ${slf4j.version}
+ ch.qos.logback
+ logback-classic
+ 1.1.7
org.slf4j
@@ -128,17 +123,6 @@
${slf4j.version}
runtime
-
- org.slf4j
- slf4j-log4j12
- ${slf4j.version}
- runtime
-
-
- log4j
- log4j
- 1.2.16
-
@@ -157,7 +141,7 @@
org.apache.maven.plugins
maven-compiler-plugin
- 2.3.2
+ 3.5.1
${java.version}
${java.version}
@@ -168,16 +152,16 @@
com.mysema.maven
- maven-apt-plugin
- 1.0.3
+ apt-maven-plugin
+ 1.1.3
process
- target/metamodel
- com.mysema.query.apt.jpa.JPAAnnotationProcessor
+ target/generated-sources/java
+ com.querydsl.apt.jpa.JPAAnnotationProcessor
diff --git a/querydsl/src/main/java/org/baeldung/dao/PersonDaoImpl.java b/querydsl/src/main/java/org/baeldung/dao/PersonDaoImpl.java
index 555ec226ce..9acaf1dd18 100644
--- a/querydsl/src/main/java/org/baeldung/dao/PersonDaoImpl.java
+++ b/querydsl/src/main/java/org/baeldung/dao/PersonDaoImpl.java
@@ -10,8 +10,8 @@ import org.baeldung.entity.Person;
import org.baeldung.entity.QPerson;
import org.springframework.stereotype.Repository;
-import com.mysema.query.group.GroupBy;
-import com.mysema.query.jpa.impl.JPAQuery;
+import com.querydsl.core.group.GroupBy;
+import com.querydsl.jpa.impl.JPAQuery;
@Repository
public class PersonDaoImpl implements PersonDao {
@@ -27,39 +27,39 @@ public class PersonDaoImpl implements PersonDao {
@Override
public List findPersonsByFirstnameQueryDSL(final String firstname) {
- final JPAQuery query = new JPAQuery(em);
+ final JPAQuery query = new JPAQuery<>(em);
final QPerson person = QPerson.person;
- return query.from(person).where(person.firstname.eq(firstname)).list(person);
+ return query.from(person).where(person.firstname.eq(firstname)).fetch();
}
@Override
public List findPersonsByFirstnameAndSurnameQueryDSL(final String firstname, final String surname) {
- final JPAQuery query = new JPAQuery(em);
+ final JPAQuery query = new JPAQuery<>(em);
final QPerson person = QPerson.person;
- return query.from(person).where(person.firstname.eq(firstname).and(person.surname.eq(surname))).list(person);
+ return query.from(person).where(person.firstname.eq(firstname).and(person.surname.eq(surname))).fetch();
}
@Override
public List findPersonsByFirstnameInDescendingOrderQueryDSL(final String firstname) {
- final JPAQuery query = new JPAQuery(em);
+ final JPAQuery query = new JPAQuery<>(em);
final QPerson person = QPerson.person;
- return query.from(person).where(person.firstname.eq(firstname)).orderBy(person.surname.desc()).list(person);
+ return query.from(person).where(person.firstname.eq(firstname)).orderBy(person.surname.desc()).fetch();
}
@Override
public int findMaxAge() {
- final JPAQuery query = new JPAQuery(em);
+ final JPAQuery query = new JPAQuery<>(em);
final QPerson person = QPerson.person;
- return query.from(person).list(person.age.max()).get(0);
+ return query.from(person).select(person.age.max()).fetchFirst();
}
@Override
public Map findMaxAgeByName() {
- final JPAQuery query = new JPAQuery(em);
+ final JPAQuery query = new JPAQuery<>(em);
final QPerson person = QPerson.person;
return query.from(person).transform(GroupBy.groupBy(person.firstname).as(GroupBy.max(person.age)));
diff --git a/querydsl/src/main/java/org/baeldung/querydsl/intro/entities/BlogPost.java b/querydsl/src/main/java/org/baeldung/querydsl/intro/entities/BlogPost.java
new file mode 100644
index 0000000000..241bc50b03
--- /dev/null
+++ b/querydsl/src/main/java/org/baeldung/querydsl/intro/entities/BlogPost.java
@@ -0,0 +1,56 @@
+/*
+ * (c) Центр ИТ, 2016. Все права защищены.
+ */
+package org.baeldung.querydsl.intro.entities;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+
+@Entity
+public class BlogPost {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+
+ private String title;
+
+ private String body;
+
+ @ManyToOne
+ private User user;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String code) {
+ this.title = code;
+ }
+
+ public String getBody() {
+ return body;
+ }
+
+ public void setBody(String body) {
+ this.body = body;
+ }
+
+ public User getUser() {
+ return user;
+ }
+
+ public void setUser(User user) {
+ this.user = user;
+ }
+}
diff --git a/querydsl/src/main/java/org/baeldung/querydsl/intro/entities/User.java b/querydsl/src/main/java/org/baeldung/querydsl/intro/entities/User.java
new file mode 100644
index 0000000000..c0681e15d1
--- /dev/null
+++ b/querydsl/src/main/java/org/baeldung/querydsl/intro/entities/User.java
@@ -0,0 +1,55 @@
+/*
+ * (c) Центр ИТ, 2016. Все права защищены.
+ */
+package org.baeldung.querydsl.intro.entities;
+
+import java.util.HashSet;
+import java.util.Set;
+import javax.persistence.*;
+
+@Entity
+public class User {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+
+ private String login;
+
+ private Boolean disabled;
+
+ @OneToMany(cascade = CascadeType.PERSIST, mappedBy = "user")
+ private Set blogPosts = new HashSet<>(0);
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getLogin() {
+ return login;
+ }
+
+ public void setLogin(String name) {
+ this.login = name;
+ }
+
+ public Set getBlogPosts() {
+ return blogPosts;
+ }
+
+ public void setBlogPosts(Set blogPosts) {
+ this.blogPosts = blogPosts;
+ }
+
+ public Boolean getDisabled() {
+ return disabled;
+ }
+
+ public void setDisabled(Boolean disabled) {
+ this.disabled = disabled;
+ }
+}
diff --git a/querydsl/src/main/resources/META-INF/persistence.xml b/querydsl/src/main/resources/META-INF/persistence.xml
index 111d7933c3..2964382d48 100644
--- a/querydsl/src/main/resources/META-INF/persistence.xml
+++ b/querydsl/src/main/resources/META-INF/persistence.xml
@@ -16,4 +16,17 @@
+
+
+ org.hibernate.jpa.HibernatePersistenceProvider
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/querydsl/src/main/resources/log4j.xml b/querydsl/src/main/resources/logback.xml
similarity index 53%
rename from querydsl/src/main/resources/log4j.xml
rename to querydsl/src/main/resources/logback.xml
index a7f96b38a4..d0a1dc06ac 100644
--- a/querydsl/src/main/resources/log4j.xml
+++ b/querydsl/src/main/resources/logback.xml
@@ -1,12 +1,9 @@
-
-
+
-
-
-
-
-
+
+
+ %d{yyyy-MM-dd HH:mm:ss} [%t] %-5p: %c - %m%n
@@ -33,10 +30,8 @@
-
-
-
-
+
+
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/querydsl/src/test/java/org/baeldung/querydsl/intro/QueryDSLTest.java b/querydsl/src/test/java/org/baeldung/querydsl/intro/QueryDSLTest.java
new file mode 100644
index 0000000000..682fa2c245
--- /dev/null
+++ b/querydsl/src/test/java/org/baeldung/querydsl/intro/QueryDSLTest.java
@@ -0,0 +1,215 @@
+/*
+ * (c) Центр ИТ, 2016. Все права защищены.
+ */
+package org.baeldung.querydsl.intro;
+
+import java.util.List;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+
+import org.baeldung.querydsl.intro.entities.BlogPost;
+import org.baeldung.querydsl.intro.entities.QBlogPost;
+import org.baeldung.querydsl.intro.entities.QUser;
+import org.baeldung.querydsl.intro.entities.User;
+import com.querydsl.core.Tuple;
+import com.querydsl.core.types.dsl.Expressions;
+import com.querydsl.core.types.dsl.NumberPath;
+import com.querydsl.jpa.JPAExpressions;
+import com.querydsl.jpa.impl.JPAQueryFactory;
+import org.junit.*;
+
+import static org.junit.Assert.*;
+
+public class QueryDSLTest {
+
+ private static EntityManagerFactory emf;
+
+ private EntityManager em;
+
+ private JPAQueryFactory queryFactory;
+
+ @BeforeClass
+ public static void populateDatabase() {
+ emf = Persistence.createEntityManagerFactory("org.baeldung.querydsl.intro");
+ EntityManager em = emf.createEntityManager();
+
+ em.getTransaction().begin();
+ User user1 = new User();
+ user1.setLogin("David");
+ em.persist(user1);
+
+ User user2 = new User();
+ user2.setLogin("Ash");
+ em.persist(user2);
+
+ User user3 = new User();
+ user3.setLogin("Call");
+ em.persist(user3);
+
+ User user4 = new User();
+ user4.setLogin("Bishop");
+ em.persist(user4);
+
+ BlogPost blogPost1 = new BlogPost();
+ blogPost1.setTitle("Hello World!");
+ blogPost1.setUser(user1);
+ em.persist(blogPost1);
+
+ BlogPost blogPost2 = new BlogPost();
+ blogPost2.setTitle("My Second Post");
+ blogPost2.setUser(user1);
+ em.persist(blogPost2);
+
+ BlogPost blogPost3 = new BlogPost();
+ blogPost3.setTitle("Hello World!");
+ blogPost3.setUser(user3);
+ em.persist(blogPost3);
+
+ em.getTransaction().commit();
+
+ em.close();
+
+ }
+
+ @Before
+ public void setUp() {
+ em = emf.createEntityManager();
+ em.getTransaction().begin();
+ queryFactory = new JPAQueryFactory(em);
+ }
+
+ @Test
+ public void whenFindByLogin_thenShouldReturnUser() {
+
+ QUser user = QUser.user;
+ User aUser = queryFactory.selectFrom(user)
+ .where(user.login.eq("David"))
+ .fetchOne();
+
+ assertNotNull(aUser);
+ assertEquals(aUser.getLogin(), "David");
+
+ }
+
+ @Test
+ public void whenUsingOrderBy_thenResultsShouldBeOrdered() {
+
+ QUser user = QUser.user;
+ List users = queryFactory.selectFrom(user)
+ .orderBy(user.login.asc())
+ .fetch();
+
+ assertEquals(users.size(), 4);
+ assertEquals(users.get(0).getLogin(), "Ash");
+ assertEquals(users.get(1).getLogin(), "Bishop");
+ assertEquals(users.get(2).getLogin(), "Call");
+ assertEquals(users.get(3).getLogin(), "David");
+
+ }
+
+ @Test
+ public void whenGroupingByTitle_thenReturnsTuples() {
+
+ QBlogPost blogPost = QBlogPost.blogPost;
+
+ NumberPath count = Expressions.numberPath(Long.class, "c");
+
+ List userTitleCounts = queryFactory.select(blogPost.title, blogPost.id.count().as(count))
+ .from(blogPost)
+ .groupBy(blogPost.title)
+ .orderBy(count.desc())
+ .fetch();
+
+ assertEquals("Hello World!", userTitleCounts.get(0).get(blogPost.title));
+ assertEquals(new Long(2), userTitleCounts.get(0).get(count));
+
+ assertEquals("My Second Post", userTitleCounts.get(1).get(blogPost.title));
+ assertEquals(new Long(1), userTitleCounts.get(1).get(count));
+
+ }
+
+ @Test
+ public void whenJoiningWithCondition_thenResultCountShouldMatch() {
+
+ QUser user = QUser.user;
+ QBlogPost blogPost = QBlogPost.blogPost;
+
+ List users = queryFactory.selectFrom(user)
+ .innerJoin(user.blogPosts, blogPost)
+ .on(blogPost.title.eq("Hello World!"))
+ .fetch();
+
+ assertEquals(2, users.size());
+ }
+
+ @Test
+ public void whenRefiningWithSubquery_thenResultCountShouldMatch() {
+
+ QUser user = QUser.user;
+ QBlogPost blogPost = QBlogPost.blogPost;
+
+ List users = queryFactory.selectFrom(user)
+ .where(user.id.in(
+ JPAExpressions.select(blogPost.user.id)
+ .from(blogPost)
+ .where(blogPost.title.eq("Hello World!"))))
+ .fetch();
+
+ assertEquals(2, users.size());
+ }
+
+ @Test
+ public void whenUpdating_thenTheRecordShouldChange() {
+
+ QUser user = QUser.user;
+
+ queryFactory.update(user)
+ .where(user.login.eq("Ash"))
+ .set(user.login, "Ash2")
+ .set(user.disabled, true)
+ .execute();
+
+ em.getTransaction().commit();
+
+ em.getTransaction().begin();
+
+ assertEquals(Boolean.TRUE,
+ queryFactory.select(user.disabled)
+ .from(user)
+ .where(user.login.eq("Ash2"))
+ .fetchOne());
+
+ }
+
+ @Test
+ public void whenDeleting_thenTheRecordShouldBeAbsent() {
+
+ QUser user = QUser.user;
+
+ queryFactory.delete(user)
+ .where(user.login.eq("Bishop"))
+ .execute();
+
+ em.getTransaction().commit();
+
+ em.getTransaction().begin();
+
+ assertNull(queryFactory.selectFrom(user)
+ .where(user.login.eq("Bishop"))
+ .fetchOne());
+
+ }
+
+ @After
+ public void tearDown() {
+ em.getTransaction().commit();
+ em.close();
+ }
+
+ @AfterClass
+ public static void afterClass() {
+ emf.close();
+ }
+
+}
diff --git a/redis/pom.xml b/redis/pom.xml
new file mode 100644
index 0000000000..ad073a66d0
--- /dev/null
+++ b/redis/pom.xml
@@ -0,0 +1,57 @@
+
+
+
+ 4.0.0
+ com.baeldung
+ redis
+ 0.1-SNAPSHOT
+
+ redis
+ http://maven.apache.org
+
+
+
+ redis.clients
+ jedis
+ 2.8.1
+
+
+
+ com.github.kstyrc
+ embedded-redis
+ 0.6
+
+
+
+ junit
+ junit
+ ${junit.version}
+ test
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.5.1
+
+ 1.8
+ 1.8
+
+
+
+
+
+
+
+ UTF-8
+
+
+ 4.12
+
+
diff --git a/redis/src/test/java/com/baeldung/JedisTest.java b/redis/src/test/java/com/baeldung/JedisTest.java
new file mode 100644
index 0000000000..766fd7b5e9
--- /dev/null
+++ b/redis/src/test/java/com/baeldung/JedisTest.java
@@ -0,0 +1,225 @@
+package com.baeldung;
+
+import java.io.IOException;
+import java.time.Duration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.JedisPool;
+import redis.clients.jedis.JedisPoolConfig;
+import redis.clients.jedis.Pipeline;
+import redis.clients.jedis.Response;
+import redis.clients.jedis.Transaction;
+import redis.embedded.RedisServer;
+
+/**
+ * Unit test for Redis Java library - Jedis.
+ */
+public class JedisTest {
+
+ private Jedis jedis;
+ private static RedisServer redisServer;
+
+ public JedisTest() {
+ jedis = new Jedis();
+ }
+
+ @BeforeClass
+ public static void setUp() throws IOException {
+ redisServer = new RedisServer(6379);
+ redisServer.start();
+ }
+
+ @AfterClass
+ public static void destroy() {
+ redisServer.stop();
+ }
+
+ @After
+ public void flush() {
+ jedis.flushAll();
+ }
+
+ @Test
+ public void givenAString_thenSaveItAsRedisStrings() {
+ String key = "key";
+ String value = "value";
+
+ jedis.set(key, value);
+ String value2 = jedis.get(key);
+
+ Assert.assertEquals(value, value2);
+ }
+
+ @Test
+ public void givenListElements_thenSaveThemInRedisList() {
+ String queue = "queue#tasks";
+
+ String taskOne = "firstTask";
+ String taskTwo = "secondTask";
+ String taskThree = "thirdTask";
+
+ jedis.lpush(queue, taskOne, taskTwo);
+
+ String taskReturnedOne = jedis.rpop(queue);
+
+ jedis.lpush(queue, taskThree);
+ Assert.assertEquals(taskOne, taskReturnedOne);
+
+ String taskReturnedTwo = jedis.rpop(queue);
+ String taskReturnedThree = jedis.rpop(queue);
+
+ Assert.assertEquals(taskTwo, taskReturnedTwo);
+ Assert.assertEquals(taskThree, taskReturnedThree);
+
+ String taskReturnedFour = jedis.rpop(queue);
+ Assert.assertNull(taskReturnedFour);
+ }
+
+ @Test
+ public void givenSetElements_thenSaveThemInRedisSet() {
+ String countries = "countries";
+
+ String countryOne = "Spain";
+ String countryTwo = "Ireland";
+ String countryThree = "Ireland";
+
+ jedis.sadd(countries, countryOne);
+
+ Set countriesSet = jedis.smembers(countries);
+ Assert.assertEquals(1, countriesSet.size());
+
+ jedis.sadd(countries, countryTwo);
+ countriesSet = jedis.smembers(countries);
+ Assert.assertEquals(2, countriesSet.size());
+
+ jedis.sadd(countries, countryThree);
+ countriesSet = jedis.smembers(countries);
+ Assert.assertEquals(2, countriesSet.size());
+
+ boolean exists = jedis.sismember(countries, countryThree);
+ Assert.assertTrue(exists);
+ }
+
+ @Test
+ public void givenObjectFields_thenSaveThemInRedisHash() {
+ String key = "user#1";
+
+ String field = "name";
+ String value = "William";
+
+ String field2 = "job";
+ String value2 = "politician";
+
+ jedis.hset(key, field, value);
+ jedis.hset(key, field2, value2);
+
+ String value3 = jedis.hget(key, field);
+ Assert.assertEquals(value, value3);
+
+ Map fields = jedis.hgetAll(key);
+ String value4 = fields.get(field2);
+ Assert.assertEquals(value2, value4);
+ }
+
+ @Test
+ public void givenARanking_thenSaveItInRedisSortedSet() {
+ String key = "ranking";
+
+ Map scores = new HashMap<>();
+
+ scores.put("PlayerOne", 3000.0);
+ scores.put("PlayerTwo", 1500.0);
+ scores.put("PlayerThree", 8200.0);
+
+ for (String player : scores.keySet()) {
+ jedis.zadd(key, scores.get(player), player);
+ }
+
+ Set players = jedis.zrevrange(key, 0, 1);
+ Assert.assertEquals("PlayerThree", players.iterator().next());
+
+ long rank = jedis.zrevrank(key, "PlayerOne");
+ Assert.assertEquals(1, rank);
+ }
+
+ @Test
+ public void givenMultipleOperationsThatNeedToBeExecutedAtomically_thenWrapThemInATransaction() {
+ String friendsPrefix = "friends#";
+
+ String userOneId = "4352523";
+ String userTwoId = "5552321";
+
+ Transaction t = jedis.multi();
+ t.sadd(friendsPrefix + userOneId, userTwoId);
+ t.sadd(friendsPrefix + userTwoId, userOneId);
+ t.exec();
+
+ boolean exists = jedis.sismember(friendsPrefix + userOneId, userTwoId);
+ Assert.assertTrue(exists);
+
+ exists = jedis.sismember(friendsPrefix + userTwoId, userOneId);
+ Assert.assertTrue(exists);
+ }
+
+ @Test
+ public void givenMultipleIndependentOperations_whenNetworkOptimizationIsImportant_thenWrapThemInAPipeline() {
+ String userOneId = "4352523";
+ String userTwoId = "4849888";
+
+ Pipeline p = jedis.pipelined();
+ p.sadd("searched#" + userOneId, "paris");
+ p.zadd("ranking", 126, userOneId);
+ p.zadd("ranking", 325, userTwoId);
+ Response pipeExists = p.sismember("searched#" + userOneId, "paris");
+ Response> pipeRanking = p.zrange("ranking", 0, -1);
+ p.sync();
+
+ Assert.assertTrue(pipeExists.get());
+ Assert.assertEquals(2, pipeRanking.get().size());
+ }
+
+ @Test
+ public void givenAPoolConfiguration_thenCreateAJedisPool() {
+ final JedisPoolConfig poolConfig = buildPoolConfig();
+
+ try (JedisPool jedisPool = new JedisPool(poolConfig, "localhost"); Jedis jedis = jedisPool.getResource()) {
+
+ // do simple operation to verify that the Jedis resource is working
+ // properly
+ String key = "key";
+ String value = "value";
+
+ jedis.set(key, value);
+ String value2 = jedis.get(key);
+
+ Assert.assertEquals(value, value2);
+
+ // flush Redis
+ jedis.flushAll();
+ }
+ }
+
+ private JedisPoolConfig buildPoolConfig() {
+ final JedisPoolConfig poolConfig = new JedisPoolConfig();
+ poolConfig.setMaxTotal(128);
+ poolConfig.setMaxIdle(128);
+ poolConfig.setMinIdle(16);
+ poolConfig.setTestOnBorrow(true);
+ poolConfig.setTestOnReturn(true);
+ poolConfig.setTestWhileIdle(true);
+ poolConfig.setMinEvictableIdleTimeMillis(Duration.ofSeconds(60).toMillis());
+ poolConfig.setTimeBetweenEvictionRunsMillis(Duration.ofSeconds(30).toMillis());
+ poolConfig.setNumTestsPerEvictionRun(3);
+ poolConfig.setBlockWhenExhausted(true);
+ return poolConfig;
+ }
+}
diff --git a/spring-all/src/main/java/org/baeldung/properties/spring/PropertiesWithPlaceHolderConfigurer.java b/spring-all/src/main/java/org/baeldung/properties/spring/PropertiesWithPlaceHolderConfigurer.java
new file mode 100644
index 0000000000..f96184a8a3
--- /dev/null
+++ b/spring-all/src/main/java/org/baeldung/properties/spring/PropertiesWithPlaceHolderConfigurer.java
@@ -0,0 +1,22 @@
+package org.baeldung.properties.spring;
+
+import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class PropertiesWithPlaceHolderConfigurer {
+
+ public PropertiesWithPlaceHolderConfigurer() {
+ super();
+ }
+
+
+ @Bean
+ public PropertyPlaceholderConfigurer propertyConfigurer() {
+ final PropertyPlaceholderConfigurer props = new PropertyPlaceholderConfigurer();
+ props.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_FALLBACK);
+ return props;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot/.classpath b/spring-boot/.classpath
deleted file mode 100644
index 26981b6dd7..0000000000
--- a/spring-boot/.classpath
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/spring-boot/.gitignore b/spring-boot/.gitignore
index 24d64373c4..e26d6af438 100644
--- a/spring-boot/.gitignore
+++ b/spring-boot/.gitignore
@@ -1 +1,4 @@
/target/
+.settings/
+.classpath
+.project
diff --git a/spring-boot/.project b/spring-boot/.project
deleted file mode 100644
index e748dc5713..0000000000
--- a/spring-boot/.project
+++ /dev/null
@@ -1,48 +0,0 @@
-
-
- spring-boot
-
-
-
-
-
- org.eclipse.wst.jsdt.core.javascriptValidator
-
-
-
-
- org.eclipse.jdt.core.javabuilder
-
-
-
-
- org.eclipse.wst.common.project.facet.core.builder
-
-
-
-
- org.eclipse.wst.validation.validationbuilder
-
-
-
-
- org.springframework.ide.eclipse.core.springbuilder
-
-
-
-
- org.eclipse.m2e.core.maven2Builder
-
-
-
-
-
- org.springframework.ide.eclipse.core.springnature
- org.eclipse.jem.workbench.JavaEMFNature
- org.eclipse.wst.common.modulecore.ModuleCoreNature
- org.eclipse.jdt.core.javanature
- org.eclipse.m2e.core.maven2Nature
- org.eclipse.wst.common.project.facet.core.nature
- org.eclipse.wst.jsdt.core.jsNature
-
-
diff --git a/spring-boot/pom.xml b/spring-boot/pom.xml
index d0a66197bf..368dfa19c1 100644
--- a/spring-boot/pom.xml
+++ b/spring-boot/pom.xml
@@ -1,4 +1,5 @@
-
+
4.0.0
com.baeldung
spring-boot
@@ -11,15 +12,29 @@
org.springframework.boot
spring-boot-starter-parent
- 1.3.3.RELEASE
+ 1.3.6.RELEASE
+
+
+
+ org.baeldung.boot.DemoApplication
+ UTF-8
+ 1.8
+
+
+
org.springframework.boot
spring-boot-starter-web
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
org.springframework.boot
spring-boot-starter-actuator
@@ -34,6 +49,17 @@
io.dropwizard.metrics
metrics-core
+
+
+ com.h2database
+ h2
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
@@ -70,4 +96,4 @@
-
\ No newline at end of file
+
diff --git a/spring-boot/src/main/java/org/baeldung/boot/DemoApplication.java b/spring-boot/src/main/java/org/baeldung/boot/DemoApplication.java
new file mode 100644
index 0000000000..e61d140396
--- /dev/null
+++ b/spring-boot/src/main/java/org/baeldung/boot/DemoApplication.java
@@ -0,0 +1,14 @@
+package org.baeldung.boot;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class DemoApplication {
+
+ public static void main(String[] args) {
+ System.setProperty("spring.config.name", "demo");
+ SpringApplication.run(DemoApplication.class, args);
+ }
+
+}
diff --git a/spring-boot/src/main/java/org/baeldung/boot/model/Foo.java b/spring-boot/src/main/java/org/baeldung/boot/model/Foo.java
new file mode 100644
index 0000000000..6a36459e3c
--- /dev/null
+++ b/spring-boot/src/main/java/org/baeldung/boot/model/Foo.java
@@ -0,0 +1,39 @@
+package org.baeldung.boot.model;
+
+import java.io.Serializable;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+@Entity
+public class Foo implements Serializable {
+ private static final long serialVersionUID = 1L;
+ @Id
+ @GeneratedValue
+ private Integer id;
+ private String name;
+
+ public Foo() {
+ }
+
+ public Foo(String name) {
+ this.name = name;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/spring-boot/src/main/java/org/baeldung/boot/repository/FooRepository.java b/spring-boot/src/main/java/org/baeldung/boot/repository/FooRepository.java
new file mode 100644
index 0000000000..09d6975dba
--- /dev/null
+++ b/spring-boot/src/main/java/org/baeldung/boot/repository/FooRepository.java
@@ -0,0 +1,8 @@
+package org.baeldung.boot.repository;
+
+import org.baeldung.boot.model.Foo;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface FooRepository extends JpaRepository {
+ public Foo findByName(String name);
+}
diff --git a/spring-boot/src/main/resources/demo.properties b/spring-boot/src/main/resources/demo.properties
new file mode 100644
index 0000000000..649b64f59b
--- /dev/null
+++ b/spring-boot/src/main/resources/demo.properties
@@ -0,0 +1,6 @@
+spring.output.ansi.enabled=never
+server.port=7070
+
+# Security
+security.user.name=admin
+security.user.password=password
\ No newline at end of file
diff --git a/spring-boot/src/test/java/org/baeldung/boot/DemoApplicationTests.java b/spring-boot/src/test/java/org/baeldung/boot/DemoApplicationTests.java
new file mode 100644
index 0000000000..41c5a545cc
--- /dev/null
+++ b/spring-boot/src/test/java/org/baeldung/boot/DemoApplicationTests.java
@@ -0,0 +1,17 @@
+package org.baeldung.boot;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.SpringApplicationConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.web.WebAppConfiguration;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@SpringApplicationConfiguration(classes = DemoApplication.class)
+@WebAppConfiguration
+public class DemoApplicationTests {
+
+ @Test
+ public void contextLoads() {
+ }
+}
diff --git a/spring-boot/src/test/java/org/baeldung/boot/repository/FooRepositoryTest.java b/spring-boot/src/test/java/org/baeldung/boot/repository/FooRepositoryTest.java
new file mode 100644
index 0000000000..9de7790a75
--- /dev/null
+++ b/spring-boot/src/test/java/org/baeldung/boot/repository/FooRepositoryTest.java
@@ -0,0 +1,34 @@
+package org.baeldung.boot.repository;
+
+import static org.junit.Assert.assertThat;
+
+import org.baeldung.boot.DemoApplicationTests;
+import org.baeldung.boot.model.Foo;
+
+import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.Matchers.is;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class FooRepositoryTest extends DemoApplicationTests {
+ @Autowired
+ private FooRepository fooRepository;
+
+ @Before
+ public void setUp() {
+ fooRepository.save(new Foo("Foo"));
+ fooRepository.save(new Foo("Bar"));
+ }
+
+ @Test
+ public void testFindByName() {
+ Foo foo = fooRepository.findByName("Bar");
+ assertThat(foo, notNullValue());
+ assertThat(foo.getId(), is(2));
+ }
+
+}
diff --git a/spring-hibernate4/README.md b/spring-hibernate4/README.md
index 4c0c6706d6..1f18e1d0e8 100644
--- a/spring-hibernate4/README.md
+++ b/spring-hibernate4/README.md
@@ -8,7 +8,8 @@
- [Hibernate Pagination](http://www.baeldung.com/hibernate-pagination)
- [Sorting with Hibernate](http://www.baeldung.com/hibernate-sort)
- [Auditing with JPA, Hibernate, and Spring Data JPA](http://www.baeldung.com/database-auditing-jpa)
-
+- [Stored Procedures with Hibernate](http://www.baeldung.com/stored-procedures-with-hibernate-tutorial)
+- [Hibernate: save, persist, update, merge, saveOrUpdate](http://www.baeldung.com/hibernate-save-persist-update-merge-saveorupdate/)
### Quick Start
diff --git a/spring-hibernate4/pom.xml b/spring-hibernate4/pom.xml
index 3652674614..4f5cd0c290 100644
--- a/spring-hibernate4/pom.xml
+++ b/spring-hibernate4/pom.xml
@@ -149,6 +149,13 @@
test
+
+ org.hsqldb
+ hsqldb
+ 2.3.4
+ test
+
+
diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Foo.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Foo.java
index 6b48c1fa66..bdd48d6aa6 100644
--- a/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Foo.java
+++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Foo.java
@@ -11,93 +11,97 @@ import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
+import javax.persistence.NamedNativeQueries;
+import javax.persistence.NamedNativeQuery;
import org.hibernate.envers.Audited;
+@NamedNativeQueries({
+ @NamedNativeQuery(name = "callGetAllFoos", query = "CALL GetAllFoos()", resultClass = Foo.class),
+ @NamedNativeQuery(name = "callGetFoosByName", query = "CALL GetFoosByName(:fooName)", resultClass = Foo.class) })
@Entity
@Audited
// @Proxy(lazy = false)
public class Foo implements Serializable {
- @Id
- @GeneratedValue(strategy = GenerationType.AUTO)
- @Column(name = "id")
- private long id;
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ @Column(name = "id")
+ private long id;
- @Column(name = "name")
- private String name;
+ @Column(name = "name")
+ private String name;
- @ManyToOne(targetEntity = Bar.class, cascade = CascadeType.ALL, fetch = FetchType.EAGER)
- @JoinColumn(name = "BAR_ID")
- private Bar bar = new Bar();
+ @ManyToOne(targetEntity = Bar.class, cascade = CascadeType.ALL, fetch = FetchType.EAGER)
+ @JoinColumn(name = "BAR_ID")
+ private Bar bar = new Bar();
- public Foo() {
- super();
- }
+ public Foo() {
+ super();
+ }
- public Foo(final String name) {
- super();
- this.name = name;
- }
+ public Foo(final String name) {
+ super();
+ this.name = name;
+ }
- //
+ //
- public Bar getBar() {
- return bar;
- }
+ public Bar getBar() {
+ return bar;
+ }
- public void setBar(final Bar bar) {
- this.bar = bar;
- }
+ public void setBar(final Bar bar) {
+ this.bar = bar;
+ }
- public long getId() {
- return id;
- }
+ public long getId() {
+ return id;
+ }
- public void setId(final long id) {
- this.id = id;
- }
+ public void setId(final long id) {
+ this.id = id;
+ }
- public String getName() {
- return name;
- }
+ public String getName() {
+ return name;
+ }
- public void setName(final String name) {
- this.name = name;
- }
+ public void setName(final String name) {
+ this.name = name;
+ }
- //
+ //
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((name == null) ? 0 : name.hashCode());
- return result;
- }
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
- @Override
- public boolean equals(final Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- final Foo other = (Foo) obj;
- if (name == null) {
- if (other.name != null)
- return false;
- } else if (!name.equals(other.name))
- return false;
- return true;
- }
-
- @Override
- public String toString() {
- final StringBuilder builder = new StringBuilder();
- builder.append("Foo [name=").append(name).append("]");
- return builder.toString();
- }
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final Foo other = (Foo) obj;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ return true;
+ }
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("Foo [name=").append(name).append("]");
+ return builder.toString();
+ }
}
diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Person.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Person.java
new file mode 100644
index 0000000000..6a95a7acf5
--- /dev/null
+++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Person.java
@@ -0,0 +1,31 @@
+package com.baeldung.persistence.model;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+@Entity
+public class Person {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+
+ private String name;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/spring-hibernate4/src/main/resources/stored_procedure.sql b/spring-hibernate4/src/main/resources/stored_procedure.sql
new file mode 100644
index 0000000000..8e1bdf57dd
--- /dev/null
+++ b/spring-hibernate4/src/main/resources/stored_procedure.sql
@@ -0,0 +1,20 @@
+DELIMITER //
+ CREATE PROCEDURE GetFoosByName(IN fooName VARCHAR(255))
+ LANGUAGE SQL
+ DETERMINISTIC
+ SQL SECURITY DEFINER
+ BEGIN
+ SELECT * FROM foo WHERE name = fooName;
+ END //
+DELIMITER ;
+
+
+DELIMITER //
+ CREATE PROCEDURE GetAllFoos()
+ LANGUAGE SQL
+ DETERMINISTIC
+ SQL SECURITY DEFINER
+ BEGIN
+ SELECT * FROM foo;
+ END //
+DELIMITER ;
\ No newline at end of file
diff --git a/spring-hibernate4/src/test/java/com/baeldung/persistence/save/SaveMethodsTest.java b/spring-hibernate4/src/test/java/com/baeldung/persistence/save/SaveMethodsTest.java
new file mode 100644
index 0000000000..aadaefbe44
--- /dev/null
+++ b/spring-hibernate4/src/test/java/com/baeldung/persistence/save/SaveMethodsTest.java
@@ -0,0 +1,272 @@
+package com.baeldung.persistence.save;
+
+
+import com.baeldung.persistence.model.Person;
+import org.hibernate.HibernateException;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.dialect.HSQLDialect;
+import org.hibernate.service.ServiceRegistry;
+import org.junit.*;
+
+import static org.junit.Assert.*;
+
+/**
+ * Testing specific implementation details for different methods:
+ * persist, save, merge, update, saveOrUpdate.
+ */
+public class SaveMethodsTest {
+
+ private static SessionFactory sessionFactory;
+
+ private Session session;
+
+ @BeforeClass
+ public static void beforeTests() {
+ Configuration configuration = new Configuration()
+ .addAnnotatedClass(Person.class)
+ .setProperty("hibernate.dialect", HSQLDialect.class.getName())
+ .setProperty("hibernate.connection.driver_class", org.hsqldb.jdbcDriver.class.getName())
+ .setProperty("hibernate.connection.url", "jdbc:hsqldb:mem:test")
+ .setProperty("hibernate.connection.username", "sa")
+ .setProperty("hibernate.connection.password", "")
+ .setProperty("hibernate.hbm2ddl.auto", "update");
+ ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(
+ configuration.getProperties()).build();
+ sessionFactory = configuration.buildSessionFactory(serviceRegistry);
+ }
+
+ @Before
+ public void setUp() {
+ session = sessionFactory.openSession();
+ session.beginTransaction();
+ }
+
+
+ @Test
+ public void whenPersistTransient_thenSavedToDatabaseOnCommit() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.persist(person);
+
+ session.getTransaction().commit();
+ session.close();
+
+ session = sessionFactory.openSession();
+ session.beginTransaction();
+
+ assertNotNull(session.get(Person.class, person.getId()));
+
+ }
+
+ @Test
+ public void whenPersistPersistent_thenNothingHappens() {
+
+ Person person = new Person();
+ person.setName("John");
+
+ session.persist(person);
+ Long id1 = person.getId();
+
+ session.persist(person);
+ Long id2 = person.getId();
+
+ assertEquals(id1, id2);
+ }
+
+ @Test(expected = HibernateException.class)
+ public void whenPersistDetached_thenThrowsException() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.persist(person);
+ session.evict(person);
+
+ session.persist(person);
+
+ }
+
+ @Test
+ public void whenSaveTransient_thenIdGeneratedImmediately() {
+
+ Person person = new Person();
+ person.setName("John");
+
+ assertNull(person.getId());
+
+ Long id = (Long) session.save(person);
+
+ assertNotNull(id);
+
+ session.getTransaction().commit();
+ session.close();
+
+ assertEquals(id, person.getId());
+
+ session = sessionFactory.openSession();
+ session.beginTransaction();
+
+ assertNotNull(session.get(Person.class, person.getId()));
+
+ }
+
+ @Test
+ public void whenSavePersistent_thenNothingHappens() {
+
+ Person person = new Person();
+ person.setName("John");
+ Long id1 = (Long) session.save(person);
+ Long id2 = (Long) session.save(person);
+ assertEquals(id1, id2);
+
+ }
+
+ @Test
+ public void whenSaveDetached_thenNewInstancePersisted() {
+
+ Person person = new Person();
+ person.setName("John");
+ Long id1 = (Long) session.save(person);
+ session.evict(person);
+
+ Long id2 = (Long) session.save(person);
+ assertNotEquals(id1, id2);
+
+ }
+
+ @Test
+ public void whenMergeDetached_thenEntityUpdatedFromDatabase() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.save(person);
+ session.evict(person);
+
+ person.setName("Mary");
+ Person mergedPerson = (Person) session.merge(person);
+
+ assertNotSame(person, mergedPerson);
+ assertEquals("Mary", mergedPerson.getName());
+
+ }
+
+ @Test
+ public void whenMergeTransient_thenNewEntitySavedToDatabase() {
+
+ Person person = new Person();
+ person.setName("John");
+ Person mergedPerson = (Person) session.merge(person);
+
+ session.getTransaction().commit();
+ session.beginTransaction();
+
+ assertNull(person.getId());
+ assertNotNull(mergedPerson.getId());
+
+ }
+
+ @Test
+ public void whenMergePersistent_thenReturnsSameObject() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.save(person);
+
+ Person mergedPerson = (Person) session.merge(person);
+
+ assertSame(person, mergedPerson);
+
+ }
+
+ @Test
+ public void whenUpdateDetached_thenEntityUpdatedFromDatabase() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.save(person);
+ session.evict(person);
+
+ person.setName("Mary");
+ session.update(person);
+ assertEquals("Mary", person.getName());
+
+ }
+
+ @Test(expected = HibernateException.class)
+ public void whenUpdateTransient_thenThrowsException() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.update(person);
+
+ }
+
+ @Test
+ public void whenUpdatePersistent_thenNothingHappens() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.save(person);
+
+ session.update(person);
+
+ }
+
+ @Test
+ public void whenSaveOrUpdateDetached_thenEntityUpdatedFromDatabase() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.save(person);
+ session.evict(person);
+
+ person.setName("Mary");
+ session.saveOrUpdate(person);
+ assertEquals("Mary", person.getName());
+
+ }
+
+ @Test
+ public void whenSaveOrUpdateTransient_thenSavedToDatabaseOnCommit() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.saveOrUpdate(person);
+
+ session.getTransaction().commit();
+ session.close();
+
+ session = sessionFactory.openSession();
+ session.beginTransaction();
+
+ assertNotNull(session.get(Person.class, person.getId()));
+
+
+ }
+
+ @Test
+ public void whenSaveOrUpdatePersistent_thenNothingHappens() {
+
+ Person person = new Person();
+ person.setName("John");
+ session.save(person);
+
+ session.saveOrUpdate(person);
+
+ }
+
+ @After
+ public void tearDown() {
+ session.getTransaction().commit();
+ session.close();
+ }
+
+ @AfterClass
+ public static void afterTests() {
+ sessionFactory.close();
+ }
+
+}
diff --git a/spring-hibernate4/src/test/java/com/baeldung/persistence/service/FooStoredProceduresIntegrationTest.java b/spring-hibernate4/src/test/java/com/baeldung/persistence/service/FooStoredProceduresIntegrationTest.java
new file mode 100644
index 0000000000..238b228101
--- /dev/null
+++ b/spring-hibernate4/src/test/java/com/baeldung/persistence/service/FooStoredProceduresIntegrationTest.java
@@ -0,0 +1,126 @@
+package com.baeldung.persistence.service;
+
+import java.util.List;
+
+import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
+import static org.junit.Assert.assertEquals;
+
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.exception.SQLGrammarException;
+import org.junit.After;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+import com.baeldung.persistence.model.Foo;
+import com.baeldung.spring.PersistenceConfig;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = {PersistenceConfig.class}, loader = AnnotationConfigContextLoader.class)
+public class FooStoredProceduresIntegrationTest {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(FooStoredProceduresIntegrationTest.class);
+
+ @Autowired
+ private SessionFactory sessionFactory;
+
+ @Autowired
+ private IFooService fooService;
+
+ private Session session;
+
+ @Before
+ public final void before() {
+ session = sessionFactory.openSession();
+ Assume.assumeTrue(getAllFoosExists());
+ Assume.assumeTrue(getFoosByNameExists());
+ }
+
+ private boolean getFoosByNameExists() {
+ try {
+ Query sqlQuery = session.createSQLQuery("CALL GetAllFoos()")
+ .addEntity(Foo.class);
+ sqlQuery.list();
+ return true;
+ } catch (SQLGrammarException e) {
+ LOGGER.error("WARNING : GetFoosByName() Procedure is may be missing ", e);
+ return false;
+ }
+ }
+
+ private boolean getAllFoosExists() {
+ try {
+ Query sqlQuery = session.createSQLQuery("CALL GetAllFoos()")
+ .addEntity(Foo.class);
+ sqlQuery.list();
+ return true;
+ } catch (SQLGrammarException e) {
+ LOGGER.error("WARNING : GetAllFoos() Procedure is may be missing ", e);
+ return false;
+ }
+ }
+
+ @After
+ public final void after() {
+ session.close();
+ }
+
+ @Test
+ public final void getAllFoosUsingStoredProcedures() {
+
+ fooService.create(new Foo(randomAlphabetic(6)));
+
+ // Stored procedure getAllFoos using createSQLQuery
+ Query sqlQuery = session.createSQLQuery("CALL GetAllFoos()").addEntity(
+ Foo.class);
+ @SuppressWarnings("unchecked")
+ List allFoos = sqlQuery.list();
+ for (Foo foo : allFoos) {
+ LOGGER.info("getAllFoos() SQL Query result : {}", foo.getName());
+ }
+ assertEquals(allFoos.size(), fooService.findAll().size());
+
+ // Stored procedure getAllFoos using a Named Query
+ Query namedQuery = session.getNamedQuery("callGetAllFoos");
+ @SuppressWarnings("unchecked")
+ List allFoos2 = namedQuery.list();
+ for (Foo foo : allFoos2) {
+ LOGGER.info("getAllFoos() NamedQuery result : {}", foo.getName());
+ }
+ assertEquals(allFoos2.size(), fooService.findAll().size());
+ }
+
+ @Test
+ public final void getFoosByNameUsingStoredProcedures() {
+
+ fooService.create(new Foo("NewFooName"));
+
+ // Stored procedure getFoosByName using createSQLQuery()
+ Query sqlQuery = session.createSQLQuery("CALL GetFoosByName(:fooName)")
+ .addEntity(Foo.class).setParameter("fooName", "NewFooName");
+ @SuppressWarnings("unchecked")
+ List allFoosByName = sqlQuery.list();
+ for (Foo foo : allFoosByName) {
+ LOGGER.info("getFoosByName() using SQL Query : found => {}", foo.toString());
+ }
+
+ // Stored procedure getFoosByName using getNamedQuery()
+ Query namedQuery = session.getNamedQuery("callGetFoosByName")
+ .setParameter("fooName", "NewFooName");
+ @SuppressWarnings("unchecked")
+ List allFoosByName2 = namedQuery.list();
+ for (Foo foo : allFoosByName2) {
+ LOGGER.info("getFoosByName() using Native Query : found => {}", foo.toString());
+ }
+
+ }
+}
diff --git a/spring-rest/pom.xml b/spring-rest/pom.xml
index 09a50b9579..e28f7e7e33 100644
--- a/spring-rest/pom.xml
+++ b/spring-rest/pom.xml
@@ -151,11 +151,10 @@
protobuf-java
2.6.1
-
- com.esotericsoftware.kryo
+ com.esotericsoftware
kryo
- 2.24.0
+ 4.0.0
diff --git a/webjars/webjarsdemo/pom.xml b/webjars/webjarsdemo/pom.xml
new file mode 100644
index 0000000000..80e4f0a42a
--- /dev/null
+++ b/webjars/webjarsdemo/pom.xml
@@ -0,0 +1,63 @@
+
+
+ 4.0.0
+
+ com.baeldung
+ webjarsdemo
+ 0.0.1-SNAPSHOT
+ jar
+
+ webjarsdemo
+ Demo project for webjars using Spring Boot
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 1.3.5.RELEASE
+
+
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.webjars
+ bootstrap
+ 3.3.4
+
+
+ org.webjars
+ jquery
+ 2.1.4
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
diff --git a/webjars/webjarsdemo/src/main/java/com/baeldung/TestController.java b/webjars/webjarsdemo/src/main/java/com/baeldung/TestController.java
new file mode 100644
index 0000000000..19a1c18c6b
--- /dev/null
+++ b/webjars/webjarsdemo/src/main/java/com/baeldung/TestController.java
@@ -0,0 +1,15 @@
+package com.baeldung;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@Controller
+public class TestController {
+
+ @RequestMapping(value="/")
+ public String welcome(Model model){
+ return "index";
+ }
+
+}
diff --git a/webjars/webjarsdemo/src/main/java/com/baeldung/WebjarsdemoApplication.java b/webjars/webjarsdemo/src/main/java/com/baeldung/WebjarsdemoApplication.java
new file mode 100644
index 0000000000..c14dc682af
--- /dev/null
+++ b/webjars/webjarsdemo/src/main/java/com/baeldung/WebjarsdemoApplication.java
@@ -0,0 +1,12 @@
+package com.baeldung;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class WebjarsdemoApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(WebjarsdemoApplication.class, args);
+ }
+}
diff --git a/webjars/webjarsdemo/src/main/resources/templates/index.html b/webjars/webjarsdemo/src/main/resources/templates/index.html
new file mode 100644
index 0000000000..046d21600a
--- /dev/null
+++ b/webjars/webjarsdemo/src/main/resources/templates/index.html
@@ -0,0 +1,19 @@
+
+
+ WebJars Demo
+
+
+
+
+
+
+
+
Success! It is working as we expected.
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/webjars/webjarsdemo/src/test/java/com/baeldung/WebjarsdemoApplicationTests.java b/webjars/webjarsdemo/src/test/java/com/baeldung/WebjarsdemoApplicationTests.java
new file mode 100644
index 0000000000..284cda5d31
--- /dev/null
+++ b/webjars/webjarsdemo/src/test/java/com/baeldung/WebjarsdemoApplicationTests.java
@@ -0,0 +1,18 @@
+package com.baeldung;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.SpringApplicationConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.web.WebAppConfiguration;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@SpringApplicationConfiguration(classes = WebjarsdemoApplication.class)
+@WebAppConfiguration
+public class WebjarsdemoApplicationTests {
+
+ @Test
+ public void contextLoads() {
+ }
+
+}