• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

evolvedbinary / elemental / 982

29 Apr 2025 08:34PM UTC coverage: 56.409% (+0.007%) from 56.402%
982

push

circleci

adamretter
[feature] Improve README.md badges

28451 of 55847 branches covered (50.94%)

Branch coverage included in aggregate %.

77468 of 131924 relevant lines covered (58.72%)

0.59 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/exist-core/src/main/java/org/exist/client/IndexDialog.java
1
/*
2
 * Elemental
3
 * Copyright (C) 2024, Evolved Binary Ltd
4
 *
5
 * admin@evolvedbinary.com
6
 * https://www.evolvedbinary.com | https://www.elemental.xyz
7
 *
8
 * Use of this software is governed by the Business Source License 1.1
9
 * included in the LICENSE file and at www.mariadb.com/bsl11.
10
 *
11
 * Change Date: 2028-04-27
12
 *
13
 * On the date above, in accordance with the Business Source License, use
14
 * of this software will be governed by the Apache License, Version 2.0.
15
 *
16
 * Additional Use Grant: Production use of the Licensed Work for a permitted
17
 * purpose. A Permitted Purpose is any purpose other than a Competing Use.
18
 * A Competing Use means making the Software available to others in a commercial
19
 * product or service that: substitutes for the Software; substitutes for any
20
 * other product or service we offer using the Software that exists as of the
21
 * date we make the Software available; or offers the same or substantially
22
 * similar functionality as the Software.
23
 *
24
 * NOTE: Parts of this file contain code from 'The eXist-db Authors'.
25
 *       The original license header is included below.
26
 *
27
 * =====================================================================
28
 *
29
 * eXist-db Open Source Native XML Database
30
 * Copyright (C) 2001 The eXist-db Authors
31
 *
32
 * info@exist-db.org
33
 * http://www.exist-db.org
34
 *
35
 * This library is free software; you can redistribute it and/or
36
 * modify it under the terms of the GNU Lesser General Public
37
 * License as published by the Free Software Foundation; either
38
 * version 2.1 of the License, or (at your option) any later version.
39
 *
40
 * This library is distributed in the hope that it will be useful,
41
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
42
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
43
 * Lesser General Public License for more details.
44
 *
45
 * You should have received a copy of the GNU Lesser General Public
46
 * License along with this library; if not, write to the Free Software
47
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
48
 */
49
package org.exist.client;
50

51
import org.exist.collections.CollectionConfigurationManager;
52
import org.exist.xmldb.IndexQueryService;
53
import org.exist.xmldb.XmldbURI;
54
import org.xmldb.api.base.Collection;
55
import org.xmldb.api.base.XMLDBException;
56

57
import javax.swing.*;
58
import javax.swing.border.TitledBorder;
59
import javax.swing.table.AbstractTableModel;
60
import javax.swing.table.TableCellRenderer;
61
import javax.swing.table.TableColumn;
62
import java.awt.*;
63
import java.awt.event.WindowAdapter;
64
import java.awt.event.WindowEvent;
65
import java.awt.event.WindowListener;
66
import java.util.ArrayList;
67

68
/**
69
 * Dialog for viewing and editing Indexes in the Admin Client 
70
 * 
71
 * @author <a href="mailto:adam@evolvedbinary.com">Adam Retter</a>
72
 */
73
class IndexDialog extends JFrame {
74

75
        private static final long serialVersionUID = 1L;
76

77
        private static final String[] CONFIG_TYPE = {
×
78
        "qname",
×
79
        "path"
×
80
    };
81
    
82
        private static final String[] INDEX_TYPES = {
×
83
                "xs:boolean",
×
84
                "xs:integer",
×
85
                "xs:dateTime",
×
86
                "xs:string"
×
87
        };
×
88
        
89
        private CollectionXConf cx = null;
×
90
        
91
        private JComboBox cmbCollections;
92
        
93
        private JTable tblRangeIndexes;
94
        private RangeIndexTableModel rangeIndexModel;
95
        
96
        private InteractiveClient client;
97
        
98
        
99
        public IndexDialog(String title, InteractiveClient client) 
100
        {
101
                super(title);
×
102
                this.client = client;
×
103
        this.setIconImage(InteractiveClient.getElementalIcon(getClass()).getImage());
×
104
                //capture the frame's close event
105
                final WindowListener windowListener = new WindowAdapter()
×
106
                {
107
                        public void windowClosing (WindowEvent e)
108
                        {
109
                saveChanges(true);
×
110
                                
111
                                IndexDialog.this.setVisible(false);
×
112
                                IndexDialog.this.dispose();
×
113
                        }
×
114
                };
115
                this.addWindowListener(windowListener);
×
116
                
117
                //draw the GUI
118
                setupComponents();
×
119
                
120
                //Get the indexes for the root collection
121
                actionGetIndexes(XmldbURI.ROOT_COLLECTION);
×
122
        }
×
123

124
        private void setupComponents()
125
        {
126
                //Dialog Content Panel
127
                final GridBagLayout grid = new GridBagLayout();
×
128
                getContentPane().setLayout(grid);
×
129
                
130
                //Constraints for Layout
131
                final GridBagConstraints c = new GridBagConstraints();
×
132
                c.insets = new Insets(2, 2, 2, 2);
×
133

134
                //collection label
135
                final JLabel label = new JLabel("Collection");
×
136
                c.gridx = 0;
×
137
                c.gridy = 0;
×
138
                c.gridwidth = 1;
×
139
                c.anchor = GridBagConstraints.WEST;
×
140
                c.fill = GridBagConstraints.NONE;
×
141
                c.weightx = 0;
×
142
                c.weighty = 0;
×
143
                grid.setConstraints(label, c);
×
144
                getContentPane().add(label);
×
145
                
146
                //get the collections but not system collections
147
                final ArrayList alCollections = new ArrayList();
×
148
        try
149
        {
150
            final Collection root = client.getCollection(XmldbURI.ROOT_COLLECTION);
×
151
            final ArrayList alAllCollections = getCollections(root, new ArrayList());
×
152
            for (Object alAllCollection : alAllCollections) {
×
153
                //TODO : use XmldbURIs !
154
                if (alAllCollection.toString().contains(CollectionConfigurationManager.CONFIG_COLLECTION)) {
×
155
                    alCollections.add(alAllCollection);
×
156
                }
157
            }
158
        }
×
159
        catch (final XMLDBException e)
×
160
        {
161
            //showErrorMessage(e.getMessage(), e);
162
            return;
×
163
        }
164
        
165
        //Create a combobox listing the collections
166
        cmbCollections = new JComboBox(alCollections.toArray());
×
167
        cmbCollections.addActionListener(e -> {
×
168

169
            saveChanges(true);
×
170

171
            final JComboBox cb = (JComboBox)e.getSource();
×
172
               actionGetIndexes(cb.getSelectedItem().toString());
×
173
        });
×
174
        c.gridx = 1;
×
175
                c.gridy = 0;
×
176
                c.gridwidth = 1;
×
177
                c.anchor = GridBagConstraints.WEST;
×
178
        c.fill = GridBagConstraints.HORIZONTAL;
×
179
                c.weightx = 1;
×
180
                c.weighty = 0;
×
181
        grid.setConstraints(cmbCollections, c);
×
182
        getContentPane().add(cmbCollections);
×
183

184
        //Panel to hold controls relating to the Range Indexes
185
                final JPanel panelRangeIndexes = new JPanel();
×
186
                panelRangeIndexes.setBorder(new TitledBorder("Range Indexes"));
×
187
                final GridBagLayout panelRangeIndexesGrid = new GridBagLayout();
×
188
                panelRangeIndexes.setLayout(panelRangeIndexesGrid);
×
189
        
190
        //Table to hold the Range Indexes with Sroll bar
191
                rangeIndexModel = new RangeIndexTableModel();
×
192
        tblRangeIndexes = new JTable(rangeIndexModel);
×
193
        tblRangeIndexes.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);
×
194
        tblRangeIndexes.setRowHeight(20);
×
195
        tblRangeIndexes.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
×
196
        TableColumn colxsType = tblRangeIndexes.getColumnModel().getColumn(2);
×
197
        colxsType.setCellEditor(new ComboBoxCellEditor(INDEX_TYPES));
×
198
        colxsType.setCellRenderer(new ComboBoxCellRenderer(INDEX_TYPES));
×
199
        colxsType = tblRangeIndexes.getColumnModel().getColumn(0);
×
200
        colxsType.setCellEditor(new ComboBoxCellEditor(CONFIG_TYPE));
×
201
        colxsType.setCellRenderer(new ComboBoxCellRenderer(CONFIG_TYPE));
×
202
        final JScrollPane scrollRangeIndexes = new JScrollPane(tblRangeIndexes);
×
203
                scrollRangeIndexes.setPreferredSize(new Dimension(350, 150));
×
204
                c.gridx = 0;
×
205
                c.gridy = 0;
×
206
                c.gridwidth = 2;
×
207
                c.anchor = GridBagConstraints.WEST;
×
208
                c.fill = GridBagConstraints.BOTH;
×
209
                c.weightx = 1;
×
210
                c.weighty = 1;
×
211
                panelRangeIndexesGrid.setConstraints(scrollRangeIndexes, c);
×
212
                panelRangeIndexes.add(scrollRangeIndexes);
×
213
        
214
                //Toolbar with add/delete buttons for Range Index
215
                final Box rangeIndexToolbarBox = Box.createHorizontalBox();
×
216
                //add button
217
                final JButton btnAddRangeIndex = new JButton("Add");
×
218
                btnAddRangeIndex.addActionListener(e -> actionAddRangeIndex());
×
219
                rangeIndexToolbarBox.add(btnAddRangeIndex);
×
220
                //delete button
221
                final JButton btnDeleteRangeIndex = new JButton("Delete");
×
222
                btnDeleteRangeIndex.addActionListener(e -> actionDeleteRangeIndex());
×
223
                rangeIndexToolbarBox.add(btnDeleteRangeIndex);
×
224
                c.gridx = 0;
×
225
                c.gridy = 1;
×
226
                c.gridwidth = 2;
×
227
                c.anchor = GridBagConstraints.CENTER;
×
228
                c.fill = GridBagConstraints.BOTH;
×
229
                c.weightx = 0;
×
230
                c.weighty = 0;
×
231
                panelRangeIndexesGrid.setConstraints(rangeIndexToolbarBox, c);
×
232
                panelRangeIndexes.add(rangeIndexToolbarBox);
×
233

234
                //add range index panel to content frame
235
                c.gridx = 0;
×
236
                c.gridy = 2;
×
237
                c.gridwidth = 2;
×
238
                c.anchor = GridBagConstraints.WEST;
×
239
            c.fill = GridBagConstraints.BOTH;
×
240
                c.weightx = 1;
×
241
                c.weighty = 1F / 3F;
×
242
            grid.setConstraints(panelRangeIndexes, c);
×
243
                getContentPane().add(panelRangeIndexes);
×
244

245
        final Box mainBtnBox = Box.createHorizontalBox();
×
246
        final JButton cancelBtn = new JButton("Cancel");
×
247
        cancelBtn.addActionListener(e -> {
×
248
            IndexDialog.this.setVisible(false);
×
249
            IndexDialog.this.dispose();
×
250
        });
×
251
        final JButton saveBtn = new JButton("Save");
×
252
        saveBtn.addActionListener(e -> {
×
253
            saveChanges(false);
×
254
            IndexDialog.this.setVisible(false);
×
255
            IndexDialog.this.dispose();
×
256
        });
×
257
        mainBtnBox.add(saveBtn);
×
258
        mainBtnBox.add(cancelBtn);
×
259
        
260
        c.gridx = 0;
×
261
                c.gridy = 3;
×
262
                c.gridwidth = 2;
×
263
                c.anchor = GridBagConstraints.WEST;
×
264
            c.fill = GridBagConstraints.BOTH;
×
265
                c.weightx = 0;
×
266
                c.weighty = 0;
×
267
            grid.setConstraints(mainBtnBox, c);
×
268
                getContentPane().add(mainBtnBox);
×
269

270
        pack();
×
271
        }
×
272

273
        //if changes have been made, allows the user to save them
274
        private void saveChanges(boolean ask)
275
        {
276
        //the collection has been changed
277
                if(cx.hasChanged())
×
278
                {
279
            boolean doSave = true;
×
280
            if (ask) {
×
281
                //ask the user if they would like to save the changes
282
                final int result = JOptionPane.showConfirmDialog(getContentPane(), "The configuration for the collection has changed, would you like to save the changes?", "Save Changes", JOptionPane.YES_NO_OPTION);
×
283
                doSave = result == JOptionPane.YES_OPTION;
×
284
            }
285
                        
286
            if(doSave)
×
287
                        {
288
                                //save the collection.xconf changes
289
                                if(cx.Save())
×
290
                                {
291
                                        //save ok, reindex?
292
                                        final int result = JOptionPane.showConfirmDialog(getContentPane(), "Your changes have been saved, but will not take effect until the collection is reindexed!\n Would you like to reindex " + cmbCollections.getSelectedItem() + " and sub-collections now?", "Reindex", JOptionPane.YES_NO_OPTION);
×
293
                                        
294
                                        if(result == JOptionPane.YES_OPTION)
×
295
                                        {
296
                                                //reindex collection
297
                                                final Runnable reindexThread = () -> {
×
298
                            try
299
                            {
300
                                IndexQueryService service = client.current.getService(IndexQueryService.class);
×
301

302
                                ArrayList subCollections = getCollections(client.getCollection((String)cmbCollections.getSelectedItem()), new ArrayList());
×
303

304
                                for (Object subCollection : subCollections) {
×
305
                                    service.reindexCollection(((ResourceDescriptor) subCollection).getName());
×
306
                                }
307

308
                                //reindex done
309
                                JOptionPane.showMessageDialog(getContentPane(), "Reindex Complete");
×
310
                            }
×
311
                            catch(XMLDBException e)
×
312
                            {
313
                                //reindex failed
314
                                JOptionPane.showMessageDialog(getContentPane(), "Reindex failed!");
×
315
                            }
316
                        };
×
317
                                        }
318
                                }
×
319
                                else
320
                                {
321
                                        //save failed
322
                                        JOptionPane.showMessageDialog(getContentPane(), "Unable to save changes!");
×
323
                                }
324
                        }
325
                }
326
        }
×
327
        
328
        
329
        //THIS IS A COPY FROM ClientFrame
330
        //TODO: share this code between the two classes
331
        private ArrayList getCollections(Collection root, ArrayList collectionsList) throws XMLDBException
332
    {
333
        collectionsList.add(new PrettyXmldbURI(XmldbURI.create(root.getName())));
×
334
        Collection child;
335
                for (String childCollection : root.listChildCollections()) {
×
336
                        child = root.getChildCollection(childCollection);
×
337
                        getCollections(child, collectionsList);
×
338
                }
339
        return collectionsList;
×
340
    }
341

342
        private void actionAddRangeIndex()
343
        {
344
                rangeIndexModel.addRow();
×
345
        }
×
346
        
347
        private void actionDeleteRangeIndex()
348
        {
349
                final int iSelectedRow = tblRangeIndexes.getSelectedRow();
×
350
                if(iSelectedRow > -1 )
×
351
                {
352
                        rangeIndexModel.removeRow(iSelectedRow);
×
353
                }
354
        }
×
355
        
356
        //Displays the indexes when a collection is selection
357
        private void actionGetIndexes(String collectionName)
358
        {
359
                try
360
                {
361
                        cx = new CollectionXConf(collectionName, client);
×
362
                        
363
                        rangeIndexModel.fireTableDataChanged();
×
364
                }
×
365
                catch(final XMLDBException xe)
×
366
                {
367
                        //TODO: CONSIDER whether CollectionXConf Should throw xmldb exception at all?
368
                }
369
                
370
        }
×
371
        
372
        public static class ComboBoxCellRenderer extends JComboBox implements TableCellRenderer
373
        {
374
                private static final long serialVersionUID = 1L;
375

376
                public ComboBoxCellRenderer(String[] items)
377
        {
378
            super(items);
×
379
        }
×
380
    
381
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
382
        {
383
            if(isSelected)
×
384
            {
385
                setForeground(table.getSelectionForeground());
×
386
                super.setBackground(table.getSelectionBackground());
×
387
            }
×
388
            else
389
            {
390
                setForeground(table.getForeground());
×
391
                setBackground(table.getBackground());
×
392
            }
393
    
394
            // Select the current value
395
            setSelectedItem(value);
×
396
            return this;
×
397
        }
398
    }
399
    
400
        
401
    public static class ComboBoxCellEditor extends DefaultCellEditor
402
    {
403
                private static final long serialVersionUID = 1L;
404

405
                public ComboBoxCellEditor(String[] items)
406
        {
407
            super(new JComboBox(items));
×
408
        }
×
409
    }
410

411
        class RangeIndexTableModel extends AbstractTableModel
412
        {        
413
                private static final long serialVersionUID = 1L;
414

415
                private final String[] columnNames = new String[] { "Type", "XPath", "xsType" };
×
416

417
                public RangeIndexTableModel()
418
                {
×
419
                        super();
×
420
                        fireTableDataChanged();
×
421
                }
×
422
                
423
                /* (non-Javadoc)
424
                * @see javax.swing.table.TableModel#isCellEditable()
425
                */
426
                public void setValueAt(Object aValue, int rowIndex, int columnIndex)
427
                {
428
                        switch (columnIndex)
×
429
                        {
430
                case 0:
431
                    cx.updateRangeIndex(rowIndex, aValue.toString(), null, null);
×
432
                    break;
×
433
                case 1:                /* XPath */
434
                                        cx.updateRangeIndex(rowIndex, null, aValue.toString(), null);
×
435
                                        break;
×
436
                                case 2 :        /* xsType */
437
                                        cx.updateRangeIndex(rowIndex, null, null, aValue.toString());
×
438
                                        break;
×
439
                                default :
440
                                        break;
441
                        }
442
                        
443
                        fireTableCellUpdated(rowIndex, columnIndex);
×
444
                }
×
445
                
446
                public void removeRow(int rowIndex)
447
                {
448
                        cx.deleteRangeIndex(rowIndex);
×
449
                        fireTableRowsDeleted(rowIndex, rowIndex);
×
450
                }
×
451
                
452
                public void addRow()
453
                {                        
454
                        cx.addRangeIndex(CollectionXConf.TYPE_QNAME, "", "xs:string");
×
455
                        fireTableRowsInserted(getRowCount(), getRowCount() + 1);
×
456
                }
×
457
                
458
                /* (non-Javadoc)
459
                * @see javax.swing.table.TableModel#isCellEditable()
460
                */
461
                public boolean isCellEditable(int rowIndex, int columnIndex)
462
                {
463
                        return true;
×
464
                }
465
                
466
                /* (non-Javadoc)
467
                * @see javax.swing.table.TableModel#getColumnCount()
468
                */
469
                public int getColumnCount()
470
                {
471
                        return columnNames.length;
×
472
                }
473

474
                /* (non-Javadoc)
475
                 * @see javax.swing.table.TableModel#getColumnName(int)
476
                 */
477
                public String getColumnName(int column)
478
                {
479
                        return columnNames[column];
×
480
                }
481

482
                /* (non-Javadoc)
483
                 * @see javax.swing.table.TableModel#getRowCount()
484
                 */
485
                public int getRowCount()
486
                {
487
                        return cx != null ? cx.getRangeIndexCount() : 0;
×
488
                }
489

490
                /* (non-Javadoc)
491
                 * @see javax.swing.table.TableModel#getValueAt(int, int)
492
                 */
493
                public Object getValueAt(int rowIndex, int columnIndex)
494
                {
495
            return switch (columnIndex) {
×
496
                case 0 -> cx.getRangeIndex(rowIndex).getType();
×
497
                case 1 ->    /* XPath */
498
                        cx.getRangeIndex(rowIndex).getXPath();
×
499
                case 2 ->    /* xsType */
500
                        cx.getRangeIndex(rowIndex).getxsType();
×
501
                default -> null;
×
502
            };
503
                }
504
        }
505
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc