diff --git a/ccm-core/src/main/java/org/libreccm/categorization/CategoryRepository.java b/ccm-core/src/main/java/org/libreccm/categorization/CategoryRepository.java
index 786dac824..52488afb3 100644
--- a/ccm-core/src/main/java/org/libreccm/categorization/CategoryRepository.java
+++ b/ccm-core/src/main/java/org/libreccm/categorization/CategoryRepository.java
@@ -20,7 +20,6 @@ package org.libreccm.categorization;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.message.FormattedMessage;
import org.libreccm.core.AbstractEntityRepository;
import java.util.List;
diff --git a/ccm-core/src/main/java/org/libreccm/configuration/ApplicationConfigurationManager.java b/ccm-core/src/main/java/org/libreccm/configuration/ApplicationConfigurationManager.java
new file mode 100644
index 000000000..1c5f5248a
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/configuration/ApplicationConfigurationManager.java
@@ -0,0 +1,194 @@
+/*
+ * 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 org.libreccm.configuration;
+
+import static org.libreccm.configuration.ConfigurationConstants.*;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.libreccm.categorization.Category;
+import org.libreccm.categorization.CategoryManager;
+import org.libreccm.categorization.CategoryRepository;
+import org.libreccm.categorization.Domain;
+import org.libreccm.categorization.DomainRepository;
+import org.libreccm.web.CcmApplication;
+
+import java.lang.reflect.Field;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.persistence.EntityManager;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@RequestScoped
+public class ApplicationConfigurationManager {
+
+ private static final Logger LOGGER = LogManager.getLogger(
+ ApplicationConfigurationManager.class
+ );
+
+ @Inject
+ private ConfigurationManager confManager;
+
+ @Inject
+ private SettingManager settingManager;
+
+ @Inject
+ private SettingConverter settingConverter;
+
+ @Inject
+ private DomainRepository domainRepo;
+
+ @Inject
+ private CategoryRepository categoryRepo;
+
+ @Inject
+ private CategoryManager categoryManager;
+
+ @Inject
+ private EntityManager entityManager;
+
+ /**
+ * Finds an application instance specific configuration and loads it values
+ * from the registry.
+ *
+ * @param The type of the configuration.
+ * @param confClass The configuration class.
+ * @param instance The application instance for which the settings are
+ * loaded.
+ *
+ * @return The configuration for the provided application instance.
+ */
+ public T findConfiguration(
+ final Class confClass, final CcmApplication instance) {
+ if (confClass == null) {
+ throw new IllegalArgumentException("confClass can't be null");
+ }
+
+ if (instance == null) {
+ throw new IllegalArgumentException("instance can't be null");
+ }
+
+ if (confClass.getAnnotation(Configuration.class) == null) {
+ throw new IllegalArgumentException(String.format(
+ "Provided class \"%s\" is not annotated with \"%s\".",
+ confClass.getName(),
+ Configuration.class.getName()));
+ }
+
+ final String confName = String.format("%s.%s",
+ confClass.getName(),
+ instance.getPrimaryUrl());
+
+ return confManager.findConfiguration(confName, confClass);
+ }
+
+ /**
+ * Saves a application instance configuration.
+ *
+ * @param configuration The configuration to save.
+ * @param instance The application instance of which the configuration
+ * stores the settings.
+ */
+ public void saveConfiguration(final ApplicationConfiguration configuration,
+ final CcmApplication instance) {
+ if (configuration == null) {
+ throw new IllegalArgumentException("Configuration can't be null");
+ }
+
+ if (configuration.getClass().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()));
+ }
+
+ if (instance == null) {
+ throw new IllegalArgumentException("Instance can't be null");
+ }
+
+ final Field[] fields = configuration.getClass().getDeclaredFields();
+ for (final Field field : fields) {
+ field.setAccessible(true);
+ try {
+ setSettingValue(configuration,
+ instance,
+ confManager.getSettingName(field),
+ field.getType(),
+ field.get(configuration));
+ } catch (IllegalAccessException ex) {
+ LOGGER.error(String.format(
+ "Failed to write setting value for setting \"%s\" "
+ + "of configuration \"%s\"",
+ confManager.getSettingName(field),
+ configuration.getClass().getName()),
+ ex);
+ throw new IllegalStateException(String.format(
+ "Failed to write setting value for setting \"%s\" "
+ + "of configuration \"%s\"",
+ confManager.getSettingName(field),
+ configuration.getClass().getName()),
+ ex);
+ }
+ }
+ }
+
+ /**
+ * Sets the value of a setting of application instance configuration.
+ *
+ * @param The value type of the setting.
+ * @param configuration The configuration to which the settings belongs.
+ * @param instance The application instance to which
+ * @param settingName The name of the setting.
+ * @param valueType The type of the value of the setting.
+ * @param value The value to set.
+ */
+ private void setSettingValue(final Object configuration,
+ final CcmApplication instance,
+ final String settingName,
+ final Class valueType,
+ final Object value) {
+ final String settingPath = String.format(
+ "%s.%s.%s",
+ configuration.getClass().getName(),
+ instance.getPrimaryUrl(),
+ settingName);
+ AbstractSetting setting = settingManager.findSetting(settingPath, valueType);
+ if (setting == null) {
+ setting = settingConverter.createSettingForValueType(valueType);
+ setting.setName(settingName);
+ final Domain registry = domainRepo
+ .findByDomainKey(REGISTRY_DOMAIN);
+ final Category category = categoryRepo
+ .findByPath(registry, configuration.getClass().getName());
+ categoryManager.addObjectToCategory(setting, category);
+ }
+
+ @SuppressWarnings("unchecked")
+ final T settingValue = (T) value;
+ setting.setValue(settingValue);
+
+ entityManager.merge(setting);
+ }
+
+}
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 62e99f4cc..65a95d206 100644
--- a/ccm-core/src/main/java/org/libreccm/configuration/ConfigurationManager.java
+++ b/ccm-core/src/main/java/org/libreccm/configuration/ConfigurationManager.java
@@ -23,22 +23,13 @@ import static org.libreccm.configuration.ConfigurationConstants.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.FormattedMessage;
-import org.libreccm.categorization.Categorization;
import org.libreccm.categorization.Category;
import org.libreccm.categorization.CategoryManager;
import org.libreccm.categorization.CategoryRepository;
import org.libreccm.categorization.Domain;
import org.libreccm.categorization.DomainRepository;
-import org.libreccm.core.CcmObject;
-import org.libreccm.l10n.LocalizedString;
-import org.libreccm.web.CcmApplication;
import java.lang.reflect.Field;
-import java.math.BigDecimal;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
import java.util.StringJoiner;
import javax.enterprise.context.RequestScoped;
@@ -51,24 +42,25 @@ import javax.persistence.EntityManager;
* @author Jens Pelzetter
*/
@RequestScoped
-@SuppressWarnings({"PMD.GodClass",
- "PMD.TooManyMethods",
- "PMD.LongVariable",
- "PMD.ModifiedCyclomaticComplexity",
- "PMD.StandardCyclomaticComplexity",})
public class ConfigurationManager {
private static final Logger LOGGER = LogManager.getLogger(
ConfigurationManager.class);
+ @Inject
+ private SettingManager settingManager;
+
+ @Inject
+ private SettingConverter settingConverter;
+
@Inject
private CategoryManager categoryManager;
@Inject
- private CategoryRepository categoryRepository;
+ private CategoryRepository categoryRepo;
@Inject
- private DomainRepository domainRepository;
+ private DomainRepository domainRepo;
@Inject
private EntityManager entityManager;
@@ -162,92 +154,6 @@ public class ConfigurationManager {
}
}
- /**
- * Finds an application instance specific configuration and loads it values
- * from the registry.
- *
- * @param The type of the configuration.
- * @param confClass The configuration class.
- * @param instance The application instance for which the settings are
- * loaded.
- *
- * @return The configuration for the provided application instance.
- */
- public T findConfiguration(
- final Class confClass, final CcmApplication instance) {
- if (confClass == null) {
- throw new IllegalArgumentException("confClass can't be null");
- }
-
- if (instance == null) {
- throw new IllegalArgumentException("instance can't be null");
- }
-
- if (confClass.getAnnotation(Configuration.class) == null) {
- throw new IllegalArgumentException(String.format(
- "Provided class \"%s\" is not annotated with \"%s\".",
- confClass.getName(),
- Configuration.class.getName()));
- }
-
- final String confName = String.format("%s.%s",
- confClass.getName(),
- instance.getPrimaryUrl());
-
- return findConfiguration(confName, confClass);
- }
-
- /**
- * Saves a application instance configuration.
- *
- * @param configuration The configuration to save.
- * @param instance The application instance of which the configuration
- * stores the settings.
- */
- public void saveConfiguration(final ApplicationConfiguration configuration,
- final CcmApplication instance) {
- if (configuration == null) {
- throw new IllegalArgumentException("Configuration can't be null");
- }
-
- if (configuration.getClass().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()));
- }
-
- if (instance == null) {
- throw new IllegalArgumentException("Instance can't be null");
- }
-
- final Field[] fields = configuration.getClass().getDeclaredFields();
- for (final Field field : fields) {
- field.setAccessible(true);
- try {
- setSettingValue(configuration,
- instance,
- getSettingName(field),
- field.getType(),
- field.get(configuration));
- } catch (IllegalAccessException ex) {
- LOGGER.error(String.format(
- "Failed to write setting value for setting \"%s\" "
- + "of configuration \"%s\"",
- getSettingName(field),
- configuration.getClass().getName()),
- ex);
- throw new IllegalStateException(String.format(
- "Failed to write setting value for setting \"%s\" "
- + "of configuration \"%s\"",
- getSettingName(field),
- configuration.getClass().getName()),
- ex);
- }
- }
- }
-
/**
* Get the {@link ConfigurationInfo} for a configuration.
*
@@ -294,205 +200,14 @@ public class ConfigurationManager {
for (final Field field : fields) {
field.setAccessible(true);
if (field.getAnnotation(Setting.class) != null) {
- confInfo.addSetting(getSettingInfo(configuration,
- field.getName()));
+ confInfo.addSetting(settingManager.getSettingInfo(
+ configuration, field.getName()));
}
}
return confInfo;
}
- /**
- * 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.
- *
- * @return The {@link SettingInfo} for the provided configuration class.
- */
- @SuppressWarnings({"PMD.NPathComplexity",
- "PMD.CyclomaticComplexity",
- "PMD.StandardCyclomaticComplexity"})
- public SettingInfo getSettingInfo(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()));
- }
-
- final Configuration confAnnotation = configuration.getAnnotation(
- Configuration.class);
- final String descBundle;
- if (confAnnotation.descBundle() == null
- || confAnnotation.descBundle().isEmpty()) {
- descBundle = String.join("",
- configuration.getClass().getName(),
- "Description");
- } else {
- descBundle = confAnnotation.descBundle();
- }
-
- final Field field;
- try {
- 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),
- ex);
- return null;
- }
-
- if (field.getAnnotation(Setting.class) == null) {
- return null;
- }
-
- final Setting settingAnnotation = field.getAnnotation(Setting.class);
- final SettingInfo settingInfo = new SettingInfo();
- if (settingAnnotation.name() == null
- || settingAnnotation.name().isEmpty()) {
- settingInfo.setName(field.getName());
- } else {
- settingInfo.setName(settingAnnotation.name());
- }
-
- settingInfo.setValueType(field.getType().getName());
-
- try {
- final Object conf = configuration.newInstance();
- settingInfo.setDefaultValue(field.get(conf).toString());
- } catch (InstantiationException | IllegalAccessException ex) {
- LOGGER.warn(String.format("Failed to create instance of \"%s\" to "
- + "get default values.",
- configuration.getName()),
- ex);
- }
-
- settingInfo.setConfClass(configuration.getName());
-
- settingInfo.setDescBundle(descBundle);
-
- if (settingAnnotation.labelKey() == null
- || settingAnnotation.labelKey().isEmpty()) {
- settingInfo.setLabelKey(String.join(".", field.getName(),
- "label"));
- } else {
- settingInfo.setLabelKey(name);
- }
-
- if (settingAnnotation.descKey() == null
- || settingAnnotation.descKey().isEmpty()) {
- settingInfo.setDescKey(String.join(".",
- field.getName(),
- "descripotion"));
- } else {
- settingInfo.setDescKey(settingAnnotation.descKey());
- }
-
- return settingInfo;
- }
-
- /**
- * A low level method for finding a setting in the registry.
- *
- * @param Type of the value 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.
- */
- public AbstractSetting findSetting(final String name,
- final Class clazz) {
- LOGGER.debug(String.format(
- "Trying to find setting \"%s\" of type \"%s\"",
- name,
- clazz.getName()));
- final String[] tokens = name.split("\\.");
- LOGGER.debug(String.format("Setting name \"%s\" has %d tokens.",
- name,
- tokens.length));
- final String[] categoryTokens = Arrays.copyOfRange(tokens,
- 0,
- tokens.length - 1);
- final String categoryPath = String.join(".", categoryTokens);
- LOGGER.debug(String.format("categoryPath for setting is \"%s\".",
- categoryPath));
-
- final Domain registry = domainRepository
- .findByDomainKey(REGISTRY_DOMAIN);
- final Category category = categoryRepository.findByPath(registry,
- categoryPath);
- if (category == null) {
- LOGGER.warn(String.format(String.format(
- "Category \"%s\" for setting \"%s\" not found.",
- categoryPath,
- name)));
- return null;
- }
-
- LOGGER.debug(String.format("Category has %d objects. Filtering.",
- category.getObjects().size()));
- final Optional result = category
- .getObjects()
- .stream()
- .filter((Categorization c)
- -> c.getCategorizedObject() instanceof AbstractSetting)
- .filter((Categorization c)
- -> ((AbstractSetting>) c.getCategorizedObject())
- .getName()
- .equals(tokens[tokens.length - 1]))
- .findFirst();
-
- if (result.isPresent()) {
- final CcmObject object = result.get().getCategorizedObject();
- final AbstractSetting> entry = (AbstractSetting>) object;
-
- if (clazz.isInstance(entry.getValue())) {
- @SuppressWarnings("unchecked")
- final AbstractSetting resultEntry
- = (AbstractSetting) entry;
- return resultEntry;
- } else {
- LOGGER.warn(String.format("Setting \"%s\" found but is not of "
- + "the requested type \"%s\".",
- name,
- clazz.getName()));
- return null;
- }
- } else {
- LOGGER.warn(String.format(
- "Setting \"%s\" was not found in category \"%s\".",
- name,
- categoryPath));
- return null;
- }
- }
-
- /**
- * Low level method of saving a setting.
- *
- * @param setting The setting to save.
- */
- public void saveSetting(final AbstractSetting> setting) {
- if (setting.getObjectId() == 0) {
- entityManager.persist(setting);
- } else {
- entityManager.merge(setting);
- }
- }
-
/**
* Helper method for generating the name of a setting. This method does not
* check if the provided field is annotated with {@link Setting}. The caller
@@ -504,7 +219,7 @@ public class ConfigurationManager {
* @return The name of the field or if the {@link Setting} annotation of the
* field has a name value, the value of that field.
*/
- private String getSettingName(final Field field) {
+ String getSettingName(final Field field) {
LOGGER.debug(String.format("Trying to get setting name from field: "
+ "\"%s\"",
field.getName()));
@@ -528,32 +243,32 @@ public class ConfigurationManager {
* @throws IllegalArgumentException If there is not setting type for the
* provided value type.
*/
- @SuppressWarnings("unchecked")
- private AbstractSetting createSettingForValueType(
- final Class valueType) {
-
- final String valueTypeName = valueType.getName();
- if (BigDecimal.class.getName().equals(valueTypeName)) {
- return (AbstractSetting) new BigDecimalSetting();
- } else if (Boolean.class.getName().equals(valueTypeName)) {
- return (AbstractSetting) new BooleanSetting();
- } else if (Double.class.getName().equals(valueTypeName)) {
- return (AbstractSetting) new DoubleSetting();
- } else if (List.class.getName().equals(valueTypeName)) {
- return (AbstractSetting) new StringListSetting();
- } else if (LocalizedString.class.getName().equals(valueTypeName)) {
- return (AbstractSetting) new LocalizedStringSetting();
- } else if (Long.class.getName().equals(valueTypeName)) {
- return (AbstractSetting) new LongSetting();
- } else if (Set.class.getName().equals(valueTypeName)) {
- return (AbstractSetting) new EnumSetting();
- } else if (String.class.getName().equals(valueTypeName)) {
- return (AbstractSetting) new StringSetting();
- } else {
- throw new IllegalArgumentException(String.format(
- "No setting type for value type \"%s\".", valueTypeName));
- }
- }
+// @SuppressWarnings("unchecked")
+// AbstractSetting createSettingForValueType(
+// final Class valueType) {
+//
+// final String valueTypeName = valueType.getName();
+// if (BigDecimal.class.getName().equals(valueTypeName)) {
+// return (AbstractSetting) new BigDecimalSetting();
+// } else if (Boolean.class.getName().equals(valueTypeName)) {
+// return (AbstractSetting) new BooleanSetting();
+// } else if (Double.class.getName().equals(valueTypeName)) {
+// return (AbstractSetting) new DoubleSetting();
+// } else if (List.class.getName().equals(valueTypeName)) {
+// return (AbstractSetting) new StringListSetting();
+// } else if (LocalizedString.class.getName().equals(valueTypeName)) {
+// return (AbstractSetting) new LocalizedStringSetting();
+// } else if (Long.class.getName().equals(valueTypeName)) {
+// return (AbstractSetting) new LongSetting();
+// } else if (Set.class.getName().equals(valueTypeName)) {
+// return (AbstractSetting) new EnumSetting();
+// } else if (String.class.getName().equals(valueTypeName)) {
+// return (AbstractSetting) new StringSetting();
+// } else {
+// throw new IllegalArgumentException(String.format(
+// "No setting type for value type \"%s\".", valueTypeName));
+// }
+// }
/**
* Sets a value on a setting in the registry.
@@ -576,12 +291,13 @@ public class ConfigurationManager {
"Saving setting \"%s\" of type \"%s\"...",
settingPath,
valueType.getName()));
- AbstractSetting setting = findSetting(settingPath, valueType);
+ AbstractSetting setting = settingManager.findSetting(settingPath,
+ valueType);
if (setting == null) {
LOGGER.debug(String.format("Setting \"%s\" does not yet exist in "
+ "database. Creating new setting.",
settingPath));
- setting = createSettingForValueType(valueType);
+ setting = settingConverter.createSettingForValueType(valueType);
setting.setName(settingName);
setting.setDisplayName(settingName);
final Category category = findCategoryForNewSetting(configuration);
@@ -603,44 +319,6 @@ public class ConfigurationManager {
entityManager.flush();
}
- /**
- * Sets the value of a setting of application instance configuration.
- *
- * @param The value type of the setting.
- * @param configuration The configuration to which the settings belongs.
- * @param instance The application instance to which
- * @param settingName The name of the setting.
- * @param valueType The type of the value of the setting.
- * @param value The value to set.
- */
- private void setSettingValue(final Object configuration,
- final CcmApplication instance,
- final String settingName,
- final Class valueType,
- final Object value) {
- final String settingPath = String.format(
- "%s.%s.%s",
- configuration.getClass().getName(),
- instance.getPrimaryUrl(),
- settingName);
- AbstractSetting setting = findSetting(settingPath, valueType);
- if (setting == null) {
- setting = createSettingForValueType(valueType);
- setting.setName(settingName);
- final Domain registry = domainRepository
- .findByDomainKey(REGISTRY_DOMAIN);
- final Category category = categoryRepository
- .findByPath(registry, configuration.getClass().getName());
- categoryManager.addObjectToCategory(setting, category);
- }
-
- @SuppressWarnings("unchecked")
- final T settingValue = (T) value;
- setting.setValue(settingValue);
-
- entityManager.merge(setting);
- }
-
/**
* Helper method for loading a configuration from the registry.
*
@@ -657,13 +335,8 @@ public class ConfigurationManager {
* @return An instance of the configuration class with all setting fields
* set to the values stored in the registry.
*/
- private T findConfiguration(final String confName,
- final Class confClass) {
- final Domain registry = domainRepository
- .findByDomainKey(REGISTRY_DOMAIN);
- final Category category = categoryRepository.findByPath(registry,
- confName);
-
+ T findConfiguration(final String confName,
+ final Class confClass) {
final T conf;
try {
conf = confClass.newInstance();
@@ -675,7 +348,9 @@ public class ConfigurationManager {
return null;
}
- if (category == null) {
+ final Domain registry = domainRepo
+ .findByDomainKey(REGISTRY_DOMAIN);
+ if (categoryRepo.findByPath(registry, confName) == null) {
return conf;
}
@@ -690,8 +365,8 @@ public class ConfigurationManager {
confClass.getName(),
getSettingName(field));
final Class> settingType = field.getType();
- final AbstractSetting> setting = findSetting(settingPath,
- settingType);
+ final AbstractSetting> setting = settingManager.findSetting(
+ settingPath, settingType);
if (setting != null) {
try {
LOGGER.debug("Setting \"{}\" found. Value: %s",
@@ -717,7 +392,7 @@ public class ConfigurationManager {
configuration.getClass().getName());
final String categoryPath = configuration.getClass().getName();
final String[] tokens = categoryPath.split("\\.");
- final Domain registry = domainRepository
+ final Domain registry = domainRepo
.findByDomainKey(REGISTRY_DOMAIN);
final Category[] categories = new Category[tokens.length];
@@ -729,8 +404,8 @@ public class ConfigurationManager {
LOGGER.debug("#findCategoryForNewSetting: "
+ "Checking if category \"{}\" exists.",
path);
- final Category category = categoryRepository.findByPath(registry,
- path);
+ final Category category = categoryRepo.findByPath(registry,
+ path);
if (category == null) {
LOGGER.debug("#findCategoryForNewSetting: "
+ "Category \"{}\" does not exist.",
@@ -778,7 +453,7 @@ public class ConfigurationManager {
categoryPath);
return categories[categories.length - 1];
}
-
+
private String buildCategoryPath(final String[] tokens,
final int index) {
final StringJoiner joiner = new StringJoiner(".");
@@ -794,7 +469,7 @@ public class ConfigurationManager {
final Category category = new Category();
category.setName(name);
category.setDisplayName(name);
- categoryRepository.save(category);
+ categoryRepo.save(category);
entityManager.flush();
categoryManager.addSubCategoryToCategory(category, parent);
diff --git a/ccm-core/src/main/java/org/libreccm/configuration/SettingConverter.java b/ccm-core/src/main/java/org/libreccm/configuration/SettingConverter.java
new file mode 100644
index 000000000..7baa7f601
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/configuration/SettingConverter.java
@@ -0,0 +1,85 @@
+/*
+ * 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 org.libreccm.configuration;
+
+import org.libreccm.l10n.LocalizedString;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.enterprise.context.RequestScoped;
+
+/**
+ * Helper class for converting values to settings.
+ *
+ * @author Jens Pelzetter
+ */
+@RequestScoped
+class SettingConverter {
+
+ private final Map>> typeMap;
+
+ public SettingConverter() {
+ typeMap = new HashMap<>();
+ typeMap.put(BigDecimal.class.getName(), BigDecimalSetting.class);
+ typeMap.put(Boolean.class.getName(), BooleanSetting.class);
+ typeMap.put(Double.class.getName(), DoubleSetting.class);
+ typeMap.put(List.class.getName(), StringListSetting.class);
+ typeMap.put(LocalizedString.class.getName(),
+ LocalizedStringSetting.class);
+ typeMap.put(Long.class.getName(), LongSetting.class);
+ typeMap.put(Set.class.getName(), EnumSetting.class);
+ typeMap.put(String.class.getName(), StringSetting.class);
+ }
+
+ /**
+ * Create a setting instance of a specific value type.
+ *
+ * @param Type variable.
+ * @param valueType The type of the value of the setting to create.
+ *
+ * @return An setting instance of the provided value type.
+ *
+ * @throws IllegalArgumentException If there is not setting type for the
+ * provided value type.
+ */
+ @SuppressWarnings("unchecked")
+ AbstractSetting createSettingForValueType(final Class valueType) {
+
+ final String valueTypeName = valueType.getName();
+ final Class extends AbstractSetting>> clazz = typeMap.get(
+ valueTypeName);
+
+ if (clazz == null) {
+ throw new IllegalArgumentException(String.format(
+ "No setting type for value type \"%s\".", valueTypeName));
+ } else {
+ try {
+ return (AbstractSetting) clazz.newInstance();
+ } catch (InstantiationException | IllegalAccessException ex) {
+ throw new IllegalStateException(
+ "Failed to create setting instance.", ex);
+ }
+ }
+ }
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/configuration/SettingManager.java b/ccm-core/src/main/java/org/libreccm/configuration/SettingManager.java
new file mode 100644
index 000000000..edaeb886a
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/configuration/SettingManager.java
@@ -0,0 +1,272 @@
+/*
+ * 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 org.libreccm.configuration;
+
+import static org.libreccm.configuration.ConfigurationConstants.*;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.libreccm.categorization.Categorization;
+import org.libreccm.categorization.Category;
+import org.libreccm.categorization.CategoryRepository;
+import org.libreccm.categorization.Domain;
+import org.libreccm.categorization.DomainRepository;
+import org.libreccm.core.CcmObject;
+
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.Optional;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.persistence.EntityManager;
+
+/**
+ * Manages settings in the registry. Normally there should be no need to use
+ * this class directly because the {@link ConfigurationManager} provide the same
+ * public methods for accessing settings than this class. The purpose of this
+ * class is only to separate the logic for managing settings from the logic for
+ * managing configuration classes and to reduce the complexity of the
+ * {@link ConfigurationManager} class
+ *
+ * @author Jens Pelzetter
+ */
+@RequestScoped
+public class SettingManager {
+
+ private static final Logger LOGGER = LogManager.getLogger(
+ SettingManager.class);
+
+ @Inject
+ private CategoryRepository categoryRepo;
+
+ @Inject
+ private DomainRepository domainRepo;
+
+ @Inject
+ private EntityManager entityManager;
+
+ /**
+ * 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.
+ *
+ * @return The {@link SettingInfo} for the provided configuration class.
+ */
+ @SuppressWarnings({"PMD.NPathComplexity",
+ "PMD.CyclomaticComplexity",
+ "PMD.StandardCyclomaticComplexity"})
+ public SettingInfo getSettingInfo(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()));
+ }
+
+// final Configuration confAnnotation = configuration.getAnnotation(
+// Configuration.class);
+// final String descBundle;
+// if (confAnnotation.descBundle() == null
+// || confAnnotation.descBundle().isEmpty()) {
+// descBundle = String.join("",
+// configuration.getClass().getName(),
+// "Description");
+// } else {
+// descBundle = confAnnotation.descBundle();
+// }
+
+
+
+ final Field field;
+ try {
+ 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),
+ ex);
+ return null;
+ }
+
+ if (field.getAnnotation(Setting.class) == null) {
+ return null;
+ }
+
+ final Setting settingAnnotation = field.getAnnotation(Setting.class);
+ final SettingInfo settingInfo = new SettingInfo();
+ if (settingAnnotation.name() == null
+ || settingAnnotation.name().isEmpty()) {
+ settingInfo.setName(field.getName());
+ } else {
+ settingInfo.setName(settingAnnotation.name());
+ }
+
+ settingInfo.setValueType(field.getType().getName());
+
+ try {
+ final Object conf = configuration.newInstance();
+ settingInfo.setDefaultValue(field.get(conf).toString());
+ } catch (InstantiationException | IllegalAccessException ex) {
+ LOGGER.warn(String.format("Failed to create instance of \"%s\" to "
+ + "get default values.",
+ configuration.getName()),
+ ex);
+ }
+
+ settingInfo.setConfClass(configuration.getName());
+ settingInfo.setDescBundle(getDescBundle(configuration));
+
+ if (settingAnnotation.labelKey() == null
+ || settingAnnotation.labelKey().isEmpty()) {
+ settingInfo.setLabelKey(String.join(".", field.getName(),
+ "label"));
+ } else {
+ settingInfo.setLabelKey(name);
+ }
+
+ if (settingAnnotation.descKey() == null
+ || settingAnnotation.descKey().isEmpty()) {
+ settingInfo.setDescKey(String.join(".",
+ field.getName(),
+ "descripotion"));
+ } else {
+ settingInfo.setDescKey(settingAnnotation.descKey());
+ }
+
+ return settingInfo;
+ }
+
+ /**
+ * A low level method for finding a setting in the registry.
+ *
+ * @param Type of the value 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.
+ */
+ public AbstractSetting findSetting(final String name,
+ final Class clazz) {
+ LOGGER.debug(String.format(
+ "Trying to find setting \"%s\" of type \"%s\"",
+ name,
+ clazz.getName()));
+ final String[] tokens = name.split("\\.");
+ LOGGER.debug(String.format("Setting name \"%s\" has %d tokens.",
+ name,
+ tokens.length));
+ final String[] categoryTokens = Arrays.copyOfRange(tokens,
+ 0,
+ tokens.length - 1);
+ final String categoryPath = String.join(".", categoryTokens);
+ LOGGER.debug(String.format("categoryPath for setting is \"%s\".",
+ categoryPath));
+
+ final Domain registry = domainRepo
+ .findByDomainKey(REGISTRY_DOMAIN);
+ final Category category = categoryRepo.findByPath(registry,
+ categoryPath);
+ if (category == null) {
+ LOGGER.warn(String.format(String.format(
+ "Category \"%s\" for setting \"%s\" not found.",
+ categoryPath,
+ name)));
+ return null;
+ }
+
+ LOGGER.debug(String.format("Category has %d objects. Filtering.",
+ category.getObjects().size()));
+ final Optional result = category
+ .getObjects()
+ .stream()
+ .filter((Categorization c)
+ -> c.getCategorizedObject() instanceof AbstractSetting)
+ .filter((Categorization c)
+ -> ((AbstractSetting>) c.getCategorizedObject())
+ .getName()
+ .equals(tokens[tokens.length - 1]))
+ .findFirst();
+
+ if (result.isPresent()) {
+ final CcmObject object = result.get().getCategorizedObject();
+ final AbstractSetting> entry = (AbstractSetting>) object;
+
+ if (clazz.isInstance(entry.getValue())) {
+ @SuppressWarnings("unchecked")
+ final AbstractSetting resultEntry
+ = (AbstractSetting) entry;
+ return resultEntry;
+ } else {
+ LOGGER.warn(String.format("Setting \"%s\" found but is not of "
+ + "the requested type \"%s\".",
+ name,
+ clazz.getName()));
+ return null;
+ }
+ } else {
+ LOGGER.warn(String.format(
+ "Setting \"%s\" was not found in category \"%s\".",
+ name,
+ categoryPath));
+ return null;
+ }
+ }
+
+
+
+ /**
+ * Low level method of saving a setting.
+ *
+ * @param setting The setting to save.
+ */
+ public void saveSetting(final AbstractSetting> setting) {
+ if (setting.getObjectId() == 0) {
+ entityManager.persist(setting);
+ } else {
+ entityManager.merge(setting);
+ }
+ }
+
+ private String getDescBundle(final Class> configuration) {
+ final Configuration confAnnotation = configuration.getAnnotation(
+ Configuration.class);
+ if (confAnnotation.descBundle() == null
+ || confAnnotation.descBundle().isEmpty()) {
+ return String.join("",
+ configuration.getClass().getName(),
+ "Description");
+ } else {
+ return confAnnotation.descBundle();
+ }
+ }
+
+}