@Test public void testCloneStackVersion() throws Exception { final StackId clonedStackId = new StackId(completeStackId.getOwner(), completeStackId.getProject(), "clonedStack"); try { service.getStackMetaData(clonedStackId.getOwner(), clonedStackId.getProject(), clonedStackId.getStack()); Assert.fail("before clone, meta data should not exist for " + clonedStackId); } catch (final ObjectNotFoundException e) { Assert.assertTrue(true); } final StackVersion clonedStackVersion = new StackVersion(new Date(), "cloned", 1, 2, 3.1, 4.1, 5.1, null, null); service.cloneStackVersion(completeStackId.getOwner(), completeStackId.getProject(), completeStackId.getStack(), clonedStackId.getStack(), null, null, null, getUriInfo(), clonedStackVersion); final StackMetaData clonedStackMetaData = service.getStackMetaData(clonedStackId.getOwner(), clonedStackId.getProject(), clonedStackId.getStack()); RenderDaoTest.validateStackMetaData(" for cloned stack", LOADING, 0, clonedStackVersion, clonedStackMetaData); }
@Path("v1/owner/{owner}/project/{fromProject}/stack/{fromStack}/cloneTo/{toStack}") @PUT @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( tags = {"Stack Data APIs"}, value = "Clones one stack to another", notes = "This operation copies all fromStack tiles and transformations to a new stack with the specified metadata. This is a potentially long running operation (depending upon the size of the fromStack).") @ApiResponses(value = { @ApiResponse(code = 201, message = "stack successfully cloned"), @ApiResponse(code = 400, message = "toStack is not in LOADING state"), @ApiResponse(code = 404, message = "fromStack not found") }) public Response cloneStackVersion(@PathParam("owner") final String owner, @PathParam("fromProject") final String fromProject, @PathParam("fromStack") final String fromStack, @PathParam("toStack") final String toStack, @QueryParam("z") final List<Double> zValues, @QueryParam("toProject") String toProject, @QueryParam("skipTransforms") final Boolean skipTransforms, @Context final UriInfo uriInfo, final StackVersion stackVersion) { LOG.info("cloneStackVersion: entry, owner={}, fromProject={}, fromStack={}, toProject={}, toStack={}, zValues={}, stackVersion={}", owner, fromProject, fromStack, toProject, toStack, zValues, stackVersion); try { if (stackVersion == null) { throw new IllegalArgumentException("no stack version provided"); } if (toProject == null) { toProject = fromProject; } final StackMetaData fromStackMetaData = getStackMetaData(owner, fromProject, fromStack); final StackId toStackId = new StackId(owner, toProject, toStack); StackMetaData toStackMetaData = renderDao.getStackMetaData(toStackId); if ((toStackMetaData != null) && (! toStackMetaData.isLoading())) { throw new IllegalStateException("Tiles cannot be cloned to stack " + toStack + " because it is " + toStackMetaData.getState() + "."); } renderDao.cloneStack(fromStackMetaData.getStackId(), toStackId, zValues, skipTransforms); toStackMetaData = new StackMetaData(toStackId, stackVersion); renderDao.saveStackMetaData(toStackMetaData); LOG.info("cloneStackVersion: created {} from {}", toStackId, fromStackMetaData.getStackId()); } catch (final Throwable t) { RenderServiceUtil.throwServiceException(t); } final Response.ResponseBuilder responseBuilder = Response.created(uriInfo.getRequestUri()); return responseBuilder.build(); }
StackMetaDataService { @Path("v1/owner/{owner}/project/{fromProject}/stack/{fromStack}/cloneTo/{toStack}") @PUT @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( tags = {"Stack Data APIs"}, value = "Clones one stack to another", notes = "This operation copies all fromStack tiles and transformations to a new stack with the specified metadata. This is a potentially long running operation (depending upon the size of the fromStack).") @ApiResponses(value = { @ApiResponse(code = 201, message = "stack successfully cloned"), @ApiResponse(code = 400, message = "toStack is not in LOADING state"), @ApiResponse(code = 404, message = "fromStack not found") }) public Response cloneStackVersion(@PathParam("owner") final String owner, @PathParam("fromProject") final String fromProject, @PathParam("fromStack") final String fromStack, @PathParam("toStack") final String toStack, @QueryParam("z") final List<Double> zValues, @QueryParam("toProject") String toProject, @QueryParam("skipTransforms") final Boolean skipTransforms, @Context final UriInfo uriInfo, final StackVersion stackVersion) { LOG.info("cloneStackVersion: entry, owner={}, fromProject={}, fromStack={}, toProject={}, toStack={}, zValues={}, stackVersion={}", owner, fromProject, fromStack, toProject, toStack, zValues, stackVersion); try { if (stackVersion == null) { throw new IllegalArgumentException("no stack version provided"); } if (toProject == null) { toProject = fromProject; } final StackMetaData fromStackMetaData = getStackMetaData(owner, fromProject, fromStack); final StackId toStackId = new StackId(owner, toProject, toStack); StackMetaData toStackMetaData = renderDao.getStackMetaData(toStackId); if ((toStackMetaData != null) && (! toStackMetaData.isLoading())) { throw new IllegalStateException("Tiles cannot be cloned to stack " + toStack + " because it is " + toStackMetaData.getState() + "."); } renderDao.cloneStack(fromStackMetaData.getStackId(), toStackId, zValues, skipTransforms); toStackMetaData = new StackMetaData(toStackId, stackVersion); renderDao.saveStackMetaData(toStackMetaData); LOG.info("cloneStackVersion: created {} from {}", toStackId, fromStackMetaData.getStackId()); } catch (final Throwable t) { RenderServiceUtil.throwServiceException(t); } final Response.ResponseBuilder responseBuilder = Response.created(uriInfo.getRequestUri()); return responseBuilder.build(); } }
StackMetaDataService { @Path("v1/owner/{owner}/project/{fromProject}/stack/{fromStack}/cloneTo/{toStack}") @PUT @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( tags = {"Stack Data APIs"}, value = "Clones one stack to another", notes = "This operation copies all fromStack tiles and transformations to a new stack with the specified metadata. This is a potentially long running operation (depending upon the size of the fromStack).") @ApiResponses(value = { @ApiResponse(code = 201, message = "stack successfully cloned"), @ApiResponse(code = 400, message = "toStack is not in LOADING state"), @ApiResponse(code = 404, message = "fromStack not found") }) public Response cloneStackVersion(@PathParam("owner") final String owner, @PathParam("fromProject") final String fromProject, @PathParam("fromStack") final String fromStack, @PathParam("toStack") final String toStack, @QueryParam("z") final List<Double> zValues, @QueryParam("toProject") String toProject, @QueryParam("skipTransforms") final Boolean skipTransforms, @Context final UriInfo uriInfo, final StackVersion stackVersion) { LOG.info("cloneStackVersion: entry, owner={}, fromProject={}, fromStack={}, toProject={}, toStack={}, zValues={}, stackVersion={}", owner, fromProject, fromStack, toProject, toStack, zValues, stackVersion); try { if (stackVersion == null) { throw new IllegalArgumentException("no stack version provided"); } if (toProject == null) { toProject = fromProject; } final StackMetaData fromStackMetaData = getStackMetaData(owner, fromProject, fromStack); final StackId toStackId = new StackId(owner, toProject, toStack); StackMetaData toStackMetaData = renderDao.getStackMetaData(toStackId); if ((toStackMetaData != null) && (! toStackMetaData.isLoading())) { throw new IllegalStateException("Tiles cannot be cloned to stack " + toStack + " because it is " + toStackMetaData.getState() + "."); } renderDao.cloneStack(fromStackMetaData.getStackId(), toStackId, zValues, skipTransforms); toStackMetaData = new StackMetaData(toStackId, stackVersion); renderDao.saveStackMetaData(toStackMetaData); LOG.info("cloneStackVersion: created {} from {}", toStackId, fromStackMetaData.getStackId()); } catch (final Throwable t) { RenderServiceUtil.throwServiceException(t); } final Response.ResponseBuilder responseBuilder = Response.created(uriInfo.getRequestUri()); return responseBuilder.build(); } @SuppressWarnings("UnusedDeclaration")  StackMetaDataService();   StackMetaDataService(final RenderDao renderDao); }
StackMetaDataService { @Path("v1/owner/{owner}/project/{fromProject}/stack/{fromStack}/cloneTo/{toStack}") @PUT @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( tags = {"Stack Data APIs"}, value = "Clones one stack to another", notes = "This operation copies all fromStack tiles and transformations to a new stack with the specified metadata. This is a potentially long running operation (depending upon the size of the fromStack).") @ApiResponses(value = { @ApiResponse(code = 201, message = "stack successfully cloned"), @ApiResponse(code = 400, message = "toStack is not in LOADING state"), @ApiResponse(code = 404, message = "fromStack not found") }) public Response cloneStackVersion(@PathParam("owner") final String owner, @PathParam("fromProject") final String fromProject, @PathParam("fromStack") final String fromStack, @PathParam("toStack") final String toStack, @QueryParam("z") final List<Double> zValues, @QueryParam("toProject") String toProject, @QueryParam("skipTransforms") final Boolean skipTransforms, @Context final UriInfo uriInfo, final StackVersion stackVersion) { LOG.info("cloneStackVersion: entry, owner={}, fromProject={}, fromStack={}, toProject={}, toStack={}, zValues={}, stackVersion={}", owner, fromProject, fromStack, toProject, toStack, zValues, stackVersion); try { if (stackVersion == null) { throw new IllegalArgumentException("no stack version provided"); } if (toProject == null) { toProject = fromProject; } final StackMetaData fromStackMetaData = getStackMetaData(owner, fromProject, fromStack); final StackId toStackId = new StackId(owner, toProject, toStack); StackMetaData toStackMetaData = renderDao.getStackMetaData(toStackId); if ((toStackMetaData != null) && (! toStackMetaData.isLoading())) { throw new IllegalStateException("Tiles cannot be cloned to stack " + toStack + " because it is " + toStackMetaData.getState() + "."); } renderDao.cloneStack(fromStackMetaData.getStackId(), toStackId, zValues, skipTransforms); toStackMetaData = new StackMetaData(toStackId, stackVersion); renderDao.saveStackMetaData(toStackMetaData); LOG.info("cloneStackVersion: created {} from {}", toStackId, fromStackMetaData.getStackId()); } catch (final Throwable t) { RenderServiceUtil.throwServiceException(t); } final Response.ResponseBuilder responseBuilder = Response.created(uriInfo.getRequestUri()); return responseBuilder.build(); } @SuppressWarnings("UnusedDeclaration")  StackMetaDataService();   StackMetaDataService(final RenderDao renderDao); @Path("v1/likelyUniqueId") @GET @Produces(MediaType.TEXT_PLAIN) @ApiOperation(value = "A (very likely) globally unique identifier") String getUniqueId(); @Path("v1/owners") @GET @Produces(MediaType.APPLICATION_JSON) @ApiOperation(value = "List of all data owners") List<String> getOwners(); @Path("v1/owner/{owner}/projects") @GET @Produces(MediaType.APPLICATION_JSON) @ApiOperation(value = "List of projects for the specified owner") List<String> getProjectsForOwner(@PathParam("owner") final String owner); @Path("v1/owner/{owner}/stackIds") @GET @Produces(MediaType.APPLICATION_JSON) @ApiOperation(value = "List of stack identifiers for the specified owner") List<StackId> getStackIdsForOwner(@PathParam("owner") final String owner); @Path("v1/owner/{owner}/project/{project}/stackIds") @GET @Produces(MediaType.APPLICATION_JSON) @ApiOperation(value = "List of stack identifiers for the specified project") List<StackId> getStackIdsForProject(@PathParam("owner") final String owner,
                                               @PathParam("project") final String project); @Path("v1/owner/{owner}/stacks") @GET @Produces(MediaType.APPLICATION_JSON) @ApiOperation(value = "List of stack metadata for the specified owner") List<StackMetaData> getStackMetaDataListForOwner(@PathParam("owner") final String owner); @Path("v1/owner/{owner}/project/{project}/stacks") @GET @Produces(MediaType.APPLICATION_JSON) @ApiOperation(value = "List of stack metadata for the specified project") List<StackMetaData> getStackMetaDataListForProject(@PathParam("owner") final String owner,
                                                              @PathParam("project") final String project); @Path("v1/owner/{owner}/project/{project}/stack/{stack}") @GET @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Metadata for the specified stack") @ApiResponses(value = { @ApiResponse(code = 404, message = "Stack not found") }) StackMetaData getStackMetaData(@PathParam("owner") final String owner,
                                          @PathParam("project") final String project,
                                          @PathParam("stack") final String stack); @Path("v1/owner/{owner}/project/{fromProject}/stack/{fromStack}/stackId") @PUT @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( tags = {"Stack Data APIs"}, value = "Rename a stack") @ApiResponses(value = { @ApiResponse(code = 200, message = "stack successfully renamed"), @ApiResponse(code = 400, message = "stack cannot be renamed"), @ApiResponse(code = 404, message = "stack not found") }) Response renameStack(@PathParam("owner") final String owner,
                                @PathParam("fromProject") final String fromProject,
                                @PathParam("fromStack") final String fromStack,
                                @Context final UriInfo uriInfo,
                                final StackId toStackId); @Path("v1/owner/{owner}/project/{fromProject}/stack/{fromStack}/cloneTo/{toStack}") @PUT @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( tags = {"Stack Data APIs"}, value = "Clones one stack to another", notes = "This operation copies all fromStack tiles and transformations to a new stack with the specified metadata. This is a potentially long running operation (depending upon the size of the fromStack).") @ApiResponses(value = { @ApiResponse(code = 201, message = "stack successfully cloned"), @ApiResponse(code = 400, message = "toStack is not in LOADING state"), @ApiResponse(code = 404, message = "fromStack not found") }) Response cloneStackVersion(@PathParam("owner") final String owner,
                                      @PathParam("fromProject") final String fromProject,
                                      @PathParam("fromStack") final String fromStack,
                                      @PathParam("toStack") final String toStack,
                                      @QueryParam("z") final List<Double> zValues,
                                      @QueryParam("toProject") String toProject,
                                      @QueryParam("skipTransforms") final Boolean skipTransforms,
                                      @Context final UriInfo uriInfo,
                                      final StackVersion stackVersion); @Path("v1/owner/{owner}/project/{project}/stack/{stack}") @POST // NOTE: POST method is used because version number is auto-incremented @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( tags = {"Stack Data APIs"}, value = "Saves new version of stack metadata") @ApiResponses(value = { @ApiResponse(code = 201, message = "stackVersion successfully created"), @ApiResponse(code = 400, message = "stackVersion not specified or stack is READ_ONLY") }) Response saveStackVersion(@PathParam("owner") final String owner,
                                     @PathParam("project") final String project,
                                     @PathParam("stack") final String stack,
                                     @Context final UriInfo uriInfo,
                                     final StackVersion stackVersion); @Path("v1/owner/{owner}/project/{project}/stack/{stack}") @DELETE @ApiOperation( tags = {"Stack Data APIs"}, value = "Deletes specified stack", notes = "Deletes all tiles, transformations, meta data, and unsaved snapshot data for the stack.") @ApiResponses(value = { @ApiResponse(code = 400, message = "stack is READ_ONLY") }) Response deleteStack(@PathParam("owner") final String owner,
                                @PathParam("project") final String project,
                                @PathParam("stack") final String stack); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/resolutionValues") @GET @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "The x, y, and z resolution values for the specified stack") @ApiResponses(value = { @ApiResponse(code = 404, message = "Stack not found") }) List<Double> getResolutionValues(@PathParam("owner") final String owner,
                                            @PathParam("project") final String project,
                                            @PathParam("stack") final String stack); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/resolutionValues") @PUT @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( tags = {"Stack Data APIs"}, value = "Saves x, y, and z resolution values for stack") @ApiResponses(value = { @ApiResponse(code = 200, message = "resolution values successfully saved"), @ApiResponse(code = 400, message = "stack is READ_ONLY"), @ApiResponse(code = 404, message = "stack not found") }) Response saveResolutionValues(@PathParam("owner") final String owner,
                                         @PathParam("project") final String project,
                                         @PathParam("stack") final String stack,
                                         final List<Double> resolutionValues); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/resolutionValues") @DELETE @ApiOperation( tags = {"Stack Data APIs"}, value = "Deletes x, y, and z resolution values for stack") @ApiResponses(value = { @ApiResponse(code = 400, message = "stack is READ_ONLY"), @ApiResponse(code = 404, message = "stack not found") }) Response deleteResolutionValues(@PathParam("owner") final String owner,
                                           @PathParam("project") final String project,
                                           @PathParam("stack") final String stack); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/materializedBoxRootPath") @GET @Produces(MediaType.TEXT_PLAIN) @ApiOperation( value = "The materializedBoxRootPath for the specified stack") @ApiResponses(value = { @ApiResponse(code = 404, message = "Stack not found") }) String getMaterializedBoxRootPath(@PathParam("owner") final String owner,
                                             @PathParam("project") final String project,
                                             @PathParam("stack") final String stack); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/materializedBoxRootPath") @PUT @Consumes(MediaType.TEXT_PLAIN) @ApiOperation( tags = {"Stack Data APIs"}, value = "Saves materializedBoxRootPath for stack") @ApiResponses(value = { @ApiResponse(code = 200, message = "materializedBoxRootPath successfully saved"), @ApiResponse(code = 400, message = "stack is READ_ONLY"), @ApiResponse(code = 404, message = "stack not found") }) Response saveMaterializedBoxRootPath(@PathParam("owner") final String owner,
                                                @PathParam("project") final String project,
                                                @PathParam("stack") final String stack,
                                                final String materializedBoxRootPath); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/materializedBoxRootPath") @DELETE @ApiOperation( tags = {"Stack Data APIs"}, value = "Deletes materializedBoxRootPath for stack") @ApiResponses(value = { @ApiResponse(code = 400, message = "stack is READ_ONLY"), @ApiResponse(code = 404, message = "stack not found") }) Response deleteMaterializedBoxRootPath(@PathParam("owner") final String owner,
                                                  @PathParam("project") final String project,
                                                  @PathParam("stack") final String stack); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/mipmapPathBuilder") @GET @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "The mipmap path builder specs for the specified stack") @ApiResponses(value = { @ApiResponse(code = 404, message = "Stack not found") }) MipmapPathBuilder getMipmapPathBuilder(@PathParam("owner") final String owner,
                                                 @PathParam("project") final String project,
                                                 @PathParam("stack") final String stack); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/mipmapPathBuilder") @PUT @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( tags = {"Stack Data APIs"}, value = "Saves mipmap path builder specs for stack") @ApiResponses(value = { @ApiResponse(code = 200, message = "mipmap path builder specs successfully saved"), @ApiResponse(code = 400, message = "stack is READ_ONLY"), @ApiResponse(code = 404, message = "stack not found") }) Response saveMipmapPathBuilder(@PathParam("owner") final String owner,
                                          @PathParam("project") final String project,
                                          @PathParam("stack") final String stack,
                                          final MipmapPathBuilder mipmapPathBuilder); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/mipmapPathBuilder") @DELETE @ApiOperation( tags = {"Stack Data APIs"}, value = "Deletes mipmap path builder specs for stack") @ApiResponses(value = { @ApiResponse(code = 400, message = "stack is READ_ONLY"), @ApiResponse(code = 404, message = "stack not found") }) Response deleteMipmapPathBuilder(@PathParam("owner") final String owner,
                                            @PathParam("project") final String project,
                                            @PathParam("stack") final String stack); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/defaultChannel") @GET @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "The default channel for the specified stack") @ApiResponses(value = { @ApiResponse(code = 404, message = "Stack not found") }) String getDefaultChannel(@PathParam("owner") final String owner,
                                    @PathParam("project") final String project,
                                    @PathParam("stack") final String stack); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/defaultChannel") @PUT @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( tags = {"Stack Data APIs"}, value = "Saves default channel name for stack") @ApiResponses(value = { @ApiResponse(code = 200, message = "default channel successfully saved"), @ApiResponse(code = 400, message = "stack is READ_ONLY"), @ApiResponse(code = 404, message = "stack not found") }) Response saveDefaultChannel(@PathParam("owner") final String owner,
                                       @PathParam("project") final String project,
                                       @PathParam("stack") final String stack,
                                       final String defaultChannel); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/defaultChannel") @DELETE @ApiOperation( tags = {"Stack Data APIs"}, value = "Deletes default channel for stack") @ApiResponses(value = { @ApiResponse(code = 400, message = "stack is READ_ONLY"), @ApiResponse(code = 404, message = "stack not found") }) Response deleteDefaultChannel(@PathParam("owner") final String owner,
                                         @PathParam("project") final String project,
                                         @PathParam("stack") final String stack); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/cycle") @GET @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "The cycle data for the specified stack") @ApiResponses(value = { @ApiResponse(code = 404, message = "Stack not found") }) ReconstructionCycle getCycle(@PathParam("owner") final String owner,
                                        @PathParam("project") final String project,
                                        @PathParam("stack") final String stack); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/cycle") @PUT @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( tags = {"Stack Data APIs"}, value = "Saves cycle data for stack") @ApiResponses(value = { @ApiResponse(code = 200, message = "cycle data successfully saved"), @ApiResponse(code = 400, message = "stack is READ_ONLY"), @ApiResponse(code = 404, message = "stack not found") }) Response saveCycle(@PathParam("owner") final String owner,
                              @PathParam("project") final String project,
                              @PathParam("stack") final String stack,
                              final ReconstructionCycle cycle); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/cycle") @DELETE @ApiOperation( tags = {"Stack Data APIs"}, value = "Deletes cycle data for stack") @ApiResponses(value = { @ApiResponse(code = 400, message = "stack is READ_ONLY"), @ApiResponse(code = 404, message = "stack not found") }) Response deleteCycleNumber(@PathParam("owner") final String owner,
                                      @PathParam("project") final String project,
                                      @PathParam("stack") final String stack); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/section/{sectionId}") @DELETE @ApiOperation( tags = {"Section Data APIs"}, value = "Deletes all tiles in section", notes = "Deletes all tiles in the specified stack with the specified sectionId value. This operation can only be performed against stacks in the LOADING state") @ApiResponses(value = { @ApiResponse(code = 400, message = "stack state is not LOADING"), @ApiResponse(code = 404, message = "stack not found"), }) Response deleteStackTilesWithSectionId(@PathParam("owner") final String owner,
                                                  @PathParam("project") final String project,
                                                  @PathParam("stack") final String stack,
                                                  @PathParam("sectionId") final String sectionId); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/z/{z}") @DELETE @ApiOperation( tags = {"Section Data APIs"}, value = "Deletes all tiles in layer", notes = "Deletes all tiles in the specified stack with the specified z value. This operation can only be performed against stacks in the LOADING state") @ApiResponses(value = { @ApiResponse(code = 400, message = "stack state is not LOADING"), @ApiResponse(code = 404, message = "stack not found"), }) Response deleteStackTilesWithZ(@PathParam("owner") final String owner,
                                          @PathParam("project") final String project,
                                          @PathParam("stack") final String stack,
                                          @PathParam("z") final Double z); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/state/{state}") @PUT @ApiOperation( tags = {"Stack Data APIs"}, value = "Sets the stack's current state", notes = "Normal progression is LOADING to COMPLETE to READ_ONLY to OFFLINE. " + "Transitioning to COMPLETE is a potentially long running operation " + "since it creates indexes and aggregates meta data. " + "Transitioning to OFFLINE assumes that the stack data has been persisted elsewhere " + "(e.g. a database dump file) and will remove the stack tile and transform collections, " + "so BE CAREFUL when transitioning to OFFLINE!") @ApiResponses(value = { @ApiResponse(code = 201, message = "state successfully changed"), @ApiResponse(code = 400, message = "stack state cannot be changed because of current state"), @ApiResponse(code = 404, message = "stack not found"), }) Response setStackState(@PathParam("owner") final String owner,
                                  @PathParam("project") final String project,
                                  @PathParam("stack") final String stack,
                                  @PathParam("state") final StackState state,
                                  @Context final UriInfo uriInfo); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/bounds") @GET @Produces(MediaType.APPLICATION_JSON) @ApiOperation( tags = {"Stack Data APIs"}, value = "Bounds for the specified stack") @ApiResponses(value = { @ApiResponse(code = 400, message = "stack bounds not available"), @ApiResponse(code = 404, message = "stack not found"), }) Bounds getStackBounds(@PathParam("owner") final String owner,
                                 @PathParam("project") final String project,
                                 @PathParam("stack") final String stack); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/tileIds") @GET @Produces(MediaType.APPLICATION_JSON) @ApiOperation( tags = {"Stack Data APIs"}, value = "Tile IDs for the specified stack", responseContainer = "List", response = String.class, notes = "For stacks with large numbers of tiles, this will produce a large amount of data (e.g. 500MB for 18 million tiles) - use wisely.") Response getStackTileIds(@PathParam("owner") final String owner,
                                    @PathParam("project") final String project,
                                    @PathParam("stack") final String stack); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/tile-specs-with-ids") @PUT @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Get flattened tile specs with the specified ids", notes = "For each tile spec, nested transform lists are flattened and reference transforms are resolved. This should make the specs suitable for external use.") List<TileSpec> getTileSpecsWithIds(@PathParam("owner") final String owner,
                                              @PathParam("project") final String project,
                                              @PathParam("stack") final String stack,
                                              final List<String> tileIdList); static StackMetaData getStackMetaData(final StackId stackId,
                                                 final RenderDao renderDao); }
StackMetaDataService { @Path("v1/owner/{owner}/project/{fromProject}/stack/{fromStack}/cloneTo/{toStack}") @PUT @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( tags = {"Stack Data APIs"}, value = "Clones one stack to another", notes = "This operation copies all fromStack tiles and transformations to a new stack with the specified metadata. This is a potentially long running operation (depending upon the size of the fromStack).") @ApiResponses(value = { @ApiResponse(code = 201, message = "stack successfully cloned"), @ApiResponse(code = 400, message = "toStack is not in LOADING state"), @ApiResponse(code = 404, message = "fromStack not found") }) public Response cloneStackVersion(@PathParam("owner") final String owner, @PathParam("fromProject") final String fromProject, @PathParam("fromStack") final String fromStack, @PathParam("toStack") final String toStack, @QueryParam("z") final List<Double> zValues, @QueryParam("toProject") String toProject, @QueryParam("skipTransforms") final Boolean skipTransforms, @Context final UriInfo uriInfo, final StackVersion stackVersion) { LOG.info("cloneStackVersion: entry, owner={}, fromProject={}, fromStack={}, toProject={}, toStack={}, zValues={}, stackVersion={}", owner, fromProject, fromStack, toProject, toStack, zValues, stackVersion); try { if (stackVersion == null) { throw new IllegalArgumentException("no stack version provided"); } if (toProject == null) { toProject = fromProject; } final StackMetaData fromStackMetaData = getStackMetaData(owner, fromProject, fromStack); final StackId toStackId = new StackId(owner, toProject, toStack); StackMetaData toStackMetaData = renderDao.getStackMetaData(toStackId); if ((toStackMetaData != null) && (! toStackMetaData.isLoading())) { throw new IllegalStateException("Tiles cannot be cloned to stack " + toStack + " because it is " + toStackMetaData.getState() + "."); } renderDao.cloneStack(fromStackMetaData.getStackId(), toStackId, zValues, skipTransforms); toStackMetaData = new StackMetaData(toStackId, stackVersion); renderDao.saveStackMetaData(toStackMetaData); LOG.info("cloneStackVersion: created {} from {}", toStackId, fromStackMetaData.getStackId()); } catch (final Throwable t) { RenderServiceUtil.throwServiceException(t); } final Response.ResponseBuilder responseBuilder = Response.created(uriInfo.getRequestUri()); return responseBuilder.build(); } @SuppressWarnings("UnusedDeclaration")  StackMetaDataService();   StackMetaDataService(final RenderDao renderDao); @Path("v1/likelyUniqueId") @GET @Produces(MediaType.TEXT_PLAIN) @ApiOperation(value = "A (very likely) globally unique identifier") String getUniqueId(); @Path("v1/owners") @GET @Produces(MediaType.APPLICATION_JSON) @ApiOperation(value = "List of all data owners") List<String> getOwners(); @Path("v1/owner/{owner}/projects") @GET @Produces(MediaType.APPLICATION_JSON) @ApiOperation(value = "List of projects for the specified owner") List<String> getProjectsForOwner(@PathParam("owner") final String owner); @Path("v1/owner/{owner}/stackIds") @GET @Produces(MediaType.APPLICATION_JSON) @ApiOperation(value = "List of stack identifiers for the specified owner") List<StackId> getStackIdsForOwner(@PathParam("owner") final String owner); @Path("v1/owner/{owner}/project/{project}/stackIds") @GET @Produces(MediaType.APPLICATION_JSON) @ApiOperation(value = "List of stack identifiers for the specified project") List<StackId> getStackIdsForProject(@PathParam("owner") final String owner,
                                               @PathParam("project") final String project); @Path("v1/owner/{owner}/stacks") @GET @Produces(MediaType.APPLICATION_JSON) @ApiOperation(value = "List of stack metadata for the specified owner") List<StackMetaData> getStackMetaDataListForOwner(@PathParam("owner") final String owner); @Path("v1/owner/{owner}/project/{project}/stacks") @GET @Produces(MediaType.APPLICATION_JSON) @ApiOperation(value = "List of stack metadata for the specified project") List<StackMetaData> getStackMetaDataListForProject(@PathParam("owner") final String owner,
                                                              @PathParam("project") final String project); @Path("v1/owner/{owner}/project/{project}/stack/{stack}") @GET @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Metadata for the specified stack") @ApiResponses(value = { @ApiResponse(code = 404, message = "Stack not found") }) StackMetaData getStackMetaData(@PathParam("owner") final String owner,
                                          @PathParam("project") final String project,
                                          @PathParam("stack") final String stack); @Path("v1/owner/{owner}/project/{fromProject}/stack/{fromStack}/stackId") @PUT @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( tags = {"Stack Data APIs"}, value = "Rename a stack") @ApiResponses(value = { @ApiResponse(code = 200, message = "stack successfully renamed"), @ApiResponse(code = 400, message = "stack cannot be renamed"), @ApiResponse(code = 404, message = "stack not found") }) Response renameStack(@PathParam("owner") final String owner,
                                @PathParam("fromProject") final String fromProject,
                                @PathParam("fromStack") final String fromStack,
                                @Context final UriInfo uriInfo,
                                final StackId toStackId); @Path("v1/owner/{owner}/project/{fromProject}/stack/{fromStack}/cloneTo/{toStack}") @PUT @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( tags = {"Stack Data APIs"}, value = "Clones one stack to another", notes = "This operation copies all fromStack tiles and transformations to a new stack with the specified metadata. This is a potentially long running operation (depending upon the size of the fromStack).") @ApiResponses(value = { @ApiResponse(code = 201, message = "stack successfully cloned"), @ApiResponse(code = 400, message = "toStack is not in LOADING state"), @ApiResponse(code = 404, message = "fromStack not found") }) Response cloneStackVersion(@PathParam("owner") final String owner,
                                      @PathParam("fromProject") final String fromProject,
                                      @PathParam("fromStack") final String fromStack,
                                      @PathParam("toStack") final String toStack,
                                      @QueryParam("z") final List<Double> zValues,
                                      @QueryParam("toProject") String toProject,
                                      @QueryParam("skipTransforms") final Boolean skipTransforms,
                                      @Context final UriInfo uriInfo,
                                      final StackVersion stackVersion); @Path("v1/owner/{owner}/project/{project}/stack/{stack}") @POST // NOTE: POST method is used because version number is auto-incremented @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( tags = {"Stack Data APIs"}, value = "Saves new version of stack metadata") @ApiResponses(value = { @ApiResponse(code = 201, message = "stackVersion successfully created"), @ApiResponse(code = 400, message = "stackVersion not specified or stack is READ_ONLY") }) Response saveStackVersion(@PathParam("owner") final String owner,
                                     @PathParam("project") final String project,
                                     @PathParam("stack") final String stack,
                                     @Context final UriInfo uriInfo,
                                     final StackVersion stackVersion); @Path("v1/owner/{owner}/project/{project}/stack/{stack}") @DELETE @ApiOperation( tags = {"Stack Data APIs"}, value = "Deletes specified stack", notes = "Deletes all tiles, transformations, meta data, and unsaved snapshot data for the stack.") @ApiResponses(value = { @ApiResponse(code = 400, message = "stack is READ_ONLY") }) Response deleteStack(@PathParam("owner") final String owner,
                                @PathParam("project") final String project,
                                @PathParam("stack") final String stack); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/resolutionValues") @GET @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "The x, y, and z resolution values for the specified stack") @ApiResponses(value = { @ApiResponse(code = 404, message = "Stack not found") }) List<Double> getResolutionValues(@PathParam("owner") final String owner,
                                            @PathParam("project") final String project,
                                            @PathParam("stack") final String stack); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/resolutionValues") @PUT @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( tags = {"Stack Data APIs"}, value = "Saves x, y, and z resolution values for stack") @ApiResponses(value = { @ApiResponse(code = 200, message = "resolution values successfully saved"), @ApiResponse(code = 400, message = "stack is READ_ONLY"), @ApiResponse(code = 404, message = "stack not found") }) Response saveResolutionValues(@PathParam("owner") final String owner,
                                         @PathParam("project") final String project,
                                         @PathParam("stack") final String stack,
                                         final List<Double> resolutionValues); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/resolutionValues") @DELETE @ApiOperation( tags = {"Stack Data APIs"}, value = "Deletes x, y, and z resolution values for stack") @ApiResponses(value = { @ApiResponse(code = 400, message = "stack is READ_ONLY"), @ApiResponse(code = 404, message = "stack not found") }) Response deleteResolutionValues(@PathParam("owner") final String owner,
                                           @PathParam("project") final String project,
                                           @PathParam("stack") final String stack); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/materializedBoxRootPath") @GET @Produces(MediaType.TEXT_PLAIN) @ApiOperation( value = "The materializedBoxRootPath for the specified stack") @ApiResponses(value = { @ApiResponse(code = 404, message = "Stack not found") }) String getMaterializedBoxRootPath(@PathParam("owner") final String owner,
                                             @PathParam("project") final String project,
                                             @PathParam("stack") final String stack); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/materializedBoxRootPath") @PUT @Consumes(MediaType.TEXT_PLAIN) @ApiOperation( tags = {"Stack Data APIs"}, value = "Saves materializedBoxRootPath for stack") @ApiResponses(value = { @ApiResponse(code = 200, message = "materializedBoxRootPath successfully saved"), @ApiResponse(code = 400, message = "stack is READ_ONLY"), @ApiResponse(code = 404, message = "stack not found") }) Response saveMaterializedBoxRootPath(@PathParam("owner") final String owner,
                                                @PathParam("project") final String project,
                                                @PathParam("stack") final String stack,
                                                final String materializedBoxRootPath); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/materializedBoxRootPath") @DELETE @ApiOperation( tags = {"Stack Data APIs"}, value = "Deletes materializedBoxRootPath for stack") @ApiResponses(value = { @ApiResponse(code = 400, message = "stack is READ_ONLY"), @ApiResponse(code = 404, message = "stack not found") }) Response deleteMaterializedBoxRootPath(@PathParam("owner") final String owner,
                                                  @PathParam("project") final String project,
                                                  @PathParam("stack") final String stack); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/mipmapPathBuilder") @GET @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "The mipmap path builder specs for the specified stack") @ApiResponses(value = { @ApiResponse(code = 404, message = "Stack not found") }) MipmapPathBuilder getMipmapPathBuilder(@PathParam("owner") final String owner,
                                                 @PathParam("project") final String project,
                                                 @PathParam("stack") final String stack); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/mipmapPathBuilder") @PUT @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( tags = {"Stack Data APIs"}, value = "Saves mipmap path builder specs for stack") @ApiResponses(value = { @ApiResponse(code = 200, message = "mipmap path builder specs successfully saved"), @ApiResponse(code = 400, message = "stack is READ_ONLY"), @ApiResponse(code = 404, message = "stack not found") }) Response saveMipmapPathBuilder(@PathParam("owner") final String owner,
                                          @PathParam("project") final String project,
                                          @PathParam("stack") final String stack,
                                          final MipmapPathBuilder mipmapPathBuilder); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/mipmapPathBuilder") @DELETE @ApiOperation( tags = {"Stack Data APIs"}, value = "Deletes mipmap path builder specs for stack") @ApiResponses(value = { @ApiResponse(code = 400, message = "stack is READ_ONLY"), @ApiResponse(code = 404, message = "stack not found") }) Response deleteMipmapPathBuilder(@PathParam("owner") final String owner,
                                            @PathParam("project") final String project,
                                            @PathParam("stack") final String stack); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/defaultChannel") @GET @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "The default channel for the specified stack") @ApiResponses(value = { @ApiResponse(code = 404, message = "Stack not found") }) String getDefaultChannel(@PathParam("owner") final String owner,
                                    @PathParam("project") final String project,
                                    @PathParam("stack") final String stack); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/defaultChannel") @PUT @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( tags = {"Stack Data APIs"}, value = "Saves default channel name for stack") @ApiResponses(value = { @ApiResponse(code = 200, message = "default channel successfully saved"), @ApiResponse(code = 400, message = "stack is READ_ONLY"), @ApiResponse(code = 404, message = "stack not found") }) Response saveDefaultChannel(@PathParam("owner") final String owner,
                                       @PathParam("project") final String project,
                                       @PathParam("stack") final String stack,
                                       final String defaultChannel); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/defaultChannel") @DELETE @ApiOperation( tags = {"Stack Data APIs"}, value = "Deletes default channel for stack") @ApiResponses(value = { @ApiResponse(code = 400, message = "stack is READ_ONLY"), @ApiResponse(code = 404, message = "stack not found") }) Response deleteDefaultChannel(@PathParam("owner") final String owner,
                                         @PathParam("project") final String project,
                                         @PathParam("stack") final String stack); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/cycle") @GET @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "The cycle data for the specified stack") @ApiResponses(value = { @ApiResponse(code = 404, message = "Stack not found") }) ReconstructionCycle getCycle(@PathParam("owner") final String owner,
                                        @PathParam("project") final String project,
                                        @PathParam("stack") final String stack); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/cycle") @PUT @Consumes(MediaType.APPLICATION_JSON) @ApiOperation( tags = {"Stack Data APIs"}, value = "Saves cycle data for stack") @ApiResponses(value = { @ApiResponse(code = 200, message = "cycle data successfully saved"), @ApiResponse(code = 400, message = "stack is READ_ONLY"), @ApiResponse(code = 404, message = "stack not found") }) Response saveCycle(@PathParam("owner") final String owner,
                              @PathParam("project") final String project,
                              @PathParam("stack") final String stack,
                              final ReconstructionCycle cycle); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/cycle") @DELETE @ApiOperation( tags = {"Stack Data APIs"}, value = "Deletes cycle data for stack") @ApiResponses(value = { @ApiResponse(code = 400, message = "stack is READ_ONLY"), @ApiResponse(code = 404, message = "stack not found") }) Response deleteCycleNumber(@PathParam("owner") final String owner,
                                      @PathParam("project") final String project,
                                      @PathParam("stack") final String stack); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/section/{sectionId}") @DELETE @ApiOperation( tags = {"Section Data APIs"}, value = "Deletes all tiles in section", notes = "Deletes all tiles in the specified stack with the specified sectionId value. This operation can only be performed against stacks in the LOADING state") @ApiResponses(value = { @ApiResponse(code = 400, message = "stack state is not LOADING"), @ApiResponse(code = 404, message = "stack not found"), }) Response deleteStackTilesWithSectionId(@PathParam("owner") final String owner,
                                                  @PathParam("project") final String project,
                                                  @PathParam("stack") final String stack,
                                                  @PathParam("sectionId") final String sectionId); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/z/{z}") @DELETE @ApiOperation( tags = {"Section Data APIs"}, value = "Deletes all tiles in layer", notes = "Deletes all tiles in the specified stack with the specified z value. This operation can only be performed against stacks in the LOADING state") @ApiResponses(value = { @ApiResponse(code = 400, message = "stack state is not LOADING"), @ApiResponse(code = 404, message = "stack not found"), }) Response deleteStackTilesWithZ(@PathParam("owner") final String owner,
                                          @PathParam("project") final String project,
                                          @PathParam("stack") final String stack,
                                          @PathParam("z") final Double z); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/state/{state}") @PUT @ApiOperation( tags = {"Stack Data APIs"}, value = "Sets the stack's current state", notes = "Normal progression is LOADING to COMPLETE to READ_ONLY to OFFLINE. " + "Transitioning to COMPLETE is a potentially long running operation " + "since it creates indexes and aggregates meta data. " + "Transitioning to OFFLINE assumes that the stack data has been persisted elsewhere " + "(e.g. a database dump file) and will remove the stack tile and transform collections, " + "so BE CAREFUL when transitioning to OFFLINE!") @ApiResponses(value = { @ApiResponse(code = 201, message = "state successfully changed"), @ApiResponse(code = 400, message = "stack state cannot be changed because of current state"), @ApiResponse(code = 404, message = "stack not found"), }) Response setStackState(@PathParam("owner") final String owner,
                                  @PathParam("project") final String project,
                                  @PathParam("stack") final String stack,
                                  @PathParam("state") final StackState state,
                                  @Context final UriInfo uriInfo); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/bounds") @GET @Produces(MediaType.APPLICATION_JSON) @ApiOperation( tags = {"Stack Data APIs"}, value = "Bounds for the specified stack") @ApiResponses(value = { @ApiResponse(code = 400, message = "stack bounds not available"), @ApiResponse(code = 404, message = "stack not found"), }) Bounds getStackBounds(@PathParam("owner") final String owner,
                                 @PathParam("project") final String project,
                                 @PathParam("stack") final String stack); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/tileIds") @GET @Produces(MediaType.APPLICATION_JSON) @ApiOperation( tags = {"Stack Data APIs"}, value = "Tile IDs for the specified stack", responseContainer = "List", response = String.class, notes = "For stacks with large numbers of tiles, this will produce a large amount of data (e.g. 500MB for 18 million tiles) - use wisely.") Response getStackTileIds(@PathParam("owner") final String owner,
                                    @PathParam("project") final String project,
                                    @PathParam("stack") final String stack); @Path("v1/owner/{owner}/project/{project}/stack/{stack}/tile-specs-with-ids") @PUT @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @ApiOperation( value = "Get flattened tile specs with the specified ids", notes = "For each tile spec, nested transform lists are flattened and reference transforms are resolved. This should make the specs suitable for external use.") List<TileSpec> getTileSpecsWithIds(@PathParam("owner") final String owner,
                                              @PathParam("project") final String project,
                                              @PathParam("stack") final String stack,
                                              final List<String> tileIdList); static StackMetaData getStackMetaData(final StackId stackId,
                                                 final RenderDao renderDao);  }