Migrating toward WingPropHandle
This commit is contained in:
@@ -274,6 +274,31 @@ WingPropHandle::Handles WingPropHandle::GetDetails(UObject* Obj, bool Mutable)
|
||||
|
||||
return Result;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Organize by Name
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool WingPropHandle::OrganizeByName(const Handles &HList, TMap<FName, TSharedPtr<IPropertyHandle>> &Result)
|
||||
{
|
||||
Result.Empty();
|
||||
TSet<FName> DuplicateNames;
|
||||
for (const TSharedPtr<IPropertyHandle> &H : HList)
|
||||
{
|
||||
FName Name = H->GetProperty()->GetFName();
|
||||
if (Result.Contains(Name)) DuplicateNames.Add(Name);
|
||||
else Result.Add(Name, H);
|
||||
}
|
||||
if (DuplicateNames.IsEmpty()) return true;
|
||||
UWingServer::Print(TEXT("More than one property with name:"));
|
||||
for (FName DupName : DuplicateNames)
|
||||
{
|
||||
UWingServer::Printf(TEXT(" %s"), *WingUtils::ExternalizeID(DupName));
|
||||
}
|
||||
UWingServer::Print(TEXT("\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@@ -426,6 +451,59 @@ bool WingPropHandle::SetJson(IPropertyHandle& Handle, const TSharedPtr<FJsonValu
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WingPropHandle::PopulateFromJson(TArray<TSharedPtr<IPropertyHandle>>& Props, const FJsonObject& Json, bool AllOptional)
|
||||
{
|
||||
bool Ok = true;
|
||||
|
||||
// Organize the properties by name.
|
||||
TMap<FName, TSharedPtr<IPropertyHandle>> OrganizedProps;
|
||||
if (!OrganizeByName(Props, OrganizedProps)) Ok = false;
|
||||
|
||||
// Parse the keys in the json, make sure they're syntactically valid and
|
||||
// that they match the names of actual properties, and that there are no dups.
|
||||
TSet<FName> Specified;
|
||||
for (const auto& KV : Json.Values)
|
||||
{
|
||||
FName Name = WingUtils::CheckInternalizeID(KV.Key);
|
||||
if (Name.IsNone()) { Ok = false; continue; }
|
||||
if (!OrganizedProps.Contains(Name))
|
||||
{
|
||||
UWingServer::Printf(TEXT("ERROR: Unknown parameter '%s'\n"), *KV.Key);
|
||||
Ok = false;
|
||||
}
|
||||
if (!WingUtils::FindNoDuplicateName(Specified, Name, TEXT("parameter"))) Ok = false;
|
||||
}
|
||||
|
||||
// Make sure that all required properties have been specified.
|
||||
if (!AllOptional)
|
||||
{
|
||||
for (const TSharedPtr<IPropertyHandle> &H : Props)
|
||||
{
|
||||
if (H->HasMetaData(TEXT("Optional"))) continue;
|
||||
FName Name = H->GetProperty()->GetFName();
|
||||
if (!Specified.Contains(Name))
|
||||
{
|
||||
UWingServer::Printf(TEXT("Required parameter %s not specified\n"),
|
||||
*WingUtils::ExternalizeID(Name));
|
||||
Ok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If anything is wrong, return early without setting anything.
|
||||
if (!Ok) return false;
|
||||
|
||||
// Populate each property from JSON. This could fail too, but at this
|
||||
// point, we're committed.
|
||||
for (const auto& KV : Json.Values)
|
||||
{
|
||||
FName Name = WingUtils::CheckInternalizeID(KV.Key);
|
||||
if (!SetJson(*OrganizedProps[Name], KV.Value)) Ok = false;
|
||||
}
|
||||
return Ok;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Print
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "WingServer.h"
|
||||
#include "WingHandler.h"
|
||||
#include "WingProperty.h"
|
||||
#include "WingPropHandle.h"
|
||||
#include "WingManual.h"
|
||||
#include "WingLogCapture.h"
|
||||
#include "WingUtils.h"
|
||||
@@ -328,7 +328,9 @@ void UWingServer::TryCallHandler(const FString &Line)
|
||||
Handler->ConfigurationObject = Found->Config.Get();
|
||||
|
||||
// Populate the handler object with the request parameters.
|
||||
if (!FWingProperty::PopulateFromJson(HandlerObj->GetClass(), HandlerObj.Get(), &*Request))
|
||||
WingPropHandle Props;
|
||||
WingPropHandle::Handles Handles = Props.AllProperties(HandlerObj.Get(), true, CPF_None);
|
||||
if (!WingPropHandle::PopulateFromJson(Handles, *Request, false))
|
||||
{
|
||||
UWingServer::SuggestManual(WingManual::Section::HandlerHelp);
|
||||
return;
|
||||
|
||||
@@ -56,9 +56,6 @@
|
||||
// Name sanitization
|
||||
// ============================================================
|
||||
|
||||
FName WingUtils::GetFName(const FWingProperty &Prop) { return Prop.Prop->GetFName(); }
|
||||
FName WingUtils::GetFName(const TSharedPtr<IPropertyHandle> &H) { return H->GetProperty()->GetFName(); }
|
||||
|
||||
FString WingUtils::ExternalizeID(FName Name)
|
||||
{
|
||||
return WingTokenizer::ExternalizeID(Name);
|
||||
@@ -272,6 +269,17 @@ FString WingUtils::FormatName(const UWidget *Widget)
|
||||
return ExternalizeID(Widget->GetFName());
|
||||
}
|
||||
|
||||
FName WingUtils::GetFName(const FWingProperty &Prop)
|
||||
{
|
||||
return Prop.Prop->GetFName();
|
||||
}
|
||||
|
||||
FName WingUtils::GetFName(const TSharedPtr<IPropertyHandle> &H)
|
||||
{
|
||||
return H->GetProperty()->GetFName();
|
||||
}
|
||||
|
||||
|
||||
// ============================================================
|
||||
// Formatting other things
|
||||
// ============================================================
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
#include "IPropertyRowGenerator.h"
|
||||
#include "PropertyHandle.h"
|
||||
|
||||
class FJsonObject;
|
||||
class FJsonValue;
|
||||
|
||||
// WingPropHandle: A module that provides easy access to
|
||||
// IPropertyHandle objects. To use this module, construct a
|
||||
// WingPropHandle, then use it to fetch properties from
|
||||
@@ -52,13 +55,27 @@ public:
|
||||
// expression properties), widgets (includes slot properties).
|
||||
Handles GetDetails(UObject* Obj, bool Mutable);
|
||||
|
||||
// Get/set text with special handling for enums (smarter prefix
|
||||
// matching via WingUtils::StringToEnum) and FEdGraphPinType
|
||||
// (human-readable format via UWingTypes).
|
||||
// Organize properties by name. If there's more than one property
|
||||
// of a given name, print an error and returns false, and returns a map
|
||||
// that contains one of the two duplicates.
|
||||
static bool OrganizeByName(const Handles &H, TMap<FName, TSharedPtr<IPropertyHandle>> &Result);
|
||||
|
||||
// Get/set text. Compared to the built in methods for getting and setting
|
||||
// text, these support more concise enum values, FEdGraphPinType, and
|
||||
// more concise Class properties.
|
||||
static FString GetText(IPropertyHandle& Handle);
|
||||
static bool SetText(IPropertyHandle& Handle, const FString& Text);
|
||||
|
||||
// Store a Json value into a property handle. The Json value must be
|
||||
// a string, number, or boolean.
|
||||
static bool SetJson(IPropertyHandle& Handle, const TSharedPtr<FJsonValue>& JsonValue);
|
||||
|
||||
// Populate a whole bunch of properties from a Json object. If
|
||||
// AllOptional is true, the Json may supply a subset of the properties.
|
||||
// If not, the Json must supply all of them, excepting properties that
|
||||
// are explicitly marked Optional.
|
||||
static bool PopulateFromJson(TArray<TSharedPtr<IPropertyHandle>>& Props, const FJsonObject& Json, bool AllOptional);
|
||||
|
||||
// Print a single property in a standardized format:
|
||||
// editable|readonly Type Name = Value
|
||||
static void Print(IPropertyHandle& Handle, FStringBuilderBase& Out);
|
||||
|
||||
Reference in New Issue
Block a user