Skip to content

Commit

Permalink
IsLoaded implementations.
Browse files Browse the repository at this point in the history
  • Loading branch information
ledsoft committed Nov 14, 2017
1 parent ea52146 commit 4055915
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 58 deletions.
Original file line number Diff line number Diff line change
@@ -1,35 +1,55 @@
/**
* Copyright (C) 2016 Czech Technical University in Prague
*
* This program 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.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details. You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* <p>
* This program 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.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details. You should have received a copy of the GNU General Public License along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
package cz.cvut.kbss.jopa.model;

/**
* Utility interface between the application and the persistence provider managing the persistence unit.
* <p>
* The methods of this interface should only be invoked on entity instances obtained from or managed by entity managers
* for this persistence unit or on new entity instances.
*/
public interface PersistenceUnitUtil {

public boolean isLoaded(Object entity, String attributeName);
/**
* Determine the load state of a given persistent attribute of an entity belonging to the persistence unit.
*
* @param entity entity instance containing the attribute
* @param attributeName name of attribute whose load state is to be determined
* @return false if entity's state has not been loaded or if the attribute state has not been loaded, else true
*/
boolean isLoaded(Object entity, String attributeName);

public boolean isLoaded(Object entity);
/**
* Determine the load state of an entity belonging to the persistence unit.
* <p>
* This method can be used to determine the load state of an entity passed as a reference. An entity is considered
* loaded if all attributes for which {@code FetchType.EAGER} has been specified have been loaded.
* <p>
* The {@link #isLoaded(Object, String)} method should be used to determine the load state of an attribute. Not
* doing so might lead to unintended loading of state.
*
* @param entity entity instance whose load state is to be determined
* @return false if the entity has not been loaded, else true
*/
boolean isLoaded(Object entity);

/**
* Return the id of the entity. A generated id is not guaranteed to be
* available until after the database insert has occurred. Returns null if
* the entity does not yet have an id.
*
* @param entity
* entity instance
* @return id of the entity
* @throws IllegalArgumentException
* if the object is found not to be an entity
*/
public Object getIdentifier(Object entity);
/**
* Return the id of the entity. A generated id is not guaranteed to be available until after the database insert has
* occurred. Returns null if the entity does not yet have an id.
*
* @param entity entity instance
* @return id of the entity
* @throws IllegalArgumentException if the object is found not to be an entity
*/
Object getIdentifier(Object entity);
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
/**
* Copyright (C) 2016 Czech Technical University in Prague
*
* This program 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.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details. You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* <p>
* This program 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.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details. You should have received a copy of the GNU General Public License along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
package cz.cvut.kbss.jopa.model;

Expand All @@ -25,10 +23,7 @@
import cz.cvut.kbss.ontodriver.OntologyStorageProperties;
import cz.cvut.kbss.ontodriver.config.OntoDriverProperties;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class EntityManagerFactoryImpl implements EntityManagerFactory, PersistenceUnitUtil {
Expand Down Expand Up @@ -160,16 +155,18 @@ public void addNamedQuery(String name, Query query) {

@Override
public Object getIdentifier(Object entity) {
Objects.requireNonNull(entity);
final EntityType<?> et = getMetamodel().entity(entity.getClass());
return EntityPropertiesUtils.getFieldValue(et.getIdentifier().getJavaField(), entity);
}

@Override
public boolean isLoaded(Object entity, String attributeName) {
Objects.requireNonNull(entity);
Objects.requireNonNull(attributeName);
for (final AbstractEntityManager emi : em) {
if (emi.contains(entity)) {
return attributeName == null || emi.isLoaded(entity, attributeName);

if (emi.contains(entity) && emi.isLoaded(entity, attributeName)) {
return true;
}
}

Expand All @@ -178,9 +175,14 @@ public boolean isLoaded(Object entity, String attributeName) {

@Override
public boolean isLoaded(Object entity) {
// TODO
Objects.requireNonNull(entity);
// Since we do not support getReference yet, all EAGER attributes are always loaded for managed instances
for (AbstractEntityManager emi : em) {
if (emi.contains(entity)) {
return true;
}
}
return false;
// return isLoaded(entity);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
/**
* Copyright (C) 2016 Czech Technical University in Prague
*
* This program 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.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details. You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* <p>
* This program 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.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details. You should have received a copy of the GNU General Public License along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
package cz.cvut.kbss.jopa.model;

import cz.cvut.kbss.jopa.exceptions.OWLPersistenceException;
import cz.cvut.kbss.jopa.exceptions.TransactionRequiredException;
import cz.cvut.kbss.jopa.model.annotations.CascadeType;
import cz.cvut.kbss.jopa.model.annotations.FetchType;
import cz.cvut.kbss.jopa.model.descriptors.Descriptor;
import cz.cvut.kbss.jopa.model.descriptors.EntityDescriptor;
import cz.cvut.kbss.jopa.model.metamodel.Attribute;
import cz.cvut.kbss.jopa.model.metamodel.FieldSpecification;
import cz.cvut.kbss.jopa.model.metamodel.Metamodel;
import cz.cvut.kbss.jopa.model.query.Query;
import cz.cvut.kbss.jopa.model.query.TypedQuery;
Expand Down Expand Up @@ -409,8 +409,17 @@ public Metamodel getMetamodel() {

@Override
public boolean isLoaded(final Object object, final String attributeName) {
// TODO
return false;
Objects.requireNonNull(object);
Objects.requireNonNull(attributeName);
if (!contains(object)) {
return false;
}
final FieldSpecification<?, ?> fieldSpec = getMetamodel().entity(object.getClass())
.getFieldSpecification(attributeName);
// This is not correct, as lazily loaded fields can be set to null, but as long as we do not have any representation
// of the loaded state of an entity, this will have to do
return fieldSpec.getFetchType() == FetchType.EAGER ||
EntityPropertiesUtils.getFieldValue(fieldSpec.getJavaField(), object) != null;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public static void initOWLClassAMocks(EntityTypeImpl<OWLClassA> etMock, Attribut
when(strAttMock.getPersistentAttributeType()).thenReturn(Attribute.PersistentAttributeType.DATA);
when(strAttMock.getConstraints()).thenReturn(new ParticipationConstraint[]{});
when(strAttMock.getCascadeTypes()).thenReturn(new CascadeType[0]);
when(strAttMock.getFetchType()).thenReturn(FetchType.EAGER);
when(typesMock.getJavaField()).thenReturn(OWLClassA.getTypesField());
when(typesMock.getName()).thenReturn(OWLClassA.getTypesField().getName());
when(typesMock.getDeclaringType()).thenReturn(etMock);
Expand Down Expand Up @@ -387,6 +388,9 @@ public static void initOWLClassKMocks(EntityTypeImpl<OWLClassK> etMock, Attribut
when(clsEMock.getIRI()).thenReturn(IRI.create(clsEIri));
when(clsEMock.getJavaType()).thenReturn(OWLClassE.class);
when(clsEMock.getDeclaringType()).thenReturn(etMock);
when(clsEMock.getFetchType()).thenReturn(FetchType.LAZY);
when(clsEMock.getName()).thenReturn(OWLClassK.getOwlClassEField().getName());
when(etMock.getFieldSpecification(clsEMock.getName())).thenReturn(clsEMock);
when(etMock.getIdentifier()).thenReturn(idMock);
when(idMock.getJavaField()).thenReturn(OWLClassK.class.getDeclaredField("uri"));
when(etMock.getLifecycleListenerManager()).thenReturn(EntityLifecycleListenerManager.empty());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package cz.cvut.kbss.jopa.model;

import cz.cvut.kbss.jopa.environment.OWLClassA;
import cz.cvut.kbss.jopa.environment.utils.DataSourceStub;
import cz.cvut.kbss.jopa.environment.utils.Generators;
import cz.cvut.kbss.ontodriver.Connection;
import cz.cvut.kbss.ontodriver.Types;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.util.HashMap;
import java.util.Map;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class EntityManagerFactoryImplTest {

private EntityManagerFactoryImpl emf;

@Mock
private Connection connection;

@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
final Map<String, String> props = new HashMap<>();
props.put(JOPAPersistenceProperties.DATA_SOURCE_CLASS, DataSourceStub.class.getName());
props.put(JOPAPersistenceProperties.ONTOLOGY_PHYSICAL_URI_KEY,
Generators.createIndividualIdentifier().toString());
props.put(JOPAPersistenceProperties.SCAN_PACKAGE, "cz.cvut.kbss.jopa.environment");
this.emf = new EntityManagerFactoryImpl(props);
emf.createEntityManager();
emf.getServerSession().unwrap(DataSourceStub.class).setConnection(connection);
when(connection.types()).thenReturn(mock(Types.class));
}

@Test
public void isLoadedReturnsTrueForManagedInstance() {
final EntityManager em = emf.createEntityManager();
try {
final OWLClassA a = Generators.generateOwlClassAInstance();
em.persist(a);
assertTrue(emf.isLoaded(a));
} finally {
em.close();
}
}

@Test
public void isLoadedReturnsTrueForAttributeOfManagedInstance() throws Exception {
final EntityManager em = emf.createEntityManager();
try {
final OWLClassA a = Generators.generateOwlClassAInstance();
em.persist(a);
assertTrue(emf.isLoaded(a, OWLClassA.getStrAttField().getName()));
} finally {
em.close();
}
}

@Test
public void isLoadedReturnsFalseNonNonManagedInstance() {
final EntityManager emOne = emf.createEntityManager();
final EntityManager emTwo = emf.createEntityManager();
try {
assertFalse(emf.isLoaded(Generators.generateOwlClassAInstance()));
} finally {
emOne.close();
emTwo.close();
}
}

@Test
public void isLoadedReturnsFalseNonNonManagedInstanceWithAttribute() throws Exception {
final EntityManager emOne = emf.createEntityManager();
final EntityManager emTwo = emf.createEntityManager();
try {
assertFalse(emf.isLoaded(Generators.generateOwlClassAInstance(), OWLClassA.getStrAttField().getName()));
} finally {
emOne.close();
emTwo.close();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -481,4 +481,31 @@ public void removeIsAbleToBreakCascadingCycle() throws Exception {
verify(uow).removeObject(cloneOne);
verify(uow).removeObject(cloneTwo);
}

@Test
public void isLoadedReturnsTrueForEagerlyLoadedAttributeOfManagedInstance() throws Exception {
final OWLClassA a = Generators.generateOwlClassAInstance();
doAnswer((invocationOnMock) -> a).when(uow).readObject(eq(OWLClassA.class), eq(a.getUri()), any(Descriptor.class));
when(uow.contains(a)).thenReturn(true);
final OWLClassA found = em.find(OWLClassA.class, a.getUri());
assertTrue(em.isLoaded(found, OWLClassA.getStrAttField().getName()));
}

@Test
public void isLoadedReturnsFalseForNonManagedInstance() throws Exception {
final OWLClassA a = Generators.generateOwlClassAInstance();
when(uow.contains(a)).thenReturn(false);
assertFalse(em.isLoaded(a, OWLClassA.getStrAttField().getName()));
}

@Test
public void isLoadedReturnsTrueForNonNullLazilyLoadedAttribute() throws Exception {
final OWLClassK inst = new OWLClassK();
inst.setUri(Generators.createIndividualIdentifier());
inst.setOwlClassE(new OWLClassE());
when(uow.contains(inst)).thenReturn(true);
doAnswer((invocationOnMock) -> inst).when(uow).readObject(eq(OWLClassK.class), eq(inst.getUri()), any(Descriptor.class));
final OWLClassK found = em.find(OWLClassK.class, inst.getUri());
assertTrue(em.isLoaded(found, OWLClassK.getOwlClassEField().getName()));
}
}

0 comments on commit 4055915

Please sign in to comment.