Skip to content

Commit

Permalink
feat: generate a base repository bean class
Browse files Browse the repository at this point in the history
Signed-off-by: Otavio Santana <[email protected]>
  • Loading branch information
otaviojava committed Mar 7, 2025
1 parent 061aa29 commit fcea3bb
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 138 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Copyright (c) 2025 Contributors to the Eclipse Foundation
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php.
*
* You may elect to redistribute this code under either of these licenses.
*
* Contributors:
*
* Otavio Santana
*/
package org.eclipse.jnosql.mapping.semistructured.query;

import jakarta.enterprise.context.spi.CreationalContext;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import org.eclipse.jnosql.mapping.DatabaseQualifier;
import org.eclipse.jnosql.mapping.DatabaseType;
import org.eclipse.jnosql.mapping.core.Converters;
import org.eclipse.jnosql.mapping.core.spi.AbstractBean;
import org.eclipse.jnosql.mapping.core.util.AnnotationLiteralUtil;
import org.eclipse.jnosql.mapping.metadata.EntitiesMetadata;
import org.eclipse.jnosql.mapping.semistructured.SemiStructuredTemplate;

/**
* Abstract base class for repository beans, handling common logic
* for both Custom and Standard Repositories.
*
* @param <T> The repository type
*/
abstract class BaseRepositoryBean<T> extends AbstractBean<T> {

private final Class<T> type;
private final Set<Type> types;
private final String provider;
private final Set<Annotation> qualifiers;
private final DatabaseType databaseType;

protected BaseRepositoryBean(Class<?> type, String provider, DatabaseType databaseType) {
this.type = (Class<T>) type;
this.types = Collections.singleton(type);
this.provider = provider;
this.databaseType = databaseType;
this.qualifiers = initializeQualifiers();
}

private Set<Annotation> initializeQualifiers() {
if (provider.isEmpty()) {
Set<Annotation> defaultQualifiers = new HashSet<>();
defaultQualifiers.add(getDatabaseQualifier());
defaultQualifiers.add(AnnotationLiteralUtil.DEFAULT_ANNOTATION);
defaultQualifiers.add(AnnotationLiteralUtil.ANY_ANNOTATION);
return defaultQualifiers;
}
return Collections.singleton(getDatabaseQualifier(provider));
}

protected abstract Class<? extends SemiStructuredTemplate> getTemplateClass();
protected abstract DatabaseQualifier getDatabaseQualifier();
protected abstract DatabaseQualifier getDatabaseQualifier(String provider);

/**
* Subclasses define how the repository handler is created.
*/
protected abstract InvocationHandler createHandler(EntitiesMetadata entities, SemiStructuredTemplate template, Converters converters);

@Override
public Class<?> getBeanClass() {
return type;
}

@SuppressWarnings("unchecked")
@Override
public T create(CreationalContext<T> context) {
var entities = getInstance(EntitiesMetadata.class);
var template = provider.isEmpty()
? getInstance(getTemplateClass())
: getInstance(getTemplateClass(), getDatabaseQualifier(provider));

var converters = getInstance(Converters.class);
InvocationHandler handler = createHandler(entities, template, converters);

return (T) Proxy.newProxyInstance(type.getClassLoader(), new Class[]{type}, handler);
}

@Override
public Set<Type> getTypes() {
return types;
}

@Override
public Set<Annotation> getQualifiers() {
return qualifiers;
}

@Override
public String getId() {
return type.getName() + '@' + databaseType + "-" + provider;
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -14,98 +14,41 @@
*/
package org.eclipse.jnosql.mapping.semistructured.query;

import jakarta.enterprise.context.spi.CreationalContext;
import java.lang.reflect.InvocationHandler;
import org.eclipse.jnosql.mapping.DatabaseQualifier;
import org.eclipse.jnosql.mapping.DatabaseType;
import org.eclipse.jnosql.mapping.core.Converters;
import org.eclipse.jnosql.mapping.core.spi.AbstractBean;
import org.eclipse.jnosql.mapping.core.util.AnnotationLiteralUtil;
import org.eclipse.jnosql.mapping.metadata.EntitiesMetadata;
import org.eclipse.jnosql.mapping.semistructured.SemiStructuredTemplate;

import java.lang.annotation.Annotation;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class CustomRepositoryBean<T> extends BaseRepositoryBean<T> {

/**
* The template method class for Custom Repository Beans to reduce duplication across different database types.
*/
public abstract class CustomRepositoryBean<T> extends AbstractBean<T> {

private final Class<T> type;
private final Set<Type> types;
private final String provider;
private final Set<Annotation> qualifiers;
private final DatabaseType databaseType;

@SuppressWarnings("unchecked")
protected CustomRepositoryBean(Class<?> type, String provider, DatabaseType databaseType) {
this.type = (Class<T>) type;
this.types = Collections.singleton(type);
this.provider = provider;
this.databaseType = databaseType;
this.qualifiers = initializeQualifiers();
public CustomRepositoryBean(Class<?> type, String provider, DatabaseType databaseType) {
super(type, provider, databaseType);
}

private Set<Annotation> initializeQualifiers() {
if (provider.isEmpty()) {
Set<Annotation> defaultQualifiers = new HashSet<>();
defaultQualifiers.add(getDatabaseQualifier());
defaultQualifiers.add(AnnotationLiteralUtil.DEFAULT_ANNOTATION);
defaultQualifiers.add(AnnotationLiteralUtil.ANY_ANNOTATION);
return defaultQualifiers;
}
return Collections.singleton(getDatabaseQualifier(provider));
@Override
protected Class<? extends SemiStructuredTemplate> getTemplateClass() {
return SemiStructuredTemplate.class;
}

protected abstract Class<? extends SemiStructuredTemplate> getTemplateClass();

protected abstract DatabaseQualifier getDatabaseQualifier();

protected abstract DatabaseQualifier getDatabaseQualifier(String provider);

@Override
public Class<?> getBeanClass() {
return type;
protected DatabaseQualifier getDatabaseQualifier() {
return DatabaseQualifier.ofGraph();
}

@SuppressWarnings("unchecked")
@Override
public T create(CreationalContext<T> context) {
var entities = getInstance(EntitiesMetadata.class);
var template = provider.isEmpty()
? getInstance(getTemplateClass())
: getInstance(getTemplateClass(), getDatabaseQualifier(provider));

var converters = getInstance(Converters.class);
protected DatabaseQualifier getDatabaseQualifier(String provider) {
return DatabaseQualifier.ofGraph(provider);
}

var handler = CustomRepositoryHandler.builder()
@Override
protected InvocationHandler createHandler(EntitiesMetadata entities, SemiStructuredTemplate template, Converters converters) {
return CustomRepositoryHandler.builder()
.entitiesMetadata(entities)
.template(template)
.customRepositoryType(type)
.customRepositoryType(getBeanClass())
.converters(converters)
.build();

return (T) Proxy.newProxyInstance(type.getClassLoader(),
new Class[]{type},
handler);
}

@Override
public Set<Type> getTypes() {
return types;
}

@Override
public Set<Annotation> getQualifiers() {
return qualifiers;
}

@Override
public String getId() {
return type.getName() + '@' + databaseType + "-" + provider;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,90 +13,39 @@
* Otavio Santana
*/
package org.eclipse.jnosql.mapping.semistructured.query;

import jakarta.data.repository.DataRepository;
import jakarta.enterprise.context.spi.CreationalContext;
import java.lang.reflect.InvocationHandler;
import org.eclipse.jnosql.mapping.DatabaseQualifier;
import org.eclipse.jnosql.mapping.DatabaseType;
import org.eclipse.jnosql.mapping.core.Converters;
import org.eclipse.jnosql.mapping.core.spi.AbstractBean;
import org.eclipse.jnosql.mapping.core.util.AnnotationLiteralUtil;
import org.eclipse.jnosql.mapping.metadata.EntitiesMetadata;
import org.eclipse.jnosql.mapping.semistructured.SemiStructuredTemplate;

import java.lang.annotation.Annotation;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/**
* Abstract class for repository beans that dynamically create repository instances.
*/
public abstract class RepositoryBean<T extends DataRepository<T, ?>> extends AbstractBean<T> {

private final Class<T> type;
private final Set<Type> types;
private final String provider;
private final Set<Annotation> qualifiers;
private final DatabaseType databaseType;
public class RepositoryBean<T extends DataRepository<T, ?>> extends BaseRepositoryBean<T> {

protected RepositoryBean(Class<?> type, String provider, DatabaseType databaseType) {
this.type = (Class<T>) type;
this.types = Collections.singleton(type);
this.provider = provider;
this.databaseType = databaseType;
this.qualifiers = initializeQualifiers();
public RepositoryBean(Class<?> type, String provider, DatabaseType databaseType) {
super(type, provider, databaseType);
}

private Set<Annotation> initializeQualifiers() {
if (provider.isEmpty()) {
Set<Annotation> defaultQualifiers = new HashSet<>();
defaultQualifiers.add(getDatabaseQualifier());
defaultQualifiers.add(AnnotationLiteralUtil.DEFAULT_ANNOTATION);
defaultQualifiers.add(AnnotationLiteralUtil.ANY_ANNOTATION);
return defaultQualifiers;
}
return Collections.singleton(getDatabaseQualifier(provider));
}

protected abstract Class<? extends SemiStructuredTemplate> getTemplateClass();

protected abstract DatabaseQualifier getDatabaseQualifier();

protected abstract DatabaseQualifier getDatabaseQualifier(String provider);

@Override
public Class<?> getBeanClass() {
return type;
protected Class<? extends SemiStructuredTemplate> getTemplateClass() {
return SemiStructuredTemplate.class;
}

@SuppressWarnings("unchecked")
@Override
public T create(CreationalContext<T> context) {
var entities = getInstance(EntitiesMetadata.class);
var template = provider.isEmpty()
? getInstance(getTemplateClass())
: getInstance(getTemplateClass(), getDatabaseQualifier(provider));

var converters = getInstance(Converters.class);

var handler = new SemiStructuredRepositoryProxy<>(template, entities, type, converters);
return (T) Proxy.newProxyInstance(type.getClassLoader(), new Class[]{type}, handler);
protected DatabaseQualifier getDatabaseQualifier() {
return DatabaseQualifier.ofGraph();
}

@Override
public Set<Type> getTypes() {
return types;
protected DatabaseQualifier getDatabaseQualifier(String provider) {
return DatabaseQualifier.ofGraph(provider);
}

@Override
public Set<Annotation> getQualifiers() {
return qualifiers;
}

@Override
public String getId() {
return type.getName() + '@' + databaseType + "-" + provider;
protected InvocationHandler createHandler(EntitiesMetadata entities, SemiStructuredTemplate template, Converters converters) {
return new SemiStructuredRepositoryProxy<>(template, entities, getBeanClass(), converters);
}
}

0 comments on commit fcea3bb

Please sign in to comment.