private void compute(
            Model model,
            ServiceShape service,
            String arnRoot,
            Shape subject,
            ResourceShape parent,
            Set<String> parentDefinitions
    ) {
        Set<String> definitions = new HashSet<>();
        if (!subject.hasTrait(IamResourceTrait.ID)
                || !subject.expectTrait(IamResourceTrait.class).isDisableConditionKeyInheritance()) {
            definitions.addAll(parentDefinitions);
        }
        resourceConditionKeys.get(service.getId()).put(subject.getId(), definitions);
        if (subject.hasTrait(ConditionKeysTrait.ID)) {
            definitions.addAll(subject.expectTrait(ConditionKeysTrait.class).resolveConditionKeys(service));
        }

        // Continue recursing into resources and computing keys.
        subject.asResourceShape().ifPresent(resource -> {
            boolean disableConditionKeyInference = resource.hasTrait(DisableConditionKeyInferenceTrait.ID)
                    || service.hasTrait(DisableConditionKeyInferenceTrait.ID);

            // Add any inferred resource identifiers to the resource and to the service-wide definitions.
            Map<String, String> childIdentifiers = !disableConditionKeyInference
                    ? inferChildResourceIdentifiers(model, service.getId(), arnRoot, resource, parent)
                    : MapUtils.of();

            // Compute the keys of each child operation, passing no keys.
            for (ShapeId operationId : resource.getAllOperations()) {
                Optional<Shape> operationOptional = model.getShape(operationId);
                if (operationOptional.isPresent()) {
                    compute(model, service, arnRoot, operationOptional.get(), resource);
                }
            }

            // Child resources always inherit the identifiers of the parent.
            definitions.addAll(childIdentifiers.values());

            // Compute the keys of each child resource.
            for (ShapeId resourceId : resource.getResources()) {
                Optional<Shape> resourceOptional = model.getShape(resourceId);
                if (resourceOptional.isPresent()) {
                    compute(model, service, arnRoot, resourceOptional.get(), resource, definitions);
                }
            }
        });
    }
Get all the defined condition keys used in an operation or resource, including
any inferred keys and keys inherited by parent resource bindings.

<p>The result does not include global condition keys like "aws:accountId".
Use {@link #getConditionKeyNames} to find all the condition keys used
but not necessarily defined for a resource or operation.

@param service Service shape/shapeId use to scope the result.
@param resourceOrOperation Resource or operation shape/shapeId
@return Returns the conditions keys of the service or an empty map when not found.
smithy-aws-iam-traits/src/main/java/software/amazon/smithy/aws/iam/traits/ConditionKeysIndex.java