Skip to content

Commit

Permalink
Merge pull request #250 from kbss-cvut/development
Browse files Browse the repository at this point in the history
[2.0.1] Release
  • Loading branch information
ledsoft authored Jun 18, 2024
2 parents b551f41 + 8a03bbf commit 5e18493
Show file tree
Hide file tree
Showing 97 changed files with 1,406 additions and 764 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# JOPA - Change Log

## 2.0.1 - 2024-06-17
- Proper implementation of `EntityManager.getReference` after 2.0.0 rewrite (Enhancement #233).
- Log JOPA version and build date on persistence unit startup (Enhancement #243).
- Prevent `AssertionError` on `EntityManager.flush` calls (Bug #240).
- Fix incorrect SOQL to SPARQL translation when traversing reference and using identifier (Bug #234).
- Fix issues with interaction of lazy loading with cascading (Bug #248).
- Dependency updates: RDF4J 4.3.12.

## 2.0.0 - 2024-05-27
- Move internal API from `jopa-api` to the `jopa-impl` module (Enhancement #146).
- Modify name resolution in OWL2Java, support prefixes so that terms are better disambiguated without appending the useless `_A` suffix if possible (Enhancement #85).
Expand Down
2 changes: 1 addition & 1 deletion datatype/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<artifactId>jopa-all</artifactId>
<groupId>cz.cvut.kbss.jopa</groupId>
<version>2.0.0</version>
<version>2.0.1</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion jopa-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>cz.cvut.kbss.jopa</groupId>
<artifactId>jopa-all</artifactId>
<version>2.0.0</version>
<version>2.0.1</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@
import cz.cvut.kbss.jopa.model.EntityManager;

/**
* Thrown when {@link EntityManager#refresh(Object)} is called and the object no longer exists in the database.
* Thrown by the persistence provider when an entity reference obtained by
* {@link EntityManager#getReference(Class, Object)} is accessed but the entity does not exist. Thrown when
* {@link EntityManager#refresh} is called and the object no longer exists in the database.
* <p>
* The current transaction, if one is active and the persistence context has been joined to it, will be marked for rollback.
* The current transaction, if one is active and the persistence context has been joined to it, will be marked for
* rollback.
*/
public class EntityNotFoundException extends OWLPersistenceException {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/
package cz.cvut.kbss.jopa.model.metamodel;

@FunctionalInterface
public interface IdentifierVisitor {

void visit(IRIIdentifier i);
Expand Down
2 changes: 1 addition & 1 deletion jopa-distribution/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>cz.cvut.kbss.jopa</groupId>
<artifactId>jopa-all</artifactId>
<version>2.0.0</version>
<version>2.0.1</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
13 changes: 12 additions & 1 deletion jopa-impl/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>cz.cvut.kbss.jopa</groupId>
<artifactId>jopa-all</artifactId>
<version>2.0.0</version>
<version>2.0.1</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down Expand Up @@ -49,6 +49,12 @@


<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.antlr</groupId>
Expand All @@ -63,6 +69,11 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>${maven.resources.plugin.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,15 @@ protected void processElements(Enumeration<URL> urls, String scanPath) throws IO
continue;
}
visited.add(elemUri);
LOG.trace("Processing classpath element {}", url);
LOG.trace("Processing classpath element {}", elemUri);
if (isJar(elemUri)) {
processJarFile(createJarFile(url));
final JarFile jarFile = createJarFile(url);
if (!elemUri.equals(jarFile.getName()) && visited.contains(jarFile.getName())) {
LOG.trace("Classpath element {} maps to a JAR file {} and it has already been processed.", elemUri, jarFile.getName());
} else {
visited.add(jarFile.getName());
processJarFile(jarFile);
}
} else {
processDirectory(new File(URI.create(elemUri).getPath()), scanPath);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import cz.cvut.kbss.jopa.utils.CollectionFactory;
import cz.cvut.kbss.jopa.utils.Configuration;
import cz.cvut.kbss.jopa.utils.EntityPropertiesUtils;
import cz.cvut.kbss.jopa.utils.JOPALazyUtils;
import cz.cvut.kbss.jopa.utils.Wrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -227,7 +228,7 @@ protected void exploreCascaded(Attribute<?, ?> at, Object merged, Object toMerge

private void mergeX(Attribute<?, ?> at, Object merged, Object toMerge, Descriptor descriptor) {
Object attVal = EntityPropertiesUtils.getAttributeValue(at, toMerge);
if (attVal == null) {
if (attVal == null || JOPALazyUtils.isLazyLoadingProxy(attVal)) {
return;
}
if (at.isCollection()) {
Expand Down Expand Up @@ -261,7 +262,7 @@ public void remove(Object object) {
registerProcessedInstance(object);
// Intentional fall-through
case REMOVED:
new SimpleOneLevelCascadeExplorer(this::remove).start(this, object, CascadeType.REMOVE);
new OneLevelRemoveCascadeExplorer(this::remove).start(this, object, CascadeType.REMOVE);
break;
default:
throw new IllegalArgumentException("Entity " + object + " is not managed and cannot be removed.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,46 @@
*/
package cz.cvut.kbss.jopa.model;

import java.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.Set;

public class JOPAPersistenceProvider implements PersistenceProvider, ProviderUtil {

private static final Logger LOG = LoggerFactory.getLogger(JOPAPersistenceProvider.class);

private static final Set<EntityManagerFactoryImpl> EMFS = Collections.synchronizedSet(new HashSet<>());

public JOPAPersistenceProvider() {
logVersionInfo();
}

@Override
public EntityManagerFactoryImpl createEntityManagerFactory(String emName, Map<String, String> properties) {
final EntityManagerFactoryImpl emf = new EntityManagerFactoryImpl(properties, this::emfClosed);
EMFS.add(emf);
return emf;
}

private static void logVersionInfo() {
try {
final Properties props = new Properties();
props.load(JOPAPersistenceProvider.class.getClassLoader().getResourceAsStream("jopa.properties"));
assert props.containsKey("cz.cvut.jopa.version");
assert props.containsKey("cz.cvut.jopa.build.timestamp");
LOG.info("This is JOPA {}, built on {}...", props.get("cz.cvut.jopa.version"), props.get("cz.cvut.jopa.build.timestamp"));
} catch (IOException e) {
LOG.warn("Unable to load properties file to log version info.", e);
}
}

void emfClosed(EntityManagerFactoryImpl emf) {
EMFS.remove(emf);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import cz.cvut.kbss.jopa.model.metamodel.MetamodelBuilder;
import cz.cvut.kbss.jopa.model.metamodel.StaticMetamodelInitializer;
import cz.cvut.kbss.jopa.proxy.lazy.gen.LazyLoadingEntityProxyGenerator;
import cz.cvut.kbss.jopa.proxy.reference.EntityReferenceProxyGenerator;
import cz.cvut.kbss.jopa.query.NamedQueryManager;
import cz.cvut.kbss.jopa.query.ResultSetMappingManager;
import cz.cvut.kbss.jopa.sessions.MetamodelProvider;
Expand Down Expand Up @@ -55,6 +56,8 @@ public class MetamodelImpl implements Metamodel, MetamodelProvider {
private TypeReferenceMap typeReferenceMap;

private final Map<Class<?>, Class<?>> lazyLoadingProxyClasses = new ConcurrentHashMap<>();
// Proxy classes for results of EntityManager.getReference
private final Map<Class<?>, Class<?>> referenceProxyClasses = new ConcurrentHashMap<>();

private NamedQueryManager namedQueryManager;
private ResultSetMappingManager resultSetMappingManager;
Expand Down Expand Up @@ -151,10 +154,12 @@ public Set<Class<?>> getInferredClasses() {
return Collections.unmodifiableSet(inferredClasses);
}

@Override
public NamedQueryManager getNamedQueryManager() {
return namedQueryManager;
}

@Override
public ResultSetMappingManager getResultSetMappingManager() {
return resultSetMappingManager;
}
Expand Down Expand Up @@ -222,12 +227,24 @@ public Set<Class<?>> getReferringTypes(Class<?> cls) {
/**
* Gets a {@link cz.cvut.kbss.jopa.proxy.lazy.LazyLoadingProxy} type for the specified class.
*
* @param cls Class to get lazy loading proxy for
* @param cls Class to get lazy loading proxy for, should be an entity class
* @param <X> Type to proxy
* @return Lazy loading proxy class
*/
public <X> Class<? extends X> getLazyLoadingProxy(Class<X> cls) {
assert isEntityType(cls);
return (Class<? extends X>) lazyLoadingProxyClasses.computeIfAbsent(cls, c -> new LazyLoadingEntityProxyGenerator().generate(c));
}

/**
* Gets a {@link cz.cvut.kbss.jopa.proxy.reference.EntityReferenceProxy} type for the specified class.
*
* @param cls Class to get reference proxy for, should be an entity class
* @param <X> Type to proxy
* @return Entity proxy class
*/
public <X> Class<? extends X> getEntityReferenceProxy(Class<X> cls) {
assert isEntityType(cls);
return (Class<? extends X>) referenceProxyClasses.computeIfAbsent(cls, c -> new EntityReferenceProxyGenerator().generate(cls));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package cz.cvut.kbss.jopa.model;

import cz.cvut.kbss.jopa.model.metamodel.Attribute;
import cz.cvut.kbss.jopa.proxy.lazy.LazyLoadingProxy;
import cz.cvut.kbss.jopa.utils.EntityPropertiesUtils;
import cz.cvut.kbss.jopa.utils.JOPALazyUtils;

import java.util.Collection;
import java.util.HashSet;
import java.util.function.Consumer;

public class OneLevelRemoveCascadeExplorer extends OneLevelCascadeExplorer {

private final Consumer<Object> removeOperation;

public OneLevelRemoveCascadeExplorer(Consumer<Object> removeOperation) {
this.removeOperation = removeOperation;
}

@Override
protected void exploreCascaded(Attribute<?, ?> at, Object o) {
Object attVal = EntityPropertiesUtils.getAttributeValue(at, o);
if (attVal == null) {
return;
}
if (JOPALazyUtils.isLazyLoadingProxy(attVal)) {
attVal = ((LazyLoadingProxy<?>) attVal).triggerLazyLoading();
}
if (at.isCollection()) {
for (final Object ox2 : new HashSet<>((Collection<?>) attVal)) {
removeOperation.accept(ox2);
}
} else {
removeOperation.accept(attVal);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
import java.util.stream.Collectors;

/**
* Instances of the type AbstractIdentifiableType represent entity or mapped superclass
* types which can be queried for attributes, subtypes and so on.
* Instances of the type AbstractIdentifiableType represent entity or mapped superclass types which can be queried for
* attributes, subtypes and so on.
*
* @param <X> Entity type being represented by this instance
*/
Expand Down Expand Up @@ -70,8 +70,8 @@ void addDeclaredQueryAttribute(final String name, final AbstractQueryAttribute<X
}

/**
* Set supertypes of this instance, and for all given supertypes add this as their subtype.
* This method should not be called multiple times on one instance.
* Set supertypes of this instance, and for all given supertypes add this as their subtype. This method should not
* be called multiple times on one instance.
*
* @param supertypes Supertypes to set
*/
Expand Down Expand Up @@ -138,9 +138,10 @@ public boolean hasSubtypes() {

/**
* Gets the Java type represented by the metamodel instance that can be instantiated.
*
* <p>
* The purpose of this method is mainly to return the generated subclass of {@link #getJavaType()} that is used for
* instantiation.
*
* @return Instantiable Java type
*/
public Class<? extends X> getInstantiableJavaType() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,9 @@
import cz.cvut.kbss.jopa.model.annotations.InheritanceType;

/**
* Instances of the type IdentifiableEntityType represent entity
* types which can be saved to and read from storage.
* Instances of this type represent entity classes that can be saved to and read from storage.
*
* @param <X> Entity type being represented by this instance
* @param <X> Entity class being represented by this instance
*/
public abstract class IdentifiableEntityType<X> extends AbstractIdentifiableType<X> implements EntityType<X> {

Expand Down Expand Up @@ -69,9 +68,10 @@ public IRI getIRI() {
/**
* Gets inheritance type of this entity type.
* <p>
* If the entity type is a root if an inheritance hierarchy, the type can be defined using the {@link
* cz.cvut.kbss.jopa.model.annotations.Inheritance} annotation. If the entity is deeper in inheritance hierarchy, it
* is inherited from the supertype. Otherwise, it defaults to {@link cz.cvut.kbss.jopa.utils.Constants#DEFAULT_INHERITANCE_TYPE}.
* If the entity type is a root if an inheritance hierarchy, the type can be defined using the
* {@link cz.cvut.kbss.jopa.model.annotations.Inheritance} annotation. If the entity is deeper in inheritance
* hierarchy, it is inherited from the supertype. Otherwise, it defaults to
* {@link cz.cvut.kbss.jopa.utils.Constants#DEFAULT_INHERITANCE_TYPE}.
*
* @return Inheritance strategy for this entity type
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ public RDFCollectionAttributeBuilder<X, V> converter(ConverterWrapper converter)
return this;
}

@Override
public RDFCollectionAttribute<X, V> build() {
return new RDFCollectionAttribute<>(this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,11 @@ private <T> void outputGeneratedClass(DynamicType.Unloaded<? extends T> typeDef)

public static class SetterInterceptor {

public static void set(@This Manageable instance, @Origin Method setter) throws Exception {
private SetterInterceptor() {
throw new AssertionError();
}

public static void set(@This Manageable instance, @Origin Method setter) {
final UnitOfWork pc = instance.getPersistenceContext();
if (pc == null || !pc.isInTransaction()) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,6 @@ <T> T loadEntity(LoadingParameters<T> loadingParameters) {
return loadInstance(loadingParameters, et);
}

@Override
<T> T loadReference(LoadingParameters<T> loadingParameters) {
final IdentifiableEntityType<T> et = metamodel.entity(loadingParameters.getEntityClass());
return loadReferenceInstance(loadingParameters, et);
}

static DefaultInstanceLoaderBuilder builder() {
return new DefaultInstanceLoaderBuilder();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ private <T> void populateQueryAttributes(T instance, EntityType<T> et, LoadState
if (queryAttribute.getFetchType() != FetchType.LAZY) {
populateQueryAttribute(instance, queryAttribute, queryFactory, et);
loadStateDescriptor.setLoaded(queryAttribute, LoadState.LOADED);
} else {
loadStateDescriptor.setLoaded(queryAttribute, LoadState.NOT_LOADED);
}
}
}
Expand Down
Loading

0 comments on commit 5e18493

Please sign in to comment.