summaryrefslogblamecommitdiffstats
path: root/src/Bindings/BlockTypeRegistry.cpp
blob: 62c3c580b44e8f7f37fd774a4b53222e0a880224 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
















                                                                                

                                        
                                       

                                       












                                           

                                                    

                                               
                                                                  


                                   

                                           












                                              

                                                                             
                                       

                                                                                                                    

                                                   

                                                                                                                                                     
                                                                 









                                                    
                                





 










                                                                                


                                                                                        

                                        


                                                   







                                                                                 
                                               







                                                                                       


                                                   











                                                                      

                                                                     


                                                             
                                                    











                              





                                         


                                                         














                                                                                   


                                                         









                                                



                                                                                

                                                                 

                                                                

                                                      







                                                               

                                                                 

 




                                                                                                                                  

          












                                                                                




                                                                                                                                             


          

#include "Globals.h"
#include "BlockTypeRegistry.h"




////////////////////////////////////////////////////////////////////////////////
// BlockInfo:

BlockInfo::BlockInfo(
	const AString & aPluginName,
	const AString & aBlockTypeName,
	std::shared_ptr<cBlockHandler> aHandler,
	const std::map<AString, AString> & aHints,
	const std::map<AString, BlockInfo::HintCallback> & aHintCallbacks
):
	m_PluginName(aPluginName),
	m_BlockTypeName(aBlockTypeName),
	m_Handler(std::move(aHandler)),
	m_Hints(aHints),
	m_HintCallbacks(aHintCallbacks)
{
}





AString BlockInfo::hintValue(
	const AString & aHintName,
	const BlockState & aBlockState
)
{
	// Search the hint callbacks first:
	auto itrC = m_HintCallbacks.find(aHintName);
	if (itrC != m_HintCallbacks.end())
	{
		// Hint callback found, use it:
		return itrC->second(m_BlockTypeName, aBlockState);
	}

	// Search the static hints:
	auto itr = m_Hints.find(aHintName);
	if (itr != m_Hints.end())
	{
		// Hint found, use it:
		return itr->second;
	}

	// Nothing found, return empty string:
	return AString();
}





void BlockInfo::setHint(const AString & aHintKey, const AString & aHintValue)
{
	m_Hints[aHintKey] = aHintValue;

	// Warn if the hint is already provided by a callback (aHintValue will be ignored when evaluating the hint):
	auto itrC = m_HintCallbacks.find(aHintKey);
	if (itrC != m_HintCallbacks.end())
	{
		LOGINFO("Setting a static hint %s for block type %s, but there's already a callback for that hint. The static hint will be ignored.",
			aHintKey.c_str(), m_BlockTypeName.c_str()
		);
	}
}





void BlockInfo::removeHint(const AString & aHintKey)
{
	m_Hints.erase(aHintKey);
}





////////////////////////////////////////////////////////////////////////////////
// BlockTypeRegistry:

void BlockTypeRegistry::registerBlockType(
	const AString & aPluginName,
	const AString & aBlockTypeName,
	std::shared_ptr<cBlockHandler> aHandler,
	const std::map<AString, AString> & aHints,
	const std::map<AString, BlockInfo::HintCallback> & aHintCallbacks
)
{
	auto blockInfo = std::make_shared<BlockInfo>(
		aPluginName, aBlockTypeName, std::move(aHandler), aHints, aHintCallbacks
	);

	// Check previous registrations:
	cCSLock lock(m_CSRegistry);
	auto itr = m_Registry.find(aBlockTypeName);
	if (itr != m_Registry.end())
	{
		if (itr->second->pluginName() != aPluginName)
		{
			throw AlreadyRegisteredException(itr->second, blockInfo);
		}
	}

	// Store the registration:
	m_Registry[aBlockTypeName] = blockInfo;
}





std::shared_ptr<BlockInfo> BlockTypeRegistry::blockInfo(const AString & aBlockTypeName)
{
	cCSLock lock(m_CSRegistry);
	auto itr = m_Registry.find(aBlockTypeName);
	if (itr == m_Registry.end())
	{
		return nullptr;
	}
	return itr->second;
}





void BlockTypeRegistry::removeAllByPlugin(const AString & aPluginName)
{
	cCSLock lock(m_CSRegistry);
	for (auto itr = m_Registry.begin(); itr != m_Registry.end();)
	{
		if (itr->second->pluginName() == aPluginName)
		{
			itr = m_Registry.erase(itr);
		}
		else
		{
			++itr;
		}
	}
}





void BlockTypeRegistry::setBlockTypeHint(
	const AString & aBlockTypeName,
	const AString & aHintKey,
	const AString & aHintValue
)
{
	cCSLock lock(m_CSRegistry);
	auto blockInfo = m_Registry.find(aBlockTypeName);
	if (blockInfo == m_Registry.end())
	{
		throw NotRegisteredException(aBlockTypeName, aHintKey, aHintValue);
	}
	blockInfo->second->setHint(aHintKey, aHintValue);
}





void BlockTypeRegistry::removeBlockTypeHint(
	const AString & aBlockTypeName,
	const AString & aHintKey
)
{
	cCSLock lock(m_CSRegistry);
	auto blockInfo = m_Registry.find(aBlockTypeName);
	if (blockInfo == m_Registry.end())
	{
		return;
	}
	blockInfo->second->removeHint(aHintKey);
}





////////////////////////////////////////////////////////////////////////////////
// BlockTypeRegistry::AlreadyRegisteredException:

BlockTypeRegistry::AlreadyRegisteredException::AlreadyRegisteredException(
	const std::shared_ptr<BlockInfo> & aPreviousRegistration,
	const std::shared_ptr<BlockInfo> & aNewRegistration
) :
	Super(message(aPreviousRegistration, aNewRegistration)),
	m_PreviousRegistration(aPreviousRegistration),
	m_NewRegistration(aNewRegistration)
{
}





AString BlockTypeRegistry::AlreadyRegisteredException::message(
	const std::shared_ptr<BlockInfo> & aPreviousRegistration,
	const std::shared_ptr<BlockInfo> & aNewRegistration
)
{
	return fmt::format(
		FMT_STRING("Attempting to register BlockTypeName {} from plugin {}, while it is already registered in plugin {}"),
		aNewRegistration->blockTypeName(),
		aNewRegistration->pluginName(),
		aPreviousRegistration->pluginName()
	);
}





////////////////////////////////////////////////////////////////////////////////
// BlockTypeRegistry::NotRegisteredException:

BlockTypeRegistry::NotRegisteredException::NotRegisteredException(
	const AString & aBlockTypeName,
	const AString & aHintKey,
	const AString & aHintValue
):
	Super(fmt::format(
		FMT_STRING("Attempting to set a hint of nonexistent BlockTypeName.\n\tBlockTypeName = {}\n\tHintKey = {}\n\tHintValue = {}"),
		aBlockTypeName,
		aHintKey,
		aHintValue
	))
{
}