private Optional<EventStreamInfo> createEventStreamInfo(
            Model model,
            OperationShape operation,
            StructureShape structure,
            MemberShape member
    ) {

        Shape eventStreamTarget = model.expectShape(member.getTarget());

        // Compute the events of the event stream.
        Map<String, StructureShape> events = new HashMap<>();
        if (eventStreamTarget.asUnionShape().isPresent()) {
            for (MemberShape unionMember : eventStreamTarget.asUnionShape().get().getAllMembers().values()) {
                model.getShape(unionMember.getTarget()).flatMap(Shape::asStructureShape).ifPresent(struct -> {
                    events.put(unionMember.getMemberName(), struct);
                });
            }
        } else if (eventStreamTarget.asStructureShape().isPresent()) {
            events.put(member.getMemberName(), eventStreamTarget.asStructureShape().get());
        } else {
            // If the event target is an invalid type, then we can't create the indexed result.
            LOGGER.severe(() -> String.format(
                    "Skipping event stream info for %s because the %s member target %s is not a structure or union",
                    operation.getId(),
                    member.getMemberName(),
                    member.getTarget()));
            return Optional.empty();
        }

        Map<String, MemberShape> initialMembers = new HashMap<>();
        Map<String, Shape> initialTargets = new HashMap<>();

        for (MemberShape structureMember : structure.getAllMembers().values()) {
            if (!structureMember.getMemberName().equals(member.getMemberName())) {
                model.getShape(structureMember.getTarget()).ifPresent(shapeTarget -> {
                    initialMembers.put(structureMember.getMemberName(), structureMember);
                    initialTargets.put(structureMember.getMemberName(), shapeTarget);
                });
            }
        }

        return Optional.of(new EventStreamInfo(
                operation,
                eventStreamTarget.expectTrait(StreamingTrait.class),
                structure,
                member,
                eventStreamTarget,
                initialMembers,
                initialTargets,
                events));
    }
Get event stream information for the output of an operation.

<p>No result is returned if the provided operation shape does not
exist, if the targeted shape is not an operation, if the operation
does not contain an output structure or if the output structure does
not contain an output event stream.

@param operationShape Operation or shape ID to retrieve information for.
@return Returns the optionally found output event stream information.
smithy-model/src/main/java/software/amazon/smithy/model/knowledge/EventStreamIndex.java