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

lahirujayathilake pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-custos.git

commit b9a666bccba4bce4f113d54e57a8c316ef040ec6
Author: lahiruj <[email protected]>
AuthorDate: Tue Oct 7 18:43:15 2025 -0400

    included AMIE project create handler
---
 .gitignore                                         |   3 +
 .../org/apache/custos/amie/client/AmieClient.java  |   4 +-
 .../amie/handler/RequestAccountCreateHandler.java  |   4 +-
 .../amie/handler/RequestProjectCreateHandler.java  | 118 +++++++++++++++++++++
 4 files changed, 125 insertions(+), 4 deletions(-)

diff --git a/.gitignore b/.gitignore
index 78c1f0f1e..f28440d5b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -40,3 +40,6 @@ node_modules/
 dist/
 
 database_data
+
+# local application properties
+application.properties
diff --git 
a/amie-decoder/src/main/java/org/apache/custos/amie/client/AmieClient.java 
b/amie-decoder/src/main/java/org/apache/custos/amie/client/AmieClient.java
index 679b74bc6..f025c82fa 100644
--- a/amie-decoder/src/main/java/org/apache/custos/amie/client/AmieClient.java
+++ b/amie-decoder/src/main/java/org/apache/custos/amie/client/AmieClient.java
@@ -47,7 +47,7 @@ import java.util.Map;
 public class AmieClient {
 
     private static final Logger LOGGER = 
LoggerFactory.getLogger(AmieClient.class);
-    private static final String PACKETS_PATH = "/packets/{site}/";
+    private static final String PACKETS_PATH = "%s/packets/%s";
     private static final String HEADER_XA_SITE = "XA-SITE";
     private static final String HEADER_XA_API_KEY = "XA-API-KEY";
 
@@ -66,7 +66,7 @@ public class AmieClient {
      * @return A list of packets. Returns an empty list if the call fails or 
no packets are found.
      */
     public List<JsonNode> fetchInProgressPackets() {
-        String url = String.format("%s/packets/%s/", properties.getBaseUrl(), 
properties.getSiteCode());
+        String url = String.format(PACKETS_PATH, properties.getBaseUrl(), 
properties.getSiteCode());
         LOGGER.info("Polling for AMIE packets at URL: {}", url);
 
         HttpHeaders headers = createAmieHeaders();
diff --git 
a/amie-decoder/src/main/java/org/apache/custos/amie/handler/RequestAccountCreateHandler.java
 
b/amie-decoder/src/main/java/org/apache/custos/amie/handler/RequestAccountCreateHandler.java
index 9fe14b712..3939b007f 100644
--- 
a/amie-decoder/src/main/java/org/apache/custos/amie/handler/RequestAccountCreateHandler.java
+++ 
b/amie-decoder/src/main/java/org/apache/custos/amie/handler/RequestAccountCreateHandler.java
@@ -31,11 +31,11 @@ import java.util.Map;
 import java.util.UUID;
 
 /**
- * Handles the 'request_account_create' AMIE packet.
+ * Handles the 'request_account_create' (RAC) AMIE packet.
  * <p>
  * This transaction asks the local site to create an account for a user on a 
project.
  * This includes creating a local user account with the specified project (a 
Unix account) if one does not exist.
- * Upon successful processing sends a 'notify_account_create' reply back to 
AMIE.
+ * Upon successful processing sends a 'notify_account_create' (NAC) reply back 
to AMIE.
  */
 @Component
 public class RequestAccountCreateHandler implements PacketHandler {
diff --git 
a/amie-decoder/src/main/java/org/apache/custos/amie/handler/RequestProjectCreateHandler.java
 
b/amie-decoder/src/main/java/org/apache/custos/amie/handler/RequestProjectCreateHandler.java
new file mode 100644
index 000000000..3841a2a89
--- /dev/null
+++ 
b/amie-decoder/src/main/java/org/apache/custos/amie/handler/RequestProjectCreateHandler.java
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+package org.apache.custos.amie.handler;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.apache.custos.amie.client.AmieClient;
+import org.apache.custos.amie.model.PacketEntity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Handles 'request_project_create' (RPC) by replying with 
'notify_project_create' (NPC).
+ */
+@Component
+public class RequestProjectCreateHandler implements PacketHandler {
+
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(RequestProjectCreateHandler.class);
+
+    private final AmieClient amieClient;
+
+    public RequestProjectCreateHandler(AmieClient amieClient) {
+        this.amieClient = amieClient;
+    }
+
+    @Override
+    public void handle(JsonNode packetJson, PacketEntity packetEntity) {
+
+        // TODO - refactor the sanity checks into Packet Router (if all the 
packets follow the same style)
+        if (packetJson == null) {
+            LOGGER.error("packet json is null");
+            throw new IllegalArgumentException("packetJson is null");
+        }
+
+        JsonNode body = packetJson.path("body");
+        if (body.isMissingNode()) {
+            LOGGER.error("body is null");
+            throw new IllegalArgumentException("packetJson.body is missing");
+        }
+
+        String grantNumber = body.path("GrantNumber").asText("");
+        String projectTitle = body.path("ProjectTitle").asText("");
+        String startDate = body.path("StartDate").asText("");
+        String endDate = body.path("EndDate").asText("");
+        String recordId = body.path("RecordID").asText("");
+        String piOrgCode = body.path("PiOrgCode").asText("");
+        String pfosNumber = body.path("PfosNumber").asText("");
+        String piGlobalID = body.path("PiGlobalID").asText("");
+
+        // ResourceList will have only one resource (According to AMIE 
documentation)
+        List<Object> resourceList = new ArrayList<>();
+        JsonNode rl = body.path("ResourceList");
+        if (rl.isArray()) {
+            rl.forEach(node -> resourceList.add(node.asText()));
+        } else {
+            LOGGER.warn("No resource list found for amie_id [{}]", 
packetEntity.getAmieId());
+        }
+
+        // TODO - Derive a local project identifier
+        String localProjectId = deriveLocalProjectId(grantNumber);
+
+        // Build the NPC reply body
+        Map<String, Object> replyBody = new HashMap<>();
+        Map<String, Object> npc = new HashMap<>();
+        npc.put("GrantNumber", grantNumber);
+        npc.put("ProjectTitle", projectTitle);
+        npc.put("StartDate", startDate);
+        npc.put("EndDate", endDate);
+        npc.put("RecordID", recordId);
+        npc.put("ProjectID", localProjectId);
+        npc.put("PiOrgCode", piOrgCode);
+        npc.put("PfosNumber", pfosNumber);
+        npc.put("PiGlobalID", piGlobalID);
+        if (!resourceList.isEmpty()) {
+            npc.put("ResourceList", resourceList);
+        }
+
+        replyBody.put("type", "notify_project_create");
+        replyBody.put("body", npc);
+
+        long packetRecId = packetEntity.getAmieId();
+        amieClient.replyToPacket(packetRecId, replyBody);
+
+        LOGGER.info("NPC sent for RPC packet_rec_id={}, LocalProjectID={}", 
packetRecId, localProjectId);
+    }
+
+    @Override
+    public String supportsType() {
+        return "request_project_create";
+    }
+
+    private String deriveLocalProjectId(String grantNumber) {
+        // TODO - need to keep a DB mapping between LocalProjectID and 
GrantNumber
+        String gn = (grantNumber == null || grantNumber.isBlank()) ? "UNKNOWN" 
: grantNumber.trim();
+        return "PRJ-" + gn;
+    }
+}

Reply via email to