void CConfigProvider::createXmlPropertyCollection(
	const std::string& keyPath,
	const SmartPtrCXmlElement& thisXml,
	std::deque<std::pair<std::string, std::string> >& propertyCollection) const {
	CAF_CM_FUNCNAME_VALIDATE("createXmlPropertyCollection");

	CAF_CM_ENTER {
		CAF_CM_VALIDATE_STRING(keyPath);
		CAF_CM_VALIDATE_SMARTPTR(thisXml);
		// propertyCollection is optional

		const CXmlElement::SmartPtrCAttributeCollection attributeCollection = thisXml->getAllAttributes();
		if (! attributeCollection.IsNull() && ! attributeCollection->empty()) {
			for (TConstIterator<CXmlElement::CAttributeCollection> attributeXmlIter(*attributeCollection);
				attributeXmlIter; attributeXmlIter++) {
				const std::string attributeName = attributeXmlIter->first;
				const std::string attributeValue = attributeXmlIter->second;

				const std::string newKeyPath = keyPath + _keyPathDelimStr + attributeName;
				propertyCollection.push_back(std::make_pair(newKeyPath, attributeValue));
			}
		}

		const CXmlElement::SmartPtrCElementCollection childrenXml = thisXml->getAllChildren();
		if (! childrenXml.IsNull() && ! childrenXml->empty()) {
			for (TConstIterator<CXmlElement::CElementCollection > childrenXmlIter(*childrenXml);
				childrenXmlIter; childrenXmlIter++) {
				const SmartPtrCXmlElement childXml = childrenXmlIter->second;
				const std::string newKeyPath = keyPath + _keyPathDelimStr + childXml->getName();

				const std::string value = childXml->getValue();
				if (! value.empty()) {
					propertyCollection.push_back(std::make_pair(newKeyPath, value));
				}

				createXmlPropertyCollection(newKeyPath, childXml, propertyCollection);
			}
		}
	}
	CAF_CM_EXIT;
}
Exemple #2
0
void CApplicationContext::parseBeanConfig(
	const std::string& beanConfigFile,
	CBeanCollection& beanCollection) const {
	CAF_CM_FUNCNAME("parseBeanConfig");
	CAF_CM_VALIDATE_STRING(beanConfigFile);
	CAF_CM_LOG_DEBUG_VA1("Parsing bean config file %s", beanConfigFile.c_str());

	// We will look up class references early in the process to fail as early
	// as possible and to make logging better.
	// Parse the bean config file
	CXmlElement::SmartPtrCElementCollection rootElements =
			CXmlUtils::parseFile(beanConfigFile, "caf:beans")->getAllChildren();
	for (TSmartConstMultimapIterator<CXmlElement::CElementCollection> rootChild(*rootElements);
			rootChild;
			rootChild++) {

		// if the child is a bean...
		if (rootChild->getName() == "bean") {
			// Syntactic sugar
			const SmartPtrCXmlElement beanElement = *rootChild;

			// Bean attributes
			const std::string beanId = beanElement->findRequiredAttribute("id");
			CAF_CM_LOG_DEBUG_VA1("Parsing bean [id=%s]", beanId.c_str());
			const std::string beanClass = beanElement->findRequiredAttribute("class");
			CAF_CM_LOG_DEBUG_VA2(
					"Checking bean class [id=%s][class=%s]",
					beanId.c_str(),
					beanClass.c_str());
			if (!CEcmSubSystemRegistry::IsRegistered(beanClass)) {
				CAF_CM_EXCEPTIONEX_VA3(
						NoSuchElementException,
						0,
						"Bean class %s is not registered. Fix the AppConfig file. "
						"[bean id=%s][bean_config_file=%s]",
						beanClass.c_str(),
						beanId.c_str(),
						beanConfigFile.c_str());
			}

			// get optional constructor args and properties
			CBeanCtorArgCollection beanCtorArgs;
			Cmapstrstr beanProperties;
			CAF_CM_LOG_DEBUG_VA1("Parsing bean ctor args and properties [id=%s]", beanId.c_str());
			CXmlElement::SmartPtrCElementCollection beanElements = beanElement->getAllChildren();
			for (TSmartConstMultimapIterator<CXmlElement::CElementCollection> beanChild(*beanElements);
					beanChild;
					beanChild++) {
				if (beanChild->getName() == "property") {
					// Syntactic sugar
					const SmartPtrCXmlElement propArgElement = *beanChild;

					// property attributes
					const std::string name = propArgElement->findRequiredAttribute("name");
					const std::string value = propArgElement->findRequiredAttribute("value");
					if (!beanProperties.insert(std::make_pair(name, value)).second) {
						CAF_CM_EXCEPTIONEX_VA3(
								DuplicateElementException,
								0,
								"Bean property name is duplicated. "
								"[bean id=%s][property name=%s][bean_config_file=%s]",
								beanId.c_str(),
								name.c_str(),
								beanConfigFile.c_str());
					}
				}
				else if (beanChild->getName() == "constructor-arg") {
					// Syntactic sugar
					const SmartPtrCXmlElement ctorArgElement = *beanChild;

					// ctor attributes
					const uint32 ctorArgIndex = CStringConv::fromString<uint32>(ctorArgElement->findRequiredAttribute("index"));
					CBeanCtorArg::ARG_TYPE ctorArgType = CBeanCtorArg::NOT_SET;
					std::string ctorArgValue = ctorArgElement->findOptionalAttribute("value");
					if (ctorArgValue.length() > 0) {
						ctorArgType = CBeanCtorArg::VALUE;
					} else {
						ctorArgValue = ctorArgElement->findOptionalAttribute("ref");
						if (ctorArgValue.length() > 0) {
							ctorArgType = CBeanCtorArg::REFERENCE;
						} else {
							CAF_CM_EXCEPTIONEX_VA2(
									InvalidArgumentException,
									0,
									"Bean constructor argument must be of type value or ref and cannot be empty. "
									"[bean id=%s][bean_config_file=%s]",
									beanId.c_str(),
									beanConfigFile.c_str());
						}
					}

					if (!beanCtorArgs.insert(
							CBeanCtorArgCollection::value_type(
									ctorArgIndex,
									CBeanCtorArg(ctorArgType, ctorArgValue))).second) {
						CAF_CM_EXCEPTIONEX_VA3(
								DuplicateElementException,
								0,
								"Bean has a duplicate constructor-arg index. "
								"[bean id=%s][bean_config_file=%s][arg-index=%d]",
								beanId.c_str(),
								beanConfigFile.c_str(),
								ctorArgIndex);
					}
					CAF_CM_LOG_DEBUG_VA4(
							"Bean ctor arg parsed [id=%s][arg-index=%d][arg-type=%s][arg-value=%s]",
							beanId.c_str(),
							ctorArgIndex,
							(CBeanCtorArg::VALUE == ctorArgType ? "VALUE" : "REFERENCE"),
							ctorArgValue.c_str());
				}
			}

			// Add the bean definition to the collection
			SmartPtrCBeanNode beanNode;
			beanNode.CreateInstance();
			beanNode->_id = beanId;
			beanNode->_class = beanClass;
			beanNode->_ctorArgs = beanCtorArgs;
			beanNode->_properties = beanProperties;

			if (!beanCollection.insert(
					CBeanCollection::value_type(
							beanId,
							beanNode)).second) {
				CAF_CM_EXCEPTIONEX_VA3(
						DuplicateElementException,
						0,
						"Duplicate bean definition detected. "
						"[bean id=%s][bean class=%s][bean_config_file=%s]",
						beanId.c_str(),
						beanNode->_class.c_str(),
						beanConfigFile.c_str());
			}
		}
	}

	CAF_CM_LOG_DEBUG_VA2(
			"Bean configuration file defined %d beans. "
			"[file=%s]",
			beanCollection.size(),
			beanConfigFile.c_str());
}