Source

BasicHelpers.js

/**
 * @file BasicHelpers
 * @author Adam Brin, Pamela Lam, Alyx Rossetti, Charles Webb, Selina Zawacki
 * @module BasicHelpers
 * @category Files
 * @description This file contains helpers for working with LinkedArt JSON-LD data
 */

import { PART } from "../data/constants.json";

/**
 * Checks whether the object has the key as a property, and returns the result as either
 * an empty array (if it doesn't exist), an array with the single object if it's an object
 * or primitive, or the array
 *
 * @category Basic Helpers
 * @param {Object} obj - The object that might have an array attribute
 * @param {String} key - The key for the attribute field we want to retrieve
 *
 * @example field doesn't exist
 * normalizeFieldToArray({"id": "1234"}, "type") would return an empty array ([])
 *
 * @example field value is not an array
 * normalizeFieldToArray({"id": "1234"}, "id") would return ["1234"]
 *
 * @returns {Array} - The field's value normalized to an array
 */
export function normalizeFieldToArray(obj, key) {
  if (obj == undefined) {
    return [];
  }

  var val = obj[key];
  if (val == undefined) {
    return [];
  }

  if (Array.isArray(val) == false) {
    return [val];
  }

  if (val.length < 1) {
    return [];
  }

  return val;
}

/**
 * Normalizes the AAT ID to one of two versions (an aat: prefixed id or a full url)
 *
 * @category Basic Helpers
 * @param {String} id - an ID to test
 *
 * @example - short to full aat value
 * normalizeAatId("aat:300388306") would return http://vocab.getty.edu/aat/300388306
 *
 * @example - full to short
 * normalizeAatId("http://vocab.getty.edu/aat/300388306") would return aat:300388306
 *
 * @returns {String} - the alternate ID format
 */
export function normalizeAatId(id) {
  let id_ = id.toLowerCase();
  // if we're using the aat:<#> format, turn it into a full vocab url
  if (id_.startsWith("aat:")) {
    return id_.replace("aat:", "http://vocab.getty.edu/aat/");
  }

  // if we've got a full url with https://, replace it with http:// to make it internally consistent
  if (id_.startsWith("https://vocab.getty.edu/aat/")) {
    return id_.replace(
      "https://vocab.getty.edu/aat/",
      "http://vocab.getty.edu/aat/"
    );
  }

  // otherwise, convert the full url to the aat:<#> format
  return id_.replace("http://vocab.getty.edu/aat/", "aat:");
}

/**
 * Normalize a field that may have parts.
 *
 * @category Basic Helpers
 * @description Some of the fields in LinkedArt may be (but sometimes dont) include parts.
 * For example, `produced_by` which may have a production, or that production may contain multiple
 * parts.  This function returns an array with the single or all parts
 *
 * @param {Object} object - the JSON-LD object (or sub-bart)
 * @param {String} field - the field to look for/in
 *
 * @example with a production without parts:
 *  normalizeFieldWithParts({produced_by: { carried_out_by: {id:123}}}, 'produced_by'), it would return an array with 1 item [{ carried_out_by: {id:123}}}]
 *
 * @example with a production with parts:
 *  normalizeFieldWithParts({produced_by: { part: [{carried_out_by: {id:123}}}]}, 'produced_by'), it would return an array with one item [{ carried_out_by: {id:123}}}]
 *
 * @returns {Array} an array that contains the single or multiple parts
 */
export function normalizeFieldWithParts(object, field) {
  let part = object[field];

  if (part == undefined) {
    return [];
  }

  let parts = [];
  if (Array.isArray(part[PART]) == false) {
    // A yale record has the top level as an array with no parts, so taking that into account
    if (Array.isArray(part)) {
      parts = part;
    } else {
      parts = [part];
    }
  } else {
    // prevent circular refs
    parts = [...part[PART]];
    // make sure we shouldn't ignore the object that has the parts (look for other fields than just core fields)
    if (_hasUniqueFields(part, ["id", "_label", "label", "type", PART])) {
      parts.push(part);
    }
  }
  return parts;
}

/**
 * Checks whether the JSON-LD object has unique fields outside of some basic fields (id, type, _label). Useful for testing whether
 * we should include the parent part in a list or not
 *
 * @category Basic Helpers
 * @param {Object} object - the JSON-LD object to check
 * @param {Array} fieldsToIgnore - a list of fields to ignore when checking
 * @private
 *
 * @returns {boolean}
 */
function _hasUniqueFields(
  object,
  fieldsToIgnore = ["id", "_label", "label", "type"]
) {
  let keys = Object.keys(object);
  // remove known fields
  keys.filter((key) => fieldsToIgnore.indexOf(key) == false);
  return keys.length > 0;
}