private Optional validateTarget()

in smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/TargetValidator.java [73:138]


    private Optional<ValidationEvent> validateTarget(Model model, Shape shape, Shape target, Relationship rel) {
        RelationshipType relType = rel.getRelationshipType();

        if (relType.getDirection() == RelationshipDirection.DIRECTED && target.hasTrait(TraitDefinition.class)) {
            return Optional.of(error(shape, format(
                    "Found a %s reference to trait definition `%s`. Trait definitions cannot be targeted by "
                    + "members or referenced by shapes in any other context other than applying them as "
                    + "traits.", relType, rel.getNeighborShapeId())));
        }

        switch (relType) {
            case MEMBER_TARGET:
                // Members cannot target other members, service, operation, or resource shapes.
                if (INVALID_MEMBER_TARGETS.contains(target.getType())) {
                    return Optional.of(error(shape, format(
                            "Members cannot target %s shapes, but found %s", target.getType(), target)));
                }
            case MAP_KEY:
                return target.asMemberShape().flatMap(m -> validateMapKey(shape, m.getTarget(), model));
            case RESOURCE:
                if (target.getType() != ShapeType.RESOURCE) {
                    return Optional.of(badType(shape, target, relType, ShapeType.RESOURCE));
                }
                return Optional.empty();
            case OPERATION:
                if (target.getType() != ShapeType.OPERATION) {
                    return Optional.of(badType(shape, target, relType, ShapeType.OPERATION));
                }
                return Optional.empty();
            case INPUT:
            case OUTPUT:
                // Input/output must target structures and cannot have the error trait.
                if (target.getType() != ShapeType.STRUCTURE) {
                    return Optional.of(badType(shape, target, relType, ShapeType.STRUCTURE));
                } else if (target.findTrait("error").isPresent()) {
                    return Optional.of(inputOutputWithErrorTrait(shape, target, rel.getRelationshipType()));
                } else {
                    return Optional.empty();
                }
            case ERROR:
                // Errors must target a structure with the error trait.
                if (target.getType() != ShapeType.STRUCTURE) {
                    return Optional.of(badType(shape, target, relType, ShapeType.STRUCTURE));
                } else if (!target.findTrait("error").isPresent()) {
                    return Optional.of(errorNoTrait(shape, target.getId()));
                } else {
                    return Optional.empty();
                }
            case IDENTIFIER:
                return validateIdentifier(shape, target);
            case CREATE:
            case READ:
            case UPDATE:
            case DELETE:
            case LIST:
                if (target.getType() != ShapeType.OPERATION) {
                    return Optional.of(error(shape, format(
                            "Resource %s lifecycle operation must target an operation, but found %s",
                            relType.toString().toLowerCase(Locale.US), target)));
                } else {
                    return Optional.empty();
                }
            default:
                return Optional.empty();
        }
    }