/*
Copyright (C) European Community 2008 - Licensed under the EUPL V.1.0 (http://ec.europa.eu/idabc/en/document/6523)
*/
package it.hotel.aspects;
import it.hotel.controller.locale.ILocaleContainer;
import it.hotel.model.label.Label;
import it.hotel.model.label.manager.ILabelManager;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.springframework.aop.AfterReturningAdvice;
/**
*
*
*/
public class MultiLingualInterceptor implements AfterReturningAdvice{
protected ILocaleContainer localeContainer = null;
protected ILabelManager labelManager = null;
/**
* @throws
*/
@Override
public void afterReturning(Object returnValue, Method method, Object[] arguments,
Object targetObject) throws Throwable {
if (returnValue == null){
return;
}
Collection c = new ArrayList();
if (returnValue.getClass().isInstance(c))
{
for (Object obj : (Collection)returnValue){
setLocaleForLocalizedObject(obj);
}
}
else
{
setLocaleForLocalizedObject(returnValue);
return;
}
}
public ILabelManager getLabelManager() {
return labelManager;
}
public void setLabelManager(ILabelManager labelManager) {
this.labelManager = labelManager;
}
public ILocaleContainer getLocaleContainer() {
return localeContainer;
}
public void setLocaleContainer(ILocaleContainer localeContainer) {
this.localeContainer = localeContainer;
}
/**
* Goes through the given hibernate model and sets fields that need to be localised,
* objects that need to be localised and collections that need to be localised. This
* is done recursively
* @param model - a hibernate model that needs to be localised (i.e it has a getId method)
* @throws Exception - mainly for the case when this is not a hibernate model
*/
private void setLocaleForLocalizedObject(Object model) throws Exception {
setLocalisedFields(model);
setLocalisedObjects(model);
setLocalisedCollections(model);
}
/**
* Goes through the given hibernate model recursively asks the objects within it that need
* to be localised to localise.
* @param model - a hibernate model that needs to be localised (i.e it has a getId method)
* @throws Exception - mainly for the case when this is not a hibernate model
*/
private void setLocalisedObjects(Object model) throws Exception
{
List<String> localisedObjectNames = MultiLingualInterceptor.getLocalisedObjectNames(model);
for (String object: localisedObjectNames){
String methodGetter = "get" + object;
Method getLocalisedObjectMethod = model.getClass().getMethod(methodGetter);
Object localisedObject = (Object) getLocalisedObjectMethod.invoke(model);
if (localisedObject != null){
setLocaleForLocalizedObject(localisedObject);
}
}
}
/**
* Goes through the given hibernate model recursively asks the collections within it that need
* to be localised to localise.
* @param model - a hibernate model that needs to be localised (i.e it has a getId method)
* @throws Exception - mainly for the case when this is not a hibernate model
*/
private void setLocalisedCollections(Object model) throws Exception
{
List<String> localisedCollectionNames = MultiLingualInterceptor.getLocalisedCollectionNames(model);
for (String collection: localisedCollectionNames){
String methodGetter = "get" + collection;
Method getLocalisedCollectionMethod = model.getClass().getMethod(methodGetter);
Collection<Object> localisedCollection = (Collection<Object>) getLocalisedCollectionMethod.invoke(model);
for (Object localisedObject : localisedCollection){
if (localisedObject != null){
setLocaleForLocalizedObject(localisedObject);
}
}
}
}
/**
* Finds all fields on the given object that need to be localised
* @param model
* @return a list of field names
*/
static public List<String> getLocalisedFields(Object model){
return getLocalisedNamesFor(model,"LocalisedField");
}
/**
* Finds all collections on the given object that need to be localised
* @param model
* @return a list of collection names
*/
static public List<String> getLocalisedCollectionNames(Object model){
return getLocalisedNamesFor(model,"LocalisedCollection");
}
/**
* Finds all objects on the given model that need to be localised
* @param model
* @return a list of object names
*/
static public List<String> getLocalisedObjectNames(Object model){
return getLocalisedNamesFor(model,"LocalisedObject");
}
/**
* Call a getter with the given name and return the value
*
* @param model model you want to call
* @param fieldName name of string field you want get
* @return value of field or empty string in case of problems
*/
public static String getFieldText(Object model, String fieldName) {
String methodGetter = "get" + fieldName;
Method getLocalisedFieldText;
String text;
try {
getLocalisedFieldText = model.getClass().getMethod(methodGetter);
text = (String) getLocalisedFieldText.invoke(model);
} catch (Exception e) {
text = new String();
}
return text;
}
/**
* set a given field on a model with given string value
*
* @param model model you want to call
* @param fieldName name of string field you want set
*/
public static void setFieldText(Object model, String fieldName,String text) {
try {
Method SetterForField = model.getClass().getMethod(("set" + fieldName), new Class[] {String.class});
SetterForField.invoke(model, text);
} catch (Exception e) {
//don't do anything
}
}
/**
*
* @param model
* @param field
* @return
*/
static public String createDescriptorCode(Object model, String field) {
String modelName = model.getClass().getSimpleName();
String descriptor = modelName + "." + field;
return descriptor;
}
/**
* Goes through the given hibernate model and sets fields that need to be localised,
* This uses reflection to search for methods on the object with the name LocalisedField
* to determine if the field needs to be looking up
*
* @param model - a hibernate model that needs to be localised (i.e it has a getId method)
* @throws Exception - mainly for the case when this is not a hibernate model
*/
private void setLocalisedFields(Object model) throws Exception {
List<String> localisedFieldNames = MultiLingualInterceptor.getLocalisedFields(model);
for (String field: localisedFieldNames){
String descriptor = MultiLingualInterceptor.createDescriptorCode(model, field);
int id = getIdFromModel(model);
String locale = localeContainer.getLocale();
Label label = labelManager.getLabel(id,descriptor,locale);
if (label == null)
{
label = new Label();
label.setText(new String());
}
setFieldText(model,field,label.getText());
}
}
/**
* Get the id of from the model using reflection, note that no object here
* should not have an id
*
* @param model - hibernate model
* @return id of model
* @throws exception when trying to get the method
*/
public static int getIdFromModel(Object model) throws NoSuchMethodException,
IllegalAccessException, InvocationTargetException {
Method getIdMethod = model.getClass().getMethod("getId");
int id = (Integer) getIdMethod.invoke(model);
return id;
}
/**
* Given an object model and a String , will search the object for methods of that
* start with that name and return the rest of the method name which should match to a field
* on the object.
*
* @param x description
* @return x description.
* @throws Exception
* @throws SecurityException
* @throws exception description
*/
private static List<String> getLocalisedNamesFor(Object model,String localisedMethodName) {
Method[] methods = model.getClass().getMethods();
int length = methods.length;
List<String> localisedNames = new ArrayList<String>();
for (int i = 0; i < length; i++){
Method method = methods[i];
String name = method.getName();
if (name.startsWith(localisedMethodName)){
String localisedName = name.substring(localisedMethodName.length());
String text = getFieldText(model, localisedName);
if(text != null){
localisedNames.add(localisedName);
}
}
}
return localisedNames;
}
}