/*global define*/
define([
'pages/js/api/NavigationProvider',
'viewmodel/js/api/DataSemanticsType',
'viewmodel/js/api/context/BookmarkData',
'viewmodel/js/api/context/EntityData',
'viewmodel/js/api/context/NavigationContext',
'viewmodel/js/api/context/QueryData'
], function(
NavigationProvider,
DataSemanticsType,
BookmarkData,
EntityData,
NavigationContext,
QueryData) {
'use strict';
/**
* Representation of contextual data which can be exchanged between pages
* during page to page navigation.
*
* <p>Contextual data is typically pair of some data and semantic type of that
* data. Optionally it can contain also data identifing the calling page.</p>
*
* <p>You will need to create <code>ContextualData</code> when using the {@link module:api/js/Pages Navigation API}
* as most of the API methods accept its instance. To create an instance use
* static factory methods <code>ContextualData</code> provides:</p>
*
* <dl>
* <dt>{@link viewmodel/js/api/context/ContextualData.createBlankPageContext ContextualData.createBlankPageContext}</dt>
* <dd>to create a blank context. You usually open ABCS landing pages with
* this context.</dd>
*
* <dt>{@link viewmodel/js/api/context/ContextualData.createStartWithBlankRecordContext ContextualData.createStartWithBlankRecordContext}</dt>
* <dd>to create a context bound to an entity and possibly initialized with
* a partial and incomplete data. You usually open ABCS create pages with
* this context.</dd>
*
* <dt>{@link viewmodel/js/api/context/ContextualData.createRecordToEditContext ContextualData.createRecordToEditContext}</dt>
* <dd>to create a context bound to an entity and initialized with record data.
* You usually open ABCS edit and detail pages with this context.</dd>
*
* </dl>
*
* @AbcsAPI stable
* @version 16.3.5
* @exports viewmodel/js/api/context/ContextualData
* @constructor
* @private
*
* @param {viewmodel/js/api/Record} data record data
* @param {viewmodel/js/api/DataSemanticsType} [semanticType=DataSemanticsType.NONE]
* @param {viewmodel/js/api/context/NavigationContext} [navigationContext] navigation context, if no context
* provided there will be used navigation context refering
* the current active page
*/
/*
* <dt>{@link viewmodel/js/api/context/ContextualData.createRecordWasChangedContext ContextualData.createRecordWasChangedContext}</dt>
* <dd>to create a context bound to an entity and initialized with updated record data.
* Use this context when navigating back to the previous page using {@link module:api/js/Pages.returnToPage Pages.returnToPage}.</dd>
*/
var ContextualData = function(data, semanticType, navigationContext) {
AbcsLib.checkThis(this);
this.data = data;
this.semanticType = semanticType ? semanticType : DataSemanticsType.NONE;
this.navigationContext = navigationContext || ContextualData._createNavigationContext();
};
/**
* Create contextual data representing a record which can be edited.
*
* @AbcsAPI stable
* @version 16.3.5
* @param {Object} input
* @param {String} input.entityId - id of the entity which data are being passed
* @param {viewmodel/js/api/Record} input.data - record data
* @param {String} [input.caller=activePageId] - id of the page which page navigation should allow to
* return to; optional parameter which fallbacks to <code>activePageId</code>
* as the id of currently open page.
* @returns {viewmodel/js/api/context/ContextualData}
*
* @example
* <caption>
* Get data of currently selected customer from a table and annotate the data
* with their type (that is 'customer' business object), with their semantic
* (that is values of an existing single record of the given business
* object are available and can be manipulated), with source where the
* data come from (that is current page). Send such data to a
* different page and let it do something useful with them.
* </caption>
* var customerToEdit = ContextualData.createRecordToEditContext({
* // what business object are these data of:
* entityId: 'customer',
* // customersListArchetype is instance of ListArchetype which
* // provides selected customer row
* data: customerListArchetype.getSelectedRecord(),
* // current page where this data and request originated;
* // by default replaced with the activePageId, if 'caller' not set
* caller: 'customerListPage'});
* // navigate to the page
* Abcs.Pages().navigateToPage('customerEditPage', customerToEdit);
*/
ContextualData.createRecordToEditContext = function(input) {
AbcsLib.checkParameterCount(arguments, 1);
AbcsLib.checkDefined(input, 'input');
AbcsLib.checkObjectLiteral(input, ['entityId', 'data', 'caller']);
return new ContextualData(
new EntityData(input.entityId, input.data),
DataSemanticsType.RECORD_TO_EDIT,
ContextualData._createNavigationContext(input.caller));
};
/**
* Create contextual data representing a record which was just created or
* updated.
*
* @AbcsAPI unstable
*
* @param {Object} input
* @param {String} input.entityId - id of the entity which data are being passed
* @param {viewmodel/js/api/Record} input.data - record data
* @returns {viewmodel/js/api/context/ContextualData}
*
* @example
* <caption>
* After new customer record was persisted in the database send it back to page which
* initiated creation of new customer; allow that page to use this information
* to update its UI or whatever is desirable.
* </caption>
* var newCustomer = ContextualData.createRecordWasChangedContext({
* // what business object are these data of:
* entityId: 'customer',
* // customerDetailArchetype is instance of DetailArchetype which
* // was used to create and persist the customer
* data: customerDetailArchetype.getRecord()});
* // navigate to the page
* Abcs.Pages().returnToPage('customerListPage', newCustomer);
*/
ContextualData.createRecordWasChangedContext = function(input) {
AbcsLib.checkParameterCount(arguments, 1);
AbcsLib.checkDefined(input, 'input');
AbcsLib.checkObjectLiteral(input, ['entityId', 'data']);
return new ContextualData(
new EntityData(input.entityId, input.data),
DataSemanticsType.RECORD_WAS_CHANGED);
};
/**
* Create contextual data representing a blank new record which can be
* populated and created. If record being created is a child record then
* reference to parent record should be pre-initialized.
*
* @AbcsAPI stable
* @version 16.3.5
* @param {Object} input
* @param {String} input.entityId - id of the entity which data are being passed
* @param {viewmodel/js/api/Record} input.data - record data
* @param {String} [input.caller=activePageId] - id of the page which page navigation should allow to
* return to; optional parameter which fallbacks to <code>activePageId</code>
* as the id of currently open page.
* @returns {viewmodel/js/api/context/ContextualData}
*
* @example
* <caption>
* Creating a new child record in a separate page may require reference to parent
* record be passed around. For example SparePart business object is child
* of Product. Initiating creation of new SparePart object spanning multiple
* pages could look like this:
* </caption>
* // productDetailArchetype is DetailArchetype representing existing
* // Product record:
* var productId = productDetailArchetype.getRecord().getValue('id');
* // create blank SpareProduct record with all mandatory parent info:
* var blankSparePart = Record.createSimpleRecord({
* // sparePart is child record of product business object and
* // product ID is mandatory for new spare part to be created:
* product: productId});
* });
* var sparePartToCreate = ContextualData.createStartWithBlankRecordContext({
* // what business object are these data of:
* entityId: 'sparePart',
* // blank or preinitialized spare part data:
* data: blankSparePart,
* // current page where this data and request originated;
* // by default replaced with the activePageId, if 'caller' not set
* caller: 'productDetailPage'});
* // navigate to page where spare part is created
* Abcs.Pages().navigateToPage('sparePartCreatePage', sparePartToCreate);
*/
ContextualData.createStartWithBlankRecordContext = function(input) {
AbcsLib.checkParameterCount(arguments, 1);
AbcsLib.checkDefined(input, 'input');
AbcsLib.checkObjectLiteral(input, ['entityId', 'data', 'caller']);
return new ContextualData(
new EntityData(input.entityId, input.data),
DataSemanticsType.START_WITH_BLANK_DATA,
ContextualData._createNavigationContext(input.caller));
};
/**
* Create contextual data representing some query parameters.
*
* Condidate for API. In V1 QUERY_PARAMETERS is not used.
* Right now Query is still used instead of new Condition (in QueryData
* and elsewhere). Once MartinJ finishes BUFP-2822 the signature of this
* method can be finalized and exposed as API.
*
* @param {Object} input
* @param {String} input.query - TBD
* @param {String} [input.caller=activePageId] - id of the page which page navigation should allow to
* return to; optional parameter which fallbacks to activePageId
* @returns {viewmodel/js/api/context/ContextualData}
*/
ContextualData.createQueryParamsContext = function(input) {
AbcsLib.checkDefined(input, 'input');
return new ContextualData(
new QueryData(input.query),
DataSemanticsType.QUERY_PARAMETERS,
ContextualData._createNavigationContext(input.caller));
};
/**
* Create empty contextual data.
*
* @AbcsAPI stable
* @version 16.3.5
* @param {Object} [input]
* @param {String} [input.caller=activePageId] - id of the page which page navigation should allow to
* return to; optional parameter which fallbacks to activePageId
* @returns {viewmodel/js/api/context/ContextualData}
*
* @example
* <caption>
* Create a blank page context and navigate to an ABCS landing page.
* </caption>
* var emptyContext = ContextualData.createBlankPageContext({
* // current page where this data and request originated;
* // by default replaced with the activePageId, if 'caller' not set
* caller: 'customerListPage'
* });
* // navigate to the landing page
* Abcs.Pages().navigateToPage('myLandingPage', emptyContext);
*/
ContextualData.createBlankPageContext = function(input) {
AbcsLib.checkParameterCount(arguments, 0, 1);
if (input) {
AbcsLib.checkObjectLiteral(input, ['caller']);
}
return new ContextualData({},
DataSemanticsType.NONE,
ContextualData._createNavigationContext(input && input.caller));
};
/**
* Create contextual data representing a bookmark to use to restore a page.
*
* @param {Object} input
* @param {String} input.bookmark - textual value containing all information required
* to restore a page
* @param {String} [input.caller=activePageId] - id of the page which page navigation should allow to
* return to; optional parameter which fallbacks to activePageId
* @returns {viewmodel/js/api/context/ContextualData}
*/
ContextualData.createBookmarkContext = function(input) {
AbcsLib.checkDefined(input, 'input');
return new ContextualData(
new BookmarkData(input.bookmark),
DataSemanticsType.BOOKMARK,
ContextualData._createNavigationContext(input.caller));
};
/**
*
* @returns {viewmodel/js/api/context/Data}
*/
ContextualData.prototype.getData = function() {
return this.data;
};
/**
*
* @returns {viewmodel/js/api/context/DataSemanticsType}
*/
ContextualData.prototype.getSemanticType = function() {
return this.semanticType;
};
/**
*
* @returns {viewmodel/js/api/context/NavigationContext}
*/
ContextualData.prototype.getNavigationContext = function() {
return this.navigationContext;
};
/**
* Creates navaigation context based on caller parameter.
*
* @param {String} caller caller's page ID
* @returns {NavigationContext}
*/
ContextualData._createNavigationContext = function(caller) {
// if caller exists use it, otherwise fallback to the activePage
caller = caller || NavigationProvider.getNavigation().getActivePageId();
return new NavigationContext(caller);
};
/**
* Serializes the contextual data to JSON object.
*
* @returns {JSON} serialized contextual data
*/
ContextualData.prototype.toJSON = function() {
var def = {};
def.data = (!this.data || !this.data.toJSON) ? JSON.stringify(this.data) : this.data.toJSON();
def.semanticType = this.semanticType;
def.navigationContext = this.navigationContext.toJSON();
return def;
};
/**
* Deserializes the contextual data from JSON object.
*
* @param {JSON} json serialized contextual data
* @returns {ContextualData} ContextualData object
*/
ContextualData.fromJSON = function(json) {
if (!AbcsLib.isObject(json)) {
return new ContextualData({});
}
var semanticType = json.semanticType;
var navigationContext = ContextualData._createNavigationContext(json.navigationContext && json.navigationContext.previousPageId);
var data = {};
switch (semanticType) {
case DataSemanticsType.BOOKMARK:
data = BookmarkData.fromJSON(json.data);
break;
case DataSemanticsType.START_WITH_BLANK_DATA:
case DataSemanticsType.RECORD_TO_EDIT:
case DataSemanticsType.RECORD_WAS_CHANGED:
data = EntityData.fromJSON(json.data);
break;
case DataSemanticsType.QUERY_PARAMETERS:
data = QueryData.fromJSON(json.data);
break;
case DataSemanticsType.NONE:
default:
data = {};
}
return new ContextualData(data, semanticType, navigationContext);
};
return ContextualData;
});