This is an automated email from the ASF dual-hosted git repository.

machristie pushed a commit to branch machristie/issue6
in repository https://gitbox.apache.org/repos/asf/airavata-data-catalog.git

commit 25a311a5c8f6f01d8492132da7ded99efcf01510
Author: Marcus Christie <[email protected]>
AuthorDate: Thu Feb 9 12:29:39 2023 -0500

    Data Product CRUD API
    Fixes #6
---
 .../api/client/DataCatalogAPIClient.java           | 63 ++++++++++++++---
 .../datacatalog/api/mapper/DataProductMapper.java  | 54 +++++++++++++++
 .../api/repository/DataProductRepository.java      |  6 +-
 .../api/service/DataCatalogAPIService.java         | 81 ++++++++++++++--------
 .../stubs/src/main/proto/DataCatalogAPI.proto      | 20 ++++++
 5 files changed, 187 insertions(+), 37 deletions(-)

diff --git 
a/data-catalog-api/client/src/main/java/org/apache/airavata/datacatalog/api/client/DataCatalogAPIClient.java
 
b/data-catalog-api/client/src/main/java/org/apache/airavata/datacatalog/api/client/DataCatalogAPIClient.java
index 4ba83e1..8ae7d07 100644
--- 
a/data-catalog-api/client/src/main/java/org/apache/airavata/datacatalog/api/client/DataCatalogAPIClient.java
+++ 
b/data-catalog-api/client/src/main/java/org/apache/airavata/datacatalog/api/client/DataCatalogAPIClient.java
@@ -1,20 +1,24 @@
 package org.apache.airavata.datacatalog.api.client;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import io.grpc.Channel;
-import io.grpc.ManagedChannel;
-import io.grpc.ManagedChannelBuilder;
-
 import java.text.MessageFormat;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.airavata.datacatalog.api.DataCatalogAPIServiceGrpc;
+import 
org.apache.airavata.datacatalog.api.DataCatalogAPIServiceGrpc.DataCatalogAPIServiceBlockingStub;
 import org.apache.airavata.datacatalog.api.DataProduct;
 import org.apache.airavata.datacatalog.api.DataProductCreateRequest;
 import org.apache.airavata.datacatalog.api.DataProductCreateResponse;
-import 
org.apache.airavata.datacatalog.api.DataCatalogAPIServiceGrpc.DataCatalogAPIServiceBlockingStub;;
+import org.apache.airavata.datacatalog.api.DataProductDeleteRequest;
+import org.apache.airavata.datacatalog.api.DataProductGetRequest;
+import org.apache.airavata.datacatalog.api.DataProductGetResponse;
+import org.apache.airavata.datacatalog.api.DataProductUpdateRequest;
+import org.apache.airavata.datacatalog.api.DataProductUpdateResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import io.grpc.Channel;
+import io.grpc.ManagedChannel;
+import io.grpc.ManagedChannelBuilder;;
 
 public class DataCatalogAPIClient {
 
@@ -32,18 +36,59 @@ public class DataCatalogAPIClient {
         return response.getDataProduct();
     }
 
+    public DataProduct updateDataProduct(DataProduct dataProduct) {
+        DataProductUpdateRequest request = 
DataProductUpdateRequest.newBuilder().setDataProduct(dataProduct).build();
+        DataProductUpdateResponse response = 
blockingStub.updateDataProduct(request);
+        return response.getDataProduct();
+    }
+
+    public DataProduct getDataProduct(String dataProductId) {
+        DataProductGetRequest request = 
DataProductGetRequest.newBuilder().setDataProductId(dataProductId).build();
+        DataProductGetResponse response = blockingStub.getDataProduct(request);
+        return response.getDataProduct();
+    }
+
+    public void deleteDataProduct(String dataProductId) {
+        DataProductDeleteRequest request = 
DataProductDeleteRequest.newBuilder().setDataProductId(dataProductId)
+                .build();
+        blockingStub.deleteDataProduct(request);
+    }
+
     public static void main(String[] args) throws InterruptedException {
         String target = "localhost:6565";
 
         ManagedChannel channel = 
ManagedChannelBuilder.forTarget(target).usePlaintext().build();
         try {
             DataCatalogAPIClient client = new DataCatalogAPIClient(channel);
+            DataProduct parentDataProduct = 
DataProduct.newBuilder().setName("parent dp").build();
+            DataProduct parentResult = 
client.createDataProduct(parentDataProduct);
+
             DataProduct dataProduct = 
DataProduct.newBuilder().setName("testing").setMetadata("{\"foo\": \"bar\"}")
+                    .setParentDataProductId(parentResult.getDataProductId())
                     .build();
             DataProduct result = client.createDataProduct(dataProduct);
             System.out.println(MessageFormat.format("Created data product with 
id [{0}]", result.getDataProductId()));
 
-        }finally {
+            DataProduct updatedDataProduct = 
result.toBuilder().setName("updated name").build();
+            result = client.updateDataProduct(updatedDataProduct);
+            System.out.println(MessageFormat.format("Updated data product with 
id [{0}] to have name [{1}]",
+                    result.getDataProductId(), result.getName()));
+
+            DataProduct retrievedDataProduct = 
client.getDataProduct(result.getDataProductId());
+            System.out.println(MessageFormat.format("Retrieved data product 
with id [{0}] to have name [{1}]",
+                    retrievedDataProduct.getDataProductId(), 
retrievedDataProduct.getName()));
+
+            DataProduct dataProduct2 = 
DataProduct.newBuilder().setName("testing 2").setMetadata("{\"foo\": \"bar\"}")
+                    .build();
+            DataProduct result2 = client.createDataProduct(dataProduct2);
+            System.out.println(
+                    MessageFormat.format("Created second data product [{0}]", 
result2));
+
+            client.deleteDataProduct(result2.getDataProductId());
+            System.out.println(
+                    MessageFormat.format("Deleted data product with id [{0}]", 
result2.getDataProductId()));
+
+        } finally {
             channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS);
         }
     }
diff --git 
a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/mapper/DataProductMapper.java
 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/mapper/DataProductMapper.java
new file mode 100644
index 0000000..8e1e155
--- /dev/null
+++ 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/mapper/DataProductMapper.java
@@ -0,0 +1,54 @@
+package org.apache.airavata.datacatalog.api.mapper;
+
+import org.apache.airavata.datacatalog.api.DataProduct;
+import org.apache.airavata.datacatalog.api.model.DataProductEntity;
+import org.apache.airavata.datacatalog.api.repository.DataProductRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+/**
+ * Map to/from
+ * {@link org.apache.airavata.datacatalog.api.model.DataProductEntity}
+ * <-> {@link org.apache.airavata.datacatalog.api.DataProduct}
+ */
+@Component
+public class DataProductMapper {
+
+    @Autowired
+    DataProductRepository dataProductRepository;
+
+    public void mapModelToEntity(DataProduct dataProduct, DataProductEntity 
dataProductEntity) {
+
+        dataProductEntity.setName(dataProduct.getName());
+
+        if (dataProduct.hasParentDataProductId()) {
+            // TODO: handle parent data product not found
+            DataProductEntity parentDataProductEntity = dataProductRepository
+                    .findByExternalId(dataProduct.getParentDataProductId());
+            
dataProductEntity.setParentDataProductEntity(parentDataProductEntity);
+        }
+        if (dataProduct.hasMetadata()) {
+            ObjectMapper mapper = new ObjectMapper();
+            try {
+                JsonNode metadata = mapper.readTree(dataProduct.getMetadata());
+                dataProductEntity.setMetadata(metadata);
+            } catch (JsonProcessingException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    public void mapEntityToModel(DataProductEntity dataProductEntity, 
DataProduct.Builder dataProductBuilder) {
+
+        dataProductBuilder
+                .setDataProductId(dataProductEntity.getExternalId())
+                .setName(dataProductEntity.getName());
+        if (dataProductEntity.getParentDataProductEntity() != null) {
+            
dataProductBuilder.setParentDataProductId(dataProductEntity.getParentDataProductEntity().getExternalId());
+        }
+    }
+}
diff --git 
a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/repository/DataProductRepository.java
 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/repository/DataProductRepository.java
index 770eb8f..acec036 100644
--- 
a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/repository/DataProductRepository.java
+++ 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/repository/DataProductRepository.java
@@ -2,9 +2,13 @@ package org.apache.airavata.datacatalog.api.repository;
 
 import org.apache.airavata.datacatalog.api.model.DataProductEntity;
 import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.transaction.annotation.Transactional;
 
 public interface DataProductRepository extends 
JpaRepository<DataProductEntity, Long> {
 
-    DataProductEntity findByExternalId(String parentDataProductId);
+    DataProductEntity findByExternalId(String externalId);
+
+    @Transactional
+    void deleteByExternalId(String externalId);
 
 }
diff --git 
a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/service/DataCatalogAPIService.java
 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/service/DataCatalogAPIService.java
index e14c437..65f92b7 100644
--- 
a/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/service/DataCatalogAPIService.java
+++ 
b/data-catalog-api/server/src/main/java/org/apache/airavata/datacatalog/api/service/DataCatalogAPIService.java
@@ -3,8 +3,16 @@ package org.apache.airavata.datacatalog.api.service;
 import java.util.UUID;
 
 import org.apache.airavata.datacatalog.api.DataCatalogAPIServiceGrpc;
+import org.apache.airavata.datacatalog.api.DataProduct;
 import org.apache.airavata.datacatalog.api.DataProductCreateRequest;
 import org.apache.airavata.datacatalog.api.DataProductCreateResponse;
+import org.apache.airavata.datacatalog.api.DataProductDeleteRequest;
+import org.apache.airavata.datacatalog.api.DataProductDeleteResponse;
+import org.apache.airavata.datacatalog.api.DataProductGetRequest;
+import org.apache.airavata.datacatalog.api.DataProductGetResponse;
+import org.apache.airavata.datacatalog.api.DataProductUpdateRequest;
+import org.apache.airavata.datacatalog.api.DataProductUpdateResponse;
+import org.apache.airavata.datacatalog.api.mapper.DataProductMapper;
 import org.apache.airavata.datacatalog.api.model.DataProductEntity;
 import org.apache.airavata.datacatalog.api.repository.DataProductRepository;
 import org.lognet.springboot.grpc.GRpcService;
@@ -12,10 +20,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
 import io.grpc.stub.StreamObserver;
 
 @GRpcService
@@ -26,6 +30,9 @@ public class DataCatalogAPIService extends 
DataCatalogAPIServiceGrpc.DataCatalog
     @Autowired
     DataProductRepository dataProductRepository;
 
+    @Autowired
+    DataProductMapper dataProductMapper = new DataProductMapper();
+
     @Override
     public void createDataProduct(DataProductCreateRequest request,
             StreamObserver<DataProductCreateResponse> responseObserver) {
@@ -34,35 +41,55 @@ public class DataCatalogAPIService extends 
DataCatalogAPIServiceGrpc.DataCatalog
         logger.info("Creating data product {}", request.getDataProduct());
         DataProductEntity dataProductEntity = new DataProductEntity();
         dataProductEntity.setExternalId(UUID.randomUUID().toString());
-        dataProductEntity.setName(request.getDataProduct().getName());
-        if (request.getDataProduct().hasParentDataProductId()) {
-            // TODO: handle parent data product not found
-            DataProductEntity parentDataProductEntity = dataProductRepository
-                    
.findByExternalId(request.getDataProduct().getParentDataProductId());
-            
dataProductEntity.setParentDataProductEntity(parentDataProductEntity);
-        }
-        if (request.getDataProduct().hasMetadata()) {
-            ObjectMapper mapper = new ObjectMapper();
-            try {
-                JsonNode metadata = 
mapper.readTree(request.getDataProduct().getMetadata());
-                dataProductEntity.setMetadata(metadata);
-            } catch (JsonProcessingException e) {
-                throw new RuntimeException(e);
-            }
-        }
+        dataProductMapper.mapModelToEntity(request.getDataProduct(), 
dataProductEntity);
         DataProductEntity savedDataProductEntity = 
dataProductRepository.save(dataProductEntity);
 
         // TODO: SharingManager.grantPermissionToUser(userInfo, dataProduct,
         // Permission.OWNER)
 
         DataProductCreateResponse.Builder responseBuilder = 
DataProductCreateResponse.newBuilder();
-        responseBuilder.getDataProductBuilder()
-                .setDataProductId(savedDataProductEntity.getExternalId())
-                .setName(savedDataProductEntity.getName()).build();
-        if (savedDataProductEntity.getParentDataProductEntity() != null) {
-            responseBuilder.getDataProductBuilder()
-                    
.setParentDataProductId(savedDataProductEntity.getParentDataProductEntity().getExternalId());
-        }
+        dataProductMapper.mapEntityToModel(savedDataProductEntity, 
responseBuilder.getDataProductBuilder());
+        responseObserver.onNext(responseBuilder.build());
+        responseObserver.onCompleted();
+    }
+
+    @Override
+    public void updateDataProduct(DataProductUpdateRequest request,
+            StreamObserver<DataProductUpdateResponse> responseObserver) {
+
+        // TODO: check that user has access to update data product record
+        // TODO: handle data product does not exist
+        DataProduct dataProduct = request.getDataProduct();
+        DataProductEntity dataProductEntity = dataProductRepository
+                .findByExternalId(dataProduct.getDataProductId());
+        dataProductMapper.mapModelToEntity(dataProduct, dataProductEntity);
+
+        DataProductEntity savedDataProductEntity = 
dataProductRepository.save(dataProductEntity);
+
+        DataProductUpdateResponse.Builder responseBuilder = 
DataProductUpdateResponse.newBuilder();
+        dataProductMapper.mapEntityToModel(savedDataProductEntity, 
responseBuilder.getDataProductBuilder());
+        responseObserver.onNext(responseBuilder.build());
+        responseObserver.onCompleted();
+    }
+
+    @Override
+    public void getDataProduct(DataProductGetRequest request, 
StreamObserver<DataProductGetResponse> responseObserver) {
+        // TODO: check that user has READ access on data product record
+        // TODO: handle data product does not exist
+        DataProductEntity dataProductEntity = dataProductRepository
+                .findByExternalId(request.getDataProductId());
+        DataProductGetResponse.Builder responseBuilder = 
DataProductGetResponse.newBuilder();
+        dataProductMapper.mapEntityToModel(dataProductEntity, 
responseBuilder.getDataProductBuilder());
+        responseObserver.onNext(responseBuilder.build());
+        responseObserver.onCompleted();
+    }
+
+    @Override
+    public void deleteDataProduct(DataProductDeleteRequest request,
+            StreamObserver<DataProductDeleteResponse> responseObserver) {
+        // TODO: check that user has WRITE access on data product record
+        dataProductRepository.deleteByExternalId(request.getDataProductId());
+        DataProductDeleteResponse.Builder responseBuilder = 
DataProductDeleteResponse.newBuilder();
         responseObserver.onNext(responseBuilder.build());
         responseObserver.onCompleted();
     }
diff --git a/data-catalog-api/stubs/src/main/proto/DataCatalogAPI.proto 
b/data-catalog-api/stubs/src/main/proto/DataCatalogAPI.proto
index 9508fff..779002c 100644
--- a/data-catalog-api/stubs/src/main/proto/DataCatalogAPI.proto
+++ b/data-catalog-api/stubs/src/main/proto/DataCatalogAPI.proto
@@ -70,7 +70,27 @@ message DataProductCreateRequest {
 message DataProductCreateResponse {
     DataProduct data_product = 1;
 }
+message DataProductUpdateRequest {
+    DataProduct data_product = 1;
+}
+message DataProductUpdateResponse {
+    DataProduct data_product = 1;
+}
+message DataProductGetRequest {
+    string data_product_id = 1;
+}
+message DataProductGetResponse {
+    DataProduct data_product = 1;
+}
+message DataProductDeleteRequest {
+    string data_product_id = 1;
+}
+message DataProductDeleteResponse {
+}
 
 service DataCatalogAPIService {
     rpc createDataProduct(DataProductCreateRequest) returns 
(DataProductCreateResponse){}
+    rpc updateDataProduct(DataProductUpdateRequest) returns 
(DataProductUpdateResponse){}
+    rpc getDataProduct(DataProductGetRequest) returns 
(DataProductGetResponse){}
+    rpc deleteDataProduct(DataProductDeleteRequest) returns 
(DataProductDeleteResponse){}
 }

Reply via email to