blob: e79964e210c5ae90d58c54ef33920524f09ecd9f [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.registry.web.link;
import org.apache.nifi.registry.bucket.Bucket;
import org.apache.nifi.registry.extension.bundle.Bundle;
import org.apache.nifi.registry.extension.bundle.BundleInfo;
import org.apache.nifi.registry.extension.bundle.BundleVersion;
import org.apache.nifi.registry.extension.bundle.BundleVersionMetadata;
import org.apache.nifi.registry.extension.component.ExtensionMetadata;
import org.apache.nifi.registry.extension.repo.ExtensionRepoArtifact;
import org.apache.nifi.registry.extension.repo.ExtensionRepoBucket;
import org.apache.nifi.registry.extension.repo.ExtensionRepoExtensionMetadata;
import org.apache.nifi.registry.extension.repo.ExtensionRepoGroup;
import org.apache.nifi.registry.extension.repo.ExtensionRepoVersionSummary;
import org.apache.nifi.registry.flow.VersionedFlow;
import org.apache.nifi.registry.flow.VersionedFlowSnapshotMetadata;
import org.apache.nifi.registry.link.LinkableDocs;
import org.apache.nifi.registry.link.LinkableEntity;
import org.springframework.stereotype.Service;
import javax.ws.rs.core.Link;
import javax.ws.rs.core.UriBuilder;
import java.net.URI;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@Service
public class LinkService {
private static final String BUCKET_PATH = "buckets/{id}";
private static final String FLOW_PATH = "buckets/{bucketId}/flows/{flowId}";
private static final String FLOW_SNAPSHOT_PATH = "buckets/{bucketId}/flows/{flowId}/versions/{versionNumber}";
private static final String EXTENSION_BUNDLE_PATH = "bundles/{bundleId}";
private static final String EXTENSION_BUNDLE_VERSION_PATH = "bundles/{bundleId}/versions/{version}";
private static final String EXTENSION_BUNDLE_VERSION_CONTENT_PATH = "bundles/{bundleId}/versions/{version}/content";
private static final String EXTENSION_BUNDLE_VERSION_EXTENSION_PATH = "bundles/{bundleId}/versions/{version}/extensions/{name}";
private static final String EXTENSION_BUNDLE_VERSION_EXTENSION_DOCS_PATH = "bundles/{bundleId}/versions/{version}/extensions/{name}/docs";
private static final String EXTENSION_REPO_BUCKET_PATH = "extension-repository/{bucketName}";
private static final String EXTENSION_REPO_GROUP_PATH = "extension-repository/{bucketName}/{groupId}";
private static final String EXTENSION_REPO_ARTIFACT_PATH = "extension-repository/{bucketName}/{groupId}/{artifactId}";
private static final String EXTENSION_REPO_VERSION_PATH = "extension-repository/{bucketName}/{groupId}/{artifactId}/{version}";
private static final String EXTENSION_REPO_EXTENSION_PATH = "extension-repository/{bucketName}/{groupId}/{artifactId}/{version}/extensions/{name}";
private static final String EXTENSION_REPO_EXTENSION_DOCS_PATH = "extension-repository/{bucketName}/{groupId}/{artifactId}/{version}/extensions/{name}/docs";
private static final LinkBuilder<Bucket> BUCKET_LINK_BUILDER = (bucket) -> {
if (bucket == null) {
return null;
}
final URI uri = UriBuilder.fromPath(BUCKET_PATH)
.resolveTemplate("id", bucket.getIdentifier())
.build();
return Link.fromUri(uri).rel("self").build();
};
// -- Flow LinkBuilders
private static final LinkBuilder<VersionedFlow> FLOW_LINK_BUILDER = (versionedFlow -> {
if (versionedFlow == null) {
return null;
}
final URI uri = UriBuilder.fromPath(FLOW_PATH)
.resolveTemplate("bucketId", versionedFlow.getBucketIdentifier())
.resolveTemplate("flowId", versionedFlow.getIdentifier())
.build();
return Link.fromUri(uri).rel("self").build();
});
private static final LinkBuilder<VersionedFlowSnapshotMetadata> FLOW_SNAPSHOT_LINK_BUILDER = (snapshotMetadata) -> {
if (snapshotMetadata == null) {
return null;
}
final URI uri = UriBuilder.fromPath(FLOW_SNAPSHOT_PATH)
.resolveTemplate("bucketId", snapshotMetadata.getBucketIdentifier())
.resolveTemplate("flowId", snapshotMetadata.getFlowIdentifier())
.resolveTemplate("versionNumber", snapshotMetadata.getVersion())
.build();
return Link.fromUri(uri).rel("content").build();
};
// -- Bundles & Extension LinkBuilders
private static final LinkBuilder<Bundle> EXTENSION_BUNDLE_LINK_BUILDER = (extensionBundle -> {
if (extensionBundle == null) {
return null;
}
final URI uri = UriBuilder.fromPath(EXTENSION_BUNDLE_PATH)
.resolveTemplate("bundleId", extensionBundle.getIdentifier())
.build();
return Link.fromUri(uri).rel("self").build();
});
private static final LinkBuilder<BundleVersionMetadata> EXTENSION_BUNDLE_VERSION_LINK_BUILDER = (bundleVersion -> {
if (bundleVersion == null) {
return null;
}
final URI uri = UriBuilder.fromPath(EXTENSION_BUNDLE_VERSION_PATH)
.resolveTemplate("bundleId", bundleVersion.getBundleId())
.resolveTemplate("version", bundleVersion.getVersion())
.build();
return Link.fromUri(uri).rel("self").build();
});
private static final LinkBuilder<BundleVersion> EXTENSION_BUNDLE_VERSION_CONTENT_LINK_BUILDER = (bundleVersion -> {
if (bundleVersion == null) {
return null;
}
final URI uri = UriBuilder.fromPath(EXTENSION_BUNDLE_VERSION_CONTENT_PATH)
.resolveTemplate("bundleId", bundleVersion.getBundle().getIdentifier())
.resolveTemplate("version", bundleVersion.getVersionMetadata().getVersion())
.build();
return Link.fromUri(uri).rel("self").build();
});
private static final LinkBuilder<ExtensionMetadata> EXTENSION_METADATA_LINK_BUILDER = (extensionMetadata -> {
if (extensionMetadata == null) {
return null;
}
final URI uri = UriBuilder.fromPath(EXTENSION_BUNDLE_VERSION_EXTENSION_PATH)
.resolveTemplate("bundleId", extensionMetadata.getBundleInfo().getBundleId())
.resolveTemplate("version", extensionMetadata.getBundleInfo().getVersion())
.resolveTemplate("name", extensionMetadata.getName())
.build();
return Link.fromUri(uri).rel("self").build();
});
private static final LinkBuilder<ExtensionMetadata> EXTENSION_METADATA_DOCS_LINK_BUILDER = (extensionMetadata -> {
if (extensionMetadata == null) {
return null;
}
final URI uri = UriBuilder.fromPath(EXTENSION_BUNDLE_VERSION_EXTENSION_DOCS_PATH)
.resolveTemplate("bundleId", extensionMetadata.getBundleInfo().getBundleId())
.resolveTemplate("version", extensionMetadata.getBundleInfo().getVersion())
.resolveTemplate("name", extensionMetadata.getName())
.build();
return Link.fromUri(uri).rel("docs").build();
});
// -- Extension Repo LinkBuilders
private static final LinkBuilder<ExtensionRepoBucket> EXTENSION_REPO_BUCKET_LINK_BUILDER = (extensionRepoBucket -> {
if (extensionRepoBucket == null) {
return null;
}
final URI uri = UriBuilder.fromPath(EXTENSION_REPO_BUCKET_PATH)
.resolveTemplate("bucketName", extensionRepoBucket.getBucketName())
.build();
return Link.fromUri(uri).rel("self").build();
});
private static final LinkBuilder<ExtensionRepoGroup> EXTENSION_REPO_GROUP_LINK_BUILDER = (extensionRepoGroup -> {
if (extensionRepoGroup == null) {
return null;
}
final URI uri = UriBuilder.fromPath(EXTENSION_REPO_GROUP_PATH)
.resolveTemplate("bucketName", extensionRepoGroup.getBucketName())
.resolveTemplate("groupId", extensionRepoGroup.getGroupId())
.build();
return Link.fromUri(uri).rel("self").build();
});
private static final LinkBuilder<ExtensionRepoArtifact> EXTENSION_REPO_ARTIFACT_LINK_BUILDER = (extensionRepoArtifact -> {
if (extensionRepoArtifact == null) {
return null;
}
final URI uri = UriBuilder.fromPath(EXTENSION_REPO_ARTIFACT_PATH)
.resolveTemplate("bucketName", extensionRepoArtifact.getBucketName())
.resolveTemplate("groupId", extensionRepoArtifact.getGroupId())
.resolveTemplate("artifactId", extensionRepoArtifact.getArtifactId())
.build();
return Link.fromUri(uri).rel("self").build();
});
private static final LinkBuilder<ExtensionRepoVersionSummary> EXTENSION_REPO_VERSION_LINK_BUILDER = (extensionRepoVersion -> {
if (extensionRepoVersion == null) {
return null;
}
final URI uri = UriBuilder.fromPath(EXTENSION_REPO_VERSION_PATH)
.resolveTemplate("bucketName", extensionRepoVersion.getBucketName())
.resolveTemplate("groupId", extensionRepoVersion.getGroupId())
.resolveTemplate("artifactId", extensionRepoVersion.getArtifactId())
.resolveTemplate("version", extensionRepoVersion.getVersion())
.build();
return Link.fromUri(uri).rel("self").build();
});
private static final LinkBuilder<ExtensionRepoExtensionMetadata> EXTENSION_REPO_EXTENSION_METADATA_LINK_BUILDER = (extensionMetadata -> {
if (extensionMetadata == null
|| extensionMetadata.getExtensionMetadata() == null
|| extensionMetadata.getExtensionMetadata().getBundleInfo() == null) {
return null;
}
final ExtensionMetadata metadata = extensionMetadata.getExtensionMetadata();
final BundleInfo bundleInfo = metadata.getBundleInfo();
final URI uri = UriBuilder.fromPath(EXTENSION_REPO_EXTENSION_PATH)
.resolveTemplate("bucketName", bundleInfo.getBucketName())
.resolveTemplate("groupId", bundleInfo.getGroupId())
.resolveTemplate("artifactId", bundleInfo.getArtifactId())
.resolveTemplate("version", bundleInfo.getVersion())
.resolveTemplate("name", metadata.getName())
.build();
return Link.fromUri(uri).rel("self").build();
});
private static final LinkBuilder<ExtensionRepoExtensionMetadata> EXTENSION_REPO_EXTENSION_METADATA_DOCS_LINK_BUILDER = (extensionMetadata -> {
if (extensionMetadata == null
|| extensionMetadata.getExtensionMetadata() == null
|| extensionMetadata.getExtensionMetadata().getBundleInfo() == null) {
return null;
}
final ExtensionMetadata metadata = extensionMetadata.getExtensionMetadata();
final BundleInfo bundleInfo = metadata.getBundleInfo();
final URI uri = UriBuilder.fromPath(EXTENSION_REPO_EXTENSION_DOCS_PATH)
.resolveTemplate("bucketName", bundleInfo.getBucketName())
.resolveTemplate("groupId", bundleInfo.getGroupId())
.resolveTemplate("artifactId", bundleInfo.getArtifactId())
.resolveTemplate("version", bundleInfo.getVersion())
.resolveTemplate("name", metadata.getName())
.build();
return Link.fromUri(uri).rel("docs").build();
});
private static final Map<Class,LinkBuilder> LINK_BUILDERS;
static {
final Map<Class,LinkBuilder> builderMap = new HashMap<>();
// -- buckets
builderMap.put(Bucket.class, BUCKET_LINK_BUILDER);
// -- flows
builderMap.put(VersionedFlow.class, FLOW_LINK_BUILDER);
builderMap.put(VersionedFlowSnapshotMetadata.class, FLOW_SNAPSHOT_LINK_BUILDER);
// -- bundles & extensions
builderMap.put(Bundle.class, EXTENSION_BUNDLE_LINK_BUILDER);
builderMap.put(BundleVersionMetadata.class, EXTENSION_BUNDLE_VERSION_LINK_BUILDER);
builderMap.put(BundleVersion.class, EXTENSION_BUNDLE_VERSION_CONTENT_LINK_BUILDER);
builderMap.put(ExtensionMetadata.class, EXTENSION_METADATA_LINK_BUILDER);
// -- extension repo
builderMap.put(ExtensionRepoBucket.class, EXTENSION_REPO_BUCKET_LINK_BUILDER);
builderMap.put(ExtensionRepoGroup.class, EXTENSION_REPO_GROUP_LINK_BUILDER);
builderMap.put(ExtensionRepoArtifact.class, EXTENSION_REPO_ARTIFACT_LINK_BUILDER);
builderMap.put(ExtensionRepoVersionSummary.class, EXTENSION_REPO_VERSION_LINK_BUILDER);
builderMap.put(ExtensionRepoExtensionMetadata.class, EXTENSION_REPO_EXTENSION_METADATA_LINK_BUILDER);
LINK_BUILDERS = Collections.unmodifiableMap(builderMap);
}
private static final Map<Class,LinkBuilder> DOCS_LINK_BUILDERS;
static {
final Map<Class,LinkBuilder> builderMap = new HashMap<>();
builderMap.put(ExtensionMetadata.class, EXTENSION_METADATA_DOCS_LINK_BUILDER);
builderMap.put(ExtensionRepoExtensionMetadata.class, EXTENSION_REPO_EXTENSION_METADATA_DOCS_LINK_BUILDER);
DOCS_LINK_BUILDERS = Collections.unmodifiableMap(builderMap);
}
public <E extends LinkableEntity> void populateLinks(final E entity) {
final LinkBuilder linkBuilder = LINK_BUILDERS.get(entity.getClass());
if (linkBuilder == null) {
throw new IllegalArgumentException("No LinkBuilder found for " + entity.getClass().getCanonicalName());
}
final Link link = linkBuilder.createLink(entity);
entity.setLink(link);
if (entity instanceof LinkableDocs) {
final LinkBuilder docsLinkBuilder = DOCS_LINK_BUILDERS.get(entity.getClass());
if (docsLinkBuilder == null) {
throw new IllegalArgumentException("No documentation LinkBuilder found for " + entity.getClass().getCanonicalName());
}
final Link docsLink = docsLinkBuilder.createLink(entity);
final LinkableDocs docsEntity = (LinkableDocs) entity;
docsEntity.setLinkDocs(docsLink);
}
}
public <E extends LinkableEntity> void populateLinks(final Iterable<E> entities) {
if (entities == null) {
return;
}
entities.forEach(e -> populateLinks(e));
}
public <E extends LinkableEntity> void populateFullLinks(final E entity, final URI baseUri) {
final LinkBuilder linkBuilder = LINK_BUILDERS.get(entity.getClass());
if (linkBuilder == null) {
throw new IllegalArgumentException("No LinkBuilder found for " + entity.getClass().getCanonicalName());
}
if (baseUri == null) {
throw new IllegalArgumentException("Base URI cannot be null");
}
final Link relativeLink = linkBuilder.createLink(entity);
final Link fullLink = getFullLink(baseUri, relativeLink);
entity.setLink(fullLink);
if (entity instanceof LinkableDocs) {
final LinkBuilder docsLinkBuilder = DOCS_LINK_BUILDERS.get(entity.getClass());
if (docsLinkBuilder == null) {
throw new IllegalArgumentException("No documentation LinkBuilder found for " + entity.getClass().getCanonicalName());
}
final Link relativeDocsLink = docsLinkBuilder.createLink(entity);
final Link fullDocsLink = getFullLink(baseUri, relativeDocsLink);
final LinkableDocs docsEntity = (LinkableDocs) entity;
docsEntity.setLinkDocs(fullDocsLink);
}
}
public <E extends LinkableEntity> void populateFullLinks(final Iterable<E> entities, final URI baseUri) {
if (entities == null) {
return;
}
entities.forEach(e -> populateFullLinks(e, baseUri));
}
private Link getFullLink(final URI baseUri, final Link relativeLink) {
final URI relativeUri = relativeLink.getUri();
final URI fullUri = UriBuilder.fromUri(baseUri)
.path(relativeUri.getPath())
.build();
return Link.fromUri(fullUri)
.rel(relativeLink.getRel())
.build();
}
}