Skip to content

Commit

Permalink
Added first version of MongoDB support
Browse files Browse the repository at this point in the history
  • Loading branch information
Tim203 committed Jun 30, 2024
1 parent e32e6e7 commit f172e7b
Show file tree
Hide file tree
Showing 46 changed files with 1,516 additions and 741 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@ currently examples can be found in the tests of the AP module and the tests of t

# What's left to do?
- make 'simple' actions like `insert` more flexible
- allow it to return something else than void, e.g. ~~the input entity~~ or whether there was a row added
- allow it to return whether there was a row added
- support adding every variable of the entity as parameter
- add `save` which either inserts the entity if it's not present or updates the already existing entity
- implementing MongoDB support
- adding migrations
- and plenty more

Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,13 @@
/*
* Copyright (c) 2024 GeyserMC <https://geysermc.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* Copyright (c) 2024 GeyserMC
* Licensed under the MIT license
* @link https://github.com/GeyserMC/DatabaseUtils
*/
package org.geysermc.databaseutils.processor;

import static org.geysermc.databaseutils.processor.util.AnnotationUtils.hasAnnotation;

import com.google.auto.common.MoreTypes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
Expand All @@ -38,7 +20,9 @@
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
import org.geysermc.databaseutils.meta.Entity;
import org.geysermc.databaseutils.meta.Index;
import org.geysermc.databaseutils.meta.Key;
import org.geysermc.databaseutils.processor.info.ColumnInfo;
import org.geysermc.databaseutils.processor.info.EntityInfo;
Expand All @@ -57,7 +41,9 @@ Collection<EntityInfo> processedEntities() {
return entityInfoByClassName.values();
}

EntityInfo processEntity(TypeElement type) {
EntityInfo processEntity(TypeMirror typeMirror) {
var type = MoreTypes.asTypeElement(typeMirror);

var cached = entityInfoByClassName.get(type.getQualifiedName());
if (cached != null) {
return cached;
Expand All @@ -78,7 +64,7 @@ EntityInfo processEntity(TypeElement type) {
var indexes = new ArrayList<IndexInfo>();
var columns = new ArrayList<ColumnInfo>();

Arrays.stream(type.getAnnotationsByType(org.geysermc.databaseutils.meta.Index.class))
Arrays.stream(type.getAnnotationsByType(Index.class))
.map(index -> new IndexInfo(index.name(), index.columns(), index.unique()))
.forEach(indexes::add);

Expand All @@ -100,14 +86,14 @@ EntityInfo processEntity(TypeElement type) {
}

TypeElement typeElement = typeUtils.toBoxedTypeElement(field.asType());
columns.add(new ColumnInfo(field.getSimpleName(), typeElement.getQualifiedName()));
columns.add(new ColumnInfo(field.getSimpleName(), typeElement, typeElement.getQualifiedName()));

if (hasAnnotation(field, Key.class)) {
keys.add(field.getSimpleName());
}
var index = field.getAnnotation(org.geysermc.databaseutils.meta.Index.class);
var index = field.getAnnotation(Index.class);
if (index != null) {
indexes.add(new IndexInfo(index.name(), index.columns(), index.unique()));
indexes.add(new IndexInfo(index.name(), index.columns(), index.unique(), index.direction()));
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,55 +1,47 @@
/*
* Copyright (c) 2024 GeyserMC <https://geysermc.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* Copyright (c) 2024 GeyserMC
* Licensed under the MIT license
* @link https://github.com/GeyserMC/DatabaseUtils
*/
package org.geysermc.databaseutils.processor;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.geysermc.databaseutils.DatabaseType;
import org.geysermc.databaseutils.processor.type.DatabaseGenerator;
import org.geysermc.databaseutils.processor.type.RepositoryGenerator;
import org.geysermc.databaseutils.processor.type.SqlDatabaseGenerator;
import org.geysermc.databaseutils.processor.type.SqlRepositoryGenerator;
import org.geysermc.databaseutils.processor.type.mongo.MongoDatabaseGenerator;
import org.geysermc.databaseutils.processor.type.mongo.MongoRepositoryGenerator;
import org.geysermc.databaseutils.processor.type.sql.SqlDatabaseGenerator;
import org.geysermc.databaseutils.processor.type.sql.SqlRepositoryGenerator;

final class RegisteredGenerators {
// both the database and the repository generators have to be on the same indexes

private static final List<Supplier<DatabaseGenerator>> DATABASE_GENERATORS = List.of(SqlDatabaseGenerator::new);
private static final List<Supplier<RepositoryGenerator>> REPOSITORY_GENERATORS =
List.of(SqlRepositoryGenerator::new);
private static final Map<DatabaseType, Supplier<DatabaseGenerator>> DATABASE_GENERATORS = new HashMap<>();
private static final Map<DatabaseType, Supplier<RepositoryGenerator>> REPOSITORY_GENERATORS = new HashMap<>();

private RegisteredGenerators() {}

public static List<DatabaseGenerator> databaseGenerators() {
return DATABASE_GENERATORS.stream().map(Supplier::get).collect(Collectors.toList());
return DATABASE_GENERATORS.values().stream().map(Supplier::get).collect(Collectors.toList());
}

public static List<RepositoryGenerator> repositoryGenerators() {
return REPOSITORY_GENERATORS.stream().map(Supplier::get).collect(Collectors.toList());
return REPOSITORY_GENERATORS.values().stream().map(Supplier::get).collect(Collectors.toList());
}

public static int generatorCount() {
return DATABASE_GENERATORS.size();
}

static {
// todo make it less cursed by using one map/list with everything for each database category
DATABASE_GENERATORS.put(DatabaseType.SQL, SqlDatabaseGenerator::new);
DATABASE_GENERATORS.put(DatabaseType.MONGODB, MongoDatabaseGenerator::new);

REPOSITORY_GENERATORS.put(DatabaseType.SQL, SqlRepositoryGenerator::new);
REPOSITORY_GENERATORS.put(DatabaseType.MONGODB, MongoRepositoryGenerator::new);
}
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,6 @@
/*
* Copyright (c) 2024 GeyserMC <https://geysermc.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* Copyright (c) 2024 GeyserMC
* Licensed under the MIT license
* @link https://github.com/GeyserMC/DatabaseUtils
*/
package org.geysermc.databaseutils.processor;
Expand Down Expand Up @@ -136,7 +117,7 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment
repositoryClasses.add(result.packageName() + "." + build.name);
}

var spec = TypeSpec.classBuilder(generator.databaseClass().getSimpleName() + "Generated");
var spec = TypeSpec.classBuilder(generator.databaseType().upperCamelCaseName() + "DatabaseGenerated");
generator.init(spec, hasAsync);
generator.addEntities(entityManager.processedEntities());
generator.addRepositories(repositoryClasses);
Expand Down Expand Up @@ -178,7 +159,7 @@ private List<RepositoryGenerator> processRepository(TypeElement repository) {
throw new InvalidRepositoryException("Repository has to extend IRepository<EntityClass>");
}

var entity = entityManager.processEntity(MoreTypes.asTypeElement(entityType));
var entity = entityManager.processEntity(entityType);

var generators = RegisteredGenerators.repositoryGenerators();
for (var generator : generators) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,6 @@
/*
* Copyright (c) 2024 GeyserMC <https://geysermc.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* Copyright (c) 2024 GeyserMC
* Licensed under the MIT license
* @link https://github.com/GeyserMC/DatabaseUtils
*/
package org.geysermc.databaseutils.processor.action;
Expand Down Expand Up @@ -146,7 +127,8 @@ public void validate(

public void addTo(List<RepositoryGenerator> generators, QueryContext context) {
if (!context.hasBySection() && !context.parametersInfo().isNoneOrAnySelf()) {
throw new InvalidRepositoryException("Expected at most one parameter, with type %s", context.entityType());
throw new InvalidRepositoryException(
"Expected at most one parameter, with type %s", context.entityTypeName());
}

for (RepositoryGenerator generator : generators) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,11 @@
/*
* Copyright (c) 2024 GeyserMC <https://geysermc.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* Copyright (c) 2024 GeyserMC
* Licensed under the MIT license
* @link https://github.com/GeyserMC/DatabaseUtils
*/
package org.geysermc.databaseutils.processor.info;

import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;

public record ColumnInfo(Name name, Name typeName) {}
public record ColumnInfo(Name name, TypeElement type, Name typeName) {}
Original file line number Diff line number Diff line change
@@ -1,25 +1,6 @@
/*
* Copyright (c) 2024 GeyserMC <https://geysermc.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* Copyright (c) 2024 GeyserMC
* Licensed under the MIT license
* @link https://github.com/GeyserMC/DatabaseUtils
*/
package org.geysermc.databaseutils.processor.info;
Expand All @@ -28,6 +9,11 @@
import java.util.List;
import java.util.stream.Collectors;
import javax.lang.model.element.TypeElement;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.databaseutils.processor.query.section.by.keyword.EqualsKeyword;
import org.geysermc.databaseutils.processor.query.section.factor.Factor;
import org.geysermc.databaseutils.processor.query.section.factor.VariableByFactor;

public record EntityInfo(
String name, TypeElement type, List<ColumnInfo> columns, List<IndexInfo> indexes, List<CharSequence> keys) {
Expand All @@ -54,10 +40,27 @@ public List<ColumnInfo> notKeyColumns() {
.toList();
}

public List<ColumnInfo> notKeyFirstColumns() {
var combined = new ArrayList<ColumnInfo>();
combined.addAll(notKeyColumns());
combined.addAll(keyColumns());
return combined;
public List<Factor> keyColumnsAsFactors(@Nullable Factor separator, @NonNull CharSequence parameterName) {
return asFactors(keyColumns(), separator, parameterName);
}

public List<Factor> notKeyColumnsAsFactors(@Nullable Factor separator, @NonNull CharSequence parameterName) {
return asFactors(notKeyColumns(), separator, parameterName);
}

private List<Factor> asFactors(
@NonNull List<ColumnInfo> columns, @Nullable Factor separator, @Nullable CharSequence parameterName) {
var factors = new ArrayList<Factor>();
for (ColumnInfo column : columns) {
if (!factors.isEmpty() && separator != null) {
factors.add(separator);
}

if (parameterName != null) {
var name = "%s.%s()".formatted(parameterName, column.name());
factors.add(new VariableByFactor(column.name(), new EqualsKeyword().addParameterName(name)));
}
}
return factors;
}
}
Loading

0 comments on commit f172e7b

Please sign in to comment.