001 package com.hammurapi.reasoning.impl;
002
003 import java.lang.reflect.Field;
004 import java.lang.reflect.InvocationTargetException;
005 import java.lang.reflect.Method;
006 import java.lang.reflect.Modifier;
007 import java.util.HashMap;
008 import java.util.Map;
009 import java.util.logging.Level;
010 import java.util.logging.Logger;
011
012 import com.hammurapi.convert.AtomicConverter;
013 import com.hammurapi.convert.Converter;
014 import com.hammurapi.reasoning.spi.Superseder;
015 import com.hammurapi.util.Context;
016
017 public class BeanSupersederAtomicConverter implements AtomicConverter<Object, Superseder> {
018 private static final Logger logger = Logger.getLogger(BeanSupersederAtomicConverter.class.getName());
019
020 @Override
021 public Superseder convert(final Object source, Converter master, Context context, ClassLoader classLoader) {
022 return new Superseder() {
023
024 @Override
025 public boolean supersedes(Object subFact) {
026 if (source==subFact) {
027 return false;
028 }
029
030 if (source==null) {
031 return false;
032 }
033
034 if (subFact==null) {
035 return false;
036 }
037
038 if (subFact.getClass().isInstance(source) && !source.getClass().isInstance(subFact)) {
039 try {
040 Map<String, Object> sourceData = extractData(source);
041 Map<String, Object> subFactData = extractData(subFact);
042 if (sourceData.keySet().containsAll(subFactData.keySet())) {
043 for (String key: subFactData.keySet()) {
044 Object sourceValue = sourceData.get(key);
045 Object subFactValue = subFactData.get(key);
046 if (sourceValue==null) {
047 if (subFactValue!=null) {
048 return false;
049 }
050 } else {
051 if (subFactValue==null) {
052 return false;
053 }
054
055 if (!sourceValue.equals(subFactValue)) {
056 return false;
057 }
058 }
059 }
060 return true;
061 }
062 } catch (InvocationTargetException e) {
063 logger.log(Level.WARNING, "Data extraction failed: "+e, e);
064 return false;
065 } catch (IllegalAccessException e) {
066 logger.log(Level.WARNING, "Data extraction failed: "+e, e);
067 return false;
068 }
069 }
070 return false;
071 }
072
073 };
074 }
075
076 private static Map<String, Object> extractData(Object obj) throws IllegalAccessException, InvocationTargetException {
077 Map<String, Object> ret = new HashMap<String, Object>();
078 for (Method method: obj.getClass().getMethods()) {
079 if (method.getName().startsWith("get")
080 && !Modifier.isStatic(method.getModifiers())
081 && method.getParameterTypes().length==0
082 && !Object.class.equals(method.getDeclaringClass())) {
083 ret.put("method:"+method.getName(), method.invoke(obj));
084 }
085 }
086
087 for (Field field: obj.getClass().getFields()) {
088 if (!Modifier.isStatic(field.getModifiers())) {
089 ret.put("field:"+field.getName(), field.get(obj));
090 }
091 }
092
093 return ret;
094 }
095
096 @Override
097 public Class<Object> getSourceType() {
098 return Object.class;
099 }
100
101 @Override
102 public Class<? extends Superseder> getTargetType() {
103 return Superseder.class;
104 }
105
106 }