001/* 002 * Copyright 2025 devteam@scivicslab.com 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, 011 * software distributed under the License is distributed on an 012 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 013 * either express or implied. See the License for the 014 * specific language governing permissions and limitations 015 * under the License. 016 */ 017 018package com.scivicslab.actoriac.report.sections.basic; 019 020import com.scivicslab.actoriac.log.DistributedLogStore; 021import com.scivicslab.pojoactor.core.Action; 022import com.scivicslab.pojoactor.core.ActionResult; 023import com.scivicslab.pojoactor.workflow.IIActorRef; 024import com.scivicslab.pojoactor.workflow.IIActorSystem; 025 026import java.sql.Connection; 027import java.util.logging.Logger; 028 029/** 030 * IIAR wrapper for {@link TransitionHistorySection}. 031 * 032 * <p>Exposes the POJO's methods as actions via {@code @Action} annotations. 033 * Handles database connection and session ID retrieval from the system.</p> 034 * 035 * <h2>Usage in workflow YAML:</h2> 036 * 037 * <p>Basic usage (shows nodeGroup transitions):</p> 038 * <pre>{@code 039 * - actor: loader 040 * method: createChild 041 * arguments: ["reportBuilder", "transitions", "...TransitionHistorySectionIIAR"] 042 * }</pre> 043 * 044 * <p>With target actor specified (using ":" separator):</p> 045 * <pre>{@code 046 * - actor: loader 047 * method: createChild 048 * arguments: ["reportBuilder", "trans:node-server1", "...TransitionHistorySectionIIAR"] 049 * }</pre> 050 * 051 * <p>Include children (add ":children" suffix):</p> 052 * <pre>{@code 053 * - actor: loader 054 * method: createChild 055 * arguments: ["reportBuilder", "trans:nodeGroup:children", "...TransitionHistorySectionIIAR"] 056 * }</pre> 057 * 058 * @author devteam@scivicslab.com 059 * @since 2.16.0 060 */ 061public class TransitionHistorySectionIIAR extends IIActorRef<TransitionHistorySection> { 062 063 private static final Logger logger = Logger.getLogger(TransitionHistorySectionIIAR.class.getName()); 064 065 /** 066 * Constructs the IIAR with a new POJO instance. 067 * 068 * <p>The actor name is parsed to extract target actor and options:</p> 069 * <ul> 070 * <li>"transitions" → target=nodeGroup, includeChildren=false</li> 071 * <li>"trans:node-server1" → target=node-server1, includeChildren=false</li> 072 * <li>"trans:nodeGroup:children" → target=nodeGroup, includeChildren=true</li> 073 * </ul> 074 * 075 * @param actorName the actor name (may encode target actor) 076 * @param system the actor system 077 */ 078 public TransitionHistorySectionIIAR(String actorName, IIActorSystem system) { 079 super(actorName, new TransitionHistorySection(), system); 080 parseActorName(actorName); 081 initializeFromSystem(); 082 } 083 084 /** 085 * Parses the actor name to extract target actor and options. 086 */ 087 private void parseActorName(String actorName) { 088 if (actorName == null) { 089 object.setTargetActorName("nodeGroup"); 090 return; 091 } 092 093 // Format: "prefix:targetActor" or "prefix:targetActor:children" 094 String[] parts = actorName.split(":", 3); 095 if (parts.length >= 2) { 096 object.setTargetActorName(parts[1]); 097 if (parts.length >= 3 && "children".equals(parts[2])) { 098 object.setIncludeChildren(true); 099 } 100 } else { 101 // No ":" - default to nodeGroup 102 object.setTargetActorName("nodeGroup"); 103 } 104 } 105 106 /** 107 * Initializes the POJO with database connection and session ID. 108 */ 109 private void initializeFromSystem() { 110 // Get database connection from DistributedLogStore 111 DistributedLogStore logStore = DistributedLogStore.getInstance(); 112 if (logStore != null) { 113 Connection conn = logStore.getConnection(); 114 if (conn != null) { 115 object.setConnection(conn); 116 logger.fine("TransitionHistorySectionIIAR: initialized database connection"); 117 } 118 } 119 120 // Get session ID from nodeGroup 121 long sessionId = getSessionIdFromNodeGroup(); 122 if (sessionId >= 0) { 123 object.setSessionId(sessionId); 124 logger.fine("TransitionHistorySectionIIAR: initialized sessionId=" + sessionId); 125 } 126 } 127 128 /** 129 * Retrieves session ID from nodeGroup actor. 130 */ 131 private long getSessionIdFromNodeGroup() { 132 if (actorSystem == null || !(actorSystem instanceof IIActorSystem)) { 133 return -1; 134 } 135 IIActorSystem iiSystem = (IIActorSystem) actorSystem; 136 137 IIActorRef<?> nodeGroup = iiSystem.getIIActor("nodeGroup"); 138 if (nodeGroup == null) { 139 return -1; 140 } 141 142 ActionResult result = nodeGroup.callByActionName("getSessionId", ""); 143 if (result.isSuccess()) { 144 try { 145 return Long.parseLong(result.getResult()); 146 } catch (NumberFormatException e) { 147 logger.warning("TransitionHistorySectionIIAR: invalid sessionId: " + result.getResult()); 148 } 149 } 150 return -1; 151 } 152 153 // ======================================================================== 154 // Actions - expose POJO methods 155 // ======================================================================== 156 157 @Action("generate") 158 public ActionResult generate(String args) { 159 String content = object.generate(); 160 return new ActionResult(true, content); 161 } 162 163 @Action("getTitle") 164 public ActionResult getTitle(String args) { 165 String title = object.getTitle(); 166 return new ActionResult(true, title != null ? title : ""); 167 } 168 169 /** 170 * Sets the target actor name dynamically. 171 * 172 * @param args the target actor name 173 * @return action result 174 */ 175 @Action("setTargetActor") 176 public ActionResult setTargetActor(String args) { 177 if (args != null && !args.isEmpty()) { 178 object.setTargetActorName(args.trim()); 179 } 180 return new ActionResult(true, "Target actor set"); 181 } 182 183 /** 184 * Sets whether to include children. 185 * 186 * @param args "true" or "false" 187 * @return action result 188 */ 189 @Action("setIncludeChildren") 190 public ActionResult setIncludeChildren(String args) { 191 boolean include = "true".equalsIgnoreCase(args); 192 object.setIncludeChildren(include); 193 return new ActionResult(true, "Include children: " + include); 194 } 195}