/*
* Copyright 2015-2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed 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.hawkular.inventory.rest.deprecated;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static javax.ws.rs.core.Response.Status.FORBIDDEN;
import static org.hawkular.inventory.api.Relationships.WellKnown.defines;
import static org.hawkular.inventory.rest.RequestUtil.extractPaging;
import java.util.Collection;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.Encoded;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.hawkular.inventory.api.Environments;
import org.hawkular.inventory.api.Feeds;
import org.hawkular.inventory.api.ResolvingToMultiple;
import org.hawkular.inventory.api.Resources;
import org.hawkular.inventory.api.filters.Filter;
import org.hawkular.inventory.api.filters.Related;
import org.hawkular.inventory.api.filters.With;
import org.hawkular.inventory.api.model.Environment;
import org.hawkular.inventory.api.model.Feed;
import org.hawkular.inventory.api.model.Resource;
import org.hawkular.inventory.api.model.Tenant;
import org.hawkular.inventory.api.paging.Page;
import org.hawkular.inventory.api.paging.Pager;
import org.hawkular.inventory.paths.CanonicalPath;
import org.hawkular.inventory.paths.Path;
import org.hawkular.inventory.rest.ResponseUtil;
import org.hawkular.inventory.rest.RestBase;
import org.hawkular.inventory.rest.deprecated.filters.ResourceFilters;
import org.hawkular.inventory.rest.json.ApiError;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
/**
* @author Lukas Krejci
* @since 1.0
*/
@javax.ws.rs.Path("/deprecated")
@Produces(APPLICATION_JSON)
@Consumes(APPLICATION_JSON)
@Api(value = "/deprecated", description = "Resources CRUD", tags = {"Deprecated"})
public class RestResources extends RestBase {
@POST
@javax.ws.rs.Path("/{environmentId}/resources")
@ApiOperation("Creates a new resource")
@ApiResponses({
@ApiResponse(code = 201, message = "Resource successfully created"),
@ApiResponse(code = 400, message = "Invalid input data", response = ApiError.class),
@ApiResponse(code = 404, message = "Tenant or environment doesn't exist", response = ApiError.class),
@ApiResponse(code = 409, message = "Resource already exists", response = ApiError.class),
@ApiResponse(code = 500, message = "Server error", response = ApiError.class)
})
public Response addResource(@PathParam("environmentId") String environmentId,
@ApiParam(required = true) Resource.Blueprint resource, @Context UriInfo uriInfo) {
String tenantId = getTenantId();
CanonicalPath env = CanonicalPath.of().tenant(tenantId).environment(environmentId).get();
if (!security.canCreate(Resource.class).under(env)) {
return Response.status(FORBIDDEN).build();
}
Resource entity = inventory.inspect(env, Environments.Single.class).resources().create(resource).entity();
return ResponseUtil.created(entity, uriInfo, resource.getId()).build();
}
@POST
@javax.ws.rs.Path("/{environmentId}/resources/{parentPath:.+}")
@ApiOperation("Creates a new resource")
@ApiResponses({
@ApiResponse(code = 201, message = "Resource successfully created"),
@ApiResponse(code = 400, message = "Invalid input data", response = ApiError.class),
@ApiResponse(code = 404, message = "Tenant or environment doesn't exist", response = ApiError.class),
@ApiResponse(code = 409, message = "Resource already exists", response = ApiError.class),
@ApiResponse(code = 500, message = "Server error", response = ApiError.class)
})
public Response addResource(@PathParam("environmentId") String environmentId,
@Encoded @PathParam("parentPath") String parentPath, @ApiParam(required = true) Resource.Blueprint resource,
@Context UriInfo uriInfo) {
String tenantId = getTenantId();
CanonicalPath parent = composeCanonicalPath(tenantId, environmentId, null, parentPath);
if (!security.canCreate(Resource.class).under(parent)) {
return Response.status(FORBIDDEN).build();
}
Resource entity = inventory.inspect(parent, Resources.Single.class).resources().create(resource).entity();
return ResponseUtil.created(entity, uriInfo, resource.getId()).build();
}
@POST
@javax.ws.rs.Path("/feeds/{feedId}/resources")
@ApiOperation("Creates a new resource")
@ApiResponses({
@ApiResponse(code = 201, message = "Resource successfully created"),
@ApiResponse(code = 400, message = "Invalid input data", response = ApiError.class),
@ApiResponse(code = 404, message = "Tenant or feed doesn't exist", response = ApiError.class),
@ApiResponse(code = 409, message = "Resource already exists", response = ApiError.class),
@ApiResponse(code = 500, message = "Server error", response = ApiError.class)
})
public Response addFeedResource(@PathParam("feedId") String feedId,
@ApiParam(required = true) Resource.Blueprint resource, @Context UriInfo uriInfo) {
String tenantId = getTenantId();
CanonicalPath feed = CanonicalPath.of().tenant(tenantId).feed(feedId).get();
if (!security.canCreate(Resource.class).under(feed)) {
return Response.status(FORBIDDEN).build();
}
Resource entity = inventory.inspect(feed, Feeds.Single.class).resources().create(resource).entity();
return ResponseUtil.created(entity, uriInfo, resource.getId()).build();
}
@POST
@javax.ws.rs.Path("/feeds/{feedId}/resources/{parentPath:.+}")
@ApiOperation("Creates a new resource")
@ApiResponses({
@ApiResponse(code = 201, message = "Resource successfully created"),
@ApiResponse(code = 400, message = "Invalid input data", response = ApiError.class),
@ApiResponse(code = 404, message = "Tenant or feed doesn't exist", response = ApiError.class),
@ApiResponse(code = 409, message = "Resource already exists", response = ApiError.class),
@ApiResponse(code = 500, message = "Server error", response = ApiError.class)
})
public Response addFeedResource(@PathParam("feedId") String feedId,
@Encoded @PathParam("parentPath") String parentPath,
@ApiParam(required = true) Resource.Blueprint resource, @Context UriInfo uriInfo) {
String tenantId = getTenantId();
CanonicalPath parent = composeCanonicalPath(tenantId, null, feedId, parentPath);
if (!security.canCreate(Resource.class).under(parent)) {
return Response.status(FORBIDDEN).build();
}
Resource entity = inventory.inspect(parent, Resources.Single.class).resources().create(resource).entity();
return ResponseUtil.created(entity, uriInfo, resource.getId()).build();
}
// TODO the is one of the few bits of querying in the API. How should we go about it generally?
// Copy the approach taken here on appropriate places or go with something more generic like a textual
// representation of our Java API?
@GET
@javax.ws.rs.Path("/{environmentId}/resources")
@ApiOperation("Retrieves resources in the environment, optionally filtering by resource type. Accepts paging " +
"query parameters.")
@ApiResponses({
@ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 404, message = "Tenant or environment doesn't exist", response = ApiError.class),
@ApiResponse(code = 500, message = "Server error", response = ApiError.class)
})
public Response getResources(@PathParam("environmentId") String environmentId,
@QueryParam("type") String typeId, @QueryParam("feedless") @DefaultValue("false") boolean feedless,
@Context UriInfo uriInfo) {
String tenantId = getTenantId();
Environments.Single envs = inventory.tenants().get(tenantId).environments().get(environmentId);
ResolvingToMultiple<Resources.Multiple> rr = feedless ? envs.resources() : envs.resources();
Pager pager = extractPaging(uriInfo);
ResourceFilters filters = new ResourceFilters(tenantId, uriInfo.getQueryParameters());
Page<Resource> rs = rr.getAll(filters.get()).entities(pager);
return pagedResponse(Response.ok(), uriInfo, rs).build();
}
@GET
@javax.ws.rs.Path("/feeds/{feedId}/resources")
@ApiOperation("Retrieves resources in the feed, optionally filtering by resource type")
@ApiResponses({
@ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 404, message = "Tenant, environment or feed doesn't exist", response = ApiError.class),
@ApiResponse(code = 500, message = "Server error", response = ApiError.class)
})
public Response getResources(@PathParam("feedId") String feedId, @Context UriInfo uriInfo) {
String tenantId = getTenantId();
Resources.ReadWrite rr = inventory.tenants().get(tenantId).feeds().get(feedId).resources();
Pager pager = extractPaging(uriInfo);
ResourceFilters filters = new ResourceFilters(tenantId, uriInfo.getQueryParameters());
Page<Resource> rs = rr.getAll(filters.get()).entities(pager);
return pagedResponse(Response.ok(), uriInfo, rs).build();
}
@GET
@javax.ws.rs.Path("/{environmentId}/resources/{resourcePath:.+}")
@ApiOperation("Retrieves a single resource")
@ApiResponses({
@ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 404, message = "Tenant, environment or resource doesn't exist",
response = ApiError.class),
@ApiResponse(code = 500, message = "Server error", response = ApiError.class)
})
public Resource getResource(@PathParam("environmentId") String environmentId,
@Encoded @PathParam("resourcePath") String resourcePath) {
CanonicalPath res = composeCanonicalPath(getTenantId(), environmentId, null, resourcePath);
return inventory.inspect(res, Resources.Single.class).entity();
}
@GET
@javax.ws.rs.Path("/feeds/{feedId}/resources/{resourcePath:.+}")
@ApiOperation("Retrieves a single resource")
@ApiResponses({
@ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 404, message = "Tenant, environment, feed or resource doesn't exist",
response = ApiError.class),
@ApiResponse(code = 500, message = "Server error", response = ApiError.class)
})
public Resource getResourceInFeed(@PathParam("feedId") String feedId,
@Encoded @PathParam("resourcePath") String resourcePath) {
CanonicalPath res = composeCanonicalPath(getTenantId(), null, feedId, resourcePath);
return inventory.inspect(res, Resources.Single.class).entity();
}
@GET
@javax.ws.rs.Path("/{environmentId}/resources/{resourcePath:.+}/children")
@ApiOperation("Retrieves child resources of a resource. This can be paged.")
@ApiResponses({
@ApiResponse(code = 200, message = "A list of child resources"),
@ApiResponse(code = 404, message = "environment or the parent resource not found"),
@ApiResponse(code = 500, message = "Internal server error", response = ApiError.class)
})
public Response getChildren(@PathParam("environmentId") String environmentId,
@Encoded @PathParam("resourcePath") String resourcePath, @Context UriInfo uriInfo) {
String tenantId = getTenantId();
CanonicalPath parent = composeCanonicalPath(tenantId, environmentId, null, resourcePath);
Pager pager = extractPaging(uriInfo);
Page<Resource> ret = inventory.inspect(parent, Resources.Single.class).allResources().getAll().entities(pager);
return pagedResponse(Response.ok(), uriInfo, ret).build();
}
@GET
@javax.ws.rs.Path("/feeds/{feedId}/resources/{resourcePath:.+}/children")
@ApiOperation("Retrieves child resources of a resource. This can be paged.")
@ApiResponses({
@ApiResponse(code = 200, message = "A list of child resources"),
@ApiResponse(code = 404, message = "environment or the parent resource not found"),
@ApiResponse(code = 500, message = "Internal server error", response = ApiError.class)
})
public Response getChildrenInFeed(@PathParam("feedId") String feedId,
@Encoded @PathParam("resourcePath") String resourcePath,
@Context UriInfo uriInfo) {
String tenantId = getTenantId();
CanonicalPath parent = composeCanonicalPath(tenantId, null, feedId, resourcePath);
Pager pager = extractPaging(uriInfo);
Page<Resource> ret = inventory.inspect(parent, Resources.Single.class).allResources().getAll().entities(pager);
return pagedResponse(Response.ok(), uriInfo, ret).build();
}
@GET
@javax.ws.rs.Path("/{environmentId}/resources/{resourcePath:.+}/parents")
@ApiOperation("Retrieves parents resources of the resource. This can be paged.")
@ApiResponses({
@ApiResponse(code = 200, message = "A list of child resources"),
@ApiResponse(code = 404, message = "environment or the parent resource not found"),
@ApiResponse(code = 500, message = "Internal server error", response = ApiError.class)
})
public Response getParents(@PathParam("environmentId") String environmentId,
@Encoded @PathParam("resourcePath") String resourcePath, @Context UriInfo uriInfo) {
String tenantId = getTenantId();
CanonicalPath parent = composeCanonicalPath(tenantId, environmentId, null, resourcePath);
Pager pager = extractPaging(uriInfo);
Page<Resource> ret = inventory.inspect(parent, Resources.Single.class).parents().getAll().entities(pager);
return pagedResponse(Response.ok(), uriInfo, ret).build();
}
@GET
@javax.ws.rs.Path("/feeds/{feedId}/resources/{resourcePath:.+}/parents")
@ApiOperation("Retrieves parent resources of a resource. This can be paged.")
@ApiResponses({
@ApiResponse(code = 200, message = "A list of child resources"),
@ApiResponse(code = 404, message = "environment or the parent resource not found"),
@ApiResponse(code = 500, message = "Internal server error", response = ApiError.class)
})
public Response getParentsInFeed(@PathParam("feedId") String feedId,
@Encoded @PathParam("resourcePath") String resourcePath, @Context UriInfo uriInfo) {
String tenantId = getTenantId();
CanonicalPath parent = composeCanonicalPath(tenantId, null, feedId, resourcePath);
Pager pager = extractPaging(uriInfo);
Page<Resource> ret = inventory.inspect(parent, Resources.Single.class).parents().getAll().entities(pager);
return pagedResponse(Response.ok(), uriInfo, ret).build();
}
@GET
@javax.ws.rs.Path("/{environmentId}/resources/{resourcePath:.+}/parent")
@ApiOperation("Retrieves the parent resources that contains the given resource. Such parent resource will not" +
" exist for resources directly contained in an environment or a feed.")
@ApiResponses({
@ApiResponse(code = 200, message = "A list of child resources"),
@ApiResponse(code = 404, message = "environment or the resource not found"),
@ApiResponse(code = 500, message = "Internal server error", response = ApiError.class)
})
public Resource getParent(@PathParam("environmentId") String environmentId,
@Encoded @PathParam("resourcePath") String resourcePath) {
String tenantId = getTenantId();
CanonicalPath resource = composeCanonicalPath(tenantId, environmentId, null, resourcePath);
return inventory.inspect(resource, Resources.Single.class).parent().entity();
}
@GET
@javax.ws.rs.Path("/feeds/{feedId}/resources/{resourcePath:.+}/parent")
@ApiOperation("Retrieves the parent resources that contains the given resource. Such parent resource will not" +
" exist for resources directly contained in an environment or a feed.")
@ApiResponses({
@ApiResponse(code = 200, message = "A list of child resources"),
@ApiResponse(code = 404, message = "environment, feed or the resource not found"),
@ApiResponse(code = 500, message = "Internal server error", response = ApiError.class)
})
public Resource getParentInFeed(@PathParam("feedId") String feedId,
@Encoded @PathParam("resourcePath") String resourcePath) {
String tenantId = getTenantId();
CanonicalPath resource = composeCanonicalPath(tenantId, null, feedId, resourcePath);
return inventory.inspect(resource, Resources.Single.class).parent().entity();
}
@POST
@javax.ws.rs.Path("/{environmentId}/resources/{resourcePath:.+}/children")
@ApiOperation("Associates given resources as children of a given resource.")
@ApiResponses({
@ApiResponse(code = 204, message = "OK"),
@ApiResponse(code = 404, message = "environment or the parent resource not found"),
@ApiResponse(code = 500, message = "Internal server error", response = ApiError.class)
})
public Response associateChildren(@PathParam("environmentId") String environmentId,
@Encoded @PathParam("resourcePath") String resourcePath,
@ApiParam("resources") Collection<String> resources) {
String tenantId = getTenantId();
CanonicalPath tenantPath = CanonicalPath.of().tenant(tenantId).get();
CanonicalPath parent = composeCanonicalPath(tenantId, environmentId, null, resourcePath);
Resources.ReadAssociate access = inventory.inspect(parent, Resources.Single.class).allResources();
resources.stream().map((p) -> Path.fromPartiallyUntypedString(p, tenantPath, parent, Resource.SEGMENT_TYPE))
.forEach(access::associate);
return Response.noContent().build();
}
@POST
@javax.ws.rs.Path("/feeds/{feedId}/resources/{resourcePath:.+}/children")
@ApiOperation("Associates given resources as children of a given resource.")
@ApiResponses({
@ApiResponse(code = 204, message = "OK"),
@ApiResponse(code = 404, message = "environment or the parent resource not found"),
@ApiResponse(code = 500, message = "Internal server error", response = ApiError.class)
})
public Response associateChildrenInFeed(@PathParam("feedId") String feedId,
@Encoded @PathParam("resourcePath") String resourcePath,
@ApiParam("resources") Collection<String> resources) {
String tenantId = getTenantId();
CanonicalPath tenantPath = CanonicalPath.of().tenant(tenantId).get();
CanonicalPath parent = composeCanonicalPath(tenantId, null, feedId, resourcePath);
Resources.ReadAssociate access = inventory.inspect(parent, Resources.Single.class).allResources();
resources.stream().map((p) -> Path.fromPartiallyUntypedString(p, tenantPath, parent, Resource.SEGMENT_TYPE))
.forEach(access::associate);
return Response.noContent().build();
}
@DELETE
@javax.ws.rs.Path("/{environmentId}/resources/{resourcePath:.+}/children/{childPath:.+}")
@ApiOperation("Disassociates given child resource from given resource. The the resource doesn't own the child, " +
"the child will no longer be considered a child of the resource, otherwise an error will be returned.")
@ApiResponses({
@ApiResponse(code = 204, message = "OK"),
@ApiResponse(code = 404, message = "environment, the parent resource or the child resource not found",
response = ApiError.class),
@ApiResponse(code = 500, message = "Internal server error", response = ApiError.class)
})
public Response disassociateChild(@PathParam("environmentId") String environmentId,
@Encoded @PathParam("resourcePath") String resourcePath,
@Encoded @PathParam("childPath") String childPath,
@QueryParam("canonical") @DefaultValue("false") boolean isCanonical) {
String tenantId = getTenantId();
CanonicalPath tenantPath = CanonicalPath.of().tenant(tenantId).get();
CanonicalPath parent = composeCanonicalPath(tenantId, environmentId, null, resourcePath);
if (isCanonical) {
childPath = "/" + childPath;
}
Path child = Path.fromPartiallyUntypedString(childPath, tenantPath, parent, Resource.SEGMENT_TYPE);
inventory.inspect(parent, Resources.Single.class).allResources().disassociate(child);
return Response.noContent().build();
}
@DELETE
@javax.ws.rs.Path("/feeds/{feedId}/resources/{resourcePath:.+}/children/{childPath:.+}")
@ApiOperation("Disassociates given child resource from given resource. The the resource doesn't own the child, " +
"the child will no longer be considered a child of the resource, otherwise an error will be returned.")
@ApiResponses({
@ApiResponse(code = 204, message = "OK"),
@ApiResponse(code = 404, message = "feed, the parent resource or the child resource not found"),
@ApiResponse(code = 500, message = "Internal server error", response = ApiError.class)
})
public Response disassociateChildInFeed(@PathParam("feedId") String feedId,
@Encoded @PathParam("resourcePath") String resourcePath,
@Encoded @PathParam("childPath") String childPath,
@QueryParam("canonical") @DefaultValue("false") boolean isCanonical) {
String tenantId = getTenantId();
CanonicalPath tenantPath = CanonicalPath.of().tenant(tenantId).get();
CanonicalPath parent = composeCanonicalPath(tenantId, null, feedId, resourcePath);
if (isCanonical) {
childPath = "/" + childPath;
}
Path child = Path.fromPartiallyUntypedString(childPath, tenantPath, parent, Resource.SEGMENT_TYPE);
inventory.inspect(parent, Resources.Single.class).allResources().disassociate(child);
return Response.noContent().build();
}
@PUT
@javax.ws.rs.Path("/{environmentId}/resources/{resourcePath:.+}")
@ApiOperation("Update a resource")
@ApiResponses({
@ApiResponse(code = 204, message = "OK"),
@ApiResponse(code = 400, message = "Invalid input data", response = ApiError.class),
@ApiResponse(code = 404, message = "Resource doesn't exist", response = ApiError.class),
@ApiResponse(code = 500, message = "Server error", response = ApiError.class)
})
public Response update(@PathParam("environmentId") String environmentId,
@Encoded @PathParam("resourcePath") String resourcePath,
@ApiParam(required = true) Resource.Update update) {
String tenantId = getTenantId();
CanonicalPath resource = composeCanonicalPath(tenantId, environmentId, null, resourcePath);
if (!security.canUpdate(resource)) {
return Response.status(FORBIDDEN).build();
}
inventory.inspect(resource, Resources.Single.class).update(update);
return Response.noContent().build();
}
@PUT
@javax.ws.rs.Path("/feeds/{feedId}/resources/{resourcePath:.+}")
@ApiOperation("Update a resource")
@ApiResponses({
@ApiResponse(code = 204, message = "OK"),
@ApiResponse(code = 400, message = "Invalid input data", response = ApiError.class),
@ApiResponse(code = 404, message = "Resource doesn't exist", response = ApiError.class),
@ApiResponse(code = 500, message = "Server error", response = ApiError.class)
})
public Response updateInFeed(@PathParam("feedId") String feedId,
@Encoded @PathParam("resourcePath") String resourcePath,
@ApiParam(required = true) Resource.Update update) {
String tenantId = getTenantId();
CanonicalPath resource = composeCanonicalPath(tenantId, null, feedId, resourcePath);
if (!security.canUpdate(resource)) {
return Response.status(FORBIDDEN).build();
}
inventory.inspect(resource, Resources.Single.class).update(update);
return Response.noContent().build();
}
@DELETE
@javax.ws.rs.Path("/{environmentId}/resources/{resourcePath:.+}")
@ApiOperation("Deletes a single resource")
@ApiResponses({
@ApiResponse(code = 204, message = "OK"),
@ApiResponse(code = 404, message = "Tenant, environment or resource doesn't exist",
response = ApiError.class),
@ApiResponse(code = 500, message = "Server error", response = ApiError.class)
})
public Response deleteResource(@PathParam("environmentId") String environmentId,
@Encoded @PathParam("resourcePath") String resourcePath) {
String tenantId = getTenantId();
CanonicalPath resource = composeCanonicalPath(tenantId, environmentId, null, resourcePath);
if (!security.canDelete(resource)) {
return Response.status(FORBIDDEN).build();
}
inventory.inspect(resource, Resources.Single.class).delete();
return Response.noContent().build();
}
@DELETE
@javax.ws.rs.Path("/feeds/{feedId}/resources/{resourcePath:.+}")
@ApiOperation("Retrieves a single resource")
@ApiResponses({
@ApiResponse(code = 204, message = "OK"),
@ApiResponse(code = 404, message = "Tenant, environment, feed or resource doesn't exist",
response = ApiError.class),
@ApiResponse(code = 500, message = "Server error", response = ApiError.class)
})
public Response deleteResourceInFeed(@PathParam("feedId") String feedId,
@Encoded @PathParam("resourcePath") String resourcePath) {
String tenantId = getTenantId();
CanonicalPath resource = composeCanonicalPath(tenantId, null, feedId, resourcePath);
if (!security.canDelete(resource)) {
return Response.status(FORBIDDEN).build();
}
inventory.inspect(resource, Resources.Single.class).delete();
return Response.noContent().build();
}
protected CanonicalPath composeCanonicalPath(String tenantId, String envId, String feedId, String resourcePath) {
CanonicalPath.Extender parent = CanonicalPath.empty().extend(Tenant.SEGMENT_TYPE, tenantId);
if (feedId != null) {
parent = parent.extend(Feed.SEGMENT_TYPE, feedId);
} else {
parent = parent.extend(Environment.SEGMENT_TYPE, envId);
}
return CanonicalPath.fromPartiallyUntypedString(parent.get().toString() + "/" + resourcePath, parent.get(),
Resource.SEGMENT_TYPE);
}
@GET
@javax.ws.rs.Path("/{environmentId}/resources/{resourcePath:.+}/recursiveChildren")
@ApiOperation("Recursively retrieves child resources of a resource of given type. Can be paged.")
@ApiResponses({
@ApiResponse(code = 200, message = "A list of child resources"),
@ApiResponse(code = 404, message = "environment or the parent resource not found"),
@ApiResponse(code = 500, message = "Internal server error", response = ApiError.class)
})
public Response getRecursiveChildren(@PathParam("environmentId") String environmentId,
@Encoded @PathParam("resourcePath") String resourcePath,
@Encoded @QueryParam("typeId") String resourceTypeId,
@Context UriInfo uriInfo) {
Page<Resource> rs = getRecursiveChildren(environmentId, null, resourcePath, resourceTypeId, true,
extractPaging(uriInfo));
return pagedResponse(Response.ok(), uriInfo, rs).build();
}
@GET
@javax.ws.rs.Path("/feeds/{feedId}/resources/{resourcePath:.+}/recursiveChildren")
@ApiOperation("Recursively retrieves child resources of a resource of given type. Can be paged.")
@ApiResponses({
@ApiResponse(code = 200, message = "A list of child resources"),
@ApiResponse(code = 404, message = "environment or the parent resource not found"),
@ApiResponse(code = 500, message = "Internal server error", response = ApiError.class)
})
public Response getRecursiveChildren(@PathParam("feedId") String feedId,
@Encoded @PathParam("resourcePath") String resourcePath,
@Encoded @QueryParam("typeId") String resourceTypeId,
@QueryParam("feedlessType") @DefaultValue("false") boolean feedlessType,
@Context UriInfo uriInfo) {
Page<Resource> rs = getRecursiveChildren(null, feedId, resourcePath, resourceTypeId, feedlessType,
extractPaging(uriInfo));
return pagedResponse(Response.ok(), uriInfo, rs).build();
}
private Page<Resource> getRecursiveChildren(String environmentId, String feedId, String
resourcePath, String resourceTypeId, boolean feedlessResourceType, Pager pager) {
String tenantId = getTenantId();
CanonicalPath parent = composeCanonicalPath(tenantId, environmentId, feedId, resourcePath);
Filter[][] resourceFilter = new Filter[0][];
if (resourceTypeId != null) {
CanonicalPath resourceTypePath = feedlessResourceType
? CanonicalPath.of().tenant(tenantId).resourceType(resourceTypeId).get()
: CanonicalPath.of().tenant(tenantId).feed(feedId).resourceType(resourceTypeId).get();
resourceFilter = new Filter[][]{{Related.asTargetBy(defines), With.path(resourceTypePath)}};
}
return inventory.inspect(parent, Resources.Single.class).recursiveResources().getAll(resourceFilter)
.entities(pager);
}
}