lib/export.js
function extractConstraintPath(constraint, valueDef, dataElementSpecs) {
  if (constraint.onValue) {
    return extractUnnormalizedConstraintPath(constraint, valueDef, dataElementSpecs);
  } else if (constraint.path.length > 0 && constraint.path[constraint.path.length-1].isValueKeyWord) {
    // Essentially the same as above, when onValue is never checked again, so just chop it off
    // treat it like above.  TODO: Determine if this is really the right approach.
    const simpleConstraint = constraint.clone();
    simpleConstraint.path = simpleConstraint.path.slice(0, simpleConstraint.path.length-1);
    return extractUnnormalizedConstraintPath(simpleConstraint, valueDef, dataElementSpecs);
  }

  if (!constraint.hasPath()) {
    return { path: [] };
  }

  let currentDef = dataElementSpecs.findByIdentifier(valueDef.effectiveIdentifier);
  const normalizedPath = [];
  let target = null;
  for (let i = 0; i < constraint.path.length; i += 1) {
    const pathId = constraint.path[i];
    target = null;
    if (pathId.namespace === PRIMITIVE_NS) {
      if (i !== constraint.path.length - 1) {
        logger.error('Encountered a constraint path containing a primitive %s at index %d that was not the leaf: %s', pathId, i, constraint.toString());
        return {};
      }
      if (!currentDef.value) {
        logger.error('Encountered a constraint path with a primitive leaf %s on an element that lacked a value: %s', pathId, constraint.toString());
        return {};
      }
      if (currentDef.value instanceof ChoiceValue) {
        target = findOptionInChoice(currentDef.value, pathId, dataElementSpecs);
        if (!target) {
          logger.error('Encountered a constraint path with a primitive leaf %s on an element with a mismatched value: %s on valueDef %s', pathId, constraint.toString(), valueDef.toString());
          return {};
        }
      } else if (!pathId.equals(currentDef.value.identifier)) {
        logger.error('Encountered a constraint path with a primitive leaf %s on an element with a mismatched value: %s on valueDef %s', pathId, constraint.toString(), valueDef.toString());
        return {};
      } else {
        target = currentDef.value;
      }
      normalizedPath.push('Value');
    } else {
      const newDef = dataElementSpecs.findByIdentifier(pathId);
      if (!newDef) {
        logger.error('Cannot resolve element definition for %s on constraint %s. ERROR_CODE:12029', pathId, constraint.toString());
        return {};
      }
      // See if the current definition has a value of the specified type.
      if (currentDef.value) {
        if (currentDef.value instanceof ChoiceValue) {
          target = findOptionInChoice(currentDef.value, pathId, dataElementSpecs);
        } else if (pathId.equals(currentDef.value.identifier) || checkHasBaseType(currentDef.value.identifier, pathId, dataElementSpecs)) {
          target = currentDef.value;
          normalizedPath.push('Value');
        }
      }

      if (!target) {
        if (!currentDef.fields || !currentDef.fields.length) {
          logger.error('Element %s lacked any fields or a value that matched %s as part of constraint %s', currentDef.identifier.fqn, pathId, constraint.toString());
          return {};
        } else {
          target = currentDef.fields.find((field) => pathId.equals(field.identifier));
          if (!target) {
            // It's possible that the field is actually defined as an "includes type" constraint on a list.
            // In this case, do nothing, because right now there isn't a valid way to represent further constraints
            // on includesType elements in the schema.
            if (valueDef.constraintsFilter.includesType.constraints.some(c => c.isA.equals(pathId))) {
              logger.warn('Cannot enforce constraint %s on Element %s since %s refers to an type introduced by an "includesType" constraint', constraint.toString(), currentDef.identifier.fqn, pathId);
            } else {
              logger.error('Element %s lacked a field or a value that matched %s as part of constraint %s', currentDef.identifier.fqn, pathId, constraint.toString());
            }
            return {};
          }
          normalizedPath.push(pathId.name);
        }
      }
      currentDef = newDef;
    }
  }

  return {path:normalizedPath, target};
}
function extractConstraintPath(constraint, valueDef, dataElementSpecs) {
  if (constraint.onValue) {
    return extractUnnormalizedConstraintPath(constraint, valueDef, dataElementSpecs);
  } else if (constraint.path.length > 0 && constraint.path[constraint.path.length-1].isValueKeyWord) {
    // Essentially the same as above, when onValue is never checked again, so just chop it off
    // treat it like above.  TODO: Determine if this is really the right approach.
    const simpleConstraint = constraint.clone();
    simpleConstraint.path = simpleConstraint.path.slice(0, simpleConstraint.path.length-1);
    return extractUnnormalizedConstraintPath(simpleConstraint, valueDef, dataElementSpecs);
  }

  if (!constraint.hasPath()) {
    return { path: [] };
  }

  let currentDef = dataElementSpecs.findByIdentifier(valueDef.effectiveIdentifier);
  const normalizedPath = [];
  let target = null;
  for (let i = 0; i < constraint.path.length; i += 1) {
    const pathId = constraint.path[i];
    target = null;
    if (pathId.namespace === PRIMITIVE_NS) {
      if (i !== constraint.path.length - 1) {
        logger.error('Encountered a constraint path containing a primitive %s at index %d that was not the leaf: %s', pathId, i, constraint.toString());
        return {};
      }
      if (!currentDef.value) {
        logger.error('Encountered a constraint path with a primitive leaf %s on an element that lacked a value: %s', pathId, constraint.toString());
        return {};
      }
      if (currentDef.value instanceof ChoiceValue) {
        target = findOptionInChoice(currentDef.value, pathId, dataElementSpecs);
        if (!target) {
          logger.error('Encountered a constraint path with a primitive leaf %s on an element with a mismatched value: %s on valueDef %s', pathId, constraint.toString(), valueDef.toString());
          return {};
        }
      } else if (!pathId.equals(currentDef.value.identifier)) {
        logger.error('Encountered a constraint path with a primitive leaf %s on an element with a mismatched value: %s on valueDef %s', pathId, constraint.toString(), valueDef.toString());
        return {};
      } else {
        target = currentDef.value;
      }
      normalizedPath.push('Value');
    } else {
      const newDef = dataElementSpecs.findByIdentifier(pathId);
      if (!newDef) {
        logger.error('Cannot resolve element definition for %s on constraint %s. ERROR_CODE:12029', pathId, constraint.toString());
        return {};
      }
      // See if the current definition has a value of the specified type.
      if (currentDef.value) {
        if (currentDef.value instanceof ChoiceValue) {
          target = findOptionInChoice(currentDef.value, pathId, dataElementSpecs);
        } else if (pathId.equals(currentDef.value.identifier) || checkHasBaseType(currentDef.value.identifier, pathId, dataElementSpecs)) {
          target = currentDef.value;
          normalizedPath.push('Value');
        }
      }

      if (!target) {
        if (!currentDef.fields || !currentDef.fields.length) {
          logger.error('Element %s lacked any fields or a value that matched %s as part of constraint %s', currentDef.identifier.fqn, pathId, constraint.toString());
          return {};
        } else {
          target = currentDef.fields.find((field) => pathId.equals(field.identifier));
          if (!target) {
            // It's possible that the field is actually defined as an "includes type" constraint on a list.
            // In this case, do nothing, because right now there isn't a valid way to represent further constraints
            // on includesType elements in the schema.
            if (valueDef.constraintsFilter.includesType.constraints.some(c => c.isA.equals(pathId))) {
              logger.warn('Cannot enforce constraint %s on Element %s since %s refers to an type introduced by an "includesType" constraint', constraint.toString(), currentDef.identifier.fqn, pathId);
            } else {
              logger.error('Element %s lacked a field or a value that matched %s as part of constraint %s', currentDef.identifier.fqn, pathId, constraint.toString());
            }
            return {};
          }
          normalizedPath.push(pathId.name);
        }
      }
      currentDef = newDef;
    }
  }

  return {path:normalizedPath, target};
}
Translates a constraint path into a valid path for the JSON Schema.
@param {Constraint} constraint - the constraint.
@param {IdentifiableValue} valueDef - the identifiable value that contains the constraint.
@param {DataElementSpecifications} dataElementSpecs - the elements in the namespace.
@return {{path: (Array<string>|undefined), target: (Value|undefined)}} - The target of the constraint and the extracted path (qualified if necessary). Both properties will be null if there was an error.