Skip to content

Commit

Permalink
Merge pull request #597 from FgForrest/596-referenced-entity-bodies-a…
Browse files Browse the repository at this point in the history
…re-not-returned-for-hierarchically-fetched-parents

fix(#596): Referenced entity bodies are not returned for hierarchically fetched parents
  • Loading branch information
novoj authored Jun 3, 2024
2 parents c8a9e22 + 50ac08f commit b710305
Show file tree
Hide file tree
Showing 4 changed files with 182 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -694,8 +694,7 @@ private static SealedEntity replaceWithSealedEntities(
.orElse(EntityClassifierWithParent.CONCEALED_ENTITY);

return ServerEntityDecorator.decorate(
entityDecorator.getDelegate(),
entityDecorator.getSchema(),
entityDecorator,
enrichedParentEntity,
entityDecorator.getLocalePredicate(),
new HierarchySerializablePredicate(true),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,34 @@ public static ServerEntityDecorator decorate(
);
}

/**
* Method allows creating the entityDecorator object with up-to-date schema definition. Data of the entity are kept
* untouched.
*/
@Nonnull
public static ServerEntityDecorator decorate(
@Nonnull ServerEntityDecorator entity,
@Nullable EntityClassifierWithParent parentEntity,
@Nonnull LocaleSerializablePredicate localePredicate,
@Nonnull HierarchySerializablePredicate hierarchyPredicate,
@Nonnull AttributeValueSerializablePredicate attributePredicate,
@Nonnull AssociatedDataValueSerializablePredicate associatedDataValuePredicate,
@Nonnull ReferenceContractSerializablePredicate referencePredicate,
@Nonnull PriceContractSerializablePredicate pricePredicate,
@Nonnull OffsetDateTime alignedNow,
int ioFetchCount,
int ioFetchedBytes
) {
return new ServerEntityDecorator(
entity, parentEntity,
localePredicate, hierarchyPredicate,
attributePredicate, associatedDataValuePredicate,
referencePredicate, pricePredicate,
alignedNow,
ioFetchCount, ioFetchedBytes
);
}

/**
* Method allows to create copy of the entity object with up-to-date schema definition. Data of the original
* entity are kept untouched.
Expand Down Expand Up @@ -165,24 +193,26 @@ public ServerEntityDecorator(
}

public ServerEntityDecorator(
@Nonnull ServerEntityDecorator decorator,
@Nonnull ServerEntityDecorator delegate,
@Nullable EntityClassifierWithParent parentEntity,
@Nonnull LocaleSerializablePredicate localePredicate,
@Nonnull HierarchySerializablePredicate hierarchyPredicate,
@Nonnull AttributeValueSerializablePredicate attributePredicate,
@Nonnull AssociatedDataValueSerializablePredicate associatedDataPredicate,
@Nonnull ReferenceContractSerializablePredicate referencePredicate,
@Nonnull PriceContractSerializablePredicate pricePredicate,
@Nonnull OffsetDateTime alignedNow
@Nonnull OffsetDateTime alignedNow,
int ioFetchCount,
int ioFetchedBytes
) {
super(
decorator, parentEntity,
delegate, parentEntity,
localePredicate, hierarchyPredicate, attributePredicate, associatedDataPredicate,
referencePredicate, pricePredicate,
alignedNow
);
this.ioFetchCount = decorator.getIoFetchCount();
this.ioFetchedBytes = decorator.getIoFetchedBytes();
this.ioFetchCount = ioFetchCount;
this.ioFetchedBytes = ioFetchedBytes;
}

public ServerEntityDecorator(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* | __/\ V /| | || (_| | |_| | |_) |
* \___| \_/ |_|\__\__,_|____/|____/
*
* Copyright (c) 2023
* Copyright (c) 2023-2024
*
* Licensed under the Business Source License, Version 1.1 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -72,11 +72,20 @@ DataCarrier setUp(Evita evita) {
return primaryKey == 0 ? null : primaryKey;
};

dataGenerator.generateEntities(
dataGenerator.getSamplePriceListSchema(session),
randomEntityPicker,
SEED
)
.limit(4)
.forEach(session::upsertEntity);

final List<EntityReference> storedCategories = dataGenerator.generateEntities(
dataGenerator.getSampleCategorySchema(
session,
builder -> {
builder
.withReferenceToEntity(Entities.PRICE_LIST, Entities.PRICE_LIST, Cardinality.ZERO_OR_ONE)
/* here we define set of associated data, that can be stored along with entity */
.withAssociatedData(ASSOCIATED_DATA_REFERENCED_FILES, ReferencedFileSet.class)
.withAssociatedData(ASSOCIATED_DATA_LABELS, Labels.class)
Expand All @@ -91,14 +100,6 @@ DataCarrier setUp(Evita evita) {
.map(session::upsertEntity)
.toList();

dataGenerator.generateEntities(
dataGenerator.getSamplePriceListSchema(session),
randomEntityPicker,
SEED
)
.limit(4)
.forEach(session::upsertEntity);

final List<EntityReference> storedStores = dataGenerator.generateEntities(
dataGenerator.getSampleStoreSchema(
session,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* | __/\ V /| | || (_| | |_| | |_) |
* \___| \_/ |_|\__\__,_|____/|____/
*
* Copyright (c) 2023
* Copyright (c) 2023-2024
*
* Licensed under the Business Source License, Version 1.1 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -3248,6 +3248,66 @@ void shouldReturnDirectHierarchyParentsUpToLevelTwo(Evita evita, Hierarchy categ
);
}

@DisplayName("Should return hierarchy parent entity references with bodies stopping at level two")
@UseDataSet(HUNDRED_PRODUCTS)
@Test
void shouldReturnDirectHierarchyParentsWithBodiesUpToLevelTwo(Evita evita, Hierarchy categoryHierarchy) {
evita.queryCatalog(
TEST_CATALOG,
session -> {
final HierarchyItem theChild = categoryHierarchy.getRootItems()
.stream()
.flatMap(it -> categoryHierarchy.getAllChildItems(it.getCode()).stream())
.max(Comparator.comparingInt(HierarchyItem::getLevel))
.orElseThrow();
final int theChildPk = Integer.parseInt(theChild.getCode());
final int theParentPk = Integer.parseInt(categoryHierarchy.getParentItem(theChild.getCode()).getCode());

final EvitaResponse<SealedEntity> categoryByPk = session.querySealedEntity(
query(
collection(Entities.CATEGORY),
filterBy(
entityPrimaryKeyInSet(theChildPk)
),
require(
entityFetch(
hierarchyContent(
stopAt(level(2)),
entityFetch(
attributeContentAll(),
referenceContent(Entities.PRICE_LIST, entityFetchAll())
)
)
)
)
)
);
assertEquals(1, categoryByPk.getRecordData().size());
assertEquals(1, categoryByPk.getTotalRecordCount());

final SealedEntity returnedEntity = categoryByPk.getRecordData().get(0);
assertEquals(theParentPk, returnedEntity.getParentEntity().orElseThrow().getPrimaryKey());

boolean atLeastOnPriceListFound = false;
Optional<EntityClassifierWithParent> parentEntityRef = returnedEntity.getParentEntity();
while (parentEntityRef.isPresent()) {
final EntityClassifierWithParent parentEntity = parentEntityRef.get();
assertInstanceOf(SealedEntity.class, parentEntity);
final Collection<ReferenceContract> references = ((SealedEntity) parentEntity).getReferences(Entities.PRICE_LIST);
if (!references.isEmpty()) {
atLeastOnPriceListFound = true;
assertEquals(1, references.size());
assertTrue(references.iterator().next().getReferencedEntity().isPresent());
parentEntityRef = parentEntity.getParentEntity();
}
}
assertTrue(atLeastOnPriceListFound, "At least one price list should be found in the hierarchy");

return null;
}
);
}

@DisplayName("Should return hierarchy parent entity references stopping at distance one")
@UseDataSet(HUNDRED_PRODUCTS)
@Test
Expand Down Expand Up @@ -3876,6 +3936,81 @@ void shouldReturnProductHierarchyParentEntitiesUpToLevelTwo(Evita evita, Hierarc
);
}

@DisplayName("Should return product hierarchy parent sealed entities stopping at level two")
@UseDataSet(HUNDRED_PRODUCTS)
@Test
void shouldReturnProductHierarchyParentEntitiesWithBodiesUpToLevelTwo(Evita evita, Hierarchy categoryHierarchy, Map<Integer, SealedEntity> originalCategories) {
evita.queryCatalog(
TEST_CATALOG,
session -> {
final HierarchyItem theChild = categoryHierarchy.getRootItems()
.stream()
.flatMap(it -> categoryHierarchy.getAllChildItems(it.getCode()).stream())
.max(Comparator.comparingInt(HierarchyItem::getLevel))
.orElseThrow();
final int theChildPk = Integer.parseInt(theChild.getCode());
final int theParentPk = Integer.parseInt(categoryHierarchy.getParentItem(theChild.getCode()).getCode());

final EvitaResponse<SealedEntity> products = session.querySealedEntity(
query(
collection(Entities.PRODUCT),
filterBy(
hierarchyWithin(Entities.CATEGORY, entityPrimaryKeyInSet(theChildPk))
),
require(
entityFetch(
referenceContent(
Entities.CATEGORY,
entityFetch(
hierarchyContent(
stopAt(level(2)),
entityFetch(
attributeContentAll(),
referenceContent(Entities.PRICE_LIST, entityFetchAll())
)
)
)
)
)
)
)
);
assertFalse(products.getRecordData().isEmpty());
assertTrue(products.getTotalRecordCount() > 0);

final ReferenceContract categoryReference = products.getRecordData().get(0).getReference(Entities.CATEGORY, theChildPk).orElseThrow();
final SealedEntity referencedCategory = categoryReference.getReferencedEntity().orElseThrow();
assertEquals(theParentPk, referencedCategory.getParentEntity().orElseThrow().getPrimaryKey());

boolean atLeastOnPriceListFound = false;
for (SealedEntity returnedEntity : products.getRecordData()) {
final Collection<ReferenceContract> referencedCategories = returnedEntity.getReferences(Entities.CATEGORY);
for (ReferenceContract category : referencedCategories) {
final Optional<SealedEntity> referencedEntity = category.getReferencedEntity();
if (referencedEntity.isPresent()) {
Optional<EntityClassifierWithParent> parentEntityRef = referencedEntity.get().getParentEntity();
while (parentEntityRef.isPresent()) {
final EntityClassifierWithParent parentEntity = parentEntityRef.get();
assertInstanceOf(SealedEntity.class, parentEntity);
final Collection<ReferenceContract> references = ((SealedEntity) parentEntity).getReferences(Entities.PRICE_LIST);
if (!references.isEmpty()) {
atLeastOnPriceListFound = true;
assertEquals(1, references.size());
assertTrue(references.iterator().next().getReferencedEntity().isPresent());
parentEntityRef = parentEntity.getParentEntity();
}
}
}

}
}

assertTrue(atLeastOnPriceListFound, "At least one price list should be found in the hierarchy");
return null;
}
);
}

@DisplayName("Should return product hierarchy parent sealed entities stopping at distance one")
@UseDataSet(HUNDRED_PRODUCTS)
@Test
Expand Down

0 comments on commit b710305

Please sign in to comment.