Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use WritablePropertyMap #5905

Merged
merged 2 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import org.labkey.api.data.CoreSchema;
import org.labkey.api.data.DbScope;
import org.labkey.api.data.PropertyManager;
import org.labkey.api.data.PropertyManager.WritablePropertyMap;
import org.labkey.api.data.SQLFragment;
import org.labkey.api.data.SimpleFilter;
import org.labkey.api.data.Sort;
Expand Down Expand Up @@ -779,7 +780,7 @@ public static Collection<? extends NotificationOption> getEmailOptions()

public static void saveDefaultEmailOption(Container c, int emailOption)
{
PropertyManager.PropertyMap props = PropertyManager.getWritableProperties(c, "defaultEmailSettings", true);
WritablePropertyMap props = PropertyManager.getWritableProperties(c, "defaultEmailSettings", true);
props.put("defaultEmailOption", Integer.toString(emailOption));
props.save();
}
Expand Down Expand Up @@ -815,7 +816,7 @@ private static int validate(int option)

public static void saveMessageBoardSettings(Container c, Settings settings)
{
PropertyManager.PropertyMap props = PropertyManager.getWritableProperties(c, MESSAGE_BOARD_SETTINGS, true);
WritablePropertyMap props = PropertyManager.getWritableProperties(c, MESSAGE_BOARD_SETTINGS, true);
props.clear(); // Get rid of old props (e.g., userList, see #13882)
props.put("boardName", settings.getBoardName());
props.put("conversationName", settings.getConversationName());
Expand Down
9 changes: 4 additions & 5 deletions api/src/org/labkey/api/data/Container.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
import org.labkey.api.cache.BlockingCache;
import org.labkey.api.cache.CacheManager;
import org.labkey.api.collections.Sets;
import org.labkey.api.data.PropertyManager.PropertyMap;
import org.labkey.api.data.PropertyManager.WritablePropertyMap;
import org.labkey.api.module.FolderType;
import org.labkey.api.module.FolderTypeManager;
import org.labkey.api.module.Module;
Expand Down Expand Up @@ -1057,9 +1057,8 @@ public void setDefaultModule(Module module)
{
if (module == null)
return;
PropertyMap props = PropertyManager.getWritableProperties(this, "defaultModules", true);
WritablePropertyMap props = PropertyManager.getWritableProperties(this, "defaultModules", true);
props.put("name", module.getName());

props.save();
ContainerManager.notifyContainerChange(getId(), ContainerManager.Property.Modules);
_defaultModule = null;
Expand All @@ -1079,7 +1078,7 @@ public void setActiveModules(Set<Module> modules, @Nullable User user)
}

boolean userHasEnableRestrictedModules = hasEnableRestrictedModules(user);
PropertyMap props = PropertyManager.getWritableProperties(this, "activeModules", true);
WritablePropertyMap props = PropertyManager.getWritableProperties(this, "activeModules", true);
props.clear();
for (Module module : modules)
{
Expand Down Expand Up @@ -1199,7 +1198,7 @@ public boolean getAsBoolean()
if (props.isEmpty() && init && null != ContainerManager.getForId(getId()))
{
//initialize properties cache
PropertyMap propsWritable = PropertyManager.getWritableProperties(this, "activeModules", true);
WritablePropertyMap propsWritable = PropertyManager.getWritableProperties(this, "activeModules", true);
props = propsWritable;

if (isProject())
Expand Down
9 changes: 5 additions & 4 deletions api/src/org/labkey/api/data/ContainerManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import org.labkey.api.collections.ConcurrentHashSet;
import org.labkey.api.data.Container.ContainerException;
import org.labkey.api.data.Container.LockState;
import org.labkey.api.data.PropertyManager.WritablePropertyMap;
import org.labkey.api.data.SimpleFilter.InClause;
import org.labkey.api.data.dialect.SqlDialect;
import org.labkey.api.data.validator.ColumnValidators;
Expand Down Expand Up @@ -427,7 +428,7 @@ public static Container createContainerFromTemplate(Container parent, String nam

public static void setRequireAuditComments(Container container, User user, @NotNull Boolean required)
{
PropertyManager.PropertyMap props = PropertyManager.getWritableProperties(container, AUDIT_SETTINGS_PROPERTY_SET_NAME, true);
WritablePropertyMap props = PropertyManager.getWritableProperties(container, AUDIT_SETTINGS_PROPERTY_SET_NAME, true);
String originalValue = props.get(REQUIRE_USER_COMMENTS_PROPERTY_NAME);
props.put(REQUIRE_USER_COMMENTS_PROPERTY_NAME, required.toString());
props.save();
Expand Down Expand Up @@ -488,7 +489,7 @@ public static void setFolderType(Container c, FolderType folderType, User user,
if (errorStrings.isEmpty())
{
oldType.unconfigureContainer(c, user);
PropertyManager.PropertyMap props = PropertyManager.getWritableProperties(c, FOLDER_TYPE_PROPERTY_SET_NAME, true);
WritablePropertyMap props = PropertyManager.getWritableProperties(c, FOLDER_TYPE_PROPERTY_SET_NAME, true);
props.put(FOLDER_TYPE_PROPERTY_NAME, folderType.getName());

if (c.isContainerTab())
Expand Down Expand Up @@ -703,14 +704,14 @@ public static boolean isContainerTabTypeOverridden(Container c)
private static void setContainerTabDeleted(Container c, String tabName, String folderTypeName)
{
// Add prop in this category <tabName, folderTypeName>
PropertyManager.PropertyMap props = PropertyManager.getWritableProperties(c, TABFOLDER_CHILDREN_DELETED, true);
WritablePropertyMap props = PropertyManager.getWritableProperties(c, TABFOLDER_CHILDREN_DELETED, true);
props.put(getDeletedTabKey(tabName, folderTypeName), "true");
props.save();
}

public static void clearContainerTabDeleted(Container c, String tabName, String folderTypeName)
{
PropertyManager.PropertyMap props = PropertyManager.getWritableProperties(c, TABFOLDER_CHILDREN_DELETED, true);
WritablePropertyMap props = PropertyManager.getWritableProperties(c, TABFOLDER_CHILDREN_DELETED, true);
String key = getDeletedTabKey(tabName, folderTypeName);
if (props.containsKey(key))
{
Expand Down
89 changes: 47 additions & 42 deletions api/src/org/labkey/api/data/PropertyManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public static PropertyStore getEncryptedStore()
* For global system properties that are attached to the root container
* Returns an empty map if property set hasn't been created
*/
public static @NotNull PropertyManager.PropertyMap getProperties(String category)
public static @NotNull PropertyMap getProperties(String category)
{
return STORE.getProperties(category);
}
Expand All @@ -92,7 +92,7 @@ public static PropertyStore getEncryptedStore()
* For shared properties that are attached to a specific container
* Returns an empty map if property set hasn't been created
*/
public static @NotNull PropertyManager.PropertyMap getProperties(Container container, String category)
public static @NotNull PropertyMap getProperties(Container container, String category)
{
return STORE.getProperties(container, category);
}
Expand All @@ -101,12 +101,12 @@ public static PropertyStore getEncryptedStore()
* For shared properties that are attached to a specific container and user
* Returns an empty map if property set hasn't been created
*/
public static @NotNull PropertyManager.PropertyMap getProperties(User user, Container container, String category)
public static @NotNull PropertyMap getProperties(User user, Container container, String category)
{
return STORE.getProperties(user, container, category);
}

private static boolean assertWritableProperties(@Nullable PropertyMap writableProps, boolean create)
private static boolean assertWritableProperties(@Nullable WritablePropertyMap writableProps, boolean create)
{
// getWritableProperties() will return null if an existing map is not found and create is false.
if (writableProps == null)
Expand Down Expand Up @@ -282,8 +282,8 @@ public static PropertyEntry[] findPropertyEntries(@Nullable User user, @Nullable
}

// Instances of this specific class are guaranteed to be immutable; all mutating Map methods (put(), remove(), etc.)
// will throw exceptions. keySet(), values(), entrySet(), and mapIterator() return immutable data structures.
// Instances of subclass WritablePropertyMap ARE mutable and can be saved, deleted, etc.
// throw exceptions. keySet(), values(), entrySet(), and mapIterator() return immutable data structures.
// Instances of subclass WritablePropertyMap, however, are mutable Maps and can be saved & deleted.
public static class PropertyMap extends AbstractMapDecorator<String, String> implements InitializingBean
{
private int _set;
Expand All @@ -293,10 +293,6 @@ public static class PropertyMap extends AbstractMapDecorator<String, String> imp
private final PropertyEncryption _propertyEncryption;
private final AbstractPropertyStore _store;

private boolean _modified = false;
private Set<Object> _removedKeys = null;
private boolean _locked = false;

protected PropertyMap(int set, @NotNull User user, @NotNull String objectId, @NotNull String category, PropertyEncryption propertyEncryption, AbstractPropertyStore store, Map<String, String> map)
{
super(map);
Expand Down Expand Up @@ -343,6 +339,44 @@ PropertyEncryption getEncryptionAlgorithm()
return _propertyEncryption;
}

@Override
public String toString()
{
return getClass().getSimpleName() + ": " + _objectId + ", " + _category + ", " + _user.getDisplayName(null) + ": " + super.toString();
}

@Override
public boolean equals(Object o)
{
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

PropertyMap that = (PropertyMap) o;

if (!_user.equals(that._user)) return false;
if (!_category.equals(that._category)) return false;

return _objectId.equals(that._objectId);
}

@Override
public int hashCode()
{
int result = _user.hashCode();
result = 31 * result + _objectId.hashCode();
result = 31 * result + _category.hashCode();
return result;
}

// TODO: Once all repos are migrated to use WritablePropertyMaps, everything below will be moved to WritablePropertyMap.
// _locked handling will be removed and cache checking will simply forbid WritablePropertyMap.
// I believe that InitializingBean & afterPropertiesSet() can be removed, since we're now loading the map before
// constructing WritablePropertyMap.

private boolean _modified = false;
private Set<Object> _removedKeys = null;
private boolean _locked = false;

@Override
public String remove(Object key)
{
Expand Down Expand Up @@ -377,12 +411,6 @@ public String put(String key, @Nullable String value)
return super.put(key, value);
}

@Override
public String toString()
{
return getClass().getSimpleName() + ": " + _objectId + ", " + _category + ", " + _user.getDisplayName(null) + ": " + super.toString();
}

@Override
public void putAll(Map<? extends String, ? extends String> m)
{
Expand All @@ -403,29 +431,6 @@ public void clear()
super.clear();
}

@Override
public boolean equals(Object o)
{
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

PropertyMap that = (PropertyMap) o;

if (!_user.equals(that._user)) return false;
if (!_category.equals(that._category)) return false;

return _objectId.equals(that._objectId);
}

@Override
public int hashCode()
{
int result = _user.hashCode();
result = 31 * result + _objectId.hashCode();
result = 31 * result + _category.hashCode();
return result;
}

public boolean isModified()
{
return _modified;
Expand Down Expand Up @@ -565,7 +570,7 @@ public boolean isLocked()
}

/**
* This subclass is mutable and can be saved, deleted, etc.
* This subclass is a mutable Map and can be saved & deleted
*/
public static class WritablePropertyMap extends PropertyMap
{
Expand Down Expand Up @@ -836,7 +841,7 @@ private void testPropertyStore(PropertyStore store, PropertyStoreTest test)

private void testProperties(PropertyStore store, User user, Container test, String category)
{
PropertyMap m = store.getWritableProperties(user, test, category, true);
WritablePropertyMap m = store.getWritableProperties(user, test, category, true);
assertNotNull(m);
m.clear();
m.save();
Expand Down Expand Up @@ -884,7 +889,7 @@ public void run()

private void testProps()
{
PropertyMap map = store.getWritableProperties(c, category, true);
WritablePropertyMap map = store.getWritableProperties(c, category, true);
map.put("foo", "abc");
map.put("bar", "xyz");
map.save();
Expand Down
3 changes: 2 additions & 1 deletion api/src/org/labkey/api/message/digest/MessageDigest.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.labkey.api.data.PropertyManager;
import org.labkey.api.data.PropertyManager.WritablePropertyMap;
import org.labkey.api.util.ExceptionUtil;
import org.labkey.api.util.JobRunner;
import org.quartz.Job;
Expand Down Expand Up @@ -132,7 +133,7 @@ private Date getLastSuccessful()

private void setLastSuccessful(Date last)
{
PropertyManager.PropertyMap props = PropertyManager.getWritableProperties(getName(), true);
WritablePropertyMap props = PropertyManager.getWritableProperties(getName(), true);
props.put(LAST_KEY, String.valueOf(last.getTime()));
props.save();
}
Expand Down
3 changes: 2 additions & 1 deletion api/src/org/labkey/api/miniprofiler/MiniProfiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.labkey.api.data.BeanObjectFactory;
import org.labkey.api.data.ContainerManager;
import org.labkey.api.data.PropertyManager;
import org.labkey.api.data.PropertyManager.WritablePropertyMap;
import org.labkey.api.module.ModuleLoader;
import org.labkey.api.security.User;
import org.labkey.api.security.permissions.TroubleshooterPermission;
Expand Down Expand Up @@ -139,7 +140,7 @@ public static void saveSettings(@NotNull Settings settings, @NotNull User user)
// Troubleshooting stacktraces are site-wide only
setCollectTroubleshootingStackTraces(settings._collectTroubleshootingStackTraces);

PropertyManager.PropertyMap map = PropertyManager.getWritableProperties(user, ContainerManager.getRoot(), CATEGORY, true);
WritablePropertyMap map = PropertyManager.getWritableProperties(user, ContainerManager.getRoot(), CATEGORY, true);
SETTINGS_FACTORY.toStringMap(settings, map);
map.save();
SETTINGS_CACHE.remove(user);
Expand Down
7 changes: 4 additions & 3 deletions api/src/org/labkey/api/module/FolderTypeManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.labkey.api.data.Container;
import org.labkey.api.data.ContainerManager;
import org.labkey.api.data.PropertyManager;
import org.labkey.api.data.PropertyManager.WritablePropertyMap;
import org.labkey.api.resource.Resource;
import org.labkey.api.settings.StandardStartupPropertyHandler;
import org.labkey.api.settings.StartupProperty;
Expand Down Expand Up @@ -242,7 +243,7 @@ public FolderType getDefaultFolderType()
*/
public void setEnabledFolderTypes(Collection<FolderType> enabledFolderTypes, FolderType defaultFolderType)
{
PropertyManager.PropertyMap enabledStates = PropertyManager.getWritableProperties(ContainerManager.getRoot(), FOLDER_TYPE_ENABLED_STATE, true);
WritablePropertyMap enabledStates = PropertyManager.getWritableProperties(ContainerManager.getRoot(), FOLDER_TYPE_ENABLED_STATE, true);
// Reset completely based on the supplied config
enabledStates.clear();
for (FolderType folderType : getAllFolderTypes())
Expand All @@ -253,7 +254,7 @@ public void setEnabledFolderTypes(Collection<FolderType> enabledFolderTypes, Fol

if (defaultFolderType != null && enabledFolderTypes.contains(defaultFolderType))
{
PropertyManager.PropertyMap propDefaultFolderType = PropertyManager.getWritableProperties(ContainerManager.getRoot(), FOLDER_TYPE_DEFAULT, true);
WritablePropertyMap propDefaultFolderType = PropertyManager.getWritableProperties(ContainerManager.getRoot(), FOLDER_TYPE_DEFAULT, true);
propDefaultFolderType.put(FOLDER_TYPE_DEFAULT, defaultFolderType.getName());
propDefaultFolderType.save();
}
Expand Down Expand Up @@ -349,7 +350,7 @@ private void populateDisabledFolderTypesWithStartupProps(String value)
{
if (value != null)
{
PropertyManager.PropertyMap enabledStates = PropertyManager.getWritableProperties(ContainerManager.getRoot(), FOLDER_TYPE_ENABLED_STATE, true);
WritablePropertyMap enabledStates = PropertyManager.getWritableProperties(ContainerManager.getRoot(), FOLDER_TYPE_ENABLED_STATE, true);
for (String folderTypeName : StringUtils.split(value, ';'))
enabledStates.put(folderTypeName, Boolean.toString(false));
enabledStates.save();
Expand Down
4 changes: 2 additions & 2 deletions api/src/org/labkey/api/module/ModuleProperty.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.json.JSONObject;
import org.labkey.api.audit.AbstractAuditTypeProvider;
import org.labkey.api.audit.AuditLogService;
import org.labkey.api.audit.provider.ModulePropertiesAuditProvider;
import org.labkey.api.data.Container;
import org.labkey.api.data.ContainerManager;
import org.labkey.api.data.PropertyManager;
import org.labkey.api.data.PropertyManager.WritablePropertyMap;
import org.labkey.api.security.User;
import org.labkey.api.security.permissions.AdminPermission;
import org.labkey.api.security.permissions.Permission;
Expand Down Expand Up @@ -295,7 +295,7 @@ public void saveValue(@Nullable User user, Container c, @Nullable String value)

validate(user, c, value);

PropertyManager.PropertyMap props = PropertyManager.getWritableProperties(PropertyManager.SHARED_USER, c, getCategory(), true);
WritablePropertyMap props = PropertyManager.getWritableProperties(PropertyManager.SHARED_USER, c, getCategory(), true);
Object oldValue = props.get(getName());
String auditComment;
if (!StringUtils.isEmpty(value))
Expand Down
3 changes: 2 additions & 1 deletion api/src/org/labkey/api/security/AuthenticationManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import org.labkey.api.data.Project;
import org.labkey.api.data.PropertyManager;
import org.labkey.api.data.PropertyManager.PropertyMap;
import org.labkey.api.data.PropertyManager.WritablePropertyMap;
import org.labkey.api.data.RuntimeSQLException;
import org.labkey.api.data.SimpleFilter;
import org.labkey.api.data.Table;
Expand Down Expand Up @@ -293,7 +294,7 @@ public static void saveAuthSetting(User user, String key, boolean value)

private static void saveAuthSetting(User user, String key, String value, String action)
{
PropertyMap props = PropertyManager.getWritableProperties(AUTHENTICATION_CATEGORY, true);
WritablePropertyMap props = PropertyManager.getWritableProperties(AUTHENTICATION_CATEGORY, true);
props.put(key, value);
addAuthSettingAuditEvent(user, key, action);
props.save();
Expand Down
Loading