docs: public <T> JSONAPIDocument<T> readDocument(InputStream dataStream, Class<T> clazz) {
  		try {
  			resourceCache.init();
  
  			JsonNode rootNode = objectMapper.readTree(dataStream);
  
  			// Validate
  			ValidationUtils.ensureNotError(objectMapper, rootNode);
  			ValidationUtils.ensureValidResource(rootNode);
  
  			JsonNode dataNode = rootNode.get(DATA);
  
  			// Parse data node without handling relationships
  			T resourceObject;
  			boolean cached = false;
  			if (dataNode != null && dataNode.isObject()) {
  				String identifier = createIdentifier(dataNode);
  				cached = identifier != null && resourceCache.contains(identifier);
  
  				if (cached) {
  					resourceObject = (T) resourceCache.get(identifier);
  				} else {
  					resourceObject = readObject(dataNode, clazz, false);
  				}
  			} else {
  				resourceObject = null;
  			}
  
  			// Parse all included resources
  			resourceCache.cache(parseIncluded(rootNode));
  
  			// Connect data node's relationships now that all resources have been parsed
  			if (resourceObject != null && !cached) {
  				handleRelationships(dataNode, resourceObject);
  			}
  
  			JSONAPIDocument<T> result = new JSONAPIDocument<>(resourceObject, objectMapper);
  
  			// Handle top-level meta
  			if (rootNode.has(META)) {
  				result.setMeta(mapMeta(rootNode.get(META)));
  			}
  
  			// Handle top-level links
  			if (rootNode.has(LINKS)) {
  				result.setLinks(new Links(mapLinks(rootNode.get(LINKS))));
  			}
  
  			return result;
  		} catch (RuntimeException e) {
  			throw e;
  		} catch (Exception e) {
  			throw new RuntimeException(e);
  		} finally {
  			resourceCache.clear();
  		}
  	}