From 117e4bd8ae01721f10a5818b41c0fe00c4f9d5a8 Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Tue, 7 Dec 2021 09:24:19 +0100 Subject: [PATCH] [#1393] Use TupleTransformer for SUBSELECT and MULTISET fetching to allow streaming --- .../CollectionInstantiatorAccumulator.java | 2 +- .../ViewTypeObjectBuilderTemplate.java | 48 +-- .../mapper/TupleElementMapperBuilder.java | 4 +- ...ctionMultisetTupleTransformerFactory.java} | 17 +- .../MultisetTupleListTransformer.java | 183 --------- .../transformer/MultisetTupleTransformer.java | 111 +++++ .../SingularMultisetTupleListTransformer.java | 147 ------- .../SingularMultisetTupleTransformer.java | 87 ++++ ...gularMultisetTupleTransformerFactory.java} | 15 +- ...tCorrelatedSubselectTupleTransformer.java} | 382 +++++++++++------- ...atedSubselectTupleTransformerFactory.java} | 16 +- ...dCollectionSubselectTupleTransformer.java} | 10 +- ...tionSubselectTupleTransformerFactory.java} | 14 +- ...rrelatedMapSubselectTupleTransformer.java} | 10 +- ...dMapSubselectTupleTransformerFactory.java} | 16 +- ...tedSingularSubselectTupleTransformer.java} | 21 +- ...ularSubselectTupleTransformerFactory.java} | 14 +- .../correlation/AbstractCorrelationTest.java | 78 ++-- 18 files changed, 555 insertions(+), 620 deletions(-) rename entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/{CollectionMultisetTupleListTransformerFactory.java => CollectionMultisetTupleTransformerFactory.java} (80%) delete mode 100644 entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/MultisetTupleListTransformer.java create mode 100644 entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/MultisetTupleTransformer.java delete mode 100644 entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/SingularMultisetTupleListTransformer.java create mode 100644 entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/SingularMultisetTupleTransformer.java rename entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/{SingularMultisetTupleListTransformerFactory.java => SingularMultisetTupleTransformerFactory.java} (81%) rename entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/{AbstractCorrelatedSubselectTupleListTransformer.java => AbstractCorrelatedSubselectTupleTransformer.java} (55%) rename entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/{AbstractCorrelatedSubselectTupleListTransformerFactory.java => AbstractCorrelatedSubselectTupleTransformerFactory.java} (75%) rename entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/{CorrelatedCollectionSubselectTupleListTransformer.java => CorrelatedCollectionSubselectTupleTransformer.java} (63%) rename entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/{CorrelatedCollectionSubselectTupleListTransformerFactory.java => CorrelatedCollectionSubselectTupleTransformerFactory.java} (64%) rename entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/{CorrelatedMapSubselectTupleListTransformer.java => CorrelatedMapSubselectTupleTransformer.java} (63%) rename entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/{CorrelatedMapSubselectTupleListTransformerFactory.java => CorrelatedMapSubselectTupleTransformerFactory.java} (60%) rename entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/{CorrelatedSingularSubselectTupleListTransformer.java => CorrelatedSingularSubselectTupleTransformer.java} (51%) rename entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/{CorrelatedSingularSubselectTupleListTransformerFactory.java => CorrelatedSingularSubselectTupleTransformerFactory.java} (57%) diff --git a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/CollectionInstantiatorAccumulator.java b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/CollectionInstantiatorAccumulator.java index 66f32ce94d..e3c4d798a3 100644 --- a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/CollectionInstantiatorAccumulator.java +++ b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/CollectionInstantiatorAccumulator.java @@ -147,7 +147,7 @@ public void addAll(Collection container, Collection collection, boolean re } for (int i = listEnd; i < other.size(); i++) { Object valueContainer = valueAccumulator.createContainer(false, 1); - valueAccumulator.add(valueContainer, null, other.get(i), false); + valueAccumulator.addAll(valueContainer, other.get(i), false); list.add(i, valueContainer); } } diff --git a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/ViewTypeObjectBuilderTemplate.java b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/ViewTypeObjectBuilderTemplate.java index de306ca1c2..c79df4385a 100644 --- a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/ViewTypeObjectBuilderTemplate.java +++ b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/ViewTypeObjectBuilderTemplate.java @@ -65,18 +65,18 @@ import com.blazebit.persistence.view.impl.objectbuilder.mapper.TupleParameterMapper; import com.blazebit.persistence.view.impl.objectbuilder.mapper.TypeUtils; import com.blazebit.persistence.view.impl.objectbuilder.transformator.TupleTransformatorFactory; -import com.blazebit.persistence.view.impl.objectbuilder.transformer.CollectionMultisetTupleListTransformerFactory; +import com.blazebit.persistence.view.impl.objectbuilder.transformer.CollectionMultisetTupleTransformerFactory; import com.blazebit.persistence.view.impl.objectbuilder.transformer.IndexedTupleListTransformer; import com.blazebit.persistence.view.impl.objectbuilder.transformer.NonIndexedTupleListTransformer; -import com.blazebit.persistence.view.impl.objectbuilder.transformer.SingularMultisetTupleListTransformerFactory; +import com.blazebit.persistence.view.impl.objectbuilder.transformer.SingularMultisetTupleTransformerFactory; import com.blazebit.persistence.view.impl.objectbuilder.transformer.SubviewTupleTransformerFactory; import com.blazebit.persistence.view.impl.objectbuilder.transformer.correlation.BasicCorrelator; import com.blazebit.persistence.view.impl.objectbuilder.transformer.correlation.CorrelatedCollectionBatchTupleListTransformerFactory; -import com.blazebit.persistence.view.impl.objectbuilder.transformer.correlation.CorrelatedCollectionSubselectTupleListTransformerFactory; +import com.blazebit.persistence.view.impl.objectbuilder.transformer.correlation.CorrelatedCollectionSubselectTupleTransformerFactory; import com.blazebit.persistence.view.impl.objectbuilder.transformer.correlation.CorrelatedMapBatchTupleListTransformerFactory; -import com.blazebit.persistence.view.impl.objectbuilder.transformer.correlation.CorrelatedMapSubselectTupleListTransformerFactory; +import com.blazebit.persistence.view.impl.objectbuilder.transformer.correlation.CorrelatedMapSubselectTupleTransformerFactory; import com.blazebit.persistence.view.impl.objectbuilder.transformer.correlation.CorrelatedSingularBatchTupleListTransformerFactory; -import com.blazebit.persistence.view.impl.objectbuilder.transformer.correlation.CorrelatedSingularSubselectTupleListTransformerFactory; +import com.blazebit.persistence.view.impl.objectbuilder.transformer.correlation.CorrelatedSingularSubselectTupleTransformerFactory; import com.blazebit.persistence.view.impl.objectbuilder.transformer.correlation.CorrelatedSubviewJoinTupleTransformerFactory; import com.blazebit.persistence.view.impl.objectbuilder.transformer.correlation.Correlator; import com.blazebit.persistence.view.impl.objectbuilder.transformer.correlation.SubviewCorrelator; @@ -496,7 +496,7 @@ private void applyMapping(AbstractAttribute attribute, String parentAttrib } else if (listKey) { indexBasicTypeSupport = IntegerBasicUserType.INSTANCE; } - mapperBuilder.setTupleListTransformerFactory(new CollectionMultisetTupleListTransformerFactory(startIndex, null, attributePath, getMultisetResultAlias(attributePath), valueConverter, attribute.getContainerAccumulator(), dirtyTracking, + mapperBuilder.addTupleTransformerFactory(new CollectionMultisetTupleTransformerFactory(startIndex, null, attributePath, getMultisetResultAlias(attributePath), valueConverter, attribute.getContainerAccumulator(), dirtyTracking, subviewTemplate, indexTemplate, managedViewType.hasSelectOrSubselectFetchedAttributes(), new SubviewTupleTransformerFactory(attributePath, subviewTemplate, updatableObjectCache, nullIfEmpty), indexTransformerFactory, null, indexBasicTypeSupport)); } else { applyCorrelatedSubviewMapping(attribute, attributePath, newTupleIdDescriptor, (ManagedViewTypeImplementor) (ManagedViewTypeImplementor) managedViewType, mapperBuilder, features, viewJpqlMacro, embeddingViewJpqlMacro, ef, batchSize, dirtyTracking); @@ -521,7 +521,7 @@ private void applyMapping(AbstractAttribute attribute, String parentAttrib } else if (listKey) { indexBasicTypeSupport = IntegerBasicUserType.INSTANCE; } - mapperBuilder.setTupleListTransformerFactory(new CollectionMultisetTupleListTransformerFactory(startIndex, mapping, attributePath, getMultisetResultAlias(attributePath), valueConverter, attribute.getContainerAccumulator(), dirtyTracking, + mapperBuilder.addTupleTransformerFactory(new CollectionMultisetTupleTransformerFactory(startIndex, mapping, attributePath, getMultisetResultAlias(attributePath), valueConverter, attribute.getContainerAccumulator(), dirtyTracking, subviewTemplate, indexTemplate, managedViewType.hasSelectOrSubselectFetchedAttributes(), new SubviewTupleTransformerFactory(attributePath, subviewTemplate, updatableObjectCache, nullIfEmpty), indexTransformerFactory, null, indexBasicTypeSupport)); } else { // Obviously, we produce null if the object type is identifiable i.e. a ViewType and it is empty = null id @@ -547,10 +547,10 @@ private void applyMapping(AbstractAttribute attribute, String parentAttrib if (pluralAttribute.isSorted()) { throw new IllegalArgumentException("The list attribute '" + pluralAttribute + "' can not be sorted!"); } else { - mapperBuilder.setTupleListTransformer(new IndexedTupleListTransformer(tupleIdDescriptor.createIdPositions(), startIndex, valueStartIndex, attribute.getContainerAccumulator(), dirtyTracking, null, valueConverter)); + mapperBuilder.addTupleListTransformer(new IndexedTupleListTransformer(tupleIdDescriptor.createIdPositions(), startIndex, valueStartIndex, attribute.getContainerAccumulator(), dirtyTracking, null, valueConverter)); } } else if (mapKey) { - mapperBuilder.setTupleListTransformer(new IndexedTupleListTransformer(tupleIdDescriptor.createIdPositions(), startIndex, valueStartIndex, attribute.getContainerAccumulator(), dirtyTracking, keyConverter, valueConverter)); + mapperBuilder.addTupleListTransformer(new IndexedTupleListTransformer(tupleIdDescriptor.createIdPositions(), startIndex, valueStartIndex, attribute.getContainerAccumulator(), dirtyTracking, keyConverter, valueConverter)); } else { switch (pluralAttribute.getCollectionType()) { case COLLECTION: @@ -570,7 +570,7 @@ private void applyMapping(AbstractAttribute attribute, String parentAttrib default: throw new IllegalArgumentException("Unknown collection type: " + pluralAttribute.getCollectionType()); } - mapperBuilder.setTupleListTransformer(new NonIndexedTupleListTransformer(tupleIdDescriptor.createIdPositions(), startIndex, attribute.getCollectionInstantiator(), dirtyTracking, valueConverter)); + mapperBuilder.addTupleListTransformer(new NonIndexedTupleListTransformer(tupleIdDescriptor.createIdPositions(), startIndex, attribute.getCollectionInstantiator(), dirtyTracking, valueConverter)); } } } else if (attribute.isQueryParameter()) { @@ -587,7 +587,7 @@ private void applyMapping(AbstractAttribute attribute, String parentAttrib boolean updatableObjectCache = managedViewType.isUpdatable() || managedViewType.isCreatable(); ViewTypeObjectBuilderTemplate subviewTemplate = applyCorrelatedSubviewMapping(attribute, attributePath, tupleIdDescriptor, (ManagedViewTypeImplementor) (ManagedViewTypeImplementor) managedViewType, mapperBuilder, features, viewJpqlMacro, embeddingViewJpqlMacro, ef, batchSize, false)[0]; TypeConverter elementConverter = (TypeConverter) (TypeConverter) managedViewType.getConverter(); - mapperBuilder.setTupleListTransformerFactory(new SingularMultisetTupleListTransformerFactory(startIndex, null, attributePath, getMultisetResultAlias(attributePath), elementConverter, subviewTemplate, managedViewType.hasSelectOrSubselectFetchedAttributes(), new SubviewTupleTransformerFactory(attributePath, subviewTemplate, updatableObjectCache, nullIfEmpty))); + mapperBuilder.addTupleTransformerFactory(new SingularMultisetTupleTransformerFactory(startIndex, null, attributePath, getMultisetResultAlias(attributePath), elementConverter, subviewTemplate, managedViewType.hasSelectOrSubselectFetchedAttributes(), new SubviewTupleTransformerFactory(attributePath, subviewTemplate, updatableObjectCache, nullIfEmpty))); } else { applyCorrelatedSubviewMapping(attribute, attributePath, tupleIdDescriptor, (ManagedViewTypeImplementor) (ManagedViewTypeImplementor) managedViewType, mapperBuilder, features, viewJpqlMacro, embeddingViewJpqlMacro, ef, batchSize, false); } @@ -600,7 +600,7 @@ private void applyMapping(AbstractAttribute attribute, String parentAttrib String mapping = mapperBuilder.getMapping(mappingAttribute); ViewTypeObjectBuilderTemplate subviewTemplate = applySubviewMapping(mappingAttribute, attributePath, tupleIdDescriptor, managedViewType, mapperBuilder, viewJpqlMacro, embeddingViewJpqlMacro, ef, false, nullIfEmpty)[0]; TypeConverter elementConverter = (TypeConverter) (TypeConverter) managedViewType.getConverter(); - mapperBuilder.setTupleListTransformerFactory(new SingularMultisetTupleListTransformerFactory(startIndex, mapping, attributePath, getMultisetResultAlias(attributePath), elementConverter, subviewTemplate, managedViewType.hasSelectOrSubselectFetchedAttributes(), new SubviewTupleTransformerFactory(attributePath, subviewTemplate, updatableObjectCache, nullIfEmpty))); + mapperBuilder.addTupleTransformerFactory(new SingularMultisetTupleTransformerFactory(startIndex, mapping, attributePath, getMultisetResultAlias(attributePath), elementConverter, subviewTemplate, managedViewType.hasSelectOrSubselectFetchedAttributes(), new SubviewTupleTransformerFactory(attributePath, subviewTemplate, updatableObjectCache, nullIfEmpty))); } else { applySubviewMapping(mappingAttribute, attributePath, tupleIdDescriptor, managedViewType, mapperBuilder, viewJpqlMacro, embeddingViewJpqlMacro, ef, false, nullIfEmpty); } @@ -741,7 +741,7 @@ private void applyBasicCorrelatedMapping(AbstractAttribute attribute, Stri } else { indexCorrelator = new BasicCorrelator(); } - mapperBuilder.setTupleListTransformerFactory(new CorrelatedMapBatchTupleListTransformerFactory( + mapperBuilder.addTupleListTransformerFactory(new CorrelatedMapBatchTupleListTransformerFactory( new BasicCorrelator(), viewRoot, viewType, correlationResult, factory, attributePath, attribute.getFetches(), correlatesThis, viewRootIndex, embeddingViewIndex, startIndex, batchSize, correlationBasisType, correlationBasisEntity, createLimiter(mapperBuilder, correlationAlias, attribute), @@ -752,7 +752,7 @@ private void applyBasicCorrelatedMapping(AbstractAttribute attribute, Stri default: throw new IllegalArgumentException("Unknown collection type: " + pluralAttribute.getCollectionType()); } - mapperBuilder.setTupleListTransformerFactory(new CorrelatedCollectionBatchTupleListTransformerFactory( + mapperBuilder.addTupleListTransformerFactory(new CorrelatedCollectionBatchTupleListTransformerFactory( new BasicCorrelator(), viewRoot, viewType, correlationResult, factory, attributePath, attribute.getFetches(), correlatesThis, viewRootIndex, embeddingViewIndex, startIndex, batchSize, correlationBasisType, correlationBasisEntity, createLimiter(mapperBuilder, correlationAlias, attribute), @@ -760,7 +760,7 @@ private void applyBasicCorrelatedMapping(AbstractAttribute attribute, Stri dirtyTracking )); } else { - mapperBuilder.setTupleListTransformerFactory(new CorrelatedSingularBatchTupleListTransformerFactory( + mapperBuilder.addTupleListTransformerFactory(new CorrelatedSingularBatchTupleListTransformerFactory( new BasicCorrelator(), viewRoot, viewType, correlationResult, factory, attributePath, attribute.getFetches(), correlatesThis, viewRootIndex, embeddingViewIndex, startIndex, batchSize, correlationBasisType, correlationBasisEntity, createLimiter(mapperBuilder, correlationAlias, attribute))); @@ -808,7 +808,7 @@ private void applyBasicCorrelatedMapping(AbstractAttribute attribute, Stri } else { indexCorrelator = new BasicCorrelator(); } - mapperBuilder.setTupleListTransformerFactory(new CorrelatedMapSubselectTupleListTransformerFactory( + mapperBuilder.addTupleTransformerFactory(new CorrelatedMapSubselectTupleTransformerFactory( new BasicCorrelator(), evm, viewRoot, viewRootAlias, viewType, embeddingViewPath, correlationResult, correlationBasisExpression, correlationKeyExpression, factory, attributePath, attribute.getFetches(), viewRootIndex, embeddingViewIndex, startIndex, correlationBasisType, correlationBasisEntity, createLimiter(mapperBuilder, correlationAlias, attribute), @@ -819,7 +819,7 @@ private void applyBasicCorrelatedMapping(AbstractAttribute attribute, Stri default: throw new IllegalArgumentException("Unknown collection type: " + pluralAttribute.getCollectionType()); } - mapperBuilder.setTupleListTransformerFactory(new CorrelatedCollectionSubselectTupleListTransformerFactory( + mapperBuilder.addTupleTransformerFactory(new CorrelatedCollectionSubselectTupleTransformerFactory( new BasicCorrelator(), evm, viewRoot, viewRootAlias, viewType, embeddingViewPath, correlationResult, correlationBasisExpression, correlationKeyExpression, factory, attributePath, attribute.getFetches(), viewRootIndex, embeddingViewIndex, startIndex, correlationBasisType, correlationBasisEntity, createLimiter(mapperBuilder, correlationAlias, attribute), @@ -827,7 +827,7 @@ private void applyBasicCorrelatedMapping(AbstractAttribute attribute, Stri dirtyTracking )); } else { - mapperBuilder.setTupleListTransformerFactory(new CorrelatedSingularSubselectTupleListTransformerFactory( + mapperBuilder.addTupleTransformerFactory(new CorrelatedSingularSubselectTupleTransformerFactory( new BasicCorrelator(), evm, viewRoot, viewRootAlias, viewType, embeddingViewPath, correlationResult, correlationBasisExpression, correlationKeyExpression, factory, attributePath, attribute.getFetches(), viewRootIndex, embeddingViewIndex, startIndex, correlationBasisType, correlationBasisEntity, createLimiter(mapperBuilder, correlationAlias, attribute))); @@ -1115,7 +1115,7 @@ private ViewTypeObjectBuilderTemplate[] applyCorrelatedSubviewMapping( } else { indexCorrelator = new BasicCorrelator(); } - mapperBuilder.setTupleListTransformerFactory(new CorrelatedMapBatchTupleListTransformerFactory( + mapperBuilder.addTupleListTransformerFactory(new CorrelatedMapBatchTupleListTransformerFactory( new SubviewCorrelator(managedViewType, null, evm, subviewAliasPrefix, attributePath), viewRoot, viewType, correlationResult, factory, attributePath, attribute.getFetches(), correlatesThis, viewRootIndex, embeddingViewIndex, startIndex, batchSize, correlationBasisType, correlationBasisEntity, createLimiter(mapperBuilder, correlationAlias, attribute), @@ -1126,7 +1126,7 @@ private ViewTypeObjectBuilderTemplate[] applyCorrelatedSubviewMapping( default: throw new IllegalArgumentException("Unknown collection type: " + pluralAttribute.getCollectionType()); } - mapperBuilder.setTupleListTransformerFactory(new CorrelatedCollectionBatchTupleListTransformerFactory( + mapperBuilder.addTupleListTransformerFactory(new CorrelatedCollectionBatchTupleListTransformerFactory( new SubviewCorrelator(managedViewType, null, evm, subviewAliasPrefix, attributePath), viewRoot, viewType, correlationResult, factory, attributePath, attribute.getFetches(), correlatesThis, viewRootIndex, embeddingViewIndex, startIndex, batchSize, correlationBasisType, correlationBasisEntity, createLimiter(mapperBuilder, correlationAlias, attribute), @@ -1134,7 +1134,7 @@ private ViewTypeObjectBuilderTemplate[] applyCorrelatedSubviewMapping( dirtyTracking )); } else { - mapperBuilder.setTupleListTransformerFactory(new CorrelatedSingularBatchTupleListTransformerFactory( + mapperBuilder.addTupleListTransformerFactory(new CorrelatedSingularBatchTupleListTransformerFactory( new SubviewCorrelator(managedViewType, null, evm, subviewAliasPrefix, attributePath), viewRoot, viewType, correlationResult, factory, attributePath, attribute.getFetches(), correlatesThis, viewRootIndex, embeddingViewIndex, startIndex, batchSize, correlationBasisType, correlationBasisEntity, createLimiter(mapperBuilder, correlationAlias, attribute))); @@ -1182,7 +1182,7 @@ private ViewTypeObjectBuilderTemplate[] applyCorrelatedSubviewMapping( } else { indexCorrelator = new BasicCorrelator(); } - mapperBuilder.setTupleListTransformerFactory(new CorrelatedMapSubselectTupleListTransformerFactory( + mapperBuilder.addTupleTransformerFactory(new CorrelatedMapSubselectTupleTransformerFactory( new SubviewCorrelator(managedViewType, null, evm, subviewAliasPrefix, attributePath), evm, viewRoot, viewRootAlias, viewType, embeddingViewPath, correlationResult, correlationBasisExpression, correlationKeyExpression, factory, attributePath, attribute.getFetches(), viewRootIndex, embeddingViewIndex, startIndex, correlationBasisType, correlationBasisEntity, createLimiter(mapperBuilder, correlationAlias, attribute), @@ -1194,7 +1194,7 @@ private ViewTypeObjectBuilderTemplate[] applyCorrelatedSubviewMapping( throw new IllegalArgumentException("Unknown collection type: " + pluralAttribute.getCollectionType()); } - mapperBuilder.setTupleListTransformerFactory(new CorrelatedCollectionSubselectTupleListTransformerFactory( + mapperBuilder.addTupleTransformerFactory(new CorrelatedCollectionSubselectTupleTransformerFactory( new SubviewCorrelator(managedViewType, null, evm, subviewAliasPrefix, attributePath), evm, viewRoot, viewRootAlias, viewType, embeddingViewPath, correlationResult, correlationBasisExpression, correlationKeyExpression, factory, attributePath, attribute.getFetches(), viewRootIndex, embeddingViewIndex, startIndex, correlationBasisType, correlationBasisEntity, createLimiter(mapperBuilder, correlationAlias, attribute), @@ -1202,7 +1202,7 @@ private ViewTypeObjectBuilderTemplate[] applyCorrelatedSubviewMapping( dirtyTracking )); } else { - mapperBuilder.setTupleListTransformerFactory(new CorrelatedSingularSubselectTupleListTransformerFactory( + mapperBuilder.addTupleTransformerFactory(new CorrelatedSingularSubselectTupleTransformerFactory( new SubviewCorrelator(managedViewType, null, evm, subviewAliasPrefix, attributePath), evm, viewRoot, viewRootAlias, viewType, embeddingViewPath, correlationResult, correlationBasisExpression, correlationKeyExpression, factory, attributePath, attribute.getFetches(), viewRootIndex, embeddingViewIndex, startIndex, correlationBasisType, correlationBasisEntity, createLimiter(mapperBuilder, correlationAlias, attribute))); diff --git a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/mapper/TupleElementMapperBuilder.java b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/mapper/TupleElementMapperBuilder.java index 22626f152d..81744ccdcf 100644 --- a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/mapper/TupleElementMapperBuilder.java +++ b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/mapper/TupleElementMapperBuilder.java @@ -283,11 +283,11 @@ public TupleTransformatorFactory getTupleTransformatorFactory() { return tupleTransformatorFactory; } - public void setTupleListTransformer(TupleListTransformer tupleListTransformer) { + public void addTupleListTransformer(TupleListTransformer tupleListTransformer) { tupleTransformatorFactory.add(tupleListTransformer); } - public void setTupleListTransformerFactory(TupleListTransformerFactory tupleListTransformerFactory) { + public void addTupleListTransformerFactory(TupleListTransformerFactory tupleListTransformerFactory) { tupleTransformatorFactory.add(tupleListTransformerFactory); } diff --git a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/CollectionMultisetTupleListTransformerFactory.java b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/CollectionMultisetTupleTransformerFactory.java similarity index 80% rename from entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/CollectionMultisetTupleListTransformerFactory.java rename to entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/CollectionMultisetTupleTransformerFactory.java index 90ff9924dc..3df1533cc1 100644 --- a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/CollectionMultisetTupleListTransformerFactory.java +++ b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/CollectionMultisetTupleTransformerFactory.java @@ -35,7 +35,7 @@ * @author Christian Beikov * @since 1.5.0 */ -public class CollectionMultisetTupleListTransformerFactory implements TupleListTransformerFactory { +public class CollectionMultisetTupleTransformerFactory implements TupleTransformerFactory { private final int startIndex; private final String mapping; @@ -53,8 +53,8 @@ public class CollectionMultisetTupleListTransformerFactory implements TupleListT private final BasicUserTypeStringSupport indexBasicTypeSupport; private final boolean hasSelectOrSubselectFetchedAttributes; - public CollectionMultisetTupleListTransformerFactory(int startIndex, String mapping, String attributePath, String multisetResultAlias, TypeConverter elementConverter, ContainerAccumulator containerAccumulator, boolean dirtyTracking, ViewTypeObjectBuilderTemplate template, - ViewTypeObjectBuilderTemplate indexTemplate, boolean hasSelectOrSubselectFetchedAttributes, TupleTransformerFactory subviewTupleTransformerFactory, TupleTransformerFactory indexSubviewTupleTransformerFactory, BasicUserTypeStringSupport valueBasicTypeSupport, BasicUserTypeStringSupport indexBasicTypeSupport) { + public CollectionMultisetTupleTransformerFactory(int startIndex, String mapping, String attributePath, String multisetResultAlias, TypeConverter elementConverter, ContainerAccumulator containerAccumulator, boolean dirtyTracking, ViewTypeObjectBuilderTemplate template, + ViewTypeObjectBuilderTemplate indexTemplate, boolean hasSelectOrSubselectFetchedAttributes, TupleTransformerFactory subviewTupleTransformerFactory, TupleTransformerFactory indexSubviewTupleTransformerFactory, BasicUserTypeStringSupport valueBasicTypeSupport, BasicUserTypeStringSupport indexBasicTypeSupport) { this.startIndex = startIndex; this.mapping = mapping; this.attributePath = attributePath; @@ -93,12 +93,17 @@ public CollectionMultisetTupleListTransformerFactory(int startIndex, String mapp } @Override - public int getConsumableIndex() { + public int getConsumeStartIndex() { return startIndex; } @Override - public TupleListTransformer create(ParameterHolder parameterHolder, Map optionalParameters, EntityViewConfiguration entityViewConfiguration) { + public int getConsumeEndIndex() { + return startIndex + 1; + } + + @Override + public TupleTransformer create(ParameterHolder parameterHolder, Map optionalParameters, EntityViewConfiguration entityViewConfiguration) { if (mapping != null) { if (parameterHolder instanceof FullQueryBuilder) { FullQueryBuilder queryBuilder = (FullQueryBuilder) parameterHolder; @@ -115,7 +120,7 @@ public TupleListTransformer create(ParameterHolder parameterHolder, Map[] fieldConverters; - private final TypeConverter elementConverter; - private final ContainerAccumulator containerAccumulator; - private final boolean dirtyTracking; - - public MultisetTupleListTransformer(int startIndex, boolean hasSelectOrSubselectFetchedAttributes, TupleTransformator tupleTransformator, TupleTransformer subviewTupleTransformer, TupleTransformer indexSubviewTupleTransformer, int indexStartIndex, - BasicUserTypeStringSupport[] fieldConverters, TypeConverter elementConverter, ContainerAccumulator containerAccumulator, boolean dirtyTracking) { - super(startIndex); - this.hasSelectOrSubselectFetchedAttributes = hasSelectOrSubselectFetchedAttributes; - this.tupleTransformator = tupleTransformator; - this.subviewTupleTransformer = subviewTupleTransformer; - this.indexSubviewTupleTransformer = indexSubviewTupleTransformer; - this.indexStartIndex = indexStartIndex; - this.elementConverter = elementConverter; - this.fieldConverters = fieldConverters; - this.containerAccumulator = containerAccumulator; - this.dirtyTracking = dirtyTracking; - } - - @Override - public int getConsumableIndex() { - return -1; - } - - @Override - public List transform(List tuples) { - Iterator tupleListIter = tuples.iterator(); - // We differentiate here because for SELECT or SUBSELECT fetching we want to apply the tuple transformator on a multiset of the nested sets - // This is done so that caching for correlation keys works properly, which isn't necessary for other fetch strategies - if (hasSelectOrSubselectFetchedAttributes) { - MultisetList nestedTuples = new MultisetList(startIndex, tuples); - int index = 0; - - // First, go through all multi-sets and convert the fields - // While doing that, also collect the multi-set sizes for nested processing - while (tupleListIter.hasNext()) { - Object[] tuple = tupleListIter.next(); - if (tuple[startIndex] != null) { - List objects = (List) tuple[startIndex]; - for (int i = 0; i < objects.size(); i++) { - Object[] elementTuple = (Object[]) objects.get(i); - for (int j = 0; j < fieldConverters.length; j++) { - if (elementTuple[j] instanceof CharSequence) { - elementTuple[j] = fieldConverters[j].fromString((CharSequence) elementTuple[j]); - } - } - } - nestedTuples.addSize(index, objects.size()); - } else { - nestedTuples.addSize(index, 0); - } - - index++; - } - - if (tupleTransformator != null) { - // Apply the tuple transformator on a multiset of the nested sets - tupleTransformator.transformAll(nestedTuples); - } - - // Build views and add them to collections - UpdatableViewMap updatableViewMap = new UpdatableViewMap(); - tupleListIter = tuples.iterator(); - while (tupleListIter.hasNext()) { - Object[] tuple = tupleListIter.next(); - Object collection = containerAccumulator.createContainer(dirtyTracking, 0); - if (tuple[startIndex] != null) { - List objects = (List) tuple[startIndex]; - for (int i = 0; i < objects.size(); i++) { - Object indexObject = null; - if (indexSubviewTupleTransformer != null) { - indexObject = indexSubviewTupleTransformer.transform(objects.get(i), updatableViewMap)[indexSubviewTupleTransformer.getConsumeStartIndex()]; - } else if (indexStartIndex != -1) { - indexObject = objects.get(i)[indexStartIndex]; - } - if (subviewTupleTransformer == null) { - add(collection, indexObject, objects.get(i)[startIndex]); - } else { - Object[] transformedTuple = subviewTupleTransformer.transform(objects.get(i), updatableViewMap); - add(collection, indexObject, transformedTuple[0]); - } - } - } - tuple[startIndex] = collection; - } - } else { - // First, go through all multi-sets and convert the fields - while (tupleListIter.hasNext()) { - Object[] tuple = tupleListIter.next(); - if (tuple[startIndex] != null) { - List objects = (List) tuple[startIndex]; - for (int i = 0; i < objects.size(); i++) { - Object[] elementTuple = objects.get(i); - for (int j = 0; j < fieldConverters.length; j++) { - if (elementTuple[j] instanceof CharSequence) { - elementTuple[j] = fieldConverters[j].fromString((CharSequence) elementTuple[j]); - } - } - } - } - } - - // Build views and add them to collections - UpdatableViewMap updatableViewMap = new UpdatableViewMap(); - tupleListIter = tuples.iterator(); - while (tupleListIter.hasNext()) { - Object[] tuple = tupleListIter.next(); - Object collection = containerAccumulator.createContainer(dirtyTracking, 0); - if (tuple[startIndex] != null) { - List objects = (List) tuple[startIndex]; - if (tupleTransformator != null) { - // Before building the subviews, apply the tuple transformator on the nested set in isolation - tupleTransformator.transformAll(objects); - } - for (int i = 0; i < objects.size(); i++) { - Object indexObject = null; - if (indexSubviewTupleTransformer != null) { - indexObject = indexSubviewTupleTransformer.transform(objects.get(i), updatableViewMap)[indexSubviewTupleTransformer.getConsumeStartIndex() - 1]; - } else if (indexStartIndex != -1) { - indexObject = objects.get(i)[indexStartIndex]; - } - if (subviewTupleTransformer == null) { - add(collection, indexObject, objects.get(i)[startIndex]); - } else { - Object[] transformedTuple = subviewTupleTransformer.transform(objects.get(i), updatableViewMap); - add(collection, indexObject, transformedTuple[0]); - } - } - } - tuple[startIndex] = collection; - } - } - - return tuples; - } - - protected void add(Object collection, Object index, Object value) { - if (elementConverter != null) { - value = elementConverter.convertToViewType(value); - } - containerAccumulator.add(collection, index, value, dirtyTracking); - } -} diff --git a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/MultisetTupleTransformer.java b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/MultisetTupleTransformer.java new file mode 100644 index 0000000000..b54d692733 --- /dev/null +++ b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/MultisetTupleTransformer.java @@ -0,0 +1,111 @@ +/* + * Copyright 2014 - 2021 Blazebit. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.blazebit.persistence.view.impl.objectbuilder.transformer; + +import com.blazebit.persistence.view.impl.objectbuilder.ContainerAccumulator; +import com.blazebit.persistence.view.impl.objectbuilder.transformator.TupleTransformator; +import com.blazebit.persistence.view.impl.objectbuilder.transformator.UpdatableViewMap; +import com.blazebit.persistence.view.spi.type.BasicUserTypeStringSupport; +import com.blazebit.persistence.view.spi.type.TypeConverter; + +import java.util.List; + +/** + * + * @author Christian Beikov + * @since 1.5.0 + */ +public class MultisetTupleTransformer implements TupleTransformer { + + private final int startIndex; + private final boolean hasSelectOrSubselectFetchedAttributes; + private final TupleTransformator tupleTransformator; + private final TupleTransformer subviewTupleTransformer; + private final TupleTransformer indexSubviewTupleTransformer; + private final int indexStartIndex; + private final BasicUserTypeStringSupport[] fieldConverters; + private final TypeConverter elementConverter; + private final ContainerAccumulator containerAccumulator; + private final boolean dirtyTracking; + + public MultisetTupleTransformer(int startIndex, boolean hasSelectOrSubselectFetchedAttributes, TupleTransformator tupleTransformator, TupleTransformer subviewTupleTransformer, TupleTransformer indexSubviewTupleTransformer, int indexStartIndex, + BasicUserTypeStringSupport[] fieldConverters, TypeConverter elementConverter, ContainerAccumulator containerAccumulator, boolean dirtyTracking) { + this.startIndex = startIndex; + this.hasSelectOrSubselectFetchedAttributes = hasSelectOrSubselectFetchedAttributes; + this.tupleTransformator = tupleTransformator; + this.subviewTupleTransformer = subviewTupleTransformer; + this.indexSubviewTupleTransformer = indexSubviewTupleTransformer; + this.indexStartIndex = indexStartIndex; + this.elementConverter = elementConverter; + this.fieldConverters = fieldConverters; + this.containerAccumulator = containerAccumulator; + this.dirtyTracking = dirtyTracking; + } + + @Override + public int getConsumeStartIndex() { + return startIndex; + } + + @Override + public int getConsumeEndIndex() { + return startIndex + 1; + } + + @Override + public Object[] transform(Object[] tuple, UpdatableViewMap updatableViewMap) { + Object collection = containerAccumulator.createContainer(dirtyTracking, 0); + if (tuple[startIndex] != null) { + List objects = (List) tuple[startIndex]; + for (int i = 0; i < objects.size(); i++) { + Object[] elementTuple = objects.get(i); + for (int j = 0; j < fieldConverters.length; j++) { + if (elementTuple[j] instanceof CharSequence) { + elementTuple[j] = fieldConverters[j].fromString((CharSequence) elementTuple[j]); + } + } + } + if (tupleTransformator != null) { + // Before building the subviews, apply the tuple transformator on the nested set in isolation + tupleTransformator.transformAll(objects); + } + for (int i = 0; i < objects.size(); i++) { + Object indexObject = null; + if (indexSubviewTupleTransformer != null) { + indexObject = indexSubviewTupleTransformer.transform(objects.get(i), updatableViewMap)[indexSubviewTupleTransformer.getConsumeStartIndex() - 1]; + } else if (indexStartIndex != -1) { + indexObject = objects.get(i)[indexStartIndex]; + } + if (subviewTupleTransformer == null) { + add(collection, indexObject, objects.get(i)[startIndex]); + } else { + Object[] transformedTuple = subviewTupleTransformer.transform(objects.get(i), updatableViewMap); + add(collection, indexObject, transformedTuple[0]); + } + } + } + tuple[startIndex] = collection; + return tuple; + } + + protected void add(Object collection, Object index, Object value) { + if (elementConverter != null) { + value = elementConverter.convertToViewType(value); + } + containerAccumulator.add(collection, index, value, dirtyTracking); + } +} diff --git a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/SingularMultisetTupleListTransformer.java b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/SingularMultisetTupleListTransformer.java deleted file mode 100644 index b543826f88..0000000000 --- a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/SingularMultisetTupleListTransformer.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2014 - 2021 Blazebit. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.blazebit.persistence.view.impl.objectbuilder.transformer; - -import com.blazebit.persistence.view.impl.objectbuilder.mapper.MultisetList; -import com.blazebit.persistence.view.impl.objectbuilder.transformator.TupleTransformator; -import com.blazebit.persistence.view.impl.objectbuilder.transformator.UpdatableViewMap; -import com.blazebit.persistence.view.spi.type.BasicUserTypeStringSupport; -import com.blazebit.persistence.view.spi.type.TypeConverter; - -import java.util.Iterator; -import java.util.List; - -/** - * - * @author Christian Beikov - * @since 1.5.0 - */ -public class SingularMultisetTupleListTransformer extends TupleListTransformer { - - private final boolean hasSelectOrSubselectFetchedAttributes; - private final TupleTransformator tupleTransformator; - private final TupleTransformer subviewTupleTransformer; - private final BasicUserTypeStringSupport[] fieldConverters; - private final TypeConverter elementConverter; - - public SingularMultisetTupleListTransformer(int startIndex, boolean hasSelectOrSubselectFetchedAttributes, TupleTransformator tupleTransformator, TupleTransformer subviewTupleTransformer, BasicUserTypeStringSupport[] fieldConverters, TypeConverter elementConverter) { - super(startIndex); - this.hasSelectOrSubselectFetchedAttributes = hasSelectOrSubselectFetchedAttributes; - this.tupleTransformator = tupleTransformator; - this.subviewTupleTransformer = subviewTupleTransformer; - this.elementConverter = elementConverter; - this.fieldConverters = fieldConverters; - } - - @Override - public int getConsumableIndex() { - return -1; - } - - @Override - public List transform(List tuples) { - Iterator tupleListIter = tuples.iterator(); - // We differentiate here because for SELECT or SUBSELECT fetching we want to apply the tuple transformator on a multiset of the nested sets - // This is done so that caching for correlation keys works properly, which isn't necessary for other fetch strategies - if (hasSelectOrSubselectFetchedAttributes) { - MultisetList nestedTuples = new MultisetList(startIndex, tuples); - int index = 0; - - // First, go through all multi-sets and convert the fields - // While doing that, also collect the multi-set sizes for nested processing - while (tupleListIter.hasNext()) { - Object[] tuple = tupleListIter.next(); - if (tuple[startIndex] != null) { - List objects = (List) tuple[startIndex]; - for (int i = 0; i < objects.size(); i++) { - Object[] elementTuple = (Object[]) objects.get(i); - for (int j = 0; j < fieldConverters.length; j++) { - if (elementTuple[j] instanceof CharSequence) { - elementTuple[j] = fieldConverters[j].fromString((CharSequence) elementTuple[j]); - } - } - } - nestedTuples.addSize(index, objects.size()); - } else { - nestedTuples.addSize(index, 0); - } - - index++; - } - - // Apply the tuple transformator on a multiset of the nested sets - tupleTransformator.transformAll(nestedTuples); - - // Build views and add them to collections - UpdatableViewMap updatableViewMap = new UpdatableViewMap(); - tupleListIter = tuples.iterator(); - while (tupleListIter.hasNext()) { - Object[] tuple = tupleListIter.next(); - if (tuple[startIndex] != null) { - List objects = (List) tuple[startIndex]; - if (objects.size() > 0) { - Object[] transformedTuple = subviewTupleTransformer.transform(objects.get(0), updatableViewMap); - if (elementConverter == null) { - tuple[startIndex] = transformedTuple[0]; - } else { - tuple[startIndex] = elementConverter.convertToViewType(transformedTuple[0]); - } - } - } - } - } else { - // First, go through all multi-sets and convert the fields - while (tupleListIter.hasNext()) { - Object[] tuple = tupleListIter.next(); - if (tuple[startIndex] != null) { - List objects = (List) tuple[startIndex]; - for (int i = 0; i < objects.size(); i++) { - Object[] elementTuple = objects.get(i); - for (int j = 0; j < fieldConverters.length; j++) { - if (elementTuple[j] instanceof CharSequence) { - elementTuple[j] = fieldConverters[j].fromString((CharSequence) elementTuple[j]); - } - } - } - } - } - - // Build views and add them to collections - UpdatableViewMap updatableViewMap = new UpdatableViewMap(); - tupleListIter = tuples.iterator(); - while (tupleListIter.hasNext()) { - Object[] tuple = tupleListIter.next(); - if (tuple[startIndex] != null) { - List objects = (List) tuple[startIndex]; - // Before building the subviews, apply the tuple transformator on the nested set in isolation - tupleTransformator.transformAll(objects); - if (objects.size() > 0) { - Object[] transformedTuple = subviewTupleTransformer.transform(objects.get(0), updatableViewMap); - if (elementConverter == null) { - tuple[startIndex] = transformedTuple[0]; - } else { - tuple[startIndex] = elementConverter.convertToViewType(transformedTuple[0]); - } - } - } - } - } - - return tuples; - } - -} diff --git a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/SingularMultisetTupleTransformer.java b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/SingularMultisetTupleTransformer.java new file mode 100644 index 0000000000..23f7976ab4 --- /dev/null +++ b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/SingularMultisetTupleTransformer.java @@ -0,0 +1,87 @@ +/* + * Copyright 2014 - 2021 Blazebit. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.blazebit.persistence.view.impl.objectbuilder.transformer; + +import com.blazebit.persistence.view.impl.objectbuilder.transformator.TupleTransformator; +import com.blazebit.persistence.view.impl.objectbuilder.transformator.UpdatableViewMap; +import com.blazebit.persistence.view.spi.type.BasicUserTypeStringSupport; +import com.blazebit.persistence.view.spi.type.TypeConverter; + +import java.util.List; + +/** + * + * @author Christian Beikov + * @since 1.5.0 + */ +public class SingularMultisetTupleTransformer implements TupleTransformer { + + private final int startIndex; + private final boolean hasSelectOrSubselectFetchedAttributes; + private final TupleTransformator tupleTransformator; + private final TupleTransformer subviewTupleTransformer; + private final BasicUserTypeStringSupport[] fieldConverters; + private final TypeConverter elementConverter; + + public SingularMultisetTupleTransformer(int startIndex, boolean hasSelectOrSubselectFetchedAttributes, TupleTransformator tupleTransformator, TupleTransformer subviewTupleTransformer, BasicUserTypeStringSupport[] fieldConverters, TypeConverter elementConverter) { + this.startIndex = startIndex; + this.hasSelectOrSubselectFetchedAttributes = hasSelectOrSubselectFetchedAttributes; + this.tupleTransformator = tupleTransformator; + this.subviewTupleTransformer = subviewTupleTransformer; + this.elementConverter = elementConverter; + this.fieldConverters = fieldConverters; + } + + @Override + public int getConsumeStartIndex() { + return startIndex; + } + + @Override + public int getConsumeEndIndex() { + return startIndex + 1; + } + + @Override + public Object[] transform(Object[] tuple, UpdatableViewMap updatableViewMap) { + // First, go through all multi-sets and convert the fields + if (tuple[startIndex] != null) { + List objects = (List) tuple[startIndex]; + for (int i = 0; i < objects.size(); i++) { + Object[] elementTuple = objects.get(i); + for (int j = 0; j < fieldConverters.length; j++) { + if (elementTuple[j] instanceof CharSequence) { + elementTuple[j] = fieldConverters[j].fromString((CharSequence) elementTuple[j]); + } + } + } + // Before building the subviews, apply the tuple transformator on the nested set in isolation + tupleTransformator.transformAll(objects); + if (!objects.isEmpty()) { + // Build views and add them to collections + Object[] transformedTuple = subviewTupleTransformer.transform(objects.get(0), updatableViewMap); + if (elementConverter == null) { + tuple[startIndex] = transformedTuple[0]; + } else { + tuple[startIndex] = elementConverter.convertToViewType(transformedTuple[0]); + } + } + } + return tuple; + } + +} diff --git a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/SingularMultisetTupleListTransformerFactory.java b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/SingularMultisetTupleTransformerFactory.java similarity index 81% rename from entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/SingularMultisetTupleListTransformerFactory.java rename to entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/SingularMultisetTupleTransformerFactory.java index 1647ceb6b9..33c66fefc1 100644 --- a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/SingularMultisetTupleListTransformerFactory.java +++ b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/SingularMultisetTupleTransformerFactory.java @@ -34,7 +34,7 @@ * @author Christian Beikov * @since 1.5.0 */ -public class SingularMultisetTupleListTransformerFactory implements TupleListTransformerFactory { +public class SingularMultisetTupleTransformerFactory implements TupleTransformerFactory { private final int startIndex; private final String mapping; @@ -46,7 +46,7 @@ public class SingularMultisetTupleListTransformerFactory implements TupleListTra private final TupleTransformerFactory subviewTupleTransformerFactory; private final boolean hasSelectOrSubselectFetchedAttributes; - public SingularMultisetTupleListTransformerFactory(int startIndex, String mapping, String attributePath, String multisetResultAlias, TypeConverter elementConverter, ViewTypeObjectBuilderTemplate template, boolean hasSelectOrSubselectFetchedAttributes, TupleTransformerFactory subviewTupleTransformerFactory) { + public SingularMultisetTupleTransformerFactory(int startIndex, String mapping, String attributePath, String multisetResultAlias, TypeConverter elementConverter, ViewTypeObjectBuilderTemplate template, boolean hasSelectOrSubselectFetchedAttributes, TupleTransformerFactory subviewTupleTransformerFactory) { this.startIndex = startIndex; this.mapping = mapping; this.attributePath = attributePath; @@ -64,12 +64,17 @@ public SingularMultisetTupleListTransformerFactory(int startIndex, String mappin } @Override - public int getConsumableIndex() { + public int getConsumeStartIndex() { return startIndex; } @Override - public TupleListTransformer create(ParameterHolder parameterHolder, Map optionalParameters, EntityViewConfiguration entityViewConfiguration) { + public int getConsumeEndIndex() { + return startIndex + 1; + } + + @Override + public TupleTransformer create(ParameterHolder parameterHolder, Map optionalParameters, EntityViewConfiguration entityViewConfiguration) { if (mapping != null) { if (parameterHolder instanceof FullQueryBuilder) { FullQueryBuilder queryBuilder = (FullQueryBuilder) parameterHolder; @@ -85,7 +90,7 @@ public TupleListTransformer create(ParameterHolder parameterHolder, Map correlationBasisType; + protected final Class correlationBasisEntity; + protected final Class viewRootEntityClass; + protected final ManagedViewTypeImplementor embeddingViewType; + protected final ManagedViewTypeImplementor viewRootType; + protected final String idAttributePath; + protected final String correlationResultExpression; + protected final String correlationAlias; + protected final String correlationExternalAlias; + protected final String indexExpression; + protected final CorrelationProviderFactory correlationProviderFactory; + protected final EntityViewConfiguration entityViewConfiguration; + + protected final int startIndex; + protected final String attributePath; + protected final ContainerAccumulator containerAccumulator; + protected final Limiter limiter; protected FullQueryBuilder criteriaBuilder; + protected int viewIndex; + protected Map> collections; protected CorrelatedSubqueryViewRootJpqlMacro viewRootJpqlMacro; protected MutableEmbeddingViewJpqlMacro embeddingViewJpqlMacro; - public AbstractCorrelatedSubselectTupleListTransformer(ExpressionFactory ef, Correlator correlator, ContainerAccumulator containerAccumulator, EntityViewManagerImpl evm, ManagedViewTypeImplementor viewRootType, String viewRootAlias, ManagedViewTypeImplementor embeddingViewType, String embeddingViewPath, - Expression correlationResult, String correlationBasisExpression, String correlationKeyExpression, CorrelationProviderFactory correlationProviderFactory, String attributePath, String[] fetches, - String[] indexFetches, Expression indexExpression, Correlator indexCorrelator, int viewRootIndex, int embeddingViewIndex, int tupleIndex, Class correlationBasisType, Class correlationBasisEntity, Limiter limiter, EntityViewConfiguration entityViewConfiguration) { - super(ef, correlator, containerAccumulator, viewRootType, embeddingViewType, correlationResult, correlationProviderFactory, attributePath, fetches, indexFetches, indexExpression, indexCorrelator, viewRootIndex, embeddingViewIndex, tupleIndex, correlationBasisType, correlationBasisEntity, limiter, entityViewConfiguration); + public AbstractCorrelatedSubselectTupleTransformer(ExpressionFactory ef, Correlator correlator, ContainerAccumulator containerAccumulator, EntityViewManagerImpl evm, ManagedViewTypeImplementor viewRootType, String viewRootAlias, ManagedViewTypeImplementor embeddingViewType, String embeddingViewPath, + Expression correlationResult, String correlationBasisExpression, String correlationKeyExpression, CorrelationProviderFactory correlationProviderFactory, String attributePath, String[] fetches, + String[] indexFetches, Expression index, Correlator indexCorrelator, int viewRootIndex, int embeddingViewIndex, int tupleIndex, Class correlationBasisType, Class correlationBasisEntity, Limiter limiter, EntityViewConfiguration entityViewConfiguration) { + this.startIndex = tupleIndex; + this.attributePath = attributePath; + this.containerAccumulator = (ContainerAccumulator) containerAccumulator; this.evm = evm; + this.correlationProviderFactory = correlationProviderFactory; + this.entityViewConfiguration = entityViewConfiguration; + this.correlationBasisType = correlationBasisType; this.viewRootAlias = viewRootAlias; + this.viewRootIndex = viewRootIndex; String viewRootAliasPrefix = viewRootAlias + "."; - this.viewRootIdExpression = viewRootAliasPrefix + getEntityIdName(viewRootType.getEntityClass()); + this.viewRootType = viewRootType; + this.viewRootIdExpression = viewRootAliasPrefix + getEntityIdName(entityViewConfiguration, viewRootType.getEntityClass()); this.viewRootIdMapperCount = viewIdMapperCount(viewRootType); + this.embeddingViewIndex = embeddingViewIndex; + this.embeddingViewType = embeddingViewType; this.embeddingViewPath = embeddingViewPath; if (viewRootAlias.equals(embeddingViewPath)) { - this.embeddingViewIdExpression = viewRootAliasPrefix + getEntityIdName(embeddingViewType.getEntityClass()); + this.embeddingViewIdExpression = viewRootAliasPrefix + getEntityIdName(entityViewConfiguration, embeddingViewType.getEntityClass()); } else { - this.embeddingViewIdExpression = embeddingViewPath + "." + getEntityIdName(embeddingViewType.getEntityClass()); + this.embeddingViewIdExpression = embeddingViewPath + "." + getEntityIdName(entityViewConfiguration, embeddingViewType.getEntityClass()); } this.embeddingViewIdMapperCount = viewIdMapperCount(embeddingViewType); this.maximumViewMapperCount = Math.max(1, Math.max(viewRootIdMapperCount, embeddingViewIdMapperCount)); this.correlationBasisExpression = correlationBasisExpression; this.correlationKeyExpression = correlationKeyExpression; this.valueIndex = correlator.getElementOffset(); - } - - private static int viewIdMapperCount(ManagedViewType viewRootType) { - MethodAttribute idAttribute; - if (viewRootType instanceof ViewType && (idAttribute = ((ViewType) viewRootType).getIdAttribute()).isSubview()) { - return viewIdMapperCount(idAttribute); + this.limiter = limiter; + this.correlationAlias = CorrelationProviderHelper.getDefaultCorrelationAlias(attributePath); + if (limiter == null) { + this.correlationExternalAlias = correlationAlias; } else { - return 0; + this.correlationExternalAlias = CorrelationProviderHelper.getDefaultExternalCorrelationAlias(attributePath); } - } - - private static int viewIdMapperCount(MethodAttribute attribute) { - if (attribute.isSubview()) { - ManagedViewType viewType = (ManagedViewType) ((SingularAttribute) attribute).getType(); - int count = 0; - for (MethodAttribute methodAttribute : viewType.getAttributes()) { - count += viewIdMapperCount(methodAttribute); - } - return count; + if (ExpressionUtils.isEmptyOrThis(correlationResult)) { + this.correlationResultExpression = correlationExternalAlias; } else { - return 1; - } - } - - private ObjectBuilder createViewAwareObjectBuilder(ManagedViewType viewType, EntityViewConfiguration configuration, String viewRoot) { - MethodAttribute idAttribute; - if (!(viewType instanceof ViewType) || !(idAttribute = ((ViewType) viewType).getIdAttribute()).isSubview()) { - return null; + this.correlationResultExpression = PrefixingQueryGenerator.prefix(ef, correlationResult, correlationExternalAlias, viewRootType.getEntityViewRootTypes().keySet(), true); } - ManagedViewType idViewType = (ManagedViewType) ((SingularAttribute) idAttribute).getType(); - return (ObjectBuilder) evm.createObjectBuilder((ManagedViewTypeImplementor) idViewType, null, viewRoot, "", criteriaBuilder, configuration, 1, 1, false); + this.indexExpression = index == null ? null : PrefixingQueryGenerator.prefix(ef, index, correlationResultExpression, viewRootType.getEntityViewRootTypes().keySet(), true); + this.fetches = prefix(correlationAlias, fetches); + this.indexFetches = prefix(indexExpression, indexFetches); + this.correlator = correlator; + this.indexCorrelator = indexCorrelator; + this.correlationBasisEntity = correlationBasisEntity; + this.viewRootEntityClass = viewRootType.getEntityClass(); + this.idAttributePath = getEntityIdName(entityViewConfiguration, viewRootEntityClass); } - @Override - public List transform(List tuples) { - Class viewRootEntityClass = viewRootType.getEntityClass(); - String idAttributePath = getEntityIdName(viewRootEntityClass); - + private void prepare() { + JpaProvider jpaProvider = entityViewConfiguration.getCriteriaBuilder().getService(JpaProvider.class); FullQueryBuilder queryBuilder = entityViewConfiguration.getCriteriaBuilder(); Map optionalParameters = entityViewConfiguration.getOptionalParameters(); @@ -141,7 +170,7 @@ public List transform(List tuples) { EmbeddingViewJpqlMacro embeddingViewJpqlMacro = entityViewConfiguration.getEmbeddingViewJpqlMacro(); ViewJpqlMacro viewJpqlMacro = entityViewConfiguration.getViewJpqlMacro(); if (queryBuilder instanceof PaginatedCriteriaBuilder) { - this.criteriaBuilder = queryBuilder.copyCriteriaBuilder(Object[].class, false); + criteriaBuilder = queryBuilder.copyCriteriaBuilder(Object[].class, false); } else { LimitBuilder limitBuilder = (LimitBuilder) queryBuilder; // To set the limit, we need the JPA provider to support this @@ -149,16 +178,16 @@ public List transform(List tuples) { // In case the outer query defines a limit/offset and this is not a paginated criteria builder // we must turn this query builder into a paginated criteria builder first try { - this.criteriaBuilder = queryBuilder.copyCriteriaBuilder(Object[].class, true) + criteriaBuilder = queryBuilder.copyCriteriaBuilder(Object[].class, true) .page(limitBuilder.getFirstResult(), limitBuilder.getMaxResults()) .copyCriteriaBuilder(Object[].class, false); } catch (IllegalStateException ex) { LOG.log(Level.WARNING, "Could not create a paginated criteria builder for SUBSELECT fetching which might lead to bad performance", ex); - this.criteriaBuilder = queryBuilder.copyCriteriaBuilder(Object[].class, false); + criteriaBuilder = queryBuilder.copyCriteriaBuilder(Object[].class, false); } } else { // Regular query without limit/offset - this.criteriaBuilder = queryBuilder.copyCriteriaBuilder(Object[].class, false); + criteriaBuilder = queryBuilder.copyCriteriaBuilder(Object[].class, false); } } int originalFirstResult = 0; @@ -167,17 +196,17 @@ public List transform(List tuples) { ((LimitBuilder) criteriaBuilder).setFirstResult(originalFirstResult); ((LimitBuilder) criteriaBuilder).setMaxResults(originalMaxResults); this.viewRootJpqlMacro = new CorrelatedSubqueryViewRootJpqlMacro(criteriaBuilder, optionalParameters, false, viewRootEntityClass, idAttributePath, viewRootExpression); - this.criteriaBuilder.registerMacro("view", viewJpqlMacro); - this.criteriaBuilder.registerMacro("view_root", viewRootJpqlMacro); - this.criteriaBuilder.registerMacro("embedding_view", embeddingViewJpqlMacro); + criteriaBuilder.registerMacro("view", viewJpqlMacro); + criteriaBuilder.registerMacro("view_root", viewRootJpqlMacro); + criteriaBuilder.registerMacro("embedding_view", embeddingViewJpqlMacro); String oldViewPath = viewJpqlMacro.getViewPath(); String oldEmbeddingViewPath = embeddingViewJpqlMacro.getEmbeddingViewPath(); - viewJpqlMacro.setViewPath(correlationResult); + viewJpqlMacro.setViewPath(correlationResultExpression); embeddingViewJpqlMacro.setEmbeddingViewPath(embeddingViewPath); String joinBase = embeddingViewPath; - SubqueryCorrelationBuilder correlationBuilder = new SubqueryCorrelationBuilder(queryBuilder, optionalParameters, criteriaBuilder, correlationAlias, correlationExternalAlias, correlationResult, correlationBasisType, correlationBasisEntityType, joinBase, attributePath, 1, limiter, true); + SubqueryCorrelationBuilder correlationBuilder = new SubqueryCorrelationBuilder(queryBuilder, optionalParameters, criteriaBuilder, correlationAlias, correlationExternalAlias, correlationResultExpression, correlationBasisType, correlationBasisEntityType, joinBase, attributePath, 1, limiter, true); CorrelationProvider provider = correlationProviderFactory.create(entityViewConfiguration.getCriteriaBuilder(), entityViewConfiguration.getOptionalParameters()); provider.applyCorrelation(correlationBuilder, correlationBasisExpression); @@ -213,100 +242,47 @@ public List transform(List tuples) { throw new IllegalStateException("The use of VIEW_ROOT in the correlation for '" + embeddingViewType.getJavaType().getName() + "." + attributePath.substring(attributePath.lastIndexOf('.') + 1) + "' is illegal because the view root type '" + viewRootType.getJavaType().getName() + "' does not declare a @IdMapping!"); } - int totalSize = tuples.size(); - Map> viewRoots = new HashMap>(totalSize); final int maximumSlotsFilled; - + final int elementKeyIndex; + final int elementViewIndex; if (usesEmbeddingView) { maximumSlotsFilled = embeddingViewIdMapperCount == 0 ? 1 : embeddingViewIdMapperCount; - this.keyIndex = (maximumViewMapperCount - maximumSlotsFilled) + 2 + valueIndex; - this.viewIndex = (maximumViewMapperCount - maximumSlotsFilled) + 1 + valueIndex; + elementKeyIndex = (maximumViewMapperCount - maximumSlotsFilled) + 2 + valueIndex; + elementViewIndex = (maximumViewMapperCount - maximumSlotsFilled) + 1 + valueIndex; + viewIndex = embeddingViewIndex; } else if (usesViewRoot) { maximumSlotsFilled = viewRootIdMapperCount == 0 ? 1 : viewRootIdMapperCount; - this.keyIndex = (maximumViewMapperCount - maximumSlotsFilled) + 2 + valueIndex; - this.viewIndex = (maximumViewMapperCount - maximumSlotsFilled) + 1 + valueIndex; + elementKeyIndex = (maximumViewMapperCount - maximumSlotsFilled) + 2 + valueIndex; + elementViewIndex = (maximumViewMapperCount - maximumSlotsFilled) + 1 + valueIndex; + viewIndex = viewRootIndex; } else { maximumSlotsFilled = 0; - this.keyIndex = maximumViewMapperCount + 1 + valueIndex; - this.viewIndex = 1 + valueIndex; + elementKeyIndex = maximumViewMapperCount + 1 + valueIndex; + elementViewIndex = 1 + valueIndex; + viewIndex = -1; } for (int i = maximumSlotsFilled; i < maximumViewMapperCount; i++) { criteriaBuilder.select("NULL"); } + ExpressionFactory ef = criteriaBuilder.getService(ExpressionFactory.class); if (usesEmbeddingView) { - ExpressionFactory ef = criteriaBuilder.getService(ExpressionFactory.class); EntityViewConfiguration configuration = new EntityViewConfiguration(criteriaBuilder, ef, new MutableViewJpqlMacro(), new MutableEmbeddingViewJpqlMacro(), Collections.emptyMap(), Collections.emptyMap(), entityViewConfiguration.getFetches(), attributePath); - ObjectBuilder embeddingViewObjectBuilder = createViewAwareObjectBuilder(embeddingViewType, configuration, embeddingViewIdExpression); + ObjectBuilder embeddingViewObjectBuilder = createViewAwareObjectBuilder(criteriaBuilder, embeddingViewType, configuration, embeddingViewIdExpression); if (embeddingViewObjectBuilder == null) { criteriaBuilder.select(embeddingViewIdExpression); } else { criteriaBuilder.selectNew(objectBuilder = new LateAdditionalObjectBuilder(objectBuilder, embeddingViewObjectBuilder, true)); } - // Group tuples by view roots and correlation values and create tuple promises - for (Object[] tuple : tuples) { - Object embeddingViewKey = tuple[embeddingViewIndex]; - Object correlationValueKey = tuple[startIndex]; - - if (embeddingViewKey != null && correlationValueKey != null) { - Map viewRootCorrelationValues = viewRoots.get(embeddingViewKey); - if (viewRootCorrelationValues == null) { - viewRootCorrelationValues = new HashMap<>(); - viewRoots.put(embeddingViewKey, viewRootCorrelationValues); - } - TuplePromise viewRootPromise = viewRootCorrelationValues.get(correlationValueKey); - if (viewRootPromise == null) { - viewRootPromise = new TuplePromise(startIndex); - viewRootCorrelationValues.put(correlationValueKey, viewRootPromise); - } - viewRootPromise.add(tuple); - } - } } else if (usesViewRoot) { - ExpressionFactory ef = criteriaBuilder.getService(ExpressionFactory.class); EntityViewConfiguration configuration = new EntityViewConfiguration(criteriaBuilder, ef, new MutableViewJpqlMacro(), new MutableEmbeddingViewJpqlMacro(), Collections.emptyMap(), Collections.emptyMap(), entityViewConfiguration.getFetches(), attributePath); - ObjectBuilder viewRootObjectBuilder = createViewAwareObjectBuilder(viewRootType, configuration, viewRootIdExpression); + ObjectBuilder viewRootObjectBuilder = createViewAwareObjectBuilder(criteriaBuilder, viewRootType, configuration, viewRootIdExpression); if (viewRootObjectBuilder == null) { criteriaBuilder.select(viewRootIdExpression); } else { criteriaBuilder.selectNew(objectBuilder = new LateAdditionalObjectBuilder(objectBuilder, viewRootObjectBuilder, true)); } - // Group tuples by view roots and correlation values and create tuple promises - for (Object[] tuple : tuples) { - Object viewRootKey = tuple[viewRootIndex]; - Object correlationValueKey = tuple[startIndex]; - - if (viewRootKey != null && correlationValueKey != null) { - Map viewRootCorrelationValues = viewRoots.get(viewRootKey); - if (viewRootCorrelationValues == null) { - viewRootCorrelationValues = new HashMap<>(); - viewRoots.put(viewRootKey, viewRootCorrelationValues); - } - TuplePromise viewRootPromise = viewRootCorrelationValues.get(correlationValueKey); - if (viewRootPromise == null) { - viewRootPromise = new TuplePromise(startIndex); - viewRootCorrelationValues.put(correlationValueKey, viewRootPromise); - } - viewRootPromise.add(tuple); - } - } - } else { - Map viewRootCorrelationValues = new HashMap<>(tuples.size()); - viewRoots.put(null, viewRootCorrelationValues); - // Group tuples by correlation values and create tuple promises - for (Object[] tuple : tuples) { - Object correlationValueKey = tuple[startIndex]; - - if (correlationValueKey != null) { - TuplePromise viewRootPromise = viewRootCorrelationValues.get(correlationValueKey); - if (viewRootPromise == null) { - viewRootPromise = new TuplePromise(startIndex); - viewRootCorrelationValues.put(correlationValueKey, viewRootPromise); - } - viewRootPromise.add(tuple); - } - } } criteriaBuilder.select(correlationKeyExpression); @@ -317,51 +293,149 @@ public List transform(List tuples) { } } - populateParameters(criteriaBuilder); + populateParameters(entityViewConfiguration, criteriaBuilder); viewJpqlMacro.setViewPath(oldViewPath); embeddingViewJpqlMacro.setEmbeddingViewPath(oldEmbeddingViewPath); List resultList = (List) criteriaBuilder.getResultList(); - populateResult(viewRoots, resultList); - fillDefaultValues(viewRoots); - - return tuples; - } - - protected void populateResult(Map> correlationValues, List list) { - Map> collections; - collections = new HashMap<>(list.size()); - for (int i = 0; i < list.size(); i++) { - Object[] element = list.get(i); - Map viewRootResult = collections.get(element[viewIndex]); + Map> collections = new HashMap<>(resultList.size()); + for (int i = 0; i < resultList.size(); i++) { + Object[] element = resultList.get(i); + Map viewRootResult = collections.get(element[elementViewIndex]); if (viewRootResult == null) { viewRootResult = new HashMap<>(); - collections.put(element[viewIndex], viewRootResult); + collections.put(element[elementViewIndex], viewRootResult); } - Object result = viewRootResult.get(element[keyIndex]); - if (result == null) { - result = createDefaultResult(); - viewRootResult.put(element[keyIndex], result); + if (this.containerAccumulator == null) { + viewRootResult.put(element[elementKeyIndex], element[valueIndex]); + } else { + Object result = viewRootResult.get(element[elementKeyIndex]); + if (result == null) { + result = createDefaultResult(); + viewRootResult.put(element[elementKeyIndex], result); + } + Object indexObject = null; + if (indexCorrelator != null || indexExpression != null) { + indexObject = element[elementKeyIndex + 1]; + } + this.containerAccumulator.add(result, indexObject, element[valueIndex], isRecording()); } + } + this.collections = collections; + } - Object indexObject = null; - if (indexCorrelator != null || indexExpression != null) { - indexObject = element[keyIndex + 1]; + @Override + public int getConsumeStartIndex() { + return -1; + } + + @Override + public int getConsumeEndIndex() { + return -1; + } + + protected String getEntityIdName(EntityViewConfiguration entityViewConfiguration, Class entityClass) { + ManagedType managedType = entityViewConfiguration.getCriteriaBuilder().getMetamodel().managedType(entityClass); + if (JpaMetamodelUtils.isIdentifiable(managedType)) { + return JpaMetamodelUtils.getSingleIdAttribute((IdentifiableType) managedType).getName(); + } else { + return null; + } + } + + private static String[] prefix(String prefix, String[] fetches) { + if (fetches == null || fetches.length == 0) { + return fetches; + } + String[] newFetches = new String[fetches.length]; + for (int i = 0; i < fetches.length; i++) { + newFetches[i] = (prefix + "." + fetches[i]).intern(); + } + + return newFetches; + } + + private static int viewIdMapperCount(ManagedViewType viewRootType) { + MethodAttribute idAttribute; + if (viewRootType instanceof ViewType && (idAttribute = ((ViewType) viewRootType).getIdAttribute()).isSubview()) { + return viewIdMapperCount(idAttribute); + } else { + return 0; + } + } + + private static int viewIdMapperCount(MethodAttribute attribute) { + if (attribute.isSubview()) { + ManagedViewType viewType = (ManagedViewType) ((SingularAttribute) attribute).getType(); + int count = 0; + for (MethodAttribute methodAttribute : viewType.getAttributes()) { + count += viewIdMapperCount(methodAttribute); } - containerAccumulator.add(result, indexObject, element[valueIndex], isRecording()); + return count; + } else { + return 1; } + } - for (Map.Entry> entry : collections.entrySet()) { - Map tuplePromiseMap = correlationValues.get(entry.getKey()); - if (tuplePromiseMap != null) { - for (Map.Entry correlationEntry : entry.getValue().entrySet()) { - TuplePromise tuplePromise = tuplePromiseMap.get(correlationEntry.getKey()); - if (tuplePromise != null) { - tuplePromise.onResult(postConstruct(correlationEntry.getValue()), this); - } - } + protected void populateParameters(EntityViewConfiguration entityViewConfiguration, FullQueryBuilder queryBuilder) { + FullQueryBuilder mainBuilder = entityViewConfiguration.getCriteriaBuilder(); + for (Parameter paramEntry : mainBuilder.getParameters()) { + if (queryBuilder.containsParameter(paramEntry.getName()) && !queryBuilder.isParameterSet(paramEntry.getName())) { + queryBuilder.setParameter(paramEntry.getName(), mainBuilder.getParameterValue(paramEntry.getName())); + } + } + for (Map.Entry paramEntry : entityViewConfiguration.getOptionalParameters().entrySet()) { + if (queryBuilder.containsParameter(paramEntry.getKey()) && !queryBuilder.isParameterSet(paramEntry.getKey())) { + queryBuilder.setParameter(paramEntry.getKey(), paramEntry.getValue()); + } + } + } + + private ObjectBuilder createViewAwareObjectBuilder(FullQueryBuilder criteriaBuilder, ManagedViewType viewType, EntityViewConfiguration configuration, String viewRoot) { + MethodAttribute idAttribute; + if (!(viewType instanceof ViewType) || !(idAttribute = ((ViewType) viewType).getIdAttribute()).isSubview()) { + return null; + } + ManagedViewType idViewType = (ManagedViewType) ((SingularAttribute) idAttribute).getType(); + return (ObjectBuilder) evm.createObjectBuilder((ManagedViewTypeImplementor) idViewType, null, viewRoot, "", criteriaBuilder, configuration, 1, 1, false); + } + + protected boolean isRecording() { + return false; + } + + protected Object createDefaultResult() { + return containerAccumulator == null ? null : containerAccumulator.createContainer(isRecording(), 0); + } + + @Override + public Object[] transform(Object[] tuple, UpdatableViewMap updatableViewMap) { + if (collections == null) { + prepare(); + } + Object viewKey; + if (viewIndex == -1) { + viewKey = null; + } else { + viewKey = tuple[viewIndex]; + } + Map collectionsByKey = collections.get(viewKey); + Object correlationValueKey = tuple[startIndex]; + if (correlationValueKey == null) { + tuple[startIndex] = createDefaultResult(); + } else if (collectionsByKey == null) { + collections.put(viewKey, collectionsByKey = new HashMap<>()); + collectionsByKey.put(correlationValueKey, tuple[startIndex] = createDefaultResult()); + } else { + Object collection = collectionsByKey.get(correlationValueKey); + if (collection == null) { + collectionsByKey.put(correlationValueKey, tuple[startIndex] = createDefaultResult()); + } else { + tuple[startIndex] = collection; } } + + return tuple; } } diff --git a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/AbstractCorrelatedSubselectTupleListTransformerFactory.java b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/AbstractCorrelatedSubselectTupleTransformerFactory.java similarity index 75% rename from entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/AbstractCorrelatedSubselectTupleListTransformerFactory.java rename to entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/AbstractCorrelatedSubselectTupleTransformerFactory.java index 51063c85dd..2ef794a6b7 100644 --- a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/AbstractCorrelatedSubselectTupleListTransformerFactory.java +++ b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/AbstractCorrelatedSubselectTupleTransformerFactory.java @@ -21,14 +21,14 @@ import com.blazebit.persistence.view.impl.EntityViewManagerImpl; import com.blazebit.persistence.view.impl.metamodel.ManagedViewTypeImplementor; import com.blazebit.persistence.view.impl.objectbuilder.Limiter; -import com.blazebit.persistence.view.impl.objectbuilder.transformer.TupleListTransformerFactory; +import com.blazebit.persistence.view.impl.objectbuilder.transformer.TupleTransformerFactory; /** * * @author Christian Beikov * @since 1.2.0 */ -public abstract class AbstractCorrelatedSubselectTupleListTransformerFactory implements TupleListTransformerFactory { +public abstract class AbstractCorrelatedSubselectTupleTransformerFactory implements TupleTransformerFactory { protected final Correlator correlator; protected final EntityViewManagerImpl evm; @@ -49,9 +49,9 @@ public abstract class AbstractCorrelatedSubselectTupleListTransformerFactory imp protected final Class correlationBasisEntity; protected final Limiter limiter; - public AbstractCorrelatedSubselectTupleListTransformerFactory(Correlator correlator, EntityViewManagerImpl evm, ManagedViewTypeImplementor viewRootType, String viewRootAlias, ManagedViewTypeImplementor embeddingViewType, String embeddingViewPath, - Expression correlationResult, String correlationBasisExpression, String correlationKeyExpression, CorrelationProviderFactory correlationProviderFactory, - String attributePath, String[] fetches, int viewRootIndex, int embeddingViewIndex, int correlationBasisIndex, Class correlationBasisType, Class correlationBasisEntity, Limiter limiter) { + public AbstractCorrelatedSubselectTupleTransformerFactory(Correlator correlator, EntityViewManagerImpl evm, ManagedViewTypeImplementor viewRootType, String viewRootAlias, ManagedViewTypeImplementor embeddingViewType, String embeddingViewPath, + Expression correlationResult, String correlationBasisExpression, String correlationKeyExpression, CorrelationProviderFactory correlationProviderFactory, + String attributePath, String[] fetches, int viewRootIndex, int embeddingViewIndex, int correlationBasisIndex, Class correlationBasisType, Class correlationBasisEntity, Limiter limiter) { this.correlator = correlator; this.evm = evm; this.viewRootType = viewRootType; @@ -73,8 +73,12 @@ public AbstractCorrelatedSubselectTupleListTransformerFactory(Correlator correla } @Override - public int getConsumableIndex() { + public int getConsumeStartIndex() { return -1; } + @Override + public int getConsumeEndIndex() { + return -1; + } } diff --git a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedCollectionSubselectTupleListTransformer.java b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedCollectionSubselectTupleTransformer.java similarity index 63% rename from entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedCollectionSubselectTupleListTransformer.java rename to entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedCollectionSubselectTupleTransformer.java index 7aca593d5d..6fb8e64354 100644 --- a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedCollectionSubselectTupleListTransformer.java +++ b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedCollectionSubselectTupleTransformer.java @@ -30,14 +30,14 @@ * @author Christian Beikov * @since 1.2.0 */ -public class CorrelatedCollectionSubselectTupleListTransformer extends AbstractCorrelatedSubselectTupleListTransformer { +public class CorrelatedCollectionSubselectTupleTransformer extends AbstractCorrelatedSubselectTupleTransformer { private final boolean recording; - public CorrelatedCollectionSubselectTupleListTransformer(ExpressionFactory ef, Correlator correlator, ContainerAccumulator containerAccumulator, EntityViewManagerImpl evm, ManagedViewTypeImplementor viewRootType, String viewRootAlias, ManagedViewTypeImplementor embeddingViewType, String embeddingViewPath, - Expression correlationResult, String correlationBasisExpression, String correlationKeyExpression, CorrelationProviderFactory correlationProviderFactory, String attributePath, String[] fetches, - String[] indexFetches, Expression indexExpression, Correlator indexCorrelator, int viewRootIndex, int embeddingViewIndex, int tupleIndex, Class correlationBasisType, Class correlationBasisEntity, - Limiter limiter, EntityViewConfiguration entityViewConfiguration, boolean recording) { + public CorrelatedCollectionSubselectTupleTransformer(ExpressionFactory ef, Correlator correlator, ContainerAccumulator containerAccumulator, EntityViewManagerImpl evm, ManagedViewTypeImplementor viewRootType, String viewRootAlias, ManagedViewTypeImplementor embeddingViewType, String embeddingViewPath, + Expression correlationResult, String correlationBasisExpression, String correlationKeyExpression, CorrelationProviderFactory correlationProviderFactory, String attributePath, String[] fetches, + String[] indexFetches, Expression indexExpression, Correlator indexCorrelator, int viewRootIndex, int embeddingViewIndex, int tupleIndex, Class correlationBasisType, Class correlationBasisEntity, + Limiter limiter, EntityViewConfiguration entityViewConfiguration, boolean recording) { super(ef, correlator, containerAccumulator, evm, viewRootType, viewRootAlias, embeddingViewType, embeddingViewPath, correlationResult, correlationBasisExpression, correlationKeyExpression, correlationProviderFactory, attributePath, fetches, indexFetches, indexExpression, indexCorrelator, viewRootIndex, embeddingViewIndex, tupleIndex, correlationBasisType, correlationBasisEntity, limiter, entityViewConfiguration); this.recording = recording; diff --git a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedCollectionSubselectTupleListTransformerFactory.java b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedCollectionSubselectTupleTransformerFactory.java similarity index 64% rename from entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedCollectionSubselectTupleListTransformerFactory.java rename to entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedCollectionSubselectTupleTransformerFactory.java index b3b4480838..95472dffd3 100644 --- a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedCollectionSubselectTupleListTransformerFactory.java +++ b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedCollectionSubselectTupleTransformerFactory.java @@ -24,7 +24,7 @@ import com.blazebit.persistence.view.impl.metamodel.ManagedViewTypeImplementor; import com.blazebit.persistence.view.impl.objectbuilder.ContainerAccumulator; import com.blazebit.persistence.view.impl.objectbuilder.Limiter; -import com.blazebit.persistence.view.impl.objectbuilder.transformer.TupleListTransformer; +import com.blazebit.persistence.view.impl.objectbuilder.transformer.TupleTransformer; import java.util.Map; @@ -33,7 +33,7 @@ * @author Christian Beikov * @since 1.2.0 */ -public class CorrelatedCollectionSubselectTupleListTransformerFactory extends AbstractCorrelatedSubselectTupleListTransformerFactory { +public class CorrelatedCollectionSubselectTupleTransformerFactory extends AbstractCorrelatedSubselectTupleTransformerFactory { private final String[] indexFetches; private final Expression indexExpression; @@ -41,9 +41,9 @@ public class CorrelatedCollectionSubselectTupleListTransformerFactory extends Ab private final ContainerAccumulator containerAccumulator; private final boolean recording; - public CorrelatedCollectionSubselectTupleListTransformerFactory(Correlator correlator, EntityViewManagerImpl evm, ManagedViewTypeImplementor viewRootType, String viewRootAlias, ManagedViewTypeImplementor embeddingViewType, String embeddingViewPath, - Expression correlationResult, String correlationBasisExpression, String correlationKeyExpression, CorrelationProviderFactory correlationProviderFactory, String attributePath, String[] fetches, - int viewRootIndex, int embeddingViewIndex, int tupleIndex, Class correlationBasisType, Class correlationBasisEntity, Limiter limiter, String[] indexFetches, Expression indexExpression, Correlator indexCorrelator, ContainerAccumulator containerAccumulator, boolean recording) { + public CorrelatedCollectionSubselectTupleTransformerFactory(Correlator correlator, EntityViewManagerImpl evm, ManagedViewTypeImplementor viewRootType, String viewRootAlias, ManagedViewTypeImplementor embeddingViewType, String embeddingViewPath, + Expression correlationResult, String correlationBasisExpression, String correlationKeyExpression, CorrelationProviderFactory correlationProviderFactory, String attributePath, String[] fetches, + int viewRootIndex, int embeddingViewIndex, int tupleIndex, Class correlationBasisType, Class correlationBasisEntity, Limiter limiter, String[] indexFetches, Expression indexExpression, Correlator indexCorrelator, ContainerAccumulator containerAccumulator, boolean recording) { super(correlator, evm, viewRootType, viewRootAlias, embeddingViewType, embeddingViewPath, correlationResult, correlationBasisExpression, correlationKeyExpression, correlationProviderFactory, attributePath, fetches, viewRootIndex, embeddingViewIndex, tupleIndex, correlationBasisType, correlationBasisEntity, limiter); this.indexFetches = indexFetches; this.indexExpression = indexExpression; @@ -53,8 +53,8 @@ public CorrelatedCollectionSubselectTupleListTransformerFactory(Correlator corre } @Override - public TupleListTransformer create(ParameterHolder parameterHolder, Map optionalParameters, EntityViewConfiguration entityViewConfiguration) { - return new CorrelatedCollectionSubselectTupleListTransformer(entityViewConfiguration.getExpressionFactory(), correlator, containerAccumulator, evm, viewRootType, viewRootAlias, embeddingViewType, embeddingViewPath, correlationResult, correlationBasisExpression, correlationKeyExpression, correlationProviderFactory, + public TupleTransformer create(ParameterHolder parameterHolder, Map optionalParameters, EntityViewConfiguration entityViewConfiguration) { + return new CorrelatedCollectionSubselectTupleTransformer(entityViewConfiguration.getExpressionFactory(), correlator, containerAccumulator, evm, viewRootType, viewRootAlias, embeddingViewType, embeddingViewPath, correlationResult, correlationBasisExpression, correlationKeyExpression, correlationProviderFactory, attributePath, fetches, indexFetches, indexExpression, indexCorrelator, viewRootIndex, embeddingViewIndex, correlationBasisIndex, correlationBasisType, correlationBasisEntity, limiter, entityViewConfiguration, recording); } diff --git a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedMapSubselectTupleListTransformer.java b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedMapSubselectTupleTransformer.java similarity index 63% rename from entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedMapSubselectTupleListTransformer.java rename to entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedMapSubselectTupleTransformer.java index f6f59bdcf2..198dcd01d9 100644 --- a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedMapSubselectTupleListTransformer.java +++ b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedMapSubselectTupleTransformer.java @@ -30,14 +30,14 @@ * @author Christian Beikov * @since 1.2.0 */ -public class CorrelatedMapSubselectTupleListTransformer extends AbstractCorrelatedSubselectTupleListTransformer { +public class CorrelatedMapSubselectTupleTransformer extends AbstractCorrelatedSubselectTupleTransformer { private final boolean recording; - public CorrelatedMapSubselectTupleListTransformer(ExpressionFactory ef, Correlator correlator, ContainerAccumulator containerAccumulator, EntityViewManagerImpl evm, ManagedViewTypeImplementor viewRootType, String viewRootAlias, ManagedViewTypeImplementor embeddingViewType, String embeddingViewPath, - Expression correlationResult, String correlationBasisExpression, String correlationKeyExpression, CorrelationProviderFactory correlationProviderFactory, String attributePath, String[] fetches, - String[] indexFetches, Expression indexExpression, Correlator indexCorrelator, int viewRootIndex, int embeddingViewIndex, int tupleIndex, Class correlationBasisType, Class correlationBasisEntity, - Limiter limiter, EntityViewConfiguration entityViewConfiguration, boolean recording) { + public CorrelatedMapSubselectTupleTransformer(ExpressionFactory ef, Correlator correlator, ContainerAccumulator containerAccumulator, EntityViewManagerImpl evm, ManagedViewTypeImplementor viewRootType, String viewRootAlias, ManagedViewTypeImplementor embeddingViewType, String embeddingViewPath, + Expression correlationResult, String correlationBasisExpression, String correlationKeyExpression, CorrelationProviderFactory correlationProviderFactory, String attributePath, String[] fetches, + String[] indexFetches, Expression indexExpression, Correlator indexCorrelator, int viewRootIndex, int embeddingViewIndex, int tupleIndex, Class correlationBasisType, Class correlationBasisEntity, + Limiter limiter, EntityViewConfiguration entityViewConfiguration, boolean recording) { super(ef, correlator, containerAccumulator, evm, viewRootType, viewRootAlias, embeddingViewType, embeddingViewPath, correlationResult, correlationBasisExpression, correlationKeyExpression, correlationProviderFactory, attributePath, fetches, indexFetches, indexExpression, indexCorrelator, viewRootIndex, embeddingViewIndex, tupleIndex, correlationBasisType, correlationBasisEntity, limiter, entityViewConfiguration); this.recording = recording; diff --git a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedMapSubselectTupleListTransformerFactory.java b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedMapSubselectTupleTransformerFactory.java similarity index 60% rename from entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedMapSubselectTupleListTransformerFactory.java rename to entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedMapSubselectTupleTransformerFactory.java index 5d1764fd1d..ec1f8fef92 100644 --- a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedMapSubselectTupleListTransformerFactory.java +++ b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedMapSubselectTupleTransformerFactory.java @@ -24,7 +24,7 @@ import com.blazebit.persistence.view.impl.metamodel.ManagedViewTypeImplementor; import com.blazebit.persistence.view.impl.objectbuilder.ContainerAccumulator; import com.blazebit.persistence.view.impl.objectbuilder.Limiter; -import com.blazebit.persistence.view.impl.objectbuilder.transformer.TupleListTransformer; +import com.blazebit.persistence.view.impl.objectbuilder.transformer.TupleTransformer; import java.util.Map; @@ -33,7 +33,7 @@ * @author Christian Beikov * @since 1.2.0 */ -public class CorrelatedMapSubselectTupleListTransformerFactory extends AbstractCorrelatedSubselectTupleListTransformerFactory { +public class CorrelatedMapSubselectTupleTransformerFactory extends AbstractCorrelatedSubselectTupleTransformerFactory { private final String[] indexFetches; private final Expression indexExpression; @@ -41,10 +41,10 @@ public class CorrelatedMapSubselectTupleListTransformerFactory extends AbstractC private final ContainerAccumulator containerAccumulator; private final boolean recording; - public CorrelatedMapSubselectTupleListTransformerFactory(Correlator correlator, EntityViewManagerImpl evm, ManagedViewTypeImplementor viewRootType, String viewRootAlias, ManagedViewTypeImplementor embeddingViewType, String embeddingViewPath, - Expression correlationResult, String correlationBasisExpression, String correlationKeyExpression, CorrelationProviderFactory correlationProviderFactory, - String attributePath, String[] fetches, int viewRootIndex, int embeddingViewIndex, int tupleIndex, Class correlationBasisType, Class correlationBasisEntity, Limiter limiter, String[] indexFetches, Expression indexExpression, Correlator indexCorrelator, ContainerAccumulator containerAccumulator, - boolean recording) { + public CorrelatedMapSubselectTupleTransformerFactory(Correlator correlator, EntityViewManagerImpl evm, ManagedViewTypeImplementor viewRootType, String viewRootAlias, ManagedViewTypeImplementor embeddingViewType, String embeddingViewPath, + Expression correlationResult, String correlationBasisExpression, String correlationKeyExpression, CorrelationProviderFactory correlationProviderFactory, + String attributePath, String[] fetches, int viewRootIndex, int embeddingViewIndex, int tupleIndex, Class correlationBasisType, Class correlationBasisEntity, Limiter limiter, String[] indexFetches, Expression indexExpression, Correlator indexCorrelator, ContainerAccumulator containerAccumulator, + boolean recording) { super(correlator, evm, viewRootType, viewRootAlias, embeddingViewType, embeddingViewPath, correlationResult, correlationBasisExpression, correlationKeyExpression, correlationProviderFactory, attributePath, fetches, viewRootIndex, embeddingViewIndex, tupleIndex, correlationBasisType, correlationBasisEntity, limiter); this.indexFetches = indexFetches; this.indexExpression = indexExpression; @@ -54,8 +54,8 @@ public CorrelatedMapSubselectTupleListTransformerFactory(Correlator correlator, } @Override - public TupleListTransformer create(ParameterHolder parameterHolder, Map optionalParameters, EntityViewConfiguration entityViewConfiguration) { - return new CorrelatedMapSubselectTupleListTransformer(entityViewConfiguration.getExpressionFactory(), correlator, containerAccumulator, evm, viewRootType, viewRootAlias, embeddingViewType, embeddingViewPath, correlationResult, correlationBasisExpression, correlationKeyExpression, correlationProviderFactory, + public TupleTransformer create(ParameterHolder parameterHolder, Map optionalParameters, EntityViewConfiguration entityViewConfiguration) { + return new CorrelatedMapSubselectTupleTransformer(entityViewConfiguration.getExpressionFactory(), correlator, containerAccumulator, evm, viewRootType, viewRootAlias, embeddingViewType, embeddingViewPath, correlationResult, correlationBasisExpression, correlationKeyExpression, correlationProviderFactory, attributePath, fetches, indexFetches, indexExpression, indexCorrelator, viewRootIndex, embeddingViewIndex, correlationBasisIndex, correlationBasisType, correlationBasisEntity, limiter, entityViewConfiguration, recording); } diff --git a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedSingularSubselectTupleListTransformer.java b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedSingularSubselectTupleTransformer.java similarity index 51% rename from entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedSingularSubselectTupleListTransformer.java rename to entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedSingularSubselectTupleTransformer.java index 9835d1cd17..f264fc0cee 100644 --- a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedSingularSubselectTupleListTransformer.java +++ b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedSingularSubselectTupleTransformer.java @@ -24,31 +24,16 @@ import com.blazebit.persistence.view.impl.metamodel.ManagedViewTypeImplementor; import com.blazebit.persistence.view.impl.objectbuilder.Limiter; -import java.util.List; -import java.util.Map; - /** * * @author Christian Beikov * @since 1.2.0 */ -public class CorrelatedSingularSubselectTupleListTransformer extends AbstractCorrelatedSubselectTupleListTransformer { +public class CorrelatedSingularSubselectTupleTransformer extends AbstractCorrelatedSubselectTupleTransformer { - public CorrelatedSingularSubselectTupleListTransformer(ExpressionFactory ef, Correlator correlator, EntityViewManagerImpl evm, ManagedViewTypeImplementor viewRootType, String viewRootAlias, ManagedViewTypeImplementor embeddingViewType, String embeddingViewPath, Expression correlationResult, String correlationBasisExpression, String correlationKeyExpression, - CorrelationProviderFactory correlationProviderFactory, String attributePath, String[] fetches, int viewRootIndex, int embeddingViewIndex, int tupleIndex, Class correlationBasisType, Class correlationBasisEntity, Limiter limiter, EntityViewConfiguration entityViewConfiguration) { + public CorrelatedSingularSubselectTupleTransformer(ExpressionFactory ef, Correlator correlator, EntityViewManagerImpl evm, ManagedViewTypeImplementor viewRootType, String viewRootAlias, ManagedViewTypeImplementor embeddingViewType, String embeddingViewPath, Expression correlationResult, String correlationBasisExpression, String correlationKeyExpression, + CorrelationProviderFactory correlationProviderFactory, String attributePath, String[] fetches, int viewRootIndex, int embeddingViewIndex, int tupleIndex, Class correlationBasisType, Class correlationBasisEntity, Limiter limiter, EntityViewConfiguration entityViewConfiguration) { super(ef, correlator, null, evm, viewRootType, viewRootAlias, embeddingViewType, embeddingViewPath, correlationResult, correlationBasisExpression, correlationKeyExpression, correlationProviderFactory, attributePath, fetches, EMPTY, null, null, viewRootIndex, embeddingViewIndex, tupleIndex, correlationBasisType, correlationBasisEntity, limiter, entityViewConfiguration); } - @Override - protected void populateResult(Map> correlationValues, List list) { - for (Object[] element : (List) (List) list) { - Map objectTuplePromiseMap = correlationValues.get(element[viewIndex]); - if (objectTuplePromiseMap != null) { - TuplePromise tuplePromise = objectTuplePromiseMap.get(element[keyIndex]); - if (tuplePromise != null) { - tuplePromise.onResult(element[valueIndex], this); - } - } - } - } } diff --git a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedSingularSubselectTupleListTransformerFactory.java b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedSingularSubselectTupleTransformerFactory.java similarity index 57% rename from entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedSingularSubselectTupleListTransformerFactory.java rename to entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedSingularSubselectTupleTransformerFactory.java index 119e418edc..228968065b 100644 --- a/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedSingularSubselectTupleListTransformerFactory.java +++ b/entity-view/impl/src/main/java/com/blazebit/persistence/view/impl/objectbuilder/transformer/correlation/CorrelatedSingularSubselectTupleTransformerFactory.java @@ -23,7 +23,7 @@ import com.blazebit.persistence.view.impl.EntityViewManagerImpl; import com.blazebit.persistence.view.impl.metamodel.ManagedViewTypeImplementor; import com.blazebit.persistence.view.impl.objectbuilder.Limiter; -import com.blazebit.persistence.view.impl.objectbuilder.transformer.TupleListTransformer; +import com.blazebit.persistence.view.impl.objectbuilder.transformer.TupleTransformer; import java.util.Map; @@ -32,17 +32,17 @@ * @author Christian Beikov * @since 1.2.0 */ -public class CorrelatedSingularSubselectTupleListTransformerFactory extends AbstractCorrelatedSubselectTupleListTransformerFactory { +public class CorrelatedSingularSubselectTupleTransformerFactory extends AbstractCorrelatedSubselectTupleTransformerFactory { - public CorrelatedSingularSubselectTupleListTransformerFactory(Correlator correlator, EntityViewManagerImpl evm, ManagedViewTypeImplementor viewRoot, String viewRootAlias, ManagedViewTypeImplementor embeddingViewType, String embeddingViewPath, - Expression correlationResult, String correlationBasisExpression, String correlationKeyExpression, CorrelationProviderFactory correlationProviderFactory, - String attributePath, String[] fetches, int viewRootIndex, int embeddingViewIndex, int tupleIndex, Class correlationBasisType, Class correlationBasisEntity, Limiter limiter) { + public CorrelatedSingularSubselectTupleTransformerFactory(Correlator correlator, EntityViewManagerImpl evm, ManagedViewTypeImplementor viewRoot, String viewRootAlias, ManagedViewTypeImplementor embeddingViewType, String embeddingViewPath, + Expression correlationResult, String correlationBasisExpression, String correlationKeyExpression, CorrelationProviderFactory correlationProviderFactory, + String attributePath, String[] fetches, int viewRootIndex, int embeddingViewIndex, int tupleIndex, Class correlationBasisType, Class correlationBasisEntity, Limiter limiter) { super(correlator, evm, viewRoot, viewRootAlias, embeddingViewType, embeddingViewPath, correlationResult, correlationBasisExpression, correlationKeyExpression, correlationProviderFactory, attributePath, fetches, viewRootIndex, embeddingViewIndex, tupleIndex, correlationBasisType, correlationBasisEntity, limiter); } @Override - public TupleListTransformer create(ParameterHolder parameterHolder, Map optionalParameters, EntityViewConfiguration entityViewConfiguration) { - return new CorrelatedSingularSubselectTupleListTransformer(entityViewConfiguration.getExpressionFactory(), correlator, evm, viewRootType, viewRootAlias, embeddingViewType, embeddingViewPath, correlationResult, correlationBasisExpression, correlationKeyExpression, correlationProviderFactory, + public TupleTransformer create(ParameterHolder parameterHolder, Map optionalParameters, EntityViewConfiguration entityViewConfiguration) { + return new CorrelatedSingularSubselectTupleTransformer(entityViewConfiguration.getExpressionFactory(), correlator, evm, viewRootType, viewRootAlias, embeddingViewType, embeddingViewPath, correlationResult, correlationBasisExpression, correlationKeyExpression, correlationProviderFactory, attributePath, fetches, viewRootIndex, embeddingViewIndex, correlationBasisIndex, correlationBasisType, correlationBasisEntity, limiter, entityViewConfiguration); } diff --git a/entity-view/testsuite/src/test/java/com/blazebit/persistence/view/testsuite/correlation/AbstractCorrelationTest.java b/entity-view/testsuite/src/test/java/com/blazebit/persistence/view/testsuite/correlation/AbstractCorrelationTest.java index 8c5de9a003..7006a74ff9 100644 --- a/entity-view/testsuite/src/test/java/com/blazebit/persistence/view/testsuite/correlation/AbstractCorrelationTest.java +++ b/entity-view/testsuite/src/test/java/com/blazebit/persistence/view/testsuite/correlation/AbstractCorrelationTest.java @@ -20,9 +20,7 @@ import com.blazebit.persistence.testsuite.tx.TxVoidWork; import com.blazebit.persistence.view.EntityViewManager; import com.blazebit.persistence.view.EntityViewSetting; -import com.blazebit.persistence.view.EntityViews; import com.blazebit.persistence.view.ConfigurationProperties; -import com.blazebit.persistence.view.spi.EntityViewConfiguration; import com.blazebit.persistence.view.testsuite.AbstractEntityViewTest; import com.blazebit.persistence.view.testsuite.correlation.model.DocumentCorrelationView; import com.blazebit.persistence.view.testsuite.correlation.model.SimpleDocumentCorrelatedView; @@ -35,7 +33,6 @@ import javax.persistence.EntityManager; import java.util.Collection; -import java.util.Iterator; import java.util.List; import static org.junit.Assert.assertEquals; @@ -118,9 +115,9 @@ protected void testCorrelation(Class enti assertEquals(0, results.get(0).getOwnerRelatedDocumentIds().size()); assertEquals(1, results.get(0).getOwnerOnlyRelatedDocumentViews().size()); - assertRemovedByName(doc1.getName(), results.get(0).getOwnerOnlyRelatedDocumentViews()); + assertExistsByName(doc1.getName(), results.get(0).getOwnerOnlyRelatedDocumentViews()); assertEquals(1, results.get(0).getOwnerOnlyRelatedDocumentIds().size()); - assertRemoved(doc1.getId(), results.get(0).getOwnerOnlyRelatedDocumentIds()); + assertExists(doc1.getId(), results.get(0).getOwnerOnlyRelatedDocumentIds()); assertEquals(0, results.get(0).getThisCorrelatedEmptyIdList().size()); assertEquals(0, results.get(0).getThisCorrelatedEmptyEntityList().size()); assertEquals(0, results.get(0).getThisCorrelatedEmptyViewList().size()); @@ -130,20 +127,20 @@ protected void testCorrelation(Class enti assertThisAndOwnerMappings(doc2, results.get(1)); assertEquals(2, results.get(1).getOwnerRelatedDocumentViews().size()); - assertRemovedByName(doc3.getName(), results.get(1).getOwnerRelatedDocumentViews()); - assertRemovedByName(doc4.getName(), results.get(1).getOwnerRelatedDocumentViews()); + assertExistsByName(doc3.getName(), results.get(1).getOwnerRelatedDocumentViews()); + assertExistsByName(doc4.getName(), results.get(1).getOwnerRelatedDocumentViews()); assertEquals(2, results.get(1).getOwnerRelatedDocumentIds().size()); - assertRemoved(doc3.getId(), results.get(1).getOwnerRelatedDocumentIds()); - assertRemoved(doc4.getId(), results.get(1).getOwnerRelatedDocumentIds()); + assertExists(doc3.getId(), results.get(1).getOwnerRelatedDocumentIds()); + assertExists(doc4.getId(), results.get(1).getOwnerRelatedDocumentIds()); assertEquals(3, results.get(1).getOwnerOnlyRelatedDocumentViews().size()); - assertRemovedByName(doc2.getName(), results.get(1).getOwnerOnlyRelatedDocumentViews()); - assertRemovedByName(doc3.getName(), results.get(1).getOwnerOnlyRelatedDocumentViews()); - assertRemovedByName(doc4.getName(), results.get(1).getOwnerOnlyRelatedDocumentViews()); + assertExistsByName(doc2.getName(), results.get(1).getOwnerOnlyRelatedDocumentViews()); + assertExistsByName(doc3.getName(), results.get(1).getOwnerOnlyRelatedDocumentViews()); + assertExistsByName(doc4.getName(), results.get(1).getOwnerOnlyRelatedDocumentViews()); assertEquals(3, results.get(1).getOwnerOnlyRelatedDocumentIds().size()); - assertRemoved(doc2.getId(), results.get(1).getOwnerOnlyRelatedDocumentIds()); - assertRemoved(doc3.getId(), results.get(1).getOwnerOnlyRelatedDocumentIds()); - assertRemoved(doc4.getId(), results.get(1).getOwnerOnlyRelatedDocumentIds()); + assertExists(doc2.getId(), results.get(1).getOwnerOnlyRelatedDocumentIds()); + assertExists(doc3.getId(), results.get(1).getOwnerOnlyRelatedDocumentIds()); + assertExists(doc4.getId(), results.get(1).getOwnerOnlyRelatedDocumentIds()); assertEquals(0, results.get(1).getThisCorrelatedEmptyIdList().size()); assertEquals(0, results.get(1).getThisCorrelatedEmptyEntityList().size()); assertEquals(0, results.get(1).getThisCorrelatedEmptyViewList().size()); @@ -153,20 +150,20 @@ protected void testCorrelation(Class enti assertThisAndOwnerMappings(doc3, results.get(2)); assertEquals(2, results.get(2).getOwnerRelatedDocumentViews().size()); - assertRemovedByName(doc2.getName(), results.get(2).getOwnerRelatedDocumentViews()); - assertRemovedByName(doc4.getName(), results.get(2).getOwnerRelatedDocumentViews()); + assertExistsByName(doc2.getName(), results.get(2).getOwnerRelatedDocumentViews()); + assertExistsByName(doc4.getName(), results.get(2).getOwnerRelatedDocumentViews()); assertEquals(2, results.get(2).getOwnerRelatedDocumentIds().size()); - assertRemoved(doc2.getId(), results.get(2).getOwnerRelatedDocumentIds()); - assertRemoved(doc4.getId(), results.get(2).getOwnerRelatedDocumentIds()); + assertExists(doc2.getId(), results.get(2).getOwnerRelatedDocumentIds()); + assertExists(doc4.getId(), results.get(2).getOwnerRelatedDocumentIds()); assertEquals(3, results.get(2).getOwnerOnlyRelatedDocumentViews().size()); - assertRemovedByName(doc2.getName(), results.get(2).getOwnerOnlyRelatedDocumentViews()); - assertRemovedByName(doc3.getName(), results.get(2).getOwnerOnlyRelatedDocumentViews()); - assertRemovedByName(doc4.getName(), results.get(2).getOwnerOnlyRelatedDocumentViews()); + assertExistsByName(doc2.getName(), results.get(2).getOwnerOnlyRelatedDocumentViews()); + assertExistsByName(doc3.getName(), results.get(2).getOwnerOnlyRelatedDocumentViews()); + assertExistsByName(doc4.getName(), results.get(2).getOwnerOnlyRelatedDocumentViews()); assertEquals(3, results.get(2).getOwnerOnlyRelatedDocumentIds().size()); - assertRemoved(doc2.getId(), results.get(2).getOwnerOnlyRelatedDocumentIds()); - assertRemoved(doc3.getId(), results.get(2).getOwnerOnlyRelatedDocumentIds()); - assertRemoved(doc4.getId(), results.get(2).getOwnerOnlyRelatedDocumentIds()); + assertExists(doc2.getId(), results.get(2).getOwnerOnlyRelatedDocumentIds()); + assertExists(doc3.getId(), results.get(2).getOwnerOnlyRelatedDocumentIds()); + assertExists(doc4.getId(), results.get(2).getOwnerOnlyRelatedDocumentIds()); assertEquals(0, results.get(2).getThisCorrelatedEmptyIdList().size()); assertEquals(0, results.get(2).getThisCorrelatedEmptyEntityList().size()); assertEquals(0, results.get(2).getThisCorrelatedEmptyViewList().size()); @@ -176,31 +173,28 @@ protected void testCorrelation(Class enti assertThisAndOwnerMappings(doc4, results.get(3)); assertEquals(2, results.get(3).getOwnerRelatedDocumentViews().size()); - assertRemovedByName(doc2.getName(), results.get(3).getOwnerRelatedDocumentViews()); - assertRemovedByName(doc3.getName(), results.get(3).getOwnerRelatedDocumentViews()); + assertExistsByName(doc2.getName(), results.get(3).getOwnerRelatedDocumentViews()); + assertExistsByName(doc3.getName(), results.get(3).getOwnerRelatedDocumentViews()); assertEquals(2, results.get(3).getOwnerRelatedDocumentIds().size()); - assertRemoved(doc2.getId(), results.get(3).getOwnerRelatedDocumentIds()); - assertRemoved(doc3.getId(), results.get(3).getOwnerRelatedDocumentIds()); + assertExists(doc2.getId(), results.get(3).getOwnerRelatedDocumentIds()); + assertExists(doc3.getId(), results.get(3).getOwnerRelatedDocumentIds()); assertEquals(3, results.get(3).getOwnerOnlyRelatedDocumentViews().size()); - assertRemovedByName(doc2.getName(), results.get(3).getOwnerOnlyRelatedDocumentViews()); - assertRemovedByName(doc3.getName(), results.get(3).getOwnerOnlyRelatedDocumentViews()); - assertRemovedByName(doc4.getName(), results.get(3).getOwnerOnlyRelatedDocumentViews()); + assertExistsByName(doc2.getName(), results.get(3).getOwnerOnlyRelatedDocumentViews()); + assertExistsByName(doc3.getName(), results.get(3).getOwnerOnlyRelatedDocumentViews()); + assertExistsByName(doc4.getName(), results.get(3).getOwnerOnlyRelatedDocumentViews()); assertEquals(3, results.get(3).getOwnerOnlyRelatedDocumentIds().size()); - assertRemoved(doc2.getId(), results.get(3).getOwnerOnlyRelatedDocumentIds()); - assertRemoved(doc3.getId(), results.get(3).getOwnerOnlyRelatedDocumentIds()); - assertRemoved(doc4.getId(), results.get(3).getOwnerOnlyRelatedDocumentIds()); + assertExists(doc2.getId(), results.get(3).getOwnerOnlyRelatedDocumentIds()); + assertExists(doc3.getId(), results.get(3).getOwnerOnlyRelatedDocumentIds()); + assertExists(doc4.getId(), results.get(3).getOwnerOnlyRelatedDocumentIds()); assertEquals(0, results.get(3).getThisCorrelatedEmptyIdList().size()); assertEquals(0, results.get(3).getThisCorrelatedEmptyEntityList().size()); assertEquals(0, results.get(3).getThisCorrelatedEmptyViewList().size()); } - private void assertRemovedByName(String expectedName, Collection views) { - Iterator iter = views.iterator(); - while (iter.hasNext()) { - SimpleDocumentCorrelatedView v = iter.next(); + private void assertExistsByName(String expectedName, Collection views) { + for (SimpleDocumentCorrelatedView v : views) { if (expectedName.equals(v.getName())) { - iter.remove(); return; } } @@ -208,8 +202,8 @@ private void assertRemovedByName(String expectedName, Collection void assertRemoved(T expectedValue, Collection collection) { - if (!collection.remove(expectedValue)) { + private void assertExists(T expectedValue, Collection collection) { + if (!collection.contains(expectedValue)) { Assert.fail("Could not find '" + expectedValue + "' in: " + collection); } }