Skip to content

Commit 8fa0a01

Browse files
authored
Merge pull request #4356 from evolvedbinary/feature/improve-query-dialog
Improve performance of JAC Query Dialog
2 parents 004e30e + e3c834e commit 8fa0a01

File tree

1 file changed

+108
-39
lines changed

1 file changed

+108
-39
lines changed

exist-core/src/main/java/org/exist/client/QueryDialog.java

Lines changed: 108 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,14 @@
5656
import javax.swing.JTextField;
5757
import javax.swing.JToolBar;
5858
import javax.swing.SpinnerNumberModel;
59+
import javax.swing.SwingWorker;
5960
import javax.swing.border.BevelBorder;
61+
import javax.swing.event.PopupMenuEvent;
62+
import javax.swing.event.PopupMenuListener;
6063
import javax.xml.transform.OutputKeys;
6164

6265
import org.exist.security.PermissionDeniedException;
66+
import org.exist.util.Holder;
6367
import org.exist.xmldb.EXistXQueryService;
6468
import org.exist.xmldb.LocalCollection;
6569
import org.exist.xmldb.UserManagementService;
@@ -84,6 +88,11 @@ public class QueryDialog extends JFrame {
8488

8589
private static final long serialVersionUID = 1L;
8690

91+
private static final AtomicInteger QUERY_THREAD_ID = new AtomicInteger();
92+
private static final AtomicInteger GET_COLLECTIONS_THREAD_ID = new AtomicInteger();
93+
94+
private static final String LOADING_INDICATOR = "Loading...";
95+
8796
private InteractiveClient client;
8897
private Collection collection;
8998
private Properties properties;
@@ -334,24 +343,47 @@ private JComponent createQueryBox() {
334343
label = new JLabel(Messages.getString("QueryDialog.contextlabel"));
335344
optionsPanel.add(label);
336345

337-
final List<String> data = new ArrayList<>();
346+
final Holder<Boolean> addedLoadingIndicator = new Holder<>(false);
347+
final List<String> collectionsList = new ArrayList<>();
338348
try {
339-
final Collection root = client.getCollection(XmldbURI.ROOT_COLLECTION);
340-
data.add(collection.getName());
341-
getCollections(root, collection, data);
349+
final String currentCollectionName = collection.getName();
350+
351+
collectionsList.add(currentCollectionName);
352+
353+
collections = new JComboBox<>(new java.util.Vector<>(collectionsList));
354+
355+
collections.addPopupMenuListener(new PopupMenuListener() {
356+
@Override
357+
public void popupMenuWillBecomeVisible(final PopupMenuEvent e) {
358+
if (!addedLoadingIndicator.value) {
359+
collections.addItem(LOADING_INDICATOR);
360+
addedLoadingIndicator.value = true;
361+
362+
final GetCollectionsListSwingWorker getCollectionsListSwingWorker = new GetCollectionsListSwingWorker(currentCollectionName);
363+
getCollectionsListSwingWorker.execute();
364+
}
365+
}
366+
367+
@Override
368+
public void popupMenuWillBecomeInvisible(final PopupMenuEvent e) {
369+
}
370+
371+
@Override
372+
public void popupMenuCanceled(final PopupMenuEvent e) {
373+
}
374+
});
342375
} catch (final XMLDBException e) {
343376
ClientFrame.showErrorMessage(
344377
Messages.getString("QueryDialog.collectionretrievalerrormessage") + ".", e);
345378
}
346-
collections = new JComboBox<>(new java.util.Vector<>(data));
347-
collections.setSelectedIndex(0);
379+
348380
collections.addActionListener(e -> {
349381
final int p = collections.getSelectedIndex();
350382
final String context;
351383
if (p == -1) {
352384
context = "/db";
353385
} else {
354-
context = data.get(p);
386+
context = collectionsList.get(p);
355387
}
356388
try {
357389
collection = client.getCollection(context);
@@ -372,35 +404,6 @@ private JComponent createQueryBox() {
372404
return tabs;
373405
}
374406

375-
private List<String> getCollections(final Collection root, final Collection collection, final List<String> collectionsList) throws XMLDBException {
376-
if (!collection.getName().equals(root.getName())) {
377-
collectionsList.add(root.getName());
378-
}
379-
final String[] childCollections = root.listChildCollections();
380-
Collection child = null;
381-
for (String childCollection : childCollections) {
382-
try {
383-
child = root.getChildCollection(childCollection);
384-
} catch (final XMLDBException xmldbe) {
385-
if (xmldbe.getCause() instanceof PermissionDeniedException) {
386-
continue;
387-
} else {
388-
throw xmldbe;
389-
}
390-
} catch (Exception npe) {
391-
System.out.println("Corrupted resource/collection skipped: " + child != null ? child.getName() != null ? child.getName() : "unknown" : "unknown");
392-
continue;
393-
}
394-
try {
395-
getCollections(child, collection, collectionsList);
396-
} catch (Exception ee) {
397-
System.out.println("Corrupted resource/collection skipped: " + child != null ? child.getName() != null ? child.getName() : "unknown" : "unknown");
398-
continue;
399-
}
400-
}
401-
return collectionsList;
402-
}
403-
404407
private void open() {
405408
final String workDir = properties.getProperty("working-dir", System.getProperty("user.dir"));
406409
final JFileChooser chooser = new JFileChooser();
@@ -470,8 +473,6 @@ private void save(String stringToSave, String fileCategory) {
470473
}
471474
}
472475

473-
private static final AtomicInteger queryThreadId = new AtomicInteger();
474-
475476
private QueryRunnable doQuery() {
476477
final String xpath = query.getText();
477478
if (xpath.length() == 0) {
@@ -480,7 +481,7 @@ private QueryRunnable doQuery() {
480481
resultDisplay.setText("");
481482

482483
final QueryRunnable queryRunnable = new QueryRunnable(xpath);
483-
final Thread queryThread = client.newClientThread("query-" + queryThreadId.getAndIncrement(), queryRunnable);
484+
final Thread queryThread = client.newClientThread("query-" + QUERY_THREAD_ID.getAndIncrement(), queryRunnable);
484485
queryThread.start();
485486
return queryRunnable;
486487
}
@@ -665,4 +666,72 @@ private void addQuery(String query) {
665666
}
666667
history.addElement(Integer.toString(history.getSize() + 1) + ". " + query);
667668
}
669+
670+
private class GetCollectionsListSwingWorker extends SwingWorker<Void, String> {
671+
private final String currentCollectionName;
672+
673+
public GetCollectionsListSwingWorker(final String currentCollectionName) {
674+
this.currentCollectionName = currentCollectionName;
675+
}
676+
677+
@Override
678+
public Void doInBackground() {
679+
try {
680+
final Collection root = client.getCollection(XmldbURI.ROOT_COLLECTION);
681+
getCollections(root, currentCollectionName);
682+
} catch (final XMLDBException e) {
683+
ClientFrame.showErrorMessage(
684+
Messages.getString("QueryDialog.collectionretrievalerrormessage") + ".", e);
685+
}
686+
687+
return null;
688+
}
689+
690+
@Override
691+
protected void process(final List<String> collectionNames) {
692+
final int idxLast = collections.getItemCount() - 1;
693+
final String lastItem = collections.getItemAt(idxLast);
694+
if (LOADING_INDICATOR.equals(lastItem)) {
695+
collections.removeItemAt(idxLast);
696+
}
697+
698+
for (final String collectionName : collectionNames) {
699+
collections.addItem(collectionName);
700+
}
701+
}
702+
703+
private void getCollections(final Collection root, final String currentCollection) throws XMLDBException {
704+
if (isCancelled()) {
705+
return;
706+
}
707+
708+
if (!currentCollection.equals(root.getName())) {
709+
publish(root.getName());
710+
}
711+
712+
final String[] childCollections = root.listChildCollections();
713+
Collection child = null;
714+
for (int i = 0; i < childCollections.length; i++) {
715+
try {
716+
child = root.getChildCollection(childCollections[i]);
717+
} catch (final XMLDBException xmldbe) {
718+
if (xmldbe.getCause() instanceof PermissionDeniedException) {
719+
continue;
720+
} else {
721+
throw xmldbe;
722+
}
723+
} catch (Exception npe) {
724+
System.out.println("Corrupted resource/collection skipped: " + child != null ? child.getName() != null ? child.getName() : "unknown" : "unknown");
725+
continue;
726+
}
727+
728+
try {
729+
getCollections(child, currentCollection);
730+
} catch (Exception ee) {
731+
System.out.println("Corrupted resource/collection skipped: " + child != null ? child.getName() != null ? child.getName() : "unknown" : "unknown");
732+
continue;
733+
}
734+
}
735+
}
736+
}
668737
}

0 commit comments

Comments
 (0)