All Downloads are FREE. Search and download functionalities are using the official Maven repository.

se.l4.vibe.internal.service.ServiceImpl Maven / Gradle / Ivy

There is a newer version: 0.4.0
Show newest version
package se.l4.vibe.internal.service;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;


/**
 * Implementation of {@link Service} that uses reflection.
 * 
 * @author Andreas Holstenson
 *
 */
public class ServiceImpl
	implements Service
{
	private final Object object;
	private final ConcurrentMap attributes;

	public ServiceImpl(Object object)
	{
		this.object = object;
		
		attributes = new ConcurrentHashMap();
		buildAttributes(attributes, object.getClass());
	}
	
	private void buildAttributes(ConcurrentMap attributes, Class type)
	{
		while(type != Object.class)
		{
			for(Field field : type.getDeclaredFields())
			{
				if(field.isAnnotationPresent(ExposeAsAttribute.class))
				{
					Attribute attr = new AttributeViaField(field);
					if(attributes.containsKey(attr.getName()))
					{
						throw new IllegalArgumentException("Attribute named " 
							+ attr.getName() + " already exists; Declared via " 
							+ attributes.get(attr.getName()));
					}
					
					attributes.put(attr.getName(), attr);
				}
			}
			
			for(Method method : type.getDeclaredMethods())
			{
				if(method.isAnnotationPresent(ExposeAsAttribute.class))
				{
					Attribute attr = new AttributeViaMethod(method);
					if(attributes.containsKey(attr.getName()))
					{
						throw new IllegalArgumentException("Attribute named " 
							+ attr.getName() + " already exists; Declared via " 
							+ attributes.get(attr.getName()));
					}
					
					attributes.put(attr.getName(), attr);
				}
			}
			
			type = type.getSuperclass();
		}
	}
	
	@Override
	public Collection getAttributes()
	{
		return attributes.values();
	}
	
	@Override
	public Attribute getAttribute(String attribute)
	{
		return attributes.get(attribute);
	}
	
	private class AttributeViaField
		implements Attribute
	{
		private final Field field;
		private final String name;

		public AttributeViaField(Field field)
		{
			this.field = field;
			field.setAccessible(true);
			
			ExposeAsAttribute annotation = field.getAnnotation(ExposeAsAttribute.class);
			this.name = annotation.value().equals("") ? field.getName() : annotation.value();
		}
		
		@Override
		public String getName()
		{
			return name;
		}
		
		@Override
		public Class getType()
		{
			return field.getType();
		}
		
		@Override
		public Object getValue()
		{
			try
			{
				return field.get(object);
			}
			catch(IllegalArgumentException e)
			{
				throw new RuntimeException("Unable to get value of field " + field + "; " + e.getMessage(), e);
			}
			catch(IllegalAccessException e)
			{
				throw new RuntimeException("Unable to get value of field " + field + "; " + e.getMessage(), e);
			}
		}
		
		@Override
		public String toString()
		{
			return "AttributeViaField[" + field + "]";
		}
	}
	
	private class AttributeViaMethod
		implements Attribute
	{
		private final Method method;
		private final String name;

		public AttributeViaMethod(Method method)
		{
			this.method = method;
			method.setAccessible(true);
			
			if(method.getParameterTypes().length != 0)
			{
				throw new IllegalArgumentException("Method " + method + " must not have any parameters");
			}
			
			if(method.getReturnType() == void.class)
			{
				throw new IllegalArgumentException("Method " + method + " must not have a non void return type");
			}
			
			ExposeAsAttribute annotation = method.getAnnotation(ExposeAsAttribute.class);
			this.name = annotation.value().equals("") ? method.getName() : annotation.value();
		}

		@Override
		public String getName()
		{
			return name;
		}

		@Override
		public Class getType()
		{
			return method.getReturnType();
		}

		@Override
		public Object getValue()
		{
			try
			{
				return method.invoke(object);
			}
			catch(IllegalArgumentException e)
			{
				throw new RuntimeException("Unable to get value; " + e.getMessage(), e);
			}
			catch(IllegalAccessException e)
			{
				throw new RuntimeException("Unable to get value; " + e.getMessage(), e);
			}
			catch(InvocationTargetException e)
			{
				throw new RuntimeException("Unable to get value; " + e.getCause().getMessage(), e.getCause());
			}
		}
		
		@Override
		public String toString()
		{
			return "AttributeViaMethod[" + method + "]";
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy