/*
This file is part of RouteConverter.
RouteConverter 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.
RouteConverter 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 RouteConverter; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Copyright (C) 2007 Christian Pesch. All Rights Reserved.
*/
package slash.navigation.routes.local;
import slash.common.io.FileFileFilter;
import slash.common.io.WindowsShortcut;
import slash.navigation.rest.exception.DuplicateNameException;
import slash.navigation.rest.exception.ForbiddenException;
import slash.navigation.routes.Category;
import slash.navigation.routes.Route;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import static java.io.File.separator;
import static java.lang.String.format;
import static org.apache.commons.io.IOUtils.copyLarge;
import static slash.common.io.Files.recursiveDelete;
import static slash.common.io.Files.removeExtension;
import static slash.common.io.InputOutput.DEFAULT_BUFFER_SIZE;
import static slash.common.io.Transfer.UTF8_ENCODING;
import static slash.common.io.Transfer.encodeFileName;
import static slash.common.io.WindowsShortcut.isPotentialValidLink;
/**
* Represents a category in the file system.
*
* @author Christian Pesch
*/
public class LocalCategory implements Category {
private final LocalCatalog catalog;
private File directory;
public LocalCategory(LocalCatalog catalog, File directory) {
this.catalog = catalog;
this.directory = directory;
}
public String getHref() {
try {
return directory.toURI().toURL().toString();
} catch (MalformedURLException e) {
throw new IllegalStateException(format("Cannot create URL for %s", directory));
}
}
public String getName() throws IOException {
return directory.getName();
}
public List<Category> getCategories() throws IOException {
List<Category> categories = new ArrayList<>();
File[] directories = directory.listFiles(new DirectoryFileFilter());
if(directories != null) {
for (File subDirectory : directories) {
if (isPotentialValidLink(subDirectory)) {
WindowsShortcut shortcut = new WindowsShortcut(subDirectory);
if (shortcut.isDirectory()) {
subDirectory = new File(removeExtension(shortcut.getRealFilename()));
} else
continue;
}
categories.add(new LocalCategory(catalog, subDirectory));
}
}
return categories;
}
public Category create(String name) throws IOException {
if (name.contains("/") || name.contains(separator))
throw new ForbiddenException(format("Cannot have slashes in name %s", name), getHref());
File subDirectory = new File(directory, encodeFileName(name));
if (subDirectory.exists())
throw new DuplicateNameException(format("%s %s already exists", subDirectory.isDirectory() ? "Category" : "Route", name), subDirectory.getAbsolutePath());
if (!subDirectory.mkdir())
throw new IOException(format("Cannot create category %s", subDirectory));
return new LocalCategory(catalog, subDirectory);
}
public void update(Category parent, String name) throws IOException {
File newParent;
String newName = encodeFileName(name);
try {
newParent = parent != null ? new File(new URL(parent.getHref()).toURI()) : directory.getParentFile();
} catch (URISyntaxException e) {
throw new IOException(format("Cannot rename %s for %s and %s", directory, parent, name));
}
File newDirectory = new File(newParent, newName);
if (!directory.renameTo(newDirectory))
throw new IOException(format("Cannot rename %s to %s", directory, newDirectory));
this.directory = newDirectory;
}
public void delete() throws IOException {
recursiveDelete(directory);
}
public List<Route> getRoutes() throws IOException {
List<Route> routes = new ArrayList<>();
File[] files = directory.listFiles(new FileFileFilter());
if(files != null) {
for (File file : files) {
if (isPotentialValidLink(file)) {
WindowsShortcut shortcut = new WindowsShortcut(file);
if (shortcut.isFile())
file = new File(shortcut.getRealFilename());
else
continue;
}
routes.add(new LocalRoute(file));
}
}
return routes;
}
public Route createRoute(String description, File localFile) throws IOException {
File destination = new File(directory, encodeFileName(description));
try (InputStream inputStream = new FileInputStream(localFile); OutputStream outputStream = new FileOutputStream(destination)) {
copyLarge(inputStream, outputStream, new byte[DEFAULT_BUFFER_SIZE]);
}
return new LocalRoute(destination);
}
public Route createRoute(String description, String url) throws IOException {
File destination = new File(directory, encodeFileName(description));
try (PrintWriter writer = new PrintWriter(destination, UTF8_ENCODING)) {
writer.println("[InternetShortcut]");
writer.println("URL=" + url);
}
return new LocalRoute(destination);
}
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
LocalCategory that = (LocalCategory) o;
return catalog.equals(that.catalog) && directory.equals(that.directory);
}
public int hashCode() {
int result = catalog.hashCode();
result = 31 * result + directory.hashCode();
return result;
}
public String toString() {
return getClass().getSimpleName() + "[directory=" + directory + "]";
}
}