| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.lucene.luke.app.desktop.components.dialog.menubar; |
| |
| import javax.swing.BorderFactory; |
| import javax.swing.BoxLayout; |
| import javax.swing.JButton; |
| import javax.swing.JDialog; |
| import javax.swing.JFileChooser; |
| import javax.swing.JLabel; |
| import javax.swing.JOptionPane; |
| import javax.swing.JPanel; |
| import javax.swing.JSeparator; |
| import javax.swing.JTextArea; |
| import javax.swing.JTextField; |
| import javax.swing.SwingWorker; |
| import java.awt.BorderLayout; |
| import java.awt.Dialog; |
| import java.awt.Dimension; |
| import java.awt.FlowLayout; |
| import java.awt.GridLayout; |
| import java.awt.Window; |
| import java.awt.event.ActionEvent; |
| import java.io.File; |
| import java.io.IOException; |
| import java.lang.invoke.MethodHandles; |
| import java.nio.file.FileVisitResult; |
| import java.nio.file.Files; |
| import java.nio.file.Path; |
| import java.nio.file.Paths; |
| import java.nio.file.SimpleFileVisitor; |
| import java.nio.file.attribute.BasicFileAttributes; |
| import java.util.concurrent.ExecutorService; |
| import java.util.concurrent.Executors; |
| |
| import org.apache.logging.log4j.Logger; |
| import org.apache.lucene.luke.app.IndexHandler; |
| import org.apache.lucene.luke.app.desktop.Preferences; |
| import org.apache.lucene.luke.app.desktop.PreferencesFactory; |
| import org.apache.lucene.luke.app.desktop.util.DialogOpener; |
| import org.apache.lucene.luke.app.desktop.util.FontUtils; |
| import org.apache.lucene.luke.app.desktop.util.ImageUtils; |
| import org.apache.lucene.luke.app.desktop.util.MessageUtils; |
| import org.apache.lucene.luke.app.desktop.util.StyleConstants; |
| import org.apache.lucene.luke.app.desktop.util.URLLabel; |
| import org.apache.lucene.luke.models.tools.IndexTools; |
| import org.apache.lucene.luke.models.tools.IndexToolsFactory; |
| import org.apache.lucene.luke.util.LoggerFactory; |
| import org.apache.lucene.store.Directory; |
| import org.apache.lucene.store.FSDirectory; |
| import org.apache.lucene.util.NamedThreadFactory; |
| import org.apache.lucene.util.SuppressForbidden; |
| |
| /** Factory of create index dialog */ |
| public class CreateIndexDialogFactory implements DialogOpener.DialogFactory { |
| |
| private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); |
| |
| private static CreateIndexDialogFactory instance; |
| |
| private final Preferences prefs; |
| |
| private final IndexHandler indexHandler; |
| |
| private final JTextField locationTF = new JTextField(); |
| |
| private final JButton browseBtn = new JButton(); |
| |
| private final JTextField dirnameTF = new JTextField(); |
| |
| private final JTextField dataDirTF = new JTextField(); |
| |
| private final JButton dataBrowseBtn = new JButton(); |
| |
| private final JButton clearBtn = new JButton(); |
| |
| private final JLabel indicatorLbl = new JLabel(); |
| |
| private final JButton createBtn = new JButton(); |
| |
| private final JButton cancelBtn = new JButton(); |
| |
| private final ListenerFunctions listeners = new ListenerFunctions(); |
| |
| private JDialog dialog; |
| |
| public synchronized static CreateIndexDialogFactory getInstance() throws IOException { |
| if (instance == null) { |
| instance = new CreateIndexDialogFactory(); |
| } |
| return instance; |
| } |
| |
| private CreateIndexDialogFactory() throws IOException { |
| this.prefs = PreferencesFactory.getInstance(); |
| this.indexHandler = IndexHandler.getInstance(); |
| initialize(); |
| } |
| |
| private void initialize() { |
| locationTF.setPreferredSize(new Dimension(360, 30)); |
| locationTF.setText(System.getProperty("user.home")); |
| locationTF.setEditable(false); |
| |
| browseBtn.setText(FontUtils.elegantIconHtml("n", MessageUtils.getLocalizedMessage("button.browse"))); |
| browseBtn.setFont(StyleConstants.FONT_BUTTON_LARGE); |
| browseBtn.setPreferredSize(new Dimension(120, 30)); |
| browseBtn.addActionListener(listeners::browseLocationDirectory); |
| |
| dirnameTF.setPreferredSize(new Dimension(200, 30)); |
| |
| dataDirTF.setPreferredSize(new Dimension(250, 30)); |
| dataDirTF.setEditable(false); |
| |
| clearBtn.setText(MessageUtils.getLocalizedMessage("button.clear")); |
| clearBtn.setPreferredSize(new Dimension(70, 30)); |
| clearBtn.addActionListener(listeners::clearDataDir); |
| |
| dataBrowseBtn.setText(FontUtils.elegantIconHtml("n", MessageUtils.getLocalizedMessage("button.browse"))); |
| dataBrowseBtn.setFont(StyleConstants.FONT_BUTTON_LARGE); |
| dataBrowseBtn.setPreferredSize(new Dimension(100, 30)); |
| dataBrowseBtn.addActionListener(listeners::browseDataDirectory); |
| |
| indicatorLbl.setIcon(ImageUtils.createImageIcon("indicator.gif", 20, 20)); |
| indicatorLbl.setVisible(false); |
| |
| createBtn.setText(MessageUtils.getLocalizedMessage("button.create")); |
| createBtn.addActionListener(listeners::createIndex); |
| |
| cancelBtn.setText(MessageUtils.getLocalizedMessage("button.cancel")); |
| cancelBtn.addActionListener(e -> dialog.dispose()); |
| } |
| |
| @Override |
| public JDialog create(Window owner, String title, int width, int height) { |
| dialog = new JDialog(owner, title, Dialog.ModalityType.APPLICATION_MODAL); |
| dialog.add(content()); |
| dialog.setSize(new Dimension(width, height)); |
| dialog.setLocationRelativeTo(owner); |
| dialog.getContentPane().setBackground(prefs.getColorTheme().getBackgroundColor()); |
| return dialog; |
| } |
| |
| private JPanel content() { |
| JPanel panel = new JPanel(); |
| panel.setOpaque(false); |
| panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS)); |
| panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); |
| |
| panel.add(basicSettings()); |
| panel.add(new JSeparator(JSeparator.HORIZONTAL)); |
| panel.add(optionalSettings()); |
| panel.add(new JSeparator(JSeparator.HORIZONTAL)); |
| panel.add(buttons()); |
| |
| return panel; |
| } |
| |
| private JPanel basicSettings() { |
| JPanel panel = new JPanel(new GridLayout(2, 1)); |
| panel.setOpaque(false); |
| |
| JPanel locPath = new JPanel(new FlowLayout(FlowLayout.LEADING)); |
| locPath.setOpaque(false); |
| locPath.add(new JLabel(MessageUtils.getLocalizedMessage("createindex.label.location"))); |
| locPath.add(locationTF); |
| locPath.add(browseBtn); |
| panel.add(locPath); |
| |
| JPanel dirName = new JPanel(new FlowLayout(FlowLayout.LEADING)); |
| dirName.setOpaque(false); |
| dirName.add(new JLabel(MessageUtils.getLocalizedMessage("createindex.label.dirname"))); |
| dirName.add(dirnameTF); |
| panel.add(dirName); |
| |
| return panel; |
| } |
| |
| private JPanel optionalSettings() { |
| JPanel panel = new JPanel(new BorderLayout()); |
| panel.setOpaque(false); |
| |
| JPanel description = new JPanel(); |
| description.setLayout(new BoxLayout(description, BoxLayout.Y_AXIS)); |
| description.setOpaque(false); |
| |
| JPanel name = new JPanel(new FlowLayout(FlowLayout.LEADING)); |
| name.setOpaque(false); |
| JLabel nameLbl = new JLabel(MessageUtils.getLocalizedMessage("createindex.label.option")); |
| name.add(nameLbl); |
| description.add(name); |
| |
| JTextArea descTA1 = new JTextArea(MessageUtils.getLocalizedMessage("createindex.textarea.data_help1")); |
| descTA1.setPreferredSize(new Dimension(550, 20)); |
| descTA1.setBorder(BorderFactory.createEmptyBorder(2, 10, 10, 5)); |
| descTA1.setOpaque(false); |
| descTA1.setLineWrap(true); |
| descTA1.setEditable(false); |
| description.add(descTA1); |
| |
| JPanel link = new JPanel(new FlowLayout(FlowLayout.LEADING, 10, 1)); |
| link.setOpaque(false); |
| JLabel linkLbl = FontUtils.toLinkText(new URLLabel(MessageUtils.getLocalizedMessage("createindex.label.data_link"))); |
| link.add(linkLbl); |
| description.add(link); |
| |
| JTextArea descTA2 = new JTextArea(MessageUtils.getLocalizedMessage("createindex.textarea.data_help2")); |
| descTA2.setPreferredSize(new Dimension(550, 50)); |
| descTA2.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 5)); |
| descTA2.setOpaque(false); |
| descTA2.setLineWrap(true); |
| descTA2.setEditable(false); |
| description.add(descTA2); |
| |
| panel.add(description, BorderLayout.PAGE_START); |
| |
| JPanel dataDirPath = new JPanel(new FlowLayout(FlowLayout.LEADING)); |
| dataDirPath.setOpaque(false); |
| dataDirPath.add(new JLabel(MessageUtils.getLocalizedMessage("createindex.label.datadir"))); |
| dataDirPath.add(dataDirTF); |
| dataDirPath.add(dataBrowseBtn); |
| |
| dataDirPath.add(clearBtn); |
| panel.add(dataDirPath, BorderLayout.CENTER); |
| |
| return panel; |
| } |
| |
| private JPanel buttons() { |
| JPanel panel = new JPanel(new FlowLayout(FlowLayout.TRAILING)); |
| panel.setOpaque(false); |
| panel.setBorder(BorderFactory.createEmptyBorder(3, 3, 10, 20)); |
| |
| panel.add(indicatorLbl); |
| panel.add(createBtn); |
| panel.add(cancelBtn); |
| |
| return panel; |
| } |
| |
| private class ListenerFunctions { |
| |
| void browseLocationDirectory(ActionEvent e) { |
| browseDirectory(locationTF); |
| } |
| |
| void browseDataDirectory(ActionEvent e) { |
| browseDirectory(dataDirTF); |
| } |
| |
| @SuppressForbidden(reason = "JFilechooser#getSelectedFile() returns java.io.File") |
| private void browseDirectory(JTextField tf) { |
| JFileChooser fc = new JFileChooser(new File(tf.getText())); |
| fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); |
| fc.setFileHidingEnabled(false); |
| int retVal = fc.showOpenDialog(dialog); |
| if (retVal == JFileChooser.APPROVE_OPTION) { |
| File dir = fc.getSelectedFile(); |
| tf.setText(dir.getAbsolutePath()); |
| } |
| } |
| |
| void createIndex(ActionEvent e) { |
| Path path = Paths.get(locationTF.getText(), dirnameTF.getText()); |
| if (Files.exists(path)) { |
| String message = "The directory " + path.toAbsolutePath().toString() + " already exists."; |
| JOptionPane.showMessageDialog(dialog, message, "Empty index path", JOptionPane.ERROR_MESSAGE); |
| } else { |
| // create new index asynchronously |
| ExecutorService executor = Executors.newFixedThreadPool(1, new NamedThreadFactory("create-index-dialog")); |
| |
| SwingWorker<Void, Void> task = new SwingWorker<Void, Void>() { |
| |
| @Override |
| protected Void doInBackground() throws Exception { |
| setProgress(0); |
| indicatorLbl.setVisible(true); |
| createBtn.setEnabled(false); |
| |
| try { |
| Directory dir = FSDirectory.open(path); |
| IndexTools toolsModel = new IndexToolsFactory().newInstance(dir); |
| |
| if (dataDirTF.getText().isEmpty()) { |
| // without sample documents |
| toolsModel.createNewIndex(); |
| } else { |
| // with sample documents |
| Path dataPath = Paths.get(dataDirTF.getText()); |
| toolsModel.createNewIndex(dataPath.toAbsolutePath().toString()); |
| } |
| |
| indexHandler.open(path.toAbsolutePath().toString(), null, false, false, false); |
| prefs.addHistory(path.toAbsolutePath().toString()); |
| |
| dirnameTF.setText(""); |
| closeDialog(); |
| } catch (Exception ex) { |
| // cleanup |
| try { |
| Files.walkFileTree(path, new SimpleFileVisitor<Path>() { |
| @Override |
| public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { |
| Files.delete(file); |
| return FileVisitResult.CONTINUE; |
| } |
| }); |
| Files.deleteIfExists(path); |
| } catch (IOException ex2) { |
| } |
| |
| log.error("Cannot create index", ex); |
| String message = "See Logs tab or log file for more details."; |
| JOptionPane.showMessageDialog(dialog, message, "Cannot create index", JOptionPane.ERROR_MESSAGE); |
| } finally { |
| setProgress(100); |
| } |
| return null; |
| } |
| |
| @Override |
| protected void done() { |
| indicatorLbl.setVisible(false); |
| createBtn.setEnabled(true); |
| } |
| }; |
| |
| executor.submit(task); |
| executor.shutdown(); |
| } |
| } |
| |
| private void clearDataDir(ActionEvent e) { |
| dataDirTF.setText(""); |
| } |
| |
| private void closeDialog() { |
| dialog.dispose(); |
| } |
| } |
| } |