package org.ssssssss.magicapi.adapter.resource; import org.ssssssss.magicapi.adapter.Resource; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public abstract class KeyValueResource implements Resource { protected String separator; protected String path; protected KeyValueResource parent; protected boolean readonly = false; public KeyValueResource(String separator, String path, KeyValueResource parent) { this.separator = separator; this.path = path; this.parent = parent; } public KeyValueResource(String separator, String path, boolean readonly, KeyValueResource parent) { this.separator = separator; this.path = path; this.parent = parent; this.readonly = readonly; } @Override public boolean isDirectory() { return this.path.endsWith(separator); } @Override public final boolean renameTo(Resource resource) { if(resource.name().equalsIgnoreCase(this.name())){ return true; } if (!(resource instanceof KeyValueResource)) { throw new IllegalArgumentException("无法将" + this.getAbsolutePath() + "重命名为:" + resource.getAbsolutePath()); } KeyValueResource targetResource = (KeyValueResource) resource; // 判断移动的是否是文件夹 if (resource.isDirectory()) { Set oldKeys = this.keys(); Map mappings = new HashMap<>(oldKeys.size()); int keyLen = this.path.length(); oldKeys.forEach(oldKey -> mappings.put(oldKey, targetResource.path + oldKey.substring(keyLen))); return renameTo(mappings); } else { return renameTo(Collections.singletonMap(this.path, targetResource.path)); } } @Override public boolean delete() { return this.keys().stream().allMatch(this::deleteByKey); } protected boolean deleteByKey(String key) { return false; } /** * 需要做修改的key,原key: 新key */ protected abstract boolean renameTo(Map renameKeys); @Override public String name() { String name = this.path; if (isDirectory()) { name = this.path.substring(0, name.length() - 1); } int index = name.lastIndexOf(separator); return index > -1 ? name.substring(index + 1) : name; } @Override public Resource getResource(String name) { name = (isDirectory() ? this.path : this.path + separator) + name; return mappedFunction().apply(name); } @Override public Resource getDirectory(String name) { return getResource(name + separator); } @Override public boolean mkdir() { if (!isDirectory()) { this.path += separator; } return write("this is directory"); } @Override public Resource parent() { return this.parent; } @Override public boolean write(byte[] bytes) { return write(new String(bytes, StandardCharsets.UTF_8)); } @Override public List resources() { return keys().stream().map(mappedFunction()).collect(Collectors.toList()); } protected abstract Function mappedFunction(); protected abstract Set keys(); @Override public List dirs() { return resources().stream().filter(Resource::isDirectory).collect(Collectors.toList()); } @Override public List files(String suffix) { return resources().stream().filter(it -> it.name().endsWith(suffix)).collect(Collectors.toList()); } @Override public String getAbsolutePath() { return this.path; } @Override public void processExport(ZipOutputStream zos, String path, Resource directory, List resources, List excludes) throws IOException { for (Resource resource : resources) { String fullName = directory.getAbsolutePath(); if (!fullName.endsWith(separator)) { fullName += separator; } fullName += resource.name(); if (resource.isDirectory()) { fullName += separator; } if (fullName.equals(resource.getAbsolutePath()) && !excludes.contains(resource.name())) { if (resource.isDirectory()) { String newPath = path + resource.name() + "/"; zos.putNextEntry(new ZipEntry(newPath)); zos.closeEntry(); processExport(zos, newPath, resource, resources, excludes); } else { zos.putNextEntry(new ZipEntry(path + resource.name())); zos.write(resource.read()); zos.closeEntry(); } } } } }