001package org.biopax.paxtools.controller;
002
003import org.biopax.paxtools.model.BioPAXElement;
004import org.biopax.paxtools.util.IllegalBioPAXArgumentException;
005
006import java.lang.reflect.Method;
007import java.util.Collections;
008import java.util.Set;
009
010/**
011 * Provides a primitive (int, float, double)  class compatible editor by extending the {@link
012 * PropertyEditor}.
013 *
014 * @see PropertyEditor
015 */
016public class PrimitivePropertyEditor<D extends BioPAXElement, R>
017                extends AbstractPropertyEditor<D, R> implements DataPropertyEditor<D,R>
018{
019// ------------------------------ FIELDS ------------------------------
020
021        /**
022         * When a value is not present in the OWL file
023         */
024        private R unknownValue = null;
025
026// --------------------------- CONSTRUCTORS ---------------------------
027
028        /**
029         *
030         * @param property Name of the property, e.g. stoichiometricCoefficient.
031         * @param getMethod A "Method" class that represents the getter method. e.g. getEntityReference()
032         * @param domain name of the domain of this property. e.g. PhysicalEntity
033         * @param range name of the range of this property. e.g. EntityReference.
034         * @param multipleCardinality false if this property is functional, e.g. many-to-one or one-to-one.
035         */
036        public PrimitivePropertyEditor(String property, Method getMethod,
037                                       Class<D> domain,
038                                       Class<R> range,
039                                       boolean multipleCardinality)
040        {
041                super(property,
042                                getMethod,
043                                domain,
044                                range,
045                                multipleCardinality);
046
047                assert (range == Boolean.class || range.isPrimitive());
048
049                if (range.equals(double.class))
050                {
051                        unknownValue = ((R) BioPAXElement.UNKNOWN_DOUBLE);
052                }
053                else if (range.equals(float.class))
054                {
055                        unknownValue = ((R) BioPAXElement.UNKNOWN_FLOAT);
056                }
057                else if (range.equals(int.class))
058                {
059                        unknownValue = ((R) BioPAXElement.UNKNOWN_INT);
060                }
061
062        }
063
064// -------------------------- OTHER METHODS --------------------------
065
066
067        @Override
068        protected R parseValueFromString(String s)
069        {
070                Class<R> range = this.getRange();
071                R value = null;
072                try
073                {
074                        if (range.equals(double.class))
075                        {
076                                value= (R) Double.valueOf(s);
077                        }
078                        else if (range.equals(float.class))
079                        {
080                                value=  (R) Float.valueOf(s);
081                        }
082                        else if (range.equals(int.class))
083                        {
084                                value= (R) Integer.valueOf(s);
085                        }
086                        else if (range.equals(Boolean.class))
087                        {
088                                value= (R) Boolean.valueOf(s);
089                        }
090                }
091
092                catch (NumberFormatException e)
093
094                {
095                        throw new IllegalBioPAXArgumentException(
096                                        "Failed to convert literal " + s +
097                                        " to " + range.getSimpleName()
098                                        + " for " + property, e);
099                }
100                return value;
101        }
102
103
104        /**
105         * According the editor type, this methods checks if value equals 
106         * to one of the unknown values defined under {@link org.biopax.paxtools.model.BioPAXElement}
107         *  or is an empty set or set of "unknown" values.
108         *
109         * @param value the value to be checked if it is unknown
110         * @return true, if value equals to the predefined unknown value
111         */
112        @Override
113        public boolean isUnknown(Object value)
114        {
115                return (value instanceof Set) 
116                        ? emptySetOrContainsOnlyUnknowns((Set)value) 
117                                : emptySetOrContainsOnlyUnknowns(Collections.singleton(value));
118        }
119
120        
121        private boolean emptySetOrContainsOnlyUnknowns(Set value) {
122                for(Object o : value) {
123                        if(o != unknownValue && !o.equals(unknownValue)) {
124                                return false; // found a "known" value
125                        }
126                }
127                // empty set or all unknown
128                return true;
129        }
130
131        
132        @Override
133        public R getUnknown() {
134                return unknownValue;
135        }
136}