From 8ce900db31e5c4cf0cc5a39dcb61bed297b9d392 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Thu, 12 Jan 2023 21:53:28 +0100 Subject: [PATCH 01/10] NodeMember: Move Member Schematics --- .../steamwar/sql/EffectiveSchematicNode.java | 248 ++++++++++++++++++ src/de/steamwar/sql/NodeMember.java | 17 +- src/de/steamwar/sql/SchematicNode.java | 108 ++------ 3 files changed, 278 insertions(+), 95 deletions(-) create mode 100644 src/de/steamwar/sql/EffectiveSchematicNode.java diff --git a/src/de/steamwar/sql/EffectiveSchematicNode.java b/src/de/steamwar/sql/EffectiveSchematicNode.java new file mode 100644 index 0000000..e62c7c9 --- /dev/null +++ b/src/de/steamwar/sql/EffectiveSchematicNode.java @@ -0,0 +1,248 @@ +package de.steamwar.sql; + +import de.steamwar.sql.internal.Field; +import de.steamwar.sql.internal.SelectStatement; +import de.steamwar.sql.internal.Table; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.sql.Timestamp; +import java.util.*; +import java.util.stream.Collectors; + +import static de.steamwar.sql.SchematicNode.TAB_CACHE; + +public class EffectiveSchematicNode { + + private static final Table table = new Table<>(EffectiveSchematicNode.class, "EffectiveSchematicNode"); + + private static final SelectStatement all = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? ORDER BY NodeName"); + + private static final SelectStatement list_null = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND ParentNode is null ORDER BY NodeName"); + private static final SelectStatement list = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND ParentNode = ? ORDER BY NodeName"); + private static final SelectStatement byParentName = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND ParentNode = ? AND NodeName = ? ORDER BY NodeName"); + private static final SelectStatement byParentName_null = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND ParentNode is null AND NodeName = ? ORDER BY NodeName"); + private static final SelectStatement schematicAccessibleForUser = new SelectStatement<>(table, "SELECT COUNT(DISTINCT NodeId) FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND NodeId = ?"); + private static final SelectStatement accessibleByUserTypeParent = new SelectStatement<>(table, "WITH RECURSIVE RSN AS (SELECT NodeId, ParentNode FROM EffectiveSchematicNode WHERE NodeType = ? AND EffectiveOwner = ? UNION SELECT SN.NodeId, SN.ParentNode FROM RSN, EffectiveSchematicNode SN WHERE SN.NodeId = RSN.ParentNode AND EffectiveOwner = ?) SELECT SN.NodeId, SN.NodeOwner, ? AS EffectiveOwner, SN.NodeName, RSN.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId"); + private static final SelectStatement accessibleByUserTypeInParent = new SelectStatement<>(table, "WITH RECURSIVE RSN AS (SELECT NodeId, ParentNode FROM EffectiveSchematicNode WHERE NodeType = ? AND EffectiveOwner = ? UNION SELECT SN.NodeId, SN.ParentNode FROM RSN, EffectiveSchematicNode SN WHERE SN.NodeId = RSN.ParentNode AND EffectiveOwner = ?) SELECT SN.NodeId, SN.NodeOwner, ? AS EffectiveOwner, SN.NodeName, RSN.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId WHERE RSN.ParentNode = ?"); + private static final SelectStatement accessibleByUserTypeInParent_null = new SelectStatement<>(table, "WITH RECURSIVE RSN AS (SELECT NodeId, ParentNode FROM EffectiveSchematicNode WHERE NodeType = ? AND EffectiveOwner = ? UNION SELECT SN.NodeId, SN.ParentNode FROM RSN, EffectiveSchematicNode SN WHERE SN.NodeId = RSN.ParentNode AND EffectiveOwner = ?) SELECT SN.NodeId, SN.NodeOwner, ? AS EffectiveOwner, SN.NodeName, RSN.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId WHERE RSN.ParentNode is null"); + private static final SelectStatement accessibleByUserType = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND NodeType = ?"); + private static final SelectStatement byIdAndUser = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND NodeId = ?"); + private static final SelectStatement allParentsOfNode = new SelectStatement<>(table, "WITH RECURSIVE R AS (SELECT NodeId, ParentNode FROM EffectiveSchematicNode WHERE NodeId = ? AND EffectiveOwner = ? UNION SELECT E.NodeId, E.ParentNode FROM R, EffectiveSchematicNode E WHERE R.ParentNode = E.NodeId AND E.EffectiveOwner = ?) SELECT SN.NodeId, SN.NodeOwner, ? AS EffectiveOwner, SN.NodeName, R.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank FROM R INNER JOIN SchematicNode SN ON SN.NodeId = R.NodeId"); + + public static List getAll(SteamwarUser user) { + return all.listSelect(user); + } + + public static Map> getAllMap(SteamwarUser user) { + return map(all.listSelect(user)); + } + + public static List list(SteamwarUser user, Integer schematicId) { + if(schematicId == null || schematicId == 0) { + return list_null.listSelect(user); + } else { + return list.listSelect(user, schematicId); + } + } + + public static Optional byParentName(SteamwarUser user, Integer schematicId, String name) { + if(schematicId == null || schematicId == 0) { + return Optional.ofNullable(byParentName_null.select(user, name)); + } else { + return Optional.ofNullable(byParentName.select(user, schematicId, name)); + } + } + + public static List accessibleByUserType(SteamwarUser user, SchematicType type) { + return accessibleByUserType.listSelect(type, user, user, user); + } + + public static Map> accessibleByUserTypeMap(SteamwarUser user, SchematicType type) { + return map(accessibleByUserTypeParent.listSelect(type, user, user, user)); + } + + public static boolean schematicAccessibleForUser(SteamwarUser user, Integer schematicId) { + return schematicAccessibleForUser.select(user, schematicId) != null; + } + + public static List accessibleByUserTypeParent(SteamwarUser user, SchematicType type, Integer parentId) { + if(parentId == null || parentId == 0) { + return accessibleByUserTypeInParent_null.listSelect(type, user, user, user); + } else { + return accessibleByUserTypeInParent.listSelect(type, user, user, user, parentId); + } + } + + public static Optional byIdAndUser(SteamwarUser user, Integer id) { + return Optional.ofNullable(byIdAndUser.select(user, id)); + } + + public static List parentsOfNode(SteamwarUser user, Integer id) { + return allParentsOfNode.listSelect(id, user, user, user).stream().filter(n -> n.getNodeId() != id).collect(Collectors.toList()); + } + + private static Map> map(List in) { + Map> map = new HashMap<>(); + for (EffectiveSchematicNode effectiveSchematicNode : in) { + map.computeIfAbsent(effectiveSchematicNode.getNodeParent().orElse(0), k -> new ArrayList<>()).add(effectiveSchematicNode); + } + return map; + } + + @Getter + @Field + private final int nodeId; + @Getter + @Field + private final int nodeOwner; + @Getter + @Field + private final int effectiveOwner; + @Getter + @Field + private final String nodeName; + @Field(nullable = true) + private final Integer parentNode; + @Getter + @Field + private final Timestamp lastUpdate; + @Field + private final String nodeItem; + @Field(nullable = true) + private final SchematicType nodeType; + @Field + private final int nodeRank; + + private String brCache = null; + + public EffectiveSchematicNode(int nodeId, int nodeOwner, int effectiveOwner, String nodeName, Integer nodeParent, Timestamp lastUpdate, String nodeItem, SchematicType nodeType, int nodeRank) { + this.nodeId = nodeId; + this.nodeOwner = nodeOwner; + this.effectiveOwner = effectiveOwner; + this.nodeName = nodeName; + this.parentNode = nodeParent; + this.lastUpdate = lastUpdate; + this.nodeItem = nodeItem; + this.nodeType = nodeType; + this.nodeRank = nodeRank; + } + + public boolean isDir() { + return nodeType == null; + } + + public Optional getNodeParent() { + return Optional.ofNullable(parentNode); + } + + public Optional getParentNode() { + return byIdAndUser(SteamwarUser.get(effectiveOwner), parentNode); + } + + public SchematicType getNodeType() { + if(isDir()) { + throw new IllegalStateException("This node is a directory"); + } + return nodeType; + } + + public int getNodeRank() { + if(isDir()) { + throw new IllegalStateException("This node is a directory"); + } + return nodeRank; + } + + public SchematicNode toSchematicNode() { + return SchematicNode.getSchematicNode(nodeId); + } + + public boolean isWritable() { + return effectiveOwner == nodeOwner; + } + + public String getNodeItem() { + if (nodeItem.isEmpty()) { + return isDir() ? "CHEST" : "CAULDRON_ITEM"; + } + return nodeItem; + } + + public static List getNodeTabcomplete(SteamwarUser user, String s) { + boolean sws = s.startsWith("/"); + if (sws) { + s = s.substring(1); + } + int index = s.lastIndexOf("/"); + String cacheKey = index == -1 ? "" : s.substring(0, index); + if(TAB_CACHE.containsKey(user.getId()) && TAB_CACHE.get(user.getId()).containsKey(cacheKey)) { + return new ArrayList<>(TAB_CACHE.get(user.getId()).get(cacheKey)); + } + List list = new ArrayList<>(); + if (s.contains("/")) { + String preTab = s.substring(0, s.lastIndexOf("/") + 1); + Optional pa = EffectiveSchematicNode.getNodeFromPath(user, preTab); + if (!pa.isPresent()) return Collections.emptyList(); + List nodes = EffectiveSchematicNode.list(user, pa.get().getNodeId()); + nodes.forEach(node -> list.add((sws ? "/" : "") + node.generateBreadcrumbs())); + } else { + List nodes = EffectiveSchematicNode.list(user, 0); + nodes.forEach(node -> list.add((sws ? "/" : "") + node.getNodeName() + (node.isDir() ? "/" : ""))); + } + list.remove("//copy"); + TAB_CACHE.computeIfAbsent(user.getId(), integer -> new HashMap<>()).putIfAbsent(cacheKey, list); + return list; + } + + public String generateBreadcrumbs() { + if(brCache == null) { + brCache = generateBreadcrumbs("/"); + } + return brCache; + } + + public String generateBreadcrumbs(String split) { + StringBuilder builder = new StringBuilder(getNodeName()); + Optional currentNode = Optional.of(this); + if(currentNode.map(EffectiveSchematicNode::isDir).orElse(false)) { + builder.append("/"); + } + while (currentNode.isPresent()) { + currentNode = currentNode.flatMap(EffectiveSchematicNode::getNodeParent).flatMap(integer -> byIdAndUser(SteamwarUser.get(effectiveOwner), integer)); + currentNode.ifPresent(node -> builder.insert(0, '/').insert(0, node.getNodeName())); + } + return builder.toString(); + } + + public static Optional getNodeFromPath(SteamwarUser user, String s) { + if (s.startsWith("/")) { + s = s.substring(1); + } + if (s.endsWith("/")) { + s = s.substring(0, s.length() - 1); + } + if (s.isEmpty()) { + return Optional.empty(); + } + if (s.contains("/")) { + String[] layers = s.split("/"); + Optional currentNode = EffectiveSchematicNode.byParentName(user, 0, layers[0]); + for (int i = 1; i < layers.length; i++) { + int finalI = i; + Optional node = currentNode.flatMap(effectiveSchematicNode -> EffectiveSchematicNode.byParentName(user, effectiveSchematicNode.getNodeId(), layers[finalI])); + if (!node.isPresent()) { + return Optional.empty(); + } else { + currentNode = node; + if (!currentNode.map(EffectiveSchematicNode::isDir).orElse(false) && i != layers.length - 1) { + return Optional.empty(); + } + } + } + return currentNode; + } else { + return EffectiveSchematicNode.byParentName(user, 0, s); + } + } +} diff --git a/src/de/steamwar/sql/NodeMember.java b/src/de/steamwar/sql/NodeMember.java index e704ad0..19417da 100644 --- a/src/de/steamwar/sql/NodeMember.java +++ b/src/de/steamwar/sql/NodeMember.java @@ -26,6 +26,7 @@ import de.steamwar.sql.internal.Table; import lombok.AllArgsConstructor; import java.util.HashSet; +import java.util.Optional; import java.util.Set; @AllArgsConstructor @@ -39,13 +40,16 @@ public class NodeMember { private static final SelectStatement getNodeMember = table.select(Table.PRIMARY); private static final SelectStatement getNodeMembers = table.selectFields("NodeId"); private static final SelectStatement getSchematics = table.selectFields("UserId"); - private static final Statement create = table.insertAll(); + private static final Statement create = table.insert(Table.PRIMARY); private static final Statement delete = table.delete(Table.PRIMARY); + private static final Statement updateParent = table.update(Table.PRIMARY, "ParentId"); @Field(keys = {Table.PRIMARY}) private final int nodeId; @Field(keys = {Table.PRIMARY}) private final int userId; + @Field(nullable = true, def = "null") + private Integer parentId; public int getNode() { return nodeId; @@ -55,13 +59,17 @@ public class NodeMember { return userId; } + public Optional getParent() { + return Optional.ofNullable(parentId); + } + public void delete() { delete.update(nodeId, userId); } public static NodeMember createNodeMember(int node, int member) { create.update(node, member); - return new NodeMember(node, member); + return new NodeMember(node, member, null); } public static NodeMember getNodeMember(int node, int member) { @@ -75,4 +83,9 @@ public class NodeMember { public static Set getSchematics(int member) { return new HashSet<>(getSchematics.listSelect(member)); } + + public void setParentId(Integer parentId) { + this.parentId = Optional.ofNullable(parentId).orElse(0) == 0 ? null : parentId; + updateParent.update(this.parentId, nodeId, userId); + } } diff --git a/src/de/steamwar/sql/SchematicNode.java b/src/de/steamwar/sql/SchematicNode.java index 3e610a6..0299e77 100644 --- a/src/de/steamwar/sql/SchematicNode.java +++ b/src/de/steamwar/sql/SchematicNode.java @@ -38,7 +38,7 @@ public class SchematicNode { new SqlTypeMapper<>(SchematicNode.class, null, (rs, identifier) -> { throw new SecurityException("SchematicNode cannot be used as type (recursive select)"); }, (st, index, value) -> st.setInt(index, value.nodeId)); } - private static final Map>> TAB_CACHE = new HashMap<>(); + protected static final Map>> TAB_CACHE = new HashMap<>(); public static void clear() { TAB_CACHE.clear(); } @@ -62,14 +62,8 @@ public class SchematicNode { private static final SelectStatement dirsByParent_null = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE ParentNode is NULL AND NodeType is NULL ORDER BY NodeName"); private static final SelectStatement byParentName = table.selectFields("NodeName", "ParentNode"); private static final SelectStatement byParentName_null = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE NodeName = ? AND ParentNode is NULL"); - private static final SelectStatement accessibleByUserTypeParent = new SelectStatement<>(table, "WITH RECURSIVE RSNB AS (WITH RECURSIVE RSN as (" + nodeSelectCreator("s.") + "s LEFT JOIN NodeMember n ON s.NodeId = n.NodeId WHERE (s.NodeOwner = ? OR n.UserId = ?) GROUP BY s.NodeId UNION " + nodeSelectCreator("SN.") + "AS SN, RSN WHERE SN.ParentNode = RSN.NodeId) SELECT * FROM RSN WHERE NodeType = ? UNION " + nodeSelectCreator("SN.") + "AS SN, RSNB WHERE SN.NodeId = RSNB.ParentNode)SELECT * FROM RSNB WHERE ParentNode = ? ORDER BY NodeName"); - private static final SelectStatement accessibleByUserTypeParent_Null = new SelectStatement<>(table, "WITH RECURSIVE RSNB AS (WITH RECURSIVE RSN as (" + nodeSelectCreator("s.") + "s LEFT JOIN NodeMember n ON s.NodeId = n.NodeId WHERE (s.NodeOwner = ? OR n.UserId = ?) GROUP BY s.NodeId UNION " + nodeSelectCreator("SN.") + "AS SN, RSN WHERE SN.ParentNode = RSN.NodeId) SELECT * FROM RSN WHERE NodeType = ? UNION " + nodeSelectCreator("SN.") + "AS SN, RSNB WHERE SN.NodeId = RSNB.ParentNode)SELECT * FROM RSNB WHERE ParentNode is null ORDER BY NodeName"); - private static final SelectStatement accessibleByUserType = new SelectStatement<>(table, "WITH RECURSIVE RSN as (" + nodeSelectCreator("s.") + "s LEFT JOIN NodeMember n ON s.NodeId = n.NodeId WHERE (s.NodeOwner = ? OR n.UserId = ?) GROUP BY s.NodeId UNION " + nodeSelectCreator("SN.") + "AS SN, RSN WHERE SN.ParentNode = RSN.NodeId) SELECT * FROM RSN WHERE NodeType = ? ORDER BY NodeName"); private static final SelectStatement byOwnerType = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE NodeOwner = ? AND NodeType = ? ORDER BY NodeName"); private static final SelectStatement byType = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE NodeType = ? ORDER BY NodeName"); - private static final SelectStatement accessibleByUser = new SelectStatement<>(table, nodeSelectCreator("s.") + "s LEFT JOIN NodeMember n ON s.NodeId = n.NodeId WHERE (s.NodeOwner = ? OR n.UserId = ?) AND ((s.NodeOwner = ? AND s.ParentNode IS NULL) OR NOT s.NodeOwner = ?) GROUP BY s.NodeId ORDER BY s.NodeName"); - private static final Statement schematicAccessibleForUser = 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 SelectStatement allAccessibleByUser = new SelectStatement<>(table, "WITH RECURSIVE RSN as (" + nodeSelectCreator("s.") + "s LEFT JOIN NodeMember n ON s.NodeId = n.NodeId WHERE (s.NodeOwner = ? OR n.UserId = ?) GROUP BY s.NodeId UNION " + nodeSelectCreator("SN.") + "AS SN, RSN WHERE SN.ParentNode = RSN.NodeId) SELECT * FROM RSN ORDER BY NodeName"); private static final SelectStatement allParentsOfNode = new SelectStatement<>(table, "WITH RECURSIVE RSN AS (" + nodeSelectCreator("") + "WHERE NodeId = ? UNION " + nodeSelectCreator("SN.") + "SN, RSN WHERE RSN.ParentNode = SN.NodeId) SELECT * FROM RSN ORDER BY NodeName"); static { @@ -100,8 +94,6 @@ public class SchematicNode { @Field(def = "1") private boolean nodeFormat; - private final Map brCache = new HashMap<>(); - public SchematicNode( int nodeId, int nodeOwner, @@ -196,14 +188,14 @@ public class SchematicNode { return byId.select(id); } + @Deprecated public static List getAccessibleSchematicsOfTypeInParent(int owner, String schemType, Integer parent) { - if(parent == null || parent == 0) - return accessibleByUserTypeParent_Null.listSelect(owner, owner, schemType); - return accessibleByUserTypeParent.listSelect(owner, owner, schemType, parent); + return EffectiveSchematicNode.accessibleByUserTypeParent(SteamwarUser.get(owner), SchematicType.fromDB(schemType), parent).stream().map(EffectiveSchematicNode::toSchematicNode).collect(Collectors.toList()); } + @Deprecated public static List getAllAccessibleSchematicsOfType(int user, String schemType) { - return accessibleByUserType.listSelect(user, user, schemType); + return EffectiveSchematicNode.accessibleByUserType(SteamwarUser.get(user), SchematicType.fromDB(schemType)).stream().map(EffectiveSchematicNode::toSchematicNode).collect(Collectors.toList()); } public static List getAllSchematicsOfType(int owner, String schemType) { @@ -233,21 +225,14 @@ public class SchematicNode { return finalList; } + @Deprecated public static List getSchematicsAccessibleByUser(int user, Integer parent) { - if (parent == null || parent == 0) - return accessibleByUser.listSelect(user, user, user, user); - - if(schematicAccessibleForUser.select(rs -> { - rs.next(); - return rs.getInt("Accessible") > 0; - }, parent, user, user)) - return getSchematicNodeInNode(parent); - - return Collections.emptyList(); + return EffectiveSchematicNode.list(SteamwarUser.get(user), parent).stream().map(EffectiveSchematicNode::toSchematicNode).collect(Collectors.toList()); } + @Deprecated public static List getAllSchematicsAccessibleByUser(int user) { - return allAccessibleByUser.listSelect(user, user); + return EffectiveSchematicNode.getAll(SteamwarUser.get(user)).stream().map(EffectiveSchematicNode::toSchematicNode).collect(Collectors.toList()); } public static List getAllParentsOfNode(SchematicNode node) { @@ -258,38 +243,9 @@ public class SchematicNode { return allParentsOfNode.listSelect(node); } + @Deprecated public static SchematicNode getNodeFromPath(SteamwarUser user, String s) { - if (s.startsWith("/")) { - s = s.substring(1); - } - if (s.isEmpty()) { - return null; - } - if (s.contains("/")) { - String[] layers = s.split("/"); - SchematicNode currentNode = null; - for (int i = 0; i < layers.length; i++) { - int finalI = i; - Optional node; - if (currentNode == null) { - 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())); - } - if (!node.isPresent()) { - return null; - } else { - currentNode = node.get(); - if (!currentNode.isDir() && i != layers.length - 1) { - return null; - } - } - } - return currentNode; - } else { - String finalS = s; - return SchematicNode.getSchematicsAccessibleByUser(user.getId(), 0).stream().filter(node1 -> node1.getName().equals(finalS)).findAny().orElse(null); - } + return EffectiveSchematicNode.getNodeFromPath(user, s).map(EffectiveSchematicNode::toSchematicNode).orElse(null); } public static List filterSchems(int user, Predicate filter) { @@ -448,7 +404,6 @@ public class SchematicNode { private void updateDB() { this.lastUpdate = Timestamp.from(Instant.now()); update.update(nodeName, parentNode, nodeItem, nodeType, nodeRank, replaceColor, allowReplay, nodeFormat, nodeId); - this.brCache.clear(); TAB_CACHE.clear(); } @@ -470,23 +425,11 @@ public class SchematicNode { } public String generateBreadcrumbs(SteamwarUser user) { - return brCache.computeIfAbsent(user.getId(), integer -> generateBreadcrumbs("/", user)); + return EffectiveSchematicNode.byIdAndUser(user, nodeId).map(EffectiveSchematicNode::generateBreadcrumbs).orElse("/"); } public String generateBreadcrumbs(String split, SteamwarUser user) { - StringBuilder builder = new StringBuilder(getName()); - SchematicNode currentNode = this; - if (currentNode.isDir()) builder.append("/"); - 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(); - i.set(currentNode.getId()); - builder.insert(0, split) - .insert(0, currentNode.getName()); - } - return builder.toString(); + return EffectiveSchematicNode.byIdAndUser(user, nodeId).map(node -> node.generateBreadcrumbs(split)).orElse("/"); } private static final List FORBIDDEN_NAMES = Collections.unmodifiableList(Arrays.asList("public")); @@ -513,30 +456,9 @@ public class SchematicNode { return false; } + @Deprecated public static List getNodeTabcomplete(SteamwarUser user, String s) { - boolean sws = s.startsWith("/"); - if (sws) { - s = s.substring(1); - } - int index = s.lastIndexOf("/"); - String cacheKey = index == -1 ? "" : s.substring(0, index); - if(TAB_CACHE.containsKey(user.getId()) && TAB_CACHE.get(user.getId()).containsKey(cacheKey)) { - return new ArrayList<>(TAB_CACHE.get(user.getId()).get(cacheKey)); - } - 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); - nodes.forEach(node -> list.add((sws ? "/" : "") + node.generateBreadcrumbs(user))); - } else { - List nodes = SchematicNode.getSchematicsAccessibleByUser(user.getId(), 0); - nodes.forEach(node -> list.add((sws ? "/" : "") + node.getName() + (node.isDir() ? "/" : ""))); - } - list.remove("//copy"); - TAB_CACHE.computeIfAbsent(user.getId(), integer -> new HashMap<>()).putIfAbsent(cacheKey, list); - return list; + return EffectiveSchematicNode.getNodeTabcomplete(user, s); } private static void rootWarning() { From 45bc5b05d71fb7bc909537b4c12522b175e62ffd Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sat, 14 Jan 2023 08:57:04 +0100 Subject: [PATCH 02/10] Add Copyright --- .../steamwar/sql/EffectiveSchematicNode.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/de/steamwar/sql/EffectiveSchematicNode.java b/src/de/steamwar/sql/EffectiveSchematicNode.java index e62c7c9..587034e 100644 --- a/src/de/steamwar/sql/EffectiveSchematicNode.java +++ b/src/de/steamwar/sql/EffectiveSchematicNode.java @@ -1,3 +1,22 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2023 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + package de.steamwar.sql; import de.steamwar.sql.internal.Field; From c94ee5c55f25caa053eae3a8b56fda7b4d707f14 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sun, 15 Jan 2023 17:55:17 +0100 Subject: [PATCH 03/10] Add Copyright --- .../steamwar/sql/EffectiveSchematicNode.java | 267 ------------------ src/de/steamwar/sql/SchematicNode.java | 184 ++++++++++-- 2 files changed, 163 insertions(+), 288 deletions(-) delete mode 100644 src/de/steamwar/sql/EffectiveSchematicNode.java diff --git a/src/de/steamwar/sql/EffectiveSchematicNode.java b/src/de/steamwar/sql/EffectiveSchematicNode.java deleted file mode 100644 index 587034e..0000000 --- a/src/de/steamwar/sql/EffectiveSchematicNode.java +++ /dev/null @@ -1,267 +0,0 @@ -/* - This file is a part of the SteamWar software. - - Copyright (C) 2023 SteamWar.de-Serverteam - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero 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 Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -package de.steamwar.sql; - -import de.steamwar.sql.internal.Field; -import de.steamwar.sql.internal.SelectStatement; -import de.steamwar.sql.internal.Table; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.sql.Timestamp; -import java.util.*; -import java.util.stream.Collectors; - -import static de.steamwar.sql.SchematicNode.TAB_CACHE; - -public class EffectiveSchematicNode { - - private static final Table table = new Table<>(EffectiveSchematicNode.class, "EffectiveSchematicNode"); - - private static final SelectStatement all = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? ORDER BY NodeName"); - - private static final SelectStatement list_null = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND ParentNode is null ORDER BY NodeName"); - private static final SelectStatement list = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND ParentNode = ? ORDER BY NodeName"); - private static final SelectStatement byParentName = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND ParentNode = ? AND NodeName = ? ORDER BY NodeName"); - private static final SelectStatement byParentName_null = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND ParentNode is null AND NodeName = ? ORDER BY NodeName"); - private static final SelectStatement schematicAccessibleForUser = new SelectStatement<>(table, "SELECT COUNT(DISTINCT NodeId) FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND NodeId = ?"); - private static final SelectStatement accessibleByUserTypeParent = new SelectStatement<>(table, "WITH RECURSIVE RSN AS (SELECT NodeId, ParentNode FROM EffectiveSchematicNode WHERE NodeType = ? AND EffectiveOwner = ? UNION SELECT SN.NodeId, SN.ParentNode FROM RSN, EffectiveSchematicNode SN WHERE SN.NodeId = RSN.ParentNode AND EffectiveOwner = ?) SELECT SN.NodeId, SN.NodeOwner, ? AS EffectiveOwner, SN.NodeName, RSN.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId"); - private static final SelectStatement accessibleByUserTypeInParent = new SelectStatement<>(table, "WITH RECURSIVE RSN AS (SELECT NodeId, ParentNode FROM EffectiveSchematicNode WHERE NodeType = ? AND EffectiveOwner = ? UNION SELECT SN.NodeId, SN.ParentNode FROM RSN, EffectiveSchematicNode SN WHERE SN.NodeId = RSN.ParentNode AND EffectiveOwner = ?) SELECT SN.NodeId, SN.NodeOwner, ? AS EffectiveOwner, SN.NodeName, RSN.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId WHERE RSN.ParentNode = ?"); - private static final SelectStatement accessibleByUserTypeInParent_null = new SelectStatement<>(table, "WITH RECURSIVE RSN AS (SELECT NodeId, ParentNode FROM EffectiveSchematicNode WHERE NodeType = ? AND EffectiveOwner = ? UNION SELECT SN.NodeId, SN.ParentNode FROM RSN, EffectiveSchematicNode SN WHERE SN.NodeId = RSN.ParentNode AND EffectiveOwner = ?) SELECT SN.NodeId, SN.NodeOwner, ? AS EffectiveOwner, SN.NodeName, RSN.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId WHERE RSN.ParentNode is null"); - private static final SelectStatement accessibleByUserType = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND NodeType = ?"); - private static final SelectStatement byIdAndUser = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND NodeId = ?"); - private static final SelectStatement allParentsOfNode = new SelectStatement<>(table, "WITH RECURSIVE R AS (SELECT NodeId, ParentNode FROM EffectiveSchematicNode WHERE NodeId = ? AND EffectiveOwner = ? UNION SELECT E.NodeId, E.ParentNode FROM R, EffectiveSchematicNode E WHERE R.ParentNode = E.NodeId AND E.EffectiveOwner = ?) SELECT SN.NodeId, SN.NodeOwner, ? AS EffectiveOwner, SN.NodeName, R.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank FROM R INNER JOIN SchematicNode SN ON SN.NodeId = R.NodeId"); - - public static List getAll(SteamwarUser user) { - return all.listSelect(user); - } - - public static Map> getAllMap(SteamwarUser user) { - return map(all.listSelect(user)); - } - - public static List list(SteamwarUser user, Integer schematicId) { - if(schematicId == null || schematicId == 0) { - return list_null.listSelect(user); - } else { - return list.listSelect(user, schematicId); - } - } - - public static Optional byParentName(SteamwarUser user, Integer schematicId, String name) { - if(schematicId == null || schematicId == 0) { - return Optional.ofNullable(byParentName_null.select(user, name)); - } else { - return Optional.ofNullable(byParentName.select(user, schematicId, name)); - } - } - - public static List accessibleByUserType(SteamwarUser user, SchematicType type) { - return accessibleByUserType.listSelect(type, user, user, user); - } - - public static Map> accessibleByUserTypeMap(SteamwarUser user, SchematicType type) { - return map(accessibleByUserTypeParent.listSelect(type, user, user, user)); - } - - public static boolean schematicAccessibleForUser(SteamwarUser user, Integer schematicId) { - return schematicAccessibleForUser.select(user, schematicId) != null; - } - - public static List accessibleByUserTypeParent(SteamwarUser user, SchematicType type, Integer parentId) { - if(parentId == null || parentId == 0) { - return accessibleByUserTypeInParent_null.listSelect(type, user, user, user); - } else { - return accessibleByUserTypeInParent.listSelect(type, user, user, user, parentId); - } - } - - public static Optional byIdAndUser(SteamwarUser user, Integer id) { - return Optional.ofNullable(byIdAndUser.select(user, id)); - } - - public static List parentsOfNode(SteamwarUser user, Integer id) { - return allParentsOfNode.listSelect(id, user, user, user).stream().filter(n -> n.getNodeId() != id).collect(Collectors.toList()); - } - - private static Map> map(List in) { - Map> map = new HashMap<>(); - for (EffectiveSchematicNode effectiveSchematicNode : in) { - map.computeIfAbsent(effectiveSchematicNode.getNodeParent().orElse(0), k -> new ArrayList<>()).add(effectiveSchematicNode); - } - return map; - } - - @Getter - @Field - private final int nodeId; - @Getter - @Field - private final int nodeOwner; - @Getter - @Field - private final int effectiveOwner; - @Getter - @Field - private final String nodeName; - @Field(nullable = true) - private final Integer parentNode; - @Getter - @Field - private final Timestamp lastUpdate; - @Field - private final String nodeItem; - @Field(nullable = true) - private final SchematicType nodeType; - @Field - private final int nodeRank; - - private String brCache = null; - - public EffectiveSchematicNode(int nodeId, int nodeOwner, int effectiveOwner, String nodeName, Integer nodeParent, Timestamp lastUpdate, String nodeItem, SchematicType nodeType, int nodeRank) { - this.nodeId = nodeId; - this.nodeOwner = nodeOwner; - this.effectiveOwner = effectiveOwner; - this.nodeName = nodeName; - this.parentNode = nodeParent; - this.lastUpdate = lastUpdate; - this.nodeItem = nodeItem; - this.nodeType = nodeType; - this.nodeRank = nodeRank; - } - - public boolean isDir() { - return nodeType == null; - } - - public Optional getNodeParent() { - return Optional.ofNullable(parentNode); - } - - public Optional getParentNode() { - return byIdAndUser(SteamwarUser.get(effectiveOwner), parentNode); - } - - public SchematicType getNodeType() { - if(isDir()) { - throw new IllegalStateException("This node is a directory"); - } - return nodeType; - } - - public int getNodeRank() { - if(isDir()) { - throw new IllegalStateException("This node is a directory"); - } - return nodeRank; - } - - public SchematicNode toSchematicNode() { - return SchematicNode.getSchematicNode(nodeId); - } - - public boolean isWritable() { - return effectiveOwner == nodeOwner; - } - - public String getNodeItem() { - if (nodeItem.isEmpty()) { - return isDir() ? "CHEST" : "CAULDRON_ITEM"; - } - return nodeItem; - } - - public static List getNodeTabcomplete(SteamwarUser user, String s) { - boolean sws = s.startsWith("/"); - if (sws) { - s = s.substring(1); - } - int index = s.lastIndexOf("/"); - String cacheKey = index == -1 ? "" : s.substring(0, index); - if(TAB_CACHE.containsKey(user.getId()) && TAB_CACHE.get(user.getId()).containsKey(cacheKey)) { - return new ArrayList<>(TAB_CACHE.get(user.getId()).get(cacheKey)); - } - List list = new ArrayList<>(); - if (s.contains("/")) { - String preTab = s.substring(0, s.lastIndexOf("/") + 1); - Optional pa = EffectiveSchematicNode.getNodeFromPath(user, preTab); - if (!pa.isPresent()) return Collections.emptyList(); - List nodes = EffectiveSchematicNode.list(user, pa.get().getNodeId()); - nodes.forEach(node -> list.add((sws ? "/" : "") + node.generateBreadcrumbs())); - } else { - List nodes = EffectiveSchematicNode.list(user, 0); - nodes.forEach(node -> list.add((sws ? "/" : "") + node.getNodeName() + (node.isDir() ? "/" : ""))); - } - list.remove("//copy"); - TAB_CACHE.computeIfAbsent(user.getId(), integer -> new HashMap<>()).putIfAbsent(cacheKey, list); - return list; - } - - public String generateBreadcrumbs() { - if(brCache == null) { - brCache = generateBreadcrumbs("/"); - } - return brCache; - } - - public String generateBreadcrumbs(String split) { - StringBuilder builder = new StringBuilder(getNodeName()); - Optional currentNode = Optional.of(this); - if(currentNode.map(EffectiveSchematicNode::isDir).orElse(false)) { - builder.append("/"); - } - while (currentNode.isPresent()) { - currentNode = currentNode.flatMap(EffectiveSchematicNode::getNodeParent).flatMap(integer -> byIdAndUser(SteamwarUser.get(effectiveOwner), integer)); - currentNode.ifPresent(node -> builder.insert(0, '/').insert(0, node.getNodeName())); - } - return builder.toString(); - } - - public static Optional getNodeFromPath(SteamwarUser user, String s) { - if (s.startsWith("/")) { - s = s.substring(1); - } - if (s.endsWith("/")) { - s = s.substring(0, s.length() - 1); - } - if (s.isEmpty()) { - return Optional.empty(); - } - if (s.contains("/")) { - String[] layers = s.split("/"); - Optional currentNode = EffectiveSchematicNode.byParentName(user, 0, layers[0]); - for (int i = 1; i < layers.length; i++) { - int finalI = i; - Optional node = currentNode.flatMap(effectiveSchematicNode -> EffectiveSchematicNode.byParentName(user, effectiveSchematicNode.getNodeId(), layers[finalI])); - if (!node.isPresent()) { - return Optional.empty(); - } else { - currentNode = node; - if (!currentNode.map(EffectiveSchematicNode::isDir).orElse(false) && i != layers.length - 1) { - return Optional.empty(); - } - } - } - return currentNode; - } else { - return EffectiveSchematicNode.byParentName(user, 0, s); - } - } -} diff --git a/src/de/steamwar/sql/SchematicNode.java b/src/de/steamwar/sql/SchematicNode.java index 0299e77..4c6d826 100644 --- a/src/de/steamwar/sql/SchematicNode.java +++ b/src/de/steamwar/sql/SchematicNode.java @@ -21,6 +21,7 @@ package de.steamwar.sql; import de.steamwar.sql.internal.*; import lombok.AccessLevel; +import lombok.Getter; import lombok.Setter; import java.io.ByteArrayOutputStream; @@ -28,7 +29,6 @@ import java.io.PrintStream; import java.sql.Timestamp; import java.time.Instant; import java.util.*; -import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -45,7 +45,7 @@ public class SchematicNode { private static final String[] fields = {"NodeId", "NodeOwner", "NodeName", "ParentNode", "LastUpdate", "NodeItem", "NodeType", "NodeRank", "ReplaceColor", "AllowReplay", "NodeFormat"}; private static String nodeSelectCreator(String itemPrefix) { - return "SELECT " + Arrays.stream(fields).map(s -> itemPrefix + s).collect(Collectors.joining(", ")) + " FROM SchematicNode "; + return "SELECT " + Arrays.stream(fields).map(s -> itemPrefix + s).collect(Collectors.joining(", ")) + ", NodeOwner AS EffectiveOwner FROM SchematicNode "; } private static final Table table = new Table<>(SchematicNode.class); @@ -60,11 +60,19 @@ public class SchematicNode { private static final SelectStatement byParent_null = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE ParentNode is NULL ORDER BY NodeName"); private static final SelectStatement dirsByParent = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE ParentNode = ? AND NodeType is NULL ORDER BY NodeName"); private static final SelectStatement dirsByParent_null = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE ParentNode is NULL AND NodeType is NULL ORDER BY NodeName"); - private static final SelectStatement byParentName = table.selectFields("NodeName", "ParentNode"); - private static final SelectStatement byParentName_null = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE NodeName = ? AND ParentNode is NULL"); private static final SelectStatement byOwnerType = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE NodeOwner = ? AND NodeType = ? ORDER BY NodeName"); private static final SelectStatement byType = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE NodeType = ? ORDER BY NodeName"); - private static final SelectStatement allParentsOfNode = new SelectStatement<>(table, "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 SelectStatement all = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? ORDER BY NodeName"); + private static final SelectStatement list_null = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND ParentNode is null ORDER BY NodeName"); + private static final SelectStatement list = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND ParentNode = ? ORDER BY NodeName"); + private static final SelectStatement byParentName = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND ParentNode = ? AND NodeName = ? ORDER BY NodeName"); + private static final SelectStatement byParentName_null = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND ParentNode is null AND NodeName = ? ORDER BY NodeName"); + private static final SelectStatement schematicAccessibleForUser = new SelectStatement<>(table, "SELECT COUNT(DISTINCT NodeId) FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND NodeId = ?"); + private static final SelectStatement accessibleByUserTypeInParent = new SelectStatement<>(table, "WITH RECURSIVE RSN AS (SELECT NodeId, ParentNode FROM EffectiveSchematicNode WHERE NodeType = ? AND EffectiveOwner = ? UNION SELECT SN.NodeId, SN.ParentNode FROM RSN, EffectiveSchematicNode SN WHERE SN.NodeId = RSN.ParentNode AND EffectiveOwner = ?) SELECT SN.NodeId, SN.NodeOwner, ? AS EffectiveOwner, SN.NodeName, RSN.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId WHERE RSN.ParentNode = ?"); + private static final SelectStatement accessibleByUserTypeInParent_null = new SelectStatement<>(table, "WITH RECURSIVE RSN AS (SELECT NodeId, ParentNode FROM EffectiveSchematicNode WHERE NodeType = ? AND EffectiveOwner = ? UNION SELECT SN.NodeId, SN.ParentNode FROM RSN, EffectiveSchematicNode SN WHERE SN.NodeId = RSN.ParentNode AND EffectiveOwner = ?) SELECT SN.NodeId, SN.NodeOwner, ? AS EffectiveOwner, SN.NodeName, RSN.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId WHERE RSN.ParentNode is null"); + private static final SelectStatement accessibleByUserType = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND NodeType = ?"); + private static final SelectStatement byIdAndUser = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND NodeId = ?"); + private static final SelectStatement allParentsOfNode = new SelectStatement<>(table, "WITH RECURSIVE R AS (SELECT NodeId, ParentNode FROM EffectiveSchematicNode WHERE NodeId = ? AND EffectiveOwner = ? UNION SELECT E.NodeId, E.ParentNode FROM R, EffectiveSchematicNode E WHERE R.ParentNode = E.NodeId AND E.EffectiveOwner = ?) SELECT SN.NodeId, SN.NodeOwner, ? AS EffectiveOwner, SN.NodeName, R.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank FROM R INNER JOIN SchematicNode SN ON SN.NodeId = R.NodeId"); static { NodeMember.init(); @@ -74,6 +82,9 @@ public class SchematicNode { private final int nodeId; @Field(keys = {"OwnerNameParent"}) private final int nodeOwner; + @Field + @Getter + private final int effectiveOwner; @Field(keys = {"OwnerNameParent"}) private String nodeName; @Field(keys = {"OwnerNameParent"}, nullable = true) @@ -94,9 +105,12 @@ public class SchematicNode { @Field(def = "1") private boolean nodeFormat; + private String brCache; + public SchematicNode( int nodeId, int nodeOwner, + int effectiveOwner, String nodeName, Integer parentNode, Timestamp lastUpdate, @@ -109,6 +123,7 @@ public class SchematicNode { ) { this.nodeId = nodeId; this.nodeOwner = nodeOwner; + this.effectiveOwner = effectiveOwner; this.nodeName = nodeName; this.parentNode = parentNode; this.nodeItem = nodeItem; @@ -120,6 +135,66 @@ public class SchematicNode { this.nodeFormat = nodeFormat; } + public static List getAll(SteamwarUser user) { + return all.listSelect(user); + } + + public static Map> getAllMap(SteamwarUser user) { + return map(getAll(user)); + } + + public static List list(SteamwarUser user, Integer schematicId) { + if(schematicId == null || schematicId == 0) { + return list_null.listSelect(user); + } else { + return list.listSelect(user, schematicId); + } + } + + public static SchematicNode byParentName(SteamwarUser user, Integer schematicId, String name) { + if(schematicId == null || schematicId == 0) { + return byParentName_null.select(user, name); + } else { + return byParentName.select(user, schematicId, name); + } + } + + public static List accessibleByUserType(SteamwarUser user, SchematicType type) { + return accessibleByUserType.listSelect(type, user, user, user); + } + + public static Map> accessibleByUserTypeMap(SteamwarUser user, SchematicType type) { + return map(accessibleByUserType(user, type)); + } + + public static boolean schematicAccessibleForUser(SteamwarUser user, Integer schematicId) { + return schematicAccessibleForUser.select(user, schematicId) != null; + } + + public static List accessibleByUserTypeParent(SteamwarUser user, SchematicType type, Integer parentId) { + if(parentId == null || parentId == 0) { + return accessibleByUserTypeInParent_null.listSelect(type, user, user, user); + } else { + return accessibleByUserTypeInParent.listSelect(type, user, user, user, parentId); + } + } + + public static SchematicNode byIdAndUser(SteamwarUser user, Integer id) { + return byIdAndUser.select(user, id); + } + + public static List parentsOfNode(SteamwarUser user, Integer id) { + return allParentsOfNode.listSelect(id, user, user, user).stream().filter(n -> n.getId() != id).collect(Collectors.toList()); + } + + private static Map> map(List in) { + Map> map = new HashMap<>(); + for (SchematicNode effectiveSchematicNode : in) { + map.computeIfAbsent(effectiveSchematicNode.getOptionalParent().orElse(0), k -> new ArrayList<>()).add(effectiveSchematicNode); + } + return map; + } + public static SchematicNode createSchematic(int owner, String name, Integer parent) { return createSchematicNode(owner, name, parent, SchematicType.Normal.toDB(), ""); } @@ -188,14 +263,12 @@ public class SchematicNode { return byId.select(id); } - @Deprecated public static List getAccessibleSchematicsOfTypeInParent(int owner, String schemType, Integer parent) { - return EffectiveSchematicNode.accessibleByUserTypeParent(SteamwarUser.get(owner), SchematicType.fromDB(schemType), parent).stream().map(EffectiveSchematicNode::toSchematicNode).collect(Collectors.toList()); + return accessibleByUserTypeParent(SteamwarUser.get(owner), SchematicType.fromDB(schemType), parent); } - @Deprecated public static List getAllAccessibleSchematicsOfType(int user, String schemType) { - return EffectiveSchematicNode.accessibleByUserType(SteamwarUser.get(user), SchematicType.fromDB(schemType)).stream().map(EffectiveSchematicNode::toSchematicNode).collect(Collectors.toList()); + return accessibleByUserType(SteamwarUser.get(user), SchematicType.fromDB(schemType)); } public static List getAllSchematicsOfType(int owner, String schemType) { @@ -227,12 +300,12 @@ public class SchematicNode { @Deprecated public static List getSchematicsAccessibleByUser(int user, Integer parent) { - return EffectiveSchematicNode.list(SteamwarUser.get(user), parent).stream().map(EffectiveSchematicNode::toSchematicNode).collect(Collectors.toList()); + return list(SteamwarUser.get(user), parent); } @Deprecated public static List getAllSchematicsAccessibleByUser(int user) { - return EffectiveSchematicNode.getAll(SteamwarUser.get(user)).stream().map(EffectiveSchematicNode::toSchematicNode).collect(Collectors.toList()); + return getAll(SteamwarUser.get(user)); } public static List getAllParentsOfNode(SchematicNode node) { @@ -243,9 +316,35 @@ public class SchematicNode { return allParentsOfNode.listSelect(node); } - @Deprecated public static SchematicNode getNodeFromPath(SteamwarUser user, String s) { - return EffectiveSchematicNode.getNodeFromPath(user, s).map(EffectiveSchematicNode::toSchematicNode).orElse(null); + if (s.startsWith("/")) { + s = s.substring(1); + } + if (s.endsWith("/")) { + s = s.substring(0, s.length() - 1); + } + if (s.isEmpty()) { + return null; + } + if (s.contains("/")) { + String[] layers = s.split("/"); + Optional currentNode = Optional.ofNullable(SchematicNode.byParentName(user, 0, layers[0])); + for (int i = 1; i < layers.length; i++) { + int finalI = i; + Optional node = currentNode.map(effectiveSchematicNode -> SchematicNode.byParentName(user, effectiveSchematicNode.getId(), layers[finalI])); + if (!node.isPresent()) { + return null; + } else { + currentNode = node; + if (!currentNode.map(SchematicNode::isDir).orElse(false) && i != layers.length - 1) { + return null; + } + } + } + return currentNode.orElse(null); + } else { + return SchematicNode.byParentName(user, 0, s); + } } public static List filterSchems(int user, Predicate filter) { @@ -262,11 +361,6 @@ public class SchematicNode { return finalList; } - @Deprecated - public static Integer countNodes() { - return -1; - } - public int getId() { return nodeId; } @@ -288,6 +382,10 @@ public class SchematicNode { return parentNode; } + public Optional getOptionalParent() { + return Optional.ofNullable(parentNode); + } + public void setParent(Integer parent) { this.parentNode = parent; updateDB(); @@ -424,12 +522,34 @@ public class SchematicNode { return ((SchematicNode) obj).getId() == nodeId; } + @Deprecated public String generateBreadcrumbs(SteamwarUser user) { - return EffectiveSchematicNode.byIdAndUser(user, nodeId).map(EffectiveSchematicNode::generateBreadcrumbs).orElse("/"); + return generateBreadcrumbs(); } + @Deprecated public String generateBreadcrumbs(String split, SteamwarUser user) { - return EffectiveSchematicNode.byIdAndUser(user, nodeId).map(node -> node.generateBreadcrumbs(split)).orElse("/"); + return generateBreadcrumbs(split); + } + + public String generateBreadcrumbs() { + if(brCache == null) { + brCache = generateBreadcrumbs("/"); + } + return brCache; + } + + public String generateBreadcrumbs(String split) { + StringBuilder builder = new StringBuilder(getName()); + Optional currentNode = Optional.of(this); + if(currentNode.map(SchematicNode::isDir).orElse(false)) { + builder.append(split); + } + while (currentNode.isPresent()) { + currentNode = currentNode.flatMap(SchematicNode::getOptionalParent).map(integer -> byIdAndUser(SteamwarUser.get(effectiveOwner), integer)); + currentNode.ifPresent(node -> builder.insert(0, split).insert(0, node.getName())); + } + return builder.toString(); } private static final List FORBIDDEN_NAMES = Collections.unmodifiableList(Arrays.asList("public")); @@ -458,7 +578,29 @@ public class SchematicNode { @Deprecated public static List getNodeTabcomplete(SteamwarUser user, String s) { - return EffectiveSchematicNode.getNodeTabcomplete(user, s); + boolean sws = s.startsWith("/"); + if (sws) { + s = s.substring(1); + } + int index = s.lastIndexOf("/"); + String cacheKey = index == -1 ? "" : s.substring(0, index); + if(TAB_CACHE.containsKey(user.getId()) && TAB_CACHE.get(user.getId()).containsKey(cacheKey)) { + return new ArrayList<>(TAB_CACHE.get(user.getId()).get(cacheKey)); + } + 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.list(user, pa.getId()); + nodes.forEach(node -> list.add((sws ? "/" : "") + node.generateBreadcrumbs())); + } else { + List nodes = SchematicNode.list(user, 0); + nodes.forEach(node -> list.add((sws ? "/" : "") + node.getName() + (node.isDir() ? "/" : ""))); + } + list.remove("//copy"); + TAB_CACHE.computeIfAbsent(user.getId(), integer -> new HashMap<>()).putIfAbsent(cacheKey, list); + return list; } private static void rootWarning() { From 9276f79d93c1f3028871aa57e6c1c80d31d1d475 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Sun, 15 Jan 2023 20:07:01 +0100 Subject: [PATCH 04/10] Utilize null safe equals --- src/de/steamwar/sql/internal/SelectStatement.java | 2 +- src/de/steamwar/sql/internal/Statement.java | 3 +++ src/de/steamwar/sql/internal/Table.java | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/de/steamwar/sql/internal/SelectStatement.java b/src/de/steamwar/sql/internal/SelectStatement.java index e17dcb7..0b39160 100644 --- a/src/de/steamwar/sql/internal/SelectStatement.java +++ b/src/de/steamwar/sql/internal/SelectStatement.java @@ -31,7 +31,7 @@ public class SelectStatement extends Statement { private final Table table; SelectStatement(Table table, String... kfields) { - this(table, "SELECT " + Arrays.stream(table.fields).map(f -> f.identifier).collect(Collectors.joining(", ")) + " FROM " + table.name + " WHERE " + Arrays.stream(kfields).map(f -> f + " = ?").collect(Collectors.joining(" AND "))); + this(table, "SELECT " + Arrays.stream(table.fields).map(f -> f.identifier).collect(Collectors.joining(", ")) + " FROM " + table.name + " WHERE " + Arrays.stream(kfields).map(f -> f + Statement.NULL_SAFE_EQUALS + "?").collect(Collectors.joining(" AND "))); } public SelectStatement(Table table, String sql) { diff --git a/src/de/steamwar/sql/internal/Statement.java b/src/de/steamwar/sql/internal/Statement.java index 6c44332..ff39a09 100644 --- a/src/de/steamwar/sql/internal/Statement.java +++ b/src/de/steamwar/sql/internal/Statement.java @@ -41,6 +41,7 @@ public class Statement implements AutoCloseable { static final Consumer> schemaCreator; static final String ON_DUPLICATE_KEY; static final UnaryOperator upsertWrapper; + public static final String NULL_SAFE_EQUALS; private static final boolean MYSQL_MODE; private static final boolean PRODUCTION_DATABASE; @@ -73,6 +74,7 @@ public class Statement implements AutoCloseable { schemaCreator = table -> {}; ON_DUPLICATE_KEY = " ON DUPLICATE KEY UPDATE "; upsertWrapper = f -> f + " = VALUES(" + f + ")"; + NULL_SAFE_EQUALS = " <=> "; } else { Connection connection; @@ -89,6 +91,7 @@ public class Statement implements AutoCloseable { schemaCreator = Table::ensureExistanceInSqlite; ON_DUPLICATE_KEY = " ON CONFLICT DO UPDATE SET "; upsertWrapper = f -> f + " = " + f; + NULL_SAFE_EQUALS = " IS "; } } diff --git a/src/de/steamwar/sql/internal/Table.java b/src/de/steamwar/sql/internal/Table.java index cbad10a..3040642 100644 --- a/src/de/steamwar/sql/internal/Table.java +++ b/src/de/steamwar/sql/internal/Table.java @@ -75,7 +75,7 @@ public class Table { } public Statement updateFields(String[] fields, String... kfields) { - return new Statement("UPDATE " + name + " SET " + Arrays.stream(fields).map(f -> f + " = ?").collect(Collectors.joining(", ")) + " WHERE " + Arrays.stream(kfields).map(f -> f + " = ?").collect(Collectors.joining(" AND "))); + return new Statement("UPDATE " + name + " SET " + Arrays.stream(fields).map(f -> f + " = ?").collect(Collectors.joining(", ")) + " WHERE " + Arrays.stream(kfields).map(f -> f + Statement.NULL_SAFE_EQUALS + "?").collect(Collectors.joining(" AND "))); } public Statement insert(String name) { @@ -100,7 +100,7 @@ public class Table { } public Statement deleteFields(String... kfields) { - return new Statement("DELETE FROM " + name + " WHERE " + Arrays.stream(kfields).map(f -> f + " = ?").collect(Collectors.joining(" AND "))); + return new Statement("DELETE FROM " + name + " WHERE " + Arrays.stream(kfields).map(f -> f + Statement.NULL_SAFE_EQUALS + "?").collect(Collectors.joining(" AND "))); } void ensureExistanceInSqlite() { From 6a6483235c50c436a82d6471789dc2e5998cd4b1 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sun, 15 Jan 2023 20:11:41 +0100 Subject: [PATCH 05/10] Add Copyright --- src/de/steamwar/sql/SchematicNode.java | 50 ++++++++++---------------- 1 file changed, 18 insertions(+), 32 deletions(-) diff --git a/src/de/steamwar/sql/SchematicNode.java b/src/de/steamwar/sql/SchematicNode.java index 4c6d826..0dadeb0 100644 --- a/src/de/steamwar/sql/SchematicNode.java +++ b/src/de/steamwar/sql/SchematicNode.java @@ -56,20 +56,15 @@ public class SchematicNode { private static final SelectStatement byId = table.select(Table.PRIMARY); private static final SelectStatement byOwnerNameParent = table.select("OwnerNameParent"); private static final SelectStatement byOwnerNameParent_null = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE NodeOwner = ? AND NodeName = ? AND ParentNode is NULL"); - private static final SelectStatement byParent = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE ParentNode = ? ORDER BY NodeName"); - private static final SelectStatement byParent_null = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE ParentNode is NULL ORDER BY NodeName"); - private static final SelectStatement dirsByParent = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE ParentNode = ? AND NodeType is NULL ORDER BY NodeName"); - private static final SelectStatement dirsByParent_null = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE ParentNode is NULL AND NodeType is NULL ORDER BY NodeName"); + private static final SelectStatement byParent = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE ParentNode <=> ? ORDER BY NodeName"); + private static final SelectStatement dirsByParent = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE ParentNode" + Statement.NULL_SAFE_EQUALS + "? AND NodeType is NULL ORDER BY NodeName"); private static final SelectStatement byOwnerType = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE NodeOwner = ? AND NodeType = ? ORDER BY NodeName"); private static final SelectStatement byType = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE NodeType = ? ORDER BY NodeName"); private static final SelectStatement all = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? ORDER BY NodeName"); - private static final SelectStatement list_null = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND ParentNode is null ORDER BY NodeName"); - private static final SelectStatement list = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND ParentNode = ? ORDER BY NodeName"); - private static final SelectStatement byParentName = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND ParentNode = ? AND NodeName = ? ORDER BY NodeName"); - private static final SelectStatement byParentName_null = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND ParentNode is null AND NodeName = ? ORDER BY NodeName"); + private static final SelectStatement list = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND ParentNode" + Statement.NULL_SAFE_EQUALS + "? ORDER BY NodeName"); + private static final SelectStatement byParentName = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND ParentNode" + Statement.NULL_SAFE_EQUALS + "? AND NodeName = ? ORDER BY NodeName"); private static final SelectStatement schematicAccessibleForUser = new SelectStatement<>(table, "SELECT COUNT(DISTINCT NodeId) FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND NodeId = ?"); - private static final SelectStatement accessibleByUserTypeInParent = new SelectStatement<>(table, "WITH RECURSIVE RSN AS (SELECT NodeId, ParentNode FROM EffectiveSchematicNode WHERE NodeType = ? AND EffectiveOwner = ? UNION SELECT SN.NodeId, SN.ParentNode FROM RSN, EffectiveSchematicNode SN WHERE SN.NodeId = RSN.ParentNode AND EffectiveOwner = ?) SELECT SN.NodeId, SN.NodeOwner, ? AS EffectiveOwner, SN.NodeName, RSN.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId WHERE RSN.ParentNode = ?"); - private static final SelectStatement accessibleByUserTypeInParent_null = new SelectStatement<>(table, "WITH RECURSIVE RSN AS (SELECT NodeId, ParentNode FROM EffectiveSchematicNode WHERE NodeType = ? AND EffectiveOwner = ? UNION SELECT SN.NodeId, SN.ParentNode FROM RSN, EffectiveSchematicNode SN WHERE SN.NodeId = RSN.ParentNode AND EffectiveOwner = ?) SELECT SN.NodeId, SN.NodeOwner, ? AS EffectiveOwner, SN.NodeName, RSN.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId WHERE RSN.ParentNode is null"); + private static final SelectStatement accessibleByUserTypeInParent = new SelectStatement<>(table, "WITH RECURSIVE RSN AS (SELECT NodeId, ParentNode FROM EffectiveSchematicNode WHERE NodeType = ? AND EffectiveOwner = ? UNION SELECT SN.NodeId, SN.ParentNode FROM RSN, EffectiveSchematicNode SN WHERE SN.NodeId = RSN.ParentNode AND EffectiveOwner = ?) SELECT SN.NodeId, SN.NodeOwner, ? AS EffectiveOwner, SN.NodeName, RSN.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId WHERE RSN.ParentNode" + Statement.NULL_SAFE_EQUALS + "?"); private static final SelectStatement accessibleByUserType = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND NodeType = ?"); private static final SelectStatement byIdAndUser = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND NodeId = ?"); private static final SelectStatement allParentsOfNode = new SelectStatement<>(table, "WITH RECURSIVE R AS (SELECT NodeId, ParentNode FROM EffectiveSchematicNode WHERE NodeId = ? AND EffectiveOwner = ? UNION SELECT E.NodeId, E.ParentNode FROM R, EffectiveSchematicNode E WHERE R.ParentNode = E.NodeId AND E.EffectiveOwner = ?) SELECT SN.NodeId, SN.NodeOwner, ? AS EffectiveOwner, SN.NodeName, R.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank FROM R INNER JOIN SchematicNode SN ON SN.NodeId = R.NodeId"); @@ -135,6 +130,13 @@ public class SchematicNode { this.nodeFormat = nodeFormat; } + private static Integer nullOrNotNul(Integer i) { + if(i == null || i == 0) { + return null; + } + return i; + } + public static List getAll(SteamwarUser user) { return all.listSelect(user); } @@ -144,19 +146,11 @@ public class SchematicNode { } public static List list(SteamwarUser user, Integer schematicId) { - if(schematicId == null || schematicId == 0) { - return list_null.listSelect(user); - } else { - return list.listSelect(user, schematicId); - } + return list.listSelect(user, nullOrNotNul(schematicId)); } public static SchematicNode byParentName(SteamwarUser user, Integer schematicId, String name) { - if(schematicId == null || schematicId == 0) { - return byParentName_null.select(user, name); - } else { - return byParentName.select(user, schematicId, name); - } + return byParentName.select(user, nullOrNotNul(schematicId), name); } public static List accessibleByUserType(SteamwarUser user, SchematicType type) { @@ -172,11 +166,7 @@ public class SchematicNode { } public static List accessibleByUserTypeParent(SteamwarUser user, SchematicType type, Integer parentId) { - if(parentId == null || parentId == 0) { - return accessibleByUserTypeInParent_null.listSelect(type, user, user, user); - } else { - return accessibleByUserTypeInParent.listSelect(type, user, user, user, parentId); - } + return accessibleByUserTypeInParent.listSelect(type, user, user, user, nullOrNotNul(parentId)); } public static SchematicNode byIdAndUser(SteamwarUser user, Integer id) { @@ -227,18 +217,16 @@ public class SchematicNode { public static List getSchematicNodeInNode(Integer parent) { if(parent == null || parent == 0) { rootWarning(); - return byParent_null.listSelect(); } - return byParent.listSelect(parent); + return byParent.listSelect(nullOrNotNul(parent)); } public static List getSchematicDirectoryInNode(Integer parent) { if(parent == null || parent == 0) { rootWarning(); - return dirsByParent_null.listSelect(); } - return dirsByParent.listSelect(parent); + return dirsByParent.listSelect(nullOrNotNul(parent)); } @Deprecated @@ -254,9 +242,8 @@ public class SchematicNode { public static SchematicNode getSchematicNode(String name, Integer parent) { if(parent == null || parent == 0) { rootWarning(); - return byParentName_null.select(name); } - return byParentName.select(name, parent); + return byParentName.select(name, nullOrNotNul(parent)); } public static SchematicNode getSchematicNode(int id) { @@ -576,7 +563,6 @@ public class SchematicNode { return false; } - @Deprecated public static List getNodeTabcomplete(SteamwarUser user, String s) { boolean sws = s.startsWith("/"); if (sws) { From ad43512d30efa05f9905296ff739df61b80431a2 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sun, 15 Jan 2023 20:18:53 +0100 Subject: [PATCH 06/10] Add Copyright --- src/de/steamwar/sql/SchematicNode.java | 38 ++++---------------------- 1 file changed, 6 insertions(+), 32 deletions(-) diff --git a/src/de/steamwar/sql/SchematicNode.java b/src/de/steamwar/sql/SchematicNode.java index 0dadeb0..594b20a 100644 --- a/src/de/steamwar/sql/SchematicNode.java +++ b/src/de/steamwar/sql/SchematicNode.java @@ -55,7 +55,6 @@ public class SchematicNode { private static final SelectStatement byId = table.select(Table.PRIMARY); private static final SelectStatement byOwnerNameParent = table.select("OwnerNameParent"); - private static final SelectStatement byOwnerNameParent_null = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE NodeOwner = ? AND NodeName = ? AND ParentNode is NULL"); private static final SelectStatement byParent = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE ParentNode <=> ? ORDER BY NodeName"); private static final SelectStatement dirsByParent = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE ParentNode" + Statement.NULL_SAFE_EQUALS + "? AND NodeType is NULL ORDER BY NodeName"); private static final SelectStatement byOwnerType = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE NodeOwner = ? AND NodeType = ? ORDER BY NodeName"); @@ -130,13 +129,6 @@ public class SchematicNode { this.nodeFormat = nodeFormat; } - private static Integer nullOrNotNul(Integer i) { - if(i == null || i == 0) { - return null; - } - return i; - } - public static List getAll(SteamwarUser user) { return all.listSelect(user); } @@ -146,11 +138,11 @@ public class SchematicNode { } public static List list(SteamwarUser user, Integer schematicId) { - return list.listSelect(user, nullOrNotNul(schematicId)); + return list.listSelect(user, schematicId); } public static SchematicNode byParentName(SteamwarUser user, Integer schematicId, String name) { - return byParentName.select(user, nullOrNotNul(schematicId), name); + return byParentName.select(user, schematicId, name); } public static List accessibleByUserType(SteamwarUser user, SchematicType type) { @@ -166,7 +158,7 @@ public class SchematicNode { } public static List accessibleByUserTypeParent(SteamwarUser user, SchematicType type, Integer parentId) { - return accessibleByUserTypeInParent.listSelect(type, user, user, user, nullOrNotNul(parentId)); + return accessibleByUserTypeInParent.listSelect(type, user, user, user, parentId); } public static SchematicNode byIdAndUser(SteamwarUser user, Integer id) { @@ -205,8 +197,6 @@ public class SchematicNode { } public static SchematicNode getSchematicNode(int owner, String name, Integer parent) { - if (parent == null || parent == 0) - return byOwnerNameParent_null.select(owner, name); return byOwnerNameParent.select(owner, name, parent); } @@ -215,18 +205,11 @@ public class SchematicNode { } public static List getSchematicNodeInNode(Integer parent) { - if(parent == null || parent == 0) { - rootWarning(); - } - - return byParent.listSelect(nullOrNotNul(parent)); + return byParent.listSelect(parent); } public static List getSchematicDirectoryInNode(Integer parent) { - if(parent == null || parent == 0) { - rootWarning(); - } - return dirsByParent.listSelect(nullOrNotNul(parent)); + return dirsByParent.listSelect(parent); } @Deprecated @@ -240,10 +223,7 @@ public class SchematicNode { } public static SchematicNode getSchematicNode(String name, Integer parent) { - if(parent == null || parent == 0) { - rootWarning(); - } - return byParentName.select(name, nullOrNotNul(parent)); + return byParentName.select(name, parent); } public static SchematicNode getSchematicNode(int id) { @@ -588,10 +568,4 @@ public class SchematicNode { TAB_CACHE.computeIfAbsent(user.getId(), integer -> new HashMap<>()).putIfAbsent(cacheKey, list); return list; } - - private static void rootWarning() { - ByteArrayOutputStream stacktraceOutput = new ByteArrayOutputStream(); - new Throwable().printStackTrace(new PrintStream(stacktraceOutput)); - SWException.log("PERFORMANCE!!! Getting all/weird subset of schematic nodes with parent NULL", stacktraceOutput.toString()); - } } From a3f13737e4031628b5f29ddc43250dbbc233f13e Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sun, 15 Jan 2023 20:46:11 +0100 Subject: [PATCH 07/10] Add Copyright --- src/de/steamwar/sql/NodeMember.java | 2 +- src/de/steamwar/sql/SchematicNode.java | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/de/steamwar/sql/NodeMember.java b/src/de/steamwar/sql/NodeMember.java index 19417da..a952028 100644 --- a/src/de/steamwar/sql/NodeMember.java +++ b/src/de/steamwar/sql/NodeMember.java @@ -85,7 +85,7 @@ public class NodeMember { } public void setParentId(Integer parentId) { - this.parentId = Optional.ofNullable(parentId).orElse(0) == 0 ? null : parentId; + this.parentId = parentId == null || parentId == 0 ? null : parentId; updateParent.update(this.parentId, nodeId, userId); } } diff --git a/src/de/steamwar/sql/SchematicNode.java b/src/de/steamwar/sql/SchematicNode.java index 594b20a..9142154 100644 --- a/src/de/steamwar/sql/SchematicNode.java +++ b/src/de/steamwar/sql/SchematicNode.java @@ -24,8 +24,6 @@ import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; import java.sql.Timestamp; import java.time.Instant; import java.util.*; @@ -38,7 +36,7 @@ public class SchematicNode { new SqlTypeMapper<>(SchematicNode.class, null, (rs, identifier) -> { throw new SecurityException("SchematicNode cannot be used as type (recursive select)"); }, (st, index, value) -> st.setInt(index, value.nodeId)); } - protected static final Map>> TAB_CACHE = new HashMap<>(); + private static final Map>> TAB_CACHE = new HashMap<>(); public static void clear() { TAB_CACHE.clear(); } From 2e39d677d2c9b6518886db620e571f564009ca14 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sun, 15 Jan 2023 21:10:35 +0100 Subject: [PATCH 08/10] Add Copyright --- src/de/steamwar/sql/SchematicNode.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/de/steamwar/sql/SchematicNode.java b/src/de/steamwar/sql/SchematicNode.java index 9142154..b0064c6 100644 --- a/src/de/steamwar/sql/SchematicNode.java +++ b/src/de/steamwar/sql/SchematicNode.java @@ -41,10 +41,7 @@ public class SchematicNode { TAB_CACHE.clear(); } - private static final String[] fields = {"NodeId", "NodeOwner", "NodeName", "ParentNode", "LastUpdate", "NodeItem", "NodeType", "NodeRank", "ReplaceColor", "AllowReplay", "NodeFormat"}; - private static String nodeSelectCreator(String itemPrefix) { - return "SELECT " + Arrays.stream(fields).map(s -> itemPrefix + s).collect(Collectors.joining(", ")) + ", NodeOwner AS EffectiveOwner FROM SchematicNode "; - } + private static final String nodeSelector = "SELECT NodeId, NodeOwner, NodeOwner AS EffectiveOwner, NodeName, ParentNode, LastUpdate, NodeItem, NodeType, NodeRank, ReplaceColor, AllowReplay, NodeFormat FROM SchematicNode "; private static final Table table = new Table<>(SchematicNode.class); private static final Statement create = table.insertFields(true, "NodeOwner", "NodeName", "ParentNode", "NodeItem", "NodeType"); @@ -53,10 +50,10 @@ public class SchematicNode { private static final SelectStatement byId = table.select(Table.PRIMARY); private static final SelectStatement byOwnerNameParent = table.select("OwnerNameParent"); - private static final SelectStatement byParent = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE ParentNode <=> ? ORDER BY NodeName"); - private static final SelectStatement dirsByParent = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE ParentNode" + Statement.NULL_SAFE_EQUALS + "? AND NodeType is NULL ORDER BY NodeName"); - private static final SelectStatement byOwnerType = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE NodeOwner = ? AND NodeType = ? ORDER BY NodeName"); - private static final SelectStatement byType = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE NodeType = ? ORDER BY NodeName"); + private static final SelectStatement byParent = new SelectStatement<>(table, nodeSelector + "WHERE ParentNode" + Statement.NULL_SAFE_EQUALS + "? ORDER BY NodeName"); + private static final SelectStatement dirsByParent = new SelectStatement<>(table, nodeSelector + "WHERE ParentNode" + Statement.NULL_SAFE_EQUALS + "? AND NodeType is NULL ORDER BY NodeName"); + private static final SelectStatement byOwnerType = new SelectStatement<>(table, nodeSelector + "WHERE NodeOwner = ? AND NodeType = ? ORDER BY NodeName"); + private static final SelectStatement byType = new SelectStatement<>(table, nodeSelector + "WHERE NodeType = ? ORDER BY NodeName"); private static final SelectStatement all = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? ORDER BY NodeName"); private static final SelectStatement list = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND ParentNode" + Statement.NULL_SAFE_EQUALS + "? ORDER BY NodeName"); private static final SelectStatement byParentName = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND ParentNode" + Statement.NULL_SAFE_EQUALS + "? AND NodeName = ? ORDER BY NodeName"); From d30650bad30d53b5fb6c4e5c9499b71c577cf849 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Mon, 16 Jan 2023 16:33:17 +0100 Subject: [PATCH 09/10] Fixes "0 wird nicht benutzt" --- src/de/steamwar/sql/NodeMember.java | 2 +- src/de/steamwar/sql/SchematicNode.java | 22 ++++++++++------------ 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/de/steamwar/sql/NodeMember.java b/src/de/steamwar/sql/NodeMember.java index a952028..e25764e 100644 --- a/src/de/steamwar/sql/NodeMember.java +++ b/src/de/steamwar/sql/NodeMember.java @@ -85,7 +85,7 @@ public class NodeMember { } public void setParentId(Integer parentId) { - this.parentId = parentId == null || parentId == 0 ? null : parentId; + this.parentId = parentId; updateParent.update(this.parentId, nodeId, userId); } } diff --git a/src/de/steamwar/sql/SchematicNode.java b/src/de/steamwar/sql/SchematicNode.java index b0064c6..ca03c0a 100644 --- a/src/de/steamwar/sql/SchematicNode.java +++ b/src/de/steamwar/sql/SchematicNode.java @@ -48,7 +48,7 @@ public class SchematicNode { private static final Statement update = table.update(Table.PRIMARY, "NodeName", "ParentNode", "NodeItem", "NodeType", "NodeRank", "ReplaceColor", "AllowReplay", "NodeFormat"); private static final Statement delete = table.delete(Table.PRIMARY); - private static final SelectStatement byId = table.select(Table.PRIMARY); + private static final SelectStatement byId = new SelectStatement<>(table, nodeSelector + "WHERE NodeId = ?"); private static final SelectStatement byOwnerNameParent = table.select("OwnerNameParent"); private static final SelectStatement byParent = new SelectStatement<>(table, nodeSelector + "WHERE ParentNode" + Statement.NULL_SAFE_EQUALS + "? ORDER BY NodeName"); private static final SelectStatement dirsByParent = new SelectStatement<>(table, nodeSelector + "WHERE ParentNode" + Statement.NULL_SAFE_EQUALS + "? AND NodeType is NULL ORDER BY NodeName"); @@ -58,10 +58,10 @@ public class SchematicNode { private static final SelectStatement list = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND ParentNode" + Statement.NULL_SAFE_EQUALS + "? ORDER BY NodeName"); private static final SelectStatement byParentName = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND ParentNode" + Statement.NULL_SAFE_EQUALS + "? AND NodeName = ? ORDER BY NodeName"); private static final SelectStatement schematicAccessibleForUser = new SelectStatement<>(table, "SELECT COUNT(DISTINCT NodeId) FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND NodeId = ?"); - private static final SelectStatement accessibleByUserTypeInParent = new SelectStatement<>(table, "WITH RECURSIVE RSN AS (SELECT NodeId, ParentNode FROM EffectiveSchematicNode WHERE NodeType = ? AND EffectiveOwner = ? UNION SELECT SN.NodeId, SN.ParentNode FROM RSN, EffectiveSchematicNode SN WHERE SN.NodeId = RSN.ParentNode AND EffectiveOwner = ?) SELECT SN.NodeId, SN.NodeOwner, ? AS EffectiveOwner, SN.NodeName, RSN.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId WHERE RSN.ParentNode" + Statement.NULL_SAFE_EQUALS + "?"); + private static final SelectStatement accessibleByUserTypeInParent = new SelectStatement<>(table, "WITH RECURSIVE RSN AS (SELECT NodeId, ParentNode FROM EffectiveSchematicNode WHERE NodeType = ? AND EffectiveOwner = ? UNION SELECT SN.NodeId, SN.ParentNode FROM RSN, EffectiveSchematicNode SN WHERE SN.NodeId = RSN.ParentNode AND EffectiveOwner = ?) SELECT SN.NodeId, SN.NodeOwner, ? AS EffectiveOwner, SN.NodeName, RSN.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank, SN.ReplaceColor, SN.AllowReplay, SN.NodeFormat FROM RSN INNER JOIN SchematicNode SN ON RSN.NodeId = SN.NodeId WHERE RSN.ParentNode" + Statement.NULL_SAFE_EQUALS + "?"); private static final SelectStatement accessibleByUserType = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND NodeType = ?"); private static final SelectStatement byIdAndUser = new SelectStatement<>(table, "SELECT * FROM EffectiveSchematicNode WHERE EffectiveOwner = ? AND NodeId = ?"); - private static final SelectStatement allParentsOfNode = new SelectStatement<>(table, "WITH RECURSIVE R AS (SELECT NodeId, ParentNode FROM EffectiveSchematicNode WHERE NodeId = ? AND EffectiveOwner = ? UNION SELECT E.NodeId, E.ParentNode FROM R, EffectiveSchematicNode E WHERE R.ParentNode = E.NodeId AND E.EffectiveOwner = ?) SELECT SN.NodeId, SN.NodeOwner, ? AS EffectiveOwner, SN.NodeName, R.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank FROM R INNER JOIN SchematicNode SN ON SN.NodeId = R.NodeId"); + private static final SelectStatement allParentsOfNode = new SelectStatement<>(table, "WITH RECURSIVE R AS (SELECT NodeId, ParentNode FROM EffectiveSchematicNode WHERE NodeId = ? AND EffectiveOwner = ? UNION SELECT E.NodeId, E.ParentNode FROM R, EffectiveSchematicNode E WHERE R.ParentNode = E.NodeId AND E.EffectiveOwner = ?) SELECT SN.NodeId, SN.NodeOwner, ? AS EffectiveOwner, SN.NodeName, R.ParentNode, SN.LastUpdate, SN.NodeItem, SN.NodeType, SN.NodeRank, SN.ReplaceColor, SN.AllowReplay, SN.NodeFormat FROM R INNER JOIN SchematicNode SN ON SN.NodeId = R.NodeId"); static { NodeMember.init(); @@ -71,7 +71,7 @@ public class SchematicNode { private final int nodeId; @Field(keys = {"OwnerNameParent"}) private final int nodeOwner; - @Field + @Field(def = "0") @Getter private final int effectiveOwner; @Field(keys = {"OwnerNameParent"}) @@ -161,7 +161,7 @@ public class SchematicNode { } public static List parentsOfNode(SteamwarUser user, Integer id) { - return allParentsOfNode.listSelect(id, user, user, user).stream().filter(n -> n.getId() != id).collect(Collectors.toList()); + return allParentsOfNode.listSelect(id, user, user, user); } private static Map> map(List in) { @@ -290,7 +290,7 @@ public class SchematicNode { } if (s.contains("/")) { String[] layers = s.split("/"); - Optional currentNode = Optional.ofNullable(SchematicNode.byParentName(user, 0, layers[0])); + Optional currentNode = Optional.ofNullable(SchematicNode.byParentName(user, null, layers[0])); for (int i = 1; i < layers.length; i++) { int finalI = i; Optional node = currentNode.map(effectiveSchematicNode -> SchematicNode.byParentName(user, effectiveSchematicNode.getId(), layers[finalI])); @@ -305,7 +305,7 @@ public class SchematicNode { } return currentNode.orElse(null); } else { - return SchematicNode.byParentName(user, 0, s); + return SchematicNode.byParentName(user, null, s); } } @@ -484,14 +484,12 @@ public class SchematicNode { return ((SchematicNode) obj).getId() == nodeId; } - @Deprecated public String generateBreadcrumbs(SteamwarUser user) { - return generateBreadcrumbs(); + return byIdAndUser(user, nodeId).generateBreadcrumbs(); } - @Deprecated public String generateBreadcrumbs(String split, SteamwarUser user) { - return generateBreadcrumbs(split); + return byIdAndUser(user, nodeId).generateBreadcrumbs(split); } public String generateBreadcrumbs() { @@ -556,7 +554,7 @@ public class SchematicNode { List nodes = SchematicNode.list(user, pa.getId()); nodes.forEach(node -> list.add((sws ? "/" : "") + node.generateBreadcrumbs())); } else { - List nodes = SchematicNode.list(user, 0); + List nodes = SchematicNode.list(user, null); nodes.forEach(node -> list.add((sws ? "/" : "") + node.getName() + (node.isDir() ? "/" : ""))); } list.remove("//copy"); From 785f31a728726265d7075fb6d92e9c794cc66b54 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Mon, 16 Jan 2023 16:40:01 +0100 Subject: [PATCH 10/10] Fixes "0 wird nicht benutzt" --- src/de/steamwar/sql/SchematicNode.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/de/steamwar/sql/SchematicNode.java b/src/de/steamwar/sql/SchematicNode.java index ca03c0a..5a8258f 100644 --- a/src/de/steamwar/sql/SchematicNode.java +++ b/src/de/steamwar/sql/SchematicNode.java @@ -49,7 +49,7 @@ public class SchematicNode { private static final Statement delete = table.delete(Table.PRIMARY); private static final SelectStatement byId = new SelectStatement<>(table, nodeSelector + "WHERE NodeId = ?"); - private static final SelectStatement byOwnerNameParent = table.select("OwnerNameParent"); + private static final SelectStatement byOwnerNameParent = new SelectStatement<>(table, nodeSelector + "WHERE NodeOwner = ? AND NodeName = ? AND ParentNode = ?"); private static final SelectStatement byParent = new SelectStatement<>(table, nodeSelector + "WHERE ParentNode" + Statement.NULL_SAFE_EQUALS + "? ORDER BY NodeName"); private static final SelectStatement dirsByParent = new SelectStatement<>(table, nodeSelector + "WHERE ParentNode" + Statement.NULL_SAFE_EQUALS + "? AND NodeType is NULL ORDER BY NodeName"); private static final SelectStatement byOwnerType = new SelectStatement<>(table, nodeSelector + "WHERE NodeOwner = ? AND NodeType = ? ORDER BY NodeName");