From 71f4063b7240ceef252119d876a0de48e5e8d636 Mon Sep 17 00:00:00 2001 From: Kunal Shroff Date: Thu, 3 Oct 2024 14:57:49 -0400 Subject: [PATCH 1/2] remove system.out calls, make git properties optional --- .../applications/display/navigation/ProcessOPI.java | 11 +++++++++-- pom.xml | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/app/display/navigation/src/main/java/org/phoebus/applications/display/navigation/ProcessOPI.java b/app/display/navigation/src/main/java/org/phoebus/applications/display/navigation/ProcessOPI.java index 468ab53c14..b801145cbd 100644 --- a/app/display/navigation/src/main/java/org/phoebus/applications/display/navigation/ProcessOPI.java +++ b/app/display/navigation/src/main/java/org/phoebus/applications/display/navigation/ProcessOPI.java @@ -52,13 +52,13 @@ public Set process() { }, () -> { throw new UnsupportedOperationException("File extension unknown"); }); - System.out.println("Processing file : " + this.rootFile); + logger.log(Level.INFO, "Processing file : " + this.rootFile); getAllLinkedFiles(this.rootFile); return this.allLinkedFiles; } private synchronized void getAllLinkedFiles(File file) { - System.out.println("Calculating linked files for " + file.getName()); + logger.log(Level.INFO, "Calculating linked files for " + file.getName()); Set linkedFiles = getLinkedFiles(file); linkedFiles.forEach(f -> { if (allLinkedFiles.contains(f) || f.equals(rootFile)) { @@ -71,6 +71,13 @@ private synchronized void getAllLinkedFiles(File file) { }); } + /** + * A Utility method which creates a list of all the files that can be launched from a given OPI. + * It only inlcudes files launched via actions. + * + * @param file root OPI file + * @return a unique Set of all files that can be reached from root OPI file + */ public static synchronized Set getLinkedFiles(File file) { Set result = new HashSet<>(); try { diff --git a/pom.xml b/pom.xml index d20dbc8b94..e0834e2e0c 100644 --- a/pom.xml +++ b/pom.xml @@ -179,6 +179,7 @@ + false ${project.basedir}/.git git false From e1d49377630a501418fe2f0d4908931bd7f3b203 Mon Sep 17 00:00:00 2001 From: Kunal Shroff Date: Thu, 3 Oct 2024 16:57:45 -0400 Subject: [PATCH 2/2] Basic utility functionality for getting embedded screens --- .../display/navigation/ProcessOPI.java | 80 ++++++++++++++++++- .../navigation/ProcessEmbeddedOPITest.java | 39 +++++++++ .../bob/embedded/level_1_embedded.bob | 31 +++++++ .../bob/embedded/level_2_embedded.bob | 19 +++++ .../resources/bob/embedded/root_embedded.bob | 30 +++++++ .../src/test/resources/bob/root_embedded.bob | 31 +++++++ 6 files changed, 229 insertions(+), 1 deletion(-) create mode 100644 app/display/navigation/src/test/java/org/phoebus/applications/display/navigation/ProcessEmbeddedOPITest.java create mode 100644 app/display/navigation/src/test/resources/bob/embedded/level_1_embedded.bob create mode 100644 app/display/navigation/src/test/resources/bob/embedded/level_2_embedded.bob create mode 100644 app/display/navigation/src/test/resources/bob/embedded/root_embedded.bob create mode 100644 app/display/navigation/src/test/resources/bob/root_embedded.bob diff --git a/app/display/navigation/src/main/java/org/phoebus/applications/display/navigation/ProcessOPI.java b/app/display/navigation/src/main/java/org/phoebus/applications/display/navigation/ProcessOPI.java index b801145cbd..65f167f5d4 100644 --- a/app/display/navigation/src/main/java/org/phoebus/applications/display/navigation/ProcessOPI.java +++ b/app/display/navigation/src/main/java/org/phoebus/applications/display/navigation/ProcessOPI.java @@ -5,6 +5,7 @@ import org.csstudio.display.builder.model.WidgetProperty; import org.csstudio.display.builder.model.persist.ModelReader; import org.csstudio.display.builder.model.properties.ActionInfos; +import org.csstudio.display.builder.model.properties.FilenameWidgetProperty; import org.csstudio.display.builder.model.spi.ActionInfo; import org.csstudio.display.builder.model.util.ModelResourceUtil; import org.csstudio.display.actions.OpenDisplayAction; @@ -31,6 +32,9 @@ public class ProcessOPI { private final File rootFile; private final Set allLinkedFiles; + private final Set allEmbeddedFiles; + + /** * @param rootFile Start of the navigation tree @@ -38,6 +42,7 @@ public class ProcessOPI { public ProcessOPI(File rootFile) { this.rootFile = rootFile; this.allLinkedFiles = new HashSet<>(); + this.allEmbeddedFiles = new HashSet<>(); } /** @@ -57,8 +62,9 @@ public Set process() { return this.allLinkedFiles; } - private synchronized void getAllLinkedFiles(File file) { + public synchronized void getAllLinkedFiles(File file) { logger.log(Level.INFO, "Calculating linked files for " + file.getName()); + Set linkedFiles = getLinkedFiles(file); linkedFiles.forEach(f -> { if (allLinkedFiles.contains(f) || f.equals(rootFile)) { @@ -120,6 +126,78 @@ public static synchronized Set getLinkedFiles(File file) { return result; } + + /** + * Gets All the files embedded in the rootFile + * This call should be made on a separate thread since it may take some time to process all the linked files + */ + public Set processEmbedded() { + getExtensionByStringHandling(this.rootFile.getName()).ifPresentOrElse(ext -> { + if (!ext.equalsIgnoreCase("bob") && !ext.equalsIgnoreCase("opi")) { + throw new UnsupportedOperationException("File extension " + ext + " is not supported. The supported extensions are .bob and .opi."); + } + }, () -> { + throw new UnsupportedOperationException("File extension unknown"); + }); + logger.log(Level.INFO, "Processing file : " + this.rootFile); + getAllEmbeddedFiles(this.rootFile); + return this.allEmbeddedFiles; + } + + public synchronized void getAllEmbeddedFiles(File file) { + logger.log(Level.INFO, "Calculating embedded files for " + file.getName()); + + Set embeddedFiles = getEmbeddedFiles(file); + embeddedFiles.forEach(f -> { + if (allEmbeddedFiles.contains(f) || f.equals(rootFile)) { + // Already handled skip it + } else { + // Find all the linked files for this file + allEmbeddedFiles.add(f); + getAllEmbeddedFiles(f); + } + }); + } + + /** + * A Utility method which creates a list of all the embedded files that can be launched from a given OPI. + * + * @param file root OPI file + * @return a unique Set of all embedded files in root OPI file + */ + public static synchronized Set getEmbeddedFiles(File file) { + Set result = new HashSet<>(); + try { + ModelReader reader = new ModelReader(new FileInputStream(file)); + DisplayModel model = reader.readModel(); + List children = model.getChildren(); + + children.forEach(widget -> { + // Find all the action properties + Optional> foundfile = widget.checkProperty("file"); + + foundfile.ifPresent(f -> { + try { + FilenameWidgetProperty wp = (FilenameWidgetProperty) widget.getProperty("file"); +// // For display path, use the combined macros... +// String expanded_path = MacroHandler.replace(widget.getEffectiveMacros(), f.getPath()); +// // .. but fall back to properties +// expanded_path = MacroHandler.replace(widget.getMacrosOrProperties(), expanded_path); + + String resource = ModelResourceUtil.resolveResource(file.getPath(), f.getValue().toString()); + result.add(new File(resource)); + } catch (Exception e) { + logger.log(Level.WARNING, "Failed to resolve macros for : " + f, e); + } + }); + }); + return result; + } catch (Exception e) { + logger.log(Level.WARNING, "Failed to getLinkedFiles for file " + file.getPath(), e); + } + return result; + } + private Optional getExtensionByStringHandling(String filename) { return Optional.ofNullable(filename) .filter(f -> f.contains(".")) diff --git a/app/display/navigation/src/test/java/org/phoebus/applications/display/navigation/ProcessEmbeddedOPITest.java b/app/display/navigation/src/test/java/org/phoebus/applications/display/navigation/ProcessEmbeddedOPITest.java new file mode 100644 index 0000000000..d08a5abe77 --- /dev/null +++ b/app/display/navigation/src/test/java/org/phoebus/applications/display/navigation/ProcessEmbeddedOPITest.java @@ -0,0 +1,39 @@ +package org.phoebus.applications.display.navigation; + + +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.util.HashSet; +import java.util.Set; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * A utility Class for handling the navigation of .bob files + */ +public class ProcessEmbeddedOPITest { + + + @Test + public void testEmbeddedList() + { + // The child_1 and grandchild_1_1 have a cyclic link. The test ensures that the checking for linked files + // does avoid entering an infinite loop + File file = new File(getClass().getClassLoader().getResource("bob/embedded/root_embedded.bob").getFile()); + ProcessOPI processOPI = new ProcessOPI(file); + Set result = processOPI.processEmbedded(); + + result.forEach(System.out::println); + // Expected results + Set expectedFiles = new HashSet<>(); + expectedFiles.add(new File(getClass().getClassLoader().getResource("bob/embedded/level_1_embedded.bob").getFile())); + expectedFiles.add(new File(getClass().getClassLoader().getResource("bob/embedded/level_2_embsedded.bob").getFile())); + + assertThat(result, is(expectedFiles)); + // assertTrue("Failed to find the linked files. expected " + " found " , result.c); + } +} diff --git a/app/display/navigation/src/test/resources/bob/embedded/level_1_embedded.bob b/app/display/navigation/src/test/resources/bob/embedded/level_1_embedded.bob new file mode 100644 index 0000000000..0a30802b64 --- /dev/null +++ b/app/display/navigation/src/test/resources/bob/embedded/level_1_embedded.bob @@ -0,0 +1,31 @@ + + + + level_1_embedded + 400 + 150 + + Label + Level 1 + 400 + 50 + + + + + 1 + 1 + + + Embedded Display + level_2_embedded.bob + 50 + 50 + + + Embedded Display_1 + level_2_embedded.bob + 100 + 50 + + diff --git a/app/display/navigation/src/test/resources/bob/embedded/level_2_embedded.bob b/app/display/navigation/src/test/resources/bob/embedded/level_2_embedded.bob new file mode 100644 index 0000000000..cf9b404e05 --- /dev/null +++ b/app/display/navigation/src/test/resources/bob/embedded/level_2_embedded.bob @@ -0,0 +1,19 @@ + + + + level_2_embedded + 400 + 50 + + Label + Level 2 + 400 + 50 + + + + + 1 + 1 + + diff --git a/app/display/navigation/src/test/resources/bob/embedded/root_embedded.bob b/app/display/navigation/src/test/resources/bob/embedded/root_embedded.bob new file mode 100644 index 0000000000..fae09b1858 --- /dev/null +++ b/app/display/navigation/src/test/resources/bob/embedded/root_embedded.bob @@ -0,0 +1,30 @@ + + + + Display + + Embedded Display + level_1_embedded.bob + 50 + 150 + + + Embedded Display_1 + level_1_embedded.bob + 400 + 50 + 150 + + + Label + ROOT + 190 + 350 + 50 + + + + + 1 + + diff --git a/app/display/navigation/src/test/resources/bob/root_embedded.bob b/app/display/navigation/src/test/resources/bob/root_embedded.bob new file mode 100644 index 0000000000..376c05fdb9 --- /dev/null +++ b/app/display/navigation/src/test/resources/bob/root_embedded.bob @@ -0,0 +1,31 @@ + + + + root_embedded + 300 + + Label + Root + 800 + 50 + + + + + 1 + 1 + + + Embedded Display + embedded/level_1_embedded.bob + 50 + 150 + + + Embedded Display_1 + embedded/level_1_embedded.bob + 400 + 50 + 150 + +