Core/updateFromJson.js

"use strict";

/*global require*/
var defaultValue = require("terriajs-cesium/Source/Core/defaultValue").default;
var defined = require("terriajs-cesium/Source/Core/defined").default;
var when = require("terriajs-cesium/Source/ThirdParty/when").default;
/**
 * Updates an object from a JSON representation of the object.  Only properties that actually exist on the object are read from the JSON,
 * and the object has the opportunity to inject specialized deserialization logic by providing an `updaters` property.
 * @param {Object} target The object to update from the JSON.
 * @param {Object} json The JSON description.  The JSON should be in the form of an object literal, not a string.
 * @param {Object} [options] Optional parameters to custom updaters.
 * @return {Promise} A promise that resolves when the update completes.
 */
function updateFromJson(target, json, options) {
  options = defaultValue(options, defaultValue.EMPTY_OBJECT);

  var promises = [];

  for (var propertyName in target) {
    if (
      target.hasOwnProperty(propertyName) &&
      shouldBeUpdated(target, propertyName, json)
    ) {
      if (target.updaters && target.updaters[propertyName]) {
        promises.push(
          target.updaters[propertyName](target, json, propertyName, options)
        );
      } else {
        target[propertyName] = json[propertyName];
      }
    }
  }

  return when.all(promises);
}

/**
 * Determines whether this property is valid for updating.
 */
function shouldBeUpdated(target, propertyName, json) {
  return (
    json[propertyName] !== undefined && // Must have a value to update to
    propertyName.length > 0 && // Must have a name to update
    propertyName[0] !== "_" && // Must not be a private property
    (propertyName !== "id" || !defined(target.id))
  ); // Must not be overwriting 'id'
}

module.exports = updateFromJson;