001package org.biopax.paxtools.controller;
002
003import org.biopax.paxtools.model.BioPAXElement;
004import org.biopax.paxtools.util.IllegalBioPAXArgumentException;
005
006import java.lang.reflect.InvocationTargetException;
007import java.lang.reflect.Method;
008import java.util.Collections;
009import java.util.Set;
010
011/**
012
013 */
014public class SimplePropertyAccessor<D extends BioPAXElement, R> extends PropertyAccessorAdapter<D, R>
015{
016        /**
017         * This variable stores the method to invoke for getting the value of the property on a given bean.
018         * In the case of multiple cardinality, this method is expected to return a {@link java.util.Set}
019         * otherwise an instance of {@link #range}
020         */
021        protected final Method getMethod;
022
023        public SimplePropertyAccessor(Class<D> domain, Class<R> range, boolean multipleCardinality, Method getMethod)
024        {
025                super(domain, range, multipleCardinality);
026                this.getMethod = getMethod;
027        }
028
029        protected static boolean isMultipleCardinality(Method getMethod)
030        {
031                return Set.class.isAssignableFrom(getMethod.getReturnType());
032        }
033
034        /**
035         * Returns the value of the <em>bean</em> using the default {@link #getMethod}.
036         * If the value is unknown returns null or an empty set depending on the cardinality.
037         * @param bean the object whose property is requested
038         * @return an object as the value
039         */
040        @Override public Set<R> getValueFromBean(D bean) throws IllegalBioPAXArgumentException
041        {
042                Object value = null;
043                try
044                {
045                        if (this.getDomain().isInstance(bean)) value = this.getMethod.invoke(bean);
046                }
047                catch (IllegalAccessException e)
048                {
049                        throw new IllegalBioPAXArgumentException(
050                                        "Could not invoke get method " + getMethod.getName() + " for " + bean, e);
051                }
052                catch (IllegalArgumentException e)
053                {
054                        throw new IllegalBioPAXArgumentException(
055                                        "Could not invoke get method " + getMethod.getName() + " for " + bean, e);
056                }
057
058                catch (InvocationTargetException e)
059                {
060                        throw new IllegalBioPAXArgumentException(
061                                        "Could not invoke get method " + getMethod.getName() + " for " + bean, e);
062                }
063
064                if (value == null) return Collections.emptySet();
065                else if (this.isMultipleCardinality())
066                {
067                        return (Collections.unmodifiableSet(((Set<R>) value)));
068                } else
069                {
070                        return Collections.singleton(((R) value));
071                }
072        }
073
074        /**
075         * Checks if the <em>value</em> is unkown. In this context a <em>value</em> is regarded to be
076         * unknown if it is null (unset).
077         * @param value the value to be checked
078         * @return true if the value is unknown
079         */
080        public boolean isUnknown(Object value)
081        {
082                return value == null || (value instanceof Set ? ((Set) value).isEmpty() : false);
083        }
084
085        @Override
086        public String toString() {
087                return String.format("%s %s %s", domain.getSimpleName(), getMethod.getName(), range.getSimpleName());
088        }
089}