From 876e4a399c221b1fae99ba59e1ca25f6ef34f5eb Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Sat, 7 Nov 2020 18:56:07 +0100 Subject: [PATCH] CCM Admin UI Settings Editor: Resetting to default value --- .../configuration/SettingManager.java | 111 ++++++++++++++---- .../configuration/SettingsController.java | 42 ++++++- .../ui/admin/configuration/settings.xhtml | 58 +++++++-- .../org/libreccm/ui/AdminBundle.properties | 4 + .../org/libreccm/ui/AdminBundle_de.properties | 4 + 5 files changed, 189 insertions(+), 30 deletions(-) diff --git a/ccm-core/src/main/java/org/libreccm/configuration/SettingManager.java b/ccm-core/src/main/java/org/libreccm/configuration/SettingManager.java index 753850409..257dc46af 100644 --- a/ccm-core/src/main/java/org/libreccm/configuration/SettingManager.java +++ b/ccm-core/src/main/java/org/libreccm/configuration/SettingManager.java @@ -39,6 +39,7 @@ import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.Set; import java.util.stream.Collectors; /** @@ -112,10 +113,10 @@ public class SettingManager { /** * Create a {@link SettingInfo} instance for a setting. * - * @param configuration The configuration class to which the settings - * belongs. - * @param name The name of the setting for which the - * {@link SettingInfo} is generated. + * @param configurationClass The configuration class to which the settings + * belongs. + * @param name The name of the setting for which the + * {@link SettingInfo} is generated. * * @return The {@link SettingInfo} for the provided configuration class. */ @@ -123,28 +124,29 @@ public class SettingManager { "PMD.CyclomaticComplexity", "PMD.StandardCyclomaticComplexity"}) public SettingInfo getSettingInfo( - final Class configuration, - final String name) { - if (configuration == null) { + final Class configurationClass, + final String name + ) { + if (configurationClass == null) { throw new IllegalArgumentException("Configuration can't be null"); } - if (configuration.getAnnotation(Configuration.class) == null) { + if (configurationClass.getAnnotation(Configuration.class) == null) { throw new IllegalArgumentException(String.format( "The class \"%s\" of the provided object is not annotated " + "with \"%s\".", - configuration.getClass().getName(), + configurationClass.getClass().getName(), Configuration.class.getName())); } final Field field; try { - field = configuration.getDeclaredField(name); + field = configurationClass.getDeclaredField(name); } catch (SecurityException | NoSuchFieldException ex) { LOGGER.warn(String.format( "Failed to generate SettingInfo for field \"%s\" of " + "configuration \"%s\". Ignoring field.", - configuration.getClass().getName(), + configurationClass.getClass().getName(), name), ex); return null; @@ -169,11 +171,19 @@ public class SettingManager { settingInfo.setValueType(field.getType().getName()); try { - final Constructor constructor = configuration.getConstructor(); - final Object conf = constructor.newInstance(); - final Object defaultValueObj = field.get(conf); + final Constructor constructor = configurationClass + .getConstructor(); + final Object configuration = constructor.newInstance(); + final Object defaultValueObj = field.get(configuration); final String defaultValue; - if (defaultValueObj instanceof LocalizedString) { + if (defaultValueObj instanceof List) { + @SuppressWarnings("unchecked") + final List defaultValueList + = (List) defaultValueObj; + defaultValue = defaultValueList + .stream() + .collect(Collectors.joining("\n")); + } else if (defaultValueObj instanceof LocalizedString) { final LocalizedString defaultValueLstr = (LocalizedString) defaultValueObj; defaultValue = defaultValueLstr @@ -186,24 +196,30 @@ public class SettingManager { entry.getKey().toString(), entry.getValue() ) ) - .collect(Collectors.joining(", ")); + .collect(Collectors.joining("\n")); + } else if (defaultValueObj instanceof Set) { + @SuppressWarnings("unchecked") + final Set defaultValueSet + = (Set) defaultValueObj; + defaultValue = defaultValueSet + .stream() + .collect(Collectors.joining("\n")); } else { defaultValue = Objects.toString(defaultValueObj); } settingInfo.setDefaultValue(defaultValue); - } catch (NoSuchMethodException | InstantiationException | InvocationTargetException | IllegalAccessException ex) { LOGGER.warn(String.format("Failed to create instance of \"%s\" to " + "get default values.", - configuration.getName()), + configurationClass.getName()), ex); } - settingInfo.setConfClass(configuration.getName()); - settingInfo.setDescBundle(getDescBundle(configuration)); + settingInfo.setConfClass(configurationClass.getName()); + settingInfo.setDescBundle(getDescBundle(configurationClass)); if (Strings.isBlank(settingAnnotation.labelKey())) { settingInfo.setLabelKey(String.join(".", field.getName(), @@ -257,6 +273,61 @@ public class SettingManager { } } + public Object getDefaultValue( + final Class configurationClass, + final String settingName + ) { + if (configurationClass == null) { + throw new IllegalArgumentException("Configuration can't be null"); + } + + if (configurationClass.getAnnotation(Configuration.class) == null) { + throw new IllegalArgumentException(String.format( + "The class \"%s\" of the provided object is not annotated " + + "with \"%s\".", + configurationClass.getClass().getName(), + Configuration.class.getName())); + } + + final Field field; + try { + field = configurationClass.getDeclaredField(settingName); + } catch (SecurityException | NoSuchFieldException ex) { + LOGGER.warn(String.format( + "Failed to generate SettingInfo for field \"%s\" of " + + "configuration \"%s\". Ignoring field.", + configurationClass.getClass().getName(), + settingName), + ex); + return null; + } + + //Make the field accessible even if it has a private modifier + field.setAccessible(true); + + if (field.getAnnotation(Setting.class) == null) { + return null; + } + + try { + final Constructor constructor = configurationClass + .getConstructor(); + final Object configuration = constructor.newInstance(); + final Object defaultValueObj = field.get(configuration); + + return defaultValueObj; + } catch (NoSuchMethodException + | IllegalAccessException + | InstantiationException + | InvocationTargetException ex) { + LOGGER.warn(String.format("Failed to create instance of \"%s\" to " + + "get default values.", + configurationClass.getName()), + ex); + return null; + } + } + /** * Low level method of saving a setting. * diff --git a/ccm-core/src/main/java/org/libreccm/ui/admin/configuration/SettingsController.java b/ccm-core/src/main/java/org/libreccm/ui/admin/configuration/SettingsController.java index e3b06ed17..68ac0b7bd 100644 --- a/ccm-core/src/main/java/org/libreccm/ui/admin/configuration/SettingsController.java +++ b/ccm-core/src/main/java/org/libreccm/ui/admin/configuration/SettingsController.java @@ -135,7 +135,7 @@ public class SettingsController { models.put("LocalizedStringClassName", LocalizedString.class.getName()); models.put("SetClassName", Set.class.getName()); models.put("StringClassName", String.class.getName()); - + models.put("IntegerMaxValue", Integer.toString(Integer.MAX_VALUE)); models.put("IntegerMinValue", Integer.toString(Integer.MIN_VALUE)); models.put("LongMaxValue", Long.toString(Long.MAX_VALUE)); @@ -323,6 +323,42 @@ public class SettingsController { } } + @POST + @Path("/{settingName}/reset") + @Transactional(Transactional.TxType.REQUIRED) + @AuthorizationRequired + @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) + public String resetSettingValue( + @PathParam("configurationClass") + final String configurationClassName, + @PathParam("settingName") + final String settingName, + @FormParam("confirmed") + final String confirmed + ) { + if ("true".equals(confirmed)) { + final Class configurationClass; + try { + configurationClass = Class.forName( + configurationClassName + ); + } catch (ClassNotFoundException ex) { + models.put("configurationClass", configurationClassName); + return "org/libreccm/ui/admin/configuration/configuration-class-not-found.xhtml"; + } + final SettingInfo settingInfo = settingManager.getSettingInfo( + configurationClass, settingName + ); + return updateSettingValue( + configurationClassName, + settingName, + settingInfo.getDefaultValue() + ); + } else { + return buildRedirectAfterUpdateSettingTarget(configurationClassName); + } + } + private String updateBigDecimalSetting( final String configurationClassName, final Class configurationClass, @@ -480,8 +516,8 @@ public class SettingsController { value ); } - - private String updateStringSetSetting( + + private String updateStringSetSetting( final String configurationClassName, final Class configurationClass, final Object configuration, diff --git a/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/configuration/settings.xhtml b/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/configuration/settings.xhtml index 459258429..be78558ae 100644 --- a/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/configuration/settings.xhtml +++ b/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/configuration/settings.xhtml @@ -53,16 +53,16 @@ - #{setting.defaultValue} +
#{setting.defaultValue}
- -
#{setting.value}
-
+
#{setting.value}
- #{setting.defaultValue} + +
#{setting.defaultValue}
+ + diff --git a/ccm-core/src/main/resources/org/libreccm/ui/AdminBundle.properties b/ccm-core/src/main/resources/org/libreccm/ui/AdminBundle.properties index fcb595bc5..9e60c46e0 100644 --- a/ccm-core/src/main/resources/org/libreccm/ui/AdminBundle.properties +++ b/ccm-core/src/main/resources/org/libreccm/ui/AdminBundle.properties @@ -236,3 +236,7 @@ configuration.setting.not_found.message=Setting {1} of type {2} not found in con configuration.settings.setting.dialog.value.label=Value configuration.setting.failed_to_update.title=Failed to update setting configuration.setting.failed_to_update.message=Failed to update setting {1} of configuration {0}. +configuration.settings.setting.reset.title=Reset setting {0} +configuration.settings.setting.reset.close=Cancel +configuration.settings.setting.reset.confirm=Are you sure to set reset setting {1} of configuration {0} to its default value {2}? +configuration.settings.setting.reset.submit=Reset to default value diff --git a/ccm-core/src/main/resources/org/libreccm/ui/AdminBundle_de.properties b/ccm-core/src/main/resources/org/libreccm/ui/AdminBundle_de.properties index 80a2c5a45..7a051b9ef 100644 --- a/ccm-core/src/main/resources/org/libreccm/ui/AdminBundle_de.properties +++ b/ccm-core/src/main/resources/org/libreccm/ui/AdminBundle_de.properties @@ -236,3 +236,7 @@ configuration.setting.not_found.message=Keine Einstellung {1} vom Typ {2} in Kon configuration.settings.setting.dialog.value.label=Wert configuration.setting.failed_to_update.title=Aktualisieren der Einstellung fehlgeschlagen configuration.setting.failed_to_update.message=Aktualisieren der Einstellung {1} in Konfiguration {0} fehlgeschlagen. +configuration.settings.setting.reset.title=Einstellung {0} zur\u00fccksetzen +configuration.settings.setting.reset.close=Abbrechen +configuration.settings.setting.reset.confirm=Sind Sie sicher, dass die die Einstellung {1} in Konfiguration {0} auf ihren Standardwert {2} zur\u00fccksetzen wollen? +configuration.settings.setting.reset.submit=Auf Standardwert zur\u00fccksetzen