419 lines
15 KiB
Java
419 lines
15 KiB
Java
package application;
|
||
|
||
import java.awt.BorderLayout;
|
||
import java.awt.Desktop;
|
||
import java.awt.Dimension;
|
||
import java.awt.GridLayout;
|
||
import java.awt.event.ActionEvent;
|
||
import java.awt.event.KeyEvent;
|
||
import java.awt.event.MouseAdapter;
|
||
import java.awt.event.MouseEvent;
|
||
import java.io.File;
|
||
import java.io.IOException;
|
||
import java.nio.file.Files;
|
||
import java.nio.file.Path;
|
||
import java.nio.file.StandardCopyOption;
|
||
import java.util.ArrayList;
|
||
import java.util.List;
|
||
import java.util.regex.Matcher;
|
||
import java.util.regex.Pattern;
|
||
|
||
import javax.naming.ConfigurationException;
|
||
import javax.swing.BorderFactory;
|
||
import javax.swing.JButton;
|
||
import javax.swing.JFileChooser;
|
||
import javax.swing.JFrame;
|
||
import javax.swing.JLabel;
|
||
import javax.swing.JMenu;
|
||
import javax.swing.JMenuBar;
|
||
import javax.swing.JMenuItem;
|
||
import javax.swing.JOptionPane;
|
||
import javax.swing.JPanel;
|
||
import javax.swing.JPopupMenu;
|
||
import javax.swing.KeyStroke;
|
||
import javax.swing.SwingUtilities;
|
||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||
|
||
import org.apache.commons.io.FilenameUtils;
|
||
|
||
import de.lcag.common.ExcelWorkbook;
|
||
import de.lcag.common.LcagProperties;
|
||
import de.lcag.common.MappingTable;
|
||
import de.lcag.common.Table;
|
||
import de.lcag.common.WorkbookComparisonResult;
|
||
import routines.LcagFileTools;
|
||
import routines.LcagStringTools;
|
||
|
||
public class FileActions extends JFrame {
|
||
private static final int FRAME_HEIGHT = 150;
|
||
private static String MASTER_FILE_LABEL = "Main Excel File";
|
||
private static String CONFIG_FILE_LABEL = "Configuration File";
|
||
|
||
private JLabel masterFileLabel, clientFileLabel, configFileLabel;
|
||
private JButton selectMasterFile, selectClientFile, selectConfigFile;
|
||
private Path configFile;
|
||
private String masterFile, clientFile;
|
||
private JMenuBar menuBar;
|
||
private JMenu actionsMenu;
|
||
private JMenuItem mergeAction;
|
||
private JPopupMenu contextMenuMasterFile, contextMenuClientFile;
|
||
private File configFileDirectoryPath = null;
|
||
private LcagProperties config = null;
|
||
private File masterDirecory = null;
|
||
private File clientDirecory = null;
|
||
private static List<String> SUPPORTED_FILE_TYPES = List.of("xls", "xlsx");
|
||
|
||
public FileActions() {
|
||
setTitle("Compare 2 Excel Files");
|
||
setSize(800, FRAME_HEIGHT);
|
||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||
|
||
JPanel mainPanel = new JPanel(new BorderLayout());
|
||
JPanel leftButtonPanel = new JPanel(new GridLayout(3, 1, 5, 5));
|
||
JPanel rightTextPanel = new JPanel(new GridLayout(3, 1, 5, 5));
|
||
// setLayout(new GridLayout(4, 2));
|
||
|
||
leftButtonPanel.setPreferredSize(new Dimension(200, FRAME_HEIGHT)); // Fixed width
|
||
|
||
// Add an empty border to create a gap on the right side of leftPanel
|
||
leftButtonPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10)); // right gap: 10px
|
||
|
||
rightTextPanel.setPreferredSize(new Dimension(1000, FRAME_HEIGHT));
|
||
mainPanel.add(leftButtonPanel, BorderLayout.WEST);
|
||
mainPanel.add(rightTextPanel, BorderLayout.EAST);
|
||
|
||
configFileLabel = new JLabel(String.format(" %s: Not selected", CONFIG_FILE_LABEL));
|
||
|
||
selectConfigFile = new JButton("Select " + CONFIG_FILE_LABEL);
|
||
leftButtonPanel.add(selectConfigFile);
|
||
rightTextPanel.add(configFileLabel);
|
||
|
||
// File Chooser for config file
|
||
selectConfigFile.setEnabled(true);
|
||
selectConfigFile.addActionListener(e -> {
|
||
if (!configFileDirectoryPath.isDirectory()) {
|
||
System.err.println(String.format("ERROR: Config directory %s does not exist",
|
||
configFileDirectoryPath.getAbsolutePath()));
|
||
System.exit(1);
|
||
}
|
||
|
||
JFileChooser fileChooser = new JFileChooser(configFileDirectoryPath);
|
||
FileNameExtensionFilter filter = new FileNameExtensionFilter("Config Files", "properties");
|
||
fileChooser.setFileFilter(filter);
|
||
if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
|
||
String clientDirString = null;
|
||
|
||
configFile = Path.of(selectFile(fileChooser));
|
||
config = new LcagProperties(configFile.toString());
|
||
|
||
configFileLabel.setText(String.format(" %s: %s", CONFIG_FILE_LABEL, configFile));
|
||
|
||
masterFile = config.getOptionalProperty("main_file");
|
||
|
||
if (masterFile != null) {
|
||
String masterFilePath = LcagFileTools.getPath(masterFile);
|
||
masterFile = LcagFileTools.getName(masterFile);
|
||
masterDirecory = new File(masterFilePath);
|
||
masterFileLabel.setText(String.format("<html>Selected: %s<br>in: %s</html>", masterFile,
|
||
masterDirecory.getAbsolutePath()));
|
||
selectMasterFile.setEnabled(true);
|
||
}
|
||
|
||
clientFile = config.getOptionalProperty("compare_file");
|
||
if (clientFile != null) {
|
||
String clientFilePath = LcagFileTools.getPath(clientFile);
|
||
clientFile = LcagFileTools.getName(clientFile);
|
||
clientDirecory = new File(clientFilePath);
|
||
|
||
if (clientDirecory.isAbsolute()) {
|
||
clientDirString = clientFilePath;
|
||
} else {
|
||
clientDirString = "same directory as 1st file";
|
||
}
|
||
clientFileLabel.setText(
|
||
String.format("<html>Selected: %s<br>in: %s </html>", clientFile, clientDirString));
|
||
selectClientFile.setEnabled(true);
|
||
}
|
||
// After user selected a config file enable buttons to set files to compare (can
|
||
// overwrite files listed in config file):
|
||
|
||
}
|
||
});
|
||
|
||
// Kontextmen<65>s erstellen
|
||
contextMenuMasterFile = new JPopupMenu();
|
||
contextMenuClientFile = new JPopupMenu();
|
||
JMenuItem renameFile1 = new JMenuItem("Rename File");
|
||
JMenuItem renameFile2 = new JMenuItem("Rename File");
|
||
contextMenuMasterFile.add(renameFile1);
|
||
contextMenuClientFile.add(renameFile2);
|
||
|
||
masterFileLabel = new JLabel(
|
||
String.format(" %s: %s", MASTER_FILE_LABEL, masterFile == null ? "Not selected" : masterFile));
|
||
|
||
selectMasterFile = new JButton("Select " + MASTER_FILE_LABEL);
|
||
leftButtonPanel.add(selectMasterFile);
|
||
rightTextPanel.add(masterFileLabel);
|
||
|
||
clientFileLabel = new JLabel(
|
||
String.format(" %s: %s", "Excel to compare", clientFile == null ? "Not selected" : clientFile));
|
||
|
||
selectClientFile = new JButton("Select Excel to Compare");
|
||
|
||
// MouseListener f<>r Kontextmen<65> auf den Labels
|
||
masterFileLabel.addMouseListener(new MouseAdapter() {
|
||
@Override
|
||
public void mouseClicked(MouseEvent e) {
|
||
if (SwingUtilities.isRightMouseButton(e) && masterFile != null) {
|
||
contextMenuMasterFile.show(masterFileLabel, e.getX(), e.getY());
|
||
}
|
||
}
|
||
});
|
||
clientFileLabel.addMouseListener(new MouseAdapter() {
|
||
@Override
|
||
public void mouseClicked(MouseEvent e) {
|
||
if (SwingUtilities.isRightMouseButton(e) && clientFile != null) {
|
||
contextMenuClientFile.show(clientFileLabel, e.getX(), e.getY());
|
||
}
|
||
}
|
||
});
|
||
|
||
leftButtonPanel.add(selectClientFile);
|
||
rightTextPanel.add(clientFileLabel);
|
||
|
||
renameFile1.addActionListener(e -> renameFile(masterFile, masterFileLabel, "Datei 1"));
|
||
renameFile2.addActionListener(e -> renameFile(clientFile, clientFileLabel, "Datei 2"));
|
||
|
||
// File Chooser f<>r Datei 1 (nur Excel-Dateien)
|
||
selectMasterFile.setEnabled(false);
|
||
selectMasterFile.addActionListener(e -> {
|
||
JFileChooser fileChooser = new JFileChooser();
|
||
FileNameExtensionFilter filter = new FileNameExtensionFilter("Excel-Files",
|
||
SUPPORTED_FILE_TYPES.toArray(new String[0]));
|
||
fileChooser.setFileFilter(filter);
|
||
|
||
if (masterFile != null) {
|
||
Path masterFilePath = Path.of(masterFile);
|
||
masterDirecory = new File(masterFilePath.getParent().toString());
|
||
fileChooser.setCurrentDirectory(masterDirecory);
|
||
|
||
masterDirecory = new File(masterFilePath.getParent().toString());
|
||
masterFileLabel.setText(String.format("<html>Selected: %s<br>in: %s</html>", masterFile,
|
||
masterFilePath.getParent().toString()));
|
||
selectClientFile.setEnabled(true);
|
||
}
|
||
|
||
if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
|
||
Path masterFilePath = Path.of(masterFile);
|
||
masterFile = selectFile(fileChooser);
|
||
masterDirecory = new File(masterFilePath.getParent().toString());
|
||
masterFileLabel.setText(String.format(" %s: %s", MASTER_FILE_LABEL, masterFilePath.getFileName()));
|
||
selectClientFile.setEnabled(true);
|
||
}
|
||
});
|
||
|
||
// File Chooser f<>r Datei 2 (im selben Verzeichnis wie Datei 1, nur
|
||
// Excel-Dateien)
|
||
selectClientFile.setEnabled(false);
|
||
selectClientFile.addActionListener(e -> {
|
||
if (masterDirecory != null) {
|
||
JFileChooser fileChooser = new JFileChooser(masterDirecory);
|
||
FileNameExtensionFilter filter = new FileNameExtensionFilter("Excel-Dateien", "xls", "xlsx");
|
||
fileChooser.setFileFilter(filter);
|
||
if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
|
||
clientFile = selectFile(fileChooser);
|
||
clientFileLabel.setText("Datei 2: " + clientFile);
|
||
}
|
||
}
|
||
});
|
||
|
||
// Men<65> erstellen
|
||
menuBar = new JMenuBar();
|
||
actionsMenu = new JMenu("Actions");
|
||
mergeAction = new JMenuItem("Merge 2nd into Main file");
|
||
|
||
mergeAction.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_M, ActionEvent.CTRL_MASK));
|
||
mergeAction.addActionListener(e -> {
|
||
System.out.println("Ctrl-C pressed on menu");
|
||
});
|
||
|
||
actionsMenu.add(mergeAction);
|
||
menuBar.add(actionsMenu);
|
||
setJMenuBar(menuBar);
|
||
|
||
// Aktion: Erste Datei in Excel <20>ffnen
|
||
mergeAction.addActionListener(e -> {
|
||
mergeFiles(config, masterFile, clientFile);
|
||
});
|
||
|
||
add(mainPanel);
|
||
pack();
|
||
setVisible(true);
|
||
}
|
||
|
||
private String selectFile(JFileChooser fileChooser) {
|
||
File result = fileChooser.getSelectedFile();
|
||
return FilenameUtils.separatorsToUnix(result.getAbsolutePath());
|
||
}
|
||
|
||
private void mergeFiles(LcagProperties pConfig, String pMasterFilePathPattern, String pClientFilePathPattern) {
|
||
Pattern masterPattern = Pattern.compile(pMasterFilePathPattern);
|
||
List<Path> masterFiles = new ArrayList<>();
|
||
String masterDirectoryPathStr = masterDirecory.getAbsolutePath();
|
||
|
||
try {
|
||
Path masterDirectoryPath = Path.of(masterDirectoryPathStr);
|
||
masterFiles = Files.walk(masterDirectoryPath).filter(p -> {
|
||
String filePath = FilenameUtils.separatorsToUnix(p.toString());
|
||
String fileName = LcagFileTools.getName(p.toString());
|
||
|
||
Matcher matcher = masterPattern.matcher(fileName);
|
||
boolean matches = matcher.matches();
|
||
return matches;
|
||
}).toList();
|
||
} catch (IOException e) {
|
||
// TODO Auto-generated catch block
|
||
e.printStackTrace();
|
||
}
|
||
|
||
if (pConfig == null) {
|
||
JOptionPane.showMessageDialog(this, "Pls select at least a config file!", "Error",
|
||
JOptionPane.ERROR_MESSAGE);
|
||
|
||
return;
|
||
}
|
||
|
||
for (Path aMasterFilePath : masterFiles) {
|
||
String masterFileName = aMasterFilePath.getFileName().toString();
|
||
String fileType = LcagFileTools.getExtension(masterFileName);
|
||
|
||
if (!SUPPORTED_FILE_TYPES.contains(fileType)) {
|
||
System.err.printf("Comparision of file type %s not supported for %s\n", fileType, masterFileName);
|
||
continue;
|
||
}
|
||
|
||
String s = FilenameUtils.separatorsToUnix(aMasterFilePath.normalize().toString());
|
||
|
||
String clientFilePathStr = clientDirecory.getAbsolutePath() + "/"
|
||
+ masterFileName.replaceFirst(pMasterFilePathPattern, pClientFilePathPattern);
|
||
Path clientFilePath = Path.of(clientFilePathStr);
|
||
String clientDirString = null;
|
||
|
||
if (clientFilePath.isAbsolute()) {
|
||
clientDirString = clientFilePath.getParent().toString();
|
||
} else {
|
||
// client file is relative expect it is same directory as master
|
||
Path dirPath = aMasterFilePath.getParent();
|
||
|
||
clientDirString = "same directory as 1st file";
|
||
clientFilePath = dirPath.resolve(clientFilePath);
|
||
}
|
||
|
||
if (clientFilePath != null) {
|
||
String fileName = clientFilePath.getFileName().toString();
|
||
clientFileLabel
|
||
.setText(String.format("<html>Selected: %s<br>in: %s</html>", fileName, clientDirString));
|
||
selectClientFile.setEnabled(true);
|
||
}
|
||
|
||
String keyFieldString = pConfig.getProperty("list_of_keys");
|
||
|
||
List<String> keyFields = LcagStringTools.asList(keyFieldString, ",\\s*");
|
||
|
||
if (aMasterFilePath != null && clientFilePath != null) {
|
||
|
||
try {
|
||
Path resultFilePath = LcagFileTools.appendStringToFilePath(aMasterFilePath, "-merged");
|
||
String fieldMapping = pConfig.getProperty("column.mapping.main2compare");
|
||
|
||
Files.copy(aMasterFilePath, resultFilePath, StandardCopyOption.REPLACE_EXISTING);
|
||
|
||
ExcelWorkbook excel1 = new ExcelWorkbook(resultFilePath.toString());
|
||
ExcelWorkbook excel2 = new ExcelWorkbook(clientFilePath.toString());
|
||
|
||
excel1.setKeyColumns(keyFields);
|
||
excel1.read();
|
||
excel2.setKeyColumns(keyFields);
|
||
excel2.read();
|
||
|
||
excel1.setOption(keyFieldString, FRAME_HEIGHT);
|
||
|
||
if (fieldMapping != null) {
|
||
MappingTable mappingTable = new MappingTable(fieldMapping, ";", "->");
|
||
|
||
excel2.setOption(Table.OPTION_USE_MAPPING, mappingTable);
|
||
}
|
||
|
||
WorkbookComparisonResult compareResult = excel1.compareTo(excel2);
|
||
|
||
if (compareResult.tablesAreEquals()) {
|
||
System.out.printf("RESULT: Tables %s and %s are equal.\n", resultFilePath, clientFilePath);
|
||
} else {
|
||
ExcelWorkbook integratedTable = (ExcelWorkbook) compareResult.integrateDifferencesIntoMaster();
|
||
|
||
integratedTable.save();
|
||
|
||
Desktop.getDesktop().open(resultFilePath.toFile());
|
||
}
|
||
} catch (IOException ex) {
|
||
JOptionPane.showMessageDialog(this, "Cannot open comparison result file.", "Error",
|
||
JOptionPane.ERROR_MESSAGE);
|
||
} catch (ConfigurationException e) {
|
||
// TODO Auto-generated catch block
|
||
e.printStackTrace();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private Path getPath(LcagProperties config, String pProperty, File pMasterFile) {
|
||
Path result = null;
|
||
String filePathString = (pMasterFile == null) ? config.getProperty(pProperty) : pMasterFile.getAbsolutePath();
|
||
|
||
if (!LcagStringTools.isEmpty(filePathString)) {
|
||
result = Path.of(filePathString);
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
private Path renameFile(String pFile, JLabel label, String prefix) {
|
||
Path newPath = null;
|
||
if (pFile == null)
|
||
return newPath;
|
||
|
||
File file = new File(pFile.toString());
|
||
String newName = JOptionPane.showInputDialog(this, "Enter new name:", file.getName());
|
||
|
||
if (!LcagStringTools.isEmpty(newName)) {
|
||
Path filePath = Path.of(pFile);
|
||
newPath = filePath.getParent().resolve(newName);
|
||
|
||
File newFile = new File(newPath.toString());
|
||
if (file.renameTo(newFile)) {
|
||
file = newFile;
|
||
label.setText(prefix + ": " + newFile.getName());
|
||
if (prefix.equals("Datei 1"))
|
||
this.masterFile = newPath.toString();
|
||
else
|
||
this.clientFile = newPath.toString();
|
||
} else {
|
||
JOptionPane.showMessageDialog(this, "Umbenennung fehlgeschlagen!", "Fehler", JOptionPane.ERROR_MESSAGE);
|
||
}
|
||
}
|
||
|
||
return newPath;
|
||
}
|
||
|
||
public static void main(String[] args) {
|
||
String cfgFileDirectory = args.length < 1 ? System.getenv("_MY_DATA") + "/Tools" : args[0];
|
||
|
||
SwingUtilities.invokeLater(() -> {
|
||
FileActions gui = new FileActions();
|
||
|
||
gui.configFileDirectoryPath = new File(cfgFileDirectory);
|
||
gui.setVisible(true);
|
||
});
|
||
}
|
||
}
|