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 c6ff18788..402754aa5 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 @@ -18,25 +18,34 @@ */ package org.libreccm.ui.admin.configuration; +import org.libreccm.configuration.AbstractSetting; import org.libreccm.configuration.ConfigurationInfo; import org.libreccm.configuration.ConfigurationManager; import org.libreccm.configuration.SettingInfo; +import org.libreccm.configuration.SettingManager; import org.libreccm.core.CoreConstants; import org.libreccm.l10n.GlobalizationHelper; +import org.libreccm.l10n.LocalizedString; import org.libreccm.l10n.LocalizedTextsUtil; import org.libreccm.security.AuthorizationRequired; import org.libreccm.security.RequiresPrivilege; +import java.math.BigDecimal; +import java.util.Arrays; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.stream.Collectors; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.mvc.Controller; import javax.mvc.Models; +import javax.ws.rs.FormParam; import javax.ws.rs.GET; +import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; @@ -48,16 +57,19 @@ import javax.ws.rs.PathParam; @RequestScoped @Path("/configuration/{configurationClass}") public class SettingsController { - + @Inject private ConfigurationManager confManager; - + @Inject private GlobalizationHelper globalizationHelper; - + @Inject private Models models; - + + @Inject + private SettingManager settingManager; + @GET @Path("/") @AuthorizationRequired @@ -67,26 +79,27 @@ public class SettingsController { ) { final Class confClass; try { - confClass = Class.forName(configurationClass); - } catch(ClassNotFoundException ex) { + confClass = Class.forName(configurationClass); + } catch (ClassNotFoundException ex) { models.put("configurationClass", configurationClass); return "org/libreccm/ui/admin/configuration/configuration-class-not-found.xhtml"; } - + final ConfigurationInfo confInfo = confManager.getConfigurationInfo( confClass ); - - final LocalizedTextsUtil textUtil = globalizationHelper.getLocalizedTextsUtil(confInfo.getDescBundle()); + + final LocalizedTextsUtil textUtil = globalizationHelper + .getLocalizedTextsUtil(confInfo.getDescBundle()); models.put( - "confLabel", + "confLabel", textUtil.getText(confInfo.getTitleKey()) ); models.put( - "configurationDesc", + "configurationDesc", textUtil.getText(confInfo.getDescKey()) ); - + final List settings = confInfo .getSettings() .entrySet() @@ -95,28 +108,342 @@ public class SettingsController { .map(this::buildSettingsTableEntry) .sorted() .collect(Collectors.toList()); - + models.put("settings", settings); - + return "org/libreccm/ui/admin/configuration/settings.xhtml"; } - + private SettingsTableEntry buildSettingsTableEntry( final SettingInfo settingInfo ) { Objects.requireNonNull(settingInfo); - + final LocalizedTextsUtil textsUtil = globalizationHelper .getLocalizedTextsUtil(settingInfo.getDescBundle()); - + final SettingsTableEntry entry = new SettingsTableEntry(); entry.setName(settingInfo.getName()); entry.setValueType(settingInfo.getValueType()); entry.setDefaultValue(settingInfo.getDefaultValue()); entry.setLabel(textsUtil.getText(settingInfo.getLabelKey())); entry.setDescription(textsUtil.getText(settingInfo.getDescKey())); - + return entry; } - + + @POST + @Path("/{settingName}") + @AuthorizationRequired + @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) + public String updateSettingValue( + @PathParam("configurationClass") final String configurationClassName, + @PathParam("settingName") final String settingName, + @FormParam("settingValue") final String valueParam + ) { + final Class confClass; + try { + confClass = 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( + confClass, settingName + ); + + final String valueType = settingInfo.getValueType(); + if (valueType.equals(BigDecimal.class.getName())) { + return updateBigDecimalSetting( + configurationClassName, settingName, valueType, valueParam + ); + } else if (valueType.equals(Boolean.class.getName()) + || valueType.equals("boolean")) { + return updateBooleanSetting( + configurationClassName, settingName, valueType, valueParam + ); + } else if (valueType.equals(Double.class.getName()) + || valueType.equals("double")) { + return updateDoubleSetting( + configurationClassName, settingName, valueType, valueParam + ); + } else if (valueType.equals(LocalizedString.class.getName())) { + return updateLocalizedStringSetting( + configurationClassName, settingName, valueType, valueParam + ); + } else if (valueType.equals(Long.class.getName()) + || valueType.equals("long")) { + return updateLongSetting( + configurationClassName, settingName, valueType, valueParam + ); + } else if (valueType.equals(List.class.getName())) { + return updateStringListSetting( + configurationClassName, settingName, valueType, valueParam + ); + } else if (valueType.equals(Set.class.getName())) { + return updateStringListSetting( + configurationClassName, settingName, valueType, valueParam + ); + } else if (valueType.equals(String.class.getName())) { + return updateStringSetting( + configurationClassName, settingName, valueType, valueParam + ); + } else { + models.put("configurationClass", configurationClassName); + models.put("settingName", settingName); + models.put("valueType", valueType); + return "org/libreccm/ui/admin/configuration/unsupported-setting-type.xhtml"; + } + } + + private String updateBigDecimalSetting( + final String configurationClassName, + final String settingName, + final String valueType, + final String valueParam + ) { + final BigDecimal value; + try { + value = new BigDecimal(valueParam); + } catch (NumberFormatException ex) { + return buildInvalidTypeErrorTarget( + configurationClassName, + settingName, + valueType, + valueParam + ); + } + + final AbstractSetting setting = settingManager + .findSetting( + configurationClassName, settingName, BigDecimal.class + ); + + if (setting == null) { + return buildSettingNotFoundErrorTarget( + configurationClassName, + settingName, + valueType + ); + } else { + setting.setValue(value); + settingManager.saveSetting(setting); + return buildRedirectAfterUpdateSettingTarget( + configurationClassName + ); + } + } + + private String updateBooleanSetting( + final String configurationClassName, + final String settingName, + final String valueType, + final String valueParam + ) { + final Boolean value = Boolean.valueOf(valueParam); + + final AbstractSetting setting = settingManager.findSetting( + configurationClassName, settingName, Boolean.class + ); + + if (setting == null) { + return buildSettingNotFoundErrorTarget( + configurationClassName, settingName, valueType + ); + } else { + setting.setValue(value); + settingManager.saveSetting(setting); + return buildRedirectAfterUpdateSettingTarget( + configurationClassName + ); + } + } + + private String updateDoubleSetting( + final String configurationClassName, + final String settingName, + final String valueType, + final String valueParam + ) { + final Double value; + try { + value = Double.valueOf(valueParam); + } catch (NumberFormatException ex) { + return buildInvalidTypeErrorTarget( + configurationClassName, + settingName, + valueType, + valueParam + ); + } + + final AbstractSetting setting = settingManager.findSetting( + configurationClassName, settingName, Double.class + ); + + if (setting == null) { + return buildSettingNotFoundErrorTarget( + configurationClassName, settingName, valueType + ); + } else { + setting.setValue(value); + settingManager.saveSetting(setting); + return buildRedirectAfterUpdateSettingTarget( + configurationClassName + ); + } + } + + private String updateLocalizedStringSetting( + final String configurationClassName, + final String settingName, + final String valueType, + final String valueParam + ) { + final LocalizedString value = new LocalizedString(); + final String[] lines = valueParam.split("\n"); + for (final String line : lines) { + final String[] tokens = line.split(":"); + if (tokens.length != 2) { + continue; + } + final Locale locale = new Locale(tokens[0]); + final String localeValue = tokens[1]; + value.addValue(locale, localeValue); + } + + final AbstractSetting setting = settingManager + .findSetting( + configurationClassName, settingName, LocalizedString.class + ); + + if (setting == null) { + return buildSettingNotFoundErrorTarget( + configurationClassName, settingName, valueType + ); + } else { + setting.setValue(value); + settingManager.saveSetting(setting); + return buildRedirectAfterUpdateSettingTarget( + configurationClassName + ); + } + } + + private String updateLongSetting( + final String configurationClassName, + final String settingName, + final String valueType, + final String valueParam + ) { + final Long value; + try { + value = Long.valueOf(valueParam, 10); + } catch (NumberFormatException ex) { + return buildInvalidTypeErrorTarget( + configurationClassName, + settingName, + valueType, + valueParam + ); + } + + final AbstractSetting setting = settingManager.findSetting( + configurationClassName, settingName, Long.class + ); + + if (setting == null) { + return buildSettingNotFoundErrorTarget( + configurationClassName, settingName, valueType + ); + } else { + setting.setValue(value); + settingManager.saveSetting(setting); + return buildRedirectAfterUpdateSettingTarget( + configurationClassName + ); + } + } + + private String updateStringListSetting( + final String configurationClassName, + final String settingName, + final String valueType, + final String valueParam + ) { + final String[] tokens = valueParam.split(","); + final List value = Arrays.asList(tokens); + + final AbstractSetting setting = settingManager.findSetting( + configurationClassName, settingName, List.class + ); + + if (setting == null) { + return buildSettingNotFoundErrorTarget( + configurationClassName, settingName, valueType + ); + } else { + setting.setValue(value); + settingManager.saveSetting(setting); + return buildRedirectAfterUpdateSettingTarget( + configurationClassName + ); + } + } + + private String updateStringSetting( + final String configurationClassName, + final String settingName, + final String valueType, + final String valueParam + ) { + final AbstractSetting setting = settingManager.findSetting( + configurationClassName, settingName, String.class + ); + + if (setting == null) { + return buildSettingNotFoundErrorTarget( + configurationClassName, settingName, valueType + ); + } else { + setting.setValue(valueParam); + settingManager.saveSetting(setting); + return buildRedirectAfterUpdateSettingTarget( + configurationClassName + ); + } + } + + private String buildInvalidTypeErrorTarget( + final String configurationClassName, + final String settingName, + final String valueType, + final String valueParam + ) { + models.put("configurationClass", configurationClassName); + models.put("settingName", settingName); + models.put("valueType", valueType); + models.put("valueParam", valueParam); + return "org/libreccm/ui/admin/configuration/invalid-setting-value.xhtml"; + } + + private String buildSettingNotFoundErrorTarget( + final String configurationClassName, + final String settingName, + final String valueType + ) { + models.put("configurationClass", configurationClassName); + models.put("settingName", settingName); + models.put("valueType", valueType); + return "org/libreccm/ui/admin/configuration/setting-not-found.xhtml"; + } + + private String buildRedirectAfterUpdateSettingTarget( + final String configurationClassName + ) { + return String.format( + "redirect:configuration/%s", configurationClassName + ); + } + } diff --git a/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/configuration/configuration-class-not-found.xhtml b/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/configuration/configuration-class-not-found.xhtml new file mode 100644 index 000000000..2ddf557dc --- /dev/null +++ b/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/configuration/configuration-class-not-found.xhtml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/configuration/invalid-setting-value.xhtml b/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/configuration/invalid-setting-value.xhtml new file mode 100644 index 000000000..9488ff48d --- /dev/null +++ b/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/configuration/invalid-setting-value.xhtml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/configuration/setting-not-found.xhtml b/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/configuration/setting-not-found.xhtml new file mode 100644 index 000000000..99de853f0 --- /dev/null +++ b/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/configuration/setting-not-found.xhtml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/configuration/unsupported-setting-type.xhtml b/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/configuration/unsupported-setting-type.xhtml new file mode 100644 index 000000000..e59cb77ba --- /dev/null +++ b/ccm-core/src/main/resources/WEB-INF/views/org/libreccm/ui/admin/configuration/unsupported-setting-type.xhtml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + 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 0ab64960d..fb8049b67 100644 --- a/ccm-core/src/main/resources/org/libreccm/ui/AdminBundle.properties +++ b/ccm-core/src/main/resources/org/libreccm/ui/AdminBundle.properties @@ -225,3 +225,11 @@ configuration.settings.setting.dialog.title=Edit setting {0} configuration.settings.setting.dialog.close=Cancel configuration.settings.setting.dialog.save=Save configuration.settings.setting.dialog.unsupported_type=Sorry, settings of type "{0}" are not supported yet. +configuration.class.not_found.title=Configuration class not found +configuration.class.not_found.message=Configuration class {0} not found +configuration.setting.type_unsupported.title=Unsupported type of setting +configuration.setting.type_unsupported.message=Type {2} of setting {1} from configuration class {0} is not supported +configuration.setting.invalid_type.title=Invalid type of value +configuration.setting.invalid_type.message=Setting {1} of configuration class {0} is of type {2} but the value {3} can be converted into this type +configuration.setting.not_found.title=Setting not found +configuration.setting.not_found.message=Setting {1} of type {2} not found in configuration class {0} 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 6a90efbca..60400040e 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 @@ -225,3 +225,11 @@ configuration.settings.setting.dialog.title=Einstellung {0} bearbeiten configuration.settings.setting.dialog.close=Abbrechen configuration.settings.setting.dialog.save=Speichern configuration.settings.setting.dialog.unsupported_type=Leider werden Einstellunge vom Typ "{0}" noch nicht unterst\u00fctzt. +configuration.class.not_found.title=Konfiguration nicht gefunden +configuration.class.not_found.message=Konfiguration {0} nicht gefunden +configuration.setting.type_unsupported.title=Typ der Einstellung nicht unterst\u00fctzt +configuration.setting.type_unsupported.message=Einstellung {1} aus Konfiguration {0} ist vom Typ {3}, dieser wird aber nicht unterst\u00fctzt +configuration.setting.invalid_type.title=Invalid type of value +configuration.setting.invalid_type.message=Einstellung {1} der Konfigurations-Klasse {0} ist vom Typ {2}, der angegebene Wert {3} kann aber nicht in diesen Typ konvertiert werden +configuration.setting.not_found.title=Einstellung nicht gefunden +configuration.setting.not_found.message=Keine Einstellung {1} vom Typ {3} in Konfiguration {0} gefunden