Skip to content

Commit

Permalink
ShapeIndex is not adding any value as a separate abstraction from
Browse files Browse the repository at this point in the history
Model. Separating ShapeIndex from Model made building models much more
verbose, interacting with shapes in a model more verbose, updating
models verbose, and caused an awkward API if you need to access things
like knowledge indexes but only have access to a ShapeIndex (knowledge
indexes are only on models).

This commit first deprecates all ShapeIndex APIs and provides
alternatives that are to be used instead. In some cases, the
alternative, Model based APIs, still call into the deprecated ShapeIndex
APIs. This is because a Model always has a ShapeIndex but a ShapeIndex
is not a model, and it cuts down on code duplication. In the next
version bump (likely 0.10.0), we will remove the ShapeIndex APIs
altogether.
  • Loading branch information
mtdowling committed Nov 25, 2019
1 parent 80543b3 commit 9d9831a
Show file tree
Hide file tree
Showing 184 changed files with 1,202 additions and 1,126 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import software.amazon.smithy.model.Model;
import software.amazon.smithy.model.knowledge.HttpBinding;
import software.amazon.smithy.model.knowledge.HttpBindingIndex;
import software.amazon.smithy.model.knowledge.TopDownIndex;
import software.amazon.smithy.model.node.ArrayNode;
import software.amazon.smithy.model.node.Node;
import software.amazon.smithy.model.shapes.ShapeIndex;
import software.amazon.smithy.model.traits.MediaTypeTrait;
import software.amazon.smithy.openapi.fromsmithy.Context;
import software.amazon.smithy.openapi.fromsmithy.OpenApiMapper;
Expand Down Expand Up @@ -63,24 +63,24 @@ public OpenApi after(Context context, OpenApi openApi) {
}

private Stream<String> supportedMediaTypes(Context context) {
ShapeIndex shapeIndex = context.getModel().getShapeIndex();
Model model = context.getModel();
HttpBindingIndex httpBindingIndex = context.getModel().getKnowledge(HttpBindingIndex.class);
TopDownIndex topDownIndex = context.getModel().getKnowledge(TopDownIndex.class);

// Find the media types defined on all request and response bindings.
return topDownIndex.getContainedOperations(context.getService()).stream()
.flatMap(operation -> Stream.concat(
OptionalUtils.stream(
binaryMediaType(shapeIndex, httpBindingIndex.getRequestBindings(operation))),
binaryMediaType(model, httpBindingIndex.getRequestBindings(operation))),
OptionalUtils.stream(
binaryMediaType(shapeIndex, httpBindingIndex.getResponseBindings(operation)))));
binaryMediaType(model, httpBindingIndex.getResponseBindings(operation)))));
}

private Optional<String> binaryMediaType(ShapeIndex shapes, Map<String, HttpBinding> httpBindings) {
private Optional<String> binaryMediaType(Model model, Map<String, HttpBinding> httpBindings) {
return httpBindings.values().stream()
.filter(binding -> binding.getLocation().equals(HttpBinding.Location.PAYLOAD))
.map(HttpBinding::getMember)
.flatMap(member -> OptionalUtils.stream(member.getMemberTrait(shapes, MediaTypeTrait.class)))
.flatMap(member -> OptionalUtils.stream(member.getMemberTrait(model, MediaTypeTrait.class)))
.map(MediaTypeTrait::getValue)
.findFirst();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public OperationObject updateOperation(Context context, OperationShape shape, Op
@Override
public OpenApi after(Context context, OpenApi openapi) {
// Find each known request validator on operation shapes.
Set<String> validators = context.getModel().getShapeIndex().shapes(OperationShape.class)
Set<String> validators = context.getModel().shapes(OperationShape.class)
.flatMap(shape -> OptionalUtils.stream(shape.getTrait(RequestValidatorTrait.class)))
.map(RequestValidatorTrait::getValue)
.filter(KNOWN_VALIDATORS::containsKey)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,14 @@ public final class ArnIndex implements KnowledgeIndex {

public ArnIndex(Model model) {
// Pre-compute the ARN services.
arnServices = unmodifiableMap(model.getShapeIndex().shapes(ServiceShape.class)
arnServices = unmodifiableMap(model.shapes(ServiceShape.class)
.flatMap(shape -> Trait.flatMapStream(shape, ServiceTrait.class))
.map(pair -> Pair.of(pair.getLeft().getId(), resolveServiceArn(pair)))
.collect(Collectors.toMap(Pair::getLeft, Pair::getRight)));

// Pre-compute all of the ArnTemplates in a service shape.
TopDownIndex topDownIndex = model.getKnowledge(TopDownIndex.class);
List<ServiceShape> services = model.getShapeIndex().shapes(ServiceShape.class)
List<ServiceShape> services = model.shapes(ServiceShape.class)
.filter(shape -> shape.hasTrait(ServiceTrait.class))
.collect(Collectors.toList());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import software.amazon.smithy.model.shapes.ResourceShape;
import software.amazon.smithy.model.shapes.ServiceShape;
import software.amazon.smithy.model.shapes.Shape;
import software.amazon.smithy.model.shapes.ShapeIndex;
import software.amazon.smithy.model.traits.Trait;
import software.amazon.smithy.model.validation.AbstractValidator;
import software.amazon.smithy.model.validation.ValidationEvent;
Expand All @@ -46,16 +45,16 @@ public final class ArnTemplateValidator extends AbstractValidator {
@Override
public List<ValidationEvent> validate(Model model) {
ArnIndex arnIndex = model.getKnowledge(ArnIndex.class);
return model.getShapeIndex().shapes(ServiceShape.class)
return model.shapes(ServiceShape.class)
.flatMap(service -> Trait.flatMapStream(service, ServiceTrait.class))
.flatMap(pair -> validateService(model.getShapeIndex(), arnIndex, pair.getLeft()))
.flatMap(pair -> validateService(model, arnIndex, pair.getLeft()))
.collect(toList());
}

private Stream<ValidationEvent> validateService(ShapeIndex index, ArnIndex arnIndex, ServiceShape service) {
private Stream<ValidationEvent> validateService(Model model, ArnIndex arnIndex, ServiceShape service) {
// Make sure each ARN template contains relevant identifiers.
return arnIndex.getServiceResourceArns(service.getId()).entrySet().stream()
.flatMap(entry -> OptionalUtils.stream(index.getShape(entry.getKey())
.flatMap(entry -> OptionalUtils.stream(model.getShape(entry.getKey())
.flatMap(Shape::asResourceShape)
.map(resource -> Pair.of(resource, entry.getValue()))))
.flatMap(pair -> validateResourceArn(pair.getLeft(), pair.getRight()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ private enum Plane { CONTROL, DATA }
public PlaneIndex(Model model) {
pathFinder = PathFinder.create(model);

model.getShapeIndex().shapes(ServiceShape.class).forEach(service -> {
model.shapes(ServiceShape.class).forEach(service -> {
Plane plane = extractPlane(service);
if (plane != null) {
servicePlanes.put(service.getId(), plane);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public final class SdkServiceIdValidator extends AbstractValidator {

@Override
public List<ValidationEvent> validate(Model model) {
return model.getShapeIndex().shapes(ServiceShape.class)
return model.shapes(ServiceShape.class)
.flatMap(service -> Trait.flatMapStream(service, ServiceTrait.class))
.flatMap(pair -> OptionalUtils.stream(validateService(pair.getLeft(), pair.getRight())))
.collect(toList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public class AuthorizerIndex implements KnowledgeIndex {
public AuthorizerIndex(Model model) {
PathFinder finder = PathFinder.create(model);

model.getShapeIndex().shapes(ServiceShape.class).forEach(service -> {
model.shapes(ServiceShape.class).forEach(service -> {
service.getTrait(AuthorizersTrait.class).ifPresent(trait -> authorizerTraits.put(service.getId(), trait));
Map<ShapeId, String> serviceMap = new HashMap<>();
authorizers.put(service.getId(), serviceMap);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
public class AuthorizersTraitValidator extends AbstractValidator {
@Override
public List<ValidationEvent> validate(Model model) {
return model.getShapeIndex().shapes(ServiceShape.class)
return model.shapes(ServiceShape.class)
.flatMap(service -> OptionalUtils.stream(validateService(service)))
.collect(Collectors.toList());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import software.amazon.smithy.model.shapes.ServiceShape;
import software.amazon.smithy.model.shapes.Shape;
import software.amazon.smithy.model.shapes.ShapeId;
import software.amazon.smithy.model.shapes.ShapeIndex;
import software.amazon.smithy.model.shapes.ToShapeId;
import software.amazon.smithy.model.traits.Trait;
import software.amazon.smithy.utils.MapUtils;
Expand All @@ -37,10 +36,10 @@ public class IntegrationTraitIndex implements KnowledgeIndex {
private Map<ShapeId, Map<ShapeId, Trait>> traits = new HashMap<>();

public IntegrationTraitIndex(Model model) {
model.getShapeIndex().shapes(ServiceShape.class).forEach(service -> {
model.shapes(ServiceShape.class).forEach(service -> {
Map<ShapeId, Trait> serviceMap = new HashMap<>();
traits.put(service.getId(), serviceMap);
walk(model.getShapeIndex(), service.getId(), service, null);
walk(model, service.getId(), service, null);
});
}

Expand Down Expand Up @@ -78,19 +77,19 @@ public <T extends Trait> Optional<T> getIntegrationTrait(ToShapeId service, ToSh
return getIntegrationTrait(service, shape).filter(type::isInstance).map(type::cast);
}

private void walk(ShapeIndex index, ShapeId service, EntityShape current, Trait trait) {
private void walk(Model model, ShapeId service, EntityShape current, Trait trait) {
Trait updatedTrait = extractTrait(current, trait);
Map<ShapeId, Trait> serviceMapping = traits.get(service);
serviceMapping.put(current.getId(), updatedTrait);

for (ShapeId resource : current.getResources()) {
index.getShape(resource)
model.getShape(resource)
.flatMap(Shape::asResourceShape)
.ifPresent(resourceShape -> walk(index, service, resourceShape, updatedTrait));
.ifPresent(resourceShape -> walk(model, service, resourceShape, updatedTrait));
}

for (ShapeId operation : current.getAllOperations()) {
index.getShape(operation).ifPresent(op -> serviceMapping.put(operation, extractTrait(op, updatedTrait)));
model.getShape(operation).ifPresent(op -> serviceMapping.put(operation, extractTrait(op, updatedTrait)));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import software.amazon.smithy.model.shapes.ServiceShape;
import software.amazon.smithy.model.shapes.Shape;
import software.amazon.smithy.model.shapes.ShapeId;
import software.amazon.smithy.model.shapes.ShapeIndex;
import software.amazon.smithy.model.traits.ErrorTrait;
import software.amazon.smithy.model.traits.Trait;
import software.amazon.smithy.model.transform.ModelTransformer;
Expand Down Expand Up @@ -61,7 +60,7 @@ public Model onRemove(ModelTransformer transformer, Collection<Shape> shapes, Mo
}

private Set<Shape> getServicesToUpdate(Model model, Set<ShapeId> removedOperations, Set<ShapeId> removedErrors) {
return model.getShapeIndex().shapes(ServiceShape.class)
return model.shapes(ServiceShape.class)
.flatMap(service -> Trait.flatMapStream(service, ClientEndpointDiscoveryTrait.class))
.filter(pair -> removedOperations.contains(pair.getRight().getOperation())
|| removedErrors.contains(pair.getRight().getError()))
Expand All @@ -78,7 +77,7 @@ private Set<Shape> getOperationsToUpdate(
Set<ShapeId> updatedServices
) {
ClientEndpointDiscoveryIndex discoveryIndex = model.getKnowledge(ClientEndpointDiscoveryIndex.class);
Set<ShapeId> stillBoundOperations = model.getShapeIndex().shapes(ServiceShape.class)
Set<ShapeId> stillBoundOperations = model.shapes(ServiceShape.class)
// Get all endpoint discovery services
.filter(service -> service.hasTrait(ClientEndpointDiscoveryTrait.class))
.map(Shape::getId)
Expand All @@ -88,7 +87,7 @@ private Set<Shape> getOperationsToUpdate(
.flatMap(service -> discoveryIndex.getEndpointDiscoveryOperations(service).stream())
.collect(Collectors.toSet());

return model.getShapeIndex().shapes(OperationShape.class)
return model.shapes(OperationShape.class)
// Get all endpoint discovery operations
.flatMap(operation -> Trait.flatMapStream(operation, ClientDiscoveredEndpointTrait.class))
// Only get the ones where discovery is optional, as it is safe to remove in that case
Expand All @@ -101,22 +100,21 @@ private Set<Shape> getOperationsToUpdate(
}

private Set<Shape> getMembersToUpdate(Model model, Set<ShapeId> updatedOperations) {
ShapeIndex shapeIndex = model.getShapeIndex();
Set<ShapeId> stillBoundMembers = shapeIndex.shapes(OperationShape.class)
Set<ShapeId> stillBoundMembers = model.shapes(OperationShape.class)
// Get all endpoint discovery operations
.filter(operation -> operation.hasTrait(ClientDiscoveredEndpointTrait.class))
// Filter out the ones which are having their endpoint discovery traits removed
.filter(operation -> !updatedOperations.contains(operation.getId()))
// Get the input shapes of those operations
.filter(operation -> operation.getInput().isPresent())
.map(operation -> shapeIndex.getShape(operation.getInput().get()).flatMap(Shape::asStructureShape))
.map(operation -> model.getShape(operation.getInput().get()).flatMap(Shape::asStructureShape))
.filter(Optional::isPresent)
// Get the input members
.flatMap(input -> input.get().getAllMembers().values().stream())
.map(Shape::getId)
.collect(Collectors.toSet());

return shapeIndex.shapes(MemberShape.class)
return model.shapes(MemberShape.class)
// Get all members which have the endpoint discovery id trait
.filter(member -> member.hasTrait(ClientEndpointDiscoveryIdTrait.class))
// Get those which are on structures that aren't still bound to endpoint discovery operations
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import software.amazon.smithy.model.shapes.ServiceShape;
import software.amazon.smithy.model.shapes.Shape;
import software.amazon.smithy.model.shapes.ShapeId;
import software.amazon.smithy.model.shapes.ShapeIndex;
import software.amazon.smithy.model.shapes.StructureShape;
import software.amazon.smithy.model.shapes.ToShapeId;
import software.amazon.smithy.model.traits.Trait;
Expand All @@ -42,20 +41,19 @@ public final class ClientEndpointDiscoveryIndex implements KnowledgeIndex {
private final Map<ShapeId, Map<ShapeId, ClientEndpointDiscoveryInfo>> endpointDiscoveryInfo = new HashMap<>();

public ClientEndpointDiscoveryIndex(Model model) {
ShapeIndex index = model.getShapeIndex();
TopDownIndex topDownIndex = model.getKnowledge(TopDownIndex.class);
OperationIndex opIndex = model.getKnowledge(OperationIndex.class);

index.shapes(ServiceShape.class)
model.shapes(ServiceShape.class)
.flatMap(service -> Trait.flatMapStream(service, ClientEndpointDiscoveryTrait.class))
.forEach(servicePair -> {
ServiceShape service = servicePair.getLeft();
ShapeId endpointOperationId = servicePair.getRight().getOperation();
ShapeId endpointErrorId = servicePair.getRight().getError();

Optional<OperationShape> endpointOperation = index.getShape(endpointOperationId)
Optional<OperationShape> endpointOperation = model.getShape(endpointOperationId)
.flatMap(Shape::asOperationShape);
Optional<StructureShape> endpointError = index.getShape(endpointErrorId)
Optional<StructureShape> endpointError = model.getShape(endpointErrorId)
.flatMap(Shape::asStructureShape);

if (endpointOperation.isPresent() && endpointError.isPresent()) {
Expand Down
Loading

0 comments on commit 9d9831a

Please sign in to comment.