AppleCommander/app/cli-acx/src/main/java/io/github/applecommander/acx/fileutil/FileUtils.java

121 lines
4.6 KiB
Java

/*
* AppleCommander - An Apple ][ image utility.
* Copyright (C) 2019-2022 by Robert Greene and others
* robgreene at users.sourceforge.net
*
* 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 2 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, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package io.github.applecommander.acx.fileutil;
import java.util.Optional;
import java.util.logging.Logger;
import com.webcodepro.applecommander.storage.DirectoryEntry;
import com.webcodepro.applecommander.storage.DiskException;
import com.webcodepro.applecommander.storage.FileEntry;
import io.github.applecommander.acx.command.CopyFileCommand;
public class FileUtils {
private static Logger LOG = Logger.getLogger(CopyFileCommand.class.getName());
private boolean overwrite;
public FileUtils(boolean overwrite) {
this.overwrite = overwrite;
}
public void copy(DirectoryEntry directory, FileEntry file) throws DiskException {
LOG.fine(() -> String.format("Copying '%s'", file.getFilename()));
if (file.isDeleted()) {
// Skip deleted files
}
else if (file.isDirectory()) {
copyDirectory(directory, (DirectoryEntry)file, file.getFilename());
}
else {
copyFile(directory, file);
}
}
void copyDirectory(DirectoryEntry targetParent, DirectoryEntry sourceDir, String name) throws DiskException {
Optional<FileEntry> targetFile = targetParent.getFiles()
.stream()
.filter(fileEntry -> name.equals(fileEntry.getFilename()))
.findFirst();
Optional<DirectoryEntry> targetDir = targetFile
.filter(FileEntry::isDirectory)
.map(DirectoryEntry.class::cast);
if (targetDir.isPresent()) {
// Fall through to general logic
}
else if (targetFile.isPresent()) {
// This is an abstract class, so faking it for now.
throw new DiskException("Unable to create directory", name) {
private static final long serialVersionUID = 4726414295404986677L;
};
}
else {
targetDir = Optional.of(targetParent.createDirectory(name));
}
for (FileEntry fileEntry : sourceDir.getFiles()) {
copy(targetDir.get(), fileEntry);
}
}
void copyFile(DirectoryEntry directory, FileEntry sourceFile) throws DiskException {
FileEntryReader source = FileEntryReader.get(sourceFile);
copyFile(directory, source);
}
public void copyFile(DirectoryEntry directory, FileEntryReader source) throws DiskException {
String sourceName = source.getFilename().get();
String sanitizedName = directory.getFormattedDisk().getSuggestedFilename(sourceName);
final Optional<FileEntry> fileEntry = directory.getFiles().stream()
.filter(entry -> entry.getFilename().equals(sanitizedName))
.findFirst();
final FileEntry targetFile;
if (fileEntry.isPresent()) {
targetFile = fileEntry
.filter(entry -> overwrite)
.orElseThrow(() -> new RuntimeException(String.format("File '%s' exists.",
source.getFilename().get())));
}
else {
targetFile = directory.createFile();
}
FileEntryWriter target = FileEntryWriter.get(targetFile);
source.getFilename().ifPresent(target::setFilename);
source.getProdosFiletype().ifPresent(target::setProdosFiletype);
source.isLocked().ifPresent(target::setLocked);
source.getBinaryAddress().ifPresent(target::setBinaryAddress);
source.getBinaryLength().ifPresent(target::setBinaryLength);
source.getAuxiliaryType().ifPresent(target::setAuxiliaryType);
source.getCreationDate().ifPresent(target::setCreationDate);
source.getLastModificationDate().ifPresent(target::setLastModificationDate);
if (source.getFileData().isPresent() && source.getResourceData().isPresent()) {
target.setFileData(source.getFileData().get(), source.getResourceData().get());
} else {
source.getFileData().ifPresent(target::setFileData);
}
}
}