function safeSchemaFaker (oldSchema, resolveTo, resolveFor, parameterSourceOption, components,
  schemaFormat, schemaCache, options) {
  var prop, key, resolvedSchema, fakedSchema,
    schemaFakerCache = _.get(schemaCache, 'schemaFakerCache', {});
  let concreteUtils = components && components.hasOwnProperty('concreteUtils') ?
    components.concreteUtils :
    DEFAULT_SCHEMA_UTILS;
  const indentCharacter = options.indentCharacter,
    includeDeprecated = options.includeDeprecated;

  resolvedSchema = deref.resolveRefs(oldSchema, parameterSourceOption, components, {
    resolveFor,
    resolveTo,
    stackLimit: options.stackLimit,
    analytics: _.get(schemaCache, 'analytics', {})
  });

  resolvedSchema = concreteUtils.fixExamplesByVersion(resolvedSchema);
  key = JSON.stringify(resolvedSchema);

  if (resolveTo === 'schema') {
    key = 'resolveToSchema ' + key;
    schemaFaker.option({
      useExamplesValue: false,
      useDefaultValue: true
    });
  }
  else if (resolveTo === 'example') {
    key = 'resolveToExample ' + key;
    schemaFaker.option({
      useExamplesValue: true
    });
  }

  if (resolveFor === PROCESSING_TYPE.VALIDATION) {
    schemaFaker.option({
      useDefaultValue: false,
      avoidExampleItemsLength: false
    });
  }

  if (schemaFormat === 'xml') {
    key += ' schemaFormatXML';
  }
  else {
    key += ' schemaFormatDEFAULT';
  }

  key = hash(key);
  if (schemaFakerCache[key]) {
    return schemaFakerCache[key];
  }

  if (resolvedSchema.properties) {
    // If any property exists with format:binary (and type: string) schemaFaker crashes
    // we just delete based on format=binary
    for (prop in resolvedSchema.properties) {
      if (resolvedSchema.properties.hasOwnProperty(prop)) {
        if (resolvedSchema.properties[prop].format === 'binary') {
          delete resolvedSchema.properties[prop].format;
        }
      }
    }
    verifyDeprecatedProperties(resolvedSchema, includeDeprecated);
  }

  try {
    if (schemaFormat === SCHEMA_FORMATS.XML) {
      fakedSchema = xmlFaker(null, resolvedSchema, indentCharacter, resolveTo);
      schemaFakerCache[key] = fakedSchema;
      return fakedSchema;
    }
    // for JSON, the indentCharacter will be applied in the JSON.stringify step later on
    fakedSchema = schemaFaker(resolvedSchema, null, _.get(schemaCache, 'schemaValidationCache'));
    schemaFakerCache[key] = fakedSchema;
    return fakedSchema;
  }
  catch (e) {
    console.warn(
      'Error faking a schema. Not faking this schema. Schema:', resolvedSchema,
      'Error', e
    );
    return null;
  }
}
Safe wrapper for schemaFaker that resolves references and
removes things that might make schemaFaker crash
@param {*} oldSchema the schema to fake
@param {string} resolveTo The desired JSON-generation mechanism (schema: prefer using the JSONschema to
   generate a fake object, example: use specified examples as-is). Default: schema
@param {*} resolveFor - resolve refs for flow validation/conversion (value to be one of VALIDATION/CONVERSION)
@param {string} parameterSourceOption Specifies whether the schema being faked is from a request or response.
@param {*} components list of predefined components (with schemas)
@param {string} schemaFormat default or xml
@param {object} schemaCache - object storing schemaFaker and schemaResolution caches
@param {object} options - a standard list of options that's globally passed around. Check options.js for more.
@returns {object} fakedObject