/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.evasion.plugin.common;
import com.evasion.ejb.local.TemplateManagerLocal;
import com.evasion.ejb.remote.TemplateManagerRemote;
import com.evasion.entity.Template;
import com.evasion.plugin.common.dao.TemplateDaoImpl;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.PostConstruct;
import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author sebastien.glon
*/
@Stateless
@Local(value = TemplateManagerLocal.class)
@Remote(value = TemplateManagerRemote.class)
public class TemplateManager implements TemplateManagerLocal, TemplateManagerRemote {
/** LOGGER */
private static final Logger LOGGER = LoggerFactory.getLogger(
TemplateManager.class);
private static final String START_PATTERN = "${";
private static final String END_PATTERN = "}";
private static final String GETTER_PREFIX = "get";
private static final String BOOLEAN_GETTER_PREFIX = "is";
private static final String FIND_PATTERN = "(.*?)"
+ escapeRegexCharacter(START_PATTERN) + "(.*?)"
+ escapeRegexCharacter(END_PATTERN) + "(.*?)";
private static final String SEPARATOR = ".";
@PersistenceContext(unitName = "EvasionPU")
private EntityManager em;
private final TemplateDaoImpl dao;
protected TemplateManager(EntityManager em) {
dao = new TemplateDaoImpl();
dao.setEntityManager(em);
}
public TemplateManager() {
dao = new TemplateDaoImpl();
}
@SuppressWarnings("PMD.UnusedPrivateMethod")
@edu.umd.cs.findbugs.annotations.SuppressWarnings("UPM_UNCALLED_PRIVATE_METHOD")
@PostConstruct
private void init() {
dao.setEntityManager(em);
}
/**
* Echape les caractères spécifique à REGEX.
* @param expression expresseion à traiter
* @return expression avec caractères spéciaux echapé.
*/
public static String escapeRegexCharacter(final String expression) {
return expression.replaceAll(
"([\\\\*+\\[\\](){}\\$.?\\^|])", "\\\\$1");
}
/**
* {@inheritDoc }
*/
@Override
public void saveTemplate(String key, Locale locale, String text) {
Template template = new Template(key, locale.getLanguage(), text);
dao.merge(template);
}
/**
* {@inheritDoc }
*/
@Override
public String getTemplate(String key, Locale locale) {
String result = null;
try {
result = dao.findByKeyAndLocale(key, locale.getLanguage());
} catch (NoResultException ex) {
LOGGER.debug("Template non trouvé", ex);
}
return result;
}
/**
* {@inheritDoc }
*/
@Override
public String merge(String key, Locale locale, Map<String, ? extends Object> properties) {
String template = getTemplate(key, locale);
return merge(template, properties);
}
/**
* Méthode de merge d'un template avec les valeurs des propriété.
* @param template le template.
* @param properties les propriété à intégrer.
* @return le résultat du merge.
*/
protected String merge(final String template, Map<String, ? extends Object> properties) {
String result = template;
Map<String, Set<String>> propertiesFind = findKey(template);
LOGGER.debug("debut du merge");
for (Map.Entry<String, ? extends Object> propertyEntry : properties.entrySet()) {
if (propertiesFind.containsKey(propertyEntry.getKey())) {
Set<String> extensions = new HashSet<String>(propertiesFind.get(propertyEntry.getKey()));
for (String ext : extensions) {
String value = getProperties(propertyEntry.getValue(), ext);
LOGGER.debug("Remplacement des valeurs: key {}, value {}", propertyEntry.getKey(), propertyEntry.getValue());
if (StringUtils.isBlank(ext)) {
// Gestion des clé sans extension.
result = StringUtils.replace(result, START_PATTERN + propertyEntry.getKey() + END_PATTERN, value);
} else {
// Gestion des clé avec extension.
result = StringUtils.replace(result, START_PATTERN + propertyEntry.getKey() + SEPARATOR + ext + END_PATTERN, value);
}
}
} else {
LOGGER.debug("Property Key: {} can not be found", (String) propertyEntry.getKey());
}
}
return result;
}
/**
* Recherhce l'ensemble des clé dans le template.
* @param templateText le template à traiter.
* @return la map des clés trouvé.
*/
protected Map<String, Set<String>> findKey(String templateText) {
Map<String, Set<String>> result = new HashMap<String, Set<String>>();
//Pattern keyTemplate = Pattern.compile(START_PATTERN + "(.*?)" + END_PATTERN);
Pattern keyTemplate = Pattern.compile(FIND_PATTERN);
Matcher tagmatch = keyTemplate.matcher(templateText);
LOGGER.debug("Matcher généré: {} - {}", tagmatch.toString(), templateText);
//LOGGER.debug("find: {}", tagmatch.find());
while (tagmatch.find()) {
LOGGER.debug("groupe: {}", tagmatch.group(2));
String key = StringUtils.substringBefore(tagmatch.group(2), SEPARATOR);
String ext = StringUtils.substringAfter(tagmatch.group(2), SEPARATOR);
if (result.containsKey(key)) {
((HashSet) result.get(key)).add(ext);
} else {
Set<String> set = new HashSet<String>();
set.add(ext);
result.put(key, set);
}
}
LOGGER.debug("End find key.");
return result;
}
/**
* définit la valeur d'une clé à partir d'un bean.
* @param bean
* @param ext
* @return
*/
protected String getProperties(Object bean, String ext) {
String[] propertiesName = StringUtils.split(ext, SEPARATOR);
Object internalBean = bean;
for (String propertyName : propertiesName) {
internalBean = getSimpleProperty(internalBean, propertyName);
}
return internalBean.toString();
}
/**
* définit la valeur d'une clé à partir d'un bean.
* @param bean
* @param ext
* @return
*/
protected Object getSimpleProperty(Object bean, String propertyName) {
Object result = null;
try {
Method getter = null;
final String methodNameSuffix = StringUtils.capitalize(propertyName);
final String getterName = new StringBuffer().append(GETTER_PREFIX).append(methodNameSuffix).toString();
final String booleanGetterName = new StringBuffer().append(BOOLEAN_GETTER_PREFIX).append(methodNameSuffix).toString();
for (Method method : bean.getClass().getMethods()) {
if ((getterName.equals(method.getName()) || booleanGetterName.equals(method.getName())) && isGetterMethod(method)) {
getter = method;
break;
}
}
if (getter == null) {
for (Method method : bean.getClass().getDeclaredMethods()) {
if ((getterName.equals(method.getName()) || booleanGetterName.equals(method.getName())) && isGetterMethod(method)) {
getter = method;
break;
}
}
}
if (getter != null) {
result = getter.invoke(bean);
}
} catch (IllegalAccessException ex) {
LOGGER.error("Erreur de récuéraction d'une propriete pour un template", ex);
} catch (IllegalArgumentException ex) {
LOGGER.error("Erreur de récuéraction d'une propriete pour un template", ex);
} catch (InvocationTargetException ex) {
LOGGER.error("Erreur de récuéraction d'une propriete pour un template", ex);
} finally {
return result;
}
}
/**
* Returns <code>true</code> if the given method is a getter.
*
* Note: a method is a getter if
* <ul>
* <li>its name starts with 'get' or 'is' and is followed by a uppercase
* letter</li>
* <li>it takes no argument</li>
* <li>its return type is not <code>void</code></li>
* </ul>
*
* @param method
* the method to test
* @return <code>true</code> if the method is a getter, <code>false</code>
* otherwise.
*/
private static boolean isGetterMethod(final Method method) {
boolean result = true;
final String methodName = method.getName();
if (!methodName.startsWith(GETTER_PREFIX)
&& !methodName.startsWith(BOOLEAN_GETTER_PREFIX)) {
// a getter method must starts with 'get' or 'is'
result = false;
}
String propertyName = null;
if (methodName.startsWith(GETTER_PREFIX)) {
propertyName = methodName.substring(GETTER_PREFIX.length());
} else if (methodName.startsWith(BOOLEAN_GETTER_PREFIX)) {
propertyName = methodName.substring(BOOLEAN_GETTER_PREFIX.length());
}
if (StringUtils.isBlank(propertyName)
|| !propertyName.equals(StringUtils.capitalize(propertyName))) {
// the first character after the prefix must be in upper case.
result = false;
}
if (method.getReturnType() == null
|| method.getReturnType() == void.class) {
// a getter method cannot return void
result = false;
}
if (method.getParameterTypes().length > 0) {
// a getter method takes no argument
result = false;
}
return result;
}
@Override
public void saveEmailTemplate(String key, Locale locale, String subject, String body) {
saveTemplate(Constante.PREFIX_EMAIL_TEMPLATE_BODY + key, locale, body);
saveTemplate(Constante.PREFIX_EMAIL_TEMPLATE_SUBJECT + key, locale, subject);
}
}