|
61 | 61 | import java.util.ArrayList; |
62 | 62 | import java.util.Collections; |
63 | 63 | import java.util.LinkedHashMap; |
| 64 | +import java.util.LinkedHashSet; |
64 | 65 | import java.util.List; |
65 | 66 | import java.util.Map; |
66 | 67 | import java.util.Optional; |
| 68 | +import java.util.Set; |
67 | 69 | import java.util.concurrent.atomic.AtomicInteger; |
68 | 70 |
|
69 | 71 | import static graphql.Assert.assertNotNull; |
@@ -314,7 +316,7 @@ public TraversalControl visitGraphQLArgument(GraphQLArgument graphQLArgument, Tr |
314 | 316 | GraphQLFieldDefinition fieldDefinition = (GraphQLFieldDefinition) parentNode; |
315 | 317 | String fieldName = fieldDefinition.getName(); |
316 | 318 | GraphQLImplementingType implementingType = (GraphQLImplementingType) context.getParentContext().getParentNode(); |
317 | | - List<GraphQLFieldDefinition> matchingInterfaceFieldDefinitions = getMatchingInterfaceFieldDefinitions(fieldName, implementingType.getInterfaces()); |
| 319 | + Set<GraphQLFieldDefinition> matchingInterfaceFieldDefinitions = getSameFields(fieldName, implementingType.getName(), interfaceToImplementations, schema); |
318 | 320 | String newName; |
319 | 321 | if (matchingInterfaceFieldDefinitions.size() == 0) { |
320 | 322 | newName = "argument" + argumentCounter.getAndIncrement(); |
@@ -367,17 +369,15 @@ public TraversalControl visitGraphQLEnumValueDefinition(GraphQLEnumValueDefiniti |
367 | 369 |
|
368 | 370 | @Override |
369 | 371 | public TraversalControl visitGraphQLFieldDefinition(GraphQLFieldDefinition graphQLFieldDefinition, TraverserContext<GraphQLSchemaElement> context) { |
370 | | - String curName = graphQLFieldDefinition.getName(); |
| 372 | + String fieldName = graphQLFieldDefinition.getName(); |
371 | 373 | GraphQLImplementingType parentNode = (GraphQLImplementingType) context.getParentNode(); |
372 | | - List<GraphQLNamedOutputType> interfaces = parentNode.getInterfaces(); |
373 | | - List<GraphQLFieldDefinition> sameFields = getMatchingInterfaceFieldDefinitions(curName, interfaces); |
374 | | - sameFields.addAll(getMatchingImplementationsFieldDefinitions(parentNode.getName(), curName, interfaceToImplementations)); |
| 374 | + Set<GraphQLFieldDefinition> sameFields = getSameFields(fieldName, parentNode.getName(), interfaceToImplementations, schema); |
375 | 375 | String newName; |
376 | 376 | if (sameFields.size() == 0) { |
377 | 377 | newName = "field" + fieldCounter.getAndIncrement(); |
378 | 378 | } else { |
379 | | - if (newNameMap.containsKey(sameFields.get(0))) { |
380 | | - newName = newNameMap.get(sameFields.get(0)); |
| 379 | + if (newNameMap.containsKey(sameFields.iterator().next())) { |
| 380 | + newName = newNameMap.get(sameFields.iterator().next()); |
381 | 381 | } else { |
382 | 382 | newName = "field" + fieldCounter.getAndIncrement(); |
383 | 383 | for (GraphQLFieldDefinition fieldDefinition : sameFields) { |
@@ -453,39 +453,62 @@ public TraversalControl visitGraphQLUnionType(GraphQLUnionType graphQLUnionType, |
453 | 453 | return newNameMap; |
454 | 454 | } |
455 | 455 |
|
456 | | - private static List<GraphQLFieldDefinition> getMatchingInterfaceFieldDefinitions( |
457 | | - String curName, |
458 | | - List<GraphQLNamedOutputType> interfaces) { |
459 | | - List<GraphQLFieldDefinition> matchingInterfaceFieldDefinitions = new ArrayList<>(); |
460 | | - for (GraphQLNamedOutputType iface : interfaces) { |
461 | | - GraphQLInterfaceType interfaceType = (GraphQLInterfaceType) iface; |
462 | | - if (interfaceType.getFieldDefinition(curName) != null) { |
463 | | - matchingInterfaceFieldDefinitions.add(interfaceType.getFieldDefinition(curName)); |
464 | | - } |
465 | | - } |
466 | | - return matchingInterfaceFieldDefinitions; |
| 456 | + private static Set<GraphQLFieldDefinition> getSameFields(String fieldName, |
| 457 | + String objectOrInterfaceName, |
| 458 | + Map<String, List<GraphQLImplementingType>> interfaceToImplementations, |
| 459 | + GraphQLSchema schema |
| 460 | + ) { |
| 461 | + Set<GraphQLFieldDefinition> result = new LinkedHashSet<>(); |
| 462 | + Set<String> alreadyChecked = new LinkedHashSet<>(); |
| 463 | + getSameFieldsImpl(fieldName, objectOrInterfaceName, interfaceToImplementations, schema, alreadyChecked, result); |
| 464 | + return result; |
467 | 465 | } |
468 | 466 |
|
469 | | - private static List<GraphQLFieldDefinition> getMatchingImplementationsFieldDefinitions( |
470 | | - String interfaceName, |
471 | | - String fieldName, |
472 | | - Map<String, List<GraphQLImplementingType>> interfaceToImplementations) { |
473 | | - List<GraphQLFieldDefinition> result = new ArrayList<>(); |
474 | | - List<GraphQLImplementingType> implementations = interfaceToImplementations.get(interfaceName); |
| 467 | + private static void getSameFieldsImpl(String fieldName, |
| 468 | + String curObjectOrInterface, |
| 469 | + Map<String, List<GraphQLImplementingType>> interfaceToImplementations, |
| 470 | + GraphQLSchema schema, |
| 471 | + Set<String> alreadyChecked, |
| 472 | + Set<GraphQLFieldDefinition> result) { |
| 473 | + if (alreadyChecked.contains(curObjectOrInterface)) { |
| 474 | + return; |
| 475 | + } |
| 476 | + alreadyChecked.add(curObjectOrInterface); |
| 477 | + |
| 478 | + // "up": get all Interfaces |
| 479 | + GraphQLImplementingType type = (GraphQLImplementingType) schema.getType(curObjectOrInterface); |
| 480 | + List<GraphQLNamedOutputType> interfaces = type.getInterfaces(); |
| 481 | + getMatchingFieldDefinitions(fieldName, interfaces, result); |
| 482 | + for (GraphQLNamedOutputType interfaze : interfaces) { |
| 483 | + getSameFieldsImpl(fieldName, interfaze.getName(), interfaceToImplementations, schema, alreadyChecked, result); |
| 484 | + } |
| 485 | + |
| 486 | + // "down": get all Object or Interfaces |
| 487 | + List<GraphQLImplementingType> implementations = interfaceToImplementations.get(curObjectOrInterface); |
475 | 488 | if (implementations == null) { |
476 | | - return Collections.emptyList(); |
| 489 | + return; |
477 | 490 | } |
| 491 | + getMatchingFieldDefinitions(fieldName, implementations, result); |
478 | 492 | for (GraphQLImplementingType implementingType : implementations) { |
| 493 | + getSameFieldsImpl(fieldName, implementingType.getName(), interfaceToImplementations, schema, alreadyChecked, result); |
| 494 | + } |
| 495 | + } |
| 496 | + |
| 497 | + private static void getMatchingFieldDefinitions( |
| 498 | + String fieldName, |
| 499 | + List<? extends GraphQLType> interfaces, |
| 500 | + Set<GraphQLFieldDefinition> result) { |
| 501 | + for (GraphQLType iface : interfaces) { |
| 502 | + GraphQLImplementingType implementingType = (GraphQLImplementingType) iface; |
479 | 503 | if (implementingType.getFieldDefinition(fieldName) != null) { |
480 | 504 | result.add(implementingType.getFieldDefinition(fieldName)); |
481 | 505 | } |
482 | 506 | } |
483 | | - return result; |
484 | 507 | } |
485 | 508 |
|
486 | 509 | private static List<GraphQLArgument> getMatchingArgumentDefinitions( |
487 | 510 | String name, |
488 | | - List<GraphQLFieldDefinition> fieldDefinitions) { |
| 511 | + Set<GraphQLFieldDefinition> fieldDefinitions) { |
489 | 512 | List<GraphQLArgument> result = new ArrayList<>(); |
490 | 513 | for (GraphQLFieldDefinition fieldDefinition : fieldDefinitions) { |
491 | 514 | Optional.ofNullable(fieldDefinition.getArgument(name)).map(result::add); |
|
0 commit comments