Source: data/service/data-mapping.js

var Montage = require("core/core").Montage;

/**
 * Maps raw data to data objects of a specific type.
 *
 * Currently services define their mapping by overriding their
 * [mapRawDataToObject()]{@link DataService#mapRawDataToObject} and
 * [mapObjectToRawData()]{@link DataService#mapObjectToRawData} methods or by
 * using a {@link DataMapping} subclass that overrides its
 * [mapRawDataToObject()]{@link DataMapping#mapRawDataToObject} and
 * [mapRawDataToObject()]{@link DataMapping#mapRawDataToObject} methods. In the
 * future it will be possible to define mappings declaratively through mapping
 * descriptors read from blueprint files.
 *
 * @class
 * @extends external:Montage
 */
exports.DataMapping = Montage.specialize(/** @lends DataMapping.prototype */ {

    /***************************************************************************
     * Mapping
     */

    /**
     * Convert raw data to data objects of an appropriate type.
     *
     * Subclasses should override this method to map properties of the raw data
     * to data objects, as in the following:
     *
     *     mapRawDataToObject: {
     *         value: function (object, data) {
     *             object.firstName = data.GIVEN_NAME;
     *             object.lastName = data.FAMILY_NAME;
     *         }
     *     }
     *
     * The default implementation of this method copies the properties defined
     * by the raw data object to the data object.
     *
     * @method
     * @argument {Object} object - An object whose properties must be set or
     *                             modified to represent the raw data.
     * @argument {Object} data   - An object whose properties' values hold
     *                             the raw data.
     * @argument {?} context     - A value that was passed in to the
     *                             [addRawData()]{@link DataService#addRawData}
     *                             call that invoked this method.
     */
    mapRawDataToObject: {
        value: function (data, object, context) {
            var i, key,
                keys = Object.keys(data);
            if (data) {
                for (i = 0; (key = keys[i]); ++i) {
                    object[key] = data[key];
                }
            }
        }
    },

    /**
     * @todo Document.
     */
    mapObjectToRawData: {
        value: function (object, data) {
            // TO DO: Provide a default mapping based on object.TYPE.
            // For now, subclasses must override this.
        }
    },

    nullPromise: {
        get: function () {
            if (!this._nullPromise) {
                this._nullPromise = Promise.resolve(null);
            }
            return this._nullPromise;
        }
    },

    /***************************************************************************
     * Deprecated
     */

    /**
     * @todo Document deprecation in favor of
     * [mapRawDataToObject()]{@link DataMapping#mapRawDataToObject}
     */
    mapFromRawData: {
        value: function (object, record, context) {
            this.mapRawDataToObject(record, object, context);
        }
    },

    /**
     * @todo Document deprecation in favor of
     * [mapObjectToRawData()]{@link DataMapping#mapObjectToRawData}
     */
    mapToRawData: {
        value: function (object, record) {
            this.mapObjectToRawData(object, record);
        }
    }

},{

    withObjectDescriptor: {
        value: function (objectDescriptor) {
            var mapping = new this();
            mapping._descriptor = objectDescriptor;
            return mapping;
        }
    }
});