2626import org .springframework .data .repository .query .ReturnedType ;
2727
2828import java .beans .PropertyDescriptor ;
29- import java .util .ArrayList ;
3029import java .util .Collection ;
3130import java .util .Collections ;
31+ import java .util .HashMap ;
3232import java .util .HashSet ;
33- import java .util .List ;
33+ import java .util .Map ;
3434
3535/**
3636 * This class is responsible for creating a List of {@link PropertyPath} entries that contains all reachable
3939@ API (status = API .Status .INTERNAL , since = "6.1.3" )
4040public final class PropertyFilterSupport {
4141
42- public static List <PropertyPath > getInputProperties (ResultProcessor resultProcessor , ProjectionFactory factory ,
43- Neo4jMappingContext mappingContext ) {
42+ public static Map <PropertyPath , Boolean > getInputProperties (ResultProcessor resultProcessor , ProjectionFactory factory ,
43+ Neo4jMappingContext mappingContext ) {
4444
4545 ReturnedType returnedType = resultProcessor .getReturnedType ();
46- List <PropertyPath > filteredProperties = new ArrayList <>();
46+ Map <PropertyPath , Boolean > filteredProperties = new HashMap <>();
4747
4848 boolean isProjecting = returnedType .isProjecting ();
4949 boolean isClosedProjection = factory .getProjectionInformation (returnedType .getReturnedType ()).isClosed ();
5050
5151 if (!isProjecting || !isClosedProjection ) {
52- return Collections .emptyList ();
52+ return Collections .emptyMap ();
5353 }
5454
5555 for (String inputProperty : returnedType .getInputProperties ()) {
@@ -60,21 +60,21 @@ public static List<PropertyPath> getInputProperties(ResultProcessor resultProces
6060 return filteredProperties ;
6161 }
6262
63- static List <PropertyPath > addPropertiesFrom (Class <?> domainType , Class <?> returnType ,
63+ static Map <PropertyPath , Boolean > addPropertiesFrom (Class <?> domainType , Class <?> returnType ,
6464 ProjectionFactory projectionFactory ,
6565 Neo4jMappingContext neo4jMappingContext ) {
6666
6767 ProjectionInformation projectionInformation = projectionFactory .getProjectionInformation (returnType );
68- List <PropertyPath > propertyPaths = new ArrayList <>();
68+ Map <PropertyPath , Boolean > propertyPaths = new HashMap <>();
6969 for (PropertyDescriptor inputProperty : projectionInformation .getInputProperties ()) {
7070 addPropertiesFrom (domainType , returnType , projectionFactory , propertyPaths , inputProperty .getName (), neo4jMappingContext );
7171 }
7272 return propertyPaths ;
7373 }
7474
7575 private static void addPropertiesFrom (Class <?> domainType , Class <?> returnedType , ProjectionFactory factory ,
76- Collection <PropertyPath > filteredProperties , String inputProperty ,
77- Neo4jMappingContext mappingContext ) {
76+ Map <PropertyPath , Boolean > filteredProperties , String inputProperty ,
77+ Neo4jMappingContext mappingContext ) {
7878
7979 ProjectionInformation projectionInformation = factory .getProjectionInformation (returnedType );
8080 PropertyPath propertyPath ;
@@ -93,33 +93,33 @@ private static void addPropertiesFrom(Class<?> domainType, Class<?> returnedType
9393 // 2. Something that looks like an entity needs to get processed as such
9494 // 3. Embedded projection
9595 if (mappingContext .getConversionService ().isSimpleType (propertyType )) {
96- filteredProperties .add (propertyPath );
96+ filteredProperties .put (propertyPath , false );
9797 } else if (mappingContext .hasPersistentEntityFor (propertyType )) {
98- // avoid recursion / cycles
99- if (propertyType .equals (domainType )) {
100- return ;
101- }
102-
10398 addPropertiesFromEntity (filteredProperties , propertyPath , propertyType , mappingContext , new HashSet <>());
10499 } else {
105100 ProjectionInformation nestedProjectionInformation = factory .getProjectionInformation (propertyType );
106- filteredProperties .add (propertyPath );
107101 // Closed projection should get handled as above (recursion)
108102 if (nestedProjectionInformation .isClosed ()) {
103+ filteredProperties .put (propertyPath , false );
109104 for (PropertyDescriptor nestedInputProperty : nestedProjectionInformation .getInputProperties ()) {
110105 PropertyPath nestedPropertyPath = propertyPath .nested (nestedInputProperty .getName ());
111- filteredProperties .add (nestedPropertyPath );
106+ if (propertyPath .hasNext () && (domainType .equals (propertyPath .getLeafProperty ().getOwningType ().getType ())
107+ || returnedType .equals (propertyPath .getLeafProperty ().getOwningType ().getType ()))) {
108+ break ;
109+ }
110+
112111 addPropertiesFrom (domainType , returnedType , factory , filteredProperties ,
113112 nestedPropertyPath .toDotPath (), mappingContext );
114113 }
115114 } else {
116115 // an open projection at this place needs to get replaced with the matching (real) entity
116+ filteredProperties .put (propertyPath , true );
117117 processEntity (domainType , filteredProperties , inputProperty , mappingContext );
118118 }
119119 }
120120 }
121121
122- private static void processEntity (Class <?> domainType , Collection <PropertyPath > filteredProperties ,
122+ private static void processEntity (Class <?> domainType , Map <PropertyPath , Boolean > filteredProperties ,
123123 String inputProperty , Neo4jMappingContext mappingContext ) {
124124
125125 Neo4jPersistentEntity <?> persistentEntity = mappingContext .getPersistentEntity (domainType );
@@ -131,59 +131,27 @@ private static void processEntity(Class<?> domainType, Collection<PropertyPath>
131131 addPropertiesFromEntity (filteredProperties , propertyPath , propertyEntityType , mappingContext , new HashSet <>());
132132 }
133133
134- private static void addPropertiesFromEntity (Collection <PropertyPath > filteredProperties , PropertyPath propertyPath ,
134+ private static void addPropertiesFromEntity (Map <PropertyPath , Boolean > filteredProperties , PropertyPath propertyPath ,
135135 Class <?> propertyType , Neo4jMappingContext mappingContext ,
136136 Collection <Neo4jPersistentEntity <?>> processedEntities ) {
137137
138+ if (!mappingContext .hasPersistentEntityFor (propertyType )) {
139+ throw new RuntimeException ("hmmmm" );
140+ }
141+
138142 Neo4jPersistentEntity <?> persistentEntityFromProperty = mappingContext .getPersistentEntity (propertyType );
139143 // break the recursion / cycles
140144 if (hasProcessedEntity (persistentEntityFromProperty , processedEntities )) {
141145 return ;
142146 }
143- processedEntities .add (persistentEntityFromProperty );
144147
145- // save base/root entity/projection type to avoid recursion later
146- Class <?> pathRootType = propertyPath .getOwningType ().getType ();
147- if (mappingContext .hasPersistentEntityFor (pathRootType )) {
148- processedEntities .add (mappingContext .getPersistentEntity (pathRootType ));
149- }
148+ filteredProperties .put (propertyPath , true );
150149
151- takeAllPropertiesFromEntity (filteredProperties , propertyPath , mappingContext , persistentEntityFromProperty , processedEntities );
152150 }
153151
154152 private static boolean hasProcessedEntity (Neo4jPersistentEntity <?> persistentEntityFromProperty ,
155153 Collection <Neo4jPersistentEntity <?>> processedEntities ) {
156154
157155 return processedEntities .contains (persistentEntityFromProperty );
158156 }
159-
160- private static void takeAllPropertiesFromEntity (Collection <PropertyPath > filteredProperties ,
161- PropertyPath propertyPath , Neo4jMappingContext mappingContext ,
162- Neo4jPersistentEntity <?> persistentEntityFromProperty ,
163- Collection <Neo4jPersistentEntity <?>> processedEntities ) {
164-
165- filteredProperties .add (propertyPath );
166-
167- persistentEntityFromProperty .doWithAll (neo4jPersistentProperty -> {
168- addPropertiesFromEntity (filteredProperties , propertyPath .nested (neo4jPersistentProperty .getFieldName ()), mappingContext , processedEntities );
169- });
170- }
171-
172- private static void addPropertiesFromEntity (Collection <PropertyPath > filteredProperties , PropertyPath propertyPath ,
173- Neo4jMappingContext mappingContext ,
174- Collection <Neo4jPersistentEntity <?>> processedEntities ) {
175-
176- // break the recursion / cycles
177- if (filteredProperties .contains (propertyPath )) {
178- return ;
179- }
180- Class <?> propertyType = propertyPath .getLeafType ();
181- // simple types can get added directly to the list.
182- if (mappingContext .getConversionService ().isSimpleType (propertyType )) {
183- filteredProperties .add (propertyPath );
184- // Other types are handled also as entities because there cannot be any nested projection within a real entity.
185- } else if (mappingContext .hasPersistentEntityFor (propertyType )) {
186- addPropertiesFromEntity (filteredProperties , propertyPath , propertyType , mappingContext , processedEntities );
187- }
188- }
189157}
0 commit comments