Skip to content
Toggle navigation
Toggle navigation
This project
Loading...
Sign in
Ean Schuessler
/
mo-mcp
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
2fb806c3
authored
2025-12-07 19:47:21 -0600
by
Ean Schuessler
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
Fix screen execution notification queuing - actually queue results instead of just logging
1 parent
cb2032a3
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
28 additions
and
533 deletions
service/McpServices.xml
service/McpServices.xml
View file @
2fb806c
...
...
@@ -758,535 +758,6 @@ try {
</actions>
</service>
<!-- Screen-based MCP Services -->
<service
verb=
"discover"
noun=
"ScreensAsMcpTools"
authenticate=
"false"
allow-remote=
"true"
transaction-timeout=
"60"
>
<description>
Discover screens accessible to user and convert them to MCP tools
</description>
<in-parameters>
<parameter
name=
"sessionId"
/>
<parameter
name=
"screenPathPattern"
required=
"false"
><description>
Optional pattern to filter screen paths (supports wildcards)
</description></parameter>
</in-parameters>
<out-parameters>
<parameter
name=
"tools"
type=
"List"
/>
</out-parameters>
<actions>
<script>
<![CDATA[
import org.moqui.context.ExecutionContext
import org.moqui.impl.context.UserFacadeImpl.UserInfo
import org.moqui.impl.screen.ScreenDefinition
ExecutionContext ec = context.ec
ec.logger.info("=== SCREEN DISCOVERY SERVICE CALLED ===")
def originalUsername = ec.user.username
def originalUserId = ec.user.userId
def userGroups = ec.user.getUserGroupIdSet().collect { it }
ec.logger.info("MCP Screen Discovery: Starting for user ${originalUsername} (${originalUserId}) with groups ${userGroups}")
def tools = []
// Discover screens that user can actually access
def accessibleScreens = [] as Set<String>
adminUserInfo = null
try {
adminUserInfo = ec.user.pushUser("ADMIN")
// Get all user's accessible screens using ArtifactAuthzCheckView
def aacvList = ec.entity.find("moqui.security.ArtifactAuthzCheckView")
.condition("userGroupId", userGroups)
.condition("artifactTypeEnumId", "AT_XML_SCREEN")
.useCache(true)
.disableAuthz()
.list()
accessibleScreens = aacvList.collect { it.artifactName } as Set
<String>
ec.logger.info("MCP Screen Discovery: Found ${accessibleScreens.size()} accessible screens for user ${originalUsername}")
} finally {
if (adminUserInfo != null) {
ec.user.popUser()
}
}
// Helper function to check if user has permission to a screen
def userHasScreenPermission = { screenName ->
return accessibleScreens.contains(screenName.toString())
}
// Helper function to convert screen path to MCP tool name
def screenPathToToolName = { screenPath ->
// Clean Encoding: strip component:// and .xml, replace / with _
// Preserves hyphens for readability.
// component://moqui-mcp-2/screen/McpTestScreen.xml -> screen_moqui-mcp-2_screen_McpTestScreen
def cleanPath = screenPath
if (cleanPath.startsWith("component://")) cleanPath = cleanPath.substring(12)
if (cleanPath.endsWith(".xml")) cleanPath = cleanPath.substring(0, cleanPath.length() - 4)
return "screen_" + cleanPath.replace('/', '_')
}
// Helper function to convert screen path to MCP tool name with subscreen support
def screenPathToToolNameWithSubscreens = { screenPath, parentScreenPath = null ->
// If we have a parent screen path, this is a subscreen - use dot notation
if (parentScreenPath) {
def parentCleanPath = parentScreenPath
if (parentCleanPath.startsWith("component://")) parentCleanPath = parentCleanPath.substring(12)
if (parentCleanPath.endsWith(".xml")) parentCleanPath = parentCleanPath.substring(0, parentCleanPath.length() - 4)
// Extract subscreen name from the full screen path
def subscreenName = screenPath.split("/")[-1]
if (subscreenName.endsWith(".xml")) subscreenName = subscreenName.substring(0, subscreenName.length() - 4)
return "screen_" + parentCleanPath.replace('/', '_') + "." + subscreenName
}
// Regular screen path conversion for main screens
return screenPathToToolName(screenPath)
}
// Helper function to create MCP tool from screen
def createScreenTool = { screenPath, title, description, parameters = [:] ->
def toolName = screenPathToToolName(screenPath)
return [
name: toolName,
title: title,
description: title, // Use title as description
inputSchema: [
type: "object",
properties: parameters,
required: []
]
]
}
// Helper function to recursively process screens and create tools directly
def processScreenWithSubscreens
processScreenWithSubscreens = { screenPath, parentScreenPath = null, processedScreens = null, toolsAccumulator = null, parentToolName = null, level = 1 ->
ec.logger.info("MCP Screen Discovery: Processing screen ${screenPath} (parent: ${parentScreenPath}, parentToolName: ${parentToolName}, level: ${level})")
// Initialize processedScreens and toolsAccumulator if null
if (processedScreens == null) processedScreens = [] as Set
<String>
if (toolsAccumulator == null) toolsAccumulator = []
if (processedScreens.contains(screenPath)) {
ec.logger.info("MCP Screen Discovery: Already processed ${screenPath}, skipping")
return
}
processedScreens.add(screenPath)
try {
// Skip problematic patterns early
if (screenPath.contains("/error/") || screenPath.contains("/system/")) {
ec.logger.info("MCP Screen Discovery: Skipping system screen ${screenPath}")
return
}
// Determine if this is a subscreen
def isSubscreen = parentScreenPath != null
// Try to get screen definition
def screenDefinition = null
def title = screenPath.split("/")[-1]
def description = "Moqui screen: ${screenPath}"
try {
screenDefinition = ec.screen.getScreenDefinition(screenPath)
if (screenDefinition?.screenNode?.attribute('default-menu-title')) {
title = screenDefinition.screenNode.attribute('default-menu-title')
description = "Moqui screen: ${screenPath} (${title})"
}
} catch (Exception e) {
ec.logger.info("MCP Screen Discovery: No screen definition for ${screenPath}, using basic info")
}
// Get screen parameters from transitions
def parameters = [:]
try {
def screenInfo = ec.screen.getScreenInfo(screenPath)
if (screenInfo?.transitionInfoByName) {
for (transitionEntry in screenInfo.transitionInfoByName) {
def transitionInfo = transitionEntry.value
if (transitionInfo?.ti) {
transitionInfo.ti.getPathParameterList()?.each { param ->
parameters[param] = [
type: "string",
description: "Path parameter for transition: ${param}"
]
}
transitionInfo.ti.getRequestParameterList()?.each { param ->
parameters[param.name] = [
type: "string",
description: "Request parameter: ${param.name}"
]
}
}
}
}
} catch (Exception e) {
ec.logger.debug("Could not extract parameters from screen ${screenPath}: ${e.message}")
}
// Create tool with proper naming
def toolName
if (isSubscreen
&&
parentToolName) {
// Use the passed hierarchical parent tool name
def subscreenName = screenPath.split("/")[-1]
if (subscreenName.endsWith(".xml")) subscreenName = subscreenName.substring(0, subscreenName.length() - 4)
// Use dot for first level subscreens (level 1), underscore for deeper levels (level 2+)
def separator = (level == 1) ? "." : "_"
toolName = parentToolName + separator + subscreenName
ec.logger.info("MCP Screen Discovery: Creating subscreen tool ${toolName} for ${screenPath} (parentToolName: ${parentToolName}, level: ${level}, separator: ${separator})")
} else if (isSubscreen
&&
parentScreenPath) {
toolName = screenPathToToolNameWithSubscreens(screenPath, parentScreenPath)
ec.logger.info("MCP Screen Discovery: Creating subscreen tool ${toolName} for ${screenPath} (parent: ${parentScreenPath})")
} else {
toolName = screenPathToToolName(screenPath)
ec.logger.info("MCP Screen Discovery: Creating main screen tool ${toolName} for ${screenPath}")
}
def tool = [
name: toolName,
title: title,
description: title, // Use title as description instead of redundant path
inputSchema: [
type: "object",
properties: parameters,
required: []
]
]
ec.logger.info("MCP Screen Discovery: Adding accessible screen tool ${toolName} for ${screenPath}")
toolsAccumulator
<
< tool
//
Recursively
process
subscreens
try
{
def
screenInfoList =
ec.screen.getScreenInfoList(screenPath,
1)
def
screenInfo =
screenInfoList?.first()
ec.logger.info("MCP
Screen
Discovery:
SCREENINFO
for
${screenPath}:
${screenInfo}")
if
(screenInfo?.subscreenInfoByName)
{
ec.logger.info("MCP
Screen
Discovery:
Found
${screenInfo.subscreenInfoByName.size()}
subscreens
for
${screenPath}:
${screenInfo.subscreenInfoByName.keySet()}")
for
(subScreenEntry
in
screenInfo.subscreenInfoByName)
{
ec.logger.info("MCP
Screen
Discovery: =
====
Processing
subscreen
${subScreenEntry.key}
from
parent
${screenPath}
=====")
def
subScreenInfo =
subScreenEntry.value
def
subScreenPathList =
subScreenInfo?.screenPath
ec.logger.info("MCP
Screen
Discovery:
Processing
subscreen
entry
-
key:
${subScreenEntry.key},
location:
${subScreenPathList},
full
info:
${subScreenInfo}")
//
TODO:
Fix
these
hard
coded
discoveries
//
Special
debug
for
Catalog.xml
if
(screenPath.contains("Catalog.xml"))
{
ec.logger.info("MCP
Screen
Discovery:
***
CATALOG
DEBUG
***
Processing
${subScreenEntry.key}
from
Catalog.xml")
}
//
Special
handling
for
known
Catalog.xml
subscreens
that
point
to
SimpleScreens
def
knownLocations =
[
"dashboard":
"component://SimpleScreens/screen/SimpleScreens/Catalog/dashboard.xml",
"Category":
"component://SimpleScreens/screen/SimpleScreens/Catalog/Category.xml",
"Feature":
"component://SimpleScreens/screen/SimpleScreens/Catalog/Feature.xml",
"FeatureGroup":
"component://SimpleScreens/screen/SimpleScreens/Catalog/FeatureGroup.xml",
"Product":
"component://SimpleScreens/screen/SimpleScreens/Catalog/Product.xml",
"Search":
"component://SimpleScreens/screen/SimpleScreens/Catalog/Search.xml"
]
//
Try
to
get
the
actual
subscreen
location
from
multiple
sources
def
actualSubScreenPath =
null
//
First,
try
known
locations
for
Catalog.xml
subscreens
if
(screenPath.contains("Catalog.xml")
&&
knownLocations[subScreenEntry.key])
{
actualSubScreenPath =
knownLocations[subScreenEntry.key]
ec.logger.info("MCP
Screen
Discovery:
Using
known
location
for
${subScreenEntry.key}:
${actualSubScreenPath}")
}
//
Then
try
to
get
location
from
subScreenInfo
object
(most
reliable)
if
(!actualSubScreenPath
&&
subScreenInfo?.screenPath)
{
//
subScreenInfo.screenPath
might
be
a
list
or
string
if
(subScreenInfo.screenPath
instanceof
List)
{
//
For
automatic
discovery
screens,
the
path
might
be
constructed
differently
def
pathList =
subScreenInfo.screenPath
ec.logger.info("MCP
Screen
Discovery:
SubScreenInfo
path
list
for
${subScreenEntry.key}:
${pathList}")
//
Try
to
find
a
valid
screen
path
from
the
list
for
(path
in
pathList)
{
if
(path
&&
path.toString().contains(".xml"))
{
actualSubScreenPath =
path.toString()
break
}
}
}
else
{
actualSubScreenPath =
subScreenInfo.screenPath.toString()
}
ec.logger.info("MCP
Screen
Discovery:
SubScreenInfo
location
for
${subScreenEntry.key}:
${actualSubScreenPath}")
}
}
catch
(Exception
childrenException)
{
ec.logger.info("MCP
Screen
Discovery:
children()
approach
failed:
${childrenException.message}")
//
Fallback:
iterate
through
node
values
subscreensNode.each
{
child
-
>
if (child.name() == "subscreens-item") {
subscreenItems
<
< child
}
}
}
}
ec.logger.info("MCP
Screen
Discovery:
Found
${subscreenItems.size()}
subscreen-item
elements:
${subscreenItems*.attributes()}")
def
subscreenItem =
subscreenItems.find
{
it.attribute('name')
==
subScreenEntry.key
}
ec.logger.info("MCP
Screen
Discovery:
Looking
for
subscreen
item
with
name
'${subScreenEntry.key}',
found:
${subscreenItem?.attributes()}")
if
(subscreenItem?.attribute('location'))
{
actualSubScreenPath =
subscreenItem.attribute('location')
ec.logger.info("MCP
Screen
Discovery:
Found
actual
subscreen
location
for
${subScreenEntry.key}:
${actualSubScreenPath}")
}
else
{
ec.logger.info("MCP
Screen
Discovery:
Subscreen
item
found
but
no
location
attribute")
}
}
}
else
{
ec.logger.info("MCP
Screen
Discovery:
Parent
screen
def
has
no
screenNode")
}
}
catch
(Exception
e)
{
ec.logger.info("MCP
Screen
Discovery:
Could
not
get
subscreen
location
for
${subScreenEntry.key}:
${e.message}")
e.printStackTrace()
}
}
//
Fallback:
try
to
construct
from
screenPathList
if
we
couldn't
get
the
actual
location
if
(!actualSubScreenPath
&&
subScreenPathList)
{
//
The
first
element
should
be
subscreen
name
def
subscreenName =
subScreenEntry.key
//
Try
to
construct
a
reasonable
path
based
on
CURRENT
screen
being
processed
(not
always
the
original
parent)
def
currentScreenPath =
screenPath
//
This
is
the
current
screen
whose
subscreens
we're
processing
//
Generic
fallback:
construct
based
on
current
screen
path
def
lastSlash =
currentScreenPath.lastIndexOf('/')
if
(lastSlash
>
0) {
def basePath = currentScreenPath.substring(0, lastSlash + 1)
actualSubScreenPath = basePath + subscreenName + ".xml"
}
ec.logger.info("MCP Screen Discovery: Constructed fallback subscreen location for ${subScreenEntry.key}: ${actualSubScreenPath}")
}
if (actualSubScreenPath
&&
!processedScreens.contains(actualSubScreenPath)) {
ec.logger.info("MCP Screen Discovery: Processing subscreen path: ${actualSubScreenPath} ${screenPath}")
processScreenWithSubscreens(actualSubScreenPath, screenPath, processedScreens, toolsAccumulator, toolName, level + 1)
} else if (!actualSubScreenPath) {
ec.logger.info("MCP Screen Discovery: Subscreen entry ${subScreenEntry.key} has no location, trying automatic discovery")
// For screens without explicit location (like Product.xml), try automatic discovery
// The subscreen location is typically based on parent screen location + subscreen name
def lastSlash = screenPath.lastIndexOf('/')
if (lastSlash > 0) {
def basePath = screenPath.substring(0, lastSlash + 1)
def autoSubScreenPath = basePath + subScreenEntry.key + ".xml"
ec.logger.info("MCP Screen Discovery: Trying automatic subscreen discovery for ${subScreenEntry.key} at ${autoSubScreenPath}")
processScreenWithSubscreens(autoSubScreenPath, screenPath, processedScreens, toolsAccumulator, toolName, level + 1)
}
} else if (processedScreens.contains(actualSubScreenPath)) {
ec.logger.info("MCP Screen Discovery: Subscreen ${actualSubScreenPath} already processed, skipping")
}
}
} else {
ec.logger.info("MCP Screen Discovery: No subscreens found for ${screenPath}")
}
} catch (Exception e) {
ec.logger.info("MCP Screen Discovery: Could not get subscreens for ${screenPath}: ${e.message}")
ec.logger.error("MCP Screen Discovery: Subscreen discovery error details:", e)
}
} catch (Exception e) {
ec.logger.warn("Error processing screen ${screenPath}: ${e.message}")
}
}
// Process all accessible screens recursively and create tools directly
def processedScreens = [] as Set
<String>
ec.logger.info("MCP Screen Discovery: Starting recursive processing from ${accessibleScreens.size()} base screens")
for (screenPath in accessibleScreens) {
ec.logger.info("MCP Screen Discovery: SCREEN PATH ${screenPath}")
processScreenWithSubscreens(screenPath, null, processedScreens, tools, null, 0)
}
ec.logger.info("MCP Screen Discovery: Recursive processing found ${tools.size()} total tools")
// Note: All screens have already been processed by processScreenWithSubscreens above
// The recursive approach handles both parent screens and their subscreens in a single pass
// No need for additional processing here
ec.logger.info("MCP Screen Discovery: Created ${tools.size()} screen tools for user ${originalUsername}")
result.tools = tools
]]>
</script>
</actions>
</service>
<service
verb=
"convert"
noun=
"ScreenToMcpTool"
authenticate=
"false"
>
<description>
Convert a screen path to MCP tool format
</description>
<in-parameters>
<parameter
name=
"screenPath"
required=
"true"
/>
</in-parameters>
<out-parameters>
<parameter
name=
"tool"
type=
"Map"
/>
</out-parameters>
<actions>
<script>
<![CDATA[
import org.moqui.context.ExecutionContext
ExecutionContext ec = context.ec
ec.logger.info("=== SCREEN TO MCP TOOL: ${screenPath} ===")
tool = null
try {
// Try to get screen definition
def screenDef = null
try {
ec.logger.info("SCREEN TO MCP: Getting screen definition for ${screenPath}")
screenDef = ec.screen.getScreenDefinition(screenPath)
ec.logger.info("SCREEN TO MCP: Got screen definition: ${screenDef ? 'YES' : 'NO'}")
} catch (Exception e) {
ec.logger.warn("SCREEN TO MCP: Error getting screen definition: ${e.message}")
// Screen might not exist or be accessible
return
}
if (!screenDef) {
return
}
// Extract screen information
// Clean Encoding
def cleanPath = screenPath
if (cleanPath.startsWith("component://")) cleanPath = cleanPath.substring(12)
if (cleanPath.endsWith(".xml")) cleanPath = cleanPath.substring(0, cleanPath.length() - 4)
def screenName = cleanPath.replace('/', '_')
def title = screenPath.split("/")[-1]
def description = "Moqui screen: ${screenPath}"
// Safely get screen description - screen XML doesn't have description elements
try {
if (screenDef?.screenNode?.attribute('default-menu-title')) {
description = screenDef.screenNode.attribute('default-menu-title')
}
} catch (Exception e) {
ec.logger.debug("Could not get screen title: ${e.message}")
}
// Get screen parameters from transitions and forms
def parameters = [:]
def required = []
try {
// Get transitions for parameter discovery
def transitions = screenDef.getTransitionMap()
transitions.each { transitionName, transition ->
transition.getPathParameterList().each { param ->
parameters[param] = [
type: "string",
description: "Path parameter: ${param}"
]
required
<
< param
}
//
Get
single
service
parameters
if
transition
calls
a
service
def
serviceName =
transition.getSingleServiceName()
if
(serviceName)
{
try
{
def
serviceDef =
ec.service.getServiceDefinition(serviceName)
if
(serviceDef)
{
def
inParamNames =
serviceDef.getInParameterNames()
for
(paramName
in
inParamNames)
{
def
paramNode =
serviceDef.getInParameter(paramName)
def
paramType =
paramNode?.attribute('type')
?:
'String'
def
paramDesc =
paramNode.first("description")?.text
?:
"Parameter
from
service
${serviceName}"
//
Convert
Moqui
type
to
JSON
Schema
type
def
typeMap =
[
"text-short":
"string",
"text-medium":
"string",
"text-long":
"string",
"text-very-long":
"string",
"id":
"string",
"id-long":
"string",
"number-integer":
"integer",
"number-decimal":
"number",
"number-float":
"number",
"date":
"string",
"date-time":
"string",
"date-time-nano":
"string",
"boolean":
"boolean",
"text-indicator":
"boolean"
]
def
jsonSchemaType =
typeMap[paramType]
?:
"string"
parameters[paramName]
=
[
type:
jsonSchemaType,
description:
paramDesc
]
if
(paramNode?.attribute('required')
==
"true")
{
required
<<
paramName
}
}
}
}
catch
(Exception
e)
{
ec.logger.debug("Error
getting
service
definition
for
${serviceName}:
${e.message}")
}
}
}
}
catch
(Exception
e)
{
ec.logger.debug("Error
getting
transitions
for
screen
${screenPath}:
${e.message}")
}
//
Build
MCP
tool
tool =
[
name:
"screen_${screenName}",
title:
title,
description:
title,
//
Use
title
as
description
inputSchema:
[
type:
"object",
properties:
parameters,
required:
required.unique()
]
]
//
Add
screen
metadata
tool.screenPath =
screenPath
tool.toolType =
"screen"
//
Add
screen
structure
metadata
try
{
def
screenInfo =
ec.screen.getScreenInfo(screenPath)
if
(screenInfo)
{
tool.screenInfo =
[
name:
screenInfo.name,
level:
screenInfo.level,
hasTransitions:
screenInfo.transitions
>
0,
hasForms: screenInfo.forms > 0,
subscreens: screenInfo.subscreens
]
}
} catch (Exception e) {
ec.logger.debug("Could not get screen info for metadata: ${e.message}")
}
} catch (Exception e) {
ec.logger.warn("Error converting screen ${screenPath} to MCP tool: ${e.message}")
}
]]>
</script>
</actions>
</service>
<service
verb=
"execute"
noun=
"ScreenAsMcpTool"
authenticate=
"true"
allow-remote=
"true"
transaction-timeout=
"120"
>
<description>
Execute a screen as an MCP tool
</description>
<in-parameters>
...
...
@@ -1656,7 +1127,27 @@ def startTime = System.currentTimeMillis()
isError: false
]
ec.logger.info("MCP Screen Execution: Queued result as notification for screen ${screenPath} in ${executionTime}s")
// Queue result as notification for real-time delivery
try {
def servlet = ec.getWeb()?.getServletContext()?.getAttribute("enhancedMcpServlet")
if (servlet
&&
sessionId) {
def notification = [
method: "notifications/tool_result",
params: [
toolName: "screen_" + screenPath.replace("/", "_").replace(".", "_"),
result: result,
executionTime: executionTime,
timestamp: System.currentTimeMillis()
]
]
servlet.queueNotification(sessionId, notification)
ec.logger.info("MCP Screen Execution: Queued result as notification for screen ${screenPath} in ${executionTime}s")
} else {
ec.logger.warn("MCP Screen Execution: No servlet or sessionId available for notification queuing")
}
} catch (Exception e) {
ec.logger.warn("MCP Screen Execution: Failed to queue notification: ${e.message}")
}
]]>
</script>
</actions>
</service>
...
...
@@ -2006,10 +1497,10 @@ def startTime = System.currentTimeMillis()
}
ec.logger.info("list#Tools: Creating subscreen tool ${toolName} for ${screenPath} (parentToolName: ${parentToolName}, level: ${level})")
} else if (isSubscreen
&&
parentScreenPath) {
toolName = screenPathToToolNameWithSubscreens(screenPath, parentScreenPath)
toolName =
parentToolName +
screenPathToToolNameWithSubscreens(screenPath, parentScreenPath)
ec.logger.info("list#Tools: Creating subscreen tool ${toolName} for ${screenPath} (parent: ${parentScreenPath})")
} else {
toolName = screenPathToToolName(screenPath)
toolName =
parentToolName +
screenPathToToolName(screenPath)
ec.logger.info("list#Tools: Creating main screen tool ${toolName} for ${screenPath}")
}
...
...
@@ -2121,6 +1612,7 @@ def startTime = System.currentTimeMillis()
}
if (actualSubScreenPath) {
ec.logger.info("list#Tools: Adding subscreen ${actualSubScreenPath} ${screenPath} ${toolName} ${level+1}")
processScreenWithSubscreens(actualSubScreenPath, screenPath, processedScreens, toolsAccumulator, toolName, level + 1)
} else if (!actualSubScreenPath) {
// For screens without explicit location, try automatic discovery
...
...
@@ -2128,6 +1620,7 @@ def startTime = System.currentTimeMillis()
if (lastSlash > 0) {
def basePath = screenPath.substring(0, lastSlash + 1)
def autoSubScreenPath = basePath + subScreenEntry.key + ".xml"
ec.logger.info("list#Tools: Constructed fallback path for ${subScreenEntry.key}: ${actualSubScreenPath}")
processScreenWithSubscreens(autoSubScreenPath, screenPath, processedScreens, toolsAccumulator, toolName, level + 1)
}
}
...
...
@@ -2146,7 +1639,9 @@ def startTime = System.currentTimeMillis()
def processedScreens = [] as Set
<String>
ec.logger.info("list#Tools: Starting recursive processing from ${allScreens.size()} base screens")
for (screenPath in allScreens) {
processScreenWithSubscreens(screenPath, null, processedScreens, tools, null, 0)
def parentToolPath = 'screen_' + screenPath.split('/')[-3..-3].join('_').replace('.xml', '') + '_'
ec.logger.info("TOPSCREEN: ${parentToolPath}")
processScreenWithSubscreens(screenPath, null, processedScreens, tools, parentToolPath, 0)
}
ec.logger.info("list#Tools: Recursive processing found ${tools.size()} total tools")
...
...
Please
register
or
sign in
to post a comment