diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h b/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h index 3b97b246a9b1431de56ddf4b3483b6befad1d1e8..e534fabc63361dac54accd9ea8337fedb5325326 100644 --- a/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperApplication.h @@ -124,9 +124,9 @@ public: ParameterGroup* GetParameterList(); /* Get the internal application parameter specified - * + * if the follow flag is on, the function returns the target of proxy parameters * WARNING: this method may disappear from the API */ - Parameter* GetParameterByKey(std::string parameter); + Parameter* GetParameterByKey(std::string parameter, bool follow=true); /* Get the internal application parameter specified * diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperCompositeApplication.h b/Modules/Wrappers/ApplicationEngine/include/otbWrapperCompositeApplication.h new file mode 100644 index 0000000000000000000000000000000000000000..5af08d98241f6795147832f9f566642ee325d448 --- /dev/null +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperCompositeApplication.h @@ -0,0 +1,151 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + + =========================================================================*/ +#ifndef otbWrapperCompositeApplication_h +#define otbWrapperCompositeApplication_h + +#include "otbWrapperApplication.h" +#include "itkStdStreamLogOutput.h" + +namespace otb +{ +namespace Wrapper +{ + +/** \class CompositeApplication + * \brief This class is a base class for composite applications + * + * This class allows to create & store internal applications with the same logic + * as parameters. You choose the application type to create, you choose an + * identifier (alphanumeric string), and you can give a short description. + * Later, you will refer to this application using the identifier. In the + * functions of this class, you can refer to parameters from internal + * applications by using their identifier as prefix. For instance, "app1.in" + * will refer to parameter "in" from internal application named "app1" + * (if such application exists, if not it will refer to a parameter of this + * composite application). + * + * \ingroup OTBApplicationEngine + */ +class OTBApplicationEngine_EXPORT CompositeApplication: public Application +{ +public: + /** Standard class typedefs. */ + typedef CompositeApplication Self; + typedef Application Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + /** RTTI support */ + itkTypeMacro(CompositeApplication, Application); + + /** Filters typedef */ + typedef itk::MemberCommand< Self > AddProcessCommandType; + + typedef struct + { + Application::Pointer App; + std::string Desc; + } InternalApplication; + + typedef std::map<std::string, InternalApplication> InternalAppContainer; + +protected: + /** Constructor */ + CompositeApplication(); + + /** Destructor */ + ~CompositeApplication() ITK_OVERRIDE; + + /** + * Callback function to retrieve the process watchers on internal filters + */ + void LinkWatchers(itk::Object * itkNotUsed(caller), const itk::EventObject & event); + + /** + * Method to instanciate and register a new internal application + * \param appType Type of the application to instanciate + * \param key Identifier associated to the created application + * \param desc Description of the internal application + */ + bool AddApplication(std::string appType, std::string key, std::string desc); + + /** + * Connect two existing parameters together. The first parameter will point to + * the second parameter. + */ + bool Connect(std::string fromKey, std::string toKey); + + /** + * Share a parameter between the composite application and an internal application + * The local parameter is created as a proxy to the internal parameter. + * \param localKey New parameter key in the composite application + * \param internalKey Key to the internal parameter to expose + * \param name Name for the local parameter, if empty the target's name is used + * \param desc Description for the local parameter, if empty the target's description is used + */ + bool ShareParameter(std::string localKey, + std::string internalKey, + std::string name = std::string(), + std::string desc = std::string()); + + /** + * Decode a key to extract potential prefix for internal applications + * If a valid prefix (corresponding to an internal app) is found: + * - prefix is removed from the input key which is altered. + * - the function returns a pointer to the internal application + * If no valid prefix is found, the input key is not modified, and the + * function returns 'this'. + */ + Application* DecodeKey(std::string &key); + + /** + * Get the internal application with the given identifier + */ + Application* GetInternalApplication(std::string id); + + /** + * Get the description of an internal application + */ + std::string GetInternalAppDescription(std::string id); + + /** + * Utility function to call Execute() on an internal app and get its output logs + */ + void ExecuteInternal(std::string key); + + /** + * Utility function to call UpdateParameters() on an internal app + */ + void UpdateInternalParameters(std::string key); + +private: + CompositeApplication(const CompositeApplication &); //purposely not implemented + void operator =(const CompositeApplication&); //purposely not implemented + + InternalAppContainer m_AppContainer; + + itk::StdStreamLogOutput::Pointer m_LogOutput; + + std::ostringstream m_Oss; + + AddProcessCommandType::Pointer m_AddProcessCommand; +}; + +} +} +#endif diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperParameterGroup.h b/Modules/Wrappers/ApplicationEngine/include/otbWrapperParameterGroup.h index fb395b439c68f70701676b16665fde8443032dd1..5aea541604912424fcec62ed5319ed33976d0162 100644 --- a/Modules/Wrappers/ApplicationEngine/include/otbWrapperParameterGroup.h +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperParameterGroup.h @@ -47,6 +47,10 @@ public: void AddParameter(Parameter::Pointer p); + /** Method to substitute a parameter in a group. + * The function returns true on success, false on failure */ + bool ReplaceParameter(std::string &key, Parameter::Pointer p); + /** Add a new choice value to an existing choice parameter */ void AddChoice(std::string paramKey, std::string paramName); @@ -61,9 +65,9 @@ public: * or the path to a choice value */ void AddParameter(ParameterType type, std::string paramKey, std::string paramName); - Parameter::Pointer GetParameterByIndex(unsigned int i); + Parameter::Pointer GetParameterByIndex(unsigned int i, bool follow=true); - Parameter::Pointer GetParameterByKey(std::string name); + Parameter::Pointer GetParameterByKey(std::string name, bool follow=true); /** rashad: Add xml parameters eg: -inxml -outxml */ void AddInXMLParameter(); @@ -93,6 +97,10 @@ public: return true; } + /** Resolve potential proxy parameters by following their targets until + * a non-proxy parameter. It will detect cycles and report an error */ + static Parameter* ResolveParameter(Parameter *param); + protected: ParameterGroup(); ~ParameterGroup() ITK_OVERRIDE; diff --git a/Modules/Wrappers/ApplicationEngine/include/otbWrapperProxyParameter.h b/Modules/Wrappers/ApplicationEngine/include/otbWrapperProxyParameter.h new file mode 100644 index 0000000000000000000000000000000000000000..ea16db09d0e8ab7c7587cecdeca187a27870a697 --- /dev/null +++ b/Modules/Wrappers/ApplicationEngine/include/otbWrapperProxyParameter.h @@ -0,0 +1,71 @@ +#ifndef otbWrapperProxyParameter_h +#define otbWrapperProxyParameter_h + +#include "itkObject.h" +#include "otbWrapperParameter.h" +#include <utility> + +namespace otb +{ +namespace Wrapper +{ +/** + * \class ProxyParameter + * + * \brief Parameter class acting as a proxy to a different parameter + * + * The target parameter of this proxy is defined as a pair of a group parameter + * containing the target and the targets key. It allows to define proxies on + * parameters that may be themselves replaced by a proxy + * + * \ingroup OTBApplicationEngine + */ +class ProxyParameter : public Parameter +{ +public: + typedef ProxyParameter Self; + typedef Parameter Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + itkNewMacro(Self); + + itkTypeMacro(ProxyParameter, Parameter); + + typedef std::pair<Parameter::Pointer, std::string> ProxyTargetType; + + /** Set the target parameter of the proxy + * \param target pair of a group parameter containing the target and its key + */ + void SetTarget(const ProxyTargetType& target) + { + m_Target = target; + } + + /** Get the target parameter of the proxy + * First part is the group parameter containing the target + * Second part is the key of the target */ + const ProxyTargetType & GetTarget(void) + { + return m_Target; + } + +protected: + ProxyParameter() {} + ~ProxyParameter() ITK_OVERRIDE {} + +private: + ProxyParameter(const Self &); //purposely not implemented + void operator =(const Self&); //purposely not implemented + + ProxyTargetType m_Target; +}; + +} +} + +//#ifndef OTB_MANUAL_INSTANTIATION +//#include "otbWrapperProxyParameter.txx" +//#endif + +#endif diff --git a/Modules/Wrappers/ApplicationEngine/src/CMakeLists.txt b/Modules/Wrappers/ApplicationEngine/src/CMakeLists.txt index 6d11c565ee8af5638682141dc0a8f911369203b5..c33fdbcdc04cf938d179a35c29271ffb39ce9e1b 100644 --- a/Modules/Wrappers/ApplicationEngine/src/CMakeLists.txt +++ b/Modules/Wrappers/ApplicationEngine/src/CMakeLists.txt @@ -27,6 +27,7 @@ set(OTBApplicationEngine_SRC otbWrapperChoiceParameter.cxx otbWrapperApplicationRegistry.cxx otbWrapperApplicationFactoryBase.cxx + otbWrapperCompositeApplication.cxx ) add_library(OTBApplicationEngine ${OTBApplicationEngine_SRC}) diff --git a/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx b/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx index 0ab8e27f8ca12f727a1b18f11262e90c7d5afc9b..f24308291ed7a3f1804baf8a070fe143dcb0f202 100644 --- a/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx +++ b/Modules/Wrappers/ApplicationEngine/src/otbWrapperApplication.cxx @@ -32,6 +32,7 @@ #include "otbWrapperInputImageListParameter.h" #include "otbWrapperInputProcessXMLParameter.h" #include "otbWrapperRAMParameter.h" +#include "otbWrapperProxyParameter.h" #include "otbWrapperAddProcessToWatchEvent.h" @@ -97,9 +98,9 @@ ParameterGroup* Application::GetParameterList() return m_ParameterList; } -Parameter* Application::GetParameterByKey(std::string name) +Parameter* Application::GetParameterByKey(std::string name, bool follow) { - return GetParameterList()->GetParameterByKey(name); + return GetParameterList()->GetParameterByKey(name, follow); } void Application::SetParameterInt(std::string parameter, int value, bool hasUserValueFlag) @@ -927,19 +928,22 @@ void Application::SetParameterOutputVectorData(std::string parameter, VectorData std::string Application::GetParameterName(std::string parameter) { - Parameter* param = GetParameterByKey(parameter); + // get the actual parameter, even if it is a proxy + Parameter* param = GetParameterByKey(parameter,false); return param->GetName(); } std::string Application::GetParameterDescription(std::string parameter) { - Parameter* param = GetParameterByKey(parameter); + // get the actual parameter, even if it is a proxy + Parameter* param = GetParameterByKey(parameter,false); return param->GetDescription(); } void Application::SetParameterDescription(std::string parameter, std::string desc) { - Parameter* param = GetParameterByKey(parameter); + // get the actual parameter, even if it is a proxy + Parameter* param = GetParameterByKey(parameter,false); param->SetDescription(desc); } @@ -1623,6 +1627,5 @@ std::string Application::GetProgressDescription() const return m_ProgressSourceDescription; } - } } diff --git a/Modules/Wrappers/ApplicationEngine/src/otbWrapperCompositeApplication.cxx b/Modules/Wrappers/ApplicationEngine/src/otbWrapperCompositeApplication.cxx new file mode 100644 index 0000000000000000000000000000000000000000..a3a264a02dcbbe290f2c59b6c8981b2fcf0c06c8 --- /dev/null +++ b/Modules/Wrappers/ApplicationEngine/src/otbWrapperCompositeApplication.cxx @@ -0,0 +1,185 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + + =========================================================================*/ + +#include "otbWrapperCompositeApplication.h" +#include "otbWrapperProxyParameter.h" +#include "otbWrapperApplicationRegistry.h" +#include "otbWrapperAddProcessToWatchEvent.h" +#include "otbWrapperParameterKey.h" + +namespace otb +{ +namespace Wrapper +{ + +CompositeApplication::CompositeApplication() +{ + m_LogOutput = itk::StdStreamLogOutput::New(); + m_LogOutput->SetStream(m_Oss); + m_AddProcessCommand = AddProcessCommandType::New(); + m_AddProcessCommand->SetCallbackFunction(this, &CompositeApplication::LinkWatchers); +} + +CompositeApplication::~CompositeApplication() +{ +} + +void +CompositeApplication +::LinkWatchers(itk::Object * itkNotUsed(caller), const itk::EventObject & event) +{ + if (typeid(AddProcessToWatchEvent) == typeid( event )) + { + this->InvokeEvent(event); + } +} + +bool +CompositeApplication +::AddApplication(std::string appType, std::string key, std::string desc) +{ + if (m_AppContainer.count(key)) + { + otbAppLogWARNING("The requested identifier for internal application is already used ("<<key<<")"); + return false; + } + InternalApplication container; + container.App = ApplicationRegistry::CreateApplication(appType); + container.Desc = desc; + // Setup logger + container.App->GetLogger()->AddLogOutput(m_LogOutput); + container.App->GetLogger()->SetTimeStampFormat(itk::LoggerBase::HUMANREADABLE); + container.App->AddObserver(AddProcessToWatchEvent(), m_AddProcessCommand.GetPointer()); + m_AppContainer[key] = container; + return true; +} + +bool +CompositeApplication +::Connect(std::string fromKey, std::string toKey) +{ + std::string key1(fromKey); + std::string key2(toKey); + Application *app1 = DecodeKey(key1); + Application *app2 = DecodeKey(key2); + + Parameter* rawParam1 = app1->GetParameterByKey(key1, false); + if (dynamic_cast<ProxyParameter*>(rawParam1)) + { + otbAppLogWARNING("Parameter is already connected ! Override current connection"); + } + ProxyParameter::Pointer proxyParam = ProxyParameter::New(); + ProxyParameter::ProxyTargetType target; + target.first = app2->GetParameterList(); + target.second = key2; + proxyParam->SetTarget(target); + proxyParam->SetName(rawParam1->GetName()); + proxyParam->SetDescription(rawParam1->GetDescription()); + return app1->GetParameterList()->ReplaceParameter(key1, proxyParam.GetPointer()); +} + +bool +CompositeApplication +::ShareParameter(std::string localKey, + std::string internalKey, + std::string name, + std::string desc) +{ + std::string internalKeyCheck(internalKey); + Application *app = DecodeKey(internalKeyCheck); + Parameter* rawTarget = app->GetParameterByKey(internalKeyCheck, false); + + // Check source + ParameterKey pKey(localKey); + std::string proxyKey(pKey.GetLastElement()); + + // Create and setup proxy parameter + ProxyParameter::Pointer proxyParam = ProxyParameter::New(); + ProxyParameter::ProxyTargetType target; + target.first = app->GetParameterList(); + target.second = internalKeyCheck; + proxyParam->SetTarget(target); + proxyParam->SetName( name.empty() ? rawTarget->GetName() : name); + proxyParam->SetDescription(desc.empty() ? rawTarget->GetDescription() : desc); + proxyParam->SetKey(proxyKey); + + // Get group parameter where the proxy should be added + Parameter::Pointer baseParam(proxyParam.GetPointer()); + ParameterGroup *parentGroup = this->GetParameterList(); + if (localKey.find('.') != std::string::npos) + { + Parameter::Pointer parentParam = this->GetParameterList()->GetParameterByKey(pKey.GetRoot()); + parentGroup = dynamic_cast<ParameterGroup*>(parentParam.GetPointer()); + baseParam->SetRoot(parentGroup); + parentGroup->AddChild(baseParam); + } + parentGroup->AddParameter(baseParam); + return true; +} + +Application* +CompositeApplication +::DecodeKey(std::string &key) +{ + Application *ret = this; + size_t pos = key.find('.'); + if (pos != std::string::npos && m_AppContainer.count(key.substr(0,pos))) + { + ret = m_AppContainer[key.substr(0,pos)].App; + key = key.substr(pos+1); + } + return ret; +} + +Application* +CompositeApplication +::GetInternalApplication(std::string id) +{ + if (!m_AppContainer.count(id)) + otbAppLogFATAL("Unknown internal application : "<<id); + return m_AppContainer[id].App; +} + +std::string +CompositeApplication +::GetInternalAppDescription(std::string id) +{ + if (!m_AppContainer.count(id)) + otbAppLogFATAL("Unknown internal application : "<<id); + return m_AppContainer[id].Desc; +} + +void +CompositeApplication +::ExecuteInternal(std::string key) +{ + otbAppLogINFO(<< GetInternalAppDescription(key) <<"..."); + GetInternalApplication(key)->Execute(); + otbAppLogINFO(<< "\n" << m_Oss.str()); + m_Oss.str(std::string("")); +} + +void +CompositeApplication +::UpdateInternalParameters(std::string key) +{ + GetInternalApplication(key)->UpdateParameters(); +} + +} // end namespace Wrapper +} // end namespace otb diff --git a/Modules/Wrappers/ApplicationEngine/src/otbWrapperParameterGroup.cxx b/Modules/Wrappers/ApplicationEngine/src/otbWrapperParameterGroup.cxx index a242cf60916566ff7ae9ca93e293d48716485637..199bb65f494267765a17f37ae064175d42e69c44 100644 --- a/Modules/Wrappers/ApplicationEngine/src/otbWrapperParameterGroup.cxx +++ b/Modules/Wrappers/ApplicationEngine/src/otbWrapperParameterGroup.cxx @@ -36,6 +36,7 @@ #include "otbWrapperInputProcessXMLParameter.h" #include "otbWrapperParameterKey.h" #include "otbWrapperRAMParameter.h" +#include "otbWrapperProxyParameter.h" #include "otb_boost_string_header.h" @@ -61,7 +62,11 @@ ParameterGroup::GetParametersKeys(bool recursive) for (pit = m_ParameterList.begin(); pit != m_ParameterList.end(); ++pit) { Parameter* param = *pit; - parameters.push_back( param->GetKey() ); + std::string currentKey(param->GetKey()); + parameters.push_back( currentKey ); + + // follow proxy parameters + param = this->ResolveParameter(param); if (recursive && dynamic_cast<ParameterGroup*>(param)) { @@ -70,7 +75,7 @@ ParameterGroup::GetParametersKeys(bool recursive) for (std::vector<std::string>::const_iterator it = subparams.begin(); it != subparams.end(); ++it) { - parameters.push_back( std::string(paramAsGroup->GetKey()) + "." + *it ); + parameters.push_back( currentKey + "." + *it ); } } else if (recursive && dynamic_cast<ChoiceParameter*>(param)) @@ -81,7 +86,7 @@ ParameterGroup::GetParametersKeys(bool recursive) for (std::vector<std::string>::const_iterator it = subparams.begin(); it != subparams.end(); ++it) { - parameters.push_back( std::string(paramAsChoice->GetKey()) + "." + *it ); + parameters.push_back( currentKey + "." + *it ); } } } @@ -670,14 +675,79 @@ ParameterGroup::AddParameter(Parameter::Pointer p) m_ParameterList.push_back(p); } +bool +ParameterGroup::ReplaceParameter(std::string &key, Parameter::Pointer p) +{ + bool ret = true; + ParameterKey pName(key); + std::vector<std::string> splitName = pName.Split(); + std::string lastkey = pName.GetLastElement(); + std::string parentkey = pName.GetRoot(); + ParameterGroup* parentGroup = this; + if( splitName.size() > 1 ) + { + Parameter* parentParam = GetParameterByKey(parentkey); + parentGroup = dynamic_cast<ParameterGroup*>(parentParam); + if (parentGroup) + { + ret = parentGroup->ReplaceParameter(lastkey, p); + } + else + { + ret = false; + } + } + else + { + // find current parameter in the current group + Parameter::Pointer oldParam; + ParameterListType::iterator vit; + for (vit = m_ParameterList.begin(); vit != m_ParameterList.end(); ++vit) + { + if (lastkey.compare((*vit)->GetKey()) == 0) + { + oldParam = *vit; + break; + } + } + if (oldParam.IsNull()) + { + // parameter to replace not found : return false + ret = false; + } + else + { + // parameter already exists : replace it + *vit = p; + p->SetKey(lastkey); + } + } + if (ret) + { + if( splitName.size() > 1 ) + { + p->SetRoot(parentGroup); + parentGroup->AddChild(p); + } + } + // don't check type compatibility here, we may want to handle special cases + // at higher level + return ret; +} + Parameter::Pointer -ParameterGroup::GetParameterByIndex(unsigned int i) +ParameterGroup::GetParameterByIndex(unsigned int i, bool follow) { - return m_ParameterList[i]; + Parameter *param = m_ParameterList[i]; + if (follow) + { + param = this->ResolveParameter(param); + } + return Parameter::Pointer(param); } Parameter::Pointer -ParameterGroup::GetParameterByKey(std::string name) +ParameterGroup::GetParameterByKey(std::string name, bool follow) { ParameterKey pName(name); @@ -705,6 +775,13 @@ ParameterGroup::GetParameterByKey(std::string name) itkExceptionMacro(<< "Could not find parameter " << name) } + // follow proxy parameters + if (follow) + { + Parameter *rawParam = this->ResolveParameter(parentParam.GetPointer()); + parentParam = rawParam; + } + // If the name contains a child, make a recursive call if (splitName.size() > 1) { @@ -778,5 +855,33 @@ ParameterGroup::GetNumberOfParameters() return m_ParameterList.size(); } +Parameter* ParameterGroup::ResolveParameter(Parameter *param) +{ + Parameter* ret = param; + if (ret == ITK_NULLPTR) + { + itkGenericExceptionMacro("Can't resolve NULL parameter!"); + } + while (dynamic_cast<ProxyParameter*>(ret)) + { + ProxyParameter* castParam = dynamic_cast<ProxyParameter*>(ret); + ProxyParameter::ProxyTargetType target = castParam->GetTarget(); + ParameterGroup* targetGroup = dynamic_cast<ParameterGroup*>(target.first.GetPointer()); + if (targetGroup) + { + ret = targetGroup->GetParameterByKey(target.second); + } + else + { + itkGenericExceptionMacro("Target group of a proxy parameter is not of type ParameterGroup"); + } + if (ret == param) + { + itkGenericExceptionMacro("Cycle detected with proxy parameters!"); + } + } + return ret; +} + } } diff --git a/Modules/Wrappers/ApplicationEngine/test/CMakeLists.txt b/Modules/Wrappers/ApplicationEngine/test/CMakeLists.txt index 753d0016ad7cb2d0075de2a9055961ad5f97378b..7b6dee37b275ed7ec8a2c99e6842e13ec5814002 100644 --- a/Modules/Wrappers/ApplicationEngine/test/CMakeLists.txt +++ b/Modules/Wrappers/ApplicationEngine/test/CMakeLists.txt @@ -177,3 +177,7 @@ otb_add_test(NAME owTvApplicationMemoryConnectTest COMMAND otbApplicationEngineT $<TARGET_FILE_DIR:otbapp_Smoothing> ${INPUTDATA}/poupees.tif ${TEMP}/owTvApplicationMemoryConnectTestOutput.tif) + +otb_add_test(NAME owTvParameterGroup COMMAND otbApplicationEngineTestDriver + otbWrapperParameterList + ) diff --git a/Modules/Wrappers/ApplicationEngine/test/otbApplicationEngineTestDriver.cxx b/Modules/Wrappers/ApplicationEngine/test/otbApplicationEngineTestDriver.cxx index 3cb4aaddcdfb84ccd62bf6e44b4fe5171bcf1619..2d6145cedbb23434b53fb12a212e3b1e85f28920 100644 --- a/Modules/Wrappers/ApplicationEngine/test/otbApplicationEngineTestDriver.cxx +++ b/Modules/Wrappers/ApplicationEngine/test/otbApplicationEngineTestDriver.cxx @@ -20,6 +20,7 @@ void RegisterTests() REGISTER_TEST(otbWrapperDocExampleStructureTest); REGISTER_TEST(otbWrapperParameterKey); REGISTER_TEST(otbWrapperParameterListNew); + REGISTER_TEST(otbWrapperParameterList); REGISTER_TEST(otbWrapperEmptyParameterNew); REGISTER_TEST(otbWrapperInputImageListParameterNew); REGISTER_TEST(otbWrapperInputImageListParameterTest1); diff --git a/Modules/Wrappers/ApplicationEngine/test/otbWrapperParameterListTest.cxx b/Modules/Wrappers/ApplicationEngine/test/otbWrapperParameterListTest.cxx index 5d14917b40d3389d20bf30ef226231f1b7664eb8..966db2ceac9724911b6249b2d66e702d6ea024d3 100644 --- a/Modules/Wrappers/ApplicationEngine/test/otbWrapperParameterListTest.cxx +++ b/Modules/Wrappers/ApplicationEngine/test/otbWrapperParameterListTest.cxx @@ -20,6 +20,9 @@ #endif #include "otbWrapperParameterGroup.h" +#include "otbWrapperStringParameter.h" +#include "otbWrapperNumericalParameter.h" +#include "otbWrapperProxyParameter.h" int otbWrapperParameterListNew(int itkNotUsed(argc), char * itkNotUsed(argv)[]) { @@ -30,3 +33,66 @@ int otbWrapperParameterListNew(int itkNotUsed(argc), char * itkNotUsed(argv)[]) return EXIT_SUCCESS; } + +int otbWrapperParameterList(int itkNotUsed(argc), char * itkNotUsed(argv)[]) +{ + typedef otb::Wrapper::ParameterGroup GroupPrm; + typedef otb::Wrapper::StringParameter StringPrm; + typedef otb::Wrapper::IntParameter IntPrm; + typedef otb::Wrapper::ProxyParameter ProxyPrm; + + // setup first group of parameters + GroupPrm::Pointer parameters = GroupPrm::New(); + + StringPrm::Pointer strParam = StringPrm::New(); + strParam->SetKey("str"); + + IntPrm::Pointer numParam = IntPrm::New(); + numParam->SetKey("num"); + numParam->SetValue(1); + + parameters->AddParameter(strParam.GetPointer()); + parameters->AddParameter(numParam.GetPointer()); + + // setup second group of parameters + GroupPrm::Pointer otherParameters = GroupPrm::New(); + + IntPrm::Pointer hiddenParam = IntPrm::New(); + hiddenParam->SetKey("hidden"); + hiddenParam->SetValue(2); + + otherParameters->AddParameter(hiddenParam.GetPointer()); + + ProxyPrm::Pointer proxyParam = ProxyPrm::New(); + ProxyPrm::ProxyTargetType target; + target.first = otherParameters; + target.second = "hidden"; + proxyParam->SetTarget(target); + + // try to set a proxy to "hidden" in the first group + std::string proxyKey("num"); + if (! parameters->ReplaceParameter(proxyKey, proxyParam.GetPointer())) + { + std::cout << "Failed to replace with proxy parameter" << std::endl; + return EXIT_FAILURE; + } + + // check that we get the right value in "num" + otb::Wrapper::Parameter* resultParam = GroupPrm::ResolveParameter(parameters->GetParameterByKey("num")); + IntPrm* castInt = dynamic_cast<IntPrm*>(resultParam); + if (castInt) + { + if (castInt->GetValue() != 2) + { + std::cout << "Failed to setup proxy on int parameter, got "<< castInt->GetValue()<< ", expected 2."<< std::endl; + return EXIT_FAILURE; + } + } + else + { + std::cout << "Can't cast parameter to Int, probably wrong type."<< std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +}