From d60fd197058e9e7f9b7bf6629eb767c7fee11202 Mon Sep 17 00:00:00 2001 From: lleplat Date: Wed, 11 Feb 2026 15:11:03 +0000 Subject: [PATCH 1/3] Allow to specify search depth --- .../javadocviewer/app/JavadocViewerApp.java | 6 +++-- .../ui/javadocviewer/core/JavadocsFinder.java | 27 +++++++++---------- .../gui/viewer/JavadocViewer.java | 13 ++++----- .../gui/viewer/JavadocViewerCommand.java | 19 +++++++------ 4 files changed, 35 insertions(+), 30 deletions(-) diff --git a/javadocviewer-app/src/main/java/qupath/ui/javadocviewer/app/JavadocViewerApp.java b/javadocviewer-app/src/main/java/qupath/ui/javadocviewer/app/JavadocViewerApp.java index cc9068d..1bbad83 100644 --- a/javadocviewer-app/src/main/java/qupath/ui/javadocviewer/app/JavadocViewerApp.java +++ b/javadocviewer-app/src/main/java/qupath/ui/javadocviewer/app/JavadocViewerApp.java @@ -39,12 +39,14 @@ public void start(Stage stage) throws IOException { try { return new URI(param); } catch (URISyntaxException e) { - logger.warn(String.format("Couldn't convert URI %s", param), e); + logger.warn("Couldn't convert URI {}", param, e); + return null; } }) .filter(Objects::nonNull) - .toArray(URI[]::new) + .toList(), + 7 ); Scene scene = new Scene(javadocViewer); diff --git a/javadocviewer/src/main/java/qupath/ui/javadocviewer/core/JavadocsFinder.java b/javadocviewer/src/main/java/qupath/ui/javadocviewer/core/JavadocsFinder.java index 90ab51a..c3e1ff7 100644 --- a/javadocviewer/src/main/java/qupath/ui/javadocviewer/core/JavadocsFinder.java +++ b/javadocviewer/src/main/java/qupath/ui/javadocviewer/core/JavadocsFinder.java @@ -11,7 +11,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -28,7 +27,6 @@ public class JavadocsFinder { private static final Logger logger = LoggerFactory.getLogger(JavadocsFinder.class); private static final String JAVADOC_INDEX_FILE = "index.html"; private static final List ARCHIVE_EXTENSIONS = List.of(".jar", ".zip"); - private static final int SEARCH_DEPTH = 4; private JavadocsFinder() { throw new AssertionError("This class is not instantiable."); @@ -37,13 +35,14 @@ private JavadocsFinder() { /** * Asynchronously search for Javadocs in the specified URIs. * - * @param urisToSearch URIs to search for Javadocs. It can be a directory, an HTTP link, - * a link to a jar file... + * @param urisToSearch URIs to search for Javadocs. It can be a directory, an HTTP link, a link to a jar file... + * @param searchDepth if one of the provided URI points to a local directory, indicate how deep to search for Javadocs + * inside that directory * @return a CompletableFuture with the list of Javadocs found */ - public static CompletableFuture> findJavadocs(URI... urisToSearch) { - return CompletableFuture.supplyAsync(() -> Arrays.stream(urisToSearch) - .map(JavadocsFinder::findJavadocUrisFromUri) + public static CompletableFuture> findJavadocs(List urisToSearch, int searchDepth) { + return CompletableFuture.supplyAsync(() -> urisToSearch.stream() + .map(uri -> findJavadocUrisFromUri(uri, searchDepth)) .flatMap(List::stream) .map(uri -> { try { @@ -63,13 +62,13 @@ public static CompletableFuture> findJavadocs(URI... urisToSearch) ); } - private static List findJavadocUrisFromUri(URI uri) { + private static List findJavadocUrisFromUri(URI uri, int searchDepth) { if (UriUtils.doesUriLinkToWebsite(uri)) { logger.debug("URI {} retrieved", uri); return List.of(uri); } else { try { - return findJavadocUrisFromPath(Paths.get(uri)); + return findJavadocUrisFromPath(Paths.get(uri), searchDepth); } catch (Exception e) { logger.debug("Could not convert URI {} to path", uri, e); return List.of(); @@ -77,18 +76,18 @@ private static List findJavadocUrisFromUri(URI uri) { } } - private static List findJavadocUrisFromPath(Path path) { + private static List findJavadocUrisFromPath(Path path, int searchDepth) { if (Files.isDirectory(path)) { - return findJavadocUrisFromDirectory(path); + return findJavadocUrisFromDirectory(path, searchDepth); } else { return findJavadocUrisFromFile(path).map(List::of).orElse(List.of()); } } - private static List findJavadocUrisFromDirectory(Path directory) { - logger.debug("Searching for javadocs in {} directory with depth {}", directory, SEARCH_DEPTH); + private static List findJavadocUrisFromDirectory(Path directory, int searchDepth) { + logger.debug("Searching for javadocs in {} directory with depth {}", directory, searchDepth); - try (Stream walk = Files.walk(directory, JavadocsFinder.SEARCH_DEPTH)) { + try (Stream walk = Files.walk(directory, searchDepth)) { return walk .map(JavadocsFinder::findJavadocUrisFromFile) .flatMap(Optional::stream) diff --git a/javadocviewer/src/main/java/qupath/ui/javadocviewer/gui/viewer/JavadocViewer.java b/javadocviewer/src/main/java/qupath/ui/javadocviewer/gui/viewer/JavadocViewer.java index 4d4e890..30a2099 100644 --- a/javadocviewer/src/main/java/qupath/ui/javadocviewer/gui/viewer/JavadocViewer.java +++ b/javadocviewer/src/main/java/qupath/ui/javadocviewer/gui/viewer/JavadocViewer.java @@ -24,7 +24,6 @@ import java.net.URI; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.util.Optional; @@ -58,11 +57,13 @@ public class JavadocViewer extends BorderPane { * * @param stylesheet a property containing a link to a stylesheet which should * be applied to this viewer. Can be null - * @param urisToSearch URIs to search for Javadocs. See {@link JavadocsFinder#findJavadocs(URI...)} + * @param urisToSearch URIs to search for Javadocs. See {@link JavadocsFinder#findJavadocs(List, int)} + * @param searchDepth if one of the provided URI points to a local directory, indicate how deep to search for Javadocs + * inside that directory * @throws IOException if the window creation fails */ - public JavadocViewer(ReadOnlyStringProperty stylesheet, URI... urisToSearch) throws IOException { - initUI(stylesheet, Arrays.stream(urisToSearch).toList()); + public JavadocViewer(ReadOnlyStringProperty stylesheet, List urisToSearch, int searchDepth) throws IOException { + initUI(stylesheet, urisToSearch, searchDepth); setUpListeners(); } @@ -85,7 +86,7 @@ private void onForwardClicked(ActionEvent ignoredEvent) { offset(1); } - private void initUI(ReadOnlyStringProperty stylesheet, List urisToSearch) throws IOException { + private void initUI(ReadOnlyStringProperty stylesheet, List urisToSearch, int searchDepth) throws IOException { FXMLLoader loader = new FXMLLoader(JavadocViewer.class.getResource("javadoc_viewer.fxml"), resources); loader.setRoot(this); loader.setController(this); @@ -123,7 +124,7 @@ protected void updateItem(URI item, boolean empty) { } webView.getEngine().loadContent(resources.getString("JavadocViewer.findingJavadocs")); - JavadocsFinder.findJavadocs(urisToSearch.toArray(new URI[0])).thenAccept(javadocs -> Platform.runLater(() -> { + JavadocsFinder.findJavadocs(urisToSearch, searchDepth).thenAccept(javadocs -> Platform.runLater(() -> { this.uris.getItems().setAll(javadocs.stream() .map(Javadoc::uri) .sorted(Comparator.comparing(JavadocViewer::getName)) diff --git a/javadocviewer/src/main/java/qupath/ui/javadocviewer/gui/viewer/JavadocViewerCommand.java b/javadocviewer/src/main/java/qupath/ui/javadocviewer/gui/viewer/JavadocViewerCommand.java index ca1f8dc..919f12f 100644 --- a/javadocviewer/src/main/java/qupath/ui/javadocviewer/gui/viewer/JavadocViewerCommand.java +++ b/javadocviewer/src/main/java/qupath/ui/javadocviewer/gui/viewer/JavadocViewerCommand.java @@ -6,7 +6,6 @@ import java.io.IOException; import java.net.URI; -import java.util.Arrays; import java.util.List; import java.util.ResourceBundle; @@ -20,21 +19,25 @@ public class JavadocViewerCommand implements Runnable { private final Stage owner; private final ReadOnlyStringProperty stylesheet; private final List urisToSearch; + private final int searchDepth; private Stage stage; private JavadocViewer javadocViewer; /** - * Create the command. This will not create the viewer until either the command is run or {@link #getJavadocViewer()} is called. + * Create the command. This will not create the viewer until either the command is run or {@link #getJavadocViewer()} + * is called. * * @param owner the stage that should own the viewer window. Can be null - * @param stylesheet a property containing a link to a stylesheet which should - * be applied to the viewer. Can be null - * @param urisToSearch URIs to search for Javadocs. See {@link JavadocViewer#JavadocViewer(ReadOnlyStringProperty, URI...)} + * @param stylesheet a property containing a link to a stylesheet which should be applied to the viewer. Can be null + * @param urisToSearch URIs to search for Javadocs. See {@link JavadocViewer#JavadocViewer(ReadOnlyStringProperty, List, int)} + * @param searchDepth if one of the provided URI points to a local directory, indicate how deep to search for Javadocs + * inside that directory */ - public JavadocViewerCommand(Stage owner, ReadOnlyStringProperty stylesheet, URI... urisToSearch) { + public JavadocViewerCommand(Stage owner, ReadOnlyStringProperty stylesheet, List urisToSearch, int searchDepth) { this.owner = owner; this.stylesheet = stylesheet; - this.urisToSearch = Arrays.stream(urisToSearch).toList(); + this.urisToSearch = List.copyOf(urisToSearch); + this.searchDepth = searchDepth; } /** @@ -46,7 +49,7 @@ public JavadocViewerCommand(Stage owner, ReadOnlyStringProperty stylesheet, URI. public JavadocViewer getJavadocViewer() { if (javadocViewer == null) { try { - javadocViewer = new JavadocViewer(stylesheet, urisToSearch.toArray(new URI[0])); + javadocViewer = new JavadocViewer(stylesheet, urisToSearch, searchDepth); } catch (IOException e) { throw new RuntimeException(e); } From 3247f8e39815d0488abb30422e03edbc0834e2eb Mon Sep 17 00:00:00 2001 From: lleplat Date: Wed, 11 Feb 2026 15:11:38 +0000 Subject: [PATCH 2/3] Decode URI before converting them to string --- .../java/qupath/ui/javadocviewer/UriUtils.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/javadocviewer/src/main/java/qupath/ui/javadocviewer/UriUtils.java b/javadocviewer/src/main/java/qupath/ui/javadocviewer/UriUtils.java index b291ef9..9fecd10 100644 --- a/javadocviewer/src/main/java/qupath/ui/javadocviewer/UriUtils.java +++ b/javadocviewer/src/main/java/qupath/ui/javadocviewer/UriUtils.java @@ -7,9 +7,11 @@ import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; +import java.net.URLDecoder; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.time.Duration; @@ -101,10 +103,14 @@ private static CompletableFuture getContentOfHttpUri(URI uri) { } private static String getContentOfJarUri(URI uri) { - // The provided URI is expected to be like: jar:file:/path/to/some-javadoc.jar!/index.html#someParameters - String jarUri = uri.toString().substring( - uri.toString().indexOf('/'), - uri.toString().lastIndexOf('!') + // The provided URI is expected to be like: jar:file:/path/to/some-javadoc.jar!/index.html#someParameters with some + // HTML encoding for special characters + String jarUri = URLDecoder.decode( + uri.toString().substring( + uri.toString().indexOf('/'), + uri.toString().lastIndexOf('!') + ), + StandardCharsets.UTF_8 ); logger.debug("Opening {} jar file to read the content of {}...", jarUri, uri); From ce51f6f85e32b0ad44140a5a14b8dce68d275559 Mon Sep 17 00:00:00 2001 From: lleplat Date: Wed, 11 Feb 2026 15:11:49 +0000 Subject: [PATCH 3/3] Bump version --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9ad6de2..ecd94f4 100644 --- a/build.gradle +++ b/build.gradle @@ -1 +1 @@ -version = "0.1.3" \ No newline at end of file +version = "0.1.4" \ No newline at end of file