diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/AdminServlet.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/AdminServlet.java
index 9201daf68..5958b320e 100644
--- a/ccm-core/src/main/java/com/arsdigita/ui/admin/AdminServlet.java
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/AdminServlet.java
@@ -129,7 +129,7 @@ public class AdminServlet
new CategoriesTab());
tabbedPane.addTab(
- new Label(new GlobalizedMessage("ui.admin.tab.registry.title",
+ new Label(new GlobalizedMessage("ui.admin.tab.configuration.title",
BUNDLE_NAME)),
new RegistryAdminTab());
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/configuration/ConfigurationTab.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/configuration/ConfigurationTab.java
new file mode 100644
index 000000000..43cc04fa4
--- /dev/null
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/configuration/ConfigurationTab.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2016 LibreCCM Foundation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+package com.arsdigita.ui.admin.configuration;
+
+import com.arsdigita.bebop.ActionLink;
+import com.arsdigita.bebop.BoxPanel;
+import com.arsdigita.bebop.Form;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.Page;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.ParameterSingleSelectionModel;
+import com.arsdigita.bebop.SegmentedPanel;
+import com.arsdigita.bebop.form.Submit;
+import com.arsdigita.bebop.form.TextField;
+import com.arsdigita.bebop.parameters.StringParameter;
+import com.arsdigita.globalization.GlobalizedMessage;
+import com.arsdigita.toolbox.ui.LayoutPanel;
+
+import static com.arsdigita.ui.admin.AdminUiConstants.*;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+public class ConfigurationTab extends LayoutPanel {
+
+ private static final String CONF_CLASSES_FILTER = "confClassesFilter";
+
+ private final StringParameter selectedConfParam;
+ private final ParameterSingleSelectionModel selectedConf;
+
+ private final StringParameter selectedSettingParam;
+ private final ParameterSingleSelectionModel selectedSetting;
+
+ private final Label confClassesFilterHeading;
+ private final Form confClassesFilterForm;
+ private final ConfigurationsTable configurationsTable;
+
+ public ConfigurationTab() {
+ super();
+
+ setClassAttr("sidebarNavPanel");
+
+ selectedConfParam = new StringParameter("selectedConfiguration");
+ selectedConf = new ParameterSingleSelectionModel<>(selectedConfParam);
+
+ selectedSettingParam = new StringParameter("selectedSetting");
+ selectedSetting = new ParameterSingleSelectionModel<>(
+ selectedSettingParam);
+
+ final SegmentedPanel left = new SegmentedPanel();
+
+ confClassesFilterHeading = new Label(new GlobalizedMessage(
+ "ui.admin.configuration.classes.filter.heading", ADMIN_BUNDLE));
+
+ confClassesFilterForm = new Form("confClassesForm");
+ final TextField confClassesFilter = new TextField(CONF_CLASSES_FILTER);
+ confClassesFilterForm.add(confClassesFilter);
+ confClassesFilterForm.add(new Submit(new GlobalizedMessage(
+ "ui.admin.configuration.classes.filter.submit", ADMIN_BUNDLE)));
+ final ActionLink clearLink = new ActionLink(new GlobalizedMessage(
+ "ui.admin.configuration.classes.filter.clear", ADMIN_BUNDLE));
+ clearLink.addActionListener(e -> {
+ final PageState state = e.getPageState();
+ confClassesFilter.setValue(state, null);
+ });
+ confClassesFilterForm.add(clearLink);
+ left.addSegment(confClassesFilterHeading, confClassesFilterForm);
+
+ setLeft(left);
+
+ final BoxPanel body = new BoxPanel(BoxPanel.VERTICAL);
+ configurationsTable = new ConfigurationsTable(
+ this, selectedConf, confClassesFilter);
+ body.add(configurationsTable);
+
+ setBody(body);
+ }
+
+ @Override
+ public void register(final Page page) {
+ super.register(page);
+
+ page.setVisibleDefault(confClassesFilterHeading, true);
+ page.setVisibleDefault(confClassesFilterForm, true);
+ page.setVisibleDefault(configurationsTable, true);
+ }
+
+ protected void showConfigurationsTable(final PageState state) {
+ confClassesFilterHeading.setVisible(state, true);
+ confClassesFilterForm.setVisible(state, true);
+ configurationsTable.setVisible(state, true);
+ }
+
+ protected void hideConfigurationsTable(final PageState state) {
+ confClassesFilterHeading.setVisible(state, false);
+ confClassesFilterForm.setVisible(state, false);
+ configurationsTable.setVisible(state, false);
+ }
+
+ protected void showConfiguration(final PageState state) {
+ hideConfigurationsTable(state);
+
+ }
+
+ protected void hideConfiguration(final PageState state) {
+
+ showConfigurationsTable(state);
+ }
+
+}
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/configuration/ConfigurationTable.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/configuration/ConfigurationTable.java
new file mode 100644
index 000000000..7c6b28c4b
--- /dev/null
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/configuration/ConfigurationTable.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2016 LibreCCM Foundation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+package com.arsdigita.ui.admin.configuration;
+
+import com.arsdigita.bebop.Component;
+import com.arsdigita.bebop.ControlLink;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.ParameterSingleSelectionModel;
+import com.arsdigita.bebop.Table;
+import com.arsdigita.bebop.event.TableActionEvent;
+import com.arsdigita.bebop.event.TableActionListener;
+import com.arsdigita.bebop.table.TableCellRenderer;
+import com.arsdigita.bebop.table.TableColumn;
+import com.arsdigita.bebop.table.TableColumnModel;
+import com.arsdigita.bebop.table.TableModel;
+import com.arsdigita.bebop.table.TableModelBuilder;
+import com.arsdigita.globalization.GlobalizedMessage;
+import com.arsdigita.util.LockableImpl;
+import com.arsdigita.util.UncheckedWrapperException;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.libreccm.cdi.utils.CdiUtil;
+import org.libreccm.configuration.ConfigurationManager;
+import org.libreccm.configuration.SettingInfo;
+import org.libreccm.configuration.SettingManager;
+import org.libreccm.l10n.GlobalizationHelper;
+
+import java.util.List;
+import java.util.logging.Level;
+
+import static com.arsdigita.ui.admin.AdminUiConstants.*;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+public class ConfigurationTable extends Table {
+
+ private static final Logger LOGGER = LogManager.getLogger(
+ ConfigurationTable.class);
+
+ private static final int COL_SETTING_LABEL = 0;
+ private static final int COL_SETTING_VALUE = 1;
+ private static final int COL_SETTING_DESC = 2;
+ private static final int COL_EDIT_SETTING = 3;
+
+ private ParameterSingleSelectionModel selectedConf;
+
+ public ConfigurationTable(
+ final ConfigurationTab configurationTab,
+ final ParameterSingleSelectionModel selectedConf,
+ final ParameterSingleSelectionModel selectedSetting) {
+
+ super();
+
+ setIdAttr("configurationTable");
+
+ this.selectedConf = selectedConf;
+
+ setEmptyView(new Label(new GlobalizedMessage(
+ "ui.admin.configuration.settings.none", ADMIN_BUNDLE)));
+
+ final TableColumnModel columnModel = getColumnModel();
+ columnModel.add(new TableColumn(
+ COL_SETTING_LABEL,
+ new Label(new GlobalizedMessage(
+ "ui.admin.configuration.settings.table.col_setting_label.header",
+ ADMIN_BUNDLE))));
+ columnModel.add(new TableColumn(
+ COL_SETTING_VALUE,
+ new Label(new GlobalizedMessage(
+ "ui.admin.configuration.settings.table.col_setting_value.header",
+ ADMIN_BUNDLE))));
+ columnModel.add(new TableColumn(
+ COL_SETTING_DESC,
+ new Label(new GlobalizedMessage(
+ "ui.admin.configuration.settings.table.col_setting_desc.header",
+ ADMIN_BUNDLE))));
+ columnModel.add(new TableColumn(
+ COL_EDIT_SETTING,
+ new Label(new GlobalizedMessage(
+ "ui.admin.configuration.settings.table.col_edit_setting.header",
+ ADMIN_BUNDLE))));
+
+ columnModel.get(COL_EDIT_SETTING).setCellRenderer(
+ new TableCellRenderer() {
+
+ @Override
+ public Component getComponent(final Table table,
+ final PageState state,
+ final Object value,
+ final boolean isSelected,
+ final Object key,
+ final int row,
+ final int column) {
+ return new ControlLink((String) value);
+ }
+
+ });
+
+ addTableActionListener(new TableActionListener() {
+
+ @Override
+ public void cellSelected(final TableActionEvent event) {
+ final PageState state = event.getPageState();
+
+ if (event.getColumn() == COL_EDIT_SETTING) {
+ final String settingName = (String) event.getRowKey();
+ selectedSetting.setSelectedKey(state, settingName);
+ }
+ }
+
+ @Override
+ public void headSelected(final TableActionEvent event) {
+ //Nothing
+ }
+
+ });
+
+ setModelBuilder(new ConfigurationTableModelBuilder());
+ }
+
+ private class ConfigurationTableModelBuilder
+ extends LockableImpl implements TableModelBuilder {
+
+ @Override
+ public TableModel makeModel(final Table table, final PageState state) {
+ final ConfigurationManager confManager = CdiUtil.createCdiUtil()
+ .findBean(ConfigurationManager.class);
+ final Class> confClass;
+ try {
+ confClass = Class.forName(selectedConf.getSelectedKey(state));
+ } catch (ClassNotFoundException ex) {
+ LOGGER.error("Configuration class '{}' not found.",
+ selectedConf.getSelectedKey(state));
+ throw new UncheckedWrapperException(String.format(
+ "Configuration class '%s not found'",
+ selectedConf.getSelectedKey(state)), ex);
+ }
+
+ final Object configuration = confManager
+ .findConfiguration(confClass);
+
+ return new ConfigurationTableModel(configuration, state);
+ }
+
+ }
+
+ private class ConfigurationTableModel implements TableModel {
+
+ private final Object configuration;
+
+ private final ConfigurationManager confManager;
+ private final SettingManager settingManager;
+ private final GlobalizationHelper globalizationHelper;
+
+ private final List settings;
+ private int index = -1;
+
+ public ConfigurationTableModel(final Object configuration,
+ final PageState state) {
+ this.configuration = configuration;
+
+ final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
+ confManager = cdiUtil.findBean(ConfigurationManager.class);
+ settingManager = cdiUtil.findBean(SettingManager.class);
+ globalizationHelper = cdiUtil.findBean(GlobalizationHelper.class);
+
+ settings = settingManager.getAllSettings(configuration.getClass());
+ }
+
+ @Override
+ public int getColumnCount() {
+ return 4;
+ }
+
+ @Override
+ public boolean nextRow() {
+ index++;
+ return index < settings.size();
+ }
+
+ @Override
+ public Object getElementAt(final int columnIndex) {
+ final String setting = settings.get(index);
+ final SettingInfo settingInfo = settingManager.getSettingInfo(
+ configuration.getClass(), setting);
+
+ switch (columnIndex) {
+ case COL_SETTING_LABEL:
+ return settingInfo.getLabel(globalizationHelper
+ .getNegotiatedLocale());
+ case COL_SETTING_VALUE: {
+ try {
+ return configuration.getClass().getField(setting).get(
+ configuration);
+ } catch (NoSuchFieldException | SecurityException | IllegalAccessException ex) {
+ LOGGER.error("Failed to read value from configuration.",
+ ex);
+ return new Label(new GlobalizedMessage(
+ "ui.admin.configuration.settings.read_error",
+ ADMIN_BUNDLE));
+ }
+ }
+ case COL_SETTING_DESC:
+ return settingInfo.getDescription(globalizationHelper
+ .getNegotiatedLocale());
+ case COL_EDIT_SETTING:
+ return new Label(new GlobalizedMessage(
+ "ui.admin.configuration.settings.edit", ADMIN_BUNDLE));
+ default:
+ throw new IllegalArgumentException("Illegal column index");
+ }
+ }
+
+ @Override
+ public Object getKeyAt(final int columnIndex) {
+ return settings.get(index);
+ }
+
+ }
+
+}
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/configuration/ConfigurationsTable.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/configuration/ConfigurationsTable.java
new file mode 100644
index 000000000..feae8a213
--- /dev/null
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/configuration/ConfigurationsTable.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2016 LibreCCM Foundation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+package com.arsdigita.ui.admin.configuration;
+
+import com.arsdigita.bebop.Component;
+import com.arsdigita.bebop.ControlLink;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.ParameterSingleSelectionModel;
+import com.arsdigita.bebop.Table;
+import com.arsdigita.bebop.event.TableActionEvent;
+import com.arsdigita.bebop.event.TableActionListener;
+import com.arsdigita.bebop.form.TextField;
+import com.arsdigita.bebop.table.TableCellRenderer;
+import com.arsdigita.bebop.table.TableColumn;
+import com.arsdigita.bebop.table.TableColumnModel;
+import com.arsdigita.bebop.table.TableModel;
+import com.arsdigita.bebop.table.TableModelBuilder;
+import com.arsdigita.globalization.GlobalizedMessage;
+import com.arsdigita.util.LockableImpl;
+
+import org.apache.logging.log4j.util.Strings;
+import org.libreccm.cdi.utils.CdiUtil;
+import org.libreccm.configuration.ConfigurationInfo;
+import org.libreccm.configuration.ConfigurationManager;
+import org.libreccm.l10n.GlobalizationHelper;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.SortedSet;
+import java.util.stream.Collectors;
+
+import static com.arsdigita.ui.admin.AdminUiConstants.*;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+public class ConfigurationsTable extends Table {
+
+ private static final int COL_TITLE = 0;
+ private static final int COL_DESC = 1;
+
+ public ConfigurationsTable(
+ final ConfigurationTab configurationTab,
+ final ParameterSingleSelectionModel selectedConf,
+ final TextField confClassesFilter) {
+
+ super();
+
+ setIdAttr("configurationsTable");
+
+ setEmptyView(new Label(new GlobalizedMessage(
+ "ui.admin.configuration.configurations.none", ADMIN_BUNDLE)));
+
+ final TableColumnModel columnModel = getColumnModel();
+ columnModel.add(new TableColumn(
+ COL_TITLE,
+ new Label(new GlobalizedMessage(
+ "ui.admin.configuration.configurations.table.name",
+ ADMIN_BUNDLE))));
+ columnModel.add(new TableColumn(
+ COL_DESC,
+ new Label(new GlobalizedMessage(
+ "ui.admin.configuration.configurations.table.desc",
+ ADMIN_BUNDLE))));
+
+ columnModel.get(COL_TITLE).setCellRenderer(new TableCellRenderer() {
+
+ @Override
+ public Component getComponent(final Table table,
+ final PageState state,
+ final Object value,
+ final boolean isSelected,
+ final Object key,
+ final int row,
+ final int column) {
+ return new ControlLink((String) value);
+ }
+
+ });
+
+ addTableActionListener(new TableActionListener() {
+
+ @Override
+ public void cellSelected(final TableActionEvent event) {
+ final PageState state = event.getPageState();
+
+ if (event.getColumn() == COL_TITLE) {
+ final String confClassName = (String) event.getRowKey();
+ selectedConf.setSelectedKey(state, confClassName);
+ }
+ }
+
+ @Override
+ public void headSelected(final TableActionEvent event) {
+ //Nothing
+ }
+
+ });
+
+ setModelBuilder(new ConfigurationsTableModelBuilder(confClassesFilter));
+ }
+
+ private class ConfigurationsTableModelBuilder
+ extends LockableImpl implements TableModelBuilder {
+
+ private final TextField confClassesFilter;
+
+ public ConfigurationsTableModelBuilder(
+ final TextField confClassesField) {
+
+ this.confClassesFilter = confClassesField;
+ }
+
+ @Override
+ public TableModel makeModel(final Table table,
+ final PageState state) {
+ table.getRowSelectionModel().clearSelection(state);
+
+ return new ConfigurationsTableModel(confClassesFilter, state);
+ }
+
+ }
+
+ private class ConfigurationsTableModel implements TableModel {
+
+ private final List> configurations;
+ private int index = -1;
+ private final ConfigurationManager confManager;
+ private final Locale negoiatedLocale;
+
+ public ConfigurationsTableModel(final TextField confClassesFilter,
+ final PageState state) {
+ final String filterTerm = (String) confClassesFilter
+ .getValue(state);
+ final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
+ confManager = cdiUtil.findBean(ConfigurationManager.class);
+ final GlobalizationHelper globalizationHelper = cdiUtil.findBean(
+ GlobalizationHelper.class);
+ negoiatedLocale = globalizationHelper.getNegotiatedLocale();
+ final SortedSet> confs = confManager
+ .findAllConfigurations();
+ configurations = confs.stream()
+ .filter(c -> {
+ final ConfigurationInfo info = confManager
+ .getConfigurationInfo(c);
+// return c.getName().startsWith(filterTerm);
+ return info.getTitle(negoiatedLocale).startsWith(filterTerm);
+ })
+ .collect(Collectors.toCollection(ArrayList::new));
+ configurations.sort((c1, c2) -> {
+// return c1.getName().compareTo(c2.getName());
+ final ConfigurationInfo info1 = confManager
+ .getConfigurationInfo(c1);
+ final ConfigurationInfo info2 = confManager
+ .getConfigurationInfo(c2);
+
+ return info1.getTitle(negoiatedLocale)
+ .compareTo(info2.getTitle(negoiatedLocale));
+ });
+ }
+
+ @Override
+ public int getColumnCount() {
+ return 2;
+ }
+
+ @Override
+ public boolean nextRow() {
+ index++;
+ return index < configurations.size();
+ }
+
+ @Override
+ public Object getElementAt(final int columnIndex) {
+ final ConfigurationInfo info = confManager.getConfigurationInfo(
+ configurations.get(index));
+ switch (columnIndex) {
+ case COL_TITLE:
+ if (Strings.isBlank(info.getTitle(negoiatedLocale))) {
+ return configurations.get(index).getSimpleName();
+ } else {
+ return info.getTitle(negoiatedLocale);
+ }
+ case COL_DESC:
+ return info.getDescription(negoiatedLocale);
+ default:
+ throw new IllegalArgumentException("Illegal column index");
+ }
+ }
+
+ @Override
+ public Object getKeyAt(final int columnIndex) {
+ return configurations.get(index).getName();
+ }
+
+ }
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/configuration/Configuration.java b/ccm-core/src/main/java/org/libreccm/configuration/Configuration.java
index aad4a85fd..1e9d811f6 100644
--- a/ccm-core/src/main/java/org/libreccm/configuration/Configuration.java
+++ b/ccm-core/src/main/java/org/libreccm/configuration/Configuration.java
@@ -18,7 +18,6 @@
*/
package org.libreccm.configuration;
-import org.libreccm.configuration.*;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -26,37 +25,44 @@ import java.lang.annotation.Target;
import java.util.ResourceBundle;
/**
- * Marks a class as configuration class which is managed by the
+ * Marks a class as configuration class which is managed by the
* {@link ConfigurationManager}.
- *
+ *
* @author Jens Pelzetter
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Configuration {
-
+
/**
* The name of the configuration. If left blank the simple name of the class
* is used.
- *
+ *
* @return Name of the configuration.
*/
//String name() default "";
-
/**
- * Points to the {@link ResourceBundle} containing the descriptions
- * of the configuration and all entries of the configuration.
- *
+ * Points to the {@link ResourceBundle} containing the descriptions of the
+ * configuration and all entries of the configuration.
+ *
* @return Fully qualified name of the {@link ResourceBundle}.
*/
String descBundle() default "";
-
+
/**
- * Key of the description of the configuration in the resource bundle
- * provided by {@link #descBundle()}.
+ * Key of the title of the description in the resource bundle provided by
+ * {@link #descBundle()}.
*
+ * @return Key of the title
+ */
+ String titleKey() default "";
+
+ /**
+ * Key of the description of the configuration in the resource bundle
+ * provided by {@link #descBundle()}.
+ *
* @return Key of the description.
*/
String descKey() default "";
-
+
}
diff --git a/ccm-core/src/main/java/org/libreccm/configuration/ConfigurationInfo.java b/ccm-core/src/main/java/org/libreccm/configuration/ConfigurationInfo.java
index c6f808be0..c53f49564 100644
--- a/ccm-core/src/main/java/org/libreccm/configuration/ConfigurationInfo.java
+++ b/ccm-core/src/main/java/org/libreccm/configuration/ConfigurationInfo.java
@@ -26,8 +26,7 @@ import java.util.ResourceBundle;
import java.util.TreeMap;
/**
- * Describes a configuration. Useful for generating user
- * interfaces.
+ * Describes a configuration. Useful for generating user interfaces.
*
* @author Jens Pelzetter
*/
@@ -44,6 +43,8 @@ public final class ConfigurationInfo {
*/
private String descBundle;
+ private String titleKey;
+
/**
* The key for the description of the configuration in the resource bundle.
*/
@@ -79,6 +80,14 @@ public final class ConfigurationInfo {
return ResourceBundle.getBundle(descBundle);
}
+ public String getTitleKey() {
+ return titleKey;
+ }
+
+ void setTitleKey(final String titleKey) {
+ this.titleKey = titleKey;
+ }
+
public String getDescKey() {
return descKey;
}
@@ -87,6 +96,10 @@ public final class ConfigurationInfo {
this.descKey = descKey;
}
+ public String getTitle(final Locale locale) {
+ return getDescriptionBundle(locale).getString(titleKey);
+ }
+
public String getDescription(final Locale locale) {
return getDescriptionBundle(locale).getString(descKey);
}
diff --git a/ccm-core/src/main/java/org/libreccm/configuration/ConfigurationManager.java b/ccm-core/src/main/java/org/libreccm/configuration/ConfigurationManager.java
index 01aa14bfd..95e7c7e23 100644
--- a/ccm-core/src/main/java/org/libreccm/configuration/ConfigurationManager.java
+++ b/ccm-core/src/main/java/org/libreccm/configuration/ConfigurationManager.java
@@ -19,12 +19,21 @@
package org.libreccm.configuration;
import java.lang.reflect.Field;
+
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
-import javax.persistence.EntityManager;
import javax.transaction.Transactional;
+
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.util.Strings;
+import org.libreccm.modules.CcmModule;
+import org.libreccm.modules.Module;
+
+import java.util.Arrays;
+import java.util.ServiceLoader;
+import java.util.SortedSet;
+import java.util.TreeSet;
/**
* Maps between configuration classes and the settings stored in the database.
@@ -43,9 +52,37 @@ public class ConfigurationManager {
@Inject
private SettingConverter settingConverter;
- @Inject
- private EntityManager entityManager;
+ /**
+ * Finds all configuration classes listed by the installed modules.
+ *
+ * @return A sorted set containing all configuration classes.
+ *
+ * @see Module#configurations()
+ */
+ public SortedSet> findAllConfigurations() {
+ final ServiceLoader modules = ServiceLoader.load(
+ CcmModule.class);
+
+ final SortedSet> configurations = new TreeSet<>((c1, c2) -> {
+ return c1.getName().compareTo(c2.getName());
+ });
+
+ for(CcmModule module : modules) {
+ final Module annotation = module.getClass().getAnnotation(
+ Module.class);
+
+ if (annotation == null) {
+ continue;
+ }
+
+ Arrays.stream(annotation.configurations()).forEach(c -> {
+ configurations.add(c);
+ });
+ }
+ return configurations;
+ }
+
/**
* Load all settings of the provided configuration class.
*
@@ -170,8 +207,12 @@ public class ConfigurationManager {
} else {
confInfo.setDescBundle(annotation.descBundle());
}
- if (annotation.descKey() == null
- || annotation.descKey().isEmpty()) {
+ if (Strings.isBlank(annotation.titleKey())) {
+ confInfo.setTitleKey("title");
+ } else {
+ confInfo.setTitleKey(annotation.titleKey());
+ }
+ if (Strings.isBlank(annotation.descKey())) {
confInfo.setDescKey("description");
} else {
confInfo.setDescKey(annotation.descKey());
diff --git a/ccm-core/src/main/java/org/libreccm/configuration/SettingInfo.java b/ccm-core/src/main/java/org/libreccm/configuration/SettingInfo.java
index 2a76b2937..d1c7fc12a 100644
--- a/ccm-core/src/main/java/org/libreccm/configuration/SettingInfo.java
+++ b/ccm-core/src/main/java/org/libreccm/configuration/SettingInfo.java
@@ -114,6 +114,10 @@ public final class SettingInfo {
void setLabelKey(final String labelKey) {
this.labelKey = labelKey;
}
+
+ public String getLabel(final Locale locale) {
+ return getDescriptionBundle(locale).getString(labelKey);
+ }
public String getDescKey() {
return descKey;
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 015479272..9f699e9f2 100644
--- a/ccm-core/src/main/java/org/libreccm/configuration/SettingManager.java
+++ b/ccm-core/src/main/java/org/libreccm/configuration/SettingManager.java
@@ -20,13 +20,18 @@ package org.libreccm.configuration;
import java.lang.reflect.Field;
import java.util.List;
+
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import javax.transaction.Transactional;
+
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.util.Strings;
+
+import java.util.ArrayList;
/**
*
@@ -43,18 +48,55 @@ import org.apache.logging.log4j.Logger;
public class SettingManager {
private static final Logger LOGGER = LogManager.getLogger(
- SettingManager.class);
+ SettingManager.class);
@Inject
private EntityManager entityManager;
+ /**
+ * Get the names of all settings of a configuration class.
+ *
+ * @param configuration The configuration class for which the settings are
+ * retrieved.
+ *
+ * @return A list with the names of all settings provided by the
+ * configuration class.
+ */
+ public List getAllSettings(final Class> configuration) {
+ if (configuration == null) {
+ throw new IllegalArgumentException("Configuration can't be null");
+ }
+
+ if (configuration.getAnnotation(Configuration.class) == null) {
+ throw new IllegalArgumentException(String.format(
+ "The class \"%s\" of the provided object is not annotated "
+ + "with \"%s\".",
+ configuration.getClass().getName(),
+ Configuration.class.getName()));
+ }
+
+ final List settings = new ArrayList<>();
+ final Field[] fields = configuration.getDeclaredFields();
+ for (Field field : fields) {
+ if (field.getAnnotation(Setting.class) != null) {
+ settings.add(field.getName());
+ }
+ }
+
+ settings.sort((s1, s2) -> {
+ return s1.compareTo(s2);
+ });
+
+ return settings;
+ }
+
/**
* 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.
+ * belongs.
+ * @param name The name of the setting for which the
+ * {@link SettingInfo} is generated.
*
* @return The {@link SettingInfo} for the provided configuration class.
*/
@@ -62,18 +104,18 @@ public class SettingManager {
"PMD.CyclomaticComplexity",
"PMD.StandardCyclomaticComplexity"})
public SettingInfo getSettingInfo(
- final Class> configuration,
- final String name) {
+ final Class> configuration,
+ final String name) {
if (configuration == null) {
throw new IllegalArgumentException("Configuration can't be null");
}
if (configuration.getAnnotation(Configuration.class) == null) {
throw new IllegalArgumentException(String.format(
- "The class \"%s\" of the provided object is not annotated "
- + "with \"%s\".",
- configuration.getClass().getName(),
- Configuration.class.getName()));
+ "The class \"%s\" of the provided object is not annotated "
+ + "with \"%s\".",
+ configuration.getClass().getName(),
+ Configuration.class.getName()));
}
final Field field;
@@ -81,10 +123,10 @@ public class SettingManager {
field = configuration.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(),
- name),
+ "Failed to generate SettingInfo for field \"%s\" of "
+ + "configuration \"%s\". Ignoring field.",
+ configuration.getClass().getName(),
+ name),
ex);
return null;
}
@@ -96,7 +138,7 @@ public class SettingManager {
final Setting settingAnnotation = field.getAnnotation(Setting.class);
final SettingInfo settingInfo = new SettingInfo();
if (settingAnnotation.name() == null
- || settingAnnotation.name().isEmpty()) {
+ || settingAnnotation.name().isEmpty()) {
settingInfo.setName(field.getName());
} else {
settingInfo.setName(settingAnnotation.name());
@@ -109,7 +151,7 @@ public class SettingManager {
settingInfo.setDefaultValue(field.get(conf).toString());
} catch (InstantiationException | IllegalAccessException ex) {
LOGGER.warn(String.format("Failed to create instance of \"%s\" to "
- + "get default values.",
+ + "get default values.",
configuration.getName()),
ex);
}
@@ -117,16 +159,14 @@ public class SettingManager {
settingInfo.setConfClass(configuration.getName());
settingInfo.setDescBundle(getDescBundle(configuration));
- if (settingAnnotation.labelKey() == null
- || settingAnnotation.labelKey().isEmpty()) {
+ if (Strings.isBlank(settingAnnotation.labelKey())) {
settingInfo.setLabelKey(String.join(".", field.getName(),
"label"));
} else {
settingInfo.setLabelKey(name);
}
- if (settingAnnotation.descKey() == null
- || settingAnnotation.descKey().isEmpty()) {
+ if (Strings.isBlank(settingAnnotation.descKey())) {
settingInfo.setDescKey(String.join(".",
field.getName(),
"descripotion"));
@@ -140,25 +180,25 @@ public class SettingManager {
/**
* A low level method for finding a setting in the registry.
*
- * @param Type of the value of the setting
+ * @param Type of the value of the setting
* @param confName Name of the configuration to which the setting belongs
- * @param name The fully qualified name of the setting.
- * @param clazz The class of the setting.
+ * @param name The fully qualified name of the setting.
+ * @param clazz The class of the setting.
*
* @return The requested setting if it exists in the registry, {@code null}
- * otherwise.
+ * otherwise.
*/
public AbstractSetting findSetting(final String confName,
final String name,
final Class clazz) {
LOGGER.debug(String.format(
- "Trying to find setting \"%s\" of type \"%s\"",
- name,
- clazz.getName()));
+ "Trying to find setting \"%s\" of type \"%s\"",
+ name,
+ clazz.getName()));
final TypedQuery query = entityManager.
- createNamedQuery("AbstractSetting.findByClassAndName",
- AbstractSetting.class);
+ createNamedQuery("AbstractSetting.findByClassAndName",
+ AbstractSetting.class);
query.setParameter("class", confName);
query.setParameter("name", name);
final List result = query.getResultList();
@@ -185,9 +225,9 @@ public class SettingManager {
private String getDescBundle(final Class> configuration) {
final Configuration confAnnotation = configuration.getAnnotation(
- Configuration.class);
+ Configuration.class);
if (confAnnotation.descBundle() == null
- || confAnnotation.descBundle().isEmpty()) {
+ || confAnnotation.descBundle().isEmpty()) {
return String.join("",
configuration.getClass().getName(),
"Description");
@@ -195,4 +235,5 @@ public class SettingManager {
return confAnnotation.descBundle();
}
}
+
}
diff --git a/ccm-core/src/main/java/org/libreccm/core/CcmCore.java b/ccm-core/src/main/java/org/libreccm/core/CcmCore.java
index d4965303a..6ddd3e18a 100644
--- a/ccm-core/src/main/java/org/libreccm/core/CcmCore.java
+++ b/ccm-core/src/main/java/org/libreccm/core/CcmCore.java
@@ -18,12 +18,18 @@
*/
package org.libreccm.core;
+import com.arsdigita.bebop.BebopConfig;
+import com.arsdigita.kernel.KernelConfig;
+import com.arsdigita.mail.MailConfig;
+import com.arsdigita.notification.NotificationConfig;
import com.arsdigita.ui.admin.AdminApplicationCreator;
import com.arsdigita.ui.admin.AdminServlet;
import com.arsdigita.ui.admin.AdminApplicationSetup;
import com.arsdigita.ui.login.LoginApplicationCreator;
import com.arsdigita.ui.login.LoginServlet;
import com.arsdigita.ui.login.LoginApplicationSetup;
+import com.arsdigita.workflow.simple.WorkflowConfig;
+import com.arsdigita.xml.XmlConfig;
import org.libreccm.modules.CcmModule;
import org.libreccm.modules.InitEvent;
@@ -31,9 +37,10 @@ import org.libreccm.modules.InstallEvent;
import org.libreccm.modules.Module;
import org.libreccm.modules.ShutdownEvent;
import org.libreccm.modules.UnInstallEvent;
+import org.libreccm.security.EmailTemplates;
+import org.libreccm.security.OneTimeAuthConfig;
import org.libreccm.security.SystemUsersSetup;
-
import org.libreccm.web.ApplicationType;
/**
@@ -51,48 +58,23 @@ import org.libreccm.web.ApplicationType;
singleton = true,
creator = AdminApplicationCreator.class,
servlet = AdminServlet.class)},
- entities = {org.libreccm.auditing.CcmRevision.class,
- org.libreccm.categorization.Categorization.class,
- org.libreccm.categorization.Category.class,
- org.libreccm.categorization.Domain.class,
- org.libreccm.categorization.DomainOwnership.class,
- org.libreccm.core.CcmObject.class,
- org.libreccm.core.Resource.class,
- org.libreccm.core.ResourceType.class,
- org.libreccm.modules.InstalledModule.class,
- org.libreccm.formbuilder.Component.class,
- org.libreccm.formbuilder.DataDrivenSelect.class,
- org.libreccm.formbuilder.FormSection.class,
- org.libreccm.formbuilder.Listener.class,
- org.libreccm.formbuilder.MetaObject.class,
- org.libreccm.formbuilder.ObjectType.class,
- org.libreccm.formbuilder.Option.class,
- org.libreccm.formbuilder.PersistentDataQuery.class,
- org.libreccm.formbuilder.ProcessListener.class,
- org.libreccm.formbuilder.Widget.class,
- org.libreccm.formbuilder.WidgetLabel.class,
- org.libreccm.formbuilder.actions.ConfirmEmailListener.class,
- org.libreccm.formbuilder.actions.ConfirmRedirectListener.class,
- org.libreccm.formbuilder.actions.RemoteServerPostListener.class,
- org.libreccm.formbuilder.actions.SimpleEmailListener.class,
- org.libreccm.formbuilder.actions.TemplateEmailListener.class,
- org.libreccm.formbuilder.actions.XmlEmailListener.class,
- org.libreccm.messaging.Attachment.class,
- org.libreccm.messaging.Message.class,
- org.libreccm.messaging.MessageThread.class,
- org.libreccm.notification.Digest.class,
- org.libreccm.notification.Notification.class,
- org.libreccm.notification.QueueItem.class,
- org.libreccm.portal.Portal.class,
- org.libreccm.portal.Portlet.class,
- org.libreccm.runtime.Initalizer.class,
- org.libreccm.search.lucene.Document.class,
- org.libreccm.search.lucene.Index.class,
- org.libreccm.web.CcmApplication.class,
- org.libreccm.web.Host.class,
- org.libreccm.workflow.Task.class,
- org.libreccm.workflow.UserTask.class,
- org.libreccm.workflow.Workflow.class})
+ configurations = {
+ com.arsdigita.bebop.BebopConfig.class,
+ com.arsdigita.dispatcher.DispatcherConfig.class,
+ com.arsdigita.globalization.GlobalizationConfig.class,
+ com.arsdigita.kernel.KernelConfig.class,
+ com.arsdigita.kernel.security.SecurityConfig.class,
+ com.arsdigita.mail.MailConfig.class,
+ com.arsdigita.notification.NotificationConfig.class,
+ com.arsdigita.templating.TemplatingConfig.class,
+ com.arsdigita.ui.UIConfig.class,
+ com.arsdigita.web.WebConfig.class,
+ com.arsdigita.workflow.simple.WorkflowConfig.class,
+ com.arsdigita.xml.XmlConfig.class,
+ com.arsdigita.xml.formatters.DateFormatterConfig.class,
+ org.libreccm.security.EmailTemplates.class,
+ org.libreccm.security.OneTimeAuthConfig.class,
+ })
public class CcmCore implements CcmModule {
@Override
@@ -100,13 +82,15 @@ public class CcmCore implements CcmModule {
// final EntityManager entityManager = event.getEntityManager();
final SystemUsersSetup systemUsersSetup = new SystemUsersSetup(
- event);
+ event);
systemUsersSetup.setupSystemUsers();
- final AdminApplicationSetup adminSetup = new AdminApplicationSetup(event);
+ final AdminApplicationSetup adminSetup
+ = new AdminApplicationSetup(event);
adminSetup.setup();
-
- final LoginApplicationSetup loginSetup = new LoginApplicationSetup(event);
+
+ final LoginApplicationSetup loginSetup
+ = new LoginApplicationSetup(event);
loginSetup.setup();
}
diff --git a/ccm-core/src/main/java/org/libreccm/modules/Module.java b/ccm-core/src/main/java/org/libreccm/modules/Module.java
index 36cf3c9e5..6999f2045 100644
--- a/ccm-core/src/main/java/org/libreccm/modules/Module.java
+++ b/ccm-core/src/main/java/org/libreccm/modules/Module.java
@@ -18,6 +18,8 @@
*/
package org.libreccm.modules;
+import org.libreccm.configuration.Configuration;
+import org.libreccm.configuration.ConfigurationManager;
import org.libreccm.web.ApplicationType;
import java.lang.annotation.Retention;
@@ -29,59 +31,63 @@ import java.lang.annotation.Target;
/**
* Annotation for describing some meta data of a module.
- *
+ *
* @author Jens Pelzetter
*/
@Target({TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Module {
-
- /**
- * Name of the module, overriding the name provided by the pom.xml and the
- * module info file of the module.
- *
- * @return The name of the module, overriding the value provided by the
- * module-info file.
+
+ /**
+ * Name of the module, overriding the name provided by the pom.xml and the
+ * module info file of the module.
+ *
+ * @return The name of the module, overriding the value provided by the
+ * module-info file.
*/
String name() default "";
- /**
- * Package name of resources of the package like DB migrations, overriding
- * default value constructed from the group id and the artifact id of the
+ /**
+ * Package name of resources of the package like DB migrations, overriding
+ * default value constructed from the group id and the artifact id of the
* module.
- *
- * @return The package name for resources of the module.
+ *
+ * @return The package name for resources of the module.
*/
String packageName() default "";
- /**
- * The version of module, overriding the value provided by the module info
+ /**
+ * The version of module, overriding the value provided by the module info
* file of the module.
- *
- * @return The version of the module.
+ *
+ * @return The version of the module.
*/
String version() default "";
/**
* Modules required by the annotated module.
- *
+ *
* @return An array of the dependencies of the module.
*/
RequiredModule[] requiredModules() default {};
-
+
/**
* ApplicationType types provided by the annotated module.
- *
- * @return An array containing the type descriptions for all application
- * types provided by the annotated module.
+ *
+ * @return An array containing the type descriptions for all application
+ * types provided by the annotated module.
*/
ApplicationType[] applicationTypes() default {};
-
+
/**
- * The JPA entities provided by the annotated module.
+ * Configuration classes provided by the module.
+ *
+ * @return An array containing all configuration classes provided by the
+ * module.
*
- * @return An array with the JPA entity classes of the annotated module.
+ * @see Configuration
+ * @see ConfigurationManager
*/
- Class>[] entities() default {};
+ Class>[] configurations() default {};
}
diff --git a/ccm-core/src/main/java/org/libreccm/modules/ModuleInfo.java b/ccm-core/src/main/java/org/libreccm/modules/ModuleInfo.java
index 99c94e062..64c019081 100644
--- a/ccm-core/src/main/java/org/libreccm/modules/ModuleInfo.java
+++ b/ccm-core/src/main/java/org/libreccm/modules/ModuleInfo.java
@@ -59,10 +59,6 @@ public class ModuleInfo {
* The data package of the module (group id).
*/
private String moduleDataPackage;
- /**
- * The entities provided by the module.
- */
- private Class>[] moduleEntities;
/**
* The version of the module.
*/
@@ -129,10 +125,6 @@ public class ModuleInfo {
return moduleVersion;
}
- public List> getModuleEntities() {
- return Collections.unmodifiableList(Arrays.asList(moduleEntities));
- }
-
public List getRequiredModules() {
return Collections.unmodifiableList(Arrays.asList(requiredModules));
}
@@ -168,7 +160,6 @@ public class ModuleInfo {
LOGGER.info("Module version is \"{}.\"", moduleVersion);
requiredModules = annotation.requiredModules();
- moduleEntities = annotation.entities();
}
/**
diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties
index 40eb8d853..8fc0cae64 100644
--- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties
+++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties
@@ -154,7 +154,7 @@ ui.admin.user.userpasswordform.retrieving_user_failed=Failed to retrieve user
ui.admin.groups.couldnt_find_specified_group=Couldn't find the specified group
ui.admin.tab.users_groups_roles.title=Users/Groups/Roles
ui.admin.tab.categories.title=Categories
-ui.admin.tab.registry.title=Registry
+ui.admin.tab.configuration.title=Configuration
ui.admin.change_password=Change password
ui.admin.tab.workflows.title=Workflows
ui.admin.users_groups_roles.users.title=Users
@@ -408,3 +408,16 @@ ui.admin.categories.doamin_details.mappings.error.please_select_app=Please selec
ui.admin.categories.domain_details.mappings.remove.confirm=Are you sure to remove this domain mapping?
ui.admin.categories.tree.header=Categories
ui.admin.categories.tree.back=Back to domain properties
+ui.admin.configuration.classes.filter.heading=Filter configurations
+ui.admin.configuration.classes.filter.submit=Apply
+ui.admin.configuration.classes.filter.clear=Clear
+ui.admin.configuration.configurations.none=No matching configurations found.
+ui.admin.configuration.configurations.table.name=Name
+ui.admin.configuration.configurations.table.desc=Description
+ui.admin.configuration.settings.none=No settings
+ui.admin.configuration.settings.table.col_setting_label.header=Setting
+ui.admin.configuration.settings.table.col_setting_value.header=Value
+ui.admin.configuration.settings.table.col_setting_desc.header=Description
+ui.admin.configuration.settings.table.col_edit_setting.header=Edit
+ui.admin.configuration.settings.edit=Edit
+ui.admin.configuration.settings.read_error=Failed to read setting value.
diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties
index 160124f03..bfad98e8e 100644
--- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties
+++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties
@@ -154,7 +154,7 @@ ui.admin.user.userpasswordform.retrieving_user_failed=Konnte Benutzer nicht abru
ui.admin.groups.couldnt_find_specified_group=Konnte die spezifische Gruppe nicht finden
ui.admin.tab.users_groups_roles.title=Benutzer/Gruppen/Rollen
ui.admin.tab.categories.title=Kategorien
-ui.admin.tab.registry.title=Registry
+ui.admin.tab.configuration.title=Konfiguration
ui.admin.change_password=Passwort \u00e4ndern
ui.admin.tab.workflows.title=Arbeitsabl\u00e4ufe
ui.admin.users_groups_roles.users.title=Benutzer
@@ -411,3 +411,16 @@ ui.admin.categories.doamin_details.mappings.error.please_select_app=Bitte w\u00e
ui.admin.categories.domain_details.mappings.remove.confirm=Sind Sie sicher, dass Sie dieses Mapping entfernen wollen?
ui.admin.categories.tree.header=Kategorien
ui.admin.categories.tree.back=Zur\u00fcck zur Domain Eigenschaften
+ui.admin.configuration.classes.filter.heading=Konfigurationen filtern
+ui.admin.configuration.classes.filter.submit=Anwenden
+ui.admin.configuration.classes.filter.clear=Zur\u00fccksetzen
+ui.admin.configuration.configurations.none=Keine passenden Konfigurationen gefunden.
+ui.admin.configuration.configurations.table.name=Name
+ui.admin.configuration.configurations.table.desc=Beschreibung
+ui.admin.configuration.settings.none=Keine Parameter
+ui.admin.configuration.settings.table.col_setting_label.header=Parameter
+ui.admin.configuration.settings.table.col_setting_value.header=Wert
+ui.admin.configuration.settings.table.col_setting_desc.header=Beschreibung
+ui.admin.configuration.settings.table.col_edit_setting.header=Bearbeiten
+ui.admin.configuration.settings.edit=Bearbeiten
+ui.admin.configuration.settings.read_error=Fehler beim lesen des Parameters.
diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties
index f653820f2..19d585bcc 100755
--- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties
+++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties
@@ -112,7 +112,7 @@ ui.admin.user.userpasswordform.retrieving_user_failed=Failed to retrieve user
ui.admin.groups.couldnt_find_specified_group=Couldn't find the specified group
ui.admin.tab.users_groups_roles.title=Users/Groups/Roles
ui.admin.tab.categories.title=Categories
-ui.admin.tab.registry.title=Registry
+ui.admin.tab.configuration.title=Configuration
ui.admin.change_password=Change password
ui.admin.tab.workflows.title=Workflows
ui.admin.tab.sysinfo.title=System information
@@ -384,3 +384,16 @@ ui.admin.categories.doamin_details.mappings.error.please_select_app=Please selec
ui.admin.categories.domain_details.mappings.remove.confirm=Are you sure to remove this domain mapping?
ui.admin.categories.tree.header=Categories
ui.admin.categories.tree.back=Back to domain properties
+ui.admin.configuration.classes.filter.heading=Filter configurations
+ui.admin.configuration.classes.filter.submit=Apply
+ui.admin.configuration.classes.filter.clear=Clear
+ui.admin.configuration.configurations.none=No matching configurations found.
+ui.admin.configuration.configurations.table.name=Name
+ui.admin.configuration.configurations.table.desc=Description
+ui.admin.configuration.settings.none=No settings
+ui.admin.configuration.settings.table.col_setting_label.header=Setting
+ui.admin.configuration.settings.table.col_setting_value.header=Value
+ui.admin.configuration.settings.table.col_setting_desc.header=Description
+ui.admin.configuration.settings.table.col_edit_setting.header=Edit
+ui.admin.configuration.settings.edit=Edit
+ui.admin.configuration.settings.read_error=Failed to read setting value.
diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties
index e35af5525..d621fff92 100755
--- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties
+++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties
@@ -97,7 +97,7 @@ ui.admin.user.userpasswordform.retrieving_user_failed=Impossible de retrouver l'
ui.admin.groups.couldnt_find_specified_group=Impossible de trouver le groupe sp\u00e9cifi\u00e9
ui.admin.tab.users_groups_roles.title=
ui.admin.tab.categories.title=Categories
-ui.admin.tab.registry.title=Registry
+ui.admin.tab.configuration.title=Configuration
ui.admin.change_password=Change password
ui.admin.tab.workflows.title=Workflows
ui.admin.save=Save
@@ -375,3 +375,16 @@ ui.admin.categories.doamin_details.mappings.error.please_select_app=Please selec
ui.admin.categories.domain_details.mappings.remove.confirm=Are you sure to remove this domain mapping?
ui.admin.categories.tree.header=Categories
ui.admin.categories.tree.back=Back to domain properties
+ui.admin.configuration.classes.filter.heading=Filter configurations
+ui.admin.configuration.classes.filter.submit=Apply
+ui.admin.configuration.classes.filter.clear=Clear
+ui.admin.configuration.configurations.none=No matching configurations found.
+ui.admin.configuration.configurations.table.name=Name
+ui.admin.configuration.configurations.table.desc=Description
+ui.admin.configuration.settings.none=No settings
+ui.admin.configuration.settings.table.col_setting_label.header=Setting
+ui.admin.configuration.settings.table.col_setting_value.header=Value
+ui.admin.configuration.settings.table.col_setting_desc.header=Description
+ui.admin.configuration.settings.table.col_edit_setting.header=Edit
+ui.admin.configuration.settings.edit=Edit
+ui.admin.configuration.settings.read_error=Failed to read setting value.