Skip to content

Commit 0042f01

Browse files
committed
Optimize transforms and validators
This commit optimizes two ModelTransformPlugin implementations and one Validator plugin to use fewer intermediate objects and streams.
1 parent eefce0b commit 0042f01

File tree

4 files changed

+185
-121
lines changed

4 files changed

+185
-121
lines changed

smithy-model/src/main/java/software/amazon/smithy/model/transform/plugins/CleanOperationStructures.java

Lines changed: 45 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@
77
import java.util.ArrayList;
88
import java.util.Collection;
99
import java.util.HashSet;
10+
import java.util.List;
1011
import java.util.Set;
11-
import java.util.stream.Collectors;
12-
import java.util.stream.Stream;
1312
import software.amazon.smithy.model.Model;
1413
import software.amazon.smithy.model.shapes.OperationShape;
1514
import software.amazon.smithy.model.shapes.Shape;
@@ -28,42 +27,67 @@ public Model onRemove(ModelTransformer transformer, Collection<Shape> removed, M
2827
}
2928

3029
private Collection<Shape> getModifiedOperations(Model model, Collection<Shape> removed) {
31-
return model.shapes(OperationShape.class)
32-
.flatMap(operation -> {
33-
OperationShape result = transformErrors(removed, operation);
34-
result = transformInput(removed, result);
35-
result = transformOutput(removed, result);
36-
return result.equals(operation) ? Stream.empty() : Stream.of(result);
37-
})
38-
.collect(Collectors.toList());
30+
List<Shape> modifiedShapes = new ArrayList<>();
31+
for (OperationShape operation : model.getOperationShapes()) {
32+
OperationShape.Builder builder = transformInput(removed, operation);
33+
builder = transformOutput(removed, operation, builder);
34+
builder = transformErrors(removed, operation, builder);
35+
if (builder != null) {
36+
modifiedShapes.add(builder.build());
37+
}
38+
}
39+
return modifiedShapes;
3940
}
4041

41-
private OperationShape transformInput(Collection<Shape> removed, OperationShape operation) {
42+
private OperationShape.Builder transformInput(
43+
Collection<Shape> removed,
44+
OperationShape operation
45+
) {
4246
for (Shape remove : removed) {
4347
if (remove.getId().equals(operation.getInputShape())) {
44-
return operation.toBuilder().input(null).build();
48+
OperationShape.Builder builder = operation.toBuilder();
49+
builder.input(null);
50+
return builder;
4551
}
4652
}
47-
return operation;
53+
return null;
4854
}
4955

50-
private OperationShape transformOutput(Collection<Shape> removed, OperationShape operation) {
56+
private OperationShape.Builder transformOutput(
57+
Collection<Shape> removed,
58+
OperationShape operation,
59+
OperationShape.Builder builder
60+
) {
5161
for (Shape remove : removed) {
5262
if (remove.getId().equals(operation.getOutputShape())) {
53-
return operation.toBuilder().output(null).build();
63+
if (builder == null) {
64+
builder = operation.toBuilder();
65+
}
66+
builder.output(null);
67+
return builder;
5468
}
5569
}
56-
return operation;
70+
return builder;
5771
}
5872

59-
private OperationShape transformErrors(Collection<Shape> removed, OperationShape operation) {
73+
private OperationShape.Builder transformErrors(
74+
Collection<Shape> removed,
75+
OperationShape operation,
76+
OperationShape.Builder builder
77+
) {
6078
Set<ShapeId> errors = new HashSet<>(operation.getErrors());
61-
removed.forEach(shape -> errors.remove(shape.getId()));
79+
for (Shape remove : removed) {
80+
errors.remove(remove.getId());
81+
}
6282

63-
if (new ArrayList<>(errors).equals(operation.getErrors())) {
64-
return operation;
83+
if (errors.size() != operation.getErrors().size()) {
84+
if (builder == null) {
85+
builder = operation.toBuilder();
86+
}
87+
builder.errors(errors);
88+
return builder;
6589
}
6690

67-
return operation.toBuilder().errors(errors).build();
91+
return builder;
6892
}
6993
}

smithy-model/src/main/java/software/amazon/smithy/model/transform/plugins/CleanStructureAndUnionMembers.java

Lines changed: 50 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,15 @@
44
*/
55
package software.amazon.smithy.model.transform.plugins;
66

7-
import static java.util.stream.Collectors.groupingBy;
8-
import static java.util.stream.Collectors.mapping;
9-
107
import java.util.ArrayList;
118
import java.util.Collection;
9+
import java.util.HashMap;
1210
import java.util.HashSet;
1311
import java.util.List;
1412
import java.util.Map;
1513
import java.util.Optional;
1614
import java.util.Set;
1715
import java.util.function.Function;
18-
import java.util.stream.Collectors;
1916
import software.amazon.smithy.model.Model;
2017
import software.amazon.smithy.model.shapes.EnumShape;
2118
import software.amazon.smithy.model.shapes.IntEnumShape;
@@ -26,8 +23,6 @@
2623
import software.amazon.smithy.model.shapes.UnionShape;
2724
import software.amazon.smithy.model.transform.ModelTransformer;
2825
import software.amazon.smithy.model.transform.ModelTransformerPlugin;
29-
import software.amazon.smithy.utils.OptionalUtils;
30-
import software.amazon.smithy.utils.Pair;
3126

3227
/**
3328
* Cleans up structure, union, enum, and intEnum shapes after shapes are removed.
@@ -59,31 +54,39 @@ private Model removeMembersFromContainers(ModelTransformer transformer, Collecti
5954
private Collection<Shape> getEnumReplacements(Model model, Collection<Shape> removed) {
6055
return createUpdatedShapes(model, removed, Shape::asEnumShape, entry -> {
6156
EnumShape.Builder builder = entry.getKey().toBuilder();
62-
entry.getValue().forEach(member -> builder.removeMember(member.getMemberName()));
57+
for (MemberShape member : entry.getValue()) {
58+
builder.removeMember(member.getMemberName());
59+
}
6360
return builder.build();
6461
});
6562
}
6663

6764
private Collection<Shape> getIntEnumReplacements(Model model, Collection<Shape> removed) {
6865
return createUpdatedShapes(model, removed, Shape::asIntEnumShape, entry -> {
6966
IntEnumShape.Builder builder = entry.getKey().toBuilder();
70-
entry.getValue().forEach(member -> builder.removeMember(member.getMemberName()));
67+
for (MemberShape member : entry.getValue()) {
68+
builder.removeMember(member.getMemberName());
69+
}
7170
return builder.build();
7271
});
7372
}
7473

7574
private Collection<Shape> getStructureReplacements(Model model, Collection<Shape> removed) {
7675
return createUpdatedShapes(model, removed, Shape::asStructureShape, entry -> {
7776
StructureShape.Builder builder = entry.getKey().toBuilder();
78-
entry.getValue().forEach(member -> builder.removeMember(member.getMemberName()));
77+
for (MemberShape member : entry.getValue()) {
78+
builder.removeMember(member.getMemberName());
79+
}
7980
return builder.build();
8081
});
8182
}
8283

8384
private Collection<Shape> getUnionReplacements(Model model, Collection<Shape> removed) {
8485
return createUpdatedShapes(model, removed, Shape::asUnionShape, entry -> {
8586
UnionShape.Builder builder = entry.getKey().toBuilder();
86-
entry.getValue().forEach(member -> builder.removeMember(member.getMemberName()));
87+
for (MemberShape member : entry.getValue()) {
88+
builder.removeMember(member.getMemberName());
89+
}
8790
return builder.build();
8891
});
8992
}
@@ -115,16 +118,24 @@ private <S extends Shape> Collection<Shape> createUpdatedShapes(
115118
Function<Shape, Optional<S>> containerShapeMapper,
116119
Function<Map.Entry<S, List<MemberShape>>, S> entryMapperAndFactory
117120
) {
118-
return removed.stream()
119-
.flatMap(shape -> OptionalUtils.stream(shape.asMemberShape()))
120-
.flatMap(member -> OptionalUtils.stream(model.getShape(member.getContainer())
121-
.flatMap(containerShapeMapper)
122-
.map(container -> Pair.of(container, member))))
123-
.collect(groupingBy(Pair::getLeft, mapping(Pair::getRight, Collectors.toList())))
124-
.entrySet()
125-
.stream()
126-
.map(entryMapperAndFactory)
127-
.collect(Collectors.toList());
121+
Map<S, List<MemberShape>> containerMemberMap = new HashMap<>();
122+
for (Shape shape : removed) {
123+
if (!shape.isMemberShape()) {
124+
continue;
125+
}
126+
127+
MemberShape member = (MemberShape) shape;
128+
Optional<S> container = model.getShape(member.getContainer()).flatMap(containerShapeMapper);
129+
if (container.isPresent()) {
130+
containerMemberMap.computeIfAbsent(container.get(), k -> new ArrayList<>()).add(member);
131+
}
132+
}
133+
134+
Collection<Shape> updatedShapes = new ArrayList<>();
135+
for (Map.Entry<S, List<MemberShape>> entry : containerMemberMap.entrySet()) {
136+
updatedShapes.add(entryMapperAndFactory.apply(entry));
137+
}
138+
return updatedShapes;
128139
}
129140

130141
/**
@@ -137,16 +148,26 @@ private <S extends Shape> Collection<Shape> createUpdatedShapes(
137148
* their target was removed.
138149
*/
139150
private Collection<Shape> findMembersThatNeedRemoval(Model model, Collection<Shape> removed) {
140-
Set<ShapeId> removedIds = removed.stream().map(Shape::getId).collect(Collectors.toSet());
151+
Set<ShapeId> removedIds = new HashSet<>();
152+
for (Shape shape : removed) {
153+
removedIds.add(shape.getId());
154+
}
155+
141156
Collection<Shape> removeMembers = new HashSet<>();
142-
model.shapes(StructureShape.class)
143-
.flatMap(shape -> shape.getAllMembers().values().stream())
144-
.filter(value -> removedIds.contains(value.getTarget()))
145-
.forEach(removeMembers::add);
146-
model.shapes(UnionShape.class)
147-
.flatMap(shape -> shape.getAllMembers().values().stream())
148-
.filter(value -> removedIds.contains(value.getTarget()))
149-
.forEach(removeMembers::add);
157+
for (StructureShape structure : model.getStructureShapes()) {
158+
for (MemberShape member : structure.members()) {
159+
if (removedIds.contains(member.getTarget())) {
160+
removeMembers.add(member);
161+
}
162+
}
163+
}
164+
for (UnionShape structure : model.getUnionShapes()) {
165+
for (MemberShape member : structure.members()) {
166+
if (removedIds.contains(member.getTarget())) {
167+
removeMembers.add(member);
168+
}
169+
}
170+
}
150171
return removeMembers;
151172
}
152173
}

0 commit comments

Comments
 (0)