/* * Zettelkasten - nach Luhmann * Copyright (C) 2001-2015 by Daniel Lüdecke (http://www.danielluedecke.de) * * Homepage: http://zettelkasten.danielluedecke.de * * * This program is free software; you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; either version 3 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with this program; * if not, see <http://www.gnu.org/licenses/>. * * * Dieses Programm ist freie Software. Sie können es unter den Bedingungen der GNU * General Public License, wie von der Free Software Foundation veröffentlicht, weitergeben * und/oder modifizieren, entweder gemäß Version 3 der Lizenz oder (wenn Sie möchten) * jeder späteren Version. * * Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, daß es Ihnen von Nutzen sein * wird, aber OHNE IRGENDEINE GARANTIE, sogar ohne die implizite Garantie der MARKTREIFE oder * der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK. Details finden Sie in der * GNU General Public License. * * Sie sollten ein Exemplar der GNU General Public License zusammen mit diesem Programm * erhalten haben. Falls nicht, siehe <http://www.gnu.org/licenses/>. */ package de.danielluedecke.zettelkasten.util; import de.danielluedecke.zettelkasten.database.Daten; import de.danielluedecke.zettelkasten.database.Settings; import java.awt.FileDialog; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.logging.Level; import javax.swing.DefaultListModel; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.filechooser.FileFilter; /** * * @author Luedeke */ public class FileOperationsUtil { /** * create a variable for a list model. this list model is used for the * JList-component which displays the links of the current entry. */ private static DefaultListModel linkListModel = new DefaultListModel(); public static DefaultListModel getListModel() { return linkListModel; } private static String[] addedAttachments = null; public static String[] getAddedAttachments() { return addedAttachments; } /** * This method creates a backup-filepath by adding the extension * <b>.backup</b> to the filepath given in {@code sourcefile}. In case this * filepath already exists, this method tries to use a new extension, until * a non-existing filepath was created.<br><br> * Results might be:<br> * <i>sourcefile.ext.backup</i><br> * <i>sourcefile.ext.backup-1</i><br> * <i>sourcefile.ext.backup-2</i><br> * and so on... * * @param sourcefile the filepath of the source-file that should be backed * up * @return a filepath-value with a non-existing backup-extenstion. */ public static File getBackupFilePath(File sourcefile) { // find correct extension. we use this in case we already // have several backups... // in case the user already created a backup, we concatenate a trainling // backup-counter-number to avoid overwriting existing backup-files // we start with a "1" int backupcounter = 1; String backupext = ".backup"; File checkbackup = new File(sourcefile.toString() + backupext); while (checkbackup.exists()) { backupcounter++; backupext = ".backup-" + String.valueOf(backupcounter); checkbackup = new File(sourcefile.toString() + backupext); } return checkbackup; } /** * Creates a mac-aqua-like file dialog. Since the typical OS X dialog can * not be created using the swing file chooser, we use the awt-FileDialog * instead to get mac-like-look'n'feel. * * @param fc a reference to a FileDialog that should be initiated. * @param dlgmode either {@code FileDialog.LOAD} or {@code FileDialog.SAVE} * @param initdir the initial directory which can be set when the dialog is * shown * @param initfile the initial file which can be selected when the dialog is * shown * @param title the dialog's title * @param acceptedext the accepted file extensions that will be accepted, * i.e. the files that are selectable * @return a reference to the created <i>and initiated</i> FileDialog which * was passed as parameter {@code fc}. */ static FileDialog getMacFileDialog(FileDialog fc, int dlgmode, String initdir, String initfile, String title, final String[] acceptedext) { fc.setTitle(title); fc.setMode(dlgmode); fc.setDirectory(initdir); fc.setFile(initfile); fc.setFilenameFilter(new FilenameFilter() { @Override public boolean accept(File dir, String name) { if (acceptedext != null && acceptedext.length > 0) { boolean acc = false; for (String ext : acceptedext) { if (name.toLowerCase().endsWith(ext)) { acc = true; } } return acc; } else { return true; } } }); return fc; } /** * * @param f * @param ext * @return */ public static String setFileExtension(File f, String ext) { if (null == f || null == ext || ext.isEmpty()) { return null; } if (!ext.startsWith(".")) { ext = "." + ext; } String s = f.getName(); int i = s.lastIndexOf("."); return s.substring(0, i - 1).concat(ext); } /** * This method creates and shows a file chooser, depending on the operating * system. In case the os is Windows or Linux, the standard * Swing-JFileChooser will be opened. In case the os is Mac OS X, the old * awt-dialog is used, which looks more nativ.<br><br> * When the user chose a file, it will be returned, else {@code null} will * be returned. * * @param parent the parent-frame of the file chooser * @param dlgmode<br> * - in case of Mac OS X: either {@code FileDialog.LOAD} or * {@code FileDialog.SAVE} - else: {@code JFileChooser.OPEN_DIALOG} or * {@code JFileChooser.SAVE_DIALOG} * @param filemode<br> * - not important for Mac OS X. - else: {@code JFileChooser.FILES_ONLY} or * the other file-selection-mode-values * @param initdir the initial directory which can be set when the dialog is * shown * @param initfile the initial file which can be selected when the dialog is * shown * @param title the dialog's title * @param acceptedext the accepted file extensions that will be accepted, * i.e. the files that are selectable * @param desc the description of which file types the extensions are * @param settings a reference to the CSettings-class * @return The chosen file, or {@code null} if dialog was cancelled */ public static File chooseFile(java.awt.Frame parent, int dlgmode, int filemode, String initdir, String initfile, String title, final String[] acceptedext, final String desc, Settings settings) { if (!settings.isMacAqua()) { File curdir = (null == initdir) ? null : new File(initdir); JFileChooser fc = createFileChooser(title, filemode, curdir, acceptedext, desc); int option = (JFileChooser.OPEN_DIALOG == dlgmode) ? fc.showOpenDialog(parent) : fc.showSaveDialog(parent); if (JFileChooser.APPROVE_OPTION == option) { return fc.getSelectedFile(); } } else { FileDialog fd = getMacFileDialog(new FileDialog(parent), dlgmode, initdir, initfile, title, acceptedext); fd.setVisible(true); String file = fd.getFile(); if (file != null) { return new File(fd.getDirectory() + fd.getFile()); } } return null; } /** * This method creates and shows a file chooser, depending on the operating * system. In case the os is Windows or Linux, the standard * Swing-JFileChooser will be opened. In case the os is Mac OS X, the old * awt-dialog is used, which looks more nativ.<br><br> * When the user chose a file, it will be returned, else {@code null} will * be returned. * * @param parent the parent-dialog of the file chooser * @param dlgmode<br> * - in case of Mac OS X: either {@code FileDialog.LOAD} or * {@code FileDialog.SAVE} - else: {@code JFileChooser.OPEN_DIALOG} or * {@code JFileChooser.SAVE_DIALOG} * @param filemode<br> * - not important for Mac OS X. - else: {@code JFileChooser.FILES_ONLY} or * the other file-selection-mode-values * @param initdir the initial directory which can be set when the dialog is * shown * @param initfile the initial file which can be selected when the dialog is * shown * @param title the dialog's title * @param acceptedext the accepted file extensions that will be accepted, * i.e. the files that are selectable * @param desc the description of which file types the extensions are * @param settings a reference to the CSettings-class * @return The chosen file, or {@code null} if dialog was cancelled */ public static File chooseFile(java.awt.Dialog parent, int dlgmode, int filemode, String initdir, String initfile, String title, final String[] acceptedext, final String desc, Settings settings) { if (!settings.isMacAqua()) { File curdir = (null == initdir) ? null : new File(initdir); JFileChooser fc = createFileChooser(title, filemode, curdir, acceptedext, desc); int option = (JFileChooser.OPEN_DIALOG == dlgmode) ? fc.showOpenDialog(parent) : fc.showSaveDialog(parent); if (JFileChooser.APPROVE_OPTION == option) { return fc.getSelectedFile(); } } else { FileDialog fd = getMacFileDialog(new FileDialog(parent), dlgmode, initdir, initfile, title, acceptedext); fd.setVisible(true); String file = fd.getFile(); if (file != null) { return new File(fd.getDirectory() + fd.getFile()); } } return null; } /** * This method returns the file extension of a given file which is passed as * parameter. * * @param f the file which extension should be retrieved * @return the extension of the given file, <b>without</b> leading period * (e.g. "jpg" is returned, not ".jpg") */ public static String getFileExtension(File f) { if (null == f) { return ""; } String ext = null; String s = f.getName(); int i = s.lastIndexOf("."); if (i > 0 && i < s.length() - 1) { ext = s.substring(i + 1).toLowerCase(); } return ext; } /** * This method returns the file extension of a given file passed as * string-parameter. * * @param settingsObj * @param dataObj * @param f the file which extension should be retrieved * @return the extension of the given file, <b>without</b> leading period * (e.g. "jpg" is returned, not ".jpg"), in upper case letters. */ public static String getFileExtension(Settings settingsObj, Daten dataObj, String f) { String ext = ""; if (isHyperlink(f)) { return "URL"; } f = getLinkFile(settingsObj, dataObj, f).toString(); if (!new File(f).exists()) { return ""; } int i = f.lastIndexOf("."); if (i > 0 && i < f.length() - 1) { ext = f.substring(i + 1).toUpperCase(); } return ext; } /** * This method returns the file name of a given file-path which is passed as * parameter. * * @param f the filepath of the file which file name should be retrieved * @return the name of the given file, excluding extension, or {@code null} * if an error occured. */ public static String getFileName(String f) { String fn = null; int i = f.lastIndexOf(String.valueOf(File.separatorChar)); if (i != -1) { int j = f.lastIndexOf("."); if (j != -1) { try { fn = f.substring(i + 1, j); } catch (IndexOutOfBoundsException ex) { return null; } } } return fn; } /** * This method returns the file path only of a given file which is passed as * parameter, <em>excluding the file name</em>. * * @param f the filepath of the file which should be cleaned from file name * @return the path of the given file, excluding file name, or an empty * string if an error occured. */ public static String getFilePath(String f) { String fn = ""; int i = f.lastIndexOf(String.valueOf(File.separatorChar)); if (i != -1) { try { fn = f.substring(0, i); } catch (IndexOutOfBoundsException ex) { return ""; } } return fn; } /** * This method returns the file path only of a given file which is passed as * parameter, <em>excluding the file name</em>. * * @param f the filepath of the file which should be cleaned from file name * @return the path of the given file, excluding file name, or an empty * string if an error occured. */ public static String getFilePath(File f) { try { return getFilePath(f.getCanonicalPath()); } catch (IOException ex) { return ""; } } /** * This method returns the file name of a given file-path which is passed as * parameter. * * @param f the filepath of the file which file name should be retrieved * @return the name of the given file, excluding extension, or {@code null} * if an error occured. */ public static String getFileName(File f) { if (f != null) { String fname = f.getName(); int extpos = fname.lastIndexOf("."); if (extpos != -1) { try { return fname.substring(0, extpos); } catch (IndexOutOfBoundsException ex) { return null; } } } return null; } /** * This method copies a file. check for existing files is not done here, * needs to be checked from within the method which calls this method. * * @param src the source file that should be copied * @param dest the destination filename and path * @param bufSize the buffer size * @throws IOException */ public static void copyFile(File src, File dest, int bufSize) throws IOException { byte[] buffer = new byte[bufSize]; InputStream in = null; OutputStream out = null; try { in = new FileInputStream(src); out = new FileOutputStream(dest); while (true) { int read = in.read(buffer); if (read == -1) { break; } out.write(buffer, 0, read); } } catch (IOException | NullPointerException e) { } finally { try { if (in != null) { in.close(); } if (out != null) { out.close(); } } catch (IOException e) { } } } /** * This merthod creates a FileChooser Dialog, initiates it (based on the * passed parameters) and returns a reference to the FileChooser Dialog. * * @param name the file dialog's title * @param filemode {@code JFileChooser.FILES_ONLY} or the other * file-selection-mode-values (not important for Mac OS X) * @param curdir the initial directory which can be set when the dialog is * shown * @param acceptedext the accepted file extensions that will be accepted, * i.e. the files that are selectable * @param desc the description of which file types the extensions are * @return a reference to a new created file chooser */ public static JFileChooser createFileChooser(String name, int filemode, File curdir, final String[] acceptedext, final String desc) { JFileChooser fc = new JFileChooser(); fc.setDialogTitle(name); fc.setAcceptAllFileFilterUsed(false); fc.setCurrentDirectory(curdir); fc.setFileSelectionMode(filemode); if (null == acceptedext || acceptedext.length < 1) { fc.setAcceptAllFileFilterUsed(true); } else { fc.setFileFilter(new FileFilter() { @Override public boolean accept(File f) { if (f.isDirectory()) { return true; } // set file extensions in the file dialog according // to user's choice of import type // other accepted files are located in the resource map boolean retval = false; String fileext = "." + getFileExtension(f); if (acceptedext != null && acceptedext.length > 0) { for (String ext : acceptedext) { if (fileext.equals(ext.toLowerCase())) { retval = true; } } } return retval; } @Override public String getDescription() { return desc; } }); } return fc; } /** * A directory-chooser for choosing directories (when file-selecting should * be restricted). * * @param name the dialog's title * @param desc the locale for "folders" * @param curdir the initial directory to be set * @return the selected directory as File-variable, or {@code null} if user * cancels the dialog */ public static File chooseDirectory(String name, final String desc, File curdir) { JFileChooser fc = new JFileChooser(); fc.setDialogTitle(name); fc.setAcceptAllFileFilterUsed(false); fc.setCurrentDirectory(curdir); fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); fc.setFileFilter(new FileFilter() { @Override public boolean accept(File f) { return f.isDirectory(); } @Override public String getDescription() { return desc; } }); int option = fc.showOpenDialog(null); if (JFileChooser.APPROVE_OPTION == option) { return fc.getSelectedFile(); } return null; } public static boolean insertAttachments(Daten dataObj, Settings settingsObj, JFrame parentFrame, File[] sources, DefaultListModel lm) { org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(de.danielluedecke.zettelkasten.ZettelkastenApp.class). getContext().getResourceMap(FileOperationsUtil.class); if (lm != null) { linkListModel = lm; } else { linkListModel = new DefaultListModel(); } List<String> addedValues = new ArrayList<>(); // modified tag boolean modified = false; // declare constants for moving/copying files // files should be copied final int ATT_COPY = 0; // files should be moved final int ATT_MOVE = 1; // files should remain in their original folder final int ATT_REMAIN = 2; // action should be cancelled final int ATT_CANCEL = 3; // declare constants for renaming/keeping files // files should be renamed final int ATT_RENAME = 0; // existing attachment file should be used final int ATT_USE_EXISTING = 1; // action should be cancelled final int ATT_CANCEL_RENAME = 2; // check whether we already have a saved data file or not. if not, we have no related // path for the subdirectory "img", thus we cannot copy the images if (null == settingsObj.getFilePath() || !settingsObj.getFilePath().exists()) { // display error message box JOptionPane.showMessageDialog(parentFrame, resourceMap.getString("noDataFileSavedMsg"), resourceMap.getString("noDataFileSavedTitle"), JOptionPane.PLAIN_MESSAGE); return false; } // retrieve the application's directory and add an "/img/" as subfolder for images // and append the file name of the image file. we need this string already now for the // message box to tell the user where the file will be copied to. String destdir = settingsObj.getAttachmentPath(dataObj.getUserAttachmentPath(), true); // create new linked list that will contain a "cleaned" list of files, i.e. only contains // those selected files that haven't been copied to the attachment directory yet. LinkedList<File> newfiles = new LinkedList<>(); // iterate array for (File cf : sources) { // first off all, let's check whether the user chose an already existing attachment-file // which already has been copied to the application's attachment directory. if so, no // new copy operation is needed, thus we *exclude* that file from the copy-list, // but already *include* it to the jList with attachments... // if the source file does not start with the same string part as the application's // applications directory, we assume that the attachment has not been copied to that directory yet. if (!cf.toString().startsWith(destdir)) { newfiles.add(cf); } else { // remove first part of the file-path, so we have the related path // to the attachment left String remainingpath = cf.toString().substring(destdir.length()); // add attachment-value to list linkListModel.addElement(remainingpath); addedValues.add(remainingpath); // set the modified state modified = true; } } // if we don't have any new files that haven't been copied to the attachment-directory before, // we can leave the method now... if (newfiles.size() < 1) { return modified; } // else create new array with files to be copied. sources = newfiles.toArray(new File[newfiles.size()]); // create a JOptionPane with moce/copy/cancel options int msgOption = JOptionPane.showOptionDialog(parentFrame, resourceMap.getString("msgConfirmAttachmentCopyMsg", destdir), resourceMap.getString("msgConfirmAttachmentCopyTitle"), JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, new Object[]{ resourceMap.getString("optionFileCopy"), resourceMap.getString("optionFileMove"), resourceMap.getString("optionFileRemain"), resourceMap.getString("optionFileCancel"),}, resourceMap.getString("optioneFileCopy")); // if the user wants to proceed, copy the image now if (ATT_COPY == msgOption || ATT_MOVE == msgOption) { // first, check whether we already have an attachment directory // create the file-object with the necessary directory path File attachmentdir = new File(destdir); // if the directory does not exist, create it if (!attachmentdir.exists()) { // create directory try { if (!attachmentdir.mkdir()) { // if it fails, show warning message and leave method // create a message string including the filepath of the directory // which could not be created JOptionPane.showMessageDialog(parentFrame, resourceMap.getString("errMsgCreateAttDirMsg", attachmentdir), resourceMap.getString("errMsgCreateDirTitle"), JOptionPane.PLAIN_MESSAGE); return false; } } catch (SecurityException e) { Constants.zknlogger.log(Level.SEVERE, e.getLocalizedMessage()); // if it fails, show warning message and leave method // create a message string including the filepath of the directory // which could not be created JOptionPane.showMessageDialog(parentFrame, resourceMap.getString("errMsgCreateAttDirMsg", attachmentdir), resourceMap.getString("errMsgCreateDirTitle"), JOptionPane.PLAIN_MESSAGE); return false; } } // go through all selected files for (File f : sources) { // store the fileextension for later use, see below String fileextension = FileOperationsUtil.getFileExtension(f); // create a string to replace german umlauts // we have to do this because it seems like the Java desktop-api // is buggy. Files with umlauts in their names or paths cannot be // opend by the desktop-api, although their path is correct String withoutumlauts = f.getName(); // replace umlauts with normal alphabetical letters withoutumlauts = withoutumlauts.replace("ä", "ae") .replace("Ä", "Ae") .replace("ö", "oe") .replace("Ö", "Oe") .replace("ü", "ue") .replace("Ü", "Ue") .replace("ß", "ss") .replace("\"", ""); // create destionation file File dest = new File(destdir + withoutumlauts); // create loop-indicator boolean dest_ok = false; // indicator whether further action is needed boolean copyneeded = true; // check whether the file exists. if yes, the user should enter another name while (!dest_ok) { // check whether file exists if (dest.exists()) { // tell user that file exist and ask whether file should be renamed, or // existing file should be used as value // create a JOptionPane with rename/use exiting file options int msgOpt = JOptionPane.showOptionDialog(parentFrame, resourceMap.getString("msgFileExistsChoice"), resourceMap.getString("msgFileExistsChoiceTitle"), JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, new Object[]{ resourceMap.getString("optionFileRename"), resourceMap.getString("optionFileUseExisting"), resourceMap.getString("optionFileCancel"),}, resourceMap.getString("optionFileUseExisting")); // if action cancelled, quit if (ATT_CANCEL_RENAME == msgOpt) { return false; } // if existing attachment should be used, do this here if (ATT_USE_EXISTING == msgOpt) { // add copied/moves file to link list... linkListModel.addElement((String) dest.getName()); addedValues.add((String) dest.getName()); // set the modified state modified = true; // indicate that while-loop is over, destination is valid dest_ok = true; // no more copying needed copyneeded = false; } else if (ATT_RENAME == msgOpt) { // open an option dialog and let the user prompt a new filename Object fnobject = JOptionPane.showInputDialog(parentFrame, resourceMap.getString("msgFileExists"), resourceMap.getString("msgFileExistsTitle"), JOptionPane.PLAIN_MESSAGE, null, null, dest.getName()); // if the user cancelled the dialog, quit method if (null == fnobject) { return false; } // else copy object to string String newfilename = fnobject.toString(); // check whether the user just typed in a name without extension // if so, add extension here if (!newfilename.endsWith("." + fileextension)) { newfilename = newfilename.concat("." + fileextension); } // and create a new file dest = new File(destdir + newfilename); } } else { // indicate that while-loop is over, destination is valid dest_ok = true; } } if (copyneeded) { try { // here we go when the user wants to *copy* the files if (ATT_COPY == msgOption) { // create and copy file... dest.createNewFile(); // if we have a file which does not already exist, copy the source to the dest FileOperationsUtil.copyFile(f, dest, 1024); } // here we go when the user wants to *move* the files else if (ATT_MOVE == msgOption) { // if moving the file failed... if (!f.renameTo(dest)) { // ... show error msg JOptionPane.showMessageDialog(parentFrame, resourceMap.getString("errMsgFileMove"), resourceMap.getString("errMsgFileMoveTitle"), JOptionPane.PLAIN_MESSAGE); } } // add copied/moves file to link list... linkListModel.addElement((String) dest.getName()); addedValues.add((String) dest.getName()); // set the modified state modified = true; // set new default directory settingsObj.setLastOpenedAttachmentDir(f); } catch (IOException ex) { Constants.zknlogger.log(Level.SEVERE, ex.getLocalizedMessage()); JOptionPane.showMessageDialog(parentFrame, resourceMap.getString("errMsgFileCopy"), resourceMap.getString("errMsgFileCopyTitle"), JOptionPane.PLAIN_MESSAGE); } } } } else if (ATT_CANCEL == msgOption) { // do nothing... } else if (ATT_REMAIN == msgOption) { // else add the text to the keyword-list (JList) for (File f : sources) { linkListModel.addElement((String) f.toString()); addedValues.add((String) f.toString()); // set new default directory settingsObj.setLastOpenedAttachmentDir(f); } // set the modified state modified = true; } // convert list to string array addedAttachments = addedValues.toArray(new String[addedValues.size()]); return modified; } /** * This methods returns the path to an entry's attachment-file, which is * passed as paraneter {@code linktye}. It creates an absolute path out from * a relative path if necessray, which e.g. occures when having * entry-attachments. * * @param settingsObj a reference to the CSettings-class * @param dataObj * @param linktype a hyperlink-file, which is received when the user clicks * on a hyperlink or linked attachment in e jEditorPane * @return the absolute filepath to the linked file */ public static File getLinkFile(Settings settingsObj, Daten dataObj, String linktype) { File linkfile = new File(linktype); if (!linkfile.exists()) { String sepchar = String.valueOf(File.separatorChar); if (linkfile.toString().startsWith(sepchar)) { sepchar = ""; } linkfile = new File(settingsObj.getAttachmentPath(dataObj.getUserAttachmentPath(), false) + sepchar + linkfile.toString()); if (!linkfile.exists()) { try { linkfile = new File(linkfile.getCanonicalPath()); if (!linkfile.exists()) { linkfile = new File(linktype); File zknp = settingsObj.getBaseDir(); if (null == zknp) { zknp = new File(new File("").getAbsolutePath()); } if (linkfile.toString().startsWith(sepchar)) { sepchar = ""; } linkfile = new File(zknp.toString() + sepchar + linkfile.toString()); if (!linkfile.exists()) { linkfile = new File(linkfile.getCanonicalPath()); } } } catch (IOException | SecurityException ex) { } } } return linkfile; } /** * This method checks whether the file's {@code imgfile} extenstion is * corresponding to an image file, i.e. whether the file extension equals * one of the most common image formats. * * @param imgfile the file which extension should be checked * @return {@code true} if the the file seems to be an image, {@code false} * otherwise. */ public static boolean isImageFile(File imgfile) { boolean retval; String ext = FileOperationsUtil.getFileExtension(imgfile); retval = ext.equalsIgnoreCase("jpg") | ext.equalsIgnoreCase("png") | ext.equalsIgnoreCase("bmp") | ext.equalsIgnoreCase("tif") | ext.equalsIgnoreCase("tiff") | ext.equalsIgnoreCase("gif") | ext.equalsIgnoreCase("jpeg") | ext.equalsIgnoreCase("tga"); return retval; } /** * This method retrieves a complete formtag, extracts the information and * converts the tag into the related image-path, which can be used for * including the related form-image (which is stored as image-file in the * subdirectory {@code Constants.FORMIMAGEPATH_SUBDIR}. * * @param formtag the form-tag, which contains the form-data in UBB-format * @param addFileExtension * @param addLargeAppendix * @return a string containing the file-name of the related form-image that * represents the graphical darstellung of the form-tag, or an empty string * if an error occured. */ public static String convertFormtagToImagepath(String formtag, boolean addFileExtension, boolean addLargeAppendix) { String imgpath = ""; if (formtag != null && !formtag.isEmpty()) { formtag = formtag.replace(" ", "_"); formtag = formtag.replace("=", "_"); formtag = formtag.replace("#", "r"); formtag = formtag.replace("|", "_"); formtag = formtag.replace("^", "__"); formtag = formtag.replace("[", "").replace("]", ""); formtag = formtag.replace("\u00e4", "ae").replace("\u00c4", "Ae").replace("\u00f6", "oe").replace("\u00d6", "Oe").replace("\u00fc", "ue").replace("\u00dc", "Ue").replace("\u00df", "ss").replace("?", "_").replace("\"", ""); imgpath = formtag; if (addLargeAppendix) { imgpath = imgpath + Constants.FORMIMAGE_LARGE_APPENDIX; } if (addFileExtension) { imgpath = imgpath + Constants.FORMIMAGE_EXTENSION; } } return imgpath; } /** * This method checks whether the file's {@code imgfile} extenstion is * corresponding to an image file and whether this image format is supported * by the JEditorPane component. * * @param imgfile the file which extension should be checked * @return {@code true} if the the file seems to be an image which is also * supported to be displayed in a JEditorPane, {@code false} otherwise. */ public static boolean isSupportedImageFile(File imgfile) { // TODO andere Grafikformate später, wenn unterstützt boolean retval; String ext = FileOperationsUtil.getFileExtension(imgfile); retval = ext.equalsIgnoreCase("jpg") | ext.equalsIgnoreCase("png") | ext.equalsIgnoreCase("gif") | ext.equalsIgnoreCase("jpeg"); return retval; } /** * This method checks whether a given string, usually passed as parameter * from the * {@link #eventHyperlinkActivated(javax.swing.event.HyperlinkEvent) eventHyperlinkActivated}, * is a hyperlink or not. this is decided from the prefix, i.e. whether the * string starts with common things like "http:" etc. * * @param linktype the clicked "hyperlink" from the hyperlink-event, as * string * @return {@code true} if the string seems to be a hyperlink, false * otherwise */ public static boolean isHyperlink(String linktype) { return linktype.toLowerCase().startsWith("http://") || linktype.toLowerCase().startsWith("https://") || linktype.toLowerCase().startsWith("ftp://") || linktype.toLowerCase().startsWith("webdav://") || linktype.toLowerCase().startsWith("news:") || linktype.toLowerCase().startsWith("outlook:"); } public static String getZettelkastenDataDir(Settings settings) { return getZettelkastenDataDir(settings, true); } /** * * @param settings * @param addTrailingSeparatorChar * @return */ public static String getZettelkastenDataDir(Settings settings, boolean addTrailingSeparatorChar) { // retrieve path of data file File f = settings.getBaseDir(); // check for valid value if (f != null) { // convert file path to string String path = f.getPath(); // check whether trailing separator should be included or not if (addTrailingSeparatorChar) { path = path.concat(String.valueOf(File.separatorChar)); } // retrieve substring, excluding filename return path; } return null; } /** * * @return */ public static String getWorkingDir() { return System.getProperty("user.dir").concat(String.valueOf(File.separatorChar)); } /** * Retrieve the {@code .Zettelkasten} subdirectory of the user home * directory. * * @return The {@code .Zettelkasten} directory, which is a subdirectory of * the user.home directory, including a trailing separator char * ({@code <user-home>/.Zettelkasten/}). */ public static String getZettelkastenHomeDir() { return getZettelkastenHomeDir(true); } /** * Retrieve the {@code .Zettelkasten} subdirectory of the user home * directory. * * @param addTrailingSeparatorChar if {@code true}, a trailing separator * char is added. * @return The {@code .Zettelkasten} directory, which is a subdirectory of * the user.home directory. */ public static String getZettelkastenHomeDir(boolean addTrailingSeparatorChar) { String fp = System.getProperty("user.home") + File.separatorChar + ".Zettelkasten"; if (addTrailingSeparatorChar) { fp = fp + File.separatorChar; } return fp; } /** * This method removes invalid characters from a file path. * * @param path the (uncleaned) file path, which might contain illegal characters. * @return a cleaned path as {@code String} value, with illegal characters removed. */ public static String getCleanFilePath(String path) { return path.replaceAll("[^a-zA-ZäöüÄÖÜß0-9.-]", "_"); } }