Skip to content

Commit e12d906

Browse files
authored
Merge pull request #82 from intuit/optimize-svc-metadata
optimize service metadata implementation
2 parents 05db9ca + 19005b7 commit e12d906

File tree

12 files changed

+300
-180
lines changed

12 files changed

+300
-180
lines changed

src/main/java/com/intuit/graphql/orchestrator/federation/metadata/FederationMetadata.java

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import com.intuit.graphql.graphQL.FieldDefinition;
66
import com.intuit.graphql.graphQL.TypeDefinition;
77
import com.intuit.graphql.orchestrator.ServiceProvider;
8-
import com.intuit.graphql.orchestrator.schema.ServiceMetadata;
98
import graphql.language.Field;
109
import graphql.schema.FieldCoordinates;
1110
import java.util.HashMap;
@@ -25,19 +24,23 @@
2524
@Getter
2625
public class FederationMetadata {
2726

28-
private final ServiceMetadata serviceMetadata;
27+
private final ServiceProvider serviceProvider;
2928

30-
/** entities owned by the service */
29+
/**
30+
* entities owned by the service
31+
*/
3132
private final Map<String, EntityMetadata> entitiesByTypename = new HashMap<>();
3233

33-
/** entities extended by the service */
34+
/**
35+
* entities extended by the service
36+
*/
3437
private final Map<String, EntityExtensionMetadata> extensionsByTypename = new HashMap<>();
3538

3639
private final Map<FieldCoordinates, Set<Field>> requiresFieldSetByCoordinate = new HashMap<>();
3740

38-
public FederationMetadata(ServiceMetadata serviceMetadata) {
39-
Objects.requireNonNull(serviceMetadata);
40-
this.serviceMetadata = serviceMetadata;
41+
public FederationMetadata(ServiceProvider serviceProvider) {
42+
Objects.requireNonNull(serviceProvider);
43+
this.serviceProvider = serviceProvider;
4144
}
4245

4346
public boolean isFieldExternal(FieldCoordinates fieldCoordinates) {
@@ -72,10 +75,15 @@ public Set<Field> getRequireFields(FieldCoordinates fieldCoordinates) {
7275
@Builder
7376
@Getter
7477
public static class EntityMetadata {
75-
@NonNull private final String typeName;
76-
@NonNull private final List<KeyDirectiveMetadata> keyDirectives;
77-
@NonNull private final Set<String> fields;
78-
@NonNull private final FederationMetadata federationMetadata;
78+
79+
@NonNull
80+
private final String typeName;
81+
@NonNull
82+
private final List<KeyDirectiveMetadata> keyDirectives;
83+
@NonNull
84+
private final Set<String> fields;
85+
@NonNull
86+
private final FederationMetadata federationMetadata;
7987

8088
public static Set<String> getFieldsFrom(TypeDefinition entityDefinition) {
8189
Set<String> output = new HashSet<>(); // make sure HashSet is used
@@ -89,10 +97,15 @@ public static Set<String> getFieldsFrom(TypeDefinition entityDefinition) {
8997
@Builder
9098
@Getter
9199
public static class EntityExtensionMetadata {
92-
@NonNull private final String typeName;
93-
@NonNull private final List<KeyDirectiveMetadata> keyDirectives;
94-
@NonNull private final Map<String, Set<Field>> requiredFieldsByFieldName;
95-
@NonNull private final FederationMetadata federationMetadata;
100+
101+
@NonNull
102+
private final String typeName;
103+
@NonNull
104+
private final List<KeyDirectiveMetadata> keyDirectives;
105+
@NonNull
106+
private final Map<String, Set<Field>> requiredFieldsByFieldName;
107+
@NonNull
108+
private final FederationMetadata federationMetadata;
96109
// TODO @provides
97110

98111
private EntityMetadata baseEntityMetadata;
@@ -112,13 +125,12 @@ public void setBaseEntityMetadata(EntityMetadata baseEntityMetadata) {
112125
}
113126

114127
public ServiceProvider getServiceProvider() {
115-
return this.federationMetadata.getServiceMetadata().getServiceProvider();
128+
return this.federationMetadata.getServiceProvider();
116129
}
117130

118131
public ServiceProvider getBaseServiceProvider() {
119132
return this.baseEntityMetadata
120133
.getFederationMetadata()
121-
.getServiceMetadata()
122134
.getServiceProvider();
123135
}
124136

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
package com.intuit.graphql.orchestrator.schema;
2+
3+
import static java.util.Objects.requireNonNull;
4+
5+
import com.intuit.graphql.orchestrator.ServiceProvider;
6+
import com.intuit.graphql.orchestrator.federation.metadata.FederationMetadata;
7+
import com.intuit.graphql.orchestrator.schema.transform.FieldResolverContext;
8+
import graphql.schema.FieldCoordinates;
9+
import java.util.HashMap;
10+
import java.util.Map;
11+
import java.util.Optional;
12+
import lombok.Getter;
13+
14+
@Getter
15+
public class ServiceMetadataImpl implements ServiceMetadata {
16+
17+
private final Map<String, TypeMetadata> typeMetadataMap;
18+
private final ServiceProvider serviceProvider;
19+
private final FederationMetadata federationMetadata;
20+
private final boolean hasInterfaceOrUnion;
21+
private final boolean hasFieldResolverDefinition;
22+
23+
private ServiceMetadataImpl(Builder builder) {
24+
typeMetadataMap = builder.typeMetadataMap;
25+
serviceProvider = requireNonNull(builder.serviceProvider);
26+
federationMetadata = builder.federationMetadata;
27+
hasInterfaceOrUnion = builder.hasInterfaceOrUnion;
28+
hasFieldResolverDefinition = builder.hasFieldResolverDefinition;
29+
}
30+
31+
public static Builder newBuilder() {
32+
return new Builder();
33+
}
34+
35+
public static Builder newBuilder(ServiceMetadataImpl copy) {
36+
Builder builder = new Builder();
37+
builder.typeMetadataMap = copy.getTypeMetadataMap();
38+
builder.serviceProvider = copy.getServiceProvider();
39+
builder.federationMetadata = copy.getFederationMetadata();
40+
builder.hasInterfaceOrUnion = copy.isHasInterfaceOrUnion();
41+
builder.hasFieldResolverDefinition = copy.isHasFieldResolverDefinition();
42+
return builder;
43+
}
44+
45+
@Override
46+
public boolean hasType(String typeName) {
47+
return this.typeMetadataMap.containsKey(typeName);
48+
}
49+
50+
@Override
51+
public boolean requiresTypenameInjection() {
52+
return this.hasInterfaceOrUnion;
53+
}
54+
55+
@Override
56+
public boolean hasFieldResolverDirective() {
57+
return this.hasFieldResolverDefinition;
58+
}
59+
60+
@Override
61+
public boolean isFederationService() {
62+
return this.serviceProvider.isFederationProvider();
63+
}
64+
65+
@Override
66+
public boolean shouldRemoveExternalFields() {
67+
return this.hasFieldResolverDirective() || this.isFederationService();
68+
}
69+
70+
71+
@Override
72+
public ServiceProvider getServiceProvider() {
73+
return this.serviceProvider;
74+
}
75+
76+
@Override
77+
public FieldResolverContext getFieldResolverContext(FieldCoordinates fieldCoordinates) {
78+
return Optional.ofNullable(this.typeMetadataMap.get(fieldCoordinates.getTypeName()))
79+
.map(typeMetadata -> typeMetadata.getFieldResolverContext(fieldCoordinates.getFieldName()))
80+
.orElse(null);
81+
}
82+
83+
@Override
84+
public boolean isOwnedByEntityExtension(FieldCoordinates fieldCoordinates) {
85+
return this.serviceProvider.isFederationProvider() && federationMetadata.isFieldExternal(fieldCoordinates);
86+
}
87+
88+
89+
@Override
90+
public boolean isEntity(String typename) {
91+
return this.isFederationService() && this.federationMetadata.isEntity(typename);
92+
}
93+
94+
@Override
95+
public FederationMetadata getFederationServiceMetadata() {
96+
return federationMetadata;
97+
}
98+
99+
100+
public static final class Builder {
101+
102+
private Map<String, TypeMetadata> typeMetadataMap = new HashMap<>();
103+
private ServiceProvider serviceProvider;
104+
private FederationMetadata federationMetadata;
105+
private boolean hasInterfaceOrUnion;
106+
private boolean hasFieldResolverDefinition;
107+
108+
private Builder() {
109+
}
110+
111+
public Builder typeMetadataMap(Map<String, TypeMetadata> val) {
112+
typeMetadataMap = val;
113+
return this;
114+
}
115+
116+
public Builder serviceProvider(ServiceProvider val) {
117+
serviceProvider = val;
118+
return this;
119+
}
120+
121+
public Builder federationMetadata(FederationMetadata val) {
122+
federationMetadata = val;
123+
return this;
124+
}
125+
126+
public Builder hasInterfaceOrUnion(boolean val) {
127+
hasInterfaceOrUnion = val;
128+
return this;
129+
}
130+
131+
public Builder hasFieldResolverDefinition(boolean val) {
132+
hasFieldResolverDefinition = val;
133+
return this;
134+
}
135+
136+
public ServiceMetadataImpl build() {
137+
return new ServiceMetadataImpl(this);
138+
}
139+
}
140+
}

src/main/java/com/intuit/graphql/orchestrator/schema/fold/XtextGraphFolder.java

Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
package com.intuit.graphql.orchestrator.schema.fold;
22

3+
import static com.intuit.graphql.orchestrator.schema.fold.FieldMergeValidations.checkMergeEligibility;
4+
import static com.intuit.graphql.orchestrator.utils.DescriptionUtils.mergeDescriptions;
5+
import static com.intuit.graphql.orchestrator.xtext.DataFetcherContext.STATIC_DATAFETCHER_CONTEXT;
6+
import static com.intuit.graphql.orchestrator.xtext.GraphQLFactoryDelegate.createObjectType;
7+
import static com.intuit.graphql.utils.XtextTypeUtils.unwrapAll;
8+
39
import com.intuit.graphql.graphQL.EnumTypeDefinition;
410
import com.intuit.graphql.graphQL.EnumValueDefinition;
511
import com.intuit.graphql.graphQL.FieldDefinition;
@@ -19,9 +25,6 @@
1925
import com.intuit.graphql.orchestrator.xtext.FieldContext;
2026
import com.intuit.graphql.orchestrator.xtext.XtextGraph;
2127
import com.intuit.graphql.utils.XtextTypeUtils;
22-
import org.eclipse.emf.common.util.EList;
23-
import org.eclipse.emf.ecore.util.EcoreUtil;
24-
2528
import java.util.Collection;
2629
import java.util.EnumMap;
2730
import java.util.HashMap;
@@ -30,12 +33,8 @@
3033
import java.util.Optional;
3134
import java.util.Set;
3235
import java.util.stream.Collectors;
33-
34-
import static com.intuit.graphql.orchestrator.schema.fold.FieldMergeValidations.checkMergeEligibility;
35-
import static com.intuit.graphql.orchestrator.utils.DescriptionUtils.mergeDescriptions;
36-
import static com.intuit.graphql.orchestrator.xtext.DataFetcherContext.STATIC_DATAFETCHER_CONTEXT;
37-
import static com.intuit.graphql.orchestrator.xtext.GraphQLFactoryDelegate.createObjectType;
38-
import static com.intuit.graphql.utils.XtextTypeUtils.unwrapAll;
36+
import org.eclipse.emf.common.util.EList;
37+
import org.eclipse.emf.ecore.util.EcoreUtil;
3938

4039
public class XtextGraphFolder implements Foldable<XtextGraph> {
4140

@@ -69,18 +68,21 @@ private XtextGraph merge(XtextGraph accumulator, XtextGraph current) {
6968
merge(accumulator.getOperationType(op), current.getOperationType(op), current.getServiceProvider()));
7069
}
7170

72-
if(current.isFederationService()) {
71+
if (current.getServiceProvider().isFederationProvider()) {
7372
current.getValueTypesByName().values()
74-
.forEach(incomingSharedType -> {
75-
TypeDefinition preexistingTypeDefinition = accumulator.getType(incomingSharedType.getName());
76-
if(incomingSharedType instanceof EnumTypeDefinition) {
77-
mergeSharedValueType((EnumTypeDefinition) preexistingTypeDefinition, (EnumTypeDefinition) incomingSharedType, current.getServiceProvider());
78-
} else if(incomingSharedType instanceof ObjectTypeDefinition) {
79-
mergeSharedValueType((ObjectTypeDefinition) preexistingTypeDefinition, (ObjectTypeDefinition) incomingSharedType, current.getServiceProvider());
80-
} else if(incomingSharedType instanceof InterfaceTypeDefinition) {
81-
mergeSharedValueType((InterfaceTypeDefinition) preexistingTypeDefinition, (InterfaceTypeDefinition) incomingSharedType, current.getServiceProvider());
82-
}
83-
});
73+
.forEach(incomingSharedType -> {
74+
TypeDefinition preexistingTypeDefinition = accumulator.getType(incomingSharedType.getName());
75+
if (incomingSharedType instanceof EnumTypeDefinition) {
76+
mergeSharedValueType((EnumTypeDefinition) preexistingTypeDefinition,
77+
(EnumTypeDefinition) incomingSharedType, current.getServiceProvider());
78+
} else if (incomingSharedType instanceof ObjectTypeDefinition) {
79+
mergeSharedValueType((ObjectTypeDefinition) preexistingTypeDefinition,
80+
(ObjectTypeDefinition) incomingSharedType, current.getServiceProvider());
81+
} else if (incomingSharedType instanceof InterfaceTypeDefinition) {
82+
mergeSharedValueType((InterfaceTypeDefinition) preexistingTypeDefinition,
83+
(InterfaceTypeDefinition) incomingSharedType, current.getServiceProvider());
84+
}
85+
});
8486
}
8587

8688
resolveTypeConflicts(accumulator.getTypes(), current.getTypes(), current);
@@ -118,7 +120,8 @@ private void resolveTypeConflicts(final Map<String, TypeDefinition> existing,
118120
TypeDefinition existingType = existing.get(typeName);
119121
if (Objects.nonNull(existingType) && !nestedTypes.containsKey(existingType.getName())) {
120122
TypeDefinition conflictingType = current.get(typeName);
121-
XtextTypeConflictResolver.INSTANCE.resolve(conflictingType, existingType, currentGraph.getServiceProvider().isFederationProvider());
123+
XtextTypeConflictResolver.INSTANCE
124+
.resolve(conflictingType, existingType, currentGraph.getServiceProvider().isFederationProvider());
122125
}
123126
}
124127
}
@@ -170,7 +173,7 @@ private ObjectTypeDefinition merge(ObjectTypeDefinition current, ObjectTypeDefin
170173
* @return merged object
171174
*/
172175
private TypeDefinition mergeSharedValueType(EnumTypeDefinition current, EnumTypeDefinition newComer,
173-
ServiceProvider newComerServiceProvider) {
176+
ServiceProvider newComerServiceProvider) {
174177
//nothing to merge
175178
if (current == null || !newComerServiceProvider.isFederationProvider()) {
176179
return current;
@@ -194,15 +197,15 @@ private TypeDefinition mergeSharedValueType(EnumTypeDefinition current, EnumType
194197
}
195198

196199
private TypeDefinition mergeSharedValueType(ObjectTypeDefinition current, ObjectTypeDefinition newComer,
197-
ServiceProvider newComerServiceProvider) {
200+
ServiceProvider newComerServiceProvider) {
198201
if (current == null || !newComerServiceProvider.isFederationProvider()) {
199202
return current;
200203
}
201204

202205
newComer.getFieldDefinition().forEach(newField -> {
203206
Optional<FieldDefinition> currentField = current.getFieldDefinition().stream()
204-
.filter(fieldName -> newField.getName().equals(fieldName.getName()))
205-
.findFirst();
207+
.filter(fieldName -> newField.getName().equals(fieldName.getName()))
208+
.findFirst();
206209

207210
if (!currentField.isPresent()) {
208211
addNewFieldToObject(current, newField, newComerServiceProvider);
@@ -217,15 +220,15 @@ private TypeDefinition mergeSharedValueType(ObjectTypeDefinition current, Object
217220
}
218221

219222
private TypeDefinition mergeSharedValueType(InterfaceTypeDefinition current, InterfaceTypeDefinition newComer,
220-
ServiceProvider newComerServiceProvider) {
223+
ServiceProvider newComerServiceProvider) {
221224
if (current == null || !newComerServiceProvider.isFederationProvider()) {
222225
return current;
223226
}
224227

225228
newComer.getFieldDefinition().forEach(newField -> {
226229
Optional<FieldDefinition> currentField = current.getFieldDefinition().stream()
227-
.filter(fieldName -> newField.getName().equals(fieldName.getName()))
228-
.findFirst();
230+
.filter(fieldName -> newField.getName().equals(fieldName.getName()))
231+
.findFirst();
229232

230233
if (!currentField.isPresent()) {
231234
addNewFieldToObject(current, newField, newComerServiceProvider);
@@ -281,13 +284,13 @@ private void addNewFieldToObject(ObjectTypeDefinition objectTypeDefinition, Fiel
281284

282285

283286
private void addNewFieldToObject(EnumTypeDefinition enumTypeDefinition, EnumValueDefinition valueDefinition,
284-
ServiceProvider serviceProvider) {
287+
ServiceProvider serviceProvider) {
285288
addFieldContextToRegistry(enumTypeDefinition.getName(), valueDefinition.getEnumValue(), serviceProvider);
286289
enumTypeDefinition.getEnumValueDefinition().add(EcoreUtil.copy(valueDefinition));
287290
}
288291

289292
private void addNewFieldToObject(InterfaceTypeDefinition interfaceTypeDefinition, FieldDefinition fieldDefinition,
290-
ServiceProvider serviceProvider) {
293+
ServiceProvider serviceProvider) {
291294
addFieldContextToRegistry(interfaceTypeDefinition.getName(), fieldDefinition.getName(), serviceProvider);
292295
interfaceTypeDefinition.getFieldDefinition().add(EcoreUtil.copy(fieldDefinition));
293296
}
@@ -297,7 +300,7 @@ private void addFieldContextToRegistry(String parentName, String definitionName,
297300
final FieldContext fieldContext = new FieldContext(parentName, definitionName);
298301

299302
accCodeRegistry.put(fieldContext, DataFetcherContext.newBuilder().namespace(serviceProvider.getNameSpace())
300-
.serviceType(serviceProvider.getSeviceType()).build());
303+
.serviceType(serviceProvider.getSeviceType()).build());
301304
}
302305

303306
/**

0 commit comments

Comments
 (0)