package com.idega.util.messages;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.OperationNotSupportedException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import com.idega.core.cache.IWCacheManager2;
import com.idega.idegaweb.IWMainApplication;
import com.idega.util.StringUtil;
import com.idega.util.expression.ELUtil;
/**
*
*
* @author <a href="anton@idega.com">Anton Makarov</a>
* @version Revision: 1.0
*
* Last modified: Oct 16, 2008 by Author: Anton
*
*/
@Service
@Scope(BeanDefinition.SCOPE_SINGLETON)
public class MessageResourceFactoryImpl implements MessageResourceFactory {
@Autowired
private List<MessageResource> uninitializedMessageResources;
private static final Logger LOGGER = Logger.getLogger(MessageResourceFactoryImpl.class.getName());
private static final String CACHED_RESOURCES = "cached_resources";
private List<MessageResource> getInitializedResourceList(Locale locale, String bundleIdentifier) {
if (bundleIdentifier == null)
bundleIdentifier = MessageResource.NO_BUNDLE;
Map<String, Map<Locale, List<MessageResource>>> cachedResources = getCache();
Map<Locale, List<MessageResource>> bundleResources = cachedResources.get(bundleIdentifier);
if (bundleResources == null) {
bundleResources = new HashMap<Locale, List<MessageResource>>();
cachedResources.put(bundleIdentifier, bundleResources);
}
if (bundleResources.containsKey(locale)) {
List<MessageResource> resources = bundleResources.get(locale);
sortResourcesByImportance(resources);
return resources;
}
// There is no bundle with specified bundleIdentifier and locale
List<MessageResource> resources = getUninitializedMessageResources();
List<MessageResource> failedInitializationResources = new ArrayList<MessageResource>();
for (MessageResource resource: resources) {
try {
resource.initialize(bundleIdentifier, locale);
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Error initializing bundle: " + bundleIdentifier, e);
failedInitializationResources.add(resource);
} catch (OperationNotSupportedException e) {
failedInitializationResources.add(resource);
}
}
for (MessageResource resource: failedInitializationResources) {
resources.remove(resource);
}
bundleResources.put(locale, resources);
sortResourcesByImportance(resources);
return resources;
}
public void addInitializedMessageResource(MessageResource resource, String bundleIdentifier, Locale locale) {
List<MessageResource> cachedResources = getInitializedResourceList(locale, bundleIdentifier);
if (!cachedResources.contains(resource)) {
cachedResources.add(resource);
}
}
/**
* Gets localized message for the current locale
* @return object that was found in resource and/or set to it or valueIfNotFound object in case no messages were found
* or auto inserted
*/
public Object getLocalisedMessage(Object key, Object valueIfNotFound, String bundleIdentifier, Locale locale) {
List<MessageResource> resources = getInitializedResourceList(locale, bundleIdentifier);
for (MessageResource resource: resources) {
if (!resource.getLevel().equals(MessageResourceImportanceLevel.OFF)) {
Object message = resource.getMessage(key);
if (message != null && String.valueOf(message).length() > 0) {
return message;
}
}
}
if (valueIfNotFound == null) {
return null;
}
//Auto inserting message in case none of resources has it
for(MessageResource resource: resources) {
if (resource.isAutoInsert()) {
resource.setMessage(key, valueIfNotFound);
}
}
return valueIfNotFound;
}
public Object setLocalisedMessage(Object key, Object value, String bundleIdentifier, Locale locale) {
List<MessageResource> resources = getInitializedResourceList(locale, bundleIdentifier);
for (MessageResource resource: resources) {
resource.setMessage(key, value);
}
return value;
}
public void setLocalisedMessages(Map<Object, Object> values, String bundleIdentifier, Locale locale) {
List<MessageResource> resources = getInitializedResourceList(locale, bundleIdentifier);
for (MessageResource resource: resources) {
resource.setMessages(values);
}
}
public Map<String, Object> setLocalisedMessageToAutoInsertRes(Object key, Object value, String bundleIdentifier, Locale locale) {
List<MessageResource> resources = getInitializedResourceList(locale, bundleIdentifier);
Map<String, Object> setMessages = new HashMap<String, Object>(resources.size());
for(MessageResource resource : resources) {
if(resource.isAutoInsert()) {
Object setValue = resource.setMessage(key, value);
if(setValue != null) {
setMessages.put(resource.getIdentifier(), setValue);
}
}
}
return setMessages;
}
public void removeLocalisedMessageFromAutoInsertRes(Object key, String bundleIdentifier, Locale locale) {
List<MessageResource> resources = getInitializedResourceList(locale, bundleIdentifier);
for (MessageResource resource: resources) {
if (resource.isAutoInsert()) {
resource.removeMessage(key);
}
}
}
private void sortResourcesByImportance(List<MessageResource> resources) {
ResourceComparatorByLevel resourceComparatorByLevel = new ResourceComparatorByLevel();
Collections.sort(resources, resourceComparatorByLevel);
}
public MessageResource getResource(String identifier, String bundleIdentifier, Locale locale) {
for (MessageResource resource: getInitializedResourceList(locale, bundleIdentifier)) {
if (identifier.equals(resource.getIdentifier())) {
return resource;
}
}
return null;
}
public List<MessageResource> getResourceListByStorageIdentifier(String storageIdentifier) {
if (StringUtil.isEmpty(storageIdentifier)) {
LOGGER.warning("Storage identifier is not defined!");
return Collections.emptyList();
}
Map<String, Map<Locale, List<MessageResource>>> cachedResources = getCache();
List<MessageResource> storageResources = new ArrayList<MessageResource>();
for (String bundleIdentifier: cachedResources.keySet()) {
Map<Locale, List<MessageResource>> bundleResources = cachedResources.get(bundleIdentifier);
if (bundleResources == null) {
bundleResources = new HashMap<Locale, List<MessageResource>>();
cachedResources.put(bundleIdentifier, bundleResources);
}
for (Locale locale: bundleResources.keySet()) {
List<MessageResource> localizedMessages = bundleResources.get(locale);
if (localizedMessages == null) {
localizedMessages = new ArrayList<MessageResource>();
bundleResources.put(locale, localizedMessages);
}
for (MessageResource resource: localizedMessages) {
if (storageIdentifier.equals(resource.getIdentifier())) {
storageResources.add(resource);
}
}
}
}
return storageResources;
}
public List<MessageResource> getResourceListByBundleAndLocale(String bundleIdentifier, Locale locale) {
return getInitializedResourceList(locale, bundleIdentifier);
}
private IWMainApplication getIWMainApplication() {
IWMainApplication iwma = IWMainApplication.getDefaultIWMainApplication();
return iwma;
}
private List<MessageResource> getUninitializedMessageResources() {
ELUtil.getInstance().autowire(this);
return uninitializedMessageResources;
}
public List<MessageResource> getAvailableUninitializedMessageResources() {
List<MessageResource> allUninitializedResources = getUninitializedMessageResources();
List<MessageResource> resourcesToRemove = new ArrayList<MessageResource>();
for (MessageResource resource : allUninitializedResources) {
List<MessageResource> availableResourcesOfType = getResourceListByStorageIdentifier(resource.getIdentifier());
if (availableResourcesOfType.isEmpty()) {
resourcesToRemove.add(resource);
}
}
for (MessageResource resource: resourcesToRemove) {
allUninitializedResources.remove(resource);
}
return allUninitializedResources;
}
protected class ResourceComparatorByLevel implements Comparator<MessageResource> {
private static final int LESS = -1;
private static final int EQUAL = 0;
private static final int GREATER = 1;
public int compare(MessageResource msg1, MessageResource msg2) {
if (msg1.getLevel().intValue() > msg2.getLevel().intValue()) {
return LESS;
} else if (msg1.getLevel().intValue() < msg2.getLevel().intValue()) {
return GREATER;
} else return EQUAL;
}
}
private Map<String, Map<Locale, List<MessageResource>>> getCache() {
return IWCacheManager2.getInstance(getIWMainApplication()).getCache(CACHED_RESOURCES, 1000, true, false, 50, 10);
}
}