Browse Source

Refactor to separate pending config logic

feature_improvement
Anton Tarasenko 2 years ago
parent
commit
de24fc4f7b
  1. 367
      sources/Commands/ACommandFeature.uc
  2. 15
      sources/Commands/ACommandFeature_Announcer.uc
  3. 271
      sources/Tools/PendingConfigsTool.uc

367
sources/Commands/ACommandFeature.uc

@ -17,28 +17,26 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Acedia. If not, see <https://www.gnu.org/licenses/>. * along with Acedia. If not, see <https://www.gnu.org/licenses/>.
*/ */
class ACommandFeature extends Command; class ACommandFeature extends Command
dependson(PendingConfigsTool);
// TODO: autoconf, newconf, deleteconf, setconf var private class<Feature> selectedFeatureClass;
var private Text selectedConfigName;
struct EditedConfigs
{
var class<Feature> featureClass;
var HashTable pendingSaves;
};
var private array<EditedConfigs> configEdits;
var private PendingConfigsTool pendingConfigs;
var private ACommandFeature_Announcer announcer; var private ACommandFeature_Announcer announcer;
protected function Finalizer() protected function Constructor()
{ {
local int i; pendingConfigs =
PendingConfigsTool(_.memory.Allocate(class'PendingConfigsTool'));
super.Constructor();
}
protected function Finalizer()
{
_.memory.Free(announcer); _.memory.Free(announcer);
for (i = 0; i < configEdits.length; i ++) { _.memory.Free(pendingConfigs);
_.memory.Free(configEdits[i].pendingSaves);
}
configEdits.length = 0;
super.Finalizer(); super.Finalizer();
} }
@ -69,122 +67,124 @@ protected function BuildData(CommandDataBuilder builder)
protected function Executed(CallData arguments, EPlayer instigator) protected function Executed(CallData arguments, EPlayer instigator)
{ {
local Text userGivenFeatureName, userGivenConfigName;
announcer.Setup(none, instigator, othersConsole); announcer.Setup(none, instigator, othersConsole);
userGivenFeatureName = arguments.parameters.GetText(P("feature"));
selectedFeatureClass = LoadFeatureClass(userGivenFeatureName);
_.memory.Free(userGivenFeatureName);
userGivenConfigName = arguments.parameters.GetText(P("config"));
if (userGivenConfigName != none)
{
selectedConfigName = userGivenConfigName.LowerCopy();
userGivenConfigName.FreeSelf();
}
pendingConfigs.SelectConfig(selectedFeatureClass, selectedConfigName);
if (arguments.subCommandName.IsEmpty()) { if (arguments.subCommandName.IsEmpty()) {
ShowAllFeatures(); ShowAllFeatures();
} }
else if (arguments.subCommandName.Compare(P("enable"))) else if (arguments.subCommandName.Compare(P("enable"))) {
{ EnableFeature();
EnableFeature(
arguments.parameters.GetText(P("feature")),
arguments.parameters.GetText(P("config")));
} }
else if (arguments.subCommandName.Compare(P("disable"))) { else if (arguments.subCommandName.Compare(P("disable"))) {
DisableFeature(arguments.parameters.GetText(P("feature"))); DisableFeature();
} }
else if (arguments.subCommandName.Compare(P("showconf"))) else if (arguments.subCommandName.Compare(P("showconf"))) {
{ ShowFeatureConfig();
ShowFeatureConfig(
arguments.parameters.GetText(P("feature")),
arguments.parameters.GetText(P("config")));
} }
else if (arguments.subCommandName.Compare(P("editconf"))) else if (arguments.subCommandName.Compare(P("editconf")))
{ {
EditFeatureConfig( EditFeatureConfig(
arguments.parameters.GetText(P("feature")),
arguments.parameters.GetText(P("config")),
arguments.parameters.GetText(P("variable path")), arguments.parameters.GetText(P("variable path")),
arguments.parameters.GetText(P("value"))); arguments.parameters.GetText(P("value")));
} }
_.memory.Free(selectedConfigName);
selectedConfigName = none;
} }
protected function EnableFeature(BaseText featureName, BaseText configParameter) protected function EnableFeature()
{ {
local bool wasEnabled; local bool wasEnabled;
local Text oldConfig, newConfig; local Text oldConfig, newConfig;
local Feature instance; local Feature instance;
local class<Feature> featureClass;
featureClass = LoadFeatureClass(featureName); wasEnabled = selectedFeatureClass.static.IsEnabled();
if (featureClass == none) { oldConfig = selectedFeatureClass.static.GetCurrentConfig();
return; newConfig = PickConfigBasedOnParameter();
}
wasEnabled = featureClass.static.IsEnabled();
oldConfig = featureClass.static.GetCurrentConfig();
newConfig = PickConfigBasedOnParameter(featureClass, configParameter);
// Already enabled with the same config! // Already enabled with the same config!
if (oldConfig != none && oldConfig.Compare(newConfig, SCASE_INSENSITIVE)) if (oldConfig != none && oldConfig.Compare(newConfig, SCASE_INSENSITIVE))
{ {
announcer.AnnounceFailedAlreadyEnabled(featureClass, newConfig); announcer.AnnounceFailedAlreadyEnabled(selectedFeatureClass, newConfig);
_.memory.Free(newConfig); _.memory.Free(newConfig);
_.memory.Free(oldConfig); _.memory.Free(oldConfig);
return; return;
} }
// Try enabling and report the result // Try enabling and report the result
instance = featureClass.static.EnableMe(newConfig); instance = selectedFeatureClass.static.EnableMe(newConfig);
if (instance == none) { if (instance == none)
announcer.AnnounceFailedCannotEnableFeature(featureClass, newConfig); {
announcer.AnnounceFailedCannotEnableFeature(
selectedFeatureClass,
newConfig);
} }
else if (wasEnabled) { else if (wasEnabled)
announcer.AnnounceSwappedConfig(featureClass, oldConfig, newConfig); {
announcer.AnnounceSwappedConfig(
selectedFeatureClass,
oldConfig,
newConfig);
} }
else { else {
announcer.AnnounceEnabledFeature(featureClass, newConfig); announcer.AnnounceEnabledFeature(selectedFeatureClass, newConfig);
} }
_.memory.Free(newConfig); _.memory.Free(newConfig);
_.memory.Free(oldConfig); _.memory.Free(oldConfig);
} }
protected function DisableFeature(Text featureName) protected function DisableFeature()
{ {
local class<Feature> featureClass; if (!selectedFeatureClass.static.IsEnabled())
featureClass = LoadFeatureClass(featureName);
if (featureClass == none) {
return;
}
if (!featureClass.static.IsEnabled())
{ {
announcer.AnnounceFailedAlreadyDisabled(featureClass); announcer.AnnounceFailedAlreadyDisabled(selectedFeatureClass);
return; return;
} }
featureClass.static.DisableMe(); selectedFeatureClass.static.DisableMe();
// It is possible that this command itself is destroyed after above command // It is possible that this command itself is destroyed after above command
// so do the check just in case // so do the check just in case
if (IsAllocated()) { if (IsAllocated()) {
announcer.AnnounceDisabledFeature(featureClass); announcer.AnnounceDisabledFeature(selectedFeatureClass);
} }
} }
protected function ShowFeatureConfig( protected function ShowFeatureConfig()
BaseText featureName,
BaseText configParameter)
{ {
local MutableText dataAsJSON; local MutableText dataAsJSON;
local HashTable currentData, pendingData; local HashTable currentData, pendingData;
local class<Feature> featureClass;
featureClass = LoadFeatureClass(featureName);
if (featureClass == none) return;
if (configParameter == none) return;
currentData = GetCurrentConfigData(featureClass, configParameter); if (selectedConfigName == none) {
return;
}
currentData = GetCurrentConfigData();
if (currentData == none) if (currentData == none)
{ {
announcer.AnnounceFailedNoDataForConfig(featureClass, configParameter); announcer.AnnounceFailedNoDataForConfig(
selectedFeatureClass,
selectedConfigName);
return; return;
} }
// Display current data // Display current data
dataAsJSON = _.json.PrettyPrint(currentData); dataAsJSON = _.json.PrettyPrint(currentData);
announcer.AnnounceCurrentConfig(featureClass, configParameter); announcer.AnnounceCurrentConfig(selectedFeatureClass, selectedConfigName);
callerConsole.Flush().WriteLine(dataAsJSON); callerConsole.Flush().WriteLine(dataAsJSON);
_.memory.Free(dataAsJSON); _.memory.Free(dataAsJSON);
// Display pending data // Display pending data
pendingData = GetPendingConfigData(featureClass, configParameter); pendingData = pendingConfigs.GetPendingConfigData();
if (pendingData != none) if (pendingData != none)
{ {
dataAsJSON = _.json.PrettyPrint(pendingData); dataAsJSON = _.json.PrettyPrint(pendingData);
announcer.AnnouncePendingConfig(featureClass, configParameter); announcer.AnnouncePendingConfig(
selectedFeatureClass,
selectedConfigName);
callerConsole.Flush().WriteLine(dataAsJSON); callerConsole.Flush().WriteLine(dataAsJSON);
_.memory.Free(dataAsJSON); _.memory.Free(dataAsJSON);
} }
@ -192,35 +192,30 @@ protected function ShowFeatureConfig(
_.memory.Free(currentData); _.memory.Free(currentData);
} }
protected function Text PickConfigBasedOnParameter( protected function Text PickConfigBasedOnParameter()
class<Feature> featureClass,
BaseText configParameter)
{ {
local Text resolvedConfig; local Text resolvedConfig;
local class<FeatureConfig> configClass; local class<FeatureConfig> configClass;
if (featureClass == none) { configClass = selectedFeatureClass.default.configClass;
return none;
}
configClass = featureClass.default.configClass;
if (configClass == none) if (configClass == none)
{ {
announcer.AnnounceFailedNoConfigClass(featureClass); announcer.AnnounceFailedNoConfigClass(selectedFeatureClass);
return none; return none;
} }
// If config was specified - simply check that it exists // If config was specified - simply check that it exists
if (configParameter != none) if (selectedConfigName != none)
{ {
if (configClass.static.Exists(configParameter)) { if (configClass.static.Exists(selectedConfigName)) {
return configParameter.Copy(); return selectedConfigName.Copy();
} }
announcer.AnnounceFailedConfigMissing(configParameter); announcer.AnnounceFailedConfigMissing(selectedConfigName);
return none; return none;
} }
// If it wasn't specified - try auto config instead // If it wasn't specified - try auto config instead
resolvedConfig = configClass.static.GetAutoEnabledConfig(); resolvedConfig = configClass.static.GetAutoEnabledConfig();
if (resolvedConfig == none) { if (resolvedConfig == none) {
announcer.AnnounceFailedNoConfigProvided(featureClass); announcer.AnnounceFailedNoConfigProvided(selectedFeatureClass);
} }
return resolvedConfig; return resolvedConfig;
} }
@ -260,7 +255,7 @@ protected function ShowFeature(class<Feature> feature)
{ {
local int i; local int i;
local Text autoConfig; local Text autoConfig;
local MutableText featureName, builder; local MutableText featureName, builder, nextConfig;
local ListBuilder configList; local ListBuilder configList;
local array<Text> availableConfigs; local array<Text> availableConfigs;
local class<FeatureConfig> configClass; local class<FeatureConfig> configClass;
@ -296,7 +291,12 @@ protected function ShowFeature(class<Feature> feature)
autoConfig = configClass.static.GetAutoEnabledConfig(); autoConfig = configClass.static.GetAutoEnabledConfig();
for (i = 0; i < availableConfigs.length; i += 1) for (i = 0; i < availableConfigs.length; i += 1)
{ {
configList.Item(availableConfigs[i]); nextConfig = availableConfigs[i].MutableCopy();
if (pendingConfigs.HasPendingConfigFor(feature, nextConfig)) {
nextConfig.Append(P("*"));
}
configList.Item(nextConfig);
_.memory.Free(nextConfig);
if ( autoConfig != none if ( autoConfig != none
&& autoConfig.Compare(availableConfigs[i], SCASE_INSENSITIVE)) && autoConfig.Compare(availableConfigs[i], SCASE_INSENSITIVE))
{ {
@ -310,206 +310,43 @@ protected function ShowFeature(class<Feature> feature)
_.memory.Free(autoConfig); _.memory.Free(autoConfig);
_.memory.Free(builder); _.memory.Free(builder);
} }
//TODO: find where `null` spam is from
//TODO add failure color to fail announcements and good color to good ones - add them too!
protected function EditFeatureConfig(
BaseText featureName,
BaseText configParameter,
BaseText pathToValue,
BaseText newValue)
{
local int arrayIndex;
local Text topValue;
local HashTable pendingData;
local JSONPointer pointer;
local Parser parser;
local AcediaObject jsonValue, container;
local class<Feature> featureClass;
featureClass = LoadFeatureClass(featureName); protected function EditFeatureConfig(BaseText pathToValue, BaseText newValue)
if (featureClass == none) {
return;
}
pendingData = GetPendingConfigData(featureClass, configParameter, true);
if (pendingData == none)
{ {
announcer.AnnounceFailedConfigMissing(configParameter); local PendingConfigsTool.PendingConfigToolError error;
return;
} error = pendingConfigs.ChangeConfig(pathToValue, newValue);
// Get guaranteed not-`none` JSON value if (error == PCTE_ConfigMissing) {
parser = newValue.Parse(); announcer.AnnounceFailedConfigMissing(selectedConfigName);
jsonValue = _.json.ParseWith(parser);
parser.FreeSelf();
if (jsonValue == none) {
jsonValue = newValue.Copy();
} }
// else if (error == PCTE_ExpectedObject) {
pointer = _.json.Pointer(pathToValue);
if (pointer.IsEmpty())
{
if (jsonValue.class != class'HashTable') {
announcer.AnnounceFailedExpectedObject(); announcer.AnnounceFailedExpectedObject();
} }
else { else if (error == PCTE_BadPointer)
ChangePendingConfigData(featureClass, configParameter, HashTable(jsonValue));
}
jsonValue.FreeSelf();
return;
}
topValue = pointer.Pop();
container = pendingData.GetItemByJSON(pointer);
if (container == none)
{ {
announcer.AnnounceFailedBadPointer(featureClass, configParameter, pathToValue); announcer.AnnounceFailedBadPointer(
pointer.FreeSelf(); selectedFeatureClass,
topValue.FreeSelf(); selectedConfigName,
return; pathToValue);
} }
if (HashTable(container) != none) {
HashTable(container).SetItem(topValue, jsonValue);
}
if (ArrayList(container) != none)
{
parser = topValue.Parse();
if (parser.MInteger(arrayIndex, 10).Ok()) {
ArrayList(container).SetItem(arrayIndex, jsonValue);
}
else if (topValue.Compare(P("-"))) {
ArrayList(container).AddItem(jsonValue);
}
else {
announcer.AnnounceFailedBadPointer(featureClass, configParameter, pathToValue);
}
parser.FreeSelf();
}
pointer.FreeSelf();
topValue.FreeSelf();
} }
/*// TODO: autoconf, newconf, deleteconf, setconf private function HashTable GetCurrentConfigData()
struct EditedConfigs
{
var class<Feature> featureClass;
var HashTable pendingSaves;
};
var private array<EditedConfigs> configEdits;*/
private function HashTable GetConfigData(
class<Feature> featureClass,
BaseText configName)
{
local HashTable result;
if (featureClass == none) return none;
if (configName == none) return none;
result = GetPendingConfigData(featureClass, configName);
if (result != none) {
return result;
}
return GetCurrentConfigData(featureClass, configName);
}
private function HashTable GetCurrentConfigData(
class<Feature> featureClass,
BaseText configName)
{ {
local class<FeatureConfig> configClass; local class<FeatureConfig> configClass;
if (featureClass == none) return none; if (selectedConfigName == none) {
if (configName == none) return none;
configClass = featureClass.default.configClass;
if (configClass == none)
{
announcer.AnnounceFailedNoConfigClass(featureClass);
return none; return none;
} }
return configClass.static.LoadData(configName); configClass = selectedFeatureClass.default.configClass;
} if (configClass == none)
private function int GetPendingConfigDataIndex(
class<Feature> featureClass)
{
local int i;
for (i = 0; i < configEdits.length; i ++)
{
if (configEdits[i].featureClass == featureClass) {
return i;
}
}
return -1;
}
private function ChangePendingConfigData(
class<Feature> featureClass,
BaseText configName,
HashTable newData)
{
local int editsIndex;
local Text lowerCaseConfigName;
if (newData == none) return;
if (configName == none) return;
editsIndex = GetPendingConfigDataIndex(featureClass);
if (editsIndex < 0) return;
lowerCaseConfigName = configName.LowerCopy();
configEdits[editsIndex].pendingSaves.SetItem(configName, newData);
lowerCaseConfigName.FreeSelf();
}
private function HashTable GetPendingConfigData(
class<Feature> featureClass,
BaseText configName,
optional bool createIfMissing)
{
local int editsIndex;
local Text lowerCaseConfigName;
local HashTable result;
local EditedConfigs newRecord;
if (featureClass == none) return none;
if (configName == none) return none;
lowerCaseConfigName = configName.LowerCopy();
editsIndex = GetPendingConfigDataIndex(featureClass);
if (editsIndex >= 0)
{
result = configEdits[editsIndex]
.pendingSaves
.GetHashTable(lowerCaseConfigName);
if (result != none)
{
lowerCaseConfigName.FreeSelf();
return result;
}
}
if (createIfMissing)
{
if (editsIndex < 0)
{
editsIndex = configEdits.length;
newRecord.featureClass = featureClass;
newRecord.pendingSaves = _.collections.EmptyHashTable();
configEdits[editsIndex] = newRecord;
}
result = GetCurrentConfigData(featureClass, configName);
if (result != none)
{ {
configEdits[editsIndex] announcer.AnnounceFailedNoConfigClass(selectedFeatureClass);
.pendingSaves return none;
.SetItem(lowerCaseConfigName, result);
}
} }
lowerCaseConfigName.FreeSelf(); return configClass.static.LoadData(selectedConfigName);
return result;
} }
// 3. Add `editconf` subcommand
// 4. Add '*' for edited configs in feature display
// 5. Add `saveconf` and `--save` flag // 5. Add `saveconf` and `--save` flag
// 6. Add `removeconf` // 6. Add `removeconf`
// 7. Add `newconf` // 7. Add `newconf`

15
sources/Commands/ACommandFeature_Announcer.uc

@ -178,7 +178,7 @@ public final function AnnounceFailedNoConfigProvided(
{ {
failedNoConfigProvided.initialized = true; failedNoConfigProvided.initialized = true;
failedNoConfigProvided.toSelfReport = _.text.MakeTemplate_S( failedNoConfigProvided.toSelfReport = _.text.MakeTemplate_S(
"{$TextFailue No config specified} and {$TextFailure no" "{$TextFailure No config specified} and {$TextFailure no"
@ "auto-enabled config} exists for feature {$TextEmphasis `%1`}"); @ "auto-enabled config} exists for feature {$TextEmphasis `%1`}");
} }
failedNoConfigProvided.toSelfReport.Reset().ArgClass(featureClass); failedNoConfigProvided.toSelfReport.Reset().ArgClass(featureClass);
@ -191,7 +191,7 @@ public final function AnnounceFailedConfigMissing(BaseText config)
{ {
failedConfigMissing.initialized = true; failedConfigMissing.initialized = true;
failedConfigMissing.toSelfReport = _.text.MakeTemplate_S( failedConfigMissing.toSelfReport = _.text.MakeTemplate_S(
"Specified config \"%1\" {$TextFailue doesn't exist}"); "Specified config \"%1\" {$TextFailure doesn't exist}");
} }
failedConfigMissing.toSelfReport.Reset().Arg(config); failedConfigMissing.toSelfReport.Reset().Arg(config);
MakeAnnouncement(failedConfigMissing); MakeAnnouncement(failedConfigMissing);
@ -269,7 +269,8 @@ public final function AnnounceFailedNoDataForConfig(
{ {
failedNoDataForConfig.initialized = true; failedNoDataForConfig.initialized = true;
failedNoDataForConfig.toSelfReport = _.text.MakeTemplate_S( failedNoDataForConfig.toSelfReport = _.text.MakeTemplate_S(
"Feature {$TextEmphasis `%1`} is missing data for config \"%2\""); "Feature {$TextEmphasis `%1`} is {$TextFailure missing data} for"
@ "config \"%2\"");
} }
failedNoDataForConfig.toSelfReport failedNoDataForConfig.toSelfReport
.Reset() .Reset()
@ -284,8 +285,8 @@ public final function AnnounceFailedExpectedObject()
{ {
failedExpectedObject.initialized = true; failedExpectedObject.initialized = true;
failedExpectedObject.toSelfReport = _.text.MakeTemplate_S( failedExpectedObject.toSelfReport = _.text.MakeTemplate_S(
"When changing the value of the whole config, a JSON object must be" "Value change {$TextFailure failed}, because when changing"
@ "provided"); @ "the value of the whole config, a JSON object must be provided");
} }
MakeAnnouncement(failedExpectedObject); MakeAnnouncement(failedExpectedObject);
} }
@ -299,8 +300,8 @@ public final function AnnounceFailedBadPointer(
{ {
failedBadPointer.initialized = true; failedBadPointer.initialized = true;
failedBadPointer.toSelfReport = _.text.MakeTemplate_S( failedBadPointer.toSelfReport = _.text.MakeTemplate_S(
"Provided JSON pointer \"%3\" is invalid for config \"%2\" of" "Provided JSON pointer \"%3\" is {$TextFailure invalid} for config"
@ "feature {$TextEmphasis `%1`}"); @ "\"%2\" of feature {$TextEmphasis `%1`}");
} }
failedBadPointer.toSelfReport failedBadPointer.toSelfReport
.Reset() .Reset()

271
sources/Tools/PendingConfigsTool.uc

@ -0,0 +1,271 @@
/**
* Auxiliary object for `ACommandFeature` to help with managing pending
* configs for `Feature`s. Pending configs are `HashTable`s with config data
* that are yet to be applied to configs and `Feature`s. They allow users to
* make several changes to the data before actually making changes to
* the gameplay code.
* Copyright 2022 Anton Tarasenko
*------------------------------------------------------------------------------
* This file is part of Acedia.
*
* Acedia is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License, or
* (at your option) any later version.
*
* Acedia is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Acedia. If not, see <https://www.gnu.org/licenses/>.
*/
class PendingConfigsTool extends AcediaObject;
var private class<Feature> selectedFeatureClass;
var private Text selectedConfigName;
enum PendingConfigToolError
{
PCTE_None,
PCTE_ConfigMissing,
PCTE_ExpectedObject,
PCTE_BadPointer
};
struct PendingConfigs
{
var class<Feature> featureClass;
var HashTable pendingSaves;
};
var private array<PendingConfigs> featurePendingEdits;
protected function Finalizer()
{
local int i;
for (i = 0; i < featurePendingEdits.length; i ++) {
_.memory.Free(featurePendingEdits[i].pendingSaves);
}
featurePendingEdits.length = 0;
}
public final function SelectConfig(
class<Feature> featureClass,
BaseText configName)
{
_.memory.Free(selectedConfigName);
selectedFeatureClass = featureClass;
selectedConfigName = none;
if (configName != none) {
selectedConfigName = configName.LowerCopy();
}
}
public function bool HasPendingConfigFor(
class<Feature> featureClass,
BaseText configName)
{
local int i;
local bool result;
local Text lowerCaseConfigName;
if (featureClass == none) return false;
if (configName == none) return false;
for (i = 0; i < featurePendingEdits.length; i ++)
{
if (featurePendingEdits[i].featureClass == featureClass)
{
lowerCaseConfigName = configName.LowerCopy();
result = featurePendingEdits[i].pendingSaves
.HasKey(lowerCaseConfigName);
lowerCaseConfigName.FreeSelf();
return result;
}
}
return false;
}
public function HashTable GetPendingConfigData(optional bool createIfMissing)
{
local int editsIndex;
local HashTable result;
local PendingConfigs newRecord;
if (selectedConfigName == none) {
return none;
}
editsIndex = GetPendingConfigDataIndex();
if (editsIndex >= 0)
{
result = featurePendingEdits[editsIndex]
.pendingSaves
.GetHashTable(selectedConfigName);
if (result != none) {
return result;
}
}
if (createIfMissing)
{
if (editsIndex < 0)
{
editsIndex = featurePendingEdits.length;
newRecord.featureClass = selectedFeatureClass;
newRecord.pendingSaves = _.collections.EmptyHashTable();
featurePendingEdits[editsIndex] = newRecord;
}
result = GetCurrentConfigData();
if (result != none)
{
featurePendingEdits[editsIndex]
.pendingSaves
.SetItem(selectedConfigName, result);
}
}
return result;
}
public function PendingConfigToolError ChangeConfig(
BaseText pathToValue,
BaseText newValue)
{
local HashTable pendingData;
local JSONPointer pointer;
local Parser parser;
local AcediaObject newValueAsJSON;
local PendingConfigToolError result;
if (pathToValue == none) {
return PCTE_BadPointer;
}
pendingData = GetPendingConfigData(true);
if (pendingData == none) {
return PCTE_ConfigMissing;
}
// Get guaranteed not-`none` JSON value, treating it as JSON string
// if necessary
parser = _.text.Parse(newValue);
newValueAsJSON = _.json.ParseWith(parser);
parser.FreeSelf();
if (newValueAsJSON == none && newValue != none) {
newValueAsJSON = newValue.Copy();
}
// Set new data
pointer = _.json.Pointer(pathToValue);
result = SetItemByJSON(pendingData, pointer, newValueAsJSON);
pointer.FreeSelf();
pendingData.FreeSelf();
_.memory.Free(newValueAsJSON);
return result;
}
private function PendingConfigToolError SetItemByJSON(
HashTable data,
JSONPointer pointer,
AcediaObject jsonValue)
{
local Text containerIndex;
local AcediaObject container;
local PendingConfigToolError result;
if (pointer.IsEmpty())
{
if (HashTable(jsonValue) != none)
{
result = ChangePendingConfigData(HashTable(jsonValue));
_.memory.Free(jsonValue);
return result;
}
_.memory.Free(jsonValue);
return PCTE_ExpectedObject;
}
// Since `!pointer.IsEmpty()`, we are guaranteed to pop a valid value
containerIndex = pointer.Pop();
container = data.GetItemByJSON(pointer);
if (container == none)
{
containerIndex.FreeSelf();
return PCTE_BadPointer;
}
result = SetContainerItemByText(container, containerIndex, jsonValue);
containerIndex.FreeSelf();
container.FreeSelf();
return result;
}
private function PendingConfigToolError SetContainerItemByText(
AcediaObject container,
BaseText containerIndex,
AcediaObject jsonValue)
{
local int arrayIndex;
local Parser parser;
local ArrayList arrayListContainer;
local HashTable hashTableContainer;
hashTableContainer = HashTable(container);
arrayListContainer = ArrayList(container);
if (hashTableContainer != none) {
hashTableContainer.SetItem(containerIndex, jsonValue);
}
if (arrayListContainer != none)
{
parser = containerIndex.Parse();
if (parser.MInteger(arrayIndex, 10).Ok())
{
arrayListContainer.SetItem(arrayIndex, jsonValue);
parser.FreeSelf();
return PCTE_None;
}
parser.FreeSelf();
if (containerIndex.Compare(P("-"))) {
arrayListContainer.AddItem(jsonValue);
}
else {
return PCTE_BadPointer;
}
}
return PCTE_None;
}
private function int GetPendingConfigDataIndex()
{
local int i;
for (i = 0; i < featurePendingEdits.length; i ++)
{
if (featurePendingEdits[i].featureClass == selectedFeatureClass) {
return i;
}
}
return -1;
}
private function PendingConfigToolError ChangePendingConfigData(
HashTable newData)
{
local int editsIndex;
if (selectedConfigName == none) {
return PCTE_None;
}
editsIndex = GetPendingConfigDataIndex();
if (editsIndex < 0) {
return PCTE_ConfigMissing;
}
featurePendingEdits[editsIndex].pendingSaves
.SetItem(selectedConfigName, newData);
return PCTE_None;
}
private function HashTable GetCurrentConfigData()
{
return selectedFeatureClass.default.configClass.static
.LoadData(selectedConfigName);
}
defaultproperties
{
}
Loading…
Cancel
Save