/** * Author: dkanus * Home repo: https://www.insultplayers.ru/git/AcediaFramework/AcediaCore * License: GPL * Copyright 2023 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 . */ class ItemCard extends AcediaObject; //! Utility class designed for storing either class of an object //! (possibly also a specific instance) along with authorization information: //! which user groups are allowed to use stored entity and with what level of //! permissions (defined by the name of a config with permissions). //! //! [`ItemCard`] has to be initialized with either [`InitializeWithClass()`] or //! [`InitializeWithInstance()`] before it can be used. /// Class of object that this card describes. var private class storedClass; /// Instance of an object (can also *optionally* be stored in this card) var private AcediaObject storedInstance; /// This [`HashTable`] maps authorized groups to their respective config names. /// /// Each key represents an authorized group, and its corresponding value /// indicates the associated config name. If a key has a value of `none`, /// the default config (named "default") should be used for that group. var private HashTable groupToConfig; var LoggerAPI.Definition errGroupAlreadyHasConfig; protected function Finalizer() { _.memory.Free2(storedInstance, groupToConfig); storedInstance = none; storedClass = none; groupToConfig = none; } /// Initializes the caller [`ItemCard`] object with class to be stored. /// /// Initialization can only be done once: once method returned `true`, /// all future calls will fail. /// /// Returns `false` if caller was already initialized or `none` is provided as /// an argument. Otherwise succeeds and returns `true`. public function bool InitializeWithClass(class toStore) { if (storedClass != none) return false; if (toStore == none) return false; storedClass = toStore; groupToConfig = _.collections.EmptyHashTable(); return true; } /// Initializes the caller [`ItemCard`] object with an object to be stored. /// /// Initialization can only be done once: once method returned `true`, /// all future calls will fail. /// /// Returns `false` caller was already initialized or `none` is provided as /// an argument. Otherwise succeeds and returns `true`. public function bool InitializeWithInstance(AcediaObject toStore) { if (storedClass != none) return false; if (toStore == none) return false; storedClass = toStore.class; storedInstance = toStore; storedInstance.NewRef(); groupToConfig = _.collections.EmptyHashTable(); return true; } /// Authorizes a new group to use the this card's item. /// /// This function allows to specify the config name for a particular user group. /// If this config name is skipped (specified as `none`), then "default" will be /// used instead. /// /// Function will return `true` if group was successfully authorized and /// `false` otherwise (either group already authorized or caller [`ItemCard`] /// isn't initialized). /// /// # Errors /// /// If specified group was already authorized to use card's item, then it /// will log an error message about it. public function bool AuthorizeGroupWithConfig(BaseText groupName, optional BaseText configName) { local Text itemKey; local Text storedConfigName; if (storedClass == none) return false; if (groupToConfig == none) return false; if (groupName == none) return false; if (groupName.IsEmpty()) return false; /// Make group name immutable and have its characters have a uniform case to /// be usable as case-insensitive keys for [`HashTable`]. itemKey = groupName.LowerCopy(); storedConfigName = groupToConfig.GetText(itemKey); if (storedConfigName != none) { _.logger.Auto(errGroupAlreadyHasConfig) .ArgClass(storedClass) .Arg(groupName.Copy()) .Arg(storedConfigName) .Arg(configName.Copy()); _.memory.Free(itemKey); return false; } // We don't actually record "default" value at this point, instead opting // to return "default" in getter functions in case stored `configName` // is `none`. groupToConfig.SetItem(itemKey, configName); _.memory.Free(itemKey); return true; } /// Returns item instance for the caller [`ItemCard`]. /// /// Returns `none` iff this card wasn't initialized with an instance. public function AcediaObject GetItem() { if (storedInstance != none) { storedInstance.NewRef(); } return storedInstance; } /// Returns item class for the caller [`ItemCard`]. /// /// Returns `none` iff this card wasn't initialized. public function class GetItemClass() { return storedClass; } /// Returns the name of config that was authorized for the specified group. /// /// Returns `none` if group wasn't authorized, otherwise guaranteed to /// return non-`none` and non-empty `Text` value. public function Text GetConfigNameForGroup(BaseText groupName) { local Text groupNameAsKey, result; if (storedClass == none) return none; if (groupToConfig == none) return none; if (groupName == none) return none; /// Make group name immutable and have its characters a uniform case to /// be usable as case-insensitive keys for [`HashTable`] groupNameAsKey = groupName.LowerCopy(); if (groupToConfig.HasKey(groupNameAsKey)) { result = groupToConfig.GetText(groupNameAsKey); if (result == none) { // If we do have specified group recorded as a key, then we must // return non-`none` config name, defaulting to "default" value // if none was provided result = P("default").Copy(); } } _.memory.Free(groupNameAsKey); return result; } defaultproperties { errGroupAlreadyHasConfig = (l=LOG_Error,m="Item `%1` is already added to group '%2' with config '%3'. Attempt to add it with config '%4' is ignored.") }