From 1a4a4b0fcf756e745aacc6348d0d3a4c54be8a06 Mon Sep 17 00:00:00 2001 From: Rogiel Date: Sun, 25 Dec 2011 21:13:00 -0200 Subject: [PATCH] Implements OrientDB as internal plug-and-play database --- l2jserver2-common/pom.xml | 10 + .../service/database/DatabaseService.java | 24 + .../service/database/StaticDatabaseRow.java | 59 + .../database/{sql => }/ddl/QueryFactory.java | 12 +- .../database/{sql => }/ddl/QueryTemplate.java | 4 +- .../database/{sql => }/ddl/TableFactory.java | 20 +- .../ddl/annotation/ColumnAutoIncrement.java | 2 +- .../ddl/annotation/ColumnDefault.java | 2 +- .../ddl/annotation/ColumnNullable.java | 2 +- .../{sql => }/ddl/annotation/ColumnSize.java | 2 +- .../database/{sql => }/ddl/struct/Column.java | 2 +- .../{sql => }/ddl/struct/ForeignKey.java | 2 +- .../{sql => }/ddl/struct/PrimaryKey.java | 2 +- .../database/{sql => }/ddl/struct/Table.java | 2 +- .../{sql => }/ddl/template/DerbyTemplate.java | 6 +- .../{sql => }/ddl/template/H2Template.java | 6 +- .../{sql => }/ddl/template/MySQLTemplate.java | 6 +- .../orientdb/AbstractOrientDBDAO.java | 51 + .../AbstractOrientDatabaseService.java | 795 + .../orientdb/DocumentDatabaseRow.java | 78 + .../sql/AbstractSQLDatabaseService.java | 97 +- .../service/database/sql/DatabaseEngine.java | 2 +- .../database/sql/DerbyDatabaseEngine.java | 4 +- .../database/sql/H2DatabaseEngine.java | 4 +- .../database/sql/MySQLDatabaseEngine.java | 4 +- .../transformer/impl/ClassTransformer.java | 2 +- l2jserver2-gameserver/config/config.xml | 8 +- l2jserver2-gameserver/data/sql/npc.sql | 41623 ---------------- l2jserver2-gameserver/data/static/npc.csv | 41562 +++++++++++++++ l2jserver2-gameserver/data/static/readme.txt | 2 + .../java/com/l2jserver/L2JGameServerMain.java | 1 + .../com/l2jserver/service/ServiceModule.java | 4 +- .../GameServerJDBCDatabaseService.java | 5 +- .../GameServerOrientDatabaseService.java | 102 + .../service/database/OrientDBDAOModule.java | 65 + .../dao/orientdb/OrientDBCharacterDAO.java | 174 + .../orientdb/OrientDBCharacterFriendDAO.java | 166 + .../OrientDBCharacterShortcutDAO.java | 149 + .../dao/orientdb/OrientDBChatMessageDAO.java | 120 + .../dao/orientdb/OrientDBClanDAO.java | 123 + .../dao/orientdb/OrientDBItemDAO.java | 154 + .../database/dao/orientdb/OrientDBNPCDAO.java | 148 + .../mapper/CharacterFriendMapper.java | 24 - .../service/database/mapper/NPCMapper.java | 1 + .../service/database/model/QActorSkill.java | 2 +- .../service/database/model/QCharacter.java | 8 +- .../database/model/QCharacterFriend.java | 2 +- .../database/model/QCharacterShortcut.java | 6 +- .../service/database/model/QClan.java | 2 +- .../service/database/model/QItem.java | 6 +- .../service/database/model/QLogChat.java | 6 +- .../service/database/model/QNPC.java | 2 +- .../service/game/npc/NPCServiceImpl.java | 1 + .../db/dao/mysql5/MySQL5CharacterDAOTest.java | 5 +- .../LoginServerSQLDatabaseService.java | 5 + .../l2jserver/tool/ddl/GenerateSQLFiles.java | 33 - pom.xml | 5 + 57 files changed, 43925 insertions(+), 41789 deletions(-) create mode 100644 l2jserver2-common/src/main/java/com/l2jserver/service/database/StaticDatabaseRow.java rename l2jserver2-common/src/main/java/com/l2jserver/service/database/{sql => }/ddl/QueryFactory.java (95%) rename l2jserver2-common/src/main/java/com/l2jserver/service/database/{sql => }/ddl/QueryTemplate.java (94%) rename l2jserver2-common/src/main/java/com/l2jserver/service/database/{sql => }/ddl/TableFactory.java (91%) rename l2jserver2-common/src/main/java/com/l2jserver/service/database/{sql => }/ddl/annotation/ColumnAutoIncrement.java (95%) rename l2jserver2-common/src/main/java/com/l2jserver/service/database/{sql => }/ddl/annotation/ColumnDefault.java (95%) rename l2jserver2-common/src/main/java/com/l2jserver/service/database/{sql => }/ddl/annotation/ColumnNullable.java (95%) rename l2jserver2-common/src/main/java/com/l2jserver/service/database/{sql => }/ddl/annotation/ColumnSize.java (95%) rename l2jserver2-common/src/main/java/com/l2jserver/service/database/{sql => }/ddl/struct/Column.java (98%) rename l2jserver2-common/src/main/java/com/l2jserver/service/database/{sql => }/ddl/struct/ForeignKey.java (96%) rename l2jserver2-common/src/main/java/com/l2jserver/service/database/{sql => }/ddl/struct/PrimaryKey.java (95%) rename l2jserver2-common/src/main/java/com/l2jserver/service/database/{sql => }/ddl/struct/Table.java (98%) rename l2jserver2-common/src/main/java/com/l2jserver/service/database/{sql => }/ddl/template/DerbyTemplate.java (94%) rename l2jserver2-common/src/main/java/com/l2jserver/service/database/{sql => }/ddl/template/H2Template.java (91%) rename l2jserver2-common/src/main/java/com/l2jserver/service/database/{sql => }/ddl/template/MySQLTemplate.java (95%) create mode 100644 l2jserver2-common/src/main/java/com/l2jserver/service/database/orientdb/AbstractOrientDBDAO.java create mode 100644 l2jserver2-common/src/main/java/com/l2jserver/service/database/orientdb/AbstractOrientDatabaseService.java create mode 100644 l2jserver2-common/src/main/java/com/l2jserver/service/database/orientdb/DocumentDatabaseRow.java delete mode 100644 l2jserver2-gameserver/data/sql/npc.sql create mode 100644 l2jserver2-gameserver/data/static/npc.csv create mode 100644 l2jserver2-gameserver/data/static/readme.txt create mode 100644 l2jserver2-gameserver/src/main/java/com/l2jserver/service/database/GameServerOrientDatabaseService.java create mode 100644 l2jserver2-gameserver/src/main/java/com/l2jserver/service/database/OrientDBDAOModule.java create mode 100644 l2jserver2-gameserver/src/main/java/com/l2jserver/service/database/dao/orientdb/OrientDBCharacterDAO.java create mode 100644 l2jserver2-gameserver/src/main/java/com/l2jserver/service/database/dao/orientdb/OrientDBCharacterFriendDAO.java create mode 100644 l2jserver2-gameserver/src/main/java/com/l2jserver/service/database/dao/orientdb/OrientDBCharacterShortcutDAO.java create mode 100644 l2jserver2-gameserver/src/main/java/com/l2jserver/service/database/dao/orientdb/OrientDBChatMessageDAO.java create mode 100644 l2jserver2-gameserver/src/main/java/com/l2jserver/service/database/dao/orientdb/OrientDBClanDAO.java create mode 100644 l2jserver2-gameserver/src/main/java/com/l2jserver/service/database/dao/orientdb/OrientDBItemDAO.java create mode 100644 l2jserver2-gameserver/src/main/java/com/l2jserver/service/database/dao/orientdb/OrientDBNPCDAO.java delete mode 100644 l2jserver2-tools/src/main/java/com/l2jserver/tool/ddl/GenerateSQLFiles.java diff --git a/l2jserver2-common/pom.xml b/l2jserver2-common/pom.xml index 846a947d8..ae6ab77a7 100644 --- a/l2jserver2-common/pom.xml +++ b/l2jserver2-common/pom.xml @@ -124,6 +124,16 @@ jar runtime + + com.orientechnologies + orient-commons + 1.0rc7 + + + com.orientechnologies + orientdb-core + 1.0rc7 + com.h2database h2 diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/DatabaseService.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/DatabaseService.java index 427582b7e..102279c0e 100644 --- a/l2jserver2-common/src/main/java/com/l2jserver/service/database/DatabaseService.java +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/DatabaseService.java @@ -16,12 +16,16 @@ */ package com.l2jserver.service.database; +import java.io.IOException; +import java.nio.file.Path; + import com.l2jserver.model.Model; import com.l2jserver.model.id.ID; import com.l2jserver.service.Service; import com.l2jserver.service.ServiceConfiguration; import com.l2jserver.service.configuration.Configuration; import com.l2jserver.service.core.threading.AsyncFuture; +import com.mysema.query.sql.RelationalPathBase; /** * This service provides access to an database implementation. Each @@ -101,6 +105,26 @@ public interface DatabaseService extends Service { int perform(); } + /** + * Imports an static data file into the database. File must be an CSV file + * with the first row as column names. + * + * @param + * the model type + * @param + * the table type + * + * @param path + * the path + * @param entity + * the table + * @throws IOException + * if any error occur while reading or parsing the file + */ + , T extends RelationalPathBase> void importData( + Path path, T entity) + throws IOException; + /** * Checks for the cached version of the object * diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/StaticDatabaseRow.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/StaticDatabaseRow.java new file mode 100644 index 000000000..635bbe4e2 --- /dev/null +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/StaticDatabaseRow.java @@ -0,0 +1,59 @@ +/* + * This file is part of l2jserver2 . + * + * l2jserver2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * l2jserver2 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with l2jserver2. If not, see . + */ +package com.l2jserver.service.database; + +import java.util.Map; + +import com.l2jserver.service.database.dao.DatabaseRow; +import com.l2jserver.util.transformer.Transformer; +import com.l2jserver.util.transformer.TransformerFactory; +import com.mysema.query.types.Path; + +/** + * @author Rogiel + * + */ +public class StaticDatabaseRow implements DatabaseRow { + /** + * The static data + */ + private final Map data; + + /** + * @param data + * the data + */ + public StaticDatabaseRow(Map data) { + this.data = data; + } + + @Override + public T get(Path path) { + final String value = data.get(path.getMetadata().getExpression() + .toString()); + @SuppressWarnings("unchecked") + Transformer transformer = (Transformer) TransformerFactory + .getTransfromer(path.getType()); + return transformer.untransform(path.getType(), value); + } + + @Override + public boolean isNull(Path path) { + // TODO Auto-generated method stub + return false; + } +} diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/QueryFactory.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/QueryFactory.java similarity index 95% rename from l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/QueryFactory.java rename to l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/QueryFactory.java index 5938627e3..17b16b7a1 100644 --- a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/QueryFactory.java +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/QueryFactory.java @@ -14,15 +14,15 @@ * You should have received a copy of the GNU General Public License * along with l2jserver2. If not, see . */ -package com.l2jserver.service.database.sql.ddl; +package com.l2jserver.service.database.ddl; import java.util.List; -import com.l2jserver.service.database.sql.ddl.struct.Column; -import com.l2jserver.service.database.sql.ddl.struct.Column.ColumnType; -import com.l2jserver.service.database.sql.ddl.struct.ForeignKey; -import com.l2jserver.service.database.sql.ddl.struct.PrimaryKey; -import com.l2jserver.service.database.sql.ddl.struct.Table; +import com.l2jserver.service.database.ddl.struct.Column; +import com.l2jserver.service.database.ddl.struct.ForeignKey; +import com.l2jserver.service.database.ddl.struct.PrimaryKey; +import com.l2jserver.service.database.ddl.struct.Table; +import com.l2jserver.service.database.ddl.struct.Column.ColumnType; import com.l2jserver.util.factory.CollectionFactory; /** diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/QueryTemplate.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/QueryTemplate.java similarity index 94% rename from l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/QueryTemplate.java rename to l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/QueryTemplate.java index f494b8019..eded8ea9c 100644 --- a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/QueryTemplate.java +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/QueryTemplate.java @@ -14,9 +14,9 @@ * You should have received a copy of the GNU General Public License * along with l2jserver2. If not, see . */ -package com.l2jserver.service.database.sql.ddl; +package com.l2jserver.service.database.ddl; -import com.l2jserver.service.database.sql.ddl.struct.Column.ColumnType; +import com.l2jserver.service.database.ddl.struct.Column.ColumnType; import com.mysema.query.sql.SQLTemplates; /** diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/TableFactory.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/TableFactory.java similarity index 91% rename from l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/TableFactory.java rename to l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/TableFactory.java index e884dd8f2..eec2a74f7 100644 --- a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/TableFactory.java +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/TableFactory.java @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with l2jserver2. If not, see . */ -package com.l2jserver.service.database.sql.ddl; +package com.l2jserver.service.database.ddl; import java.lang.reflect.Field; import java.sql.Connection; @@ -27,15 +27,15 @@ import java.util.Date; import java.util.List; import java.util.Map; -import com.l2jserver.service.database.sql.ddl.annotation.ColumnAutoIncrement; -import com.l2jserver.service.database.sql.ddl.annotation.ColumnDefault; -import com.l2jserver.service.database.sql.ddl.annotation.ColumnNullable; -import com.l2jserver.service.database.sql.ddl.annotation.ColumnSize; -import com.l2jserver.service.database.sql.ddl.struct.Column; -import com.l2jserver.service.database.sql.ddl.struct.Column.ColumnType; -import com.l2jserver.service.database.sql.ddl.struct.ForeignKey; -import com.l2jserver.service.database.sql.ddl.struct.PrimaryKey; -import com.l2jserver.service.database.sql.ddl.struct.Table; +import com.l2jserver.service.database.ddl.annotation.ColumnAutoIncrement; +import com.l2jserver.service.database.ddl.annotation.ColumnDefault; +import com.l2jserver.service.database.ddl.annotation.ColumnNullable; +import com.l2jserver.service.database.ddl.annotation.ColumnSize; +import com.l2jserver.service.database.ddl.struct.Column; +import com.l2jserver.service.database.ddl.struct.ForeignKey; +import com.l2jserver.service.database.ddl.struct.PrimaryKey; +import com.l2jserver.service.database.ddl.struct.Table; +import com.l2jserver.service.database.ddl.struct.Column.ColumnType; import com.l2jserver.util.ClassUtils; import com.l2jserver.util.factory.CollectionFactory; import com.mysema.query.sql.RelationalPathBase; diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/annotation/ColumnAutoIncrement.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/annotation/ColumnAutoIncrement.java similarity index 95% rename from l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/annotation/ColumnAutoIncrement.java rename to l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/annotation/ColumnAutoIncrement.java index 89e709099..de7069bd3 100644 --- a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/annotation/ColumnAutoIncrement.java +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/annotation/ColumnAutoIncrement.java @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with l2jserver2. If not, see . */ -package com.l2jserver.service.database.sql.ddl.annotation; +package com.l2jserver.service.database.ddl.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/annotation/ColumnDefault.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/annotation/ColumnDefault.java similarity index 95% rename from l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/annotation/ColumnDefault.java rename to l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/annotation/ColumnDefault.java index 6ed155558..f01385a5d 100644 --- a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/annotation/ColumnDefault.java +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/annotation/ColumnDefault.java @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with l2jserver2. If not, see . */ -package com.l2jserver.service.database.sql.ddl.annotation; +package com.l2jserver.service.database.ddl.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/annotation/ColumnNullable.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/annotation/ColumnNullable.java similarity index 95% rename from l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/annotation/ColumnNullable.java rename to l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/annotation/ColumnNullable.java index 4d2bb514e..08df11743 100644 --- a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/annotation/ColumnNullable.java +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/annotation/ColumnNullable.java @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with l2jserver2. If not, see . */ -package com.l2jserver.service.database.sql.ddl.annotation; +package com.l2jserver.service.database.ddl.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/annotation/ColumnSize.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/annotation/ColumnSize.java similarity index 95% rename from l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/annotation/ColumnSize.java rename to l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/annotation/ColumnSize.java index 41595b452..579010992 100644 --- a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/annotation/ColumnSize.java +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/annotation/ColumnSize.java @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with l2jserver2. If not, see . */ -package com.l2jserver.service.database.sql.ddl.annotation; +package com.l2jserver.service.database.ddl.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/struct/Column.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/struct/Column.java similarity index 98% rename from l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/struct/Column.java rename to l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/struct/Column.java index c9f72e5ad..404b759f1 100644 --- a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/struct/Column.java +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/struct/Column.java @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with l2jserver2. If not, see . */ -package com.l2jserver.service.database.sql.ddl.struct; +package com.l2jserver.service.database.ddl.struct; import java.util.List; diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/struct/ForeignKey.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/struct/ForeignKey.java similarity index 96% rename from l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/struct/ForeignKey.java rename to l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/struct/ForeignKey.java index 86953e818..cf0244757 100644 --- a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/struct/ForeignKey.java +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/struct/ForeignKey.java @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with l2jserver2. If not, see . */ -package com.l2jserver.service.database.sql.ddl.struct; +package com.l2jserver.service.database.ddl.struct; import java.util.Collections; import java.util.List; diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/struct/PrimaryKey.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/struct/PrimaryKey.java similarity index 95% rename from l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/struct/PrimaryKey.java rename to l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/struct/PrimaryKey.java index 61f258300..a4ef3e667 100644 --- a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/struct/PrimaryKey.java +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/struct/PrimaryKey.java @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with l2jserver2. If not, see . */ -package com.l2jserver.service.database.sql.ddl.struct; +package com.l2jserver.service.database.ddl.struct; /** * @author Rogiel diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/struct/Table.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/struct/Table.java similarity index 98% rename from l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/struct/Table.java rename to l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/struct/Table.java index d878f345b..71f64d7a9 100644 --- a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/struct/Table.java +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/struct/Table.java @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with l2jserver2. If not, see . */ -package com.l2jserver.service.database.sql.ddl.struct; +package com.l2jserver.service.database.ddl.struct; import java.util.Collection; import java.util.Collections; diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/template/DerbyTemplate.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/template/DerbyTemplate.java similarity index 94% rename from l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/template/DerbyTemplate.java rename to l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/template/DerbyTemplate.java index 4b3808b66..1a600b2d2 100644 --- a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/template/DerbyTemplate.java +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/template/DerbyTemplate.java @@ -14,10 +14,10 @@ * You should have received a copy of the GNU General Public License * along with l2jserver2. If not, see . */ -package com.l2jserver.service.database.sql.ddl.template; +package com.l2jserver.service.database.ddl.template; -import com.l2jserver.service.database.sql.ddl.QueryTemplate; -import com.l2jserver.service.database.sql.ddl.struct.Column.ColumnType; +import com.l2jserver.service.database.ddl.QueryTemplate; +import com.l2jserver.service.database.ddl.struct.Column.ColumnType; import com.mysema.query.QueryMetadata; import com.mysema.query.QueryModifiers; import com.mysema.query.sql.support.SerializationContext; diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/template/H2Template.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/template/H2Template.java similarity index 91% rename from l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/template/H2Template.java rename to l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/template/H2Template.java index 3bd755ac0..f8d10e7aa 100644 --- a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/template/H2Template.java +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/template/H2Template.java @@ -14,10 +14,10 @@ * You should have received a copy of the GNU General Public License * along with l2jserver2. If not, see . */ -package com.l2jserver.service.database.sql.ddl.template; +package com.l2jserver.service.database.ddl.template; -import com.l2jserver.service.database.sql.ddl.QueryTemplate; -import com.l2jserver.service.database.sql.ddl.struct.Column.ColumnType; +import com.l2jserver.service.database.ddl.QueryTemplate; +import com.l2jserver.service.database.ddl.struct.Column.ColumnType; import com.mysema.query.types.Ops; /** diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/template/MySQLTemplate.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/template/MySQLTemplate.java similarity index 95% rename from l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/template/MySQLTemplate.java rename to l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/template/MySQLTemplate.java index a28de4f02..d70c9ea39 100644 --- a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/ddl/template/MySQLTemplate.java +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/ddl/template/MySQLTemplate.java @@ -14,12 +14,12 @@ * You should have received a copy of the GNU General Public License * along with l2jserver2. If not, see . */ -package com.l2jserver.service.database.sql.ddl.template; +package com.l2jserver.service.database.ddl.template; import java.math.BigDecimal; -import com.l2jserver.service.database.sql.ddl.QueryTemplate; -import com.l2jserver.service.database.sql.ddl.struct.Column.ColumnType; +import com.l2jserver.service.database.ddl.QueryTemplate; +import com.l2jserver.service.database.ddl.struct.Column.ColumnType; import com.mysema.query.types.Ops; /** diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/orientdb/AbstractOrientDBDAO.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/orientdb/AbstractOrientDBDAO.java new file mode 100644 index 000000000..34322f887 --- /dev/null +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/orientdb/AbstractOrientDBDAO.java @@ -0,0 +1,51 @@ +/* + * This file is part of l2jserver2 . + * + * l2jserver2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * l2jserver2 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with l2jserver2. If not, see . + */ +package com.l2jserver.service.database.orientdb; + +import com.google.inject.Inject; +import com.l2jserver.model.Model; +import com.l2jserver.model.id.ID; +import com.l2jserver.service.database.AbstractDAO; +import com.l2jserver.service.database.DatabaseService; + +/** + * {@link AbstractDAO} for OrientDB DAO implementation + * + * @author Rogiel + * + * @param + * the object for the DAO + * @param + * the object ID type + */ +public abstract class AbstractOrientDBDAO, I extends ID> + extends AbstractDAO { + /** + * The JDBC Database Service + */ + protected final AbstractOrientDatabaseService database; + + /** + * @param database + * the database service + */ + @Inject + protected AbstractOrientDBDAO(DatabaseService database) { + super(database); + this.database = (AbstractOrientDatabaseService) database; + } +} diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/orientdb/AbstractOrientDatabaseService.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/orientdb/AbstractOrientDatabaseService.java new file mode 100644 index 000000000..c3b53ddb0 --- /dev/null +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/orientdb/AbstractOrientDatabaseService.java @@ -0,0 +1,795 @@ +/* + * This file is part of l2jserver2 . + * + * l2jserver2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * l2jserver2 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with l2jserver2. If not, see . + */ +package com.l2jserver.service.database.orientdb; + +import java.io.BufferedReader; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Iterators; +import com.google.inject.Inject; +import com.l2jserver.model.Model; +import com.l2jserver.model.Model.ObjectDesire; +import com.l2jserver.model.id.ID; +import com.l2jserver.model.id.object.allocator.IDAllocator; +import com.l2jserver.service.AbstractService; +import com.l2jserver.service.ServiceStartException; +import com.l2jserver.service.ServiceStopException; +import com.l2jserver.service.cache.Cache; +import com.l2jserver.service.cache.CacheService; +import com.l2jserver.service.configuration.ConfigurationService; +import com.l2jserver.service.configuration.XMLConfigurationService.ConfigurationXPath; +import com.l2jserver.service.core.threading.AbstractTask; +import com.l2jserver.service.core.threading.AsyncFuture; +import com.l2jserver.service.core.threading.ScheduledAsyncFuture; +import com.l2jserver.service.core.threading.ThreadService; +import com.l2jserver.service.database.DAOResolver; +import com.l2jserver.service.database.DataAccessObject; +import com.l2jserver.service.database.DatabaseService; +import com.l2jserver.service.database.dao.DatabaseRow; +import com.l2jserver.service.database.dao.InsertMapper; +import com.l2jserver.service.database.dao.SelectMapper; +import com.l2jserver.service.database.dao.UpdateMapper; +import com.l2jserver.util.factory.CollectionFactory; +import com.mysema.query.sql.ForeignKey; +import com.mysema.query.sql.RelationalPathBase; +import com.mysema.query.types.Path; +import com.orientechnologies.orient.core.db.document.ODatabaseDocumentPool; +import com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx; +import com.orientechnologies.orient.core.metadata.schema.OClass; +import com.orientechnologies.orient.core.metadata.schema.OClass.INDEX_TYPE; +import com.orientechnologies.orient.core.metadata.schema.OProperty; +import com.orientechnologies.orient.core.metadata.schema.OSchema; +import com.orientechnologies.orient.core.metadata.schema.OType; +import com.orientechnologies.orient.core.query.nativ.ONativeSynchQuery; +import com.orientechnologies.orient.core.query.nativ.OQueryContextNative; +import com.orientechnologies.orient.core.record.impl.ODocument; + +/** + * This is an implementation of {@link DatabaseService} that provides an layer + * to OrientDB Document Database. + * + *

Internal specification

The {@link Query} object

+ * + * If you wish to implement a new {@link DataAccessObject} you should try not + * use {@link Query} object directly because it only provides low level access + * to the JDBC architecture. Instead, you could use an specialized class, like + * {@link InsertQuery}, {@link SelectListQuery} or {@link SelectSingleQuery}. If + * you do need low level access, feel free to use the {@link Query} class + * directly. + * + *

The {@link SelectMapper} object

+ * + * The {@link SelectMapper} object maps an OrientDB {@link ODocument} into an + * Java {@link Object}. + * + * @author Rogiel + */ +public abstract class AbstractOrientDatabaseService extends AbstractService + implements DatabaseService { + /** + * The configuration object + */ + private final OrientDatabaseConfiguration config; + /** + * The logger + */ + private final Logger log = LoggerFactory + .getLogger(AbstractOrientDatabaseService.class); + + /** + * The cache service + */ + private final CacheService cacheService; + /** + * The thread service + */ + private final ThreadService threadService; + /** + * The {@link DAOResolver} instance + */ + private final DAOResolver daoResolver; + + /** + * An cache object + */ + private Cache> objectCache; + /** + * Future for the auto-save task. Each object that has changed is auto saved + * every 1 minute. + */ + private ScheduledAsyncFuture autoSaveFuture; + + /** + * Configuration interface for {@link AbstractOrientDatabaseService}. + * + * @author Rogiel + */ + public interface OrientDatabaseConfiguration extends DatabaseConfiguration { + /** + * @return the orientdb url + */ + @ConfigurationPropertyGetter(defaultValue = "local:data/database") + @ConfigurationXPath("/configuration/services/database/orientdb/url") + String getUrl(); + + /** + * @param url + * the new orientdb url + */ + @ConfigurationPropertySetter + @ConfigurationXPath("/configuration/services/database/orientdb/url") + void setUrl(String url); + + /** + * @return the orientdb database username + */ + @ConfigurationPropertyGetter(defaultValue = "admin") + @ConfigurationXPath("/configuration/services/database/orientdb/username") + String getUsername(); + + /** + * @param username + * the orientdb database username + */ + @ConfigurationPropertySetter + @ConfigurationXPath("/configuration/services/database/orientdb/username") + void setUsername(String username); + + /** + * @return the orientdb database password + */ + @ConfigurationPropertyGetter(defaultValue = "admin") + @ConfigurationXPath("/configuration/services/database/orientdb/password") + String getPassword(); + + /** + * @param password + * the jdbc database password + */ + @ConfigurationPropertySetter + @ConfigurationXPath("/configuration/services/database/jdbc/password") + void setPassword(String password); + } + + /** + * @param configService + * the configuration service + * @param cacheService + * the cache service + * @param threadService + * the thread service + * @param daoResolver + * the {@link DataAccessObject DAO} resolver + */ + @Inject + public AbstractOrientDatabaseService(ConfigurationService configService, + CacheService cacheService, ThreadService threadService, + DAOResolver daoResolver) { + config = configService.get(OrientDatabaseConfiguration.class); + this.cacheService = cacheService; + this.threadService = threadService; + this.daoResolver = daoResolver; + } + + @Override + protected void doStart() throws ServiceStartException { + ODatabaseDocumentTx database; + try { + database = ODatabaseDocumentPool.global().acquire(config.getUrl(), + config.getUsername(), config.getPassword()); + } catch (Exception e) { + database = new ODatabaseDocumentTx(config.getUrl()); + if (!database.exists()) { + database.create(); + + } + } + + ensureDatabaseSchema(); + + database.close(); + + // cache must be large enough for all world objects, to avoid + // duplication... this would endanger non-persistent states + objectCache = cacheService.createEternalCache("database-service", + IDAllocator.ALLOCABLE_IDS); + + // start the auto save task + autoSaveFuture = threadService.async(60, TimeUnit.SECONDS, 60, + new Runnable() { + @Override + public void run() { + log.debug("Auto save task started"); + int objects = 0; + for (final Model object : objectCache) { + @SuppressWarnings("unchecked") + final DataAccessObject, ?> dao = daoResolver + .getDAO(object.getClass()); + if (dao.save(object) > 0) { + objects++; + } + } + log.info( + "{} objects have been saved by the auto save task", + objects); + } + }); + } + + @Override + public int transaction(TransactionExecutor executor) { + return executor.perform(); + } + + @Override + public AsyncFuture transactionAsync( + final TransactionExecutor executor) { + return threadService.async(new AbstractTask() { + @Override + public Integer call() throws Exception { + return transaction(executor); + } + }); + } + + /** + * Executes an query in the database. + * + * @param + * the query return type + * @param query + * the query + * @return an instance of T + */ + public T query(Query query) { + Preconditions.checkNotNull(query, "query"); + final ODatabaseDocumentTx database = ODatabaseDocumentPool.global() + .acquire(config.getUrl(), config.getUsername(), + config.getPassword()); + + log.debug("Executing query {} with {}", query, database); + try { + return query.query(database, this); + } finally { + database.commit(); + } + } + + @Override + public , T extends RelationalPathBase> void importData( + java.nio.file.Path path, T entity) throws IOException { + final ODatabaseDocumentTx database = ODatabaseDocumentPool.global() + .acquire(config.getUrl(), config.getUsername(), + config.getPassword()); + + log.info("Importing {} to {}", path, entity); + + BufferedReader reader = Files.newBufferedReader(path, + Charset.defaultCharset()); + final String header[] = reader.readLine().split(","); + String line; + while ((line = reader.readLine()) != null) { + final String data[] = line.split(","); + final ODocument document = new ODocument(database, + entity.getTableName()); + for (int i = 0; i < data.length; i++) { + document.field(header[i], data[i]); + } + database.save(document); + } + } + + /** + * Makes sure the database schema is up-to-date with the external database + */ + protected abstract void ensureDatabaseSchema(); + + /** + * @param table + * the {@link RelationalPathBase} table + * @return true if a new schema was created + */ + protected boolean createSchema(RelationalPathBase table) { + final ODatabaseDocumentTx database = ODatabaseDocumentPool.global() + .acquire(config.getUrl(), config.getUsername(), + config.getPassword()); + boolean newSchema = false; + try { + final OSchema schemas = database.getMetadata().getSchema(); + OClass schema = schemas.getClass(table.getTableName()); + if (schema == null) { + schema = schemas.createClass(table.getTableName()); + newSchema = true; + } + for (final Path path : table.all()) { + final String name = path.getMetadata().getExpression() + .toString(); + OProperty property = schema.getProperty(name); + if (property == null) + property = schema.createProperty( + path.getMetadata().getExpression().toString(), + (path.getType().isEnum() ? OType.STRING : OType + .getTypeByClass(path.getType()))); + if (path.getType().isEnum()) { + property.setType(OType.STRING); + } else { + property.setType(OType.getTypeByClass(path.getType())); + } + } + for (final ForeignKey fk : table.getForeignKeys()) { + final String[] columns = new String[fk.getLocalColumns().size()]; + int i = 0; + for (final Path keyPath : fk.getLocalColumns()) { + columns[i++] = keyPath.getMetadata().getExpression() + .toString(); + } + schema.createIndex(StringUtils.join(columns, "-"), + INDEX_TYPE.NOTUNIQUE, columns); + } + final String[] pkColumns = new String[table.getPrimaryKey() + .getLocalColumns().size()]; + int i = 0; + for (final Path keyPath : table.getPrimaryKey() + .getLocalColumns()) { + pkColumns[i++] = keyPath.getMetadata().getExpression() + .toString(); + } + schema.createIndex("PRIMARY", INDEX_TYPE.UNIQUE, pkColumns); + schemas.save(); + } finally { + database.close(); + } + return newSchema; + } + + @Override + @SuppressWarnings("unchecked") + public , O extends Model> O getCachedObject(I id) { + Preconditions.checkNotNull(id, "id"); + log.debug("Fetching cached object {}", id); + return (O) objectCache.get(id); + } + + @Override + public , O extends Model> boolean hasCachedObject(I id) { + Preconditions.checkNotNull(id, "id"); + log.debug("Locating cached object {}", id); + return objectCache.contains(id); + } + + @Override + public , O extends Model> void updateCache(I id, O value) { + Preconditions.checkNotNull(id, "key"); + Preconditions.checkNotNull(value, "value"); + log.debug("Updating cached object {} with {}", id, value); + objectCache.put(id, value); + } + + @Override + public , O extends Model> void removeCache(I id) { + Preconditions.checkNotNull(id, "key"); + log.debug("Removing cached object {}", id); + objectCache.remove(id); + } + + @Override + protected void doStop() throws ServiceStopException { + autoSaveFuture.cancel(true); + autoSaveFuture = null; + cacheService.dispose(objectCache); + objectCache = null; + ODatabaseDocumentPool.global().close(); + } + + /** + * The query interface. The query will receive an connection an will be + * executed. The can return return a value if required. + * + * @author Rogiel + * + * @param + * the return type + */ + public interface Query { + /** + * Execute the query in conn + * + * @param database + * the database instance + * @param service + * the database service instance + * @return the query return value + */ + R query(ODatabaseDocumentTx database, DatabaseService service); + } + + public static abstract class AbstractQuery implements Query { + protected void updateDesire(Object object, ObjectDesire expected) { + if (object instanceof Model) { + if (((Model) object).getObjectDesire() == expected) { + ((Model) object).setObjectDesire(ObjectDesire.NONE); + } + } + } + + protected String name(Path path) { + return path.getMetadata().getExpression().toString(); + } + } + + public static class InsertQuery, E extends RelationalPathBase> + extends AbstractQuery { + private final InsertMapper mapper; + private final Iterator iterator; + @SuppressWarnings("unused") + // FIXME implement id generation + private final Path primaryKey; + + protected final E e; + + /** + * @param entity + * the entity type + * @param mapper + * the insert mapper + * @param iterator + * the objects to be inserted + * @param primaryKey + * the primary key, if any. Only required if the ID is + * generated by the database engine. + */ + public InsertQuery(E entity, InsertMapper mapper, + Path primaryKey, Iterator iterator) { + this.iterator = iterator; + this.mapper = mapper; + this.e = entity; + this.primaryKey = primaryKey; + } + + /** + * @param entity + * the entity type + * @param mapper + * the insert mapper + * @param iterator + * the objects to be inserted + */ + public InsertQuery(E entity, InsertMapper mapper, + Iterator iterator) { + this(entity, mapper, null, iterator); + } + + /** + * @param entity + * the entity type + * @param mapper + * the insert mapper + * @param objects + * the objects to be inserted + */ + @SafeVarargs + public InsertQuery(E entity, InsertMapper mapper, + O... objects) { + this(entity, mapper, null, Iterators.forArray(objects)); + } + + /** + * @param entity + * the entity type + * @param mapper + * the insert mapper + * @param objects + * the objects to be inserted + * @param primaryKey + * the primary key, if any. Only required if the ID is + * generated by the database engine. + */ + @SafeVarargs + public InsertQuery(E entity, InsertMapper mapper, + Path primaryKey, O... objects) { + this(entity, mapper, primaryKey, Iterators.forArray(objects)); + } + + @Override + public final Integer query(ODatabaseDocumentTx database, + DatabaseService service) { + int rows = 0; + final DocumentDatabaseRow row = new DocumentDatabaseRow(); + while (iterator.hasNext()) { + final O object = iterator.next(); + row.setDocument(new ODocument(database, e.getTableName())); + + mapper.insert(e, object, row); + + // TODO generate ids + row.getDocument().save(); + rows++; + + updateDesire(object, ObjectDesire.INSERT); + } + return rows; + } + } + + public static abstract class UpdateQuery> + extends AbstractQuery { + private final UpdateMapper mapper; + private final Iterator iterator; + protected final E e; + + /** + * @param entity + * the entity type + * @param mapper + * the update mapper + * @param iterator + * the objects to be inserted + */ + public UpdateQuery(E entity, UpdateMapper mapper, + Iterator iterator) { + this.iterator = iterator; + this.mapper = mapper; + this.e = entity; + } + + /** + * @param entity + * the entity type + * @param mapper + * the update mapper + * @param objects + * the objects to be inserted + */ + @SafeVarargs + public UpdateQuery(E entity, UpdateMapper mapper, O... objects) { + this(entity, mapper, Iterators.forArray(objects)); + } + + @Override + public final Integer query(ODatabaseDocumentTx database, + DatabaseService service) { + int rows = 0; + final DocumentDatabaseRow row = new DocumentDatabaseRow(); + while (iterator.hasNext()) { + final O object = iterator.next(); + + List documents = database + .query(new ONativeSynchQuery( + database, e.getTableName(), + new OQueryContextNative()) { + private static final long serialVersionUID = 1L; + + @Override + public boolean filter(OQueryContextNative record) { + return query(record, object).go(); + }; + }); + if (documents.size() < 1) + continue; + row.setDocument(documents.get(0)); + mapper.update(e, object, row); + + row.getDocument().save(); + rows++; + + updateDesire(object, ObjectDesire.UPDATE); + } + return rows; + } + + protected abstract OQueryContextNative query( + OQueryContextNative record, O o); + } + + public static abstract class DeleteQuery> + extends AbstractQuery { + private final Iterator iterator; + protected final E e; + + /** + * @param entity + * the entity type + * @param iterator + * the objects to be inserted + */ + public DeleteQuery(E entity, Iterator iterator) { + this.iterator = iterator; + this.e = entity; + } + + /** + * @param entity + * the entity type + * @param objects + * the objects to be inserted + */ + @SafeVarargs + public DeleteQuery(E entity, O... objects) { + this(entity, Iterators.forArray(objects)); + } + + @Override + public final Integer query(ODatabaseDocumentTx database, + DatabaseService service) { + int rows = 0; + while (iterator.hasNext()) { + final O object = iterator.next(); + + List documents = database + .query(new ONativeSynchQuery( + database, e.getTableName(), + new OQueryContextNative()) { + private static final long serialVersionUID = 1L; + + @Override + public boolean filter(OQueryContextNative record) { + return query(record, object).go(); + }; + }); + for (final ODocument document : documents) { + document.delete(); + rows++; + } + + updateDesire(object, ObjectDesire.DELETE); + } + return rows; + } + + protected abstract OQueryContextNative query( + OQueryContextNative record, O o); + } + + public static abstract class AbstractSelectQuery, E extends RelationalPathBase> + extends AbstractQuery { + protected final E entity; + protected final SelectMapper mapper; + + /** + * @param entity + * the entity type + * @param mapper + * the object mapper + */ + public AbstractSelectQuery(E entity, SelectMapper mapper) { + this.entity = entity; + this.mapper = mapper; + } + + @Override + public final R query(ODatabaseDocumentTx database, + DatabaseService service) { + List documents = database + .query(new ONativeSynchQuery(database, + entity.getTableName(), new OQueryContextNative()) { + private static final long serialVersionUID = 1L; + + @Override + public boolean filter(OQueryContextNative record) { + record = query(record, entity); + if (record == null) + return true; + return record.go(); + }; + }); + return perform(documents, service); + } + + protected abstract OQueryContextNative query( + OQueryContextNative record, E e); + + protected abstract R perform(List documents, + DatabaseService service); + + @SuppressWarnings("unchecked") + protected O lookupCache(DatabaseRow row, DatabaseService database) { + final I id = mapper.getPrimaryKeyMapper().createID( + (RI) row.get(entity.getPrimaryKey().getLocalColumns() + .get(0))); + + if (id != null) { + if (database.hasCachedObject(id)) + return (O) database.getCachedObject(id); + } + return null; + } + + protected void updateCache(O instance, DatabaseService database) { + if (instance == null) + return; + if (instance instanceof Model) + database.updateCache(((Model) instance).getID(), + (Model) instance); + } + } + + public static abstract class SelectSingleQuery, E extends RelationalPathBase> + extends AbstractSelectQuery { + /** + * @param entity + * the entity + * @param mapper + * the mapper + */ + public SelectSingleQuery(E entity, SelectMapper mapper) { + super(entity, mapper); + } + + @Override + protected final O perform(List documents, + DatabaseService service) { + final ODocument document = (!documents.isEmpty() ? documents.get(0) + : null); + if (document == null) + return null; + final DocumentDatabaseRow row = new DocumentDatabaseRow(document); + O object = lookupCache(row, service); + if (object == null) { + object = mapper.select(entity, row); + updateCache(object, service); + if (object instanceof Model) { + ((Model) object).setObjectDesire(ObjectDesire.NONE); + } + } + return object; + } + } + + public static abstract class SelectListQuery, E extends RelationalPathBase> + extends AbstractSelectQuery, O, RI, I, E> { + /** + * @param entity + * the entity + * @param mapper + * the mapper + */ + public SelectListQuery(E entity, SelectMapper mapper) { + super(entity, mapper); + } + + @Override + protected final List perform(List documents, + DatabaseService service) { + final List results = CollectionFactory.newList(); + final DocumentDatabaseRow row = new DocumentDatabaseRow(); + for (final ODocument document : documents) { + row.setDocument(document); + O object = lookupCache(row, service); + if (object == null) { + object = mapper.select(entity, row); + updateCache(object, service); + if (object instanceof Model) { + ((Model) object).setObjectDesire(ObjectDesire.NONE); + } + } + if (object != null) + results.add(object); + } + return results; + } + } +} diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/orientdb/DocumentDatabaseRow.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/orientdb/DocumentDatabaseRow.java new file mode 100644 index 000000000..71b067936 --- /dev/null +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/orientdb/DocumentDatabaseRow.java @@ -0,0 +1,78 @@ +/* + * This file is part of l2jserver2 . + * + * l2jserver2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * l2jserver2 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with l2jserver2. If not, see . + */ +package com.l2jserver.service.database.orientdb; + +import com.l2jserver.service.database.dao.DatabaseRow; +import com.l2jserver.service.database.dao.WritableDatabaseRow; +import com.mysema.query.types.Path; +import com.orientechnologies.orient.core.record.impl.ODocument; + +/** + * @author Rogiel + * + */ +public class DocumentDatabaseRow implements DatabaseRow, WritableDatabaseRow { + private ODocument document; + + /** + * @param document + * the orientdb document + */ + public DocumentDatabaseRow(ODocument document) { + this.document = document; + } + + public DocumentDatabaseRow() { + } + + @Override + public T get(Path path) { + return document.field(path.getMetadata().getExpression().toString(), + path.getType()); + } + + @Override + public boolean isNull(Path path) { + return get(path) == null; + } + + @Override + public WritableDatabaseRow set(Path path, T value) { + document.field(path.getMetadata().getExpression().toString(), value); + return this; + } + + @Override + public WritableDatabaseRow setNull(Path path) { + return set(path, null); + } + + /** + * @return the orientdb document + */ + public ODocument getDocument() { + return document; + } + + /** + * @param document + * the orientdb document to set + */ + public void setDocument(ODocument document) { + this.document = document; + } +} diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/AbstractSQLDatabaseService.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/AbstractSQLDatabaseService.java index d5b1ecb6d..22984c12f 100644 --- a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/AbstractSQLDatabaseService.java +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/AbstractSQLDatabaseService.java @@ -25,6 +25,7 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; import javax.sql.DataSource; @@ -64,14 +65,17 @@ import com.l2jserver.service.database.dao.DatabaseRow; import com.l2jserver.service.database.dao.InsertMapper; import com.l2jserver.service.database.dao.SelectMapper; import com.l2jserver.service.database.dao.UpdateMapper; -import com.l2jserver.service.database.sql.ddl.QueryFactory; -import com.l2jserver.service.database.sql.ddl.TableFactory; -import com.l2jserver.service.database.sql.ddl.struct.Table; +import com.l2jserver.service.database.ddl.QueryFactory; +import com.l2jserver.service.database.ddl.TableFactory; +import com.l2jserver.service.database.ddl.struct.Table; import com.l2jserver.util.factory.CollectionFactory; import com.mysema.query.sql.AbstractSQLQuery; +import com.mysema.query.sql.RelationalPath; import com.mysema.query.sql.RelationalPathBase; import com.mysema.query.sql.SQLQueryFactory; +import com.mysema.query.sql.dml.Mapper; import com.mysema.query.sql.dml.SQLDeleteClause; +import com.mysema.query.sql.dml.SQLInsertClause; import com.mysema.query.sql.dml.SQLUpdateClause; import com.mysema.query.sql.types.Type; import com.mysema.query.types.Path; @@ -442,43 +446,6 @@ public abstract class AbstractSQLDatabaseService extends AbstractService return create; } - /** - * Imports an entire SQL file into the database. If the file consists of - * several SQL statements, they will be splitted and executed separated. - * - * @param conn - * the SQL connection - * @param sqlPath - * the path for the SQL file - * @throws IOException - * if any error occur while reading the file - * @throws SQLException - * if any error occur while executing the statements - */ - protected void importSQL(Connection conn, java.nio.file.Path sqlPath) - throws IOException, SQLException { - BufferedReader reader = Files.newBufferedReader(sqlPath, - Charset.defaultCharset()); - final StringBuilder builder = new StringBuilder(); - String line; - conn.setAutoCommit(false); - try { - while ((line = reader.readLine()) != null) { - builder.append(line).append("\n"); - if (line.trim().endsWith(";")) { - executeSQL(conn, builder.substring(0, builder.length() - 2)); - builder.setLength(0); - } - } - conn.commit(); - } catch (SQLException | IOException e) { - conn.rollback(); - throw e; - } finally { - conn.setAutoCommit(true); - } - } - /** * Executes the SQL code in the databases * @@ -503,6 +470,56 @@ public abstract class AbstractSQLDatabaseService extends AbstractService } } + @Override + public , T extends RelationalPathBase> void importData( + java.nio.file.Path path, T entity) throws IOException { + Connection conn; + try { + conn = dataSource.getConnection(); + } catch (SQLException e) { + return; + } + log.info("Importing {} to {}", path, entity); + try { + BufferedReader reader = Files.newBufferedReader(path, + Charset.defaultCharset()); + final String header[] = reader.readLine().split(","); + String line; + while ((line = reader.readLine()) != null) { + final String data[] = line.split(","); + SQLInsertClause insert = engine.createSQLQueryFactory(conn) + .insert(entity); + insert.populate(data, new Mapper() { + @Override + public Map, Object> createMap( + RelationalPath relationalPath, Object[] object) { + final Map, Object> values = CollectionFactory + .newMap(); + pathFor: for (final Path path : relationalPath + .getColumns()) { + int i = 0; + for (final String headerName : header) { + if (path.getMetadata().getExpression() + .toString().equals(headerName)) { + values.put(path, object[i]); + continue pathFor; + } + i++; + } + } + return values; + } + }); + insert.execute(); + } + } finally { + try { + conn.close(); + } catch (SQLException e) { + } + } + } + @Override public int transaction(TransactionExecutor executor) { Preconditions.checkNotNull(executor, "executor"); diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/DatabaseEngine.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/DatabaseEngine.java index 649315347..4182e5c7b 100644 --- a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/DatabaseEngine.java +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/DatabaseEngine.java @@ -20,7 +20,7 @@ import java.sql.Connection; import java.sql.Driver; import java.sql.SQLException; -import com.l2jserver.service.database.sql.ddl.QueryTemplate; +import com.l2jserver.service.database.ddl.QueryTemplate; import com.mysema.query.sql.AbstractSQLQuery; import com.mysema.query.sql.SQLQueryFactory; import com.mysema.query.sql.types.Type; diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/DerbyDatabaseEngine.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/DerbyDatabaseEngine.java index db7f392dd..c4b782d54 100644 --- a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/DerbyDatabaseEngine.java +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/DerbyDatabaseEngine.java @@ -24,8 +24,8 @@ import javax.inject.Provider; import org.apache.derby.jdbc.EmbeddedDriver; -import com.l2jserver.service.database.sql.ddl.QueryTemplate; -import com.l2jserver.service.database.sql.ddl.template.DerbyTemplate; +import com.l2jserver.service.database.ddl.QueryTemplate; +import com.l2jserver.service.database.ddl.template.DerbyTemplate; import com.mysema.query.sql.AbstractSQLQuery; import com.mysema.query.sql.Configuration; import com.mysema.query.sql.SQLQueryFactory; diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/H2DatabaseEngine.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/H2DatabaseEngine.java index 56759cd09..96ac8a014 100644 --- a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/H2DatabaseEngine.java +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/H2DatabaseEngine.java @@ -23,8 +23,8 @@ import javax.inject.Provider; import org.h2.Driver; -import com.l2jserver.service.database.sql.ddl.QueryTemplate; -import com.l2jserver.service.database.sql.ddl.template.H2Template; +import com.l2jserver.service.database.ddl.QueryTemplate; +import com.l2jserver.service.database.ddl.template.H2Template; import com.mysema.query.sql.AbstractSQLQuery; import com.mysema.query.sql.Configuration; import com.mysema.query.sql.SQLQueryFactory; diff --git a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/MySQLDatabaseEngine.java b/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/MySQLDatabaseEngine.java index 014aab8be..1be076a91 100644 --- a/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/MySQLDatabaseEngine.java +++ b/l2jserver2-common/src/main/java/com/l2jserver/service/database/sql/MySQLDatabaseEngine.java @@ -22,8 +22,8 @@ import java.sql.SQLException; import javax.inject.Provider; -import com.l2jserver.service.database.sql.ddl.QueryTemplate; -import com.l2jserver.service.database.sql.ddl.template.MySQLTemplate; +import com.l2jserver.service.database.ddl.QueryTemplate; +import com.l2jserver.service.database.ddl.template.MySQLTemplate; import com.mysema.query.sql.AbstractSQLQuery; import com.mysema.query.sql.Configuration; import com.mysema.query.sql.SQLQueryFactory; diff --git a/l2jserver2-common/src/main/java/com/l2jserver/util/transformer/impl/ClassTransformer.java b/l2jserver2-common/src/main/java/com/l2jserver/util/transformer/impl/ClassTransformer.java index c6b5de874..aadd01718 100644 --- a/l2jserver2-common/src/main/java/com/l2jserver/util/transformer/impl/ClassTransformer.java +++ b/l2jserver2-common/src/main/java/com/l2jserver/util/transformer/impl/ClassTransformer.java @@ -38,7 +38,7 @@ public class ClassTransformer implements Transformer> { @Override public Class untransform(Class> type, String value) { try { - return Class.forName(value); + return Class.forName(value.trim()); } catch (ClassNotFoundException e) { throw new TransformException(e); } diff --git a/l2jserver2-gameserver/config/config.xml b/l2jserver2-gameserver/config/config.xml index a7a29ad17..2cd249f53 100644 --- a/l2jserver2-gameserver/config/config.xml +++ b/l2jserver2-gameserver/config/config.xml @@ -19,12 +19,18 @@ not sure on the usage of any parameter, read the "Configuration" section in wiki article about DatabaseService. --> + + local:data/database + admin + admin + jdbc:mysql://localhost/l2jserver2 - com.l2jserver.service.database.sql.MySQLDatabaseEngine + com.l2jserver.service.database.sql.MySQLDatabaseEngine +