-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Enhancement #69] Replace pending references with empty object (with …
…id) when ASSUME_TARGET_TYPE is configured.
- Loading branch information
Showing
8 changed files
with
196 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
71 changes: 71 additions & 0 deletions
71
...main/java/cz/cvut/kbss/jsonld/deserialization/reference/AssumedTypeReferenceReplacer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package cz.cvut.kbss.jsonld.deserialization.reference; | ||
|
||
import cz.cvut.kbss.jsonld.JsonLd; | ||
import cz.cvut.kbss.jsonld.common.BeanAnnotationProcessor; | ||
import cz.cvut.kbss.jsonld.common.BeanClassProcessor; | ||
import cz.cvut.kbss.jsonld.deserialization.util.DataTypeTransformer; | ||
import cz.cvut.kbss.jsonld.exception.UnknownPropertyException; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.lang.reflect.Field; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.Objects; | ||
import java.util.Optional; | ||
|
||
/** | ||
* Replaces pending references with objects of assumed target type. | ||
* <p> | ||
* These objects have only identifier value set. | ||
*/ | ||
public class AssumedTypeReferenceReplacer { | ||
|
||
private static final Logger LOG = LoggerFactory.getLogger(AssumedTypeReferenceReplacer.class); | ||
|
||
/** | ||
* Replaces pending references from the specified {@link PendingReferenceRegistry} with empty objects of the assumed | ||
* target type. | ||
* <p> | ||
* The objects will have only the identifiers set. | ||
* <p> | ||
* If unable to determine target type (typically for pending collection item references), the pending reference is | ||
* skipped. | ||
* | ||
* @param registry Registry from which the pending references should be replaced | ||
*/ | ||
public void replacePendingReferencesWithAssumedTypedObjects(PendingReferenceRegistry registry) { | ||
Objects.requireNonNull(registry); | ||
final Map<String, Class<?>> idsToTypes = getAssumedTargetTypes(registry); | ||
idsToTypes.forEach((id, type) -> { | ||
final Object instance = BeanClassProcessor.createInstance(type); | ||
final Optional<Field> idField = BeanAnnotationProcessor.getIdentifierField(type); | ||
if (idField.isEmpty()) { | ||
throw UnknownPropertyException.create(JsonLd.ID, type); | ||
} | ||
Object identifier = id; | ||
if (!idField.get().getType().isAssignableFrom(String.class)) { | ||
identifier = DataTypeTransformer.transformValue(id, idField.get().getType()); | ||
} | ||
BeanClassProcessor.setFieldValue(idField.get(), instance, identifier); | ||
registry.resolveReferences(id, instance); | ||
}); | ||
} | ||
|
||
private static Map<String, Class<?>> getAssumedTargetTypes(PendingReferenceRegistry registry) { | ||
final Map<String, Class<?>> idsToTypes = new HashMap<>(); | ||
registry.getPendingReferences().forEach((id, refs) -> { | ||
assert refs != null; | ||
assert !refs.isEmpty(); | ||
final Optional<Class<?>> targetType = | ||
refs.stream().filter(ref -> ref.getTargetType().isPresent()).findFirst().flatMap( | ||
PendingReference::getTargetType); | ||
if (targetType.isEmpty()) { | ||
LOG.debug("No assumed target type found for reference with id '{}'. Skipping the reference.", id); | ||
} else { | ||
idsToTypes.put(id, targetType.get()); | ||
} | ||
}); | ||
return idsToTypes; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
67 changes: 67 additions & 0 deletions
67
.../java/cz/cvut/kbss/jsonld/deserialization/reference/AssumedTypeReferenceReplacerTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package cz.cvut.kbss.jsonld.deserialization.reference; | ||
|
||
import cz.cvut.kbss.jsonld.environment.Generator; | ||
import cz.cvut.kbss.jsonld.environment.model.Employee; | ||
import cz.cvut.kbss.jsonld.environment.model.User; | ||
import cz.cvut.kbss.jsonld.exception.UnknownPropertyException; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import java.net.URI; | ||
import java.util.ArrayList; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
import static org.junit.jupiter.api.Assertions.assertFalse; | ||
import static org.junit.jupiter.api.Assertions.assertNotNull; | ||
import static org.junit.jupiter.api.Assertions.assertSame; | ||
import static org.junit.jupiter.api.Assertions.assertThrows; | ||
|
||
class AssumedTypeReferenceReplacerTest { | ||
|
||
private final PendingReferenceRegistry registry = new PendingReferenceRegistry(); | ||
|
||
private final AssumedTypeReferenceReplacer sut = new AssumedTypeReferenceReplacer(); | ||
|
||
@Test | ||
void replacePendingReferencesWithAssumedTypedObjectsReplacesPendingSingularReferenceWithObjectWithId() throws Exception { | ||
final URI id = Generator.generateUri(); | ||
final Employee target = Generator.generateEmployee(); | ||
target.setEmployer(null); | ||
registry.addPendingReference(id.toString(), target, Employee.getEmployerField()); | ||
sut.replacePendingReferencesWithAssumedTypedObjects(registry); | ||
assertNotNull(target.getEmployer()); | ||
assertEquals(id, target.getEmployer().getUri()); | ||
} | ||
|
||
@Test | ||
void replacePendingReferenceReplacesAllReferencesWithSameObject() throws Exception { | ||
final URI id = Generator.generateUri(); | ||
final Employee targetOne = Generator.generateEmployee(); | ||
targetOne.setEmployer(null); | ||
registry.addPendingReference(id.toString(), targetOne, Employee.getEmployerField()); | ||
final Employee targetTwo = Generator.generateEmployee(); | ||
targetTwo.setEmployer(null); | ||
registry.addPendingReference(id.toString(), targetTwo, Employee.getEmployerField()); | ||
sut.replacePendingReferencesWithAssumedTypedObjects(registry); | ||
assertNotNull(targetOne.getEmployer()); | ||
assertEquals(id, targetOne.getEmployer().getUri()); | ||
assertNotNull(targetTwo.getEmployer()); | ||
assertSame(targetOne.getEmployer(), targetTwo.getEmployer()); | ||
} | ||
|
||
@Test | ||
void replacePendingReferencesThrowsUnknownPropertyExceptionWhenTargetTypeDoesNotHaveIdentifierField() throws Exception { | ||
final URI id = Generator.generateUri(); | ||
final Employee target = Generator.generateEmployee(); | ||
registry.addPendingReference(id.toString(), target, User.getUsernameField()); | ||
assertThrows(UnknownPropertyException.class, () -> sut.replacePendingReferencesWithAssumedTypedObjects(registry)); | ||
} | ||
|
||
@Test | ||
void replacePendingReferencesSkipsPendingReferencesWithoutClearTargetType() { | ||
final URI id = Generator.generateUri(); | ||
registry.addPendingReference(id.toString(), new ArrayList<>()); | ||
|
||
sut.replacePendingReferencesWithAssumedTypedObjects(registry); | ||
assertFalse(registry.getPendingReferences().isEmpty()); | ||
} | ||
} |