diff --git a/CommonCore/SQL/src/de/steamwar/sql/IgnoreSystem.java b/CommonCore/SQL/src/de/steamwar/sql/IgnoreSystem.java
deleted file mode 100644
index c0c38cc8..00000000
--- a/CommonCore/SQL/src/de/steamwar/sql/IgnoreSystem.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * This file is a part of the SteamWar software.
- *
- * Copyright (C) 2025 SteamWar.de-Serverteam
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package de.steamwar.sql;
-
-import de.steamwar.sql.internal.Field;
-import de.steamwar.sql.internal.SelectStatement;
-import de.steamwar.sql.internal.Statement;
-import de.steamwar.sql.internal.Table;
-import lombok.AllArgsConstructor;
-
-import java.sql.ResultSet;
-import java.util.UUID;
-
-@AllArgsConstructor
-public class IgnoreSystem {
-
- private static final Table table = new Table<>(IgnoreSystem.class, "IgnoredPlayers");
- private static final SelectStatement select = table.select(Table.PRIMARY);
- private static final Statement insert = table.insertAll();
- private static final Statement delete = table.delete(Table.PRIMARY);
-
- @Field(keys = {Table.PRIMARY})
- private final int ignorer;
- @Field(keys = {Table.PRIMARY})
- private final int ignored;
-
- public static boolean isIgnored(UUID ignorer, UUID ignored){
- return isIgnored(SteamwarUser.get(ignorer), SteamwarUser.get(ignored));
- }
-
- public static boolean isIgnored(SteamwarUser ignorer, SteamwarUser ignored) {
- return select.select(ResultSet::next, ignorer.getId(), ignored.getId());
- }
-
- public static void ignore(SteamwarUser ignorer, SteamwarUser ignored) {
- insert.update(ignorer.getId(), ignored.getId());
- }
-
- public static void unIgnore(SteamwarUser ignorer, SteamwarUser ignored) {
- delete.update(ignorer.getId(), ignored.getId());
- }
-}
diff --git a/CommonCore/SQL/src/de/steamwar/sql/IgnoreSystem.kt b/CommonCore/SQL/src/de/steamwar/sql/IgnoreSystem.kt
new file mode 100644
index 00000000..b94c111a
--- /dev/null
+++ b/CommonCore/SQL/src/de/steamwar/sql/IgnoreSystem.kt
@@ -0,0 +1,74 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2025 SteamWar.de-Serverteam
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package de.steamwar.sql
+
+import de.steamwar.sql.internal.useDb
+import org.jetbrains.exposed.v1.core.and
+import org.jetbrains.exposed.v1.core.dao.id.CompositeID
+import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
+import org.jetbrains.exposed.v1.core.dao.id.EntityID
+import org.jetbrains.exposed.v1.core.eq
+import org.jetbrains.exposed.v1.dao.CompositeEntity
+import org.jetbrains.exposed.v1.dao.CompositeEntityClass
+import java.util.UUID
+
+object IgnoreSystemTable: CompositeIdTable("IgnoreTable") {
+ val ignorer = reference("Ignorer", SteamwarUserTable)
+ val ignored = reference("Ignored", SteamwarUserTable)
+
+ override val primaryKey = PrimaryKey(ignorer, ignored)
+
+ init {
+ addIdColumn(ignorer)
+ addIdColumn(ignored)
+ }
+}
+
+class IgnoreSystem(id: EntityID) : CompositeEntity(id) {
+ var ignorer by IgnoreSystemTable.ignorer
+ var ignored by IgnoreSystemTable.ignored
+
+ companion object : CompositeEntityClass(IgnoreSystemTable) {
+ @JvmStatic
+ fun isIgnored(ignorer: UUID, ignored: UUID) = useDb { isIgnored(SteamwarUser.get(ignorer)!!, SteamwarUser.get(ignored)!!) }
+
+ @JvmStatic
+ fun isIgnored(ignorer: SteamwarUser, ignored: SteamwarUser) = useDb {
+ find {
+ (IgnoreSystemTable.ignorer eq ignorer.id) and (IgnoreSystemTable.ignored eq ignored.id)
+ }.firstOrNull() != null
+ }
+
+ @JvmStatic
+ fun ignore(ignorer: SteamwarUser, ignored: SteamwarUser) = useDb {
+ new {
+ this.ignorer = ignorer.id
+ this.ignored = ignored.id
+ }
+ }
+
+ @JvmStatic
+ fun unIgnore(ignorer: SteamwarUser, ignored: SteamwarUser) = useDb {
+ find {
+ (IgnoreSystemTable.ignorer eq ignorer.id) and (IgnoreSystemTable.ignored eq ignored.id)
+ }.firstOrNull()?.delete()
+ }
+ }
+}
\ No newline at end of file
diff --git a/CommonCore/SQL/src/de/steamwar/sql/Mod.java b/CommonCore/SQL/src/de/steamwar/sql/Mod.java
deleted file mode 100644
index 4d8fcd9d..00000000
--- a/CommonCore/SQL/src/de/steamwar/sql/Mod.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * This file is a part of the SteamWar software.
- *
- * Copyright (C) 2025 SteamWar.de-Serverteam
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package de.steamwar.sql;
-
-import de.steamwar.sql.internal.*;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-import java.util.List;
-
-@AllArgsConstructor
-public class Mod {
-
- static {
- SqlTypeMapper.ordinalEnumMapper(Platform.class);
- SqlTypeMapper.ordinalEnumMapper(ModType.class);
- }
-
- private static final Table table = new Table<>(Mod.class, "Mods");
- private static final SelectStatement get = table.select(Table.PRIMARY);
- private static final SelectStatement findFirst = new SelectStatement<>(table, "SELECT * FROM Mods WHERE ModType = 0 LIMIT 1");
- private static final SelectStatement getPageOfType = new SelectStatement<>(table, "SELECT * FROM Mods WHERE ModType = ? ORDER BY ModName DESC LIMIT ?, ?");
- private static final Statement insert = table.insert(Table.PRIMARY);
- private static final Statement set = table.update(Table.PRIMARY, "ModType");
-
- public static Mod get(String name, Platform platform) {
- return get.select(platform, name);
- }
-
- public static Mod getOrCreate(String name, Platform platform) {
- Mod mod = get(name, platform);
- if(mod != null)
- return mod;
-
- insert.update(platform, name);
- return new Mod(platform, name, ModType.UNKLASSIFIED);
- }
-
- public static List getAllModsFiltered(int page, int elementsPerPage, ModType filter) {
- return Mod.getPageOfType.listSelect(filter, page * elementsPerPage, elementsPerPage);
- }
-
- public static Mod findFirstMod() {
- return findFirst.select();
- }
-
- @Getter
- @Field(keys = {Table.PRIMARY})
- private final Platform platform;
- @Getter
- @Field(keys = {Table.PRIMARY})
- private final String modName;
- @Getter
- @Field(def = "0")
- private ModType modType;
-
- public void setModType(ModType modType) {
- set.update(modType, platform, modName);
- this.modType = modType;
- }
-
- public enum Platform {
- FORGE,
- LABYMOD,
- FABRIC
- }
-
- public enum ModType {
- UNKLASSIFIED("7"),
- GREEN("a"),
- YELLOW("e"),
- RED("c"),
- YOUTUBER_ONLY("6");
-
- ModType(String colorcode) {
- this.colorcode = colorcode;
- }
- private final String colorcode;
-
- public String getColorCode() {
- return colorcode;
- }
- }
-}
diff --git a/CommonCore/SQL/src/de/steamwar/sql/Mod.kt b/CommonCore/SQL/src/de/steamwar/sql/Mod.kt
new file mode 100644
index 00000000..9e3b4d50
--- /dev/null
+++ b/CommonCore/SQL/src/de/steamwar/sql/Mod.kt
@@ -0,0 +1,88 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2025 SteamWar.de-Serverteam
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package de.steamwar.sql
+
+import de.steamwar.sql.internal.useDb
+import org.jetbrains.exposed.v1.core.SortOrder
+import org.jetbrains.exposed.v1.core.and
+import org.jetbrains.exposed.v1.core.dao.id.CompositeID
+import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
+import org.jetbrains.exposed.v1.core.dao.id.EntityID
+import org.jetbrains.exposed.v1.core.eq
+import org.jetbrains.exposed.v1.dao.CompositeEntity
+import org.jetbrains.exposed.v1.dao.CompositeEntityClass
+
+object ModTable : CompositeIdTable("Mods") {
+ val platform = enumeration("Platform", Mod.Platform::class)
+ val modName = varchar("ModName", 100)
+ val modeType = enumerationByName("ModType", 10, Mod.ModType::class)
+}
+
+class Mod(id: EntityID) : CompositeEntity(id) {
+ companion object : CompositeEntityClass(ModTable) {
+ @JvmStatic
+ fun get(modName: String, platform: Platform) = useDb {
+ find { ModTable.platform eq platform and (ModTable.modName eq modName) }.firstOrNull()
+ }
+
+ @JvmStatic
+ fun getOrCreate(modName: String, platform: Platform) = useDb {
+ get(modName, platform) ?: new {
+ this.platform = platform
+ this.modName = modName
+ this.type = ModType.UNKLASSIFIED
+ }
+ }
+
+ @JvmStatic
+ fun getAllModsFiltered(page: Int, elementsPerPage: Int, filter: ModType) = useDb {
+ find { ModTable.modeType eq filter }.limit(elementsPerPage).offset((elementsPerPage * page).toLong())
+ .orderBy(
+ ModTable.modName to SortOrder.DESC
+ ).toList()
+ }
+
+ @JvmStatic
+ fun findFirstMod() = useDb {
+ find { ModTable.modeType eq ModType.UNKLASSIFIED }.limit(1).firstOrNull()
+ }
+ }
+
+ var platform by ModTable.platform
+ var modName by ModTable.modName
+ private var type by ModTable.modeType
+ var modType: ModType
+ get() = type
+ set(value) = useDb { type = value }
+
+ enum class Platform {
+ FORGE,
+ LABYMOD,
+ FABRIC
+ }
+
+ enum class ModType(val colorCode: String) {
+ UNKLASSIFIED("7"),
+ GREEN("a"),
+ YELLOW("e"),
+ RED("c"),
+ YOUTUBER_ONLY("6");
+ }
+}
\ No newline at end of file
diff --git a/CommonCore/SQL/src/de/steamwar/sql/NodeDownload.java b/CommonCore/SQL/src/de/steamwar/sql/NodeDownload.java
deleted file mode 100644
index 6580b589..00000000
--- a/CommonCore/SQL/src/de/steamwar/sql/NodeDownload.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * This file is a part of the SteamWar software.
- *
- * Copyright (C) 2025 SteamWar.de-Serverteam
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package de.steamwar.sql;
-
-import de.steamwar.sql.internal.Field;
-import de.steamwar.sql.internal.SelectStatement;
-import de.steamwar.sql.internal.Statement;
-import de.steamwar.sql.internal.Table;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.sql.Timestamp;
-import java.time.Instant;
-
-@AllArgsConstructor
-public class NodeDownload {
-
- private static final char[] HEX = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
- private static final String LINK_BASE = "https://api.steamwar.de/download/";
-
- private static final Table table = new Table<>(NodeDownload.class);
- private static final Statement insert = table.insertFields("NodeId", "Link");
-
- private static final SelectStatement select = table.selectFields("link");
-
- private static final Statement delete = table.delete(Table.PRIMARY);
-
- public static NodeDownload get(String link) {
- return select.select(link);
- }
-
- @Getter
- @Field(keys = {Table.PRIMARY})
- private final int nodeId;
- @Field
- private final String link;
- @Field(def = "CURRENT_TIMESTAMP")
- @Getter
- private final Timestamp timestamp;
-
- 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 = base16encode(digest.digest());
- insert.update(schem.getId(), hash);
- return LINK_BASE + hash;
- }
-
- public static String base16encode(byte[] byteArray) {
- StringBuilder hexBuffer = new StringBuilder(byteArray.length * 2);
- for (byte b : byteArray)
- hexBuffer.append(HEX[(b >>> 4) & 0xF]).append(HEX[b & 0xF]);
- return hexBuffer.toString();
- }
-
- public void delete() {
- delete.update(nodeId);
- }
-}
diff --git a/CommonCore/SQL/src/de/steamwar/sql/NodeDownload.kt b/CommonCore/SQL/src/de/steamwar/sql/NodeDownload.kt
new file mode 100644
index 00000000..adb25b90
--- /dev/null
+++ b/CommonCore/SQL/src/de/steamwar/sql/NodeDownload.kt
@@ -0,0 +1,73 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2025 SteamWar.de-Serverteam
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package de.steamwar.sql
+
+import de.steamwar.sql.internal.useDb
+import org.jetbrains.exposed.v1.core.dao.id.EntityID
+import org.jetbrains.exposed.v1.core.dao.id.IdTable
+import org.jetbrains.exposed.v1.core.eq
+import org.jetbrains.exposed.v1.dao.IntEntity
+import org.jetbrains.exposed.v1.dao.IntEntityClass
+import org.jetbrains.exposed.v1.javatime.timestamp
+import java.security.MessageDigest
+import java.sql.Timestamp
+import java.time.Instant
+
+object NodeDownloadTable: IdTable("NodeDownload") {
+ override val id = reference("NodeId", SchematicNodeTable).uniqueIndex()
+ val link = varchar("Link", 255)
+ val timestamp = timestamp("Timestamp").default(Instant.now())
+}
+
+class NodeDownload(id: EntityID) : IntEntity(id) {
+ companion object : IntEntityClass(NodeDownloadTable) {
+ const val LINK_BASE = "https://api.steamwar.de/download/"
+
+ @JvmStatic
+ fun getLink(schem: SchematicNode): String {
+ if (schem.isDir())
+ throw IllegalArgumentException("Cannot get link for directory")
+
+ val digest = MessageDigest.getInstance("SHA-1")
+ digest.update("${Instant.now()}${schem.owner}${schem.nodeId}".toByteArray())
+ val hash = digest.digest().joinToString("") { "%02x".format(it) }
+ useDb {
+ new {
+ nodeId = schem.id.value
+ link = hash
+ }
+ }
+ return "${LINK_BASE}${hash}"
+ }
+
+ @JvmStatic
+ fun get(link: String) = useDb {
+ find { NodeDownloadTable.link eq link }.firstOrNull()
+ }
+ }
+
+ var nodeId by NodeDownloadTable.id.transform({ EntityID(it, SchematicNodeTable) }, { it.value })
+ var link by NodeDownloadTable.link
+ var timestamp by NodeDownloadTable.timestamp.transform({ it.toInstant() }, { Timestamp.from(it) })
+
+ override fun delete() = useDb {
+ super.delete()
+ }
+}
\ No newline at end of file
diff --git a/CommonCore/SQL/src/de/steamwar/sql/NodeMember.java b/CommonCore/SQL/src/de/steamwar/sql/NodeMember.java
deleted file mode 100644
index 8b40b8be..00000000
--- a/CommonCore/SQL/src/de/steamwar/sql/NodeMember.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * This file is a part of the SteamWar software.
- *
- * Copyright (C) 2025 SteamWar.de-Serverteam
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package de.steamwar.sql;
-
-import de.steamwar.sql.internal.Field;
-import de.steamwar.sql.internal.SelectStatement;
-import de.steamwar.sql.internal.Statement;
-import de.steamwar.sql.internal.Table;
-import lombok.AllArgsConstructor;
-
-import java.util.HashSet;
-import java.util.Optional;
-import java.util.Set;
-
-@AllArgsConstructor
-public class NodeMember {
-
- public static void init() {
- // enforce class initialization
- }
-
- private static final Table table = new Table<>(NodeMember.class);
- private static final SelectStatement getNodeMember = table.select(Table.PRIMARY);
- private static final SelectStatement getNodeMembers = table.selectFields("NodeId");
- private static final SelectStatement getSchematics = table.selectFields("UserId");
- private static final Statement create = table.insert(Table.PRIMARY);
- private static final Statement delete = table.delete(Table.PRIMARY);
- private static final Statement updateParent = table.update(Table.PRIMARY, "ParentId");
-
- @Field(keys = {Table.PRIMARY})
- private final int nodeId;
- @Field(keys = {Table.PRIMARY})
- private final int userId;
- @Field(nullable = true, def = "null")
- private Integer parentId;
-
- public int getNode() {
- return nodeId;
- }
-
- public int getMember() {
- return userId;
- }
-
- public Optional getParent() {
- return Optional.ofNullable(parentId);
- }
-
- public void delete() {
- delete.update(nodeId, userId);
- }
-
- public static NodeMember createNodeMember(int node, int member) {
- create.update(node, member);
- return new NodeMember(node, member, null);
- }
-
- public static NodeMember getNodeMember(int node, SteamwarUser member) {
- return getNodeMember(node, member.getId());
- }
-
- public static NodeMember getNodeMember(int node, int member) {
- return getNodeMember.select(node, member);
- }
-
- public static Set getNodeMembers(int node) {
- return new HashSet<>(getNodeMembers.listSelect(node));
- }
-
- public static Set getSchematics(int member) {
- return new HashSet<>(getSchematics.listSelect(member));
- }
-
- public void setParentId(Integer parentId) {
- this.parentId = parentId;
- updateParent.update(this.parentId, nodeId, userId);
- }
-}
diff --git a/CommonCore/SQL/src/de/steamwar/sql/NodeMember.kt b/CommonCore/SQL/src/de/steamwar/sql/NodeMember.kt
new file mode 100644
index 00000000..a953e90a
--- /dev/null
+++ b/CommonCore/SQL/src/de/steamwar/sql/NodeMember.kt
@@ -0,0 +1,92 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2025 SteamWar.de-Serverteam
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package de.steamwar.sql
+
+import de.steamwar.sql.internal.useDb
+import org.jetbrains.exposed.v1.core.and
+import org.jetbrains.exposed.v1.core.dao.id.CompositeID
+import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
+import org.jetbrains.exposed.v1.core.dao.id.EntityID
+import org.jetbrains.exposed.v1.core.eq
+import org.jetbrains.exposed.v1.dao.CompositeEntity
+import org.jetbrains.exposed.v1.dao.CompositeEntityClass
+import org.jetbrains.exposed.v1.jdbc.insertIgnore
+import java.util.Optional
+import kotlin.jvm.optionals.getOrNull
+
+object NodeMemberTable : CompositeIdTable("NodeMember") {
+ val node = reference("NodeId", SchematicNodeTable)
+ val nodeOwner = reference("NodeOwner", SteamwarUserTable)
+ val parentNode = optReference("ParentNodeId", SchematicNodeTable)
+
+ override val primaryKey = PrimaryKey(node, nodeOwner)
+
+ init {
+ addIdColumn(node)
+ addIdColumn(nodeOwner)
+ }
+}
+
+class NodeMember(id: EntityID) : CompositeEntity(id) {
+ companion object : CompositeEntityClass(NodeMemberTable) {
+ @JvmStatic
+ fun createNodeMember(node: Int, member: Int): NodeMember = useDb {
+ NodeMemberTable.insertIgnore {
+ it[this.node] = EntityID(node, SchematicNodeTable)
+ it[this.nodeOwner] = EntityID(member, SteamwarUserTable)
+ }
+ getNodeMember(node, member) ?: throw IllegalStateException("NodeMember not created")
+ }
+
+ @JvmStatic
+ fun createNodeMember(node: Int, member: SteamwarUser) = createNodeMember(node, member.id.value)
+
+ @JvmStatic
+ fun getNodeMember(node: Int, member: Int) = useDb {
+ find { (NodeMemberTable.node eq node) and (NodeMemberTable.nodeOwner eq member) }.firstOrNull()
+ }
+
+ @JvmStatic
+ fun getNodeMember(node: Int, member: SteamwarUser) = getNodeMember(node, member.id.value)
+
+ @JvmStatic
+ fun getNodeMembers(node: Int) = useDb { find { NodeMemberTable.node eq node }.toSet() }
+
+ @JvmStatic
+ fun getSchematics(member: Int) = useDb { find { NodeMemberTable.nodeOwner eq member }.toSet() }
+
+ @JvmStatic
+ fun init() = Unit
+ }
+
+ val node by NodeMemberTable.node.transform({ EntityID(it, SchematicNodeTable) }, { it.value })
+ val member by NodeMemberTable.nodeOwner.transform({ EntityID(it, SteamwarUserTable) }, { it.value })
+ var parent by NodeMemberTable.parentNode.transform(
+ { it.map { EntityID(it, SchematicNodeTable) }.getOrNull() },
+ { Optional.ofNullable(it?.value) })
+
+ fun setParentId(id: Int?) {
+ parent = Optional.ofNullable(id)
+ }
+
+ override fun delete() = useDb {
+ super.delete()
+ }
+}