001    package jcolibri.method.retrieve.NNretrieval.similarity.local;
002    
003    
004    
005    import jcolibri.method.retrieve.NNretrieval.similarity.LocalSimilarityFunction;
006    
007    
008    /**
009     * This function computes the similarity between two enum values as their cyclic
010     * distance.
011     * 
012     * @author Juan A. Recio-García
013     */
014    public class EnumCyclicDistance implements LocalSimilarityFunction {
015    
016    
017    
018            /**
019             * Applies the similarity.
020             * 
021             * @param o1
022             *            Enum.
023             * @param o2
024             *            Enum.
025             * @return the result to apply the similarity.
026             */
027            public double compute(Object o1, Object o2) throws jcolibri.exception.NoApplicableSimilarityFunctionException{
028                    if ((o1 == null) || (o2 == null))
029                            return 0;
030                    if(!(o1 instanceof Enum))
031                            throw new jcolibri.exception.NoApplicableSimilarityFunctionException(this.getClass(), o1.getClass());
032                    if(!(o2 instanceof Enum))
033                            throw new jcolibri.exception.NoApplicableSimilarityFunctionException(this.getClass(), o2.getClass());
034                    
035                    Enum e1 = (Enum)o1;
036                    Enum e2 = (Enum)o2;
037                    
038                    double size = e1.getDeclaringClass().getEnumConstants().length;
039                    double distance = Math.abs(e1.ordinal() - e2.ordinal());
040                    double cyclicDistance = size - distance;
041                    
042                    if(distance <= cyclicDistance)
043                            return 1 - distance / size;
044                    else
045                            return 1 - cyclicDistance / size;
046            }
047            
048            /** Applicable to Enum */
049            public boolean isApplicable(Object o1, Object o2)
050            {
051                    if((o1==null)&&(o2==null))
052                            return true;
053                    else if(o1==null)
054                            return o2 instanceof Enum;
055                    else if(o2==null)
056                            return o1 instanceof Enum;
057                    else
058                            return (o1 instanceof Enum)&&(o2 instanceof Enum);
059            }
060    
061    }