Experiment with new CachedResource framework
This commit is contained in:
parent
c5c8525b49
commit
95ce706e2e
|
@ -1,22 +1,23 @@
|
||||||
package net.filebot;
|
package net.filebot;
|
||||||
|
|
||||||
import static java.awt.GraphicsEnvironment.*;
|
import static java.awt.GraphicsEnvironment.*;
|
||||||
|
import static java.util.stream.Collectors.*;
|
||||||
import static javax.swing.JOptionPane.*;
|
import static javax.swing.JOptionPane.*;
|
||||||
import static net.filebot.Logging.*;
|
import static net.filebot.Logging.*;
|
||||||
import static net.filebot.Settings.*;
|
import static net.filebot.Settings.*;
|
||||||
import static net.filebot.util.FileUtilities.*;
|
import static net.filebot.util.FileUtilities.*;
|
||||||
|
import static net.filebot.util.XPathUtilities.*;
|
||||||
import static net.filebot.util.ui.SwingUI.*;
|
import static net.filebot.util.ui.SwingUI.*;
|
||||||
|
|
||||||
import java.awt.Desktop;
|
import java.awt.Desktop;
|
||||||
import java.awt.Dialog.ModalityType;
|
import java.awt.Dialog.ModalityType;
|
||||||
import java.awt.event.ActionEvent;
|
|
||||||
import java.awt.event.WindowAdapter;
|
import java.awt.event.WindowAdapter;
|
||||||
import java.awt.event.WindowEvent;
|
import java.awt.event.WindowEvent;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.nio.ByteBuffer;
|
import java.net.URL;
|
||||||
import java.nio.channels.Channels;
|
import java.nio.channels.Channels;
|
||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
import java.nio.file.StandardOpenOption;
|
import java.nio.file.StandardOpenOption;
|
||||||
|
@ -26,14 +27,11 @@ import java.security.PermissionCollection;
|
||||||
import java.security.Permissions;
|
import java.security.Permissions;
|
||||||
import java.security.Policy;
|
import java.security.Policy;
|
||||||
import java.security.ProtectionDomain;
|
import java.security.ProtectionDomain;
|
||||||
import java.util.Locale;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import javax.swing.AbstractAction;
|
|
||||||
import javax.swing.JButton;
|
|
||||||
import javax.swing.JDialog;
|
import javax.swing.JDialog;
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
|
@ -41,7 +39,6 @@ import javax.swing.JOptionPane;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
|
||||||
|
|
||||||
import net.filebot.cli.ArgumentBean;
|
import net.filebot.cli.ArgumentBean;
|
||||||
import net.filebot.cli.ArgumentProcessor;
|
import net.filebot.cli.ArgumentProcessor;
|
||||||
|
@ -54,14 +51,12 @@ import net.filebot.ui.MainFrame;
|
||||||
import net.filebot.ui.PanelBuilder;
|
import net.filebot.ui.PanelBuilder;
|
||||||
import net.filebot.ui.SinglePanelFrame;
|
import net.filebot.ui.SinglePanelFrame;
|
||||||
import net.filebot.ui.transfer.FileTransferable;
|
import net.filebot.ui.transfer.FileTransferable;
|
||||||
import net.filebot.util.ByteBufferInputStream;
|
|
||||||
import net.filebot.util.PreferencesMap.PreferencesEntry;
|
import net.filebot.util.PreferencesMap.PreferencesEntry;
|
||||||
import net.filebot.util.TeePrintStream;
|
import net.filebot.util.TeePrintStream;
|
||||||
import net.filebot.web.CachedResource;
|
|
||||||
import net.miginfocom.swing.MigLayout;
|
import net.miginfocom.swing.MigLayout;
|
||||||
|
|
||||||
import org.kohsuke.args4j.CmdLineException;
|
import org.kohsuke.args4j.CmdLineException;
|
||||||
import org.w3c.dom.NodeList;
|
import org.w3c.dom.Document;
|
||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
|
|
||||||
|
@ -276,74 +271,41 @@ public class Main {
|
||||||
* Show update notifications if updates are available
|
* Show update notifications if updates are available
|
||||||
*/
|
*/
|
||||||
private static void checkUpdate() throws Exception {
|
private static void checkUpdate() throws Exception {
|
||||||
final Properties updateProperties = new CachedResource<Properties>(getApplicationProperty("update.url"), Properties.class, CachedResource.ONE_WEEK, 0, 0) {
|
Cache cache = Cache.getCache(getApplicationName(), CacheType.Persistent);
|
||||||
|
Document dom = cache.xml("update.url", s -> new URL(getApplicationProperty(s)), Cache.ONE_WEEK).get();
|
||||||
|
|
||||||
@Override
|
// parse update xml
|
||||||
public Properties process(ByteBuffer data) {
|
final Map<String, String> update = streamChildren(dom.getFirstChild()).collect(toMap(n -> n.getNodeName(), n -> n.getTextContent().trim()));
|
||||||
try {
|
|
||||||
Properties properties = new Properties();
|
|
||||||
NodeList fields = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new ByteBufferInputStream(data)).getFirstChild().getChildNodes();
|
|
||||||
for (int i = 0; i < fields.getLength(); i++) {
|
|
||||||
properties.setProperty(fields.item(i).getNodeName(), fields.item(i).getTextContent().trim());
|
|
||||||
}
|
|
||||||
return properties;
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.get();
|
|
||||||
|
|
||||||
// check if update is required
|
// check if update is required
|
||||||
int latestRev = Integer.parseInt(updateProperties.getProperty("revision"));
|
int latestRev = Integer.parseInt(update.get("revision"));
|
||||||
int currentRev = getApplicationRevisionNumber();
|
int currentRev = getApplicationRevisionNumber();
|
||||||
|
|
||||||
if (latestRev > currentRev && currentRev > 0) {
|
if (latestRev > currentRev && currentRev > 0) {
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
final JDialog dialog = new JDialog(JFrame.getFrames()[0], update.get("title"), ModalityType.APPLICATION_MODAL);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
final JDialog dialog = new JDialog(JFrame.getFrames()[0], updateProperties.getProperty("title"), ModalityType.APPLICATION_MODAL);
|
|
||||||
final JPanel pane = new JPanel(new MigLayout("fill, nogrid, insets dialog"));
|
final JPanel pane = new JPanel(new MigLayout("fill, nogrid, insets dialog"));
|
||||||
dialog.setContentPane(pane);
|
dialog.setContentPane(pane);
|
||||||
|
|
||||||
pane.add(new JLabel(ResourceManager.getIcon("window.icon.medium")), "aligny top");
|
pane.add(new JLabel(ResourceManager.getIcon("window.icon.medium")), "aligny top");
|
||||||
pane.add(new JLabel(updateProperties.getProperty("message")), "gap 10, wrap paragraph:push");
|
pane.add(new JLabel(update.get("message")), "gap 10, wrap paragraph:push");
|
||||||
pane.add(new JButton(new AbstractAction("Download", ResourceManager.getIcon("dialog.continue")) {
|
|
||||||
|
|
||||||
@Override
|
pane.add(newButton("Download", ResourceManager.getIcon("dialog.continue"), evt -> {
|
||||||
public void actionPerformed(ActionEvent evt) {
|
openURI(update.get("download"));
|
||||||
try {
|
|
||||||
Desktop.getDesktop().browse(URI.create(updateProperties.getProperty("download")));
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
} finally {
|
|
||||||
dialog.setVisible(false);
|
dialog.setVisible(false);
|
||||||
}
|
|
||||||
}
|
|
||||||
}), "tag ok");
|
}), "tag ok");
|
||||||
pane.add(new JButton(new AbstractAction("Details", ResourceManager.getIcon("action.report")) {
|
|
||||||
|
|
||||||
@Override
|
pane.add(newButton("Details", ResourceManager.getIcon("action.report"), evt -> {
|
||||||
public void actionPerformed(ActionEvent evt) {
|
openURI(update.get("discussion"));
|
||||||
try {
|
|
||||||
Desktop.getDesktop().browse(URI.create(updateProperties.getProperty("discussion")));
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}), "tag help2");
|
}), "tag help2");
|
||||||
pane.add(new JButton(new AbstractAction("Ignore", ResourceManager.getIcon("dialog.cancel")) {
|
|
||||||
|
|
||||||
@Override
|
pane.add(newButton("Ignore", ResourceManager.getIcon("dialog.cancel"), evt -> {
|
||||||
public void actionPerformed(ActionEvent evt) {
|
|
||||||
dialog.setVisible(false);
|
dialog.setVisible(false);
|
||||||
}
|
|
||||||
}), "tag cancel");
|
}), "tag cancel");
|
||||||
|
|
||||||
dialog.pack();
|
dialog.pack();
|
||||||
dialog.setLocation(getOffsetLocation(dialog.getOwner()));
|
dialog.setLocation(getOffsetLocation(dialog.getOwner()));
|
||||||
dialog.setVisible(true);
|
dialog.setVisible(true);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -357,9 +319,8 @@ public class Main {
|
||||||
started.setValue("1");
|
started.setValue("1");
|
||||||
started.flush();
|
started.flush();
|
||||||
|
|
||||||
SwingUtilities.invokeLater(() -> {
|
// open Getting Started
|
||||||
GettingStartedStage.start();
|
SwingUtilities.invokeLater(() -> GettingStartedStage.start());
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,18 +332,14 @@ public class Main {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String message = String.format(Locale.ROOT, "<html><p style='font-size:16pt; font-weight:bold'>Thank you for using FileBot!</p><br><p>It has taken many nights to develop this application. If you enjoy using it,<br>please consider a donation to me and my work. It will help to<br>make FileBot even better!<p><p style='font-size:14pt; font-weight:bold'>You've renamed %,d files.</p><br><html>", HistorySpooler.getInstance().getPersistentHistoryTotalSize());
|
String message = String.format("<html><p style='font-size:16pt; font-weight:bold'>Thank you for using FileBot!</p><br><p>It has taken many nights to develop this application. If you enjoy using it,<br>please consider a donation to me and my work. It will help to<br>make FileBot even better!<p><p style='font-size:14pt; font-weight:bold'>You've renamed %,d files.</p><br><html>", HistorySpooler.getInstance().getPersistentHistoryTotalSize());
|
||||||
String[] actions = new String[] { "Donate! :)", donationRev > 0 ? "Not this time" : "Later" };
|
String[] actions = { "Donate! :)", donationRev > 0 ? "Not this time" : "Later" };
|
||||||
JOptionPane pane = new JOptionPane(message, INFORMATION_MESSAGE, YES_NO_OPTION, ResourceManager.getIcon("message.donate"), actions, actions[0]);
|
JOptionPane pane = new JOptionPane(message, INFORMATION_MESSAGE, YES_NO_OPTION, ResourceManager.getIcon("message.donate"), actions, actions[0]);
|
||||||
pane.createDialog(null, "Please Donate").setVisible(true);
|
pane.createDialog(null, "Please Donate").setVisible(true);
|
||||||
|
|
||||||
if (pane.getValue() == actions[0]) {
|
if (pane.getValue() == actions[0]) {
|
||||||
try {
|
openURI(getDonateURL());
|
||||||
Desktop.getDesktop().browse(new URI(getDonateURL()));
|
|
||||||
} catch (Exception e) {
|
|
||||||
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, "Failed to browse URI", e);
|
|
||||||
} finally {
|
|
||||||
donation.setValue(String.valueOf(currentRev));
|
donation.setValue(String.valueOf(currentRev));
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (donationRev > 0 && donationRev < currentRev) {
|
if (donationRev > 0 && donationRev < currentRev) {
|
||||||
donation.setValue(String.valueOf(currentRev));
|
donation.setValue(String.valueOf(currentRev));
|
||||||
|
@ -401,17 +358,21 @@ public class Main {
|
||||||
int currentRev = getApplicationRevisionNumber();
|
int currentRev = getApplicationRevisionNumber();
|
||||||
donation.setValue(String.valueOf(currentRev));
|
donation.setValue(String.valueOf(currentRev));
|
||||||
|
|
||||||
String message = String.format(Locale.ROOT, "<html><p style='font-size:16pt; font-weight:bold'>Thank you for using FileBot!</p><br><p>It has taken many nights to develop this application. If you enjoy using it,<br>please consider writing a nice little review on the %s.<p><p style='font-size:14pt; font-weight:bold'>You've renamed %,d files.</p><br><html>", getAppStoreName(), HistorySpooler.getInstance().getPersistentHistoryTotalSize());
|
String message = String.format("<html><p style='font-size:16pt; font-weight:bold'>Thank you for using FileBot!</p><br><p>It has taken many nights to develop this application. If you enjoy using it,<br>please consider writing a nice little review on the %s.<p><p style='font-size:14pt; font-weight:bold'>You've renamed %,d files.</p><br><html>", getAppStoreName(), HistorySpooler.getInstance().getPersistentHistoryTotalSize());
|
||||||
String[] actions = new String[] { "Review! I like FileBot. :)", "Never! Don't bother me again." };
|
String[] actions = { "Review! I like FileBot. :)", "Never! Don't bother me again." };
|
||||||
JOptionPane pane = new JOptionPane(message, INFORMATION_MESSAGE, YES_NO_OPTION, ResourceManager.getIcon("window.icon.large"), actions, actions[0]);
|
JOptionPane pane = new JOptionPane(message, INFORMATION_MESSAGE, YES_NO_OPTION, ResourceManager.getIcon("window.icon.large"), actions, actions[0]);
|
||||||
pane.createDialog(null, "Please rate FileBot").setVisible(true);
|
pane.createDialog(null, "Please rate FileBot").setVisible(true);
|
||||||
if (pane.getValue() == actions[0]) {
|
if (pane.getValue() == actions[0]) {
|
||||||
try {
|
openURI(getAppStoreLink());
|
||||||
Desktop.getDesktop().browse(getAppStoreURI()); // this will naturally only work on Mac or Ubuntu ;)
|
|
||||||
} catch (Exception e) {
|
|
||||||
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, "Failed to browse URI", e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void openURI(String uri) {
|
||||||
|
try {
|
||||||
|
Desktop.getDesktop().browse(URI.create(uri));
|
||||||
|
} catch (Exception e) {
|
||||||
|
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, "Failed to open URI: " + uri, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void restoreWindowBounds(final JFrame window, final Settings settings) {
|
private static void restoreWindowBounds(final JFrame window, final Settings settings) {
|
||||||
|
|
|
@ -5,7 +5,6 @@ import static net.filebot.util.StringUtilities.*;
|
||||||
|
|
||||||
import java.awt.GraphicsEnvironment;
|
import java.awt.GraphicsEnvironment;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.net.URI;
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -198,11 +197,11 @@ public final class Settings {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static URI getAppStoreURI() {
|
public static String getAppStoreLink() {
|
||||||
if (isMacApp())
|
if (isMacApp())
|
||||||
return getApplicationLink("link.mas");
|
return getApplicationProperty("link.mas");
|
||||||
if (isUbuntuApp())
|
if (isUbuntuApp())
|
||||||
return getApplicationLink("link.usc");
|
return getApplicationProperty("link.usc");
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -216,30 +215,27 @@ public final class Settings {
|
||||||
return getApplicationProperty("link.app.help") + '#' + getApplicationDeployment();
|
return getApplicationProperty("link.app.help") + '#' + getApplicationDeployment();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map<String, URI> getHelpURIs() {
|
public static Map<String, String> getHelpURIs() {
|
||||||
Map<String, URI> links = new LinkedHashMap<String, URI>();
|
Map<String, String> links = new LinkedHashMap<String, String>();
|
||||||
links.put("Getting Started", getApplicationLink("link.intro"));
|
|
||||||
links.put("FAQ", getApplicationLink("link.faq"));
|
links.put("Getting Started", getApplicationProperty("link.intro"));
|
||||||
links.put("Forums", getApplicationLink("link.forums"));
|
links.put("FAQ", getApplicationProperty("link.faq"));
|
||||||
|
links.put("Forums", getApplicationProperty("link.forums"));
|
||||||
|
|
||||||
if (isMacSandbox()) {
|
if (isMacSandbox()) {
|
||||||
links.put("Report Bugs", getApplicationLink("link.help.mas"));
|
links.put("Report Bugs", getApplicationProperty("link.help.mas"));
|
||||||
links.put("Request Help", getApplicationLink("link.help.mas"));
|
links.put("Request Help", getApplicationProperty("link.help.mas"));
|
||||||
} else {
|
} else {
|
||||||
links.put("Report Bugs", getApplicationLink("link.bugs"));
|
links.put("Report Bugs", getApplicationProperty("link.bugs"));
|
||||||
links.put("Request Help", getApplicationLink("link.help"));
|
links.put("Request Help", getApplicationProperty("link.help"));
|
||||||
}
|
}
|
||||||
|
|
||||||
links.put("Contact us on Twitter", getApplicationLink("link.twitter"));
|
links.put("Contact us on Twitter", getApplicationProperty("link.twitter"));
|
||||||
links.put("Contact us on Facebook", getApplicationLink("link.facebook"));
|
links.put("Contact us on Facebook", getApplicationProperty("link.facebook"));
|
||||||
|
|
||||||
return links;
|
return links;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static URI getApplicationLink(String key) {
|
|
||||||
return URI.create(getApplicationProperty(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Settings forPackage(Class<?> type) {
|
public static Settings forPackage(Class<?> type) {
|
||||||
return new Settings(Preferences.userNodeForPackage(type));
|
return new Settings(Preferences.userNodeForPackage(type));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
package net.filebot.ui;
|
package net.filebot.ui;
|
||||||
|
|
||||||
|
import static net.filebot.util.ui.SwingUI.*;
|
||||||
|
|
||||||
import java.awt.Desktop;
|
import java.awt.Desktop;
|
||||||
import java.awt.event.ActionEvent;
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.swing.AbstractAction;
|
|
||||||
import javax.swing.Action;
|
import javax.swing.Action;
|
||||||
import javax.swing.JMenu;
|
import javax.swing.JMenu;
|
||||||
import javax.swing.JMenuBar;
|
import javax.swing.JMenuBar;
|
||||||
|
|
||||||
import net.filebot.Main;
|
|
||||||
import net.filebot.Settings;
|
import net.filebot.Settings;
|
||||||
|
|
||||||
public class FileBotMenuBar {
|
public class FileBotMenuBar {
|
||||||
|
@ -19,7 +18,7 @@ public class FileBotMenuBar {
|
||||||
public static JMenuBar createHelp() {
|
public static JMenuBar createHelp() {
|
||||||
JMenu help = new JMenu("Help");
|
JMenu help = new JMenu("Help");
|
||||||
Settings.getHelpURIs().forEach((title, uri) -> {
|
Settings.getHelpURIs().forEach((title, uri) -> {
|
||||||
help.add(createLink(title, uri));
|
help.add(createLink(title, URI.create(uri)));
|
||||||
});
|
});
|
||||||
|
|
||||||
JMenuBar menuBar = new JMenuBar();
|
JMenuBar menuBar = new JMenuBar();
|
||||||
|
@ -28,17 +27,13 @@ public class FileBotMenuBar {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Action createLink(final String title, final URI uri) {
|
private static Action createLink(final String title, final URI uri) {
|
||||||
return new AbstractAction(title) {
|
return newAction(title, null, evt -> {
|
||||||
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent evt) {
|
|
||||||
try {
|
try {
|
||||||
Desktop.getDesktop().browse(uri);
|
Desktop.getDesktop().browse(uri);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Logger.getLogger(Main.class.getName()).log(Level.WARNING, "Failed to browse URI", e);
|
Logger.getLogger(FileBotMenuBar.class.getName()).log(Level.SEVERE, "Failed to open URI: " + uri, e);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@ package net.filebot.util;
|
||||||
import java.util.AbstractList;
|
import java.util.AbstractList;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import javax.xml.namespace.QName;
|
import javax.xml.namespace.QName;
|
||||||
import javax.xml.xpath.XPathConstants;
|
import javax.xml.xpath.XPathConstants;
|
||||||
|
@ -140,11 +142,12 @@ public final class XPathUtilities {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public static Stream<Node> streamChildren(Node parent) {
|
||||||
* Dummy constructor to prevent instantiation.
|
return stream(parent.getChildNodes());
|
||||||
*/
|
}
|
||||||
private XPathUtilities() {
|
|
||||||
throw new UnsupportedOperationException();
|
public static Stream<Node> stream(NodeList nodes) {
|
||||||
|
return IntStream.range(0, nodes.getLength()).mapToObj(nodes::item);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static class NodeListDecorator extends AbstractList<Node> {
|
protected static class NodeListDecorator extends AbstractList<Node> {
|
||||||
|
@ -167,4 +170,8 @@ public final class XPathUtilities {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private XPathUtilities() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue