You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by ma...@apache.org on 2023/02/09 17:29:46 UTC

[airavata-data-catalog] branch machristie/issue6 created (now 25a311a)

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

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


      at 25a311a  Data Product CRUD API Fixes #6

This branch includes the following new commits:

     new 25a311a  Data Product CRUD API Fixes #6

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[airavata-data-catalog] 01/01: Data Product CRUD API Fixes #6

Posted by ma...@apache.org.
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 <ma...@apache.org>
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){}
 }