18#include "UtInputBlock.hpp"
20#include "UtMemory.hpp"
26template<
typename DerivedComponent>
32template<
typename DerivedComponent>
38template<
typename DerivedComponent>
41 const std::string command(aInput.GetCommand());
42 if (command ==
"model")
44 UtInputBlock inputBlock(aInput);
45 return ProcessModel(inputBlock, ProcessModelName(inputBlock));
47 else if (command ==
"add" || command ==
"edit")
50 std::string nextCommand;
51 aInput.ReadCommand(nextCommand);
52 if (nextCommand !=
"model")
54 throw UtInput::BadValue(aInput, std::string(
"Unexpected command ") + nextCommand +
". Expected model");
56 UtInputBlock inputBlock(aInput);
57 return ProcessModel(inputBlock, ProcessModelName(inputBlock, command ==
"edit"));
59 else if (command ==
"common")
61 return ProcessCommonParameters(aInput);
69template<
typename DerivedComponent>
70bool WsfMultiresolutionWrapperMetaModel<DerivedComponent>::ProcessModel(
71 UtInputBlock& aInputBlock,
72 const typename WsfMultiresolutionWrapperMetaModel<DerivedComponent>::Index aModelIndex)
75 assert(aModelIndex < mComponentModels.size());
76 ModelWithFidelity& model = mComponentModels[aModelIndex];
77 std::string nextCommand;
78 while (aInputBlock.ReadCommand(nextCommand))
80 if (nextCommand ==
"fidelity_range")
82 model.mFidelityRange = wm::ProcessFidelityRange(aInputBlock.GetInput());
83 AffirmDisjointWithFidelityRanges(aInputBlock.GetInput(), model);
85 else if (nextCommand == wm::BaseComponentName<DerivedComponent>())
87 model.mComponent = ProcessComponent(aInputBlock.GetInput(), std::move(model.mComponent));
89 else if (nextCommand ==
"default")
91 mDefaultComponentIndex = aModelIndex;
95 throw UtInput::BadValue(aInputBlock.GetInput(),
96 std::string(
"Unexpected command ") + nextCommand +
97 ". Expected either fidelity_range, default, or " +
98 std::string(wm::BaseComponentName<DerivedComponent>()));
101 FinalizeModelProcessing(aInputBlock.GetInput(), model);
105template<
typename DerivedComponent>
106std::unique_ptr<DerivedComponent>
107WsfMultiresolutionWrapperMetaModel<DerivedComponent>::ProcessComponent(UtInput& aInput,
108 std::unique_ptr<DerivedComponent> aExistingComponent)
110 UtInputBlock componentBlock(aInput);
111 std::unique_ptr<DerivedComponent> component =
112 aExistingComponent ? std::move(aExistingComponent) : ProcessComponentType(aInput);
114 bool processedInput =
true;
115 std::string nextCommand;
116 while (componentBlock.ReadCommand(nextCommand) && processedInput)
118 processedInput &= component->ProcessInput(aInput);
122 throw UtInput::BadValue(aInput,
"Model couldn't process its input. Model type: " + component->GetType());
127template<
typename DerivedComponent>
128typename WsfMultiresolutionWrapperMetaModel<DerivedComponent>::Index
129WsfMultiresolutionWrapperMetaModel<DerivedComponent>::ProcessModelName(UtInputBlock& aInputBlock,
130 const ut::optional<bool> aExpectExists)
132 std::string modelName;
133 aInputBlock.GetInput().ReadValue(modelName);
134 ut::optional<Index> modelIndex = ModelIndexWithName(modelName);
138 if (modelIndex.has_value() && !aExpectExists.value())
140 throw UtInput::BadValue(aInputBlock.GetInput(),
"Expected no existing model with name " + modelName);
142 else if (!modelIndex.has_value() && aExpectExists.value())
144 throw UtInput::BadValue(aInputBlock.GetInput(),
"Expected existing model with name " + modelName);
148 if (!modelIndex.has_value())
150 mComponentModels.emplace_back();
151 mComponentModels.back().mName = std::move(modelName);
152 modelIndex = mComponentModels.size() - 1;
157template<
typename DerivedComponent>
158std::unique_ptr<DerivedComponent> WsfMultiresolutionWrapperMetaModel<DerivedComponent>::ProcessComponentType(UtInput& aInput)
160 std::string baseType;
161 aInput.ReadValue(baseType);
164 auto component = std::unique_ptr<DerivedComponent>(componentTypeList.
Clone(baseType));
168 component.reset(componentTypeList.
Clone(baseType));
172 throw UtInput::BadValue(aInput,
"Could not load type " + baseType);
177template<
typename DerivedComponent>
178bool WsfMultiresolutionWrapperMetaModel<DerivedComponent>::ProcessCommonParameters(UtInput& aInput)
180 auto commonInputLocation = aInput.StoreLocation();
181 bool inputProcessed =
true;
182 if (mComponentModels.empty())
184 throw UtInput::BadValue(aInput,
"Expected common input block after definition of one or more models.");
186 for (
auto& component : mComponentModels)
188 aInput.RestoreLocation(commonInputLocation);
189 UtInputBlock inputBlock(aInput);
190 std::string nextCommand;
191 while (inputBlock.ReadCommand(nextCommand))
193 inputProcessed &= component.mComponent->ProcessInput(aInput);
196 return inputProcessed;
199template<
typename DerivedComponent>
200void WsfMultiresolutionWrapperMetaModel<DerivedComponent>::FinalizeModelProcessing(
202 const typename WsfMultiresolutionWrapperMetaModel<DerivedComponent>::ModelWithFidelity& aModelWithFidelity)
204 if (aModelWithFidelity.mComponent)
207 AffirmDisjointWithFidelityRanges(aInput, aModelWithFidelity);
213 throw UtInput::BadValue(aInput,
214 "Expected a model specification of type " +
219template<
typename DerivedComponent>
220void WsfMultiresolutionWrapperMetaModel<DerivedComponent>::AffirmDisjointWithFidelityRanges(
222 const typename WsfMultiresolutionWrapperMetaModel<DerivedComponent>::ModelWithFidelity& aModelWithFidelity)
const
224 const auto result = std::find_if(mComponentModels.cbegin(),
225 mComponentModels.cend(),
226 [&aModelWithFidelity](
const ModelWithFidelity& model)
228 return aModelWithFidelity.mComponent.get() != model.mComponent.get() &&
229 aModelWithFidelity.mFidelityRange.Overlaps(model.mFidelityRange);
231 if (result != mComponentModels.end())
233 throw UtInput::BadValue(aInput,
234 "Expected no overlap between any models' fidelity_range. Found overlap between " +
235 aModelWithFidelity.mName +
" and " + result->mName);
239template<
typename DerivedComponent>
240ut::optional<typename WsfMultiresolutionWrapperMetaModel<DerivedComponent>::Index>
241WsfMultiresolutionWrapperMetaModel<DerivedComponent>::ModelIndexForFidelity(
const double aFidelity)
const
243 assert(!mComponentModels.empty());
244 assert(aFidelity >= 0.0);
245 assert(aFidelity <= 1.0);
247 std::find_if(mComponentModels.cbegin(),
248 mComponentModels.cend(),
249 [aFidelity](
const ModelWithFidelity& model) { return model.mFidelityRange.Contains(aFidelity); });
250 if (result != mComponentModels.cend())
252 return std::distance(mComponentModels.cbegin(), result);
255 <<
" on platform " << this->GetComponentParent()->GetName() <<
". Using default model.";
256 if (!mDefaultComponentIndex)
259 <<
" on platform " << this->GetComponentParent()->GetName();
261 return mDefaultComponentIndex;
264template<
typename DerivedComponent>
265typename ut::optional<typename WsfMultiresolutionWrapperMetaModel<DerivedComponent>::Index>
266WsfMultiresolutionWrapperMetaModel<DerivedComponent>::ModelIndexWithName(
const std::string& aTypeName)
const
268 const auto result = std::find_if(mComponentModels.cbegin(),
269 mComponentModels.cend(),
270 [&aTypeName](
const ModelWithFidelity& model) { return model.mName == aTypeName; });
271 if (result != mComponentModels.cend())
273 return std::distance(mComponentModels.cbegin(), result);
281template<
typename DerivedComponent>
284 const ut::optional<Index> componentIndex = ModelIndexForFidelity(this->GetFidelity());
285 if (componentIndex.has_value())
287 return std::unique_ptr<DerivedComponent>{mComponentModels[*componentIndex].mComponent->Clone()};
Definition WsfComponent.hpp:39
Definition WsfObjectTypeList.hpp:42
T * Clone(WsfStringId aId) const override
Definition WsfObjectTypeList.hpp:118
WsfObject()
This is the constructor for the WsfObject class.
Definition WsfObject.cpp:88
Definition ComponentNameHelper.cpp:17
constexpr const char * BaseComponentName()
Definition ComponentNameHelper.hpp:103
std::string CommandName()
This name, associated with DerivedComponent, is for use in the multiresolution framework....
Definition ComponentNameHelper.hpp:74
WsfObjectTypeList< DerivedComponent > & GetObjectTypeList(UtInput &aInput)
Definition WsfMultiresolutionPlatformComponent.hpp:85