diff --git a/SpigotCore_14/src/de/steamwar/core/WorldEditWrapper14.java b/SpigotCore_14/src/de/steamwar/core/WorldEditWrapper14.java index 96b135b..f23e7fc 100644 --- a/SpigotCore_14/src/de/steamwar/core/WorldEditWrapper14.java +++ b/SpigotCore_14/src/de/steamwar/core/WorldEditWrapper14.java @@ -29,10 +29,9 @@ import com.sk89q.worldedit.world.registry.LegacyMapper; import de.steamwar.sql.NoClipboardException; import org.bukkit.entity.Player; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; import java.util.*; +import java.util.logging.Level; import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkNotNull; @@ -43,7 +42,7 @@ public class WorldEditWrapper14 implements WorldEditWrapper.IWorldEditWrapper { private static final ClipboardFormat SCHEM = BuiltInClipboardFormat.SPONGE_SCHEMATIC; @Override - public byte[] getPlayerClipboard(Player player, boolean schemFormat) { + public InputStream getPlayerClipboard(Player player, boolean schemFormat) { ClipboardHolder clipboardHolder; try { clipboardHolder = WorldEditWrapper.getWorldEditPlugin().getSession(player).getClipboard(); @@ -55,21 +54,36 @@ public class WorldEditWrapper14 implements WorldEditWrapper.IWorldEditWrapper { if(clipboard == null) throw new NoClipboardException(); - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - try{ - if(schemFormat){ - ClipboardWriter writer = SCHEM.getWriter(outputStream); - writer.write(clipboard); - writer.close(); - }else{ - SCHEMATIC.getWriter(outputStream).write(clipboard); - } + PipedOutputStream outputStream = new PipedOutputStream(); + PipedInputStream inputStream; + try { + inputStream = new PipedInputStream(outputStream, 4096); }catch(NullPointerException e){ throw new RuntimeException(e.getMessage(), new IOException(e)); } catch (IOException e) { - throw new RuntimeException(e.getMessage(), e); + throw new SecurityException("Could not init piped input stream", e); } - return outputStream.toByteArray(); + + new Thread(() -> { + try{ + if(schemFormat){ + ClipboardWriter writer = SCHEM.getWriter(outputStream); + writer.write(clipboard); + writer.close(); + }else{ + SCHEMATIC.getWriter(outputStream).write(clipboard); + } + }catch(NullPointerException | IOException e) { + Core.getInstance().getLogger().log(Level.SEVERE, "Could not write schematic", e); + } + try { + outputStream.close(); + } catch (IOException e) { + Core.getInstance().getLogger().log(Level.SEVERE, "Could not close schem writer", e); + } + }, "SchemWriter").start(); + + return inputStream; } @Override diff --git a/SpigotCore_8/src/de/steamwar/core/WorldEditWrapper8.java b/SpigotCore_8/src/de/steamwar/core/WorldEditWrapper8.java index 3e243bd..2b1cb0e 100644 --- a/SpigotCore_8/src/de/steamwar/core/WorldEditWrapper8.java +++ b/SpigotCore_8/src/de/steamwar/core/WorldEditWrapper8.java @@ -19,19 +19,18 @@ import com.sk89q.worldedit.world.registry.WorldData; import de.steamwar.sql.NoClipboardException; import org.bukkit.entity.Player; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.logging.Level; import java.util.stream.Collectors; public class WorldEditWrapper8 implements WorldEditWrapper.IWorldEditWrapper { @Override - public byte[] getPlayerClipboard(Player player, boolean schemFormat) { + public InputStream getPlayerClipboard(Player player, boolean schemFormat) { ClipboardHolder clipboardHolder; try { clipboardHolder = WorldEditWrapper.getWorldEditPlugin().getSession(player).getClipboard(); @@ -43,13 +42,28 @@ public class WorldEditWrapper8 implements WorldEditWrapper.IWorldEditWrapper { if(clipboard == null) throw new NoClipboardException(); - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + PipedOutputStream outputStream = new PipedOutputStream(); + PipedInputStream inputStream; try { - ClipboardFormat.SCHEMATIC.getWriter(outputStream).write(clipboard, clipboardHolder.getWorldData()); + inputStream = new PipedInputStream(outputStream, 4096); } catch (IOException e) { - throw new RuntimeException(e.getMessage(), e); + throw new SecurityException("Could not init piped input stream", e); } - return outputStream.toByteArray(); + + new Thread(() -> { + try { + ClipboardFormat.SCHEMATIC.getWriter(outputStream).write(clipboard, clipboardHolder.getWorldData()); + } catch (IOException e) { + Core.getInstance().getLogger().log(Level.SEVERE, "Could not write schematic", e); + } + try { + outputStream.close(); + } catch (IOException e) { + Core.getInstance().getLogger().log(Level.SEVERE, "Could not close schem writer", e); + } + }, "SchemWriter").start(); + + return inputStream; } @Override diff --git a/SpigotCore_Main/src/de/steamwar/comms/packets/PrepareSchemPacket.java b/SpigotCore_Main/src/de/steamwar/comms/packets/PrepareSchemPacket.java index 99f2ecc..8c0968d 100644 --- a/SpigotCore_Main/src/de/steamwar/comms/packets/PrepareSchemPacket.java +++ b/SpigotCore_Main/src/de/steamwar/comms/packets/PrepareSchemPacket.java @@ -22,21 +22,29 @@ package de.steamwar.comms.packets; import com.google.common.io.ByteArrayDataOutput; import de.steamwar.comms.PacketIdManager; import de.steamwar.sql.Schematic; +import de.steamwar.sql.SchematicNode; import de.steamwar.sql.SchematicType; import de.steamwar.sql.SteamwarUser; public class PrepareSchemPacket extends SpigotPacket{ private final SteamwarUser user; - private final Schematic schematic; + private final SchematicNode schematic; private final SchematicType schematicType; - public PrepareSchemPacket(SteamwarUser user, Schematic schematic, SchematicType schematicType){ + public PrepareSchemPacket(SteamwarUser user, SchematicNode schematic, SchematicType schematicType) { this.user = user; this.schematic = schematic; this.schematicType = schematicType; } + @Deprecated + public PrepareSchemPacket(SteamwarUser user, Schematic schematic, SchematicType schematicType) { + this.user = user; + this.schematic = schematic.getNode(); + this.schematicType = schematicType; + } + @Override public int getName() { return PacketIdManager.PREPARE_SCHEM; @@ -45,7 +53,7 @@ public class PrepareSchemPacket extends SpigotPacket{ @Override public void writeVars(ByteArrayDataOutput byteArrayDataOutput) { byteArrayDataOutput.writeInt(user.getId()); - byteArrayDataOutput.writeInt(schematic.getSchemID()); + byteArrayDataOutput.writeInt(schematic.getId()); byteArrayDataOutput.writeUTF(schematicType.toDB()); } } diff --git a/SpigotCore_Main/src/de/steamwar/core/WorldEditWrapper.java b/SpigotCore_Main/src/de/steamwar/core/WorldEditWrapper.java index 920bc9f..0b860ee 100644 --- a/SpigotCore_Main/src/de/steamwar/core/WorldEditWrapper.java +++ b/SpigotCore_Main/src/de/steamwar/core/WorldEditWrapper.java @@ -14,7 +14,7 @@ public class WorldEditWrapper { public static final IWorldEditWrapper impl = VersionDependent.getVersionImpl(Core.getInstance()); public interface IWorldEditWrapper { - byte[] getPlayerClipboard(Player player, boolean schemFormat); + InputStream getPlayerClipboard(Player player, boolean schemFormat); void setPlayerClipboard(Player player, InputStream is, boolean schemFormat); Clipboard getClipboard(InputStream is, boolean schemFormat) throws IOException; diff --git a/SpigotCore_Main/src/de/steamwar/inventory/SWListInv.java b/SpigotCore_Main/src/de/steamwar/inventory/SWListInv.java index 43c294f..d0d9c22 100644 --- a/SpigotCore_Main/src/de/steamwar/inventory/SWListInv.java +++ b/SpigotCore_Main/src/de/steamwar/inventory/SWListInv.java @@ -20,6 +20,7 @@ package de.steamwar.inventory; import de.steamwar.sql.Schematic; +import de.steamwar.sql.SchematicNode; import de.steamwar.sql.SchematicType; import org.bukkit.Bukkit; import org.bukkit.Material; @@ -27,6 +28,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import java.util.*; +import java.util.stream.Collectors; public class SWListInv extends SWInventory { @@ -115,26 +117,32 @@ public class SWListInv extends SWInventory { return onlinePlayers; } - public static List> getSchemList(SchematicType type, int steamwarUserId){ - List> schemList = new ArrayList<>(); + public static List> getSchemnodeList(SchematicType type, int steamwarUserId){ + List> schemList = new ArrayList<>(); - List schems; + List schems; if(type == null) - schems = Schematic.getSchemsAccessibleByUser(steamwarUserId); + schems = SchematicNode.getAllSchematicsAccessibleByUser(steamwarUserId); else - schems = Schematic.getSchemsOfType(steamwarUserId, type); + schems = SchematicNode.getAllAccessibleSchematicsOfType(steamwarUserId, type.toDB()); - for(Schematic s : schems){ + for(SchematicNode s : schems){ Material m; if(s.getItem().isEmpty()) m = SWItem.getMaterial("CAULDRON_ITEM"); else m = SWItem.getMaterial(s.getItem()); - SWItem item = new SWItem(m,"§e" + s.getSchemName()); + SWItem item = new SWItem(m,"§e" + s.getName()); + item.setEnchanted(s.isDir()); schemList.add(new SWListEntry<>(item, s)); } return schemList; } + + @Deprecated + public static List> getSchemList(SchematicType type, int steamwarUserId){ + return getSchemnodeList(type, steamwarUserId).stream().map(schematicNodeSWListEntry -> new SWListEntry(schematicNodeSWListEntry.getItem(), Schematic.wrap(schematicNodeSWListEntry.getObject()))).collect(Collectors.toList()); + } private boolean sizeBiggerMax(){ return dynamicSize ? elements.size() > 54 : elements.size() > 45; diff --git a/SpigotCore_Main/src/de/steamwar/sql/CheckedSchematic.java b/SpigotCore_Main/src/de/steamwar/sql/CheckedSchematic.java index db8df93..0411239 100644 --- a/SpigotCore_Main/src/de/steamwar/sql/CheckedSchematic.java +++ b/SpigotCore_Main/src/de/steamwar/sql/CheckedSchematic.java @@ -1,6 +1,6 @@ -/* +/* This file is a part of the SteamWar software. - + Copyright (C) 2020 SteamWar.de-Serverteam This program is free software: you can redistribute it and/or modify @@ -24,72 +24,86 @@ import java.util.ArrayList; import java.util.List; import java.util.UUID; - public class CheckedSchematic { - private static final SQL.Statement checkHistory = new SQL.Statement("SELECT * FROM CheckedSchematic WHERE SchemOwner = ? AND DeclineReason != '' AND DeclineReason != 'Prüfvorgang abgebrochen' ORDER BY EndTime DESC"); + private static final SQL.Statement checkHistory = new SQL.Statement("SELECT * FROM CheckedSchematic WHERE NodeId IN (SELECT NodeId FROM SchematicNode WHERE NodeOwner = ?) AND DeclineReason != '' AND DeclineReason != 'Prüfvorgang abgebrochen' AND NodeId is not NULL ORDER BY EndTime DESC"); + private static final SQL.Statement nodeHistory = new SQL.Statement("SELECT * FROM CheckedSchematic WHERE NodeId = ? AND DeclineReason != '' AND DeclineReason != 'Prüfvorgang abgebrochen' ORDER BY EndTime DESC"); + private static final SQL.Statement insert = new SQL.Statement("INSERT INTO CheckedSchematic (NodeId, NodeName, NodeOwner, Validator, StartTime, EndTime, DeclineReason) VALUES (?, ?, ?, ?, ?, ?, ?)"); + private static final SQL.Statement setNodeNull = new SQL.Statement("UPDATE CheckedSchematic SET NodeId = NULL WHERE NodeId = ?"); - private final String schemName; - private final int schemOwner; + private final Integer node; private final int validator; private final Timestamp startTime; private final Timestamp endTime; private final String declineReason; - private CheckedSchematic(String schemName, int schemOwner, int validator, Timestamp startTime, Timestamp endTime, String declineReason, boolean insertDB){ - this.schemName = schemName; - this.schemOwner = schemOwner; + private CheckedSchematic(int node, int validator, Timestamp startTime, Timestamp endTime, String declineReason, boolean insertDB){ + this.node = node; this.validator = validator; this.startTime = startTime; this.endTime = endTime; this.declineReason = declineReason; - if(insertDB) + if(insertDB) { insertDB(); + } } @Deprecated public CheckedSchematic(String schemName, int schemOwner, int validator, Timestamp startTime, Timestamp endTime, String declineReason){ - this(schemName, schemOwner, validator, startTime, endTime, declineReason, true); + this(Schematic.getSchemFromDB(schemName, schemOwner).getSchemID(), validator, startTime, endTime, declineReason, true); } @Deprecated public CheckedSchematic(String schemName, UUID schemOwner, UUID validator, Timestamp startTime, Timestamp endTime, String declineReason){ - this(schemName, SteamwarUser.get(schemOwner).getId(), SteamwarUser.get(validator).getId(), startTime, endTime, declineReason, true); + this(Schematic.getSchemFromDB(schemName, schemOwner).getSchemID(), SteamwarUser.get(validator).getId(), startTime, endTime, declineReason, true); } - @Deprecated - private void insertDB(){ - SQL.update("INSERT INTO CheckedSchematic" + - " (SchemName, SchemOwner, Validator, StartTime, EndTime, DeclineReason) VALUES (?, ?, ?, ?, ?, ?)", - schemName, schemOwner, validator, startTime, endTime, declineReason); + public CheckedSchematic(int node, int validator, Timestamp startTime, Timestamp endTime, String declineReason){ + this(node, validator, startTime, endTime, declineReason, true); } - public static List getLastDeclined(UUID schemOwner){ - return getLastDelined(SteamwarUser.get(schemOwner).getId()); + public CheckedSchematic(int node, UUID validator, Timestamp startTime, Timestamp endTime, String declineReason){ + this(node, SteamwarUser.get(validator).getId(), startTime, endTime, declineReason, true); + } + + private void insertDB() { + SchematicNode sNode = SchematicNode.getSchematicNode(node); + String nodeName = sNode.getName(); + int nodeOwner = sNode.getOwner(); + insert.update(node, nodeName, nodeOwner, validator, startTime, endTime, declineReason); + } + + public static List getLastDeclinedOfNode(SchematicNode node){ + return getLastDeclinedOfNode(node.getId()); + } + + public static List getLastDeclinedOfNode(int node){ + return nodeHistory.select(rs -> { + List lastDeclined = new ArrayList<>(); + while(rs.next()){ + int validator = rs.getInt("Validator"); + Timestamp startTime = rs.getTimestamp("StartTime"); + Timestamp endTime = rs.getTimestamp("EndTime"); + String declineReason = rs.getString("DeclineReason"); + lastDeclined.add(new CheckedSchematic(node, validator, startTime, endTime, declineReason, false)); + } + return lastDeclined; + }, node); + } + + public static List getLastDeclined(UUID uuid){ + return getLastDelined(SteamwarUser.get(uuid).getId()); } public static List getLastDelined(int schemOwner){ return checkHistory.select(rs -> { List history = new ArrayList<>(); while(rs.next()) - history.add(new CheckedSchematic(rs.getString("SchemName"), schemOwner, rs.getInt("Validator"), rs.getTimestamp("StartTime"), rs.getTimestamp("EndTime"), rs.getString("DeclineReason"), false)); + history.add(new CheckedSchematic(rs.getInt("NodeId"), rs.getInt("Validator"), rs.getTimestamp("StartTime"), rs.getTimestamp("EndTime"), rs.getString("DeclineReason"), false)); return history; }, schemOwner); } - @Deprecated - public void remove() { - SQL.update("DELETE FROM CheckedSchematic WHERE SchemOwner = ? AND SchemName = ?", schemOwner, schemName); - } - - public String getSchemName() { - return schemName; - } - - public int getSchemOwner() { - return schemOwner; - } - public int getValidator() { return validator; } @@ -105,4 +119,20 @@ public class CheckedSchematic { public String getDeclineReason() { return declineReason; } + + public int getNode() { + return node; + } + + public String getSchemName() { + return SchematicNode.getSchematicNode(node).getName(); + } + + public int getSchemOwner() { + return SchematicNode.getSchematicNode(node).getId(); + } + + public void remove() { + setNodeNull.update(node); + } } diff --git a/SpigotCore_Main/src/de/steamwar/sql/DownloadSchematic.java b/SpigotCore_Main/src/de/steamwar/sql/DownloadSchematic.java index 104f952..64812f9 100644 --- a/SpigotCore_Main/src/de/steamwar/sql/DownloadSchematic.java +++ b/SpigotCore_Main/src/de/steamwar/sql/DownloadSchematic.java @@ -19,30 +19,11 @@ package de.steamwar.sql; -import com.google.common.io.BaseEncoding; - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.time.Instant; - public class DownloadSchematic { private DownloadSchematic(){} - private static final SQL.Statement createLink = new SQL.Statement("INSERT INTO SchemDownload (SchemID, Link) VALUES (?, ?) ON DUPLICATE KEY UPDATE Link = VALUES(Link)"); - - private static final String BASE = "https://steamwar.de/download.php?schem="; - + @Deprecated public static String getLink(Schematic schem){ - MessageDigest digest; - try { - digest = MessageDigest.getInstance("SHA-1"); - } catch (NoSuchAlgorithmException e) { - throw new SecurityException(e); - } - digest.reset(); - digest.update((Instant.now().toString() + schem.getSchemOwner() + schem.getSchemID()).getBytes()); - String hash = BaseEncoding.base16().encode(digest.digest()); - createLink.update(schem.getSchemID(), hash); - return BASE + hash; + return NodeDownload.getLink(schem.getNode()); } } diff --git a/SpigotCore_Main/src/de/steamwar/sql/NodeDownload.java b/SpigotCore_Main/src/de/steamwar/sql/NodeDownload.java new file mode 100644 index 0000000..acc7a11 --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/sql/NodeDownload.java @@ -0,0 +1,49 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2021 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 com.google.common.io.BaseEncoding; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.time.Instant; + +public class NodeDownload { + + private static final SQL.Statement createLink = new SQL.Statement("INSERT INTO NodeDownload (NodeId, Link) VALUES (?, ?) ON DUPLICATE KEY UPDATE Link = VALUES(Link)"); + + private static final String BASE = "https://steamwar.de/download.php?schem="; + + public static String getLink(SchematicNode schem){ + if(schem.isDir()) + throw new SecurityException("Can not Download Directorys"); + MessageDigest digest; + try { + digest = MessageDigest.getInstance("SHA-1"); + } catch (NoSuchAlgorithmException e) { + throw new SecurityException(e); + } + digest.reset(); + digest.update((Instant.now().toString() + schem.getOwner() + schem.getId()).getBytes()); + String hash = BaseEncoding.base16().encode(digest.digest()); + createLink.update(schem.getId(), hash); + return BASE + hash; + } +} diff --git a/SpigotCore_Main/src/de/steamwar/sql/NodeMember.java b/SpigotCore_Main/src/de/steamwar/sql/NodeMember.java new file mode 100644 index 0000000..f2f1d90 --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/sql/NodeMember.java @@ -0,0 +1,85 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 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 java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashSet; +import java.util.Set; + +public class NodeMember { + + private static final SQL.Statement getNodeMember = new SQL.Statement("SELECT * FROM NodeMember WHERE NodeId = ? AND UserId = ?"); + private static final SQL.Statement getNodeMembers = new SQL.Statement("SELECT * FROM NodeMember WHERE NodeId = ?"); + private static final SQL.Statement getSchematics = new SQL.Statement("SELECT * FROM NodeMember WHERE UserId = ?"); + private static final SQL.Statement createNodeMember = new SQL.Statement("INSERT INTO NodeMember (NodeId, UserId) VALUES (?, ?)"); + private static final SQL.Statement deleteNodeMember = new SQL.Statement("DELETE FROM NodeMember WHERE NodeId = ? AND UserId = ?"); + + public static NodeMember getNodeMember(int node, int member) { + return getNodeMember.select(rs -> { + if(!rs.next()) + return null; + return new NodeMember(rs); + }, node, member); + } + + public static Set getNodeMembers(int node) { + return getNodeMembers.select(rs -> { + Set members = new HashSet<>(); + while (rs.next()) + members.add(new NodeMember(rs)); + return members; + }, node); + } + + public static Set getSchematics(int member) { + return getSchematics.select(rs -> { + Set members = new HashSet<>(); + while (rs.next()) + members.add(new NodeMember(rs)); + return members; + }, member); + } + + public static NodeMember createNodeMember(int node, int member) { + createNodeMember.update(node, member); + return getNodeMember(node, member); + } + + final int node; + final int member; + + private NodeMember(ResultSet set) throws SQLException { + node = set.getInt("NodeId"); + member = set.getInt("UserId"); + } + + public int getNode() { + return node; + } + + public int getMember() { + return member; + } + + public void delete() { + deleteNodeMember.update(node, member); + } +} diff --git a/SpigotCore_Main/src/de/steamwar/sql/Schematic.java b/SpigotCore_Main/src/de/steamwar/sql/Schematic.java index b364072..efe4b66 100644 --- a/SpigotCore_Main/src/de/steamwar/sql/Schematic.java +++ b/SpigotCore_Main/src/de/steamwar/sql/Schematic.java @@ -1,6 +1,6 @@ -/* +/* This file is a part of the SteamWar software. - + Copyright (C) 2020 SteamWar.de-Serverteam This program is free software: you can redistribute it and/or modify @@ -26,232 +26,172 @@ import org.bukkit.entity.Player; import java.io.IOException; import java.io.InputStream; -import java.sql.Blob; -import java.sql.ResultSet; -import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.UUID; -import java.util.zip.GZIPInputStream; +@Deprecated public class Schematic { - private static final SQL.Statement getSchemsOfType = new SQL.Statement("SELECT DISTINCT s.SchemID, s.SchemName, s.SchemOwner, s.Item, s.SchemType, s.Rank, s.SchemFormat FROM Schematic s LEFT JOIN SchemMember sm ON sm.SchemName = s.SchemName AND sm.SchemOwner = s.SchemOwner WHERE s.SchemType = ? AND (s.SchemOwner = ? OR sm.Member = ?) ORDER BY s.SchemName"); + private static final SQL.Statement getSchemsOfType = new SQL.Statement("SELECT DISTINCT s.SchemID, s.SchemName, s.SchemOwner, s.Item, s.SchemType, s.Rank, s.SchemFormat FROM Schematic s LEFT JOIN SchemMember sm ON sm.SchemName = s.SchemName AND sm.SchemOwner = s.SchemOwner WHERE s.SchemType = ? AND (s.SchemOwner = ? OR sm.Member = ?) ORDER BY s.SchemName"); - private final int schemID; - private final String schemName; - private final int schemOwner; - private boolean schemFormat; - private String item; - private int rank; - private SchematicType schemType; + private final SchematicNode node; - private Schematic(ResultSet rs) throws SQLException { - this.schemID = rs.getInt("SchemID"); - this.schemName = rs.getString("SchemName"); - this.schemOwner = rs.getInt("SchemOwner"); - this.item = rs.getString("Item"); - this.rank = rs.getInt("Rank"); - this.schemType = SchematicType.fromDB(rs.getString("SchemType")); - this.schemFormat = rs.getBoolean("SchemFormat"); - } + private Schematic(SchematicNode node) { + this.node = node; + } - private void updateDB(){ - createSchem(schemName, schemOwner, item, schemType); - } + public static Schematic wrap(SchematicNode node) { + return new Schematic(node); + } - public static void createSchem(String schemName, UUID schemOwner, String item, SchematicType schemType){ - createSchem(schemName, SteamwarUser.get(schemOwner).getId(), item, schemType); - } + public static void createSchem(String schemName, UUID schemOwner, String item, SchematicType schemType){ + createSchem(schemName, SteamwarUser.get(schemOwner).getId(), item, schemType); + } - public static void createSchem(String schemName, int schemOwner, String item, SchematicType schemType){ - SQL.update("INSERT INTO Schematic (SchemName, SchemOwner, Item, SchemType) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE Item = VALUES(Item), SchemType = VALUES(SchemType)", - schemName, schemOwner, item, schemType.toDB()); - } + public static void createSchem(String schemName, int schemOwner, String item, SchematicType schemType){ + SchematicNode.createSchematicNode(schemOwner, schemName, null, schemType.toDB(), item); + } - public static Schematic getSchemFromDB(String schemName, UUID schemOwner){ - return getSchemFromDB(schemName, SteamwarUser.get(schemOwner).getId()); - } + public static Schematic getSchemFromDB(String schemName, UUID schemOwner){ + return getSchemFromDB(schemName, SteamwarUser.get(schemOwner).getId()); + } - public static Schematic getSchemFromDB(String schemName, int schemOwner){ - ResultSet schematic = SQL.select("SELECT SchemID, SchemName, SchemOwner, Item, SchemType, Rank, SchemFormat FROM Schematic WHERE SchemName = ? AND SchemOwner = ?", schemName, schemOwner); - try { - if(schematic == null || !schematic.next()){ - SchematicMember member = SchematicMember.getMemberBySchematic(schemName, schemOwner); - if(member == null){ - return null; - } - return getSchemFromDB(schemName, member.getSchemOwner()); - } - return new Schematic(schematic); - } catch (SQLException e) { - throw new SecurityException("Failed loading schematic", e); - } - } + public static Schematic getSchemFromDB(String schemName, int schemOwner){ + SchematicNode node = SchematicNode.getSchematicNode(schemOwner, schemName, 0); + if(node != null) { + return new Schematic(node); + } + return null; + } - public static Schematic getSchemFromDB(int schemID){ - ResultSet schematic = SQL.select("SELECT SchemID, SchemName, SchemOwner, Item, SchemType, Rank, SchemFormat FROM Schematic WHERE SchemID = ?", schemID); - try { - if(!schematic.next()) - throw new SecurityException("Failed loading schematic " + schemID); - return new Schematic(schematic); - } catch (SQLException e) { - throw new SecurityException("Failed loading schematic", e); - } - } + public static Schematic getSchemFromDB(int schemID){ + SchematicNode node = SchematicNode.getSchematicNode(schemID); + if(node != null) { + return new Schematic(node); + } else { + throw new SecurityException("Failed to load Schematics"); + } + } - public static List getSchemsAccessibleByUser(UUID schemOwner){ - return getSchemsAccessibleByUser(SteamwarUser.get(schemOwner).getId()); - } + public static List getSchemsAccessibleByUser(UUID schemOwner){ + return getSchemsAccessibleByUser(SteamwarUser.get(schemOwner).getId()); + } - public static List getSchemsAccessibleByUser(int schemOwner){ - try{ - ResultSet schematic = SQL.select("SELECT DISTINCT s.SchemID, s.SchemName, s.SchemOwner, s.Item, s.SchemType, s.Rank, s.SchemFormat FROM Schematic s LEFT JOIN SchemMember sm ON sm.SchemName = s.SchemName AND sm.SchemOwner = s.SchemOwner WHERE s.SchemOwner = ? OR sm.Member = ? ORDER BY s.SchemName", schemOwner, schemOwner); - List schematics = new ArrayList<>(); - while(schematic.next()) - schematics.add(new Schematic(schematic)); - return schematics; - }catch(SQLException e){ - throw new SecurityException("Failed listing schematics", e); - } - } + public static List getSchemsAccessibleByUser(int schemOwner){ + List schematics = new ArrayList<>(); + SchematicNode.getSchematicsAccessibleByUser(schemOwner, null) + .forEach(node1 -> { + if (!node1.isDir()) schematics.add(new Schematic(node1)); + }); + return schematics; + } - public static List getSchemsOfType(UUID schemOwner, SchematicType schemType){ - return getSchemsOfType(SteamwarUser.get(schemOwner).getId(), schemType); - } + public static List getSchemsOfType(UUID schemOwner, SchematicType schemType){ + return getSchemsOfType(SteamwarUser.get(schemOwner).getId(), schemType); + } - public static List getSchemsOfType(int schemOwner, SchematicType schemType){ - return getSchemsOfType.select(rs -> { - List schematics = new ArrayList<>(); - while(rs.next()) - schematics.add(new Schematic(rs)); - return schematics; - }, schemType.toDB(), schemOwner, schemOwner); - } + public static List getSchemsOfType(int schemOwner, SchematicType schemType){ + List schematics = new ArrayList<>(); + SchematicNode.getAllAccessibleSchematicsOfType(schemOwner, schemType.toDB()) + .forEach(node1 -> { + if (!node1.isDir()) schematics.add(new Schematic(node1)); + }); + return schematics; + } - public static List getAllSchemsOfType(SchematicType schemType){ - try{ - ResultSet schematic = SQL.select("SELECT SchemID, SchemName, SchemOwner, Item, SchemType, Rank, SchemFormat FROM Schematic WHERE SchemType = ?", schemType.toDB()); - List schematics = new ArrayList<>(); - while(schematic.next()){ - schematics.add(new Schematic(schematic)); - } - return schematics; - }catch(SQLException e){ - throw new SecurityException("Failed loading all schems of type", e); - } - } + public static List getAllSchemsOfType(SchematicType schemType){ + List schematics = new ArrayList<>(); + SchematicNode.getAllSchematicsOfType(schemType.toDB()) + .forEach(node1 -> schematics.add(new Schematic(node1))); + return schematics; + } - public int getSchemID() { - return schemID; - } + public int getSchemID() { + return node.getId(); + } - public String getSchemName() { - return schemName; - } + public String getSchemName() { + return node.getName(); + } - public int getSchemOwner() { - return schemOwner; - } + public int getSchemOwner() { + return node.getOwner(); + } - public int getRank(){ - return rank; - } + public int getRank(){ + return node.getRank(); + } - public String getItem() { - return item; - } + public String getItem() { + return node.getItem(); + } - public void setItem(String item) { - this.item = item; - updateDB(); - } + public void setItem(String item) { + node.setItem(item); + } - public void setRank(int rank){ - this.rank = rank; - SQL.update("UPDATE Schematic SET Rank = ? WHERE SchemID = ?", rank, schemID); - } + public void setRank(int rank){ + node.setRank(rank); + } - public SchematicType getSchemType() { - return schemType; - } + public SchematicType getSchemType() { + return node.getSchemtype(); + } - public void setSchemType(SchematicType schemType) { - this.schemType = schemType; - updateDB(); - } + public void setSchemType(SchematicType schemType) { + node.setType(schemType.toDB()); + } - public boolean availible(){ - return true; - } + public boolean availible(){ + return true; + } - public InputStream schemData() throws IOException { - ResultSet rs = SQL.select("SELECT SchemData FROM Schematic WHERE SchemID = ?", schemID); - try { - rs.next(); - Blob schemData = rs.getBlob("SchemData"); - if(schemData == null) - throw new IOException("SchemData is null"); - return new GZIPInputStream(schemData.getBinaryStream()); - } catch (SQLException e) { - throw new IOException(e); - } - } + public InputStream schemData() throws IOException { + return node.schemData(); + } - public static Clipboard clipboardFromStream(InputStream is, boolean schemFormat) { - try { - return WorldEditWrapper.impl.getClipboard(is, schemFormat); - } catch (IOException e) { - throw new SecurityException("Could not read schem", e); - } - } + public static Clipboard clipboardFromStream(InputStream is, boolean schemFormat) { + try { + return WorldEditWrapper.impl.getClipboard(is, schemFormat); + } catch (IOException e) { + throw new SecurityException("Could not read schem", e); + } + } - public Clipboard load() throws IOException, NoClipboardException { - return clipboardFromStream(schemData(), schemFormat); - } + public Clipboard load() throws IOException, NoClipboardException { + return clipboardFromStream(schemData(), node.getSchemFormat()); + } - public void loadToPlayer(Player player) throws IOException, NoClipboardException { - InputStream is = schemData(); - WorldEditWrapper.impl.setPlayerClipboard(player, is, schemFormat); - } + public void loadToPlayer(Player player) throws IOException, NoClipboardException { + InputStream is = schemData(); + WorldEditWrapper.impl.setPlayerClipboard(player, is, node.getSchemFormat()); + } - public void saveOldFormatFromPlayer(Player player) throws IOException, NoClipboardException { - saveFromPlayer(player, false); - } + public void saveOldFormatFromPlayer(Player player) throws IOException, NoClipboardException { + saveFromPlayer(player, false); + } - public void saveFromPlayer(Player player) throws IOException, NoClipboardException { - saveFromPlayer(player, Core.getVersion() > 12); - } + public void saveFromPlayer(Player player) throws IOException, NoClipboardException { + saveFromPlayer(player, Core.getVersion() > 12); + } - public void saveFromBytes(byte[] bytes, boolean newFormat) { - Blob blob = SQL.blob(); - try { - blob.setBytes(1, bytes); - updateDatabase(blob, newFormat); - } catch (SQLException e) { - throw new SecurityException(e); - } - } + public void saveFromBytes(byte[] bytes, boolean newFormat) { + node.saveFromBytes(bytes, newFormat); + } - private void saveFromPlayer(Player player, boolean newFormat) throws IOException, NoClipboardException { - Blob blob = SQL.blob(); - try { - blob.setBytes(1, WorldEditWrapper.impl.getPlayerClipboard(player, newFormat)); - } catch (SQLException e) { - throw new SecurityException(e.getMessage(), e); - } - updateDatabase(blob, newFormat); - } + private void saveFromPlayer(Player player, boolean newFormat) throws IOException, NoClipboardException { + node.saveFromPlayer(player, newFormat); + } - private void updateDatabase(Blob blob, boolean newFormat) { - SQL.update("UPDATE Schematic SET SchemData = ?, SchemFormat = ? WHERE SchemID = ?", blob, newFormat, schemID); - schemFormat = newFormat; - } + public void remove(){ + node.delete(); + } - public void remove(){ - SQL.update("DELETE FROM SchemMember WHERE SchemOwner = ? AND SchemName = ?", schemOwner, schemName); - SQL.update("DELETE FROM Schematic WHERE SchemOwner = ? AND SchemName = ?", schemOwner, schemName); - } + public SchematicNode getNode() { + return node; + } - public static class WrongVersionException extends Exception{} + @Deprecated + public static class WrongVersionException extends Exception{} } diff --git a/SpigotCore_Main/src/de/steamwar/sql/SchematicMember.java b/SpigotCore_Main/src/de/steamwar/sql/SchematicMember.java index 87bf2fb..e84fa54 100644 --- a/SpigotCore_Main/src/de/steamwar/sql/SchematicMember.java +++ b/SpigotCore_Main/src/de/steamwar/sql/SchematicMember.java @@ -1,134 +1,96 @@ -/* +/* This file is a part of the SteamWar software. - - Copyright (C) 2020 SteamWar.de-Serverteam + Copyright (C) 2020 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 java.sql.ResultSet; -import java.sql.SQLException; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.UUID; +@Deprecated public class SchematicMember { - private final int schemOwner; - private final String schemName; - private final int member; - private SchematicMember(String schemName, int schemOwner, int schemMember, boolean updateDB){ - this.schemOwner = schemOwner; - member = schemMember; - this.schemName = schemName; - if(updateDB) - updateDB(); - } + private final NodeMember member; - public SchematicMember(String schemName, int schemOwner, int schemMember){ - this(schemName, schemOwner, schemMember, true); - } + private SchematicMember(NodeMember member){ + this.member = member; + } - public SchematicMember(String schemName, UUID schemOwner, UUID schemMember){ - this(schemName, SteamwarUser.get(schemOwner).getId(), SteamwarUser.get(schemMember).getId(), true); - } + public SchematicMember(String schemName, int schemOwner, int schemMember){ + this(NodeMember.createNodeMember(Schematic.getSchemFromDB(schemName, schemOwner).getSchemID(), schemMember)); + } - private void updateDB(){ - SQL.update("INSERT INTO SchemMember (SchemName, SchemOwner, Member) VALUES (?, ?, ?)", schemName, schemOwner, member); - } + public SchematicMember(String schemName, UUID schemOwner, UUID schemMember){ + this(NodeMember.createNodeMember(Schematic.getSchemFromDB(schemName, schemOwner).getSchemID(), SteamwarUser.get(schemMember).getId())); + } - public static SchematicMember getSchemMemberFromDB(String schemName, UUID schemOwner, UUID schemMember){ - return getSchemMemberFromDB(schemName, SteamwarUser.get(schemOwner).getId(), SteamwarUser.get(schemMember).getId()); - } + public static SchematicMember getSchemMemberFromDB(String schemName, UUID schemOwner, UUID schemMember){ + return getSchemMemberFromDB(schemName, SteamwarUser.get(schemOwner).getId(), SteamwarUser.get(schemMember).getId()); + } - public static SchematicMember getSchemMemberFromDB(String schemName, int schemOwner, int schemMember){ - ResultSet schematicMember = SQL.select("SELECT * FROM SchemMember WHERE SchemName = ? AND SchemOwner = ? AND Member = ?", schemName, schemOwner, schemMember); - try { - if(schematicMember == null || !schematicMember.next()){ - return null; - } - return new SchematicMember(schemName, schemOwner, schemMember, false); - } catch (SQLException e) { - throw new SecurityException("Could not get schemmember", e); - } - } + public static SchematicMember getSchemMemberFromDB(String schemName, int schemOwner, int schemMember){ + NodeMember member = NodeMember.getNodeMember(Schematic.getSchemFromDB(schemName, schemOwner).getSchemID(), schemMember); + if(member == null) { + return null; + } + return new SchematicMember(member); + } - public static SchematicMember getMemberBySchematic(String schemName, int schemMember){ - ResultSet schematicMember = SQL.select("SELECT * FROM SchemMember WHERE SchemName = ? AND Member = ?", schemName, schemMember); - try { - if(schematicMember == null || !schematicMember.next()){ - return null; - } - int schemOwner = schematicMember.getInt("SchemOwner"); - return new SchematicMember(schemName, schemOwner, schemMember, false); - } catch (SQLException e) { - throw new SecurityException("Could not get member", e); - } - } + public static SchematicMember getMemberBySchematic(String schemName, int schemMember){ + Optional nodeMember = NodeMember.getSchematics(schemMember) + .stream().filter(member1 -> SchematicNode.getSchematicNode(member1.getNode()).getName().equalsIgnoreCase(schemName)).findFirst(); + return nodeMember.map(SchematicMember::new).orElse(null); + } - public static List getSchemMembers(String schemName, UUID schemOwner){ - return getSchemMembers(schemName, SteamwarUser.get(schemOwner).getId()); - } + public static List getSchemMembers(String schemName, UUID schemOwner){ + return getSchemMembers(schemName, SteamwarUser.get(schemOwner).getId()); + } - public static List getSchemMembers(String schemName, int schemOwner){ - ResultSet schematicMember = SQL.select("SELECT * FROM SchemMember WHERE SchemName = ? AND SchemOwner = ?", schemName, schemOwner); - try { - List schematicMembers = new ArrayList<>(); - while(schematicMember.next()){ - int schemMember = schematicMember.getInt("Member"); - schematicMembers.add(new SchematicMember(schemName, schemOwner, schemMember, false)); - } - return schematicMembers; - } catch (SQLException e) { - throw new SecurityException("Could not get schemmembers", e); - } - } + public static List getSchemMembers(String schemName, int schemOwner){ + List members = new ArrayList<>(); + NodeMember.getNodeMembers(Schematic.getSchemFromDB(schemName, schemOwner).getSchemID()) + .forEach(member1 -> members.add(new SchematicMember(member1))); + return members; + } - public static List getAccessibleSchems(UUID schemMember){ - return getAccessibleSchems(SteamwarUser.get(schemMember).getId()); - } + public static List getAccessibleSchems(UUID schemMember){ + return getAccessibleSchems(SteamwarUser.get(schemMember).getId()); + } - public static List getAccessibleSchems(int schemMember){ - ResultSet schematicMember = SQL.select("SELECT * FROM SchemMember WHERE Member = ?", schemMember); - try { - List schematicMembers = new ArrayList<>(); - while(schematicMember.next()){ - String schemName = schematicMember.getString("SchemName"); - int schemOwner = schematicMember.getInt("SchemOwner"); - schematicMembers.add(new SchematicMember(schemName, schemOwner, schemMember, false)); - } - return schematicMembers; - } catch (SQLException e) { - throw new SecurityException("Could not get accessible schems", e); - } - } + public static List getAccessibleSchems(int schemMember){ + List members = new ArrayList<>(); + NodeMember.getSchematics(schemMember) + .forEach(member1 -> members.add(new SchematicMember(member1))); + return members; + } - public int getSchemOwner() { - return schemOwner; - } + public int getSchemOwner() { + return SchematicNode.getSchematicNode(member.getNode()).getOwner(); + } - public String getSchemName() { - return schemName; - } + public String getSchemName() { + return SchematicNode.getSchematicNode(member.getNode()).getName(); + } - public int getMember() { - return member; - } + public int getMember() { + return member.getMember(); + } - public void remove(){ - SQL.update("DELETE FROM SchemMember WHERE SchemOwner = ? AND SchemName = ? AND Member = ?", schemOwner, schemName, member); - } + public void remove(){ + member.delete(); + } } diff --git a/SpigotCore_Main/src/de/steamwar/sql/SchematicNode.java b/SpigotCore_Main/src/de/steamwar/sql/SchematicNode.java new file mode 100644 index 0000000..f885d59 --- /dev/null +++ b/SpigotCore_Main/src/de/steamwar/sql/SchematicNode.java @@ -0,0 +1,529 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 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 com.sk89q.worldedit.extent.clipboard.Clipboard; +import de.steamwar.core.Core; +import de.steamwar.core.VersionedCallable; +import de.steamwar.core.VersionedRunnable; +import de.steamwar.core.WorldEditWrapper; +import org.bukkit.entity.Player; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.sql.Blob; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.time.Instant; +import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Predicate; +import java.util.zip.GZIPInputStream; + +public class SchematicNode { + + private static final SQL.Statement createNode = new SQL.Statement("INSERT INTO SchematicNode (NodeName, NodeOwner, ParentNode, NodeType, NodeItem) VALUES (?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE NodeName = VALUES(NodeName), ParentNode = VALUES(ParentNode), NodeItem = VALUES(NodeItem), NodeType = VALUES(NodeType), NodeItem = VALUES(NodeItem)"); + private static final SQL.Statement getSchematicNode_Null = new SQL.Statement("SELECT NodeId, NodeName, NodeOwner, ParentNode, NodeType, NodeItem, NodeRank, NodeFormat, LastUpdate FROM SchematicNode WHERE NodeOwner = ? AND NodeName = ? AND ParentNode is NULL"); + private static final SQL.Statement getSchematicNode = new SQL.Statement("SELECT NodeId, NodeName, NodeOwner, ParentNode, NodeType, NodeItem, NodeRank, NodeFormat, LastUpdate FROM SchematicNode WHERE NodeOwner = ? AND NodeName = ? AND ParentNode = ?"); + private static final SQL.Statement getSchematicsInNode_Null = new SQL.Statement("SELECT NodeId, NodeName, NodeOwner, ParentNode, NodeType, NodeItem, NodeRank, NodeFormat, LastUpdate FROM SchematicNode WHERE ParentNode is NULL"); + private static final SQL.Statement getSchematicsInNode = new SQL.Statement("SELECT NodeId, NodeName, NodeOwner, ParentNode, NodeType, NodeItem, NodeRank, NodeFormat, LastUpdate FROM SchematicNode WHERE ParentNode = ?"); + private static final SQL.Statement getDirsInNode_Null = new SQL.Statement("SELECT NodeId, NodeName, NodeOwner, ParentNode, NodeType, NodeItem, NodeRank, NodeFormat, LastUpdate FROM SchematicNode WHERE ParentNode is NULL AND NodeType is NULL"); + private static final SQL.Statement getDirsInNode = new SQL.Statement("SELECT NodeId, NodeName, NodeOwner, ParentNode, NodeType, NodeItem, NodeRank, NodeFormat, LastUpdate FROM SchematicNode WHERE ParentNode = ? AND NodeType is NULL"); + private static final SQL.Statement getSchematicDirectory_Null = new SQL.Statement("SELECT NodeId, NodeName, NodeOwner, ParentNode, NodeType, NodeItem, NodeRank, NodeFormat, LastUpdate FROM SchematicNode WHERE NodeName = ? AND ParentNode is NULL"); + private static final SQL.Statement getSchematicDirectory = new SQL.Statement("SELECT NodeId, NodeName, NodeOwner, ParentNode, NodeType, NodeItem, NodeRank, NodeFormat, LastUpdate FROM SchematicNode WHERE NodeName = ? AND ParentNode = ?"); + private static final SQL.Statement getSchematicNodeO_Null = new SQL.Statement("SELECT NodeId, NodeName, NodeOwner, ParentNode, NodeType, NodeItem, NodeRank, NodeFormat, LastUpdate FROM SchematicNode WHERE NodeName = ? AND ParentNode is NULL"); + private static final SQL.Statement getSchematicNodeO = new SQL.Statement("SELECT NodeId, NodeName, NodeOwner, ParentNode, NodeType, NodeItem, NodeRank, NodeFormat, LastUpdate FROM SchematicNode WHERE NodeName = ? AND ParentNode = ?"); + private static final SQL.Statement getSchematicNodeId = new SQL.Statement("SELECT NodeId, NodeName, NodeOwner, ParentNode, NodeType, NodeItem, NodeRank, NodeFormat, LastUpdate FROM SchematicNode WHERE NodeId = ?"); + private static final SQL.Statement getAllSchemsOfTypeOwner = new SQL.Statement("SELECT NodeId, NodeName, NodeOwner, ParentNode, NodeType, NodeItem, NodeRank, NodeFormat, LastUpdate FROM SchematicNode WHERE NodeOwner = ? AND NodeType = ?"); + private static final SQL.Statement getAllSchemsOfType = new SQL.Statement("SELECT NodeId, NodeName, NodeOwner, ParentNode, NodeType, NodeItem, NodeRank, NodeFormat, LastUpdate FROM SchematicNode WHERE NodeType = ?"); + private static final SQL.Statement getAccessibleByUser = new SQL.Statement("SELECT s.NodeId, s.NodeName, s.NodeOwner, s.NodeItem, s.NodeType, s.ParentNode, s.NodeRank, s.NodeFormat, s.LastUpdate FROM SchematicNode 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 SQL.Statement getAccessibleByUserByTypeInNode = new SQL.Statement("WITH RECURSIVE RSNB AS (WITH RECURSIVE RSN as (SELECT s.NodeId, s.NodeName, s.NodeOwner, s.NodeItem, s.NodeType, s.ParentNode, s.NodeRank, s.NodeFormat, s.LastUpdate FROM SchematicNode s LEFT JOIN NodeMember n ON s.NodeId = n.NodeId WHERE (s.NodeOwner = ? OR n.UserId = ?) GROUP BY s.NodeId union select SN.NodeId, SN.NodeName, SN.NodeOwner, SN.NodeItem, SN.NodeType, SN.ParentNode, SN.NodeRank, SN.NodeFormat, SN.LastUpdate FROM SchematicNode AS SN, RSN WHERE SN.ParentNode = RSN.NodeId) SELECT * FROM RSN WHERE NodeType = ? union select SN.NodeId, SN.NodeName, SN.NodeOwner, SN.NodeItem, SN.NodeType, SN.ParentNode, SN.NodeRank, SN.NodeFormat, SN.LastUpdate FROM SchematicNode AS SN, RSNB WHERE SN.NodeId = RSNB.ParentNode)SELECT * FROM RSNB WHERE ParentNode = ?"); + private static final SQL.Statement getAccessibleByUserByTypeInNode_Null = new SQL.Statement("WITH RECURSIVE RSNB AS (WITH RECURSIVE RSN as (SELECT s.NodeId, s.NodeName, s.NodeOwner, s.NodeItem, s.NodeType, s.ParentNode, s.NodeRank, s.NodeFormat, s.LastUpdate FROM SchematicNode s LEFT JOIN NodeMember n ON s.NodeId = n.NodeId WHERE (s.NodeOwner = ? OR n.UserId = ?) GROUP BY s.NodeId union select SN.NodeId, SN.NodeName, SN.NodeOwner, SN.NodeItem, SN.NodeType, SN.ParentNode, SN.NodeRank, SN.NodeFormat, SN.LastUpdate FROM SchematicNode AS SN, RSN WHERE SN.ParentNode = RSN.NodeId) SELECT * FROM RSN WHERE NodeType = ? union select SN.NodeId, SN.NodeName, SN.NodeOwner, SN.NodeItem, SN.NodeType, SN.ParentNode, SN.NodeRank, SN.NodeFormat, SN.LastUpdate FROM SchematicNode AS SN, RSNB WHERE SN.NodeId = RSNB.ParentNode)SELECT * FROM RSNB WHERE ParentNode is null"); + private static final SQL.Statement getAccessibleByUserByType = new SQL.Statement("WITH RECURSIVE RSN as (SELECT s.NodeId, s.NodeName, s.NodeOwner, s.NodeItem, s.NodeType, s.ParentNode, s.NodeRank, s.NodeFormat, s.LastUpdate FROM SchematicNode s LEFT JOIN NodeMember n ON s.NodeId = n.NodeId WHERE (s.NodeOwner = ? OR n.UserId = ?) GROUP BY s.NodeId union select SN.NodeId, SN.NodeName, SN.NodeOwner, SN.NodeItem, SN.NodeType, SN.ParentNode, SN.NodeRank, SN.NodeFormat, SN.LastUpdate FROM SchematicNode AS SN, RSN WHERE SN.ParentNode = RSN.NodeId) SELECT * FROM RSN WHERE NodeType = ?"); + private static final SQL.Statement getAllSchematicsAccessibleByUser = new SQL.Statement("WITH RECURSIVE RSN as (SELECT s.NodeId, s.NodeName, s.NodeOwner, s.NodeItem, s.NodeType, s.ParentNode, s.NodeRank, s.NodeFormat, s.LastUpdate FROM SchematicNode s LEFT JOIN NodeMember n ON s.NodeId = n.NodeId WHERE (s.NodeOwner = ? OR n.UserId = ?) GROUP BY s.NodeId union select SN.NodeId, SN.NodeName, SN.NodeOwner, SN.NodeItem, SN.NodeType, SN.ParentNode, SN.NodeRank, SN.NodeFormat, SN.LastUpdate FROM SchematicNode AS SN, RSN WHERE SN.ParentNode = RSN.NodeId) SELECT * FROM RSN"); + private static final SQL.Statement isSchematicAccessibleForUser = new SQL.Statement("WITH RECURSIVE RSN AS (SELECT NodeId, NodeName, NodeOwner, ParentNode, NodeType, NodeItem, NodeRank, NodeFormat, LastUpdate FROM SchematicNode WHERE NodeId = ? union select SN.NodeId, SN.NodeName, SN.NodeOwner, SN.ParentNode, SN.NodeType, SN.NodeItem, SN.NodeRank, SN.NodeFormat, SN.LastUpdate FROM SchematicNode 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 SQL.Statement getAllParentsOfNode = new SQL.Statement("WITH RECURSIVE RSN AS (SELECT NodeId, NodeName, NodeOwner, ParentNode, NodeType, NodeItem, NodeRank, NodeFormat, LastUpdate FROM SchematicNode WHERE NodeId = ? UNION SELECT SN.NodeId, SN.NodeName, SN.NodeOwner, SN.ParentNode, SN.NodeType, SN.NodeItem, SN.NodeRank, SN.NodeFormat, SN.LastUpdate FROM SchematicNode SN, RSN WHERE RSN.ParentNode = SN.NodeId) SELECT * FROM RSN"); + private static final SQL.Statement countNodes = new SQL.Statement("SELECT COUNT(NodeId) AS 'count' FROM SchematicNode"); + private static final SQL.Statement updateDB = new SQL.Statement("UPDATE SchematicNode SET NodeName = ?, NodeOwner = ?, ParentNode = ?, NodeItem = ?, NodeType = ?, NodeRank = ? WHERE NodeId = ?"); + private static final SQL.Statement updateDatabase = new SQL.Statement("UPDATE SchematicNode SET NodeData = ?, NodeFormat = ? WHERE NodeId = ?"); + private static final SQL.Statement selSchemData = new SQL.Statement("SELECT NodeData FROM SchematicNode WHERE NodeId = ?"); + private static final SQL.Statement deleteNode = new SQL.Statement("DELETE FROM SchematicNode WHERE NodeId = ?"); + + public static SchematicNode createSchematic(int owner, String name, Integer parent) { + return createSchematicNode(owner, name, parent, SchematicType.Normal.toDB(), ""); + } + + public static SchematicNode createSchematicDirectory(int owner, String name, Integer parent) { + return createSchematicNode(owner, name, parent, null, ""); + } + + public static SchematicNode createSchematicNode(int owner, String name, Integer parent, String type, String item) { + if (parent == 0) + parent = null; + createNode.update(name, owner, parent, type, item); + return getSchematicNode(owner, name, parent); + } + + private Timestamp lastUpdate; + + public static SchematicNode getSchematicNode(int owner, String name, SchematicNode parent) { + return getSchematicNode(owner, name, parent.getId()); + } + + private SchematicNode(ResultSet set) throws SQLException { + id = set.getInt("NodeId"); + owner = set.getInt("NodeOwner"); + name = set.getString("NodeName"); + parent = set.getInt("ParentNode"); + item = set.getString("NodeItem"); + type = set.getString("NodeType"); + lastUpdate = set.getTimestamp("LastUpdate"); + if (type != null) { + isDir = false; + rank = set.getInt("NodeRank"); + schemFormat = set.getBoolean("NodeFormat"); + } else { + isDir = true; + } + } + + public static List getSchematicNodeInNode(SchematicNode parent) { + return getSchematicNodeInNode(parent.getId()); + } + + public static SchematicNode getSchematicDirectory(String name, SchematicNode parent) { + return getSchematicDirectory(name, parent.getId()); + } + + public static SchematicNode getSchematicNode(int owner, String name, Integer parent) { + if (parent != null && parent == 0) { + parent = null; + } + SQL.Statement.ResultSetUser user = rs -> { + while (rs.next()) { + SchematicNode node = new SchematicNode(rs); + return node; + } + return null; + }; + if(parent == null) { + return getSchematicNode_Null.select(user, owner, name); + } else { + return getSchematicNode.select(user, owner, name, parent); + } + } + + public static List getSchematicNodeInNode(Integer parent) { + if(parent != null && parent == 0) + parent = null; + SQL.Statement.ResultSetUser> user = rs -> { + List nodes = new ArrayList<>(); + while (rs.next()) + nodes.add(new SchematicNode(rs)); + return nodes; + }; + if(parent == null) { + return getSchematicsInNode_Null.select(user); + }else { + return getSchematicsInNode.select(user, parent); + } + } + + public static List getSchematicDirectoryInNode(Integer parent) { + if(parent != null && parent == 0) + parent = null; + SQL.Statement.ResultSetUser> user = rs -> { + List nodes = new ArrayList<>(); + while (rs.next()) + nodes.add(new SchematicNode(rs)); + return nodes; + }; + if(parent == null) { + return getDirsInNode_Null.select(user); + }else { + return getDirsInNode.select(user, parent); + } + } + + public static SchematicNode getSchematicDirectory(String name, Integer parent) { + if(parent != null && parent == 0) + parent = null; + SQL.Statement.ResultSetUser user = rs -> { + while (rs.next()) { + SchematicNode node = new SchematicNode(rs); + if(node.isDir()) + return node; + } + return null; + }; + + if(parent == null) { + return getSchematicDirectory_Null.select(user, name); + }else { + return getSchematicDirectory.select(user, name, parent); + } + } + + public static SchematicNode getSchematicNode(String name, Integer parent) { + if(parent != null && parent == 0) + parent = null; + SQL.Statement.ResultSetUser user = rs -> { + while (rs.next()) { + return new SchematicNode(rs); + } + return null; + }; + if(parent == null) { + return getSchematicNodeO_Null.select(user, name); + }else { + return getSchematicNodeO.select(user, name, parent); + } + } + + public static SchematicNode getSchematicNode(int id) { + return getSchematicNodeId.select(rs -> { + if (!rs.next()) + return null; + return new SchematicNode(rs); + }, id); + } + + public static List getAccessibleSchematicsOfTypeInParent(int owner, String schemType, Integer parent) { + SQL.Statement.ResultSetUser> user = rs -> { + List nodes = new ArrayList<>(); + while (rs.next()) { + nodes.add(new SchematicNode(rs)); + } + return nodes; + }; + if(parent == null || parent == 0) { + return getAccessibleByUserByTypeInNode_Null.select(user, owner, owner, schemType); + } else { + return getAccessibleByUserByTypeInNode.select(user, owner, owner, schemType, parent); + } + } + + public static List getAllAccessibleSchematicsOfType(int user, String schemType) { + return getAccessibleByUserByType.select(rs -> { + List nodes = new ArrayList<>(); + while (rs.next()) { + nodes.add(new SchematicNode(rs)); + } + return nodes; + }, user, user, schemType); + } + + public static List getAllSchematicsOfType(int owner, String schemType) { + return getAllSchemsOfTypeOwner.select(rs -> { + List nodes = new ArrayList<>(); + while (rs.next()) + nodes.add(new SchematicNode(rs)); + return nodes; + }, owner, schemType); + } + + public static List getAllSchematicsOfType(String schemType) { + return getAllSchemsOfType.select(rs -> { + List nodes = new ArrayList<>(); + while (rs.next()) + nodes.add(new SchematicNode(rs)); + return nodes; + }, schemType); + } + + public static List deepGet(Integer parent, Predicate filter) { + List finalList = new ArrayList<>(); + List 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 getSchematicsAccessibleByUser(int user, Integer parent) { + if (parent != null && parent != 0) { + if(isSchematicAccessibleForUser.select(rs -> { + rs.next(); + return rs.getInt("Accessible") > 0; + }, parent, user, user)) + return getSchematicNodeInNode(parent); + } else { + return getAccessibleByUser.select(rs -> { + List nodes = new ArrayList<>(); + while(rs.next()) + nodes.add(new SchematicNode(rs)); + return nodes; + }, user, user, user, user); + } + return Collections.emptyList(); + } + + public static List getAllSchematicsAccessibleByUser(int user) { + return getAllSchematicsAccessibleByUser.select(rs -> { + List nodes = new ArrayList<>(); + while(rs.next()) { + nodes.add(new SchematicNode(rs)); + } + return nodes; + }, user, user); + } + + public static List getAllParentsOfNode(SchematicNode node) { + return getAllParentsOfNode(node.getId()); + } + + public static List getAllParentsOfNode(int node) { + return getAllParentsOfNode.select(rs -> { + List nodes = new ArrayList<>(); + while(rs.next()) { + nodes.add(new SchematicNode(rs)); + } + return nodes; + }, node); + } + + private final int id; + private final int owner; + private String name; + private Integer parent; + private String item; + private String type; + private boolean schemFormat; + private int rank; + private final boolean isDir; + private Map brCache = new HashMap<>(); + + public static List filterSchems(int user, Predicate filter) { + List finalList = new ArrayList<>(); + List nodes = SchematicNode.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; + } + + public static Integer countNodes() { + return countNodes.select(rs -> { + if (rs.next()) { + return rs.getInt("count"); + } + return 0; + }); + } + + public int getId() { + return id; + } + + public int getOwner() { + return owner; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + updateDB(); + } + + public Integer getParent() { + return parent; + } + + public void setParent(Integer parent) { + this.parent = parent; + updateDB(); + } + + public String getItem() { + return item; + } + + public void setItem(String item) { + this.item = item; + updateDB(); + } + + public String getType() { + if(isDir) + throw new SecurityException("Node is Directory"); + return type; + } + + public void setType(String type) { + if(isDir) + throw new SecurityException("Node is Directory"); + this.type = type; + updateDB(); + } + + public boolean isDir() { + return isDir; + } + + public boolean getSchemFormat() { + if(isDir) + throw new SecurityException("Node is Directory"); + return schemFormat; + } + + public int getRank() { + if(isDir) + throw new SecurityException("Node is Directory"); + return rank; + } + + public void setRank(int rank) { + if(isDir) + throw new SecurityException("Node is Directory"); + this.rank = rank; + } + + public SchematicType getSchemtype() { + if(isDir()) + throw new RuntimeException("Is Directory"); + return SchematicType.fromDB(type); + } + + public SchematicNode getParentNode() { + return SchematicNode.getSchematicNode(parent); + } + + public boolean accessibleByUser(int user) { + return NodeMember.getNodeMember(id, user) != null; + } + + public Set getMembers() { + return NodeMember.getNodeMembers(id); + } + + public Timestamp getLastUpdate() { + return lastUpdate; + } + + 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("/"); + while (currentNode.getParentNode() != null) { + currentNode = currentNode.getParentNode(); + builder.insert(0, split) + .insert(0, currentNode.getName()); + if (currentNode.getMembers().stream().anyMatch(member -> member.getMember() == user.getId())) { + break; + } + } + return builder.toString(); + } + + private void updateDB() { + updateDB.update(name, owner, parent, item, type, rank, id); + this.lastUpdate = Timestamp.from(Instant.now()); + this.brCache.clear(); + } + + public void delete() { + if (isDir()) { + getSchematicNodeInNode(getId()).forEach(SchematicNode::delete); + } + deleteNode.update(id); + } + + public InputStream schemData() throws IOException { + try { + return selSchemData.select(rs -> { + rs.next(); + Blob schemData = rs.getBlob("NodeData"); + if(schemData == null) { + throw new SecurityException("SchemData is null"); + } + try { + return new GZIPInputStream(schemData.getBinaryStream()); + } catch (IOException e) { + throw new SecurityException("SchemData is wrong", e); + } + }, id); + } catch (Exception e) { + throw new IOException(e); + } + } + + public Clipboard load() throws IOException, NoClipboardException { + if(isDir) + throw new SecurityException("Node is Directory"); + return WorldEditWrapper.impl.getClipboard(schemData(), schemFormat); + } + + public void loadToPlayer(Player player) throws IOException, NoClipboardException { + if(isDir) + throw new SecurityException("Node is Directory"); + WorldEditWrapper.impl.setPlayerClipboard(player, schemData(), schemFormat); + } + + public void saveFromPlayer(Player player) throws IOException, NoClipboardException { + if(isDir) + throw new SecurityException("Node is Directory"); + saveFromPlayer(player, Core.getVersion() > 12); + } + + public void saveFromBytes(byte[] bytes, boolean newFormat) { + if(isDir) + throw new SecurityException("Node is Directory"); + updateDatabase(new ByteArrayInputStream(bytes), newFormat); + } + + public void saveFromPlayer(Player player, boolean newFormat) throws IOException, NoClipboardException { + if(isDir) + throw new SecurityException("Node is Directory"); + updateDatabase(WorldEditWrapper.impl.getPlayerClipboard(player, newFormat), newFormat); + } + + private void updateDatabase(InputStream blob, boolean newFormat) { + updateDatabase.update(blob, newFormat, id); + schemFormat = newFormat; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof SchematicNode)) + return false; + + SchematicNode node = (SchematicNode) obj; + return node.getId() == id; + } +}