Dieser Commit ist enthalten in:
Ursprung
9043ab9dc5
Commit
662c3cdd9b
@ -22,6 +22,7 @@ package de.steamwar.sql;
|
|||||||
import de.steamwar.sql.internal.Field;
|
import de.steamwar.sql.internal.Field;
|
||||||
import de.steamwar.sql.internal.SelectStatement;
|
import de.steamwar.sql.internal.SelectStatement;
|
||||||
import de.steamwar.sql.internal.Table;
|
import de.steamwar.sql.internal.Table;
|
||||||
|
import de.steamwar.sql.v2.SchematicNode;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
|
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
|
@ -19,134 +19,43 @@
|
|||||||
|
|
||||||
package de.steamwar.sql;
|
package de.steamwar.sql;
|
||||||
|
|
||||||
import de.steamwar.sql.internal.*;
|
|
||||||
import lombok.AccessLevel;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.PrintStream;
|
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public class SchematicNode {
|
public class SchematicNode {
|
||||||
|
|
||||||
static {
|
private static int nullableInt(Integer i) {
|
||||||
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));
|
return i == null ? 0 : i;
|
||||||
}
|
}
|
||||||
|
private final de.steamwar.sql.v2.SchematicNode node;
|
||||||
private static final Map<Integer, Map<String, List<String>>> TAB_CACHE = new HashMap<>();
|
|
||||||
public static void clear() {
|
|
||||||
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(", ")) + " FROM SchematicNode ";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Table<SchematicNode> table = new Table<>(SchematicNode.class);
|
|
||||||
private static final Statement create = table.insertFields(true, "NodeOwner", "NodeName", "ParentNode", "NodeItem", "NodeType");
|
|
||||||
private static final Statement update = table.insertAll();
|
|
||||||
private static final Statement delete = table.delete(Table.PRIMARY);
|
|
||||||
|
|
||||||
private static final SelectStatement<SchematicNode> byId = table.select(Table.PRIMARY);
|
|
||||||
private static final SelectStatement<SchematicNode> byOwnerNameParent = table.select("OwnerNameParent");
|
|
||||||
private static final SelectStatement<SchematicNode> byOwnerNameParent_null = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE NodeOwner = ? AND NodeName = ? AND ParentNode is NULL");
|
|
||||||
private static final SelectStatement<SchematicNode> byParent = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE ParentNode = ? ORDER BY NodeName");
|
|
||||||
private static final SelectStatement<SchematicNode> byParent_null = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE ParentNode is NULL ORDER BY NodeName");
|
|
||||||
private static final SelectStatement<SchematicNode> dirsByParent = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE ParentNode = ? AND NodeType is NULL ORDER BY NodeName");
|
|
||||||
private static final SelectStatement<SchematicNode> dirsByParent_null = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE ParentNode is NULL AND NodeType is NULL ORDER BY NodeName");
|
|
||||||
private static final SelectStatement<SchematicNode> byParentName = table.selectFields("NodeName", "ParentNode");
|
|
||||||
private static final SelectStatement<SchematicNode> byParentName_null = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE NodeName = ? AND ParentNode is NULL");
|
|
||||||
private static final SelectStatement<SchematicNode> 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<SchematicNode> 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<SchematicNode> 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<SchematicNode> byOwnerType = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE NodeOwner = ? AND NodeType = ? ORDER BY NodeName");
|
|
||||||
private static final SelectStatement<SchematicNode> byType = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE NodeType = ? ORDER BY NodeName");
|
|
||||||
private static final SelectStatement<SchematicNode> 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<SchematicNode> 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<SchematicNode> 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");
|
|
||||||
|
|
||||||
@Field(keys = {Table.PRIMARY}, autoincrement = true)
|
|
||||||
private final int nodeId;
|
|
||||||
@Field(keys = {"OwnerNameParent"})
|
|
||||||
private final int nodeOwner;
|
|
||||||
@Field(keys = {"OwnerNameParent"})
|
|
||||||
private String nodeName;
|
|
||||||
@Field(keys = {"OwnerNameParent"}, nullable = true)
|
|
||||||
private Integer parentNode;
|
|
||||||
@Field(def = "CURRENT_TIMESTAMP")
|
|
||||||
private Timestamp lastUpdate;
|
|
||||||
@Field(def = "''")
|
|
||||||
private String nodeItem;
|
|
||||||
@Field(def = "'normal'", nullable = true)
|
|
||||||
private SchematicType nodeType;
|
|
||||||
@Field(def = "0")
|
|
||||||
private int nodeRank;
|
|
||||||
@Field(def = "1")
|
|
||||||
private boolean replaceColor;
|
|
||||||
@Field(def = "1")
|
|
||||||
private boolean allowReplay;
|
|
||||||
@Setter(AccessLevel.PACKAGE)
|
|
||||||
@Field(def = "1")
|
|
||||||
private boolean nodeFormat;
|
|
||||||
|
|
||||||
private final Map<Integer, String> brCache = new HashMap<>();
|
private final Map<Integer, String> brCache = new HashMap<>();
|
||||||
|
|
||||||
public SchematicNode(
|
public SchematicNode(de.steamwar.sql.v2.SchematicNode node) {
|
||||||
int nodeId,
|
this.node = node;
|
||||||
int nodeOwner,
|
|
||||||
String nodeName,
|
|
||||||
Integer parentNode,
|
|
||||||
Timestamp lastUpdate,
|
|
||||||
String nodeItem,
|
|
||||||
SchematicType nodeType,
|
|
||||||
int nodeRank,
|
|
||||||
boolean replaceColor,
|
|
||||||
boolean allowReplay,
|
|
||||||
boolean nodeFormat
|
|
||||||
) {
|
|
||||||
this.nodeId = nodeId;
|
|
||||||
this.nodeOwner = nodeOwner;
|
|
||||||
this.nodeName = nodeName;
|
|
||||||
this.parentNode = parentNode;
|
|
||||||
this.nodeItem = nodeItem;
|
|
||||||
this.nodeType = nodeType;
|
|
||||||
this.lastUpdate = lastUpdate;
|
|
||||||
this.nodeRank = nodeRank;
|
|
||||||
this.replaceColor = replaceColor;
|
|
||||||
this.allowReplay = allowReplay;
|
|
||||||
this.nodeFormat = nodeFormat;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SchematicNode createSchematic(int owner, String name, Integer parent) {
|
public static SchematicNode createSchematic(int owner, String name, Integer parent) {
|
||||||
return createSchematicNode(owner, name, parent, SchematicType.Normal.toDB(), "");
|
return new SchematicNode(de.steamwar.sql.v2.SchematicNode.createSchematic(SteamwarUser.get(owner), name, nullableInt(parent)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SchematicNode createSchematicDirectory(int owner, String name, Integer parent) {
|
public static SchematicNode createSchematicDirectory(int owner, String name, Integer parent) {
|
||||||
return createSchematicNode(owner, name, parent, null, "");
|
return new SchematicNode(de.steamwar.sql.v2.SchematicNode.createSchematicNode(SteamwarUser.get(owner), name, nullableInt(parent), null, ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SchematicNode createSchematicNode(int owner, String name, Integer parent, String type, String item) {
|
public static SchematicNode createSchematicNode(int owner, String name, Integer parent, String type, String item) {
|
||||||
if (parent != null && parent == 0)
|
return new SchematicNode(de.steamwar.sql.v2.SchematicNode.createSchematicNode(SteamwarUser.get(owner), name, nullableInt(parent), type, item));
|
||||||
parent = null;
|
|
||||||
int nodeId = create.insertGetKey(owner, name, parent, type, item);
|
|
||||||
return getSchematicNode(nodeId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SchematicNode getSchematicNode(int owner, String name, SchematicNode parent) {
|
public static SchematicNode getSchematicNode(int owner, String name, SchematicNode parent) {
|
||||||
return getSchematicNode(owner, name, parent.getId());
|
return de.steamwar.sql.v2.SchematicNode.getSchematicNode(SteamwarUser.get(owner), name, parent.node).map(SchematicNode::new).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SchematicNode getSchematicNode(int owner, String name, Integer parent) {
|
public static SchematicNode getSchematicNode(int owner, String name, Integer parent) {
|
||||||
if (parent == null || parent == 0)
|
return de.steamwar.sql.v2.SchematicNode.getSchematicNode(SteamwarUser.get(owner), name, de.steamwar.sql.v2.SchematicNode.getSchematicNode(nullableInt(parent))).map(SchematicNode::new).orElse(null);
|
||||||
return byOwnerNameParent_null.select(owner, name);
|
|
||||||
return byOwnerNameParent.select(owner, name, parent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<SchematicNode> getSchematicNodeInNode(SchematicNode parent) {
|
public static List<SchematicNode> getSchematicNodeInNode(SchematicNode parent) {
|
||||||
@ -154,20 +63,11 @@ public class SchematicNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static List<SchematicNode> getSchematicNodeInNode(Integer parent) {
|
public static List<SchematicNode> getSchematicNodeInNode(Integer parent) {
|
||||||
if(parent == null || parent == 0) {
|
return de.steamwar.sql.v2.SchematicNode.getSchematicNodeInNode(de.steamwar.sql.v2.SchematicNode.getSchematicNode(nullableInt(parent))).stream().map(SchematicNode::new).collect(Collectors.toList());
|
||||||
rootWarning();
|
|
||||||
return byParent_null.listSelect();
|
|
||||||
}
|
|
||||||
|
|
||||||
return byParent.listSelect(parent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<SchematicNode> getSchematicDirectoryInNode(Integer parent) {
|
public static List<SchematicNode> getSchematicDirectoryInNode(Integer parent) {
|
||||||
if(parent == null || parent == 0) {
|
return de.steamwar.sql.v2.SchematicNode.getSchematicDirectoryInNode(de.steamwar.sql.v2.SchematicNode.getSchematicNode(nullableInt(parent))).stream().map(SchematicNode::new).collect(Collectors.toList());
|
||||||
rootWarning();
|
|
||||||
return dirsByParent_null.listSelect();
|
|
||||||
}
|
|
||||||
return dirsByParent.listSelect(parent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@ -181,69 +81,44 @@ public class SchematicNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static SchematicNode getSchematicNode(String name, Integer parent) {
|
public static SchematicNode getSchematicNode(String name, Integer parent) {
|
||||||
if(parent == null || parent == 0) {
|
return de.steamwar.sql.v2.SchematicNode.getSchematicNode(name, de.steamwar.sql.v2.SchematicNode.getSchematicNode(nullableInt(parent))).map(SchematicNode::new).orElse(null);
|
||||||
rootWarning();
|
|
||||||
return byParentName_null.select(name);
|
|
||||||
}
|
|
||||||
return byParentName.select(name, parent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SchematicNode getSchematicNode(int id) {
|
public static SchematicNode getSchematicNode(int id) {
|
||||||
return byId.select(id);
|
return new SchematicNode(de.steamwar.sql.v2.SchematicNode.getSchematicNode(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<SchematicNode> getAccessibleSchematicsOfTypeInParent(int owner, String schemType, Integer parent) {
|
public static List<SchematicNode> getAccessibleSchematicsOfTypeInParent(int owner, String schemType, Integer parent) {
|
||||||
if(parent == null || parent == 0)
|
return de.steamwar.sql.v2.SchematicNode.getAccessibleSchematicsOfTypeInParent(SteamwarUser.get(owner), schemType, de.steamwar.sql.v2.SchematicNode.getSchematicNode(nullableInt(parent))).stream().map(SchematicNode::new).collect(Collectors.toList());
|
||||||
return accessibleByUserTypeParent_Null.listSelect(owner, owner, schemType);
|
|
||||||
return accessibleByUserTypeParent.listSelect(owner, owner, schemType, parent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<SchematicNode> getAllAccessibleSchematicsOfType(int user, String schemType) {
|
public static List<SchematicNode> getAllAccessibleSchematicsOfType(int user, String schemType) {
|
||||||
return accessibleByUserType.listSelect(user, user, schemType);
|
return de.steamwar.sql.v2.SchematicNode.getAllAccessibleSchematicsOfType(SteamwarUser.get(user), SchematicType.fromDB(schemType)).stream().map(SchematicNode::new).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<SchematicNode> getAllSchematicsOfType(int owner, String schemType) {
|
public static List<SchematicNode> getAllSchematicsOfType(int owner, String schemType) {
|
||||||
return byOwnerType.listSelect(owner, schemType);
|
return de.steamwar.sql.v2.SchematicNode.getAllSchematicsOfType(SteamwarUser.get(owner), SchematicType.fromDB(schemType)).stream().map(SchematicNode::new).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public static List<SchematicNode> getAllSchematicsOfType(String schemType) {
|
public static List<SchematicNode> getAllSchematicsOfType(String schemType) {
|
||||||
return byType.listSelect(schemType);
|
return de.steamwar.sql.v2.SchematicNode.getAllSchematicsOfType(SchematicType.fromDB(schemType)).stream().map(SchematicNode::new).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<SchematicNode> getAllSchematicsOfType(SchematicType schemType) {
|
public static List<SchematicNode> getAllSchematicsOfType(SchematicType schemType) {
|
||||||
return byType.listSelect(schemType);
|
return de.steamwar.sql.v2.SchematicNode.getAllSchematicsOfType(schemType).stream().map(SchematicNode::new).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<SchematicNode> deepGet(Integer parent, Predicate<SchematicNode> filter) {
|
public static List<SchematicNode> deepGet(Integer parent, Predicate<SchematicNode> filter) {
|
||||||
List<SchematicNode> finalList = new ArrayList<>();
|
return de.steamwar.sql.v2.SchematicNode.deepGet(de.steamwar.sql.v2.SchematicNode.getSchematicNode(nullableInt(parent)), schematicNode -> filter.test(new SchematicNode(schematicNode))).stream().map(SchematicNode::new).collect(Collectors.toList());
|
||||||
List<SchematicNode> nodes = SchematicNode.getSchematicNodeInNode(parent);
|
|
||||||
nodes.forEach(node -> {
|
|
||||||
if (node.isDir()) {
|
|
||||||
finalList.addAll(deepGet(node.getId(), filter));
|
|
||||||
} else {
|
|
||||||
if (filter.test(node))
|
|
||||||
finalList.add(node);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return finalList;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<SchematicNode> getSchematicsAccessibleByUser(int user, Integer parent) {
|
public static List<SchematicNode> getSchematicsAccessibleByUser(int user, Integer parent) {
|
||||||
if (parent == null || parent == 0)
|
return de.steamwar.sql.v2.SchematicNode.getSchematicsAccessibleByUser(SteamwarUser.get(user), de.steamwar.sql.v2.SchematicNode.getSchematicNode(nullableInt(parent))).stream().map(SchematicNode::new).collect(Collectors.toList());
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<SchematicNode> getAllSchematicsAccessibleByUser(int user) {
|
public static List<SchematicNode> getAllSchematicsAccessibleByUser(int user) {
|
||||||
return allAccessibleByUser.listSelect(user, user);
|
return de.steamwar.sql.v2.SchematicNode.getAllSchematicsAccessibleByUser(SteamwarUser.get(user)).stream().map(SchematicNode::new).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<SchematicNode> getAllParentsOfNode(SchematicNode node) {
|
public static List<SchematicNode> getAllParentsOfNode(SchematicNode node) {
|
||||||
@ -251,55 +126,15 @@ public class SchematicNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static List<SchematicNode> getAllParentsOfNode(int node) {
|
public static List<SchematicNode> getAllParentsOfNode(int node) {
|
||||||
return allParentsOfNode.listSelect(node);
|
return de.steamwar.sql.v2.SchematicNode.getAllParentsOfNode(de.steamwar.sql.v2.SchematicNode.getSchematicNode(node)).stream().map(SchematicNode::new).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SchematicNode getNodeFromPath(SteamwarUser user, String s) {
|
public static SchematicNode getNodeFromPath(SteamwarUser user, String s) {
|
||||||
if (s.startsWith("/")) {
|
return de.steamwar.sql.v2.SchematicNode.getNodeFromPath(user, s).map(SchematicNode::new).orElse(null);
|
||||||
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<SchematicNode> 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<SchematicNode> filterSchems(int user, Predicate<SchematicNode> filter) {
|
public static List<SchematicNode> filterSchems(int user, Predicate<SchematicNode> filter) {
|
||||||
List<SchematicNode> finalList = new ArrayList<>();
|
return de.steamwar.sql.v2.SchematicNode.filterSchems(SteamwarUser.get(user), schematicNode -> filter.test(new SchematicNode(schematicNode))).stream().map(SchematicNode::new).collect(Collectors.toList());
|
||||||
List<SchematicNode> nodes = getSchematicsAccessibleByUser(user, null);
|
|
||||||
nodes.forEach(node -> {
|
|
||||||
if (node.isDir()) {
|
|
||||||
finalList.addAll(deepGet(node.getId(), filter));
|
|
||||||
} else {
|
|
||||||
if (filter.test(node))
|
|
||||||
finalList.add(node);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return finalList;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@ -308,236 +143,139 @@ public class SchematicNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int getId() {
|
public int getId() {
|
||||||
return nodeId;
|
return node.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getOwner() {
|
public int getOwner() {
|
||||||
return nodeOwner;
|
return node.getOwner().getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return nodeName;
|
return node.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
this.nodeName = name;
|
node.setName(name);
|
||||||
updateDB();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getParent() {
|
public Integer getParent() {
|
||||||
return parentNode;
|
return node.getParent() == null ? null : node.getParent().getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setParent(Integer parent) {
|
public void setParent(Integer parent) {
|
||||||
this.parentNode = parent;
|
node.setParent(de.steamwar.sql.v2.SchematicNode.getSchematicNode(nullableInt(parent)));
|
||||||
updateDB();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getItem() {
|
public String getItem() {
|
||||||
if (nodeItem.isEmpty()) {
|
return node.getItem();
|
||||||
return isDir() ? "CHEST" : "CAULDRON_ITEM";
|
|
||||||
}
|
|
||||||
return nodeItem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setItem(String item) {
|
public void setItem(String item) {
|
||||||
this.nodeItem = item;
|
node.setItem(item);
|
||||||
updateDB();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public String getType() {
|
public String getType() {
|
||||||
return nodeType.name();
|
return node.getSchemtype().toDB();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setType(String type) {
|
public void setType(String type) {
|
||||||
if(isDir())
|
node.setSchemtype(SchematicType.fromDB(type));
|
||||||
throw new SecurityException("Node is Directory");
|
|
||||||
this.nodeType = SchematicType.fromDB(type);
|
|
||||||
updateDB();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDir() {
|
public boolean isDir() {
|
||||||
return nodeType == null;
|
return node.isDir();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getSchemFormat() {
|
public boolean getSchemFormat() {
|
||||||
if(isDir())
|
return node.getSchemFormat();
|
||||||
throw new SecurityException("Node is Directory");
|
|
||||||
return nodeFormat;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getRank() {
|
public int getRank() {
|
||||||
if(isDir())
|
return node.getRank();
|
||||||
throw new SecurityException("Node is Directory");
|
|
||||||
return nodeRank;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public int getRankUnsafe() {
|
public int getRankUnsafe() {
|
||||||
return nodeRank;
|
return node.getRank();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRank(int rank) {
|
public void setRank(int rank) {
|
||||||
if(isDir())
|
node.setRank(rank);
|
||||||
throw new SecurityException("Node is Directory");
|
|
||||||
this.nodeRank = rank;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SchematicType getSchemtype() {
|
public SchematicType getSchemtype() {
|
||||||
if(isDir())
|
return node.getSchemtype();
|
||||||
throw new SecurityException("Is Directory");
|
|
||||||
return nodeType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSchemtype(SchematicType type) {
|
public void setSchemtype(SchematicType type) {
|
||||||
if(isDir())
|
node.setSchemtype(type);
|
||||||
throw new SecurityException("Is Directory");
|
|
||||||
this.nodeType = type;
|
|
||||||
updateDB();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean replaceColor() {
|
public boolean replaceColor() {
|
||||||
return replaceColor;
|
return node.replaceColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setReplaceColor(boolean replaceColor) {
|
public void setReplaceColor(boolean replaceColor) {
|
||||||
if(isDir())
|
node.setReplaceColor(replaceColor);
|
||||||
throw new SecurityException("Is Directory");
|
|
||||||
this.replaceColor = replaceColor;
|
|
||||||
updateDB();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean allowReplay() {
|
public boolean allowReplay() {
|
||||||
return allowReplay;
|
return node.allowReplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAllowReplay(boolean allowReplay) {
|
public void setAllowReplay(boolean allowReplay) {
|
||||||
if(isDir())
|
node.setAllowReplay(allowReplay);
|
||||||
throw new SecurityException("Is Directory");
|
|
||||||
this.allowReplay = allowReplay;
|
|
||||||
updateDB();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SchematicNode getParentNode() {
|
public SchematicNode getParentNode() {
|
||||||
if(parentNode == null) return null;
|
return node.getParent() == de.steamwar.sql.v2.SchematicNode.ROOT ? null : new SchematicNode(node.getParent());
|
||||||
return SchematicNode.getSchematicNode(parentNode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getElo(int season) {
|
public int getElo(int season) {
|
||||||
return SchemElo.getElo(this, season);
|
return node.getElo(season);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean accessibleByUser(int user) {
|
public boolean accessibleByUser(int user) {
|
||||||
return NodeMember.getNodeMember(nodeId, user) != null;
|
return node.accessibleByUser(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<NodeMember> getMembers() {
|
public Set<NodeMember> getMembers() {
|
||||||
return NodeMember.getNodeMembers(nodeId);
|
return node.getMembers();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Timestamp getLastUpdate() {
|
public Timestamp getLastUpdate() {
|
||||||
return lastUpdate;
|
return node.getLastUpdate();
|
||||||
}
|
|
||||||
|
|
||||||
private void updateDB() {
|
|
||||||
this.lastUpdate = Timestamp.from(Instant.now());
|
|
||||||
update.update(nodeId, nodeOwner, nodeName, parentNode, nodeItem, nodeType, lastUpdate, nodeRank, replaceColor, allowReplay, nodeFormat);
|
|
||||||
this.brCache.clear();
|
|
||||||
TAB_CACHE.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete() {
|
public void delete() {
|
||||||
delete.update(nodeId);
|
node.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return nodeId;
|
return node.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (!(obj instanceof SchematicNode))
|
return node.equals(obj);
|
||||||
return false;
|
|
||||||
|
|
||||||
return ((SchematicNode) obj).getId() == nodeId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String generateBreadcrumbs(SteamwarUser user) {
|
public String generateBreadcrumbs(SteamwarUser user) {
|
||||||
return brCache.computeIfAbsent(user.getId(), integer -> generateBreadcrumbs("/", user));
|
return node.generateBreadcrumbs(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String generateBreadcrumbs(String split, SteamwarUser user) {
|
public String generateBreadcrumbs(String split, SteamwarUser user) {
|
||||||
StringBuilder builder = new StringBuilder(getName());
|
return node.generateBreadcrumbs(split, user);
|
||||||
SchematicNode currentNode = this;
|
|
||||||
if (currentNode.isDir()) builder.append("/");
|
|
||||||
final Set<NodeMember> 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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final List<String> FORBIDDEN_NAMES = Collections.unmodifiableList(Arrays.asList("public"));
|
|
||||||
public static boolean invalidSchemName(String[] layers) {
|
public static boolean invalidSchemName(String[] layers) {
|
||||||
for (String layer : layers) {
|
return de.steamwar.sql.v2.SchematicNode.invalidSchemName(layers);
|
||||||
if (layer.isEmpty()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (layer.contains("/") ||
|
|
||||||
layer.contains("\\") ||
|
|
||||||
layer.contains("<") ||
|
|
||||||
layer.contains(">") ||
|
|
||||||
layer.contains("^") ||
|
|
||||||
layer.contains("°") ||
|
|
||||||
layer.contains("'") ||
|
|
||||||
layer.contains("\"") ||
|
|
||||||
layer.contains(" ")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if(FORBIDDEN_NAMES.contains(layer.toLowerCase())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<String> getNodeTabcomplete(SteamwarUser user, String s) {
|
public static List<String> getNodeTabcomplete(SteamwarUser user, String s) {
|
||||||
boolean sws = s.startsWith("/");
|
return de.steamwar.sql.v2.SchematicNode.getNodeTabcomplete(user, s);
|
||||||
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<String> 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<SchematicNode> nodes = SchematicNode.getSchematicNodeInNode(pa);
|
|
||||||
nodes.forEach(node -> list.add((sws ? "/" : "") + node.generateBreadcrumbs(user)));
|
|
||||||
} else {
|
|
||||||
List<SchematicNode> 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
482
src/de/steamwar/sql/v2/SchematicNode.java
Normale Datei
482
src/de/steamwar/sql/v2/SchematicNode.java
Normale Datei
@ -0,0 +1,482 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.sql.v2;
|
||||||
|
|
||||||
|
import de.steamwar.sql.*;
|
||||||
|
import de.steamwar.sql.internal.*;
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
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;
|
||||||
|
|
||||||
|
public class SchematicNode {
|
||||||
|
|
||||||
|
static {
|
||||||
|
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<Integer, Map<String, List<String>>> TAB_CACHE = new HashMap<>();
|
||||||
|
public static void clear() {
|
||||||
|
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(", ")) + " FROM SchematicNode ";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final SchematicNode ROOT = new SchematicNode(0, 0, "ROOT", 0, Timestamp.from(Instant.now()), "", SchematicType.Normal, 0, false, false, false);
|
||||||
|
|
||||||
|
private static final Table<SchematicNode> table = new Table<>(SchematicNode.class);
|
||||||
|
private static final Statement create = table.insertFields(true, "NodeOwner", "NodeName", "ParentNode", "NodeItem", "NodeType");
|
||||||
|
private static final Statement update = table.insertAll();
|
||||||
|
private static final Statement delete = table.delete(Table.PRIMARY);
|
||||||
|
|
||||||
|
private static final SelectStatement<SchematicNode> byId = table.select(Table.PRIMARY);
|
||||||
|
private static final SelectStatement<SchematicNode> byOwnerNameParent = table.select("OwnerNameParent");
|
||||||
|
private static final SelectStatement<SchematicNode> byParent = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE ParentNode = ? ORDER BY NodeName");
|
||||||
|
private static final SelectStatement<SchematicNode> dirsByParent = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE ParentNode = ? AND NodeType is NULL ORDER BY NodeName");
|
||||||
|
private static final SelectStatement<SchematicNode> byParentName = table.selectFields("NodeName", "ParentNode");
|
||||||
|
private static final SelectStatement<SchematicNode> 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<SchematicNode> 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<SchematicNode> byOwnerType = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE NodeOwner = ? AND NodeType = ? ORDER BY NodeName");
|
||||||
|
private static final SelectStatement<SchematicNode> byType = new SelectStatement<>(table, nodeSelectCreator("") + "WHERE NodeType = ? ORDER BY NodeName");
|
||||||
|
private static final SelectStatement<SchematicNode> 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<SchematicNode> 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<SchematicNode> 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");
|
||||||
|
|
||||||
|
@Field(keys = {Table.PRIMARY}, autoincrement = true)
|
||||||
|
private final int nodeId;
|
||||||
|
@Field(keys = {"OwnerNameParent"})
|
||||||
|
private final int nodeOwner;
|
||||||
|
@Field(keys = {"OwnerNameParent"})
|
||||||
|
private String nodeName;
|
||||||
|
@Field(keys = {"OwnerNameParent"})
|
||||||
|
private int parentNode;
|
||||||
|
@Field(def = "CURRENT_TIMESTAMP")
|
||||||
|
private Timestamp lastUpdate;
|
||||||
|
@Field(def = "''")
|
||||||
|
private String nodeItem;
|
||||||
|
@Field(def = "'normal'", nullable = true)
|
||||||
|
private SchematicType nodeType;
|
||||||
|
@Field(def = "0")
|
||||||
|
private int nodeRank;
|
||||||
|
@Field(def = "1")
|
||||||
|
private boolean replaceColor;
|
||||||
|
@Field(def = "1")
|
||||||
|
private boolean allowReplay;
|
||||||
|
@Setter(AccessLevel.PACKAGE)
|
||||||
|
@Field(def = "1")
|
||||||
|
private boolean nodeFormat;
|
||||||
|
|
||||||
|
private final Map<Integer, String> brCache = new HashMap<>();
|
||||||
|
|
||||||
|
public SchematicNode(
|
||||||
|
int nodeId,
|
||||||
|
int nodeOwner,
|
||||||
|
String nodeName,
|
||||||
|
int parentNode,
|
||||||
|
Timestamp lastUpdate,
|
||||||
|
String nodeItem,
|
||||||
|
SchematicType nodeType,
|
||||||
|
int nodeRank,
|
||||||
|
boolean replaceColor,
|
||||||
|
boolean allowReplay,
|
||||||
|
boolean nodeFormat
|
||||||
|
) {
|
||||||
|
this.nodeId = nodeId;
|
||||||
|
this.nodeOwner = nodeOwner;
|
||||||
|
this.nodeName = nodeName;
|
||||||
|
this.parentNode = parentNode;
|
||||||
|
this.nodeItem = nodeItem;
|
||||||
|
this.nodeType = nodeType;
|
||||||
|
this.lastUpdate = lastUpdate;
|
||||||
|
this.nodeRank = nodeRank;
|
||||||
|
this.replaceColor = replaceColor;
|
||||||
|
this.allowReplay = allowReplay;
|
||||||
|
this.nodeFormat = nodeFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SchematicNode createSchematic(SteamwarUser owner, String name, int parent) {
|
||||||
|
return createSchematicNode(owner, name, parent, SchematicType.Normal.toDB(), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SchematicNode createSchematicDirectory(SteamwarUser owner, String name, int parent) {
|
||||||
|
return createSchematicNode(owner, name, parent, null, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SchematicNode createSchematicNode(SteamwarUser owner, String name, int parent, String type, String item) {
|
||||||
|
int nodeId = create.insertGetKey(owner, name, parent, type, item);
|
||||||
|
return getSchematicNode(nodeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Optional<SchematicNode> getSchematicNode(SteamwarUser owner, String name, SchematicNode parent) {
|
||||||
|
return getSchematicNode(owner, name, parent.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Optional<SchematicNode> getSchematicNode(SteamwarUser owner, String name, int parent) {
|
||||||
|
return Optional.ofNullable(byOwnerNameParent.select(owner, name, parent));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<SchematicNode> getSchematicNodeInNode(SchematicNode parent) {
|
||||||
|
if(parent.equals(ROOT)) {
|
||||||
|
rootWarning();
|
||||||
|
}
|
||||||
|
|
||||||
|
return byParent.listSelect(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<SchematicNode> getSchematicDirectoryInNode(SchematicNode parent) {
|
||||||
|
if(parent.equals(ROOT)) {
|
||||||
|
rootWarning();
|
||||||
|
}
|
||||||
|
return dirsByParent.listSelect(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Optional<SchematicNode> getSchematicNode(String name, SchematicNode parent) {
|
||||||
|
if(parent.equals(ROOT)) {
|
||||||
|
rootWarning();
|
||||||
|
}
|
||||||
|
return Optional.ofNullable(byParentName.select(name, parent));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SchematicNode getSchematicNode(int id) {
|
||||||
|
if(id == 0) return ROOT;
|
||||||
|
return Optional.ofNullable(byId.select(id)).orElseThrow(() -> new IllegalStateException("Schematic node " + id + " does not exist"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<SchematicNode> getAccessibleSchematicsOfTypeInParent(SteamwarUser owner, String schemType, SchematicNode parent) {
|
||||||
|
return accessibleByUserTypeParent.listSelect(owner, owner, schemType, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<SchematicNode> getAllAccessibleSchematicsOfType(SteamwarUser user, SchematicType schemType) {
|
||||||
|
return accessibleByUserType.listSelect(user, user, schemType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<SchematicNode> getAllSchematicsOfType(SteamwarUser owner, SchematicType schemType) {
|
||||||
|
return byOwnerType.listSelect(owner, schemType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<SchematicNode> getAllSchematicsOfType(SchematicType schemType) {
|
||||||
|
return byType.listSelect(schemType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<SchematicNode> deepGet(SchematicNode parent, Predicate<SchematicNode> filter) {
|
||||||
|
List<SchematicNode> finalList = new ArrayList<>();
|
||||||
|
List<SchematicNode> nodes = SchematicNode.getSchematicNodeInNode(parent);
|
||||||
|
nodes.forEach(node -> {
|
||||||
|
if (node.isDir()) {
|
||||||
|
finalList.addAll(deepGet(node, filter));
|
||||||
|
} else {
|
||||||
|
if (filter.test(node))
|
||||||
|
finalList.add(node);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return finalList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<SchematicNode> getSchematicsAccessibleByUser(SteamwarUser user, SchematicNode parent) {
|
||||||
|
if (parent.equals(ROOT)) {
|
||||||
|
return accessibleByUser.listSelect(user, user, user, user);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Boolean.TRUE.equals(schematicAccessibleForUser.select(rs -> {
|
||||||
|
rs.next();
|
||||||
|
return rs.getBoolean("Accessible");
|
||||||
|
}, parent, user, user)))
|
||||||
|
return getSchematicNodeInNode(parent);
|
||||||
|
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<SchematicNode> getAllSchematicsAccessibleByUser(SteamwarUser user) {
|
||||||
|
return allAccessibleByUser.listSelect(user, user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<SchematicNode> getAllParentsOfNode(SchematicNode node) {
|
||||||
|
return allParentsOfNode.listSelect(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Optional<SchematicNode> getNodeFromPath(SteamwarUser user, String s) {
|
||||||
|
if (s.startsWith("/")) {
|
||||||
|
s = s.substring(1);
|
||||||
|
}
|
||||||
|
if (s.isEmpty()) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
if (s.contains("/")) {
|
||||||
|
String[] layers = s.split("/");
|
||||||
|
SchematicNode currentNode = null;
|
||||||
|
for (int i = 0; i < layers.length; i++) {
|
||||||
|
int finalI = i;
|
||||||
|
Optional<SchematicNode> node;
|
||||||
|
if (currentNode == null) {
|
||||||
|
node = SchematicNode.getSchematicsAccessibleByUser(user, ROOT).stream().filter(node1 -> node1.getName().equals(layers[finalI])).findAny();
|
||||||
|
} else {
|
||||||
|
node = SchematicNode.getSchematicNode(layers[i], currentNode);
|
||||||
|
}
|
||||||
|
if (!node.isPresent()) {
|
||||||
|
return Optional.empty();
|
||||||
|
} else {
|
||||||
|
currentNode = node.get();
|
||||||
|
if (!currentNode.isDir() && i != layers.length - 1) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Optional.ofNullable(currentNode);
|
||||||
|
} else {
|
||||||
|
String finalS = s;
|
||||||
|
return SchematicNode.getSchematicsAccessibleByUser(user, ROOT).stream().filter(node1 -> node1.getName().equals(finalS)).findAny();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<SchematicNode> filterSchems(SteamwarUser user, Predicate<SchematicNode> filter) {
|
||||||
|
List<SchematicNode> finalList = new ArrayList<>();
|
||||||
|
List<SchematicNode> nodes = getSchematicsAccessibleByUser(user, ROOT);
|
||||||
|
nodes.forEach(node -> {
|
||||||
|
if (node.isDir()) {
|
||||||
|
finalList.addAll(deepGet(node, filter));
|
||||||
|
} else {
|
||||||
|
if (filter.test(node))
|
||||||
|
finalList.add(node);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return finalList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return nodeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SteamwarUser getOwner() {
|
||||||
|
return SteamwarUser.get(nodeOwner);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return nodeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.nodeName = name;
|
||||||
|
updateDB();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SchematicNode getParent() {
|
||||||
|
return SchematicNode.getSchematicNode(parentNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParent(SchematicNode parent) {
|
||||||
|
this.parentNode = parent.nodeId;
|
||||||
|
updateDB();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getItem() {
|
||||||
|
if (nodeItem.isEmpty()) {
|
||||||
|
return isDir() ? "CHEST" : "CAULDRON_ITEM";
|
||||||
|
}
|
||||||
|
return nodeItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItem(String item) {
|
||||||
|
this.nodeItem = item;
|
||||||
|
updateDB();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDir() {
|
||||||
|
return nodeType == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getSchemFormat() {
|
||||||
|
throwIfDir();
|
||||||
|
return nodeFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRank() {
|
||||||
|
throwIfDir();
|
||||||
|
return nodeRank;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRank(int rank) {
|
||||||
|
throwIfDir();
|
||||||
|
this.nodeRank = rank;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SchematicType getSchemtype() {
|
||||||
|
throwIfDir();
|
||||||
|
return nodeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSchemtype(SchematicType type) {
|
||||||
|
throwIfDir();
|
||||||
|
this.nodeType = type;
|
||||||
|
updateDB();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean replaceColor() {
|
||||||
|
return replaceColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReplaceColor(boolean replaceColor) {
|
||||||
|
throwIfDir();
|
||||||
|
this.replaceColor = replaceColor;
|
||||||
|
updateDB();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean allowReplay() {
|
||||||
|
return allowReplay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAllowReplay(boolean allowReplay) {
|
||||||
|
throwIfDir();
|
||||||
|
this.allowReplay = allowReplay;
|
||||||
|
updateDB();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getElo(int season) {
|
||||||
|
return SchemElo.getElo(this, season);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean accessibleByUser(int user) {
|
||||||
|
return NodeMember.getNodeMember(nodeId, user) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<NodeMember> getMembers() {
|
||||||
|
return NodeMember.getNodeMembers(nodeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Timestamp getLastUpdate() {
|
||||||
|
return lastUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateDB() {
|
||||||
|
this.lastUpdate = Timestamp.from(Instant.now());
|
||||||
|
update.update(nodeId, nodeOwner, nodeName, parentNode, nodeItem, nodeType, lastUpdate, nodeRank, replaceColor, allowReplay, nodeFormat);
|
||||||
|
this.brCache.clear();
|
||||||
|
TAB_CACHE.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete() {
|
||||||
|
delete.update(nodeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return nodeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (!(obj instanceof SchematicNode))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return ((SchematicNode) obj).getId() == nodeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String generateBreadcrumbs(SteamwarUser user) {
|
||||||
|
return brCache.computeIfAbsent(user.getId(), integer -> generateBreadcrumbs("/", user));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String generateBreadcrumbs(String split, SteamwarUser user) {
|
||||||
|
StringBuilder builder = new StringBuilder(getName());
|
||||||
|
SchematicNode currentNode = this;
|
||||||
|
if (currentNode.isDir()) builder.append("/");
|
||||||
|
final Set<NodeMember> nodeMembers = NodeMember.getSchematics(user.getId());
|
||||||
|
AtomicInteger i = new AtomicInteger();
|
||||||
|
i.set(currentNode.getId());
|
||||||
|
while (!currentNode.getParent().equals(ROOT) && nodeMembers.stream().noneMatch(nodeMember -> nodeMember.getNode() == i.get())) {
|
||||||
|
currentNode = currentNode.getParent();
|
||||||
|
i.set(currentNode.getId());
|
||||||
|
builder.insert(0, split)
|
||||||
|
.insert(0, currentNode.getName());
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final List<String> FORBIDDEN_NAMES = Collections.unmodifiableList(Arrays.asList("public"));
|
||||||
|
public static boolean invalidSchemName(String[] layers) {
|
||||||
|
for (String layer : layers) {
|
||||||
|
if (layer.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (layer.contains("/") ||
|
||||||
|
layer.contains("\\") ||
|
||||||
|
layer.contains("<") ||
|
||||||
|
layer.contains(">") ||
|
||||||
|
layer.contains("^") ||
|
||||||
|
layer.contains("°") ||
|
||||||
|
layer.contains("'") ||
|
||||||
|
layer.contains("\"") ||
|
||||||
|
layer.contains(" ")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(FORBIDDEN_NAMES.contains(layer.toLowerCase())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<String> 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<String> list = new ArrayList<>();
|
||||||
|
if (s.contains("/")) {
|
||||||
|
String preTab = s.substring(0, s.lastIndexOf("/") + 1);
|
||||||
|
Optional<SchematicNode> pa = SchematicNode.getNodeFromPath(user, preTab);
|
||||||
|
if (!pa.isPresent()) return Collections.emptyList();
|
||||||
|
List<SchematicNode> nodes = pa.map(SchematicNode::getSchematicNodeInNode).orElseGet(Collections::emptyList);
|
||||||
|
nodes.forEach(node -> list.add((sws ? "/" : "") + node.generateBreadcrumbs(user)));
|
||||||
|
} else {
|
||||||
|
List<SchematicNode> nodes = SchematicNode.getSchematicsAccessibleByUser(user, ROOT);
|
||||||
|
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() {
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void throwIfDir() {
|
||||||
|
if (isDir()) {
|
||||||
|
throw new SecurityException("Is Directory");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren