define([
'module'
], function (
module
) {
'use strict';
/**
* View model support for work with Business Objects (BO) providing higher-level
* BO related operations and building blocks for complex UIs such as forms,
* collections, charts and others.
*
* <p>Data driven applications consist of handful of patterns and behaviours
* which keep repeating again and again. ABCS recognizes this and provides
* for each of these patterns an abstraction called "archetype". The goal of
* archetype is to:</p>
*
* <ul>
* <li>hide low level repetitive programming details</li>
* <li>provide building blocks which describe application semantic and its purpose</li>
* <li>separate UI (which changes in time) from application business logic (which is fairly set)</li>
* <li>support rapid application building</li>
* </ul>
*
* <p>The claim which ABCS makes is that any data driven application can be
* described using the archetypes architecture. That is, core of any data
* driven application is primarily about querying data, displaying data,
* capturing data.</p>
*
* <p>Archetypes that are part of a page are generated into its {@link viewmodel/js/api/PageViewModel view model}
* where you may access them as e.g. <code>pageViewModel.Archetypes.customerTableArchetype</code>.</p>
*
* <p><strong>Note that</strong> archetypes may not be present on a page indefinitely.
* As their owner component (such as table, list or a form) may be removed
* from the page, so may the archetype be removed along with it. Hence you
* should always check for the archetype's existence before using it:</p>
* <pre>
* var archetype = pageViewModel.Archetypes.customerTableArchetype;
* if (archetype) {
* // do something with the archetype
* }
* </pre>
*
* <p>Known implementations of <code>Archetype</code> are:</p>
* <dl>
* <dt>{@link viewmodel/js/api/CollectionArchetype CollectionArchetype}</dt>
* <dd>Solves use-cases related to work with collection of data
* and collection components (table or list).</dd>
* <dt>{@link viewmodel/js/api/DetailArchetype DetailArchetype}</dt>
* <dd>Solves use-cases related to work with a single record and
* a form component.</dd>
* </dl>
*
* @AbcsAPI stable
* @version 16.3.5
* @exports viewmodel/js/api/Archetype
*
* @constructor
* @private
* @param {Entity} entity
* @param {Object} archetypeJSON - JSON description (metadata) of the underlying archetype
* @see {@link viewmodel/js/api/CollectionArchetype CollectionArchetype} for archetype
* working with collection of records.
* @see {@link viewmodel/js/api/DetailArchetype DetailArchetype} for archetype
* working with a single record.
* @see {@link viewmodel/js/api/PageViewModel PageViewModel} to see how to access
* archetype instances in a page.
*/
/*
* Archetype constructor is guaranteed to be called only once when page
* owning it is created for the first time. Any initialization which is
* independent of page state should be performed here.
*/
var Archetype = function(entity, archetypeJSON) {
AbcsLib.checkThis(this);
this._entity = entity;
this._entityName = entity ? entity.getName() : AbcsLib.i18n('viewmodel.missingBusinessObjectName');
if (entity) {
this._entityId = entity.getId();
}
this._observables = {};
if (archetypeJSON) {
var id = archetypeJSON.id;
this._id = id;
// Check also for archetypeJSON.archetype for backward compatibility
this._type = archetypeJSON.type ? archetypeJSON.type : archetypeJSON.archetype;
this._entityId = this._entityId || archetypeJSON.entityId;
if (!this._entity) {
Archetype._LOGGER.error('Incomplete archetype initialization, nonexistent entity with ID: ' + this._entityId);
}
}
};
Archetype._LOGGER = Logger.get(module.id);
/**
* Returns archetype's ID.
*
* The ID is unique inside an ABCS page, not across whole ABCS application.
*
* @AbcsAPI stable
* @version 16.3.5
* @returns {String}
*/
Archetype.prototype.getId = function() {
AbcsLib.checkParameterCount(arguments, 0);
return this._id;
};
/**
* Returns {@link viewmodel/js/api/ArchetypeType type} of the archetype.
*
* Type defines the archetype's behaviour, methods, fields and observables.
* Currently known types are:
* <ul>
* <li>{@link viewmodel/js/api/ArchetypeType.COLLECTION ArchetypeType.COLLECTION} identifies a
* {@link viewmodel/js/api/CollectionArchetype CollectionArchetype} working
* with collections.
* <li>{@link viewmodel/js/api/ArchetypeType.ENTITY_DETAIL ArchetypeType.ENTITY_DETAIL} identifies a
* {@link viewmodel/js/api/DetailArchetype DetailArchetype} working with single record.
* </ul>
*
* @AbcsAPI stable
* @version 16.3.5
* @returns {viewmodel/js/api/ArchetypeType}
*/
Archetype.prototype.getType = function() {
AbcsLib.checkParameterCount(arguments, 0);
return this._type;
};
/**
* Returns entity instance this archetype is bound to.
*
* <p><strong>Note</strong> that there are cases when this may be <code>undefined</code>,
* such as when the entity is not found in the data model.</p>
*
* @AbcsAPI stable
* @version 16.3.5
* @returns {entity/js/api/Entity} entity the archetype is bound to. In special
* occassions when the archetype is broken this may return <code>undefined</code>.
* @example <caption>List all Business Objects in all page archetypes and
* print their names.</caption>
* // expecting you have an instance of a page view model assigned to 'self'
* // as this will often be the case in business actions code.
* var pageViewModel = self;
* var archetypeIds = Object.keys(pageViewModel.Archetypes);
* archetypeIds.forEach(function (archetypeId) {
* // get instance of bound entity for an archetype
* var entity = pageViewModel.Archetypes[archetypeId].getEntity();
* // you should always check if the value is defined as in rare cases
* // the archetype may not give you the reference to its entity
* if (entity) {
* // print its name
* console.log('Page contains an archetype with BO: ' + entity.getName());
* }
* });
*/
Archetype.prototype.getEntity = function() {
AbcsLib.checkParameterCount(arguments, 0);
return this._entity;
};
Archetype.prototype.getEntityId = function() {
return this._entityId;
};
Archetype.prototype.getEntityName = function() {
return this._entityName;
};
/**
* Returns an object that contains a set of fields and observables you can
* bind to in your components and use to communicate with other components on
* a page bound to the same instances.
*
* The content of the object is described in specific archetype instances:
* <ul>
* <li>{@link viewmodel/js/api/CollectionArchetype#getObservables CollectionArchetype}</li>
* <li>{@link viewmodel/js/api/DetailArchetype#getObservables DetailArchetype}</li>
* </ul>
*
* @AbcsAPI stable
* @version 16.3.5
* @returns {Object} observables exposed by the archetype
* @see {@link viewmodel/js/api/CollectionArchetype#getObservables CollectionArchetype} to see
* an example and description of what collection archetype's method returns.
* @see {@link viewmodel/js/api/DetailArchetype#getObservables DetailArchetype} to see
* an example and description of what detail archetype's method returns.
*/
Archetype.prototype.getObservables = function() {
AbcsLib.checkParameterCount(arguments, 0);
return this._observables;
};
/**
* Called by {@link ViewModelDefinition} once all archetypes are initialized.
*
* <p>
* This allows particular subclasses initiate their references if there are any.
* </p>
*
* @param {Object} archetypeJSON - archetype descriptor in JSON format
* @param {Archetype[]} archetypes - list of all archetypes from the viewmodel
*/
Archetype.prototype.setUpReferences = function(/*archetypeJSON, archetypes*/) {
};
/**
* To be subclassed.
*
* @param {string} piece of document fragment to restore the page model state.
*/
Archetype.prototype.getBookmark = function() {
};
/**
* Called upon page opening to allow archetype to updated itself based
* on context in which the page is being opened. This method is called
* as a result of Navigation.navigateToPage call. See also updateViewModel.
*
* @param {ContextualData} contextualData
*/
Archetype.prototype.createViewModel = function(contextualData) {
this._contextualData = contextualData;
};
/**
*
* @returns {ContextualData}
*/
Archetype.prototype.getContextualData = function() {
return this._contextualData;
};
/**
* Called upon returning to an already opened page to allow archetype to
* update itself based on changes represented in updateContextualData. This
* method is called as a result of Navigation.returnToPage call. See also
* createViewModel.
*
* <p>To be implemented by descendants based on their needs.</p>
*
* @param {ContextualData} contextualData
*/
Archetype.prototype.updateViewModel = function(/*contextualData*/) {
};
Archetype.prototype.getDefinition = function () {
var def = {};
def.id = this.getId();
def.type = this.getType();
def.entityId = this._entityId;
return def;
};
return Archetype;
});