All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.reprezen.genflow.api.normal.openapi.ContentManager Maven / Gradle / Ivy

There is a newer version: 1.4.2
Show newest version
package com.reprezen.genflow.api.normal.openapi;

import static java.util.Spliterators.spliterator;
import static java.util.Spliterators.spliteratorUnknownSize;
import static java.util.stream.StreamSupport.stream;

import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.Spliterator;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.reprezen.genflow.api.normal.openapi.ContentLocalizer.LocalContent;

/**
 * Loads and manages all the documents that contribute to a given model spec.
 * 

* Here, "document" means a Json tree loaded from a single file. */ public class ContentManager { private final Integer modelVersion; private final Map contentItems = Maps.newLinkedHashMap(); private final ContentLocalizer localizer; private final Set toBeLoaded = Sets.newLinkedHashSet(); // following lets us avoid using URLs as set items or map keys, because // URL#equals is potentially very expensive // (involving network operations). And it gives us an exception-free way to // translate from URL strings we know to be // cached into the corresponding URLs. private final Map urlCache = Maps.newHashMap(); public ContentManager(Integer modelVersion) { this.modelVersion = modelVersion; this.localizer = new ContentLocalizer(modelVersion); } public Integer getModelVersion() { return modelVersion; } /** * Public load for the top-level model document. *

* This method may provide the preloaded tree corresponding to the specified * URL. E.g. this would generally be the case when a model spec in an open * editor is normalized. In such cases, the URL is still required so that * relative references appearing in that tree can be resolved. */ public Content load(URL url, JsonNode tree, boolean rewriteSimpleRefs) { Content content = loadInternal(url, tree, rewriteSimpleRefs); loadRequestedDocuments(rewriteSimpleRefs); return content; } /** * This private load method is used to load documents directly or indirectly * referenced by the top-level document. A preloaded tree is never provided in * this case. */ private Content loadRequestedDoc(URL url, boolean rewriteSimpleRefs) { return loadInternal(url, null, rewriteSimpleRefs); } /** * Load a JSON tree from the given URL (unless preloaded tree is provided), * register the content, and maybe rewrite "simple" refs to local object refs */ private Content loadInternal(URL url, JsonNode tree, boolean rewriteSimpleRefs) { String urlString = cacheUrl(url); Content content = contentItems.get(urlString); if (content == null) { content = new ContentLoader(this).load(url, tree, rewriteSimpleRefs); contentItems.put(urlString, content); } return content; } /** * Request that a document be loaded and registered with the content manager. *

* This will be called for every document (i.e. a reference minus its fragment) * referenced in any loaded document. */ public void requestDocument(URL url) { toBeLoaded.add(cacheUrl(url)); } /** * Load requested documents until there are no more newly requested documents. *

* During this method, more documents may be requested. */ private void loadRequestedDocuments(boolean rewriteSimpleRefs) { while (!toBeLoaded.isEmpty()) { String urlString = toBeLoaded.iterator().next(); toBeLoaded.remove(urlString); if (!contentItems.containsKey(urlString)) { loadRequestedDoc(urlCache.get(urlString), rewriteSimpleRefs); } } } public Iterable contentItems() { return contentItems.values(); } public Optional getModelObject(Reference ref) { if (ref.isModelObjectRef()) { String urlString = cacheUrl(ref.getUrl()); Content content = contentItems.get(urlString); if (content != null) { return content.getObject(ref.getSection(), ref.getObjectName()); } } return Optional.empty(); } public Reference getLocalizedRef(Reference ref) { Optional node = getModelObject(ref); if (node.isPresent()) { localizer.register(ref, node.get()); return localizer.getLocalizedRef(ref); } else { return ref.getBadRef(); } } public JsonNode getLocalizedRefNode(Reference ref) { Optional node = getModelObject(ref); if (node.isPresent()) { localizer.register(ref, node.get()); return localizer.getLocalizedRefNode(ref); } else { return ref.getBadRefNode(); } } /** * Localize all the model objects in the given content item *

* This is used when to ensure that all model objects appearing in the top-level * spec will retain their original names in the final spec. Model objects * appearing in other specs may have their names changed for disambiguation. */ public void localizeObjects(Content content) { for (ObjectType section : ObjectType.getTypesForVersion(modelVersion, Option.COMPONENT_OBJECTS)) { localizeObjectsInSection(content, section); } localizeObjectsInSection(content, ObjectType.PATH); } public void localizeObjectsInSection(Content content, ObjectType section) { for (String objectName : content.getObjectNames(section)) { Reference ref = content.getObjectReference(section, objectName); JsonNode obj = content.getObject(section, objectName).get(); localizer.register(ref, obj); } } public ContentLocalizer getLocalizer() { return localizer; } public void applyRetentionPolicy(RetentionPolicy policy) { for (Entry e : contentItems.entrySet()) { Content content = e.getValue(); for (ObjectType section : ObjectType.getTypesForVersion(modelVersion)) { if (policy.shouldRetain(urlCache.get(e.getKey()), section)) { retainObjectsInSection(content, section); } } } } private void retainObjectsInSection(Content content, ObjectType section) { for (String objectName : content.getObjectNames(section)) { Reference ref = content.getObjectReference(section, objectName); JsonNode obj = content.getObject(section, objectName).get(); localizer.register(ref, obj).retain(); } } public void retainImplicitlyReferencedObjects() { for (LocalContent item : localizer.getLocalContentItems()) { if (item.isRetained()) { if (item.getSectionType() == ObjectType.PATH && item.isRetained()) { getRequiredSecuritySchemesFromPath(item).forEach(LocalContent::retain); } } else if (item.getSectionType() == ObjectType.SECURITY_SCHEME) { item.retain(); } } } /* * Returns all SecuritySchemes that are being used in the current path security * requirements. */ private Set getRequiredSecuritySchemesFromPath(LocalContent path) { JsonNode tree = path.getContent(); List securityRequirementArrays = Stream .of("get", "put", "post", "delete", "options", "head", "patch", "trace") // .filter(e -> tree.has(e)) // .map(e -> tree.get(e).path("security")) // .filter(e -> e != null && !e.isMissingNode())// .collect(Collectors.toList()); return collectSecuritySchemeObjects(collectSecuritySchemeNames( securityRequirementArrays.toArray(new ArrayNode[securityRequirementArrays.size()]))); } /* * Returns all SecuritySchemes having a name that is listed in the security * requirements. */ private Set collectSecuritySchemeObjects(Set securitySchemeNames) { return securitySchemeNames.stream() // .map(name -> localizer.getLocalContent("/components/securitySchemes", name)) // .filter(Objects::nonNull) // .collect(Collectors.toSet()); } /* * Returns all security requirement names. */ private Set collectSecuritySchemeNames(ArrayNode... securityRequirements) { return Stream.of(securityRequirements) // .flatMap(e -> stream(spliterator(e.elements(), e.size(), Spliterator.ORDERED), false)) // .flatMap(e -> stream(spliteratorUnknownSize(e.fieldNames(), Spliterator.ORDERED), false)) // .collect(Collectors.toSet()); } public Optional getAndRemoveRetainedModelObject() { return localizer.getAndRemoveRetainedModelObject(); } private String cacheUrl(URL url) { String key = url.toString(); urlCache.put(key, url); return key; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy