diff --git a/SpigotCore_Main/src/de/steamwar/command/TypeUtils.java b/SpigotCore_Main/src/de/steamwar/command/TypeUtils.java index f4db4f9..51a9f57 100644 --- a/SpigotCore_Main/src/de/steamwar/command/TypeUtils.java +++ b/SpigotCore_Main/src/de/steamwar/command/TypeUtils.java @@ -50,7 +50,7 @@ public class TypeUtils { SWCommandUtils.addMapper(SchematicNode.class, new TypeMapper() { @Override public SchematicNode map(CommandSender commandSender, String[] previousArguments, String s) { - return SchematicNode.getNodeFromPath(SteamwarUser.get(((Player) commandSender).getUniqueId()), s); + return SchematicNode.getNodeFromPath(SteamwarUser.get(((Player) commandSender).getUniqueId()), s).orElse(null); } @Override diff --git a/SpigotCore_Main/src/de/steamwar/inventory/SchematicSelector.java b/SpigotCore_Main/src/de/steamwar/inventory/SchematicSelector.java index 0f6ba59..d04b71e 100644 --- a/SpigotCore_Main/src/de/steamwar/inventory/SchematicSelector.java +++ b/SpigotCore_Main/src/de/steamwar/inventory/SchematicSelector.java @@ -20,10 +20,7 @@ package de.steamwar.inventory; import de.steamwar.core.Core; -import de.steamwar.sql.NodeMember; -import de.steamwar.sql.SchematicNode; -import de.steamwar.sql.SchematicType; -import de.steamwar.sql.SteamwarUser; +import de.steamwar.sql.*; import lombok.*; import org.bukkit.Material; import org.bukkit.entity.Player; @@ -241,11 +238,15 @@ public class SchematicSelector { name = name.replace(filter.getName(), Core.MESSAGE.parse("SCHEM_SELECTOR_ITEM_REPLACE", player, filter.getName())); } - SWItem item = new SWItem(m, name, Collections.singletonList(node.isDir() ? (Core.MESSAGE.parse("SCHEM_SELECTOR_DIR", player)) : Core.MESSAGE.parse("SCHEM_SELECTOR_ITEM_LORE_TYPE", player, node.getSchemtype().name())), !node.isDir() && !node.getSchemtype().writeable(), click -> { + String finalName = name; + SWItem item = node.getSchematic().map(schematicNodeSchematic -> + new SWItem(m, finalName, Collections.singletonList(Core.MESSAGE.parse("SCHEM_SELECTOR_ITEM_LORE_TYPE", player, schematicNodeSchematic.getSchemtype().name())), !node.isDir() && !schematicNodeSchematic.getSchemtype().writeable(), click -> { + })).orElseGet(() -> + new SWItem(m, finalName, Collections.singletonList(Core.MESSAGE.parse("SCHEM_SELECTOR_DIR", player)), false, click -> { + })); + node.getSchematic().map(sNode -> sNode.getRank() > 0 ? sNode : null).ifPresent(sNode -> { + item.setLore(Arrays.asList(Core.MESSAGE.parse("SCHEM_SELECTOR_ITEM_LORE_TYPE", player, sNode.getSchemtype().name()), Core.MESSAGE.parse("SCHEM_SELECTOR_RANK", player, sNode.getRank()))); }); - if(!node.isDir() && node.getRank() > 0) { - item.setLore(Arrays.asList(Core.MESSAGE.parse("SCHEM_SELECTOR_ITEM_LORE_TYPE", player, node.getSchemtype().name()), Core.MESSAGE.parse("SCHEM_SELECTOR_RANK", player, node.getRank()))); - } return new SWListInv.SWListEntry<>(item, node); } @@ -387,7 +388,7 @@ public class SchematicSelector { nodes.removeIf(node -> !node.isDir()); } if(target.target == Target.SCHEMATIC_TYPE) { - nodes.removeIf(node -> node.isDir() || !node.getSchemtype().equals(target.type)); + nodes.removeIf(node -> node.getSchematic().map(SchematicNode.SchematicNodeSchematic::getSchemtype).map(type -> type != filter.getType()).orElse(true)); } return nodes; } @@ -406,12 +407,7 @@ public class SchematicSelector { case SCHEMATIC_TYPE: nodes.addAll(SchematicNode.getAccessibleSchematicsOfTypeInParent(user.getId(), target.type.toDB(), parent==null?0:parent.getId())); if(target.rank >= 0) { - nodes.removeIf(node -> { - if(node.isDir()) { - return false; - } - return node.getRank() > target.rank; - }); + nodes.removeIf(node -> node.getSchematic().map(SchematicNode.SchematicNodeSchematic::getRank).map(rank -> rank < target.rank).orElse(true)); } break; default: @@ -425,10 +421,7 @@ public class SchematicSelector { } private static SchematicNode getParent(SchematicNode node) { - if(node.getParent() == null) { - return null; - } - return node.getParentNode(); + return node.getParentNode().orElse(null); } public static SelectorTarget selectSchematic() { @@ -504,7 +497,7 @@ public class SchematicSelector { matches = false; } - if(type != null && (node.isDir() || !node.getSchemtype().equals(type))) { + if(type != null && node.getSchematic().map(SchematicNode.SchematicNodeSchematic::getSchemtype).map(type::equals).orElse(false)) { matches = false; } @@ -536,7 +529,8 @@ public class SchematicSelector { if(o1.isDir() || o2.isDir()) { return Boolean.compare(o1.isDir(), o2.isDir()); } else { - return o1.getSchemtype().name().compareTo(o2.getSchemtype().name()); + // Unclean, but it works + return o1.getSchematic().get().getSchemtype().name().compareTo(o2.getSchematic().get().getSchemtype().name()); } }), LAST_UPDATED(SWItem.getMaterial("WATCH"), "SCHEM_SELECTOR_SORTING_UPDATE", Comparator.comparing(SchematicNode::getLastUpdate)); diff --git a/SpigotCore_Main/src/de/steamwar/sql/CheckedSchematic.java b/SpigotCore_Main/src/de/steamwar/sql/CheckedSchematic.java index 3c19e4e..0f9003b 100644 --- a/SpigotCore_Main/src/de/steamwar/sql/CheckedSchematic.java +++ b/SpigotCore_Main/src/de/steamwar/sql/CheckedSchematic.java @@ -21,6 +21,7 @@ package de.steamwar.sql; import java.sql.Timestamp; import java.util.List; +import java.util.Optional; import java.util.UUID; public class CheckedSchematic { @@ -75,11 +76,11 @@ public class CheckedSchematic { return node; } - public String getSchemName() { - return SchematicNode.getSchematicNode(node).getName(); + public Optional getSchemName() { + return SchematicNode.getSchematicNode(node).map(SchematicNode::getName); } - public int getSchemOwner() { - return SchematicNode.getSchematicNode(node).getId(); + public Optional getSchemOwner() { + return SchematicNode.getSchematicNode(node).map(SchematicNode::getOwner); } } diff --git a/SpigotCore_Main/src/de/steamwar/sql/Provider.java b/SpigotCore_Main/src/de/steamwar/sql/Provider.java index b511a03..2942a62 100644 --- a/SpigotCore_Main/src/de/steamwar/sql/Provider.java +++ b/SpigotCore_Main/src/de/steamwar/sql/Provider.java @@ -24,10 +24,7 @@ import de.steamwar.core.Core; import java.io.IOException; import java.io.InputStream; import java.sql.Timestamp; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; +import java.util.*; import java.util.function.Consumer; public interface Provider { @@ -85,12 +82,12 @@ public interface Provider { void removePlayerConfig(int id, String config); void createSchematicNode(int owner, String name, Integer parent, String type, String item); - SchematicNode getSchematicNode(int owner, String name, Integer parent); + Optional getSchematicNode(int owner, String name, Integer parent); List getSchematicNodeInNode(Integer parent); List getSchematicDirectoryInNode(Integer parent); - SchematicNode getSchematicDirectory(String name, Integer parent); - SchematicNode getSchematicNode(String name, Integer parent); - SchematicNode getSchematicNode(int id); + Optional getSchematicDirectory(String name, Integer parent); + Optional getSchematicNode(String name, Integer parent); + Optional getSchematicNode(int id); List getAccessibleSchematicsOfTypeInParent(int owner, String schemType, Integer parent); List getAllAccessibleSchematicsOfType(int user, String schemType); List getAllSchematicsOfType(int owner, String schemType); diff --git a/SpigotCore_Main/src/de/steamwar/sql/SQLProvider.java b/SpigotCore_Main/src/de/steamwar/sql/SQLProvider.java index ce1da9a..0aa9253 100644 --- a/SpigotCore_Main/src/de/steamwar/sql/SQLProvider.java +++ b/SpigotCore_Main/src/de/steamwar/sql/SQLProvider.java @@ -409,7 +409,8 @@ public class SQLProvider implements Provider { private static final Statement isSchematicAccessibleForUser = new Statement("WITH RECURSIVE RSN AS (" + nodeSelectCreator("") + "WHERE NodeId = ? UNION " + nodeSelectCreator("SN.") + "SN, RSN WHERE RSN.ParentNode = SN.NodeId) SELECT COUNT(RSN.NodeId) AS `Accessible` FROM RSN LEFT Join NodeMember NM On NM.NodeId = RSN.NodeId WHERE NodeOwner = ? OR UserId = ? LIMIT 1"); private static final Statement getAllParentsOfNode = new Statement("WITH RECURSIVE RSN AS (" + nodeSelectCreator("") + "WHERE NodeId = ? UNION " + nodeSelectCreator("SN.") + "SN, RSN WHERE RSN.ParentNode = SN.NodeId) SELECT * FROM RSN ORDER BY NodeName"); private static final Statement countNodes = new Statement("SELECT COUNT(NodeId) AS 'count' FROM SchematicNode"); - private static final Statement updateDB = new Statement("UPDATE SchematicNode SET NodeName = ?, NodeOwner = ?, ParentNode = ?, NodeItem = ?, NodeType = ?, NodeRank = ?, ReplaceColor = ?, AllowReplay = ? WHERE NodeId = ?"); + private static final Statement updateDB = new Statement("UPDATE SchematicNode SET NodeName = ?, NodeOwner = ?, ParentNode = ?, NodeItem = ? WHERE NodeId = ?"); + private static final Statement updateSchematicDB = new Statement("UPDATE SchematicNode SET NodeType = ?, NodeRank = ?, ReplaceColor = ?, AllowReplay = ? WHERE NodeId = ?"); private static final Statement updateDatabase = new Statement("UPDATE SchematicNode SET NodeData = ?, NodeFormat = ? WHERE NodeId = ?"); private static final Statement selSchemData = new Statement("SELECT NodeData FROM SchematicNode WHERE NodeId = ?"); private static final Statement deleteNode = new Statement("DELETE FROM SchematicNode WHERE NodeId = ?"); @@ -422,11 +423,11 @@ public class SQLProvider implements Provider { } return nodes; }; - private static final Statement.ResultSetUser toSchematicNode = rs -> { + private static final Statement.ResultSetUser> toSchematicNode = rs -> { if (rs.next()) { - return nodeFromResultSet(rs); + return Optional.of(nodeFromResultSet(rs)); } - return null; + return Optional.empty(); }; private static SchematicNode nodeFromResultSet(ResultSet rs) throws SQLException { @@ -435,7 +436,7 @@ public class SQLProvider implements Provider { parent = null; } String type = rs.getString("NodeType"); - return new SchematicNode( + return SchematicNode.constructSchematicNode( rs.getInt("NodeId"), rs.getInt("NodeOwner"), rs.getString("NodeName"), @@ -457,7 +458,7 @@ public class SQLProvider implements Provider { } @Override - public SchematicNode getSchematicNode(int owner, String name, Integer parent) { + public Optional getSchematicNode(int owner, String name, Integer parent) { if(parent == null) { return getSchematicNode_Null.select(toSchematicNode, owner, name); @@ -485,14 +486,14 @@ public class SQLProvider implements Provider { } @Override - public SchematicNode getSchematicDirectory(String name, Integer parent) { - Statement.ResultSetUser user = rs -> { + public Optional getSchematicDirectory(String name, Integer parent) { + Statement.ResultSetUser> user = rs -> { while (rs.next()) { SchematicNode node = nodeFromResultSet(rs); if(node.isDir()) - return node; + return Optional.of(node); } - return null; + return Optional.empty(); }; if(parent == null) { @@ -503,7 +504,7 @@ public class SQLProvider implements Provider { } @Override - public SchematicNode getSchematicNode(String name, Integer parent) { + public Optional getSchematicNode(String name, Integer parent) { if(parent == null) { return getSchematicNodeO_Null.select(toSchematicNode, name); }else { @@ -512,12 +513,8 @@ public class SQLProvider implements Provider { } @Override - public SchematicNode getSchematicNode(int id) { - return getSchematicNodeId.select(rs -> { - if (!rs.next()) - return null; - return nodeFromResultSet(rs); - }, id); + public Optional getSchematicNode(int id) { + return getSchematicNodeId.select(toSchematicNode, id); } @Override @@ -591,12 +588,19 @@ public class SQLProvider implements Provider { node.getOwner(), node.getParent(), node.getItem(), - node.getType(), - node.getRankUnsafe(), - node.replaceColor(), - node.allowReplay(), node.getId() ); + + node.getSchematic().ifPresent(schematicNodeSchematic -> { + SchematicNode.SchematicNodeSchematic.Unsafe unsafe = schematicNodeSchematic.unsafe(); + updateSchematicDB.update( + unsafe.getType(), + schematicNodeSchematic.getRank(), + schematicNodeSchematic.replaceColor(), + schematicNodeSchematic.allowReplay(), + node.getId() + ); + }); } @Override diff --git a/SpigotCore_Main/src/de/steamwar/sql/SchematicNode.java b/SpigotCore_Main/src/de/steamwar/sql/SchematicNode.java index cadf8fd..697304d 100644 --- a/SpigotCore_Main/src/de/steamwar/sql/SchematicNode.java +++ b/SpigotCore_Main/src/de/steamwar/sql/SchematicNode.java @@ -22,6 +22,7 @@ package de.steamwar.sql; import com.sk89q.worldedit.extent.clipboard.Clipboard; import de.steamwar.core.Core; import de.steamwar.core.WorldEditWrapper; +import lombok.NonNull; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -35,125 +36,137 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Predicate; public class SchematicNode { + protected static final Map>> TAB_CACHE = new HashMap<>(); - public static SchematicNode createSchematic(int owner, String name, Integer parent) { + static { + Bukkit.getScheduler().runTaskTimer(Core.getInstance(), TAB_CACHE::clear, 20L * 30, 20L * 30); + } + + public static @NonNull SchematicNode createSchematic(int owner, @NonNull String name, Integer parent) { return createSchematicNode(owner, name, parent, SchematicType.Normal.toDB(), ""); } - public static SchematicNode createSchematicDirectory(int owner, String name, Integer parent) { + public static @NonNull SchematicNode createSchematicDirectory(int owner, @NonNull String name, Integer parent) { return createSchematicNode(owner, name, parent, null, ""); } - public static SchematicNode createSchematicNode(int owner, String name, Integer parent, String type, String item) { - if (parent != null && parent == 0) - parent = null; + public static @NonNull SchematicNode createSchematicNode(int owner, @NonNull String name, Integer parent, String type, @NonNull String item) { Provider.impl.createSchematicNode(owner, name, parent, type, item); - return getSchematicNode(owner, name, parent); + return getSchematicNode(owner, name, parent).orElseThrow(() -> new IllegalStateException("Could not create schematic node")); } - public static SchematicNode getSchematicNode(int owner, String name, SchematicNode parent) { + public static Optional getSchematicNode(int owner, @NonNull String name, @NonNull SchematicNode parent) { return getSchematicNode(owner, name, parent.getId()); } + public static SchematicNode constructSchematicNode( + int id, + int owner, + @NonNull String name, + Integer parent, + @NonNull String item, + String type, + boolean isDir, + int rank, + @NonNull Timestamp lastUpdate, + boolean schemFormat, + boolean replaceColor, + boolean allowReplay + ) { + if(isDir) { + return new SchematicNode(id, owner, name, parent, item, true, lastUpdate); + } else { + return new SchematicNodeSchematic(id, owner, name, parent, item, type, rank, lastUpdate, schemFormat, replaceColor, allowReplay); + } + } + public SchematicNode( int id, int owner, - String name, - Integer parent, - String item, - String type, + @NonNull String name, + @NonNull Integer parent, + @NonNull String item, boolean isDir, - int rank, - Timestamp lastUpdate, - boolean schemFormat, - boolean replaceColor, - boolean allowReplay + @NonNull Timestamp lastUpdate ) { this.id = id; this.owner = owner; this.name = name; this.parent = parent; this.item = item; - this.type = type; this.lastUpdate = lastUpdate; this.isDir = isDir; - if (!isDir) { - this.schemFormat = schemFormat; - this.rank = rank; - this.replaceColor = replaceColor; - this.allowReplay = allowReplay; - } } - public static List getSchematicNodeInNode(SchematicNode parent) { + public static @NonNull List getSchematicNodeInNode(@NonNull SchematicNode parent) { return getSchematicNodeInNode(parent.getId()); } - public static SchematicNode getSchematicDirectory(String name, SchematicNode parent) { + public static @NonNull Optional getSchematicDirectory(@NonNull String name, @NonNull SchematicNode parent) { return getSchematicDirectory(name, parent.getId()); } - public static SchematicNode getSchematicNode(int owner, String name, Integer parent) { + public static @NonNull Optional getSchematicNode(int owner, @NonNull String name, Integer parent) { if (parent != null && parent == 0) { parent = null; } return Provider.impl.getSchematicNode(owner, name, parent); } - public static List getSchematicNodeInNode(Integer parent) { + public static @NonNull List getSchematicNodeInNode(Integer parent) { if(parent != null && parent == 0) { parent = null; } return Provider.impl.getSchematicNodeInNode(parent); } - public static List getSchematicDirectoryInNode(Integer parent) { + public static @NonNull List getSchematicDirectoryInNode(Integer parent) { if(parent != null && parent == 0) { parent = null; } return Provider.impl.getSchematicDirectoryInNode(parent); } - public static SchematicNode getSchematicDirectory(String name, Integer parent) { + public static @NonNull Optional getSchematicDirectory(@NonNull String name, Integer parent) { if(parent != null && parent == 0) { parent = null; } return Provider.impl.getSchematicDirectory(name, parent); } - public static SchematicNode getSchematicNode(String name, Integer parent) { + public static @NonNull Optional getSchematicNode(@NonNull String name, Integer parent) { if(parent != null && parent == 0) { parent = null; } return Provider.impl.getSchematicNode(name, parent); } - public static SchematicNode getSchematicNode(int id) { + public static @NonNull Optional getSchematicNode(int id) { return Provider.impl.getSchematicNode(id); } - public static List getAccessibleSchematicsOfTypeInParent(int owner, String schemType, Integer parent) { + public static @NonNull List getAccessibleSchematicsOfTypeInParent(int owner, @NonNull String schemType, Integer parent) { return Provider.impl.getAccessibleSchematicsOfTypeInParent(owner, schemType, parent); } - public static List getAllAccessibleSchematicsOfType(int user, String schemType) { + public static @NonNull List getAllAccessibleSchematicsOfType(int user, @NonNull String schemType) { return Provider.impl.getAllAccessibleSchematicsOfType(user, schemType); } - public static List getAllSchematicsOfType(int owner, String schemType) { + public static @NonNull List getAllSchematicsOfType(int owner, @NonNull String schemType) { return Provider.impl.getAllSchematicsOfType(owner, schemType); } @Deprecated - public static List getAllSchematicsOfType(String schemType) { + public static @NonNull List getAllSchematicsOfType(@NonNull String schemType) { return Provider.impl.getAllSchematicsOfType(schemType); } - public static List getAllSchematicsOfType(SchematicType schemType) { + public static @NonNull List getAllSchematicsOfType(@NonNull SchematicType schemType) { return Provider.impl.getAllSchematicsOfType(schemType.toDB()); } - public static List deepGet(Integer parent, Predicate filter) { + public static @NonNull List deepGet(Integer parent, @NonNull Predicate filter) { List finalList = new ArrayList<>(); List nodes = SchematicNode.getSchematicNodeInNode(parent); nodes.forEach(node -> { @@ -167,53 +180,54 @@ public class SchematicNode { return finalList; } - public static List getSchematicsAccessibleByUser(int user, Integer parent) { + public static @NonNull List getSchematicsAccessibleByUser(int user, Integer parent) { return Provider.impl.getSchematicsAccessibleByUser(user, parent); } - public static List getAllSchematicsAccessibleByUser(int user) { + public static @NonNull List getAllSchematicsAccessibleByUser(int user) { return Provider.impl.getAllSchematicsAccessibleByUser(user); } - public static List getAllParentsOfNode(SchematicNode node) { + public static @NonNull List getAllParentsOfNode(@NonNull SchematicNode node) { return getAllParentsOfNode(node.getId()); } - public static List getAllParentsOfNode(int node) { + public static @NonNull List getAllParentsOfNode(int node) { return Provider.impl.getAllParentsOfNode(node); } - public static SchematicNode getNodeFromPath(SteamwarUser user, String s) { + public static @NonNull Optional getNodeFromPath(@NonNull SteamwarUser user, @NonNull String s) { if (s.startsWith("/")) { s = s.substring(1); } if (s.isEmpty()) { - return null; + return Optional.empty(); } if (s.contains("/")) { String[] layers = s.split("/"); - SchematicNode currentNode = null; + Optional currentNode = Optional.empty(); for (int i = 0; i < layers.length; i++) { int finalI = i; Optional node; - if (currentNode == null) { + if (!currentNode.isPresent()) { node = SchematicNode.getSchematicsAccessibleByUser(user.getId(), 0).stream().filter(node1 -> node1.getName().equals(layers[finalI])).findAny(); } else { - node = Optional.ofNullable(SchematicNode.getSchematicNode(layers[i], currentNode.getId())); + node = SchematicNode.getSchematicNode(layers[i], currentNode.get().getId()); } + if (!node.isPresent()) { - return null; + return Optional.empty(); } else { - currentNode = node.get(); - if (!currentNode.isDir() && i != layers.length - 1) { - return null; + currentNode = node; + if (!currentNode.map(SchematicNode::isDir).orElse(false) && i != layers.length - 1) { + return Optional.empty(); } } } return currentNode; } else { String finalS = s; - return SchematicNode.getSchematicsAccessibleByUser(user.getId(), 0).stream().filter(node1 -> node1.getName().equals(finalS)).findAny().orElse(null); + return SchematicNode.getSchematicsAccessibleByUser(user.getId(), 0).stream().filter(node1 -> node1.getName().equals(finalS)).findAny(); } } @@ -222,16 +236,11 @@ public class SchematicNode { private String name; private Integer parent; private String item; - private String type; - private boolean replaceColor; - private boolean allowReplay; - private boolean schemFormat; - private int rank; private Timestamp lastUpdate; private final boolean isDir; private Map brCache = new HashMap<>(); - public static List filterSchems(int user, Predicate filter) { + public static @NonNull List filterSchems(int user, @NonNull Predicate filter) { List finalList = new ArrayList<>(); List nodes = SchematicNode.getSchematicsAccessibleByUser(user, null); nodes.forEach(node -> { @@ -245,7 +254,7 @@ public class SchematicNode { return finalList; } - public static Integer countNodes() { + public static @NonNull Integer countNodes() { return Provider.impl.countNodes(); } @@ -257,17 +266,17 @@ public class SchematicNode { return owner; } - public String getName() { + public @NonNull String getName() { return name; } - public void setName(String name) { + public void setName(@NonNull String name) { this.name = name; updateDB(); } - public Integer getParent() { - return parent; + public @NonNull Optional getParent() { + return Optional.ofNullable(parent); } public void setParent(Integer parent) { @@ -275,73 +284,24 @@ public class SchematicNode { updateDB(); } - public String getItem() { + public @NonNull String getItem() { if (item.isEmpty()) { return isDir ? "CHEST" : "CAULDRON_ITEM"; } return item; } - public void setItem(String item) { + public void setItem(@NonNull String item) { this.item = item; updateDB(); } - @Deprecated - public String getType() { - return type; - } - - @Deprecated - public void setType(String type) { - if(isDir) - throw new SecurityException("Node is Directory"); - this.type = type; - updateDB(); - } - public boolean isDir() { return isDir; } - public boolean getSchemFormat() { - if(isDir) - throw new SecurityException("Node is Directory"); - return schemFormat; - } - - public int getRank() { - if(isDir) - throw new SecurityException("Node is Directory"); - return rank; - } - - @Deprecated - public int getRankUnsafe() { - return rank; - } - - public void setRank(int rank) { - if(isDir) - throw new SecurityException("Node is Directory"); - this.rank = rank; - } - - public SchematicType getSchemtype() { - if(isDir()) - throw new SecurityException("Is Directory"); - return SchematicType.fromDB(type); - } - - public void setSchemtype(SchematicType type) { - if(isDir()) - throw new SecurityException("Is Directory"); - this.type = type.toDB(); - updateDB(); - } - - public SchematicNode getParentNode() { - if(parent == null) return null; + public @NonNull Optional getParentNode() { + if(parent == null) return Optional.empty(); return SchematicNode.getSchematicNode(parent); } @@ -349,27 +309,31 @@ public class SchematicNode { return NodeMember.getNodeMember(id, user) != null; } - public Set getMembers() { + public @NonNull Set getMembers() { return NodeMember.getNodeMembers(id); } - public Timestamp getLastUpdate() { + public @NonNull Timestamp getLastUpdate() { return lastUpdate; } - public String generateBreadcrumbs(SteamwarUser user) { + public @NonNull Optional getSchematic() { + return Optional.of(isDir).map(dir -> dir ? null : (SchematicNodeSchematic) this); + } + + public @NonNull String generateBreadcrumbs(@NonNull SteamwarUser user) { return brCache.computeIfAbsent(user.getId(), integer -> generateBreadcrumbs("/", user)); } - public String generateBreadcrumbs(String split, SteamwarUser user) { + public @NonNull String generateBreadcrumbs(@NonNull String split, @NonNull SteamwarUser user) { StringBuilder builder = new StringBuilder(getName()); SchematicNode currentNode = this; - if (currentNode.isDir()) builder.append("/"); + if (currentNode.isDir()) builder.append(split); final Set nodeMembers = NodeMember.getSchematics(user.getId()); AtomicInteger i = new AtomicInteger(); i.set(currentNode.getId()); - while (currentNode.getParentNode() != null && nodeMembers.stream().noneMatch(nodeMember -> nodeMember.getNode() == i.get())) { - currentNode = currentNode.getParentNode(); + while (currentNode.getParentNode().isPresent() && nodeMembers.stream().noneMatch(nodeMember -> nodeMember.getNode() == i.get())) { + currentNode = currentNode.getParentNode().get(); i.set(currentNode.getId()); builder.insert(0, split) .insert(0, currentNode.getName()); @@ -377,7 +341,7 @@ public class SchematicNode { return builder.toString(); } - private void updateDB() { + protected void updateDB() { Provider.impl.updateSchematicNode(this); this.lastUpdate = Timestamp.from(Instant.now()); this.brCache.clear(); @@ -388,53 +352,6 @@ public class SchematicNode { Provider.impl.deleteSchematicNode(this); } - public InputStream schemData() throws IOException { - return Provider.impl.getSchematicData(this); - } - - public Clipboard load() throws IOException, NoClipboardException { - if(isDir) - throw new SecurityException("Node is Directory"); - return WorldEditWrapper.impl.getClipboard(schemData(), schemFormat); - } - - public void loadToPlayer(Player player) throws IOException, NoClipboardException { - if(isDir) - throw new SecurityException("Node is Directory"); - WorldEditWrapper.impl.setPlayerClipboard(player, schemData(), schemFormat); - } - - public void saveFromPlayer(Player player) throws IOException, NoClipboardException { - if(isDir) - throw new SecurityException("Node is Directory"); - saveFromPlayer(player, Core.getVersion() > 12); - } - - public void saveFromBytes(byte[] bytes, boolean newFormat) { - if(isDir) - throw new SecurityException("Node is Directory"); - updateDatabase(new ByteArrayInputStream(bytes), newFormat); - } - - public void saveFromPlayer(Player player, boolean newFormat) throws IOException, NoClipboardException { - if(isDir) - throw new SecurityException("Node is Directory"); - updateDatabase(WorldEditWrapper.impl.getPlayerClipboard(player, newFormat), newFormat); - } - - private void updateDatabase(InputStream blob, boolean newFormat) { - Provider.impl.saveSchematicNode(this, blob, newFormat); - schemFormat = newFormat; - } - - public static Clipboard clipboardFromStream(InputStream is, boolean schemFormat) { - try { - return WorldEditWrapper.impl.getClipboard(is, schemFormat); - } catch (IOException e) { - throw new SecurityException("Could not read schem", e); - } - } - @Override public boolean equals(Object obj) { if (!(obj instanceof SchematicNode)) @@ -444,13 +361,7 @@ public class SchematicNode { return node.getId() == id; } - protected static final Map>> TAB_CACHE = new HashMap<>(); - - static { - Bukkit.getScheduler().runTaskTimer(Core.getInstance(), TAB_CACHE::clear, 20L * 30, 20L * 30); - } - - public static List getNodeTabcomplete(SteamwarUser user, String s) { + public static @NonNull List getNodeTabcomplete(@NonNull SteamwarUser user, @NonNull String s) { boolean sws = s.startsWith("/"); if (sws) { s = s.substring(1); @@ -463,9 +374,9 @@ public class SchematicNode { List list = new ArrayList<>(); if (s.contains("/")) { String preTab = s.substring(0, s.lastIndexOf("/") + 1); - SchematicNode pa = SchematicNode.getNodeFromPath(user, preTab); - if (pa == null) return Collections.emptyList(); - List nodes = SchematicNode.getSchematicNodeInNode(pa); + Optional pa = SchematicNode.getNodeFromPath(user, preTab); + if (pa.isPresent()) return Collections.emptyList(); + List nodes = SchematicNode.getSchematicNodeInNode(pa.get()); nodes.forEach(node -> list.add((sws ? "/" : "") + node.generateBreadcrumbs(user))); } else { List nodes = SchematicNode.getSchematicsAccessibleByUser(user.getId(), 0); @@ -477,7 +388,7 @@ public class SchematicNode { } private static final List FORBIDDEN_NAMES = Collections.unmodifiableList(Arrays.asList("public")); - public static boolean invalidSchemName(String[] layers) { + public static boolean invalidSchemName(@NonNull String[] layers) { for (String layer : layers) { if (layer.isEmpty()) { return true; @@ -493,36 +404,154 @@ public class SchematicNode { layer.contains(" ")) { return true; } - if(FORBIDDEN_NAMES.contains(layer.toLowerCase())) { + if (FORBIDDEN_NAMES.contains(layer.toLowerCase())) { return true; } } return false; } - public boolean replaceColor() { - return replaceColor; + public static class SchematicNodeSchematic extends SchematicNode { + + private boolean replaceColor; + private boolean allowReplay; + private boolean schemFormat; + private int rank; + private String type; + + public SchematicNodeSchematic( + int id, + int owner, + @NonNull String name, + Integer parent, + @NonNull String item, + @NonNull String type, + int rank, + @NonNull Timestamp lastUpdate, + boolean schemFormat, + boolean replaceColor, + boolean allowReplay + ) { + super(id, owner, name, parent, item, false, lastUpdate); + this.rank = rank; + this.schemFormat = schemFormat; + this.replaceColor = replaceColor; + this.allowReplay = allowReplay; + this.type = type; + } + + public boolean getSchemFormat() { + return schemFormat; + } + + public int getRank() { + return rank; + } + + public void setRank(int rank) { + this.rank = rank; + } + + + public SchematicType getSchemtype() { + return SchematicType.fromDB(type); + } + + public void setSchemtype(@NonNull SchematicType type) { + this.type = type.toDB(); + updateDB(); + } + + public boolean replaceColor() { + return replaceColor; + } + + public void setReplaceColor(boolean replaceColor) { + this.replaceColor = replaceColor; + updateDB(); + } + + public boolean allowReplay() { + return allowReplay; + } + + public void setAllowReplay(boolean allowReplay) { + this.allowReplay = allowReplay; + updateDB(); + } + + public int getElo(int season) { + return Provider.impl.getSchematicElo(this, season); + } + + public @NonNull Unsafe unsafe() { + return new Unsafe() { + @Override + public void setType(@NonNull String type) { + SchematicNode.SchematicNodeSchematic.this.type = type; + SchematicNode.SchematicNodeSchematic.this.updateDB(); + } + + @Override + public @NonNull String getType() { + return SchematicNode.SchematicNodeSchematic.this.type; + } + }; + } + + public interface Unsafe { + public void setType(@NonNull String type); + public @NonNull String getType(); + } + + private void updateDatabase(@NonNull InputStream blob, boolean newFormat) { + Provider.impl.saveSchematicNode(this, blob, newFormat); + schemFormat = newFormat; + } + + public @NonNull Spigot spigot() { + return new Spigot() { + public @NonNull InputStream schemData() throws IOException { + return Provider.impl.getSchematicData(SchematicNode.SchematicNodeSchematic.this); + } + + public @NonNull Clipboard load() throws IOException, NoClipboardException { + return WorldEditWrapper.impl.getClipboard(schemData(), schemFormat); + } + + public void loadToPlayer(@NonNull Player player) throws IOException, NoClipboardException { + WorldEditWrapper.impl.setPlayerClipboard(player, schemData(), schemFormat); + } + + public void saveFromPlayer(@NonNull Player player) throws IOException, NoClipboardException { + saveFromPlayer(player, Core.getVersion() > 12); + } + + public void saveFromBytes(byte[] bytes, boolean newFormat) { + updateDatabase(new ByteArrayInputStream(bytes), newFormat); + } + + public void saveFromPlayer(@NonNull Player player, boolean newFormat) throws IOException, NoClipboardException { + updateDatabase(WorldEditWrapper.impl.getPlayerClipboard(player, newFormat), newFormat); + } + }; + } + + public interface Spigot { + @NonNull InputStream schemData() throws IOException; + @NonNull Clipboard load() throws IOException, NoClipboardException; + void loadToPlayer(@NonNull Player player) throws IOException, NoClipboardException; + void saveFromPlayer(@NonNull Player player) throws IOException, NoClipboardException; + void saveFromBytes(byte[] bytes, boolean newFormat); + void saveFromPlayer(@NonNull Player player, boolean newFormat) throws IOException, NoClipboardException; + } } - public void setReplaceColor(boolean replaceColor) { - if(isDir()) - throw new SecurityException("Is Directory"); - this.replaceColor = replaceColor; - updateDB(); - } - - public boolean allowReplay() { - return allowReplay; - } - - public void setAllowReplay(boolean allowReplay) { - if(isDir()) - throw new SecurityException("Is Directory"); - this.allowReplay = allowReplay; - updateDB(); - } - - public int getElo(int season) { - return Provider.impl.getSchematicElo(this, season); + public static @NonNull Clipboard clipboardFromStream(@NonNull InputStream is, boolean schemFormat) { + try { + return WorldEditWrapper.impl.getClipboard(is, schemFormat); + } catch (IOException e) { + throw new SecurityException("Could not read schem", e); + } } } diff --git a/SpigotCore_Main/src/de/steamwar/sql/StandaloneProvider.java b/SpigotCore_Main/src/de/steamwar/sql/StandaloneProvider.java index 0a9b3f7..26a3ab4 100644 --- a/SpigotCore_Main/src/de/steamwar/sql/StandaloneProvider.java +++ b/SpigotCore_Main/src/de/steamwar/sql/StandaloneProvider.java @@ -226,7 +226,7 @@ public class StandaloneProvider implements Provider { try (Stream stream = Files.list(id==null?schematicDir.toPath():nodesToPath.get(id))) { List list = stream.map(path -> { File file = path.toFile(); - SchematicNode node = new SchematicNode( + SchematicNode node = SchematicNode.constructSchematicNode( nodeId++, 0, file.isDirectory()?file.getName():file.getName().substring(file.getName().lastIndexOf(".")), @@ -268,7 +268,7 @@ public class StandaloneProvider implements Provider { File file = p.toFile(); int id = nodeId++; nodesToPath.put(id, p); - SchematicNode node = new SchematicNode( + SchematicNode node = SchematicNode.constructSchematicNode( nodeId++, 0, file.isDirectory()?file.getName():file.getName().substring(file.getName().lastIndexOf(".")), @@ -287,8 +287,8 @@ public class StandaloneProvider implements Provider { } @Override - public SchematicNode getSchematicNode(int owner, String name, Integer parent) { - return nodesByParent.get(parent).stream().filter(node -> node.getName().equals(name)).findAny().orElse(null); + public Optional getSchematicNode(int owner, String name, Integer parent) { + return nodesByParent.get(parent).stream().filter(node -> node.getName().equals(name)).findAny(); } @Override @@ -302,28 +302,36 @@ public class StandaloneProvider implements Provider { } @Override - public SchematicNode getSchematicDirectory(String name, Integer parent) { - return getSchematicDirectoryInNode(parent).stream().filter(node -> node.getName().equals(name)).findFirst().orElse(null); + public Optional getSchematicDirectory(String name, Integer parent) { + return getSchematicDirectoryInNode(parent).stream().filter(node -> node.getName().equals(name)).findFirst(); } @Override - public SchematicNode getSchematicNode(String name, Integer parent) { - return getSchematicNodeInNode(parent).stream().filter(node -> name.equals(node.getName())).findFirst().orElse(null); + public Optional getSchematicNode(String name, Integer parent) { + return getSchematicNodeInNode(parent).stream().filter(node -> name.equals(node.getName())).findFirst(); } @Override - public SchematicNode getSchematicNode(int id) { - return nodeById.getOrDefault(id, null); + public Optional getSchematicNode(int id) { + return Optional.ofNullable(nodeById.get(id)); } @Override public List getAccessibleSchematicsOfTypeInParent(int ignored, String schemType, Integer parent) { - return getSchematicDirectoryInNode(parent).stream().filter(node -> node.getType().equals(schemType)).collect(Collectors.toList()); + return getSchematicDirectoryInNode(parent).stream().filter(node -> node.getSchematic() + .map(SchematicNode.SchematicNodeSchematic::unsafe) + .map(SchematicNode.SchematicNodeSchematic.Unsafe::getType) + .map(type -> type.equals(schemType)) + .orElse(false)).collect(Collectors.toList()); } @Override public List getAllAccessibleSchematicsOfType(int ignored, String schemType) { - return getAllSchematicsAccessibleByUser(ignored).stream().filter(node -> schemType.equals(node.getType())).collect(Collectors.toList()); + return getAllSchematicsAccessibleByUser(ignored).stream().filter(node -> node.getSchematic() + .map(SchematicNode.SchematicNodeSchematic::unsafe) + .map(SchematicNode.SchematicNodeSchematic.Unsafe::getType) + .map(type -> type.equals(schemType)) + .orElse(false)).collect(Collectors.toList()); } @Override @@ -352,7 +360,7 @@ public class StandaloneProvider implements Provider { @Override public List getAllParentsOfNode(int node) { List allSchematicsAccessibleByUser = getAllSchematicsAccessibleByUser(node); - allSchematicsAccessibleByUser.remove(getSchematicNode(node)); + allSchematicsAccessibleByUser.remove(getSchematicNode(node).get()); return allSchematicsAccessibleByUser; } @@ -364,7 +372,7 @@ public class StandaloneProvider implements Provider { @Override public void updateSchematicNode(SchematicNode node) { try { - Path newPath = new File(nodesToPath.get(node.getParent() == null?-1:node.getParent()).toFile(), node.getName() + (node.getSchemFormat()?".schem":".schematic")).toPath(); + Path newPath = new File(nodesToPath.get(node.getParent().isPresent()?-1:node.getParent()).toFile(), node.getName() + node.getSchematic().map(SchematicNode.SchematicNodeSchematic::getSchemFormat).map(aBoolean -> aBoolean?".schem":".schematic").orElse("")).toPath(); Files.move(nodesToPath.get(node.getId()), newPath); nodesToPath.put(node.getId(), newPath); } catch (IOException e) { @@ -399,9 +407,12 @@ public class StandaloneProvider implements Provider { stream.write(bucket, 0, nReadBytes); } - if(newFormat != node.getSchemFormat()) { - nodesToPath.get(node.getId()).toFile().renameTo(new File(nodesToPath.get(node.getId()).toFile().getParentFile(), node.getName() + "." + (newFormat?".schem":"schematic"))); - } + node.getSchematic().ifPresent(schematicNodeSchematic -> { + if(newFormat != schematicNodeSchematic.getSchemFormat()) { + nodesToPath.get(node.getId()).toFile().renameTo(new File(nodesToPath.get(node.getId()).toFile().getParentFile(), node.getName() + "." + (newFormat?".schem":"schematic"))); + } + }); + } catch (IOException e) { throw new SecurityException(e); }