nl.strohalm.cyclos.services.settings.SettingsServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for nl.strohalm.cyclos.services.settings.SettingsServiceImpl.java

Source

/*
This file is part of Cyclos (www.cyclos.org).
A project of the Social Trade Organisation (www.socialtrade.org).
    
Cyclos is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
    
Cyclos 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 General Public License for more details.
    
You should have received a copy of the GNU General Public License
along with Cyclos; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    
 */
package nl.strohalm.cyclos.services.settings;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import nl.strohalm.cyclos.dao.settings.SettingDAO;
import nl.strohalm.cyclos.entities.customization.fields.MemberCustomField;
import nl.strohalm.cyclos.entities.settings.AccessSettings;
import nl.strohalm.cyclos.entities.settings.AlertSettings;
import nl.strohalm.cyclos.entities.settings.LocalSettings;
import nl.strohalm.cyclos.entities.settings.LogSettings;
import nl.strohalm.cyclos.entities.settings.MailSettings;
import nl.strohalm.cyclos.entities.settings.MailTranslation;
import nl.strohalm.cyclos.entities.settings.MessageSettings;
import nl.strohalm.cyclos.entities.settings.Setting;
import nl.strohalm.cyclos.entities.settings.Setting.Type;
import nl.strohalm.cyclos.entities.settings.events.AccessSettingsChangeListener;
import nl.strohalm.cyclos.entities.settings.events.AlertSettingsChangeListener;
import nl.strohalm.cyclos.entities.settings.events.LocalSettingsChangeListener;
import nl.strohalm.cyclos.entities.settings.events.LogSettingsChangeListener;
import nl.strohalm.cyclos.entities.settings.events.MailSettingsChangeListener;
import nl.strohalm.cyclos.entities.settings.events.MailTranslationChangeListener;
import nl.strohalm.cyclos.entities.settings.events.MessageSettingsChangeListener;
import nl.strohalm.cyclos.entities.settings.events.SettingsChangeListener;
import nl.strohalm.cyclos.services.InitializingService;
import nl.strohalm.cyclos.services.fetch.FetchServiceLocal;
import nl.strohalm.cyclos.services.settings.exceptions.SelectedSettingTypeNotInFileException;
import nl.strohalm.cyclos.utils.EntityHelper;
import nl.strohalm.cyclos.utils.XmlHelper;
import nl.strohalm.cyclos.utils.conversion.CoercionHelper;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 * Implementation class for settings service
 * @author luis
 * @author Jefferson Magno
 */
public class SettingsServiceImpl implements SettingsServiceLocal, InitializingService, InitializingBean {

    private static final String ROOT_ELEMENT = "cyclos-settings";
    private static final String SETTINGS_ELEMENT = "settings";
    private static final String SETTING_ELEMENT = "setting";
    private static final List<String> IGNORED_SETTINGS = Arrays.asList("applicationName", "language");

    private FetchServiceLocal fetchService;
    private SettingDAO settingDao;

    // Handlers for each settings type
    private Map<Setting.Type, SettingsHandler<?, ?>> handlersMap;
    private SettingsHandler<AccessSettings, AccessSettingsChangeListener> accessSettingsHandler;
    private SettingsHandler<AlertSettings, AlertSettingsChangeListener> alertSettingsHandler;
    private SettingsHandler<LocalSettings, LocalSettingsChangeListener> localSettingsHandler;
    private SettingsHandler<LogSettings, LogSettingsChangeListener> logSettingsHandler;
    private SettingsHandler<MailSettings, MailSettingsChangeListener> mailSettingsHandler;
    private SettingsHandler<MailTranslation, MailTranslationChangeListener> mailTranslationHandler;
    private SettingsHandler<MessageSettings, MessageSettingsChangeListener> messageSettingsHandler;
    private Set<SettingsChangeListener> listenersPendingToAdd = new HashSet<SettingsChangeListener>();

    @Override
    public void addListener(final SettingsChangeListener listener) {
        // Before completing initialization, other components might want to register listeners, but handlers are not set yet.
        // So, we'll just add them after the initialization is complete
        if (listenersPendingToAdd != null) {
            listenersPendingToAdd.add(listener);
            return;
        }
        if (listener instanceof AccessSettingsChangeListener) {
            accessSettingsHandler.addListener((AccessSettingsChangeListener) listener);
        }
        if (listener instanceof AlertSettingsChangeListener) {
            alertSettingsHandler.addListener((AlertSettingsChangeListener) listener);
        }
        if (listener instanceof LocalSettingsChangeListener) {
            localSettingsHandler.addListener((LocalSettingsChangeListener) listener);
        }
        if (listener instanceof LogSettingsChangeListener) {
            logSettingsHandler.addListener((LogSettingsChangeListener) listener);
        }
        if (listener instanceof MailSettingsChangeListener) {
            mailSettingsHandler.addListener((MailSettingsChangeListener) listener);
        }
        if (listener instanceof MailTranslationChangeListener) {
            mailTranslationHandler.addListener((MailTranslationChangeListener) listener);
        }
        if (listener instanceof MessageSettingsChangeListener) {
            messageSettingsHandler.addListener((MessageSettingsChangeListener) listener);
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        // Create a map with all handlers by type
        handlersMap = new HashMap<Setting.Type, SettingsHandler<?, ?>>();
        handlersMap.put(Setting.Type.ACCESS, accessSettingsHandler);
        handlersMap.put(Setting.Type.ALERT, alertSettingsHandler);
        handlersMap.put(Setting.Type.LOCAL, localSettingsHandler);
        handlersMap.put(Setting.Type.LOG, logSettingsHandler);
        handlersMap.put(Setting.Type.MAIL, mailSettingsHandler);
        handlersMap.put(Setting.Type.MAIL_TRANSLATION, mailTranslationHandler);
        handlersMap.put(Setting.Type.MESSAGE, messageSettingsHandler);

        // Add any listeners which were registered before the initialization was completed
        Set<SettingsChangeListener> listeners = listenersPendingToAdd;
        listenersPendingToAdd = null;
        for (SettingsChangeListener listener : listeners) {
            addListener(listener);
        }
    }

    @Override
    public String exportToXml(final Collection<Type> types) {
        final LocalSettings localSettings = getLocalSettings();
        final StringBuilder xml = new StringBuilder();
        xml.append("<?xml version=\"1.0\" encoding=\"").append(localSettings.getCharset()).append("\"?>\n");
        xml.append('<').append(ROOT_ELEMENT).append(">\n");
        for (final Type type : types) {
            appendSettingType(xml, type);
        }
        xml.append("</").append(ROOT_ELEMENT).append(">\n");
        return xml.toString();
    }

    @Override
    public AccessSettings getAccessSettings() {
        return accessSettingsHandler.get();
    }

    @Override
    public AlertSettings getAlertSettings() {
        return alertSettingsHandler.get();
    }

    @Override
    public LocalSettings getLocalSettings() {
        return localSettingsHandler.get();
    }

    @Override
    public LogSettings getLogSettings() {
        return logSettingsHandler.get();
    }

    @Override
    public MailSettings getMailSettings() {
        return mailSettingsHandler.get();
    }

    @Override
    public MailTranslation getMailTranslation() {
        return mailTranslationHandler.get();
    }

    @Override
    public MessageSettings getMessageSettings() {
        return messageSettingsHandler.get();
    }

    @Override
    public MemberCustomField getSmsCustomField() {
        final Long id = getLocalSettings().getSmsCustomFieldId();
        if (id == null) {
            return null;
        }
        final MemberCustomField reference = EntityHelper.reference(MemberCustomField.class, id);
        return fetchService.fetch(reference);
    }

    @Override
    public List<?> importFromXml(final String xml, final Collection<Setting.Type> types) {
        final Document doc = XmlHelper.readDocument(xml);
        final Element root = doc.getDocumentElement();
        final List<Element> settingTypesNodes = XmlHelper.getChilden(root, SETTINGS_ELEMENT);
        final Set<Setting.Type> typesImported = new HashSet<Setting.Type>();
        final List<Object> settings = new ArrayList<Object>();
        for (final Element settingTypeNode : settingTypesNodes) {
            final String settingTypeName = settingTypeNode.getAttribute("type");
            final Setting.Type type = CoercionHelper.coerce(Setting.Type.class, settingTypeName);
            if (!types.contains(type)) {
                continue;
            }
            final Map<String, String> values = new HashMap<String, String>();
            final List<Element> settingsNodes = XmlHelper.getChilden(settingTypeNode, SETTING_ELEMENT);
            for (final Element settingNode : settingsNodes) {
                final String settingName = settingNode.getAttribute("name");
                // Setting in ignore list, don't import it
                if (type == Setting.Type.LOCAL && IGNORED_SETTINGS.contains(settingName)) {
                    continue;
                }
                String settingValue;
                try {
                    settingValue = StringUtils.trimToNull(settingNode.getChildNodes().item(0).getNodeValue());
                } catch (final Exception e) {
                    settingValue = null;
                }
                values.put(settingName, settingValue);
            }
            final SettingsHandler<?, ?> settingsHandler = handlersMap.get(type);
            final Object setting = settingsHandler.importFrom(values);
            typesImported.add(type);
            settings.add(setting);
        }
        final List<Setting.Type> notImportedTypes = new ArrayList<Setting.Type>();
        for (final Setting.Type type : types) {
            if (!typesImported.contains(type)) {
                notImportedTypes.add(type);
            }
        }
        if (CollectionUtils.isNotEmpty(notImportedTypes)) {
            throw new SelectedSettingTypeNotInFileException(notImportedTypes);
        }

        return settings;
    }

    @Override
    public void initializeService() {
        importNew();
    }

    @Override
    public void reloadTranslation() {
        // Delete all mail and message translations
        settingDao.deleteByType(Setting.Type.MAIL_TRANSLATION, Setting.Type.MESSAGE);
        // Delete some local settings which are also 'translatable'
        for (final Setting setting : settingDao.listByType(Setting.Type.LOCAL)) {
            final String name = setting.getName();
            if ("applicationUsername".equals(name) || "chargebackDescription".equals(name)) {
                settingDao.delete(setting.getId());
            }
        }
        // Now import them all again, with the current language
        importNew();

        // Then, refresh the handler's state
        refreshTranslationRelatedHandlers();
    }

    @Override
    public void removeListener(final SettingsChangeListener listener) {
        if (listener instanceof AccessSettingsChangeListener) {
            accessSettingsHandler.removeListener((AccessSettingsChangeListener) listener);
        }
        if (listener instanceof AlertSettingsChangeListener) {
            alertSettingsHandler.removeListener((AlertSettingsChangeListener) listener);
        }
        if (listener instanceof LocalSettingsChangeListener) {
            localSettingsHandler.removeListener((LocalSettingsChangeListener) listener);
        }
        if (listener instanceof LogSettingsChangeListener) {
            logSettingsHandler.removeListener((LogSettingsChangeListener) listener);
        }
        if (listener instanceof MailSettingsChangeListener) {
            mailSettingsHandler.removeListener((MailSettingsChangeListener) listener);
        }
        if (listener instanceof MailTranslationChangeListener) {
            mailTranslationHandler.removeListener((MailTranslationChangeListener) listener);
        }
        if (listener instanceof MessageSettingsChangeListener) {
            messageSettingsHandler.removeListener((MessageSettingsChangeListener) listener);
        }
    }

    @Override
    public AccessSettings save(final AccessSettings settings) {
        return accessSettingsHandler.update(settings);
    }

    @Override
    public AlertSettings save(final AlertSettings settings) {
        return alertSettingsHandler.update(settings);
    }

    @Override
    public LocalSettings save(final LocalSettings settings) {
        return localSettingsHandler.update(settings);
    }

    @Override
    public LogSettings save(final LogSettings settings) {
        return logSettingsHandler.update(settings);
    }

    @Override
    public MailSettings save(final MailSettings settings) {
        return mailSettingsHandler.update(settings);
    }

    @Override
    public MailTranslation save(final MailTranslation settings) {
        return mailTranslationHandler.update(settings);
    }

    @Override
    public MessageSettings save(final MessageSettings settings) {
        return messageSettingsHandler.update(settings);
    }

    public void setAccessSettingsHandler(
            final SettingsHandler<AccessSettings, AccessSettingsChangeListener> accessSettingsHandler) {
        this.accessSettingsHandler = accessSettingsHandler;
    }

    public void setAlertSettingsHandler(
            final SettingsHandler<AlertSettings, AlertSettingsChangeListener> alertSettingsHandler) {
        this.alertSettingsHandler = alertSettingsHandler;
    }

    public void setFetchServiceLocal(final FetchServiceLocal fetchService) {
        this.fetchService = fetchService;
    }

    public void setLocalSettingsHandler(
            final SettingsHandler<LocalSettings, LocalSettingsChangeListener> localSettingsHandler) {
        this.localSettingsHandler = localSettingsHandler;
    }

    public void setLogSettingsHandler(
            final SettingsHandler<LogSettings, LogSettingsChangeListener> logSettingsHandler) {
        this.logSettingsHandler = logSettingsHandler;
    }

    public void setMailSettingsHandler(
            final SettingsHandler<MailSettings, MailSettingsChangeListener> mailSettingsHandler) {
        this.mailSettingsHandler = mailSettingsHandler;
    }

    public void setMailTranslationHandler(
            final SettingsHandler<MailTranslation, MailTranslationChangeListener> mailTranslationHandler) {
        this.mailTranslationHandler = mailTranslationHandler;
    }

    public void setMessageSettingsHandler(
            final SettingsHandler<MessageSettings, MessageSettingsChangeListener> messageSettingsHandler) {
        this.messageSettingsHandler = messageSettingsHandler;
    }

    public void setSettingDao(final SettingDAO settingDao) {
        this.settingDao = settingDao;
    }

    @Override
    public void validate(final AccessSettings settings) {
        accessSettingsHandler.validate(settings);
    }

    @Override
    public void validate(final AlertSettings settings) {
        alertSettingsHandler.validate(settings);
    }

    @Override
    public void validate(final LocalSettings settings) {
        localSettingsHandler.validate(settings);
    }

    @Override
    public void validate(final LogSettings settings) {
        logSettingsHandler.validate(settings);
    }

    @Override
    public void validate(final MailSettings settings) {
        mailSettingsHandler.validate(settings);
    }

    @Override
    public void validate(final MailTranslation settings) {
        mailTranslationHandler.validate(settings);
    }

    @Override
    public void validate(final MessageSettings settings) {
        messageSettingsHandler.validate(settings);
    }

    private void appendSetting(final StringBuilder xml, final Setting setting) {
        final String indent2Levels = StringUtils.repeat("    ", 2);
        final String indent3Levels = StringUtils.repeat("    ", 3);
        xml.append(indent2Levels).append(String.format("<setting name=\"%s\" >\n", setting.getName()));
        xml.append(indent3Levels).append(StringEscapeUtils.escapeXml(setting.getValue()));
        xml.append(indent2Levels).append("</setting>\n");
    }

    private void appendSettingType(final StringBuilder xml, final Setting.Type type) {
        final String indent = StringUtils.repeat("    ", 1);
        xml.append(String.format("%s<settings type=\"%s\" >\n", indent, type.getValue()));
        final SettingsHandler<?, ?> handler = handlersMap.get(type);
        final List<Setting> settings = handler.listSettings();
        for (final Setting setting : settings) {
            // Setting in ignore list, don't export it
            if (type == Setting.Type.LOCAL && IGNORED_SETTINGS.contains(setting.getName())) {
                continue;
            }
            appendSetting(xml, setting);
        }
        xml.append(indent).append("</settings>\n");
    }

    private void importNew() {
        settingDao.importNew(getLocalSettings().getLocale());
        refreshTranslationRelatedHandlers();
    }

    private void refreshTranslationRelatedHandlers() {
        localSettingsHandler.refresh();
        messageSettingsHandler.refresh();
        mailTranslationHandler.refresh();
    }

}