001package com.hammurapi.extract;
002
003import java.util.concurrent.TimeUnit;
004
005
006public class Equal<T, V, C> extends ComparisonPredicate<T, V, C> {
007
008        private boolean identity;
009
010        public Equal(
011                        double initialCost, 
012                        TimeUnit costUnit,
013                        Extractor<T, V, C> leftExtractor,
014                        Extractor<T, V, C> rightExtractor, 
015                        boolean identity) {
016                super(initialCost, costUnit, leftExtractor, rightExtractor);
017                this.identity = identity;
018        }
019
020        @Override
021        @SuppressWarnings("unchecked")
022        public ComparisonResult compareTo(Extractor<T, Boolean, C> otherPredicate) {
023                
024                if (otherPredicate instanceof Equal) {
025                        if (equals(otherPredicate) || operandsAreReverseEqual((Equal) otherPredicate)) {
026                                return ComparisonResult.EQUAL_NM;
027                        }
028                        
029                        ComparisonResult cr = null;
030                        if (leftExtractor.equals(((ComparisonPredicate) otherPredicate).leftExtractor)) {
031                                cr = rightExtractor.compareTo(((ComparisonPredicate) otherPredicate).rightExtractor);
032                        } else if (leftExtractor.equals(((ComparisonPredicate) otherPredicate).rightExtractor)) {
033                                cr = rightExtractor.compareTo(((ComparisonPredicate) otherPredicate).leftExtractor);                            
034                        } else if (rightExtractor.equals(((ComparisonPredicate) otherPredicate).leftExtractor)) {
035                                cr = leftExtractor.compareTo(((ComparisonPredicate) otherPredicate).rightExtractor);                            
036                        } else if (rightExtractor.equals(((ComparisonPredicate) otherPredicate).rightExtractor)) {
037                                cr = leftExtractor.compareTo(((ComparisonPredicate) otherPredicate).leftExtractor);                             
038                        }
039                        
040                        if (cr!=null && cr.isOneToOneMapping()) {
041                                switch (cr.getType()) {
042                                case UNEQUAL:
043                                        return ComparisonResult.OPPOSITE_LESS_RESTRICTIVE_NM;
044                                case OPPOSITE:
045                                        return ComparisonResult.OPPOSITE_NM;
046                                }
047                        }
048                }               
049                
050                if (otherPredicate instanceof NotEqual) {
051                        NotEqual<T, V, C> op = (NotEqual<T, V, C>) otherPredicate;
052                        return operandsAreEqual(op) || operandsAreReverseEqual(op) ? ComparisonResult.OPPOSITE_NM : ComparisonResult.NOT_EQUAL_NM;
053                } 
054                
055                if (otherPredicate instanceof Not) {
056                        Not<T, C> op = (Not<T, C>) otherPredicate;
057                        ComparisonResult cr = compareTo(op.getPredicate());
058                        if (cr.isOneToOneMapping()) {
059                                switch (cr.getType()) {
060                                case EQUAL:
061                                        return ComparisonResult.OPPOSITE_NM;
062                                case OPPOSITE:
063                                        return ComparisonResult.EQUAL_NM;
064                                default:
065                                        return ComparisonResult.NOT_EQUAL_NM;
066                                }
067                        }
068                        /**
069                         * TODO Implement comparisons.
070                         * a * b ? c * d, * - can be <, <=, ==, !=, =>, >
071                         * 36 permutations. Each permutation - compare a/b, c/d 
072                         */
073                        
074                        // TODO Address mappings
075                }
076                return super.compareTo(otherPredicate);
077        }
078
079        @Override
080        protected boolean compare(int n1, int n2) {
081                return n1==n2;
082        }
083        
084        @Override
085        protected boolean compare(Object o1, Object o2) {
086                if (identity) {
087                        return o1==o2;
088                }
089                
090                if (o1==null) {
091                        return o2==null;
092                }
093
094                return o1.equals(o2);
095        }
096
097        @Override
098        protected boolean compare(long n1, long n2) {
099                return n1==n2;
100        }
101
102        @Override
103        protected boolean compare(float n1, float n2) {
104                return n1==n2;
105        }
106
107        @Override
108        protected boolean compare(double n1, double n2) {
109                return n1==n2;
110        }
111
112        @Override
113        protected Extractor<T, Boolean, C> newInstance(Extractor<T, V, C> leftExtractor, Extractor<T, V, C> rightExtractor) {
114                return new Equal<T,V,C>(initialCost, costUnit, leftExtractor, rightExtractor, identity);
115        }
116        
117        public boolean isIdentity() {
118                return identity;
119        }
120}