http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6d19e129/odf/odf-web/src/main/java/org/apache/atlas/odf/admin/rest/resources/AnalysesResource.java ---------------------------------------------------------------------- diff --git a/odf/odf-web/src/main/java/org/apache/atlas/odf/admin/rest/resources/AnalysesResource.java b/odf/odf-web/src/main/java/org/apache/atlas/odf/admin/rest/resources/AnalysesResource.java new file mode 100755 index 0000000..a3bc3b2 --- /dev/null +++ b/odf/odf-web/src/main/java/org/apache/atlas/odf/admin/rest/resources/AnalysesResource.java @@ -0,0 +1,156 @@ +/** + * + * 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.apache.atlas.odf.admin.rest.resources; + +import java.util.logging.Logger; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.apache.atlas.odf.api.analysis.AnalysisCancelResult; +import org.apache.atlas.odf.api.analysis.AnalysisRequest; +import org.apache.atlas.odf.api.analysis.AnalysisRequestStatus; +import org.apache.atlas.odf.api.analysis.AnalysisResponse; +import org.apache.atlas.odf.json.JSONUtils; +import org.apache.wink.json4j.JSONException; + +import org.apache.atlas.odf.admin.rest.RestUtils; +import org.apache.atlas.odf.api.analysis.AnalysisRequestSummary; +import org.apache.atlas.odf.api.analysis.AnalysisRequestTrackers; +import org.apache.atlas.odf.api.ODFFactory; + +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; + +@Path("/analyses") +@Api(value = "/analyses", description = "Create and view analysis requests", produces = MediaType.APPLICATION_JSON) +public class AnalysesResource { + private Logger logger = Logger.getLogger(AnalysesResource.class.getName()); + + @GET + @Path("/stats") + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Get analysis request statistics", httpMethod = "GET", notes = "Return number of successfull and failing analysis requests", response = AnalysisRequestSummary.class) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK"), + @ApiResponse(code = 500, message = "Internal server error") + }) + public Response getStats() { + try { + return Response.ok(JSONUtils.toJSON(new ODFFactory().create().getAnalysisManager().getAnalysisStats())).build(); + } catch (JSONException e) { + e.printStackTrace(); + logger.info("Parse exception " + e); + return RestUtils.createErrorResponse(e); + } + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Get list of analysis requests", httpMethod = "GET", notes = "Retrieve list of recent analysis requests (from latest to oldest)", responseContainer="List", response = AnalysisRequestTrackers.class) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK"), + @ApiResponse(code = 500, message = "Internal server error") + }) + public Response getAnalysisRequests( + @ApiParam(value = "Starting offset (use 0 to start with the latest request).", required = false) + @DefaultValue("0") @QueryParam("offset") int offset, + @ApiParam(value = "Maximum number of analysis requests to be returned (use -1 to retrieve all requests).", required = false) + @DefaultValue("10") @QueryParam("limit") int limit) { + try { + String result = JSONUtils.toJSON(new ODFFactory().create().getAnalysisManager().getAnalysisRequests(offset, limit)); + return Response.ok(result).build(); + } catch (Exception exc) { + throw new RuntimeException(exc); + } + } + + @GET + @Path("/{requestId}") + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Get analysis request status", httpMethod = "GET", notes = "Show status of a specific analysis request", response = AnalysisRequestStatus.class) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK"), + @ApiResponse(code = 400, message = "Bad Request"), + @ApiResponse(code = 500, message = "Internal server error") + }) + public Response getAnalysisStatus( + @ApiParam(value = "ID of the analysis request", required = true) + @PathParam("requestId") String requestId) { + logger.entering(AnalysesResource.class.getName(), "getAnalysisStatus"); + AnalysisRequestStatus analysisRequestStatus = new ODFFactory().create().getAnalysisManager().getAnalysisRequestStatus(requestId); + try { + return Response.ok(JSONUtils.toJSON(analysisRequestStatus)).build(); + } catch (JSONException e) { + e.printStackTrace(); + logger.info("Parse exception " + e); + return RestUtils.createErrorResponse(e); + } + } + + @POST + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Run analysis", httpMethod = "POST", notes = "Create and run new analysis request", response = AnalysisResponse.class) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK"), + @ApiResponse(code = 400, message = "Bad Request"), + @ApiResponse(code = 500, message = "Internal server error") + }) + public Response startAnalysis(@ApiParam(value = "Analysis request to be started", required = true) AnalysisRequest request) { + logger.entering(AnalysesResource.class.getName(), "startAnalysis"); + try { + AnalysisResponse analysisResponse = new ODFFactory().create().getAnalysisManager().runAnalysis(request); + return Response.ok(JSONUtils.toJSON(analysisResponse)).build(); + } catch (JSONException e) { + e.printStackTrace(); + logger.info("Parse exception " + e); + return RestUtils.createErrorResponse(e); + } + } + + @POST + @Path("/{requestId}/cancel") + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Cancel analysis request", httpMethod = "POST", notes = "Cancel a queued analysis request that has not been started yet", response = Response.class) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK"), + @ApiResponse(code = 400, message = "Bad Request - The request with the provided id could not be found"), + @ApiResponse(code = 403, message = "Forbidden - The status of the analysis request does not allow for cancellation") + }) + public Response cancelAnalysisRequest(@ApiParam(value = "ID of the analysis request", required = true) @PathParam("requestId") String requestId) { + logger.entering(AnalysesResource.class.getName(), "cancelAnalysisRequest"); + AnalysisCancelResult result = new ODFFactory().create().getAnalysisManager().cancelAnalysisRequest(requestId); + if (result.getState() == AnalysisCancelResult.State.NOT_FOUND) { + return Response.status(Status.BAD_REQUEST).build(); + } else if (result.getState() == AnalysisCancelResult.State.INVALID_STATE) { + return Response.status(Status.FORBIDDEN).build(); + } + return Response.ok().build(); + } + +}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6d19e129/odf/odf-web/src/main/java/org/apache/atlas/odf/admin/rest/resources/AnnotationsResource.java ---------------------------------------------------------------------- diff --git a/odf/odf-web/src/main/java/org/apache/atlas/odf/admin/rest/resources/AnnotationsResource.java b/odf/odf-web/src/main/java/org/apache/atlas/odf/admin/rest/resources/AnnotationsResource.java new file mode 100755 index 0000000..704b004 --- /dev/null +++ b/odf/odf-web/src/main/java/org/apache/atlas/odf/admin/rest/resources/AnnotationsResource.java @@ -0,0 +1,130 @@ +/** + * + * 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.apache.atlas.odf.admin.rest.resources; + +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.apache.atlas.odf.admin.rest.RestUtils; +import org.apache.atlas.odf.api.metadata.MetaDataObjectReference; +import org.apache.atlas.odf.api.metadata.models.Annotation; +import org.apache.atlas.odf.api.ODFFactory; +import org.apache.atlas.odf.api.annotation.AnnotationStore; +import org.apache.atlas.odf.api.annotation.AnnotationStoreUtils; +import org.apache.atlas.odf.api.annotation.Annotations; +import org.apache.atlas.odf.json.JSONUtils; + +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; + +@Path("/annotations") +@Api(value = "/annotations", description = "Create and query ODF annotations", produces = MediaType.APPLICATION_JSON) +public class AnnotationsResource { + + Logger logger = Logger.getLogger(AnnotationsResource.class.getName()); + + @GET + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Retrieve annotations", httpMethod = "GET", notes = "Retrieve annotations for an asset and/or for a specific analysis request.", response = Annotations.class) + @ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 500, message = "Internal server error") }) + public Response retrieveAnnotationsForAsset(@ApiParam(value = "Reference ID of the asset", required = false) @QueryParam("assetReference") String assetReference, + @ApiParam(value = "Analysis request ID", required = false) @QueryParam("analysisRequestId") String analysisRequestId) { + try { + MetaDataObjectReference ref = null; + if (assetReference != null) { + ref = new MetaDataObjectReference(); + String repoId = new ODFFactory().create().getMetadataStore().getRepositoryId(); + ref.setRepositoryId(repoId); + ref.setId(assetReference); + } + AnnotationStore as = new ODFFactory().create().getAnnotationStore(); + List<Annotation> annots = as.getAnnotations(ref, analysisRequestId); + Annotations result = new Annotations(); + result.setAnnotations(annots); + return Response.ok(JSONUtils.toJSON(result)).build(); + } catch (Exception exc) { + logger.log(Level.WARNING, "An exception occurred while retrieving annotations", exc); + return RestUtils.createErrorResponse(exc); + } + } + + + @GET + @Path("/objects/{objectReference}") + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Retrieve annotation", httpMethod = "GET", notes = "Retrieve annotation by Id.", response = Annotation.class) + @ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 500, message = "Internal server error") }) + public Response retrieveAnnotation(@ApiParam(value = "Reference ID of the annotation", required = true) @PathParam("objectReference") String objectReference) { + try { + MetaDataObjectReference ref = new MetaDataObjectReference(); + AnnotationStore as = new ODFFactory().create().getAnnotationStore(); + ref.setRepositoryId(as.getRepositoryId()); + ref.setId(objectReference); + Annotation annot = as.retrieveAnnotation(ref); + return Response.ok(JSONUtils.toJSON(annot)).build(); + } catch (Exception exc) { + logger.log(Level.WARNING, "An exception occurred while retrieving annotation", exc); + return RestUtils.createErrorResponse(exc); + } + } + + + // no swagger documentation as this will be replaced by "annotation propagation" + @GET + @Path("/newestAnnotations/{assetReference}") + @Produces(MediaType.APPLICATION_JSON) + public Response retrieveMostRecentAnnotations(@PathParam("assetReference") String assetReference) { + try { + MetaDataObjectReference ref = JSONUtils.fromJSON(assetReference, MetaDataObjectReference.class); + AnnotationStore as = new ODFFactory().create().getAnnotationStore(); + List<Annotation> annotations = AnnotationStoreUtils.getMostRecentAnnotationsByType(as, ref); + String result = JSONUtils.toJSON(annotations); + return Response.ok(result).build(); + } catch (Exception e) { + logger.log(Level.WARNING, "An exception occurred while retrieving most recent annotations", e); + return RestUtils.createErrorResponse(e); + } + } + + @POST + @ApiOperation(value = "Create annotation", httpMethod = "POST", notes = "Create new annotation object", response = MetaDataObjectReference.class) + @ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 400, message = "Bad Request"), @ApiResponse(code = 500, message = "Internal server error") }) + public Response createAnnotation(@ApiParam(value = "Analysis request to be started", required = true) String annotString) { + try { + Annotation annot = JSONUtils.fromJSON(annotString, Annotation.class); + AnnotationStore as = new ODFFactory().create().getAnnotationStore(); + MetaDataObjectReference annotRef = as.store(annot); + return Response.status(Status.CREATED).entity(JSONUtils.toJSON(annotRef)).build(); + } catch (Exception exc) { + logger.log(Level.WARNING, "An exception occurred while storing an annotation", exc); + return RestUtils.createErrorResponse(exc); + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6d19e129/odf/odf-web/src/main/java/org/apache/atlas/odf/admin/rest/resources/DiscoveryServicesResource.java ---------------------------------------------------------------------- diff --git a/odf/odf-web/src/main/java/org/apache/atlas/odf/admin/rest/resources/DiscoveryServicesResource.java b/odf/odf-web/src/main/java/org/apache/atlas/odf/admin/rest/resources/DiscoveryServicesResource.java new file mode 100755 index 0000000..bd01e60 --- /dev/null +++ b/odf/odf-web/src/main/java/org/apache/atlas/odf/admin/rest/resources/DiscoveryServicesResource.java @@ -0,0 +1,341 @@ +/** + * 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.apache.atlas.odf.admin.rest.resources; + +import java.io.InputStream; +import java.util.List; +import java.util.logging.Logger; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.apache.atlas.odf.api.settings.validation.ValidationException; +import org.apache.wink.json4j.JSONException; + +import org.apache.atlas.odf.admin.rest.RestUtils; +import org.apache.atlas.odf.api.ODFFactory; +import org.apache.atlas.odf.api.discoveryservice.DiscoveryServiceManager; +import org.apache.atlas.odf.api.discoveryservice.DiscoveryServiceProperties; +import org.apache.atlas.odf.api.discoveryservice.DiscoveryServiceRuntimeStatistics; +import org.apache.atlas.odf.api.discoveryservice.DiscoveryServiceStatus; +import org.apache.atlas.odf.api.discoveryservice.ServiceNotFoundException; +import org.apache.atlas.odf.api.discoveryservice.ServiceStatusCount; +import org.apache.atlas.odf.json.JSONUtils; + +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; + +@Path("/services") +@Api(value = "/services", description = "Manage ODF services", produces = MediaType.APPLICATION_JSON) +public class DiscoveryServicesResource { + private Logger logger = Logger.getLogger(DiscoveryServicesResource.class.getName()); + + @GET + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Get list of discovery services", httpMethod = "GET", notes = "Retrieve list of all discovery services registered in ODF", responseContainer="List", response = DiscoveryServiceProperties.class) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK"), + @ApiResponse(code = 500, message = "Internal server error") + }) + public Response getDiscoveryServices() { + logger.entering(DiscoveryServicesResource.class.getName(), "getServices"); + DiscoveryServiceManager dsAdmin = new ODFFactory().create().getDiscoveryServiceManager(); + Response response; + List<DiscoveryServiceProperties> dsProperties = dsAdmin.getDiscoveryServicesProperties(); + try { + String json = JSONUtils.toJSON(dsProperties); + response = Response.ok(json).build(); + } catch (JSONException e) { + e.printStackTrace(); + logger.info("Parse exception " + e); + response = RestUtils.createErrorResponse(e); + } + return response; + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("/status") + @ApiOperation(value = "Get status of discovery services", httpMethod = "GET", notes = "Retrieve status overview of all discovery services registered in ODF", responseContainer="List", response = ServiceStatusCount.class) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK"), + @ApiResponse(code = 404, message = "Not found"), + @ApiResponse(code = 500, message = "Internal server error") + }) + public Response getAllServicesStatus() { + logger.entering(DiscoveryServicesResource.class.getName(), "getAllServicesStatus"); + List<ServiceStatusCount> servicesStatus = new ODFFactory().create().getDiscoveryServiceManager().getDiscoveryServiceStatusOverview(); + if (servicesStatus == null) { + return Response.status(Status.NOT_FOUND).build(); + } + String json; + try { + json = JSONUtils.toJSON(servicesStatus); + } catch (JSONException e) { + throw new RuntimeException(e); + } + return Response.ok(json).build(); + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("/{serviceId}/status") + @ApiOperation(value = "Get discovery service status", httpMethod = "GET", notes = "Retrieve status of a discovery service that is registered in ODF", response = Response.class) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK"), + @ApiResponse(code = 404, message = "Not found"), + @ApiResponse(code = 500, message = "Internal server error") + }) + public Response getDiscoveryServiceStatus( + @ApiParam(value = "Discovery service ID", required = true) + @PathParam("serviceId") String serviceId) { + logger.entering(DiscoveryServicesResource.class.getName(), "getDiscoveryServiceStatus"); + DiscoveryServiceManager dsAdmin = new ODFFactory().create().getDiscoveryServiceManager(); + Response response; + try { + DiscoveryServiceStatus dsStatus = dsAdmin.getDiscoveryServiceStatus(serviceId); + if (dsStatus == null) { + response = Response.status(Status.NOT_FOUND).build(); + } + else { + try { + String json = JSONUtils.toJSON(dsStatus); + response = Response.ok(json).build(); + } catch (JSONException e) { + e.printStackTrace(); + logger.info("Parse exception " + e); + response = RestUtils.createErrorResponse(e); + } + } + } + catch (ServiceNotFoundException snfe) { + response = Response.status(Status.NOT_FOUND).entity(snfe.getMessage()).build(); + } + return response; + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("/{serviceId}/runtimeStats") + @ApiOperation(value = "Get runtime statistics of a discovery service", httpMethod = "GET", notes = "Retrieve the runtime statistics of a discovery service that is registered in ODF.", response = Response.class) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK"), + @ApiResponse(code = 404, message = "Not found"), + @ApiResponse(code = 500, message = "Internal server error") + }) + public Response getDiscoveryServiceRuntimeStats( + @ApiParam(value = "Discovery service ID", required = true) + @PathParam("serviceId") String serviceId) { + logger.entering(DiscoveryServicesResource.class.getName(), "getDiscoveryServiceRuntimeStats"); + DiscoveryServiceManager dsAdmin = new ODFFactory().create().getDiscoveryServiceManager(); + Response response; + try { + DiscoveryServiceRuntimeStatistics dsRuntimeStats = dsAdmin.getDiscoveryServiceRuntimeStatistics(serviceId); + String json = JSONUtils.toJSON(dsRuntimeStats); + response = Response.ok(json).build(); + } + catch (JSONException e) { + e.printStackTrace(); + logger.info("Parse exception " + e); + response = RestUtils.createErrorResponse(e); + } + catch (ServiceNotFoundException snfe) { + response = Response.status(Status.NOT_FOUND).entity(snfe.getMessage()).build(); + } + return response; + } + + @DELETE + @Path("/{serviceId}/runtimeStats") + @ApiOperation(value = "Delete runtime statistics of a discovery service", httpMethod = "DELETE", notes = "Delete the runtime statistics of a discovery service that is registered in ODF.", response = Response.class) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK"), + @ApiResponse(code = 404, message = "Not found"), + @ApiResponse(code = 500, message = "Internal server error") + }) + public Response deleteDiscoveryServiceRuntimeStats( + @ApiParam(value = "Discovery service ID", required = true) + @PathParam("serviceId") String serviceId) { + logger.entering(DiscoveryServicesResource.class.getName(), "deleteDiscoveryServiceRuntimeStats"); + DiscoveryServiceManager dsAdmin = new ODFFactory().create().getDiscoveryServiceManager(); + Response response; + try { + dsAdmin.deleteDiscoveryServiceRuntimeStatistics(serviceId); + response = Response.ok().build(); + } + catch (ServiceNotFoundException snfe) { + response = Response.status(Status.NOT_FOUND).entity(snfe.getMessage()).build(); + } + return response; + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("/{serviceId}") + @ApiOperation(value = "Get properties of a discovery service registered in ODF", httpMethod = "GET", notes = "Retrieve properties of a discovery service that is registered in ODF", response = Response.class) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK"), + @ApiResponse(code = 404, message = "Not found"), + @ApiResponse(code = 500, message = "Internal server error") + }) + public Response getDiscoveryServiceProperties( + @ApiParam(value = "Id string of discovery service", required = true) + @PathParam("serviceId") String serviceId) { + logger.entering(DiscoveryServicesResource.class.getName(), "getDiscoveryServiceProperties"); + DiscoveryServiceManager dsAdmin = new ODFFactory().create().getDiscoveryServiceManager(); + Response response; + try { + DiscoveryServiceProperties dsStatus = dsAdmin.getDiscoveryServiceProperties(serviceId); + if (dsStatus == null) { + response = Response.status(Status.NOT_FOUND).build(); + } + else { + try { + String json = JSONUtils.toJSON(dsStatus); + response = Response.ok(json).build(); + } catch (JSONException e) { + e.printStackTrace(); + logger.info("Parse exception " + e); + response = RestUtils.createErrorResponse(e); + } + } + } + catch (ServiceNotFoundException snfe) { + response = Response.status(Status.NOT_FOUND).entity(snfe.getMessage()).build(); + } + return response; + } + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Register a discovery service", httpMethod = "POST", notes = "Register a new service in ODF", response = Response.class) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK"), + @ApiResponse(code = 400, message = "Bad Request"), + @ApiResponse(code = 500, message = "Internal server error") + }) + public Response registerDiscoveryService( + @ApiParam(value = "ODF service definition", required = true) DiscoveryServiceProperties dsProperties) { + logger.entering(DiscoveryServicesResource.class.getName(), "registerDiscoveryService"); + Response response; + try { + DiscoveryServiceManager dsAdmin = new ODFFactory().create().getDiscoveryServiceManager(); + dsAdmin.createDiscoveryService(dsProperties); + response = Response.ok().build(); + } catch (ValidationException e) { + e.printStackTrace(); + logger.info("Validation exception during setting of property " + e.getProperty()); + response = RestUtils.createErrorResponse(e.getErrorCause()); + } + return response; + } + + @PUT + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Update properties of a discovery service", httpMethod = "POST", notes = "Update properties of a discovery service that is registered in ODF", response = Response.class) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK"), + @ApiResponse(code = 400, message = "Bad Request"), + @ApiResponse(code = 500, message = "Internal server error") + }) + public Response updateDiscoveryService( + @ApiParam(value = "ODF service definition", required = true) DiscoveryServiceProperties dsProperties) { + logger.entering(DiscoveryServicesResource.class.getName(), "updateDiscoveryService"); + Response response; + try { + DiscoveryServiceManager dsAdmin = new ODFFactory().create().getDiscoveryServiceManager(); + dsAdmin.replaceDiscoveryService(dsProperties); + response = Response.ok().build(); + } + catch (ServiceNotFoundException snfe) { + response = Response.status(Status.NOT_FOUND).entity(snfe.getMessage()).build(); + } + catch (ValidationException e) { + e.printStackTrace(); + logger.info("Validation exception during setting of property " + e.getProperty()); + response = RestUtils.createErrorResponse(e.getErrorCause()); + } + return response; + } + + @DELETE + @Path("/{serviceId}") + @ApiOperation(value = "Delete a discovery service", httpMethod = "DELETE", notes = "Remove a registered service from ODF", response = Response.class) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK"), + @ApiResponse(code = 400, message = "Bad Request"), + @ApiResponse(code = 500, message = "Internal server error") + }) + public Response deleteDiscoveryService( + @ApiParam(value = "Id string of discovery service to be deleted", required = true) + @PathParam("serviceId") String serviceId) { + logger.entering(DiscoveryServicesResource.class.getName(), "deleteDiscoveryService"); + Response response; + try { + DiscoveryServiceManager dsAdmin = new ODFFactory().create().getDiscoveryServiceManager(); + dsAdmin.deleteDiscoveryService(serviceId); + response = Response.ok().build(); + } + catch (ServiceNotFoundException snfe) { + response = Response.status(Status.NOT_FOUND).entity(snfe.getMessage()).build(); + } + catch (ValidationException e) { + e.printStackTrace(); + logger.info("Validation exception during deletion. Property: " + e.getProperty()); + response = RestUtils.createErrorResponse(e.getErrorCause()); + } + return response; + } + + @GET + @Path("/{serviceId}/image") + @Produces("image/*") + @ApiOperation(value = "Get a discovery service logo", httpMethod = "GET", notes = "Retrieve image representing a discovery service", response = InputStream.class) + @ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 404, message = "Not found"), @ApiResponse(code = 500, message = "Internal server error") }) + public Response getImage( + @ApiParam(value = "ID of discovery service", required = true) + @PathParam("serviceId") String serviceId) { + + DiscoveryServiceManager dsAdmin = new ODFFactory().create().getDiscoveryServiceManager(); + Response response = null; + InputStream is; + try { + is = dsAdmin.getDiscoveryServiceImage(serviceId); + if (is == null) { + // should never happen + response = Response.status(Status.NOT_FOUND).build(); + } + else { + response = Response.ok(is, "image/png").build(); + } + } catch (ServiceNotFoundException snfe) { + response = Response.status(Status.NOT_FOUND).entity(snfe.getMessage()).build(); + } + return response; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6d19e129/odf/odf-web/src/main/java/org/apache/atlas/odf/admin/rest/resources/EngineResource.java ---------------------------------------------------------------------- diff --git a/odf/odf-web/src/main/java/org/apache/atlas/odf/admin/rest/resources/EngineResource.java b/odf/odf-web/src/main/java/org/apache/atlas/odf/admin/rest/resources/EngineResource.java new file mode 100755 index 0000000..d6cd37d --- /dev/null +++ b/odf/odf-web/src/main/java/org/apache/atlas/odf/admin/rest/resources/EngineResource.java @@ -0,0 +1,167 @@ +/** + * + * 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.apache.atlas.odf.admin.rest.resources; + +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.apache.atlas.odf.api.engine.SystemHealth; +import org.apache.atlas.odf.api.utils.ODFLogConfig; +import org.apache.wink.json4j.JSONException; + +import org.apache.atlas.odf.admin.log.LoggingHandler; +import org.apache.atlas.odf.admin.rest.RestUtils; +import org.apache.atlas.odf.api.ODFFactory; +import org.apache.atlas.odf.api.engine.ODFEngineOptions; +import org.apache.atlas.odf.api.engine.ODFStatus; +import org.apache.atlas.odf.api.engine.ODFVersion; +import org.apache.atlas.odf.api.engine.ServiceRuntimesInfo; +import org.apache.atlas.odf.json.JSONUtils; + +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; + +@Path("/engine") +@Api(value = "/engine", description = "Monitor and control the ODF engine", produces = MediaType.APPLICATION_JSON) +public class EngineResource { + final static LoggingHandler REST_LOG_HANDLER = new LoggingHandler(); + + static { + //initialize log config and log handler to cache logs + ODFLogConfig.run(); + Logger rootLogger = Logger.getLogger("org.apache.atlas.odf"); + REST_LOG_HANDLER.setLevel(Level.ALL); + rootLogger.addHandler(REST_LOG_HANDLER); + } + + private Logger logger = Logger.getLogger(EngineResource.class.getName()); + + @POST + @Path("shutdown") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Shutdown ODF engine", httpMethod = "POST", notes = "Shutdown ODF engine, purge all scheduled analysis requests from the queues, and cancel all running analysis requests (for debugging purposes only)", response = Response.class) + @ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 500, message = "Internal server error") }) + public Response shutdown(@ApiParam(value = "Engine options", defaultValue = "false", required = true) ODFEngineOptions engineOptions) { + logger.entering(EngineResource.class.getName(), "shutdown"); + logger.log(Level.INFO, "Restart option is ", engineOptions.isRestart()); + new ODFFactory().create().getEngineManager().shutdown(engineOptions); + return Response.ok().build(); + } + + @GET + @Path("health") + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Get health status", httpMethod = "GET", notes = "Check the health status of ODF", response = SystemHealth.class) + @ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 400, message = "Bad Request"), @ApiResponse(code = 500, message = "Internal server error") }) + public Response healthCheck() { + logger.entering(EngineResource.class.getName(), "healthCheck"); + SystemHealth health = new ODFFactory().create().getEngineManager().checkHealthStatus(); + Status status = Status.OK; + try { + return Response.status(status).entity(JSONUtils.toJSON(health)).type(MediaType.APPLICATION_JSON).build(); + } catch (JSONException e) { + e.printStackTrace(); + logger.info("Parse exception " + e); + return RestUtils.createErrorResponse(e); + } + } + + @GET + @Path("runtimes") + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Get info about the available runtimes", httpMethod = "GET", notes = "Get information about all runtimes running discovery services", response = SystemHealth.class) + @ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 400, message = "Bad Request"), @ApiResponse(code = 500, message = "Internal server error") }) + public Response getRuntimesInfo() { + logger.entering(EngineResource.class.getName(), "getRuntimesInfo"); + ServiceRuntimesInfo sri = new ODFFactory().create().getEngineManager().getRuntimesInfo(); + Status status = Status.OK; + try { + return Response.status(status).entity(JSONUtils.toJSON(sri)).type(MediaType.APPLICATION_JSON).build(); + } catch (JSONException e) { + e.printStackTrace(); + logger.info("Parse exception " + e); + return RestUtils.createErrorResponse(e); + } finally { + logger.exiting(EngineResource.class.getName(), "getRuntimesInfo"); + } + } + + @GET + @Path("status") + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Get current status", httpMethod = "GET", notes = "Retrieve status of the messaging subsystem and the internal thread manager", response = ODFStatus.class) + @ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 500, message = "Internal server error") }) + public Response getStatus() throws IOException { + logger.entering(EngineResource.class.getName(), "getStatus"); + try { + ODFStatus odfStatus = new ODFFactory().create().getEngineManager().getStatus(); + return Response.status(Status.OK).entity(JSONUtils.toJSON(odfStatus)).type(MediaType.APPLICATION_JSON).build(); + } catch (Exception exc) { + logger.log(Level.INFO, "An exception occurred while getting the request status", exc); + return RestUtils.createErrorResponse(exc); + } + } + + @GET + @Path("log") + @Produces(MediaType.TEXT_PLAIN) + @ApiOperation(value = "Get current application log", httpMethod = "GET", notes = "Retrieve logs of the ODF instance", response = ODFStatus.class) + @ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 500, message = "Internal server error") }) + public Response getLog(@QueryParam("numberOfLogs") Integer numberOfLogs, @QueryParam("logLevel") String logLevel) throws IOException { + logger.entering(EngineResource.class.getName(), "getLog"); + try { + Level level = Level.ALL; + if (logLevel != null) { + level = Level.parse(logLevel); + } + return Response.status(Status.OK).entity(REST_LOG_HANDLER.getFormattedCachedLog(numberOfLogs, level)).type(MediaType.TEXT_PLAIN).build(); + } catch (Exception exc) { + logger.log(Level.INFO, "An exception occurred while getting the ODF log", exc); + return RestUtils.createErrorResponse(exc); + } + } + + @GET + @Path("version") + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Get the ODF build version", httpMethod = "GET", notes = "The version is of the form versionnumber-buildid, e.g., 0.1.0-154", response = ODFVersion.class) + @ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 500, message = "Internal server error") }) + public Response getVersion() { + try { + ODFVersion version = new ODFFactory().create().getEngineManager().getVersion(); + Status status = Status.OK; + return Response.status(status).entity(JSONUtils.toJSON(version)).type(MediaType.APPLICATION_JSON).build(); + } catch (Exception exc) { + logger.log(Level.INFO, "An exception occurred while getting the version", exc); + return RestUtils.createErrorResponse(exc); + } + + } +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6d19e129/odf/odf-web/src/main/java/org/apache/atlas/odf/admin/rest/resources/ImportResource.java ---------------------------------------------------------------------- diff --git a/odf/odf-web/src/main/java/org/apache/atlas/odf/admin/rest/resources/ImportResource.java b/odf/odf-web/src/main/java/org/apache/atlas/odf/admin/rest/resources/ImportResource.java new file mode 100755 index 0000000..ef489a8 --- /dev/null +++ b/odf/odf-web/src/main/java/org/apache/atlas/odf/admin/rest/resources/ImportResource.java @@ -0,0 +1,89 @@ +/** + * + * 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.apache.atlas.odf.admin.rest.resources; + +import java.util.logging.Logger; + +import javax.ws.rs.Consumes; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.apache.atlas.odf.api.metadata.importer.JDBCMetadataImportResult; +import org.apache.atlas.odf.api.metadata.importer.JDBCMetadataImporter; +import org.apache.wink.json4j.JSONException; +import org.apache.wink.json4j.JSONObject; + +import org.apache.atlas.odf.admin.rest.RestUtils; +import org.apache.atlas.odf.api.ODFFactory; +import org.apache.atlas.odf.api.metadata.importer.MetadataImportException; +import org.apache.atlas.odf.api.metadata.models.JDBCConnection; +import org.apache.atlas.odf.json.JSONUtils; + +@Path("/import") +public class ImportResource { + private Logger logger = Logger.getLogger(ImportResource.class.getName()); + + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response doImport(String parameterString) { + logger.entering(ImportResource.class.getName(), "import"); + try { + JSONObject parameter = new JSONObject(parameterString); + + Object jdbcObj = parameter.get("jdbcString"); + Object userObj = parameter.get("user"); + Object passwordObj = parameter.get("password"); + Object dbObj = parameter.get("database"); + Object schemaObj = parameter.get("schema"); + Object tableObj = parameter.get("table"); + + if (jdbcObj == null || userObj == null || passwordObj == null) { + return RestUtils.createErrorResponse("jdbcString, user, password, database, schema and table are required!"); + } + + String user = (String) userObj; + String password = (String) passwordObj; + String jdbcString = (String) jdbcObj; + String db = (String) dbObj; + String schema = (String) schemaObj; + String table = (String) tableObj; + + JDBCMetadataImporter importer = new ODFFactory().create().getJDBCMetadataImporter(); + JDBCConnection conn = new JDBCConnection(); + conn.setJdbcConnectionString(jdbcString); + conn.setUser(user); + conn.setPassword(password); + + JDBCMetadataImportResult result = null; + try { + result = importer.importTables(conn, db, schema, table); + } catch (MetadataImportException ex) { + return RestUtils.createErrorResponse(ex.getMessage()); + } + + if (result == null) { + return Response.serverError().build(); + } + + return Response.ok(JSONUtils.toJSON(result)).build(); + } catch (JSONException e) { + return RestUtils.createErrorResponse(e.getMessage()); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6d19e129/odf/odf-web/src/main/java/org/apache/atlas/odf/admin/rest/resources/MetadataResource.java ---------------------------------------------------------------------- diff --git a/odf/odf-web/src/main/java/org/apache/atlas/odf/admin/rest/resources/MetadataResource.java b/odf/odf-web/src/main/java/org/apache/atlas/odf/admin/rest/resources/MetadataResource.java new file mode 100755 index 0000000..9daf09a --- /dev/null +++ b/odf/odf-web/src/main/java/org/apache/atlas/odf/admin/rest/resources/MetadataResource.java @@ -0,0 +1,246 @@ +/** + * + * 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.apache.atlas.odf.admin.rest.resources; + +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.apache.wink.json4j.JSONException; +import org.apache.wink.json4j.JSONObject; + +import org.apache.atlas.odf.admin.rest.RestUtils; +import org.apache.atlas.odf.api.metadata.InternalMetaDataUtils; +import org.apache.atlas.odf.api.metadata.MetaDataObjectReference; +import org.apache.atlas.odf.api.metadata.MetadataStore; +import org.apache.atlas.odf.api.metadata.MetadataStoreException; +import org.apache.atlas.odf.api.metadata.models.MetaDataObject; +import org.apache.atlas.odf.api.ODFFactory; +import org.apache.atlas.odf.json.JSONUtils; + +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; + +@Path("/metadata") +@Api(value = "/metadata", description = "Populate and query metadata repository", produces = MediaType.APPLICATION_JSON) +public class MetadataResource { + private Logger logger = Logger.getLogger(MetadataResource.class.getName()); + + @GET + @Path("/connectiontest") + public Response testConnection() { + try { + MetadataStore mds = new ODFFactory().create().getMetadataStore(); + MetadataStore.ConnectionStatus status = mds.testConnection(); + switch (status) { + case OK: + return Response.ok().build(); + case AUTHORIZATION_FAILED: + return Response.status(Status.UNAUTHORIZED).build(); + case UNREACHABLE: + return Response.status(Status.NOT_FOUND).build(); + default: + return Response.status(Status.INTERNAL_SERVER_ERROR).build(); + } + } catch (Exception e) { + logger.log(Level.WARNING, "An exception occurred while getting metatdata store properties", e); + return RestUtils.createErrorResponse(e); + } + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Get metadata store properties", httpMethod = "GET", notes = "Retrieve type and URL of underlying metadata store", response = Response.class) + @ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 500, message = "Internal server error") }) + public Response getMetadataStoreProperties() { + try { + JSONObject result = new JSONObject(); + MetadataStore mds = new ODFFactory().create().getMetadataStore(); + Hashtable<Object, Object> propertyHashtable = (Hashtable<Object, Object>) mds.getProperties(); + for (Object propKey : propertyHashtable.keySet()) { + result.put((String) propKey, (String) propertyHashtable.get(propKey)); + } + String s = result.write(); + return Response.ok(s).build(); + } catch (Exception e) { + logger.log(Level.WARNING, "An exception occurred while getting metatdata store properties", e); + return RestUtils.createErrorResponse(e); + } + } + + @GET + @Path("/referencetypes") + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Get list of available reference types", httpMethod = "GET", notes = "Retrieve list of supported metadata object reference types", responseContainer="List", response = MetaDataObject.class) + @ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 500, message = "Internal server error") }) + public Response getReferenceTypes() { + JSONObject result = new JSONObject(); + List<String> referenceTypes = null; + try { + MetadataStore mds = new ODFFactory().create().getMetadataStore(); + referenceTypes = mds.getReferenceTypes(); + result = JSONUtils.toJSONObject(referenceTypes); + return Response.ok(result.write()).build(); + } catch (JSONException e) { + logger.warning("Parse exception " + e.getMessage() + " Parsed object: " + referenceTypes); + return RestUtils.createErrorResponse(e); + } + } + + @GET + @Path("/asset/{assetReference}") + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Retrieve asset by reference", httpMethod = "GET", notes = "Retrieve object from metadata repository", response = MetaDataObject.class) + @ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 500, message = "Internal server error") }) + public Response retrieveAsset(@ApiParam(value = "Metadata object reference id", required = true) @PathParam("assetReference") String assetReference) { + JSONObject result; + try { + MetaDataObjectReference ref = JSONUtils.fromJSON(assetReference, MetaDataObjectReference.class); + MetadataStore mds = new ODFFactory().create().getMetadataStore(); + MetaDataObject mdo = mds.retrieve(ref); + if (mdo != null) { + result = JSONUtils.toJSONObject(mdo); + } else { + // Return empty JSON document to indicate that the result should be null. + result = new JSONObject(); + } + return Response.ok(result.write()).build(); + } catch (JSONException e) { + logger.warning("Parse exception " + e.getMessage() + " Parsed object: " + assetReference); + return RestUtils.createErrorResponse(e); + } + } + + @GET + @Path("/asset/{assetReference}/{referenceType}") + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Retrieve objects referenced by an asset", httpMethod = "GET", notes = "Retrieve referenced metadata objects by reference type", responseContainer="List", response = MetaDataObject.class) + @ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 500, message = "Internal server error") }) + public Response retrieveAssetReferences( + @ApiParam(value = "Metadata object reference", required = true) @PathParam("assetReference") String assetReference, + @ApiParam(value = "Reference type name (including 'PARENT' and 'CHILDREN')", required = true) @PathParam("referenceType") String referenceType) { + try { + MetaDataObjectReference ref = JSONUtils.fromJSON(assetReference, MetaDataObjectReference.class); + MetadataStore mds = new ODFFactory().create().getMetadataStore(); + List<MetaDataObject> referencedObjects = new ArrayList<MetaDataObject>(); + if (InternalMetaDataUtils.ODF_PARENT_REFERENCE.equals(referenceType.toUpperCase())) { + MetaDataObject parent = mds.getParent(mds.retrieve(ref)); + if (parent != null) { + referencedObjects.add(parent); + } + } else if (InternalMetaDataUtils.ODF_CHILDREN_REFERENCE.toString().equals(referenceType.toUpperCase())) { + referencedObjects = mds.getChildren(mds.retrieve(ref)); + } else { + referencedObjects = mds.getReferences(referenceType.toUpperCase(), mds.retrieve(ref)); + } + List<JSONObject> jsons = new ArrayList<JSONObject>(); + for (MetaDataObject obj : referencedObjects) { + jsons.add(JSONUtils.toJSONObject(obj)); + } + String result = JSONUtils.toJSON(jsons); + logger.log(Level.FINE, "Serialized JSON: {0}", result); + return Response.ok(result).build(); + } catch (JSONException e) { + logger.warning("Parse exception " + e.getMessage() + " Parsed object: " + assetReference); + return RestUtils.createErrorResponse(e); + } + } + + @GET + @Path("/sampledata") + @ApiOperation(value = "Create sample data", httpMethod = "GET", notes = "Populate metadata repository with ODF sample metadata", response = Response.class) + @ApiResponses(value = { @ApiResponse(code = 200, message = "OK"), @ApiResponse(code = 500, message = "Internal server error") }) + public Response createSampleData() { + try { + MetadataStore mds = new ODFFactory().create().getMetadataStore(); + mds.createSampleData(); + return Response.ok().build(); + } catch (Exception exc) { + exc.printStackTrace(); + throw new RuntimeException(exc); + } + } + + @POST + @Path("/resetalldata") + public Response resetAllData() { + try { + MetadataStore mds = new ODFFactory().create().getMetadataStore(); + mds.resetAllData(); + return Response.ok().build(); + } catch (Exception e) { + logger.log(Level.WARNING, "An exception occurred while resetting metatdata store", e); + return RestUtils.createErrorResponse(e); + } + } + + @GET + @Path("/search") + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Query metadata repository", httpMethod = "GET", notes = "Search for objects in metadata repository", responseContainer="List", response = MetaDataObjectReference.class) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK"), + @ApiResponse(code = 400, message = "Bad Request"), + @ApiResponse(code = 500, message = "Internal server error") }) + public Response search(@ApiParam(value = "Query to be sent to metadata repository (refer to Atlas query notation)", required = true) @QueryParam("query") String query, + @ApiParam(value = "Type of results to be returned, 'objects' vs. 'references'", required = false) @QueryParam("resulttype") String resultType) { + List<MetaDataObjectReference> queryResults; + try { + MetadataStore mds = new ODFFactory().create().getMetadataStore(); + try { + queryResults = mds.search(query); + } catch(MetadataStoreException e) { + logger.log(Level.WARNING, MessageFormat.format("Error processing query ''{0}''.", query), e); + return Response.status(Status.BAD_REQUEST).build(); + } + List<JSONObject> jsons = new ArrayList<JSONObject>(); + if ((resultType != null) && resultType.equals("references")) { + for (MetaDataObjectReference ref : queryResults) { + jsons.add(JSONUtils.toJSONObject(ref)); + } + } else { + // TODO very slow, retrieve results in bulk ?!? + //FIXME serialization of each object on its own is necessary because of a jackson issue (https://github.com/FasterXML/jackson-databind/issues/336) + //this should be replaced by a custom objectmapper initialization, issue #59 in gitlab + for (MetaDataObjectReference ref : queryResults) { + MetaDataObject retrievedMdo = mds.retrieve(ref); + jsons.add(JSONUtils.toJSONObject(retrievedMdo)); + } + } + String result = JSONUtils.toJSON(jsons); + logger.log(Level.FINE, "Serialized JSON: {0}", result); + return Response.ok(result).build(); + } catch (Exception exc) { + exc.printStackTrace(); + throw new RuntimeException(exc); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6d19e129/odf/odf-web/src/main/java/org/apache/atlas/odf/admin/rest/resources/SettingsResource.java ---------------------------------------------------------------------- diff --git a/odf/odf-web/src/main/java/org/apache/atlas/odf/admin/rest/resources/SettingsResource.java b/odf/odf-web/src/main/java/org/apache/atlas/odf/admin/rest/resources/SettingsResource.java new file mode 100755 index 0000000..e203774 --- /dev/null +++ b/odf/odf-web/src/main/java/org/apache/atlas/odf/admin/rest/resources/SettingsResource.java @@ -0,0 +1,128 @@ +/** + * + * 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.apache.atlas.odf.admin.rest.resources; + +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; + +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.logging.Logger; + +import javax.ws.rs.Consumes; +import javax.ws.rs.POST; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.apache.atlas.odf.admin.rest.RestUtils; +import org.apache.atlas.odf.api.settings.ODFSettings; +import org.apache.atlas.odf.api.settings.SettingsManager; +import org.apache.atlas.odf.api.settings.validation.ValidationException; +import org.apache.atlas.odf.json.JSONUtils; +import org.apache.wink.json4j.JSONException; + +import org.apache.atlas.odf.api.ODFFactory; + +@Path("/settings") +@Api(value = "/settings", description = "View or update the settings of the Open Discovery Framework", produces = MediaType.APPLICATION_JSON) +public class SettingsResource { + + private Logger logger = Logger.getLogger(SettingsResource.class.getName()); + + @GET + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Retrieve settings", httpMethod = "GET", notes = "Retrieve current ODF settings", response = ODFSettings.class) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK"), + @ApiResponse(code = 500, message = "Internal server error") + }) + public Response getSettings() { + logger.entering(SettingsResource.class.getName(), "getConfig"); + try { + return Response.ok(JSONUtils.toJSON(new ODFFactory().create().getSettingsManager().getODFSettingsHidePasswords()), MediaType.APPLICATION_JSON).build(); + } catch (JSONException e) { + e.printStackTrace(); + logger.info("Parse exception " + e); + return RestUtils.createErrorResponse(e); + } + } + + @POST + @Path("/reset") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Reset settings", httpMethod = "POST", notes = "Reset ODF settings to the default", response = Response.class) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK"), + @ApiResponse(code = 500, message = "Internal server error") + }) + public Response resetSettings() { + logger.entering(SettingsResource.class.getName(), "getConfig"); + new ODFFactory().create().getSettingsManager().resetODFSettings(); + return Response.ok().build(); + } + + @PUT + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Update settings", httpMethod = "PUT", notes = "Update ODF settings", response = ODFSettings.class) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK"), + @ApiResponse(code = 400, message = "Bad Request"), + @ApiResponse(code = 500, message = "Internal server error") + }) + public Response changeSettings(@ApiParam(value = "ODF configuration options", required = true) ODFSettings odfConfig) { + logger.entering(SettingsResource.class.getName(), "changeConfig"); + if (odfConfig == null) { + return Response.status(Status.BAD_REQUEST).entity("The body must be a valid settings JSON.").build(); + } + + try { + SettingsManager config = new ODFFactory().create().getSettingsManager(); + config.updateODFSettings(odfConfig); + return Response.ok(JSONUtils.toJSON(config.getODFSettingsHidePasswords())).build(); + } catch (ValidationException e) { + e.printStackTrace(); + logger.info("Validation exception during setting of property " + e.getProperty()); + return RestUtils.createErrorResponse(e); + } catch (JSONException e1) { + e1.printStackTrace(); + return RestUtils.createErrorResponse(MessageFormat.format("The provided input is not valid JSON in form {0}", getEmptyODFConfig())); + } + } + + private String getEmptyODFConfig() { + ODFSettings odf = new ODFSettings(); + odf.setUserDefined(new HashMap<String, Object>()); + String emptyJSON = ""; + try { + emptyJSON = JSONUtils.toJSON(odf); + } catch (JSONException e2) { + e2.printStackTrace(); + } + return emptyJSON; + } + + + +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6d19e129/odf/odf-web/src/main/resources/org/apache/atlas/odf/images/activity_32.png ---------------------------------------------------------------------- diff --git a/odf/odf-web/src/main/resources/org/apache/atlas/odf/images/activity_32.png b/odf/odf-web/src/main/resources/org/apache/atlas/odf/images/activity_32.png new file mode 100755 index 0000000..fabcc37 Binary files /dev/null and b/odf/odf-web/src/main/resources/org/apache/atlas/odf/images/activity_32.png differ http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6d19e129/odf/odf-web/src/main/resources/org/apache/atlas/odf/images/applications_32.png ---------------------------------------------------------------------- diff --git a/odf/odf-web/src/main/resources/org/apache/atlas/odf/images/applications_32.png b/odf/odf-web/src/main/resources/org/apache/atlas/odf/images/applications_32.png new file mode 100755 index 0000000..1f3744b Binary files /dev/null and b/odf/odf-web/src/main/resources/org/apache/atlas/odf/images/applications_32.png differ http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6d19e129/odf/odf-web/src/main/resources/org/apache/atlas/odf/images/bar-chart_32.png ---------------------------------------------------------------------- diff --git a/odf/odf-web/src/main/resources/org/apache/atlas/odf/images/bar-chart_32.png b/odf/odf-web/src/main/resources/org/apache/atlas/odf/images/bar-chart_32.png new file mode 100755 index 0000000..59a7ff8 Binary files /dev/null and b/odf/odf-web/src/main/resources/org/apache/atlas/odf/images/bar-chart_32.png differ http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6d19e129/odf/odf-web/src/main/resources/org/apache/atlas/odf/images/world_32.png ---------------------------------------------------------------------- diff --git a/odf/odf-web/src/main/resources/org/apache/atlas/odf/images/world_32.png b/odf/odf-web/src/main/resources/org/apache/atlas/odf/images/world_32.png new file mode 100755 index 0000000..4b9bcd3 Binary files /dev/null and b/odf/odf-web/src/main/resources/org/apache/atlas/odf/images/world_32.png differ http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6d19e129/odf/odf-web/src/main/webapp/.gitignore ---------------------------------------------------------------------- diff --git a/odf/odf-web/src/main/webapp/.gitignore b/odf/odf-web/src/main/webapp/.gitignore new file mode 100755 index 0000000..4cc0506 --- /dev/null +++ b/odf/odf-web/src/main/webapp/.gitignore @@ -0,0 +1,19 @@ +# +# 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. +# +/odf-web.js +/odf-web.js.map +/odf-client.js +/odf-client.js.map +resources +resources/** http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6d19e129/odf/odf-web/src/main/webapp/WEB-INF/web.xml ---------------------------------------------------------------------- diff --git a/odf/odf-web/src/main/webapp/WEB-INF/web.xml b/odf/odf-web/src/main/webapp/WEB-INF/web.xml new file mode 100755 index 0000000..9e16b0d --- /dev/null +++ b/odf/odf-web/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +~ +~ 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. +--> +<web-app id="WebApp_ID" version="3.0" + xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> + <display-name>odf-admin</display-name> + <servlet> + <servlet-name>odf-admin-servlet</servlet-name> + <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> + <init-param> + <param-name>javax.ws.rs.Application</param-name> + <param-value>org.apache.atlas.odf.admin.rest.ODFAdminApp</param-value> + </init-param> + <load-on-startup>1</load-on-startup> + <enabled>true</enabled> + <async-supported>false</async-supported> + </servlet> + + <servlet-mapping> + <servlet-name>odf-admin-servlet</servlet-name> + <url-pattern>/odf/api/v1/*</url-pattern> + </servlet-mapping> + + <security-constraint> + <web-resource-collection> + <web-resource-name>Secure resources</web-resource-name> + <url-pattern>/*</url-pattern> + </web-resource-collection> + <auth-constraint> + <role-name>admin</role-name> + <role-name>user</role-name> + <role-name>moderator</role-name> + </auth-constraint> + </security-constraint> + <login-config> + <auth-method>BASIC</auth-method> + <realm-name>ODF Realm</realm-name> + </login-config> +</web-app> http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6d19e129/odf/odf-web/src/main/webapp/client_index.html ---------------------------------------------------------------------- diff --git a/odf/odf-web/src/main/webapp/client_index.html b/odf/odf-web/src/main/webapp/client_index.html new file mode 100755 index 0000000..ea85c87 --- /dev/null +++ b/odf/odf-web/src/main/webapp/client_index.html @@ -0,0 +1,31 @@ +<!doctype html> +<!-- + ~ 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. + --> +<html> +<head> + <meta charset="utf-8"> + <title>Data lake application</title> +</head> +<body> + <div id="odf-toplevel-div" class="container-fluid"> + Loading... + </div> + <script type="text/javascript" src="odf-config.js"></script> + <script type="text/javascript" src="odf-client.js"></script> +</body> +</html> http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6d19e129/odf/odf-web/src/main/webapp/img/lg_proc.gif ---------------------------------------------------------------------- diff --git a/odf/odf-web/src/main/webapp/img/lg_proc.gif b/odf/odf-web/src/main/webapp/img/lg_proc.gif new file mode 100755 index 0000000..7dd40ef Binary files /dev/null and b/odf/odf-web/src/main/webapp/img/lg_proc.gif differ http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6d19e129/odf/odf-web/src/main/webapp/index.html ---------------------------------------------------------------------- diff --git a/odf/odf-web/src/main/webapp/index.html b/odf/odf-web/src/main/webapp/index.html new file mode 100755 index 0000000..f224997 --- /dev/null +++ b/odf/odf-web/src/main/webapp/index.html @@ -0,0 +1,31 @@ +<!doctype html> +<!-- + ~ 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. + --> +<html> +<head> + <meta charset="utf-8"> + <title>Open Discovery Framework</title> +</head> +<body> + <div id="odf-toplevel-div" class="container-fluid"> + Loading... + </div> + <script type="text/javascript" src="odf-config.js"></script> + <script type="text/javascript" src="odf-web.js"></script> +</body> +</html> http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6d19e129/odf/odf-web/src/main/webapp/odf-config.js ---------------------------------------------------------------------- diff --git a/odf/odf-web/src/main/webapp/odf-config.js b/odf/odf-web/src/main/webapp/odf-config.js new file mode 100755 index 0000000..6bb4a47 --- /dev/null +++ b/odf/odf-web/src/main/webapp/odf-config.js @@ -0,0 +1,15 @@ +/** + * + * 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. + */ +const API_PATH = "odf/api/v1/"; http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6d19e129/odf/odf-web/src/main/webapp/scripts/odf-analysis-request.js ---------------------------------------------------------------------- diff --git a/odf/odf-web/src/main/webapp/scripts/odf-analysis-request.js b/odf/odf-web/src/main/webapp/scripts/odf-analysis-request.js new file mode 100755 index 0000000..67bb709 --- /dev/null +++ b/odf/odf-web/src/main/webapp/scripts/odf-analysis-request.js @@ -0,0 +1,473 @@ +/** + * + * 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. + */ +var $ = require("jquery"); +var bootstrap = require("bootstrap"); + +var React = require("react"); +var ReactDOM = require("react-dom"); +var LinkedStateMixin = require('react-addons-linked-state-mixin'); +var ReactBootstrap = require("react-bootstrap"); +var AJAXCleanupMixin = require("./odf-mixins.js"); +var configurationStore = require("./odf-configuration-store.js"); +var metadataStore = require("./odf-utils.js").MetadataStore; +var ODFGlobals = require("./odf-globals.js"); + +var Button = ReactBootstrap.Button; +var Row = ReactBootstrap.Row; +var Col = ReactBootstrap.Col; +var Table = ReactBootstrap.Table; +var Modal = ReactBootstrap.Modal; +var Input = ReactBootstrap.Input; +var Alert = ReactBootstrap.Alert; +var Panel = ReactBootstrap.Panel; +var Label = ReactBootstrap.Label; +var Input = ReactBootstrap.Input; +var Image = ReactBootstrap.Image; + +var OdfAnalysisRequest = { + NewAnalysisRequestButton : React.createClass({ + + getInitialState : function(){ + return {showAnalysisRequestDialog : false}; + }, + + open : function(){ + this.setState({showAnalysisRequestDialog: true}); + }, + + onClose : function(){ + this.setState({showAnalysisRequestDialog: false}); + if(this.props.onClose){ + this.props.onClose(); + } + }, + + render : function() { + return ( + <span> + <Button bsStyle={this.props.bsStyle} onClick={this.open}>Start analysis (service sequence)</Button> + <OdfAnalysisRequest.NewAnalysisRequestDialog show={this.state.showAnalysisRequestDialog} dataSetId={this.props.dataSetId} alertCallback={this.props.alertCallback} onClose={this.onClose}/> + </span> + ); + } + + }), + + NewAnalysisRequestDialog : React.createClass({ + + mixins : [AJAXCleanupMixin], + + getInitialState : function() { + return ({config: null, discoveryServices: [], errorMessage: null, discoveryServiceSequence: []}); + }, + + close : function() { + this.clearDialogState(); + if(this.props.onClose){ + this.props.onClose(); + } + }, + + submitRequest : function() { + this.setState({requestInProgress : true}); + var dataSet = this.refs.inputDataSet.getValue(); + var discoveryServiceIDs = $.map(this.state.discoveryServiceSequence, + function(dsreg) { + return dsreg.id; + } + ); + + var repositoryId = this.state.repositoryId; + var metadataObjectRef = { + repositoryId: repositoryId, + id: dataSet + }; + var analysisRequest = { + dataSets: [metadataObjectRef], + discoveryServiceSequence: discoveryServiceIDs + }; + + // now post request + // clear alert + if(this.props.alertCallback){ + this.props.alertCallback({type: "", message: ""}); + } + var req = $.ajax({ + url: ODFGlobals.analysisUrl, + contentType: "application/json", + dataType: 'json', + type: 'POST', + data: JSON.stringify(analysisRequest), + success: function(analysisResponse) { + if(!this.isMounted()){ + return; + } + if (analysisResponse.invalidRequest) { + this.setState({errorMessage: analysisResponse.details, requestInProgress: false}); + } else { + var msg = "Analysis request was started. ID: " + analysisResponse.id; + if(this.props.alertCallback){ + this.props.alertCallback({type: "success", message: msg}); + } + this.close(); + } + }.bind(this), + error: function(xhr, status, err) { + var msg = "Error while reading ODF services: " + err.toString(); + this.setState({errorMessage: msg, requestInProgress: false}); + }.bind(this) + }); + + this.storeAbort(req.abort); + }, + + componentDidMount : function() { + this.loadDiscoveryServices(); + }, + + loadDiscoveryServices : function() { + var req = configurationStore.readConfig( + function(config) { + if(!this.isMounted()){ + return; + } + this.setState({config: config}); + // clear alert + if(this.props.alertCallback){ + this.props.alertCallback({type: "", message: ""}); + } + var req2 = $.ajax({ + url: ODFGlobals.servicesUrl, + dataType: 'json', + type: 'GET', + success: function(data) { + if(!this.isMounted()){ + return; + } + this.setState({discoveryServices: data}); + }.bind(this), + error: function(xhr, status, err) { + var msg = "Error while reading ODF services: " + err.toString(); + if(this.props.alertCallback){ + this.props.alertCallback({type: "danger", message: msg}); + } + }.bind(this) + }); + this.storeAbort(req2.abort); + }.bind(this), + this.props.alertCallback + ); + + this.storeAbort(req.abort); + }, + + getDiscoveryServiceFromId : function(id) { + var servicesWithSameId = this.state.discoveryServices.filter( + function(dsreg) { + return dsreg.id == id; + } + ); + if (servicesWithSameId.length > 0) { + return servicesWithSameId[0]; + } + return null; + }, + + processDiscoveryServiceSelection : function() { + var selection = this.refs.inputAvailableDiscoveryServices.getValue(); + var dsreg = this.getDiscoveryServiceFromId(selection); + if (dsreg) { + var newSequence = this.state.discoveryServiceSequence.slice(); + newSequence.push(dsreg); + this.setState({discoveryServiceSequence: newSequence}); + } + }, + + clearDialogState : function() { + this.setState({discoveryServiceSequence: [], requestInProgress : false, }); + }, + + render : function() { + var alert = null; + if (this.state.errorMessage) { + alert = <Alert bsStyle="danger">{this.state.errorMessage}</Alert>; + } + var servicesOptions = $.map( + this.state.discoveryServices, + function(dsreg) { + return (<option key={dsreg.id} value={dsreg.id}>{dsreg.name}</option>); + }.bind(this) + ); + + var discoveryServiceSequenceComponents = $.map(this.state.discoveryServiceSequence, + function(dsreg) { + return <li key={dsreg.id}>{dsreg.name} ({dsreg.id})</li> + } + ); + + var waitingContainer = <div style={{position:"absolute", width:"100%", height:"100%", left:"50%", top: "30%"}}><Image src="img/lg_proc.gif" rounded /></div>; + if(!this.state.requestInProgress){ + waitingContainer = null; + } + + return ( + <Modal show={this.props.show} onHide={this.close}> + <Modal.Header closeButton> + <Modal.Title>Start analysis (specify service sequence)</Modal.Title> + </Modal.Header> + <Modal.Body> + {waitingContainer} + {alert} + <Input type="text" ref="inputDataSet" label="Data Set" value={this.props.dataSetId} readOnly={this.props.dataSetId}></Input> + <hr/> + Select a service from the "Available Services" + dropdown to append it to the sequence. Repeat selection to run multiple services for the data set. + <Input type="select" onChange={this.processDiscoveryServiceSelection} ref="inputAvailableDiscoveryServices" label="Available Services"> + <option key="emptySelection"><Select a service...></option> + {servicesOptions} + </Input> + <strong>Service Sequence</strong> + <ol>{discoveryServiceSequenceComponents}</ol> + <hr /> + <Button bsStyle="warning" onClick={this.clearDialogState}>Clear Sequence</Button> + </Modal.Body> + <Modal.Footer> + <Button onClick={this.submitRequest} bsStyle="primary">Submit</Button> + <Button onClick={this.close} >Cancel</Button> + </Modal.Footer> + </Modal> + ); + } + + }), + + NewCreateAnnotationsButton : React.createClass({ + + getInitialState : function(){ + return {showCreateAnnotationsDialog : false}; + }, + + open : function(){ + this.setState({showCreateAnnotationsDialog: true}); + }, + + onClose : function(){ + this.setState({showCreateAnnotationsDialog: false}); + if(this.props.onClose){ + this.props.onClose(); + } + }, + + render : function() { + return ( + <span> + <Button bsStyle={this.props.bsStyle} onClick={this.open}>Start analysis (annotation types)</Button> + <OdfAnalysisRequest.NewCreateAnnotationsDialog show={this.state.showCreateAnnotationsDialog} dataSetId={this.props.dataSetId} alertCallback={this.props.alertCallback} onClose={this.onClose}/> + </span> + ); + } + + }), + + NewCreateAnnotationsDialog : React.createClass({ + + mixins : [AJAXCleanupMixin], + + getInitialState : function() { + return ({config: null, annotationTypes: [], errorMessage: null, analysisTypeSelection: []}); + }, + + close : function() { + this.clearDialogState(); + if(this.props.onClose){ + this.props.onClose(); + } + }, + + submitRequest : function() { + this.setState({requestInProgress : true}); + var dataSet = this.refs.inputDataSet.getValue(); + var annotationTypeIDs = $.map(this.state.analysisTypeSelection, + function(annotationTypeId) { + return annotationTypeId; + } + ); + + var repositoryId = this.state.repositoryId; + var metadataObjectRef = { + repositoryId: repositoryId, + id: dataSet + }; + var analysisRequest = { + dataSets: [metadataObjectRef], + annotationTypes: annotationTypeIDs + }; + + // now post request + // clear alert + if(this.props.alertCallback){ + this.props.alertCallback({type: "", message: ""}); + } + var req = $.ajax({ + url: ODFGlobals.analysisUrl, + contentType: "application/json", + dataType: 'json', + type: 'POST', + data: JSON.stringify(analysisRequest), + success: function(analysisResponse) { + if(!this.isMounted()){ + return; + } + if (analysisResponse.invalidRequest) { + this.setState({errorMessage: analysisResponse.details, requestInProgress: false}); + } else { + var msg = "Analysis request was started. ID: " + analysisResponse.id; + if(this.props.alertCallback){ + this.props.alertCallback({type: "success", message: msg}); + } + this.close(); + } + }.bind(this), + error: function(xhr, status, err) { + var msg = "Error starting discovery request: " + err.toString(); + this.setState({errorMessage: msg, requestInProgress: false}); + }.bind(this) + }); + + this.storeAbort(req.abort); + }, + + componentDidMount : function() { + this.loadannotationTypes(); + }, + + loadannotationTypes : function() { + var req = configurationStore.readConfig( + function(config) { + if(!this.isMounted()){ + return; + } + this.setState({config: config}); + // clear alert + if(this.props.alertCallback){ + this.props.alertCallback({type: "", message: ""}); + } + var req2 = $.ajax({ + url: ODFGlobals.servicesUrl, + dataType: 'json', + type: 'GET', + success: function(data) { + if(!this.isMounted()){ + return; + } + var ids = []; + $.each(data, function(key, dsreg){ + $.each(dsreg.resultingAnnotationTypes, function(key, annotationTypeId){ + if($.inArray(annotationTypeId,ids) == -1){ + ids.push(annotationTypeId); + }; + }); + }); + this.setState({annotationTypes: ids}); + }.bind(this), + error: function(xhr, status, err) { + var msg = "Error while reading ODF services: " + err.toString(); + if(this.props.alertCallback){ + this.props.alertCallback({type: "danger", message: msg}); + } + }.bind(this) + }); + this.storeAbort(req2.abort); + }.bind(this), + this.props.alertCallback + ); + metadataStore.getProperties( + function(data) { + this.setState({repositoryId: data.STORE_PROPERTY_ID}); + }.bind(this) + ); + this.storeAbort(req.abort); + }, + + processAnalysisTypeSelection : function() { + var selection = this.refs.inputAvailableAnnotationTypes.getValue(); + if (selection) { + var newSelection = this.state.analysisTypeSelection.slice(); + newSelection.push(selection); + this.setState({analysisTypeSelection: newSelection}); + } + }, + + clearDialogState : function() { + this.setState({analysisTypeSelection: [], requestInProgress : false, }); + }, + + render : function() { + var alert = null; + if (this.state.errorMessage) { + alert = <Alert bsStyle="danger">{this.state.errorMessage}</Alert>; + } + var analysisTypeOptions = $.map( + this.state.annotationTypes, + function(annotationTypeId) { + return (<option key={annotationTypeId} value={annotationTypeId}>{annotationTypeId}</option>); + }.bind(this) + ); + + var analysisTypeSelectionComponents = $.map(this.state.analysisTypeSelection, + function(annotationTypeId) { + return <li key={annotationTypeId}>{annotationTypeId}</li> + } + ); + + var waitingContainer = <div style={{position:"absolute", width:"100%", height:"100%", left:"50%", top: "30%"}}><Image src="img/lg_proc.gif" rounded /></div>; + if(!this.state.requestInProgress){ + waitingContainer = null; + } + + return ( + <Modal show={this.props.show} onHide={this.close}> + <Modal.Header closeButton> + <Modal.Title>Start analysis (specify annotation types)</Modal.Title> + </Modal.Header> + <Modal.Body> + {waitingContainer} + {alert} + <Input type="text" ref="inputDataSet" label="Data Set" value={this.props.dataSetId} readOnly={this.props.dataSetId}></Input> + <hr/> + Select an annotation type from the "Available Annotation Types" + dropdown to append it to the list. Repeat selection to create multiple annotation types for the data set. + <Input type="select" onChange={this.processAnalysisTypeSelection} ref="inputAvailableAnnotationTypes" label="Available Annotation Types"> + <option key="emptySelection"><Select an annotation type...></option> + {analysisTypeOptions} + </Input> + <strong>Selected Annotation Types</strong> + <ol>{analysisTypeSelectionComponents}</ol> + <hr /> + <Button bsStyle="warning" onClick={this.clearDialogState}>Clear Selection</Button> + </Modal.Body> + <Modal.Footer> + <Button onClick={this.submitRequest} bsStyle="primary">Submit</Button> + <Button onClick={this.close} >Cancel</Button> + </Modal.Footer> + </Modal> + ); + } + + }) +} + + +module.exports = OdfAnalysisRequest;
