function(DeclareShapeComponent componentName)
	string(REPLACE ":" "_" NAMESPACE_COMPONENT ${componentName})
    set(SHAPE_COMPONENT_${NAMESPACE_COMPONENT} ${componentName} PARENT_SCOPE)
	message(STATUS "DeclareShapeComponent(): ComponentName: ${SHAPE_COMPONENT_${NAMESPACE_COMPONENT}}")
endfunction()

function(AddShapeProvidedInterface componentName interface)
	string(REPLACE ":" "_" NAMESPACE_COMPONENT ${componentName})
	if(${SHAPE_COMPONENT_${NAMESPACE_COMPONENT}} STREQUAL ${componentName})
		set(IFACE
			"    component.provideInterface<${interface}>(\"${interface}\");"
		)
		set(SHAPE_COMPONENT_PROVIDED_IFACES_${NAMESPACE_COMPONENT} ${SHAPE_COMPONENT_PROVIDED_IFACES_${NAMESPACE_COMPONENT}} "${IFACE}" PARENT_SCOPE)
	else()
		message( SEND_ERROR "AddShapeProvidedInterface(): Component ${componentName} must be declared in advance by DeclareShapeComponent()")
	endif()
endfunction()

function(AddShapeRequiredInterface componentName interface optionality cardinality)
	string(REPLACE ":" "_" NAMESPACE_COMPONENT ${componentName})
	if(${SHAPE_COMPONENT_${NAMESPACE_COMPONENT}} STREQUAL ${componentName})
		if(NOT ((${optionality} MATCHES MANDATORY) OR (${optionality} MATCHES UNREQUIRED)))
			message( SEND_ERROR "optionality must be UNREQUIRED|MANDATORY" )
		endif()
		if(NOT ((${cardinality} MATCHES SINGLE) OR (${cardinality} MATCHES MULTIPLE)))
			message( SEND_ERROR "optionality must be UNREQUIRED|MANDATORY" )
		endif()
		set(IFACE
			"    component.requireInterface<${interface}>(\"${interface}\", shape::Optionality::${optionality}, shape::Cardinality::${cardinality});"
		)
		set(SHAPE_COMPONENT_REQUIRED_IFACES_${NAMESPACE_COMPONENT} ${SHAPE_COMPONENT_REQUIRED_IFACES_${NAMESPACE_COMPONENT}} "${IFACE}" PARENT_SCOPE)
	else()
		message( SEND_ERROR "AddShapeRequiredInterface(): Component ${componentName} must be declared in advance by DeclareShapeComponent()")
	endif()
endfunction()

function(ConfigureShapeComponent componentName componentHeader)
	string(REPLACE ":" "_" NAMESPACE_COMPONENT ${componentName})
	if(${SHAPE_COMPONENT_${NAMESPACE_COMPONENT}} STREQUAL ${componentName})
		string(REPLACE ";" ";\n" PROVIDED_INTERFACES "${SHAPE_COMPONENT_PROVIDED_IFACES_${NAMESPACE_COMPONENT}}")
		string(REPLACE ";" ";\n" REQUIRED_INTERFACES "${SHAPE_COMPONENT_REQUIRED_IFACES_${NAMESPACE_COMPONENT}}")
		set(TARGET_FILE "${CMAKE_CURRENT_BINARY_DIR}/${NAMESPACE_COMPONENT}.hxx")
		configure_file(${shape_CMAKE_MODULE_PATH}/Component.hxx.in ${TARGET_FILE} @ONLY)
		set(${componentHeader} ${TARGET_FILE} PARENT_SCOPE)
		message(STATUS "Component ${componentName} configured to ${TARGET_FILE}")
	else()
		message( SEND_ERROR "ConfigureShapeComponent(): Component ${componentName} must be declared in advance by DeclareShapeComponent()")
	endif()
endfunction()
