001    /*
002    // $Id: //open/mondrian/src/main/mondrian/olap/fun/DistinctFunDef.java#3 $
003    // This software is subject to the terms of the Common Public License
004    // Agreement, available at the following URL:
005    // http://www.opensource.org/licenses/cpl.html.
006    // Copyright (C) 2007-2008 Julian Hyde
007    // All Rights Reserved.
008    // You must accept the terms of that agreement to use this software.
009    */
010    package mondrian.olap.fun;
011    
012    import java.util.ArrayList;
013    import java.util.Arrays;
014    import java.util.HashSet;
015    import java.util.List;
016    import java.util.Set;
017    
018    import mondrian.calc.*;
019    import mondrian.calc.impl.AbstractListCalc;
020    import mondrian.mdx.ResolvedFunCall;
021    import mondrian.olap.Evaluator;
022    import mondrian.olap.Member;
023    
024    /**
025     * Definition of the <code>Distinct</code> MDX function.
026     *
027     * <p>Syntax:
028     * <blockquote><code>Distinct(&lt;Set&gt;)</code></blockquote>
029     *
030     * @author jhyde
031     * @version $Id: //open/mondrian/src/main/mondrian/olap/fun/DistinctFunDef.java#3 $
032     * @since Jun 10, 2007
033    */
034    class DistinctFunDef extends FunDefBase {
035        public static final DistinctFunDef instance = new DistinctFunDef();
036    
037        private DistinctFunDef() {
038            super("Distinct",
039                "Eliminates duplicate tuples from a set.",
040                "fxx");
041        }
042    
043        public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
044            final ListCalc listCalc =
045                    compiler.compileList(call.getArg(0));
046            return new CalcImpl(call, listCalc);
047        }
048    
049        static class CalcImpl extends AbstractListCalc {
050            private final ListCalc listCalc;
051    
052            public CalcImpl(ResolvedFunCall call, ListCalc listCalc) {
053                super(call, new Calc[]{listCalc});
054                this.listCalc = listCalc;
055            }
056    
057            public List evaluateList(Evaluator evaluator) {
058                List list = listCalc.evaluateList(evaluator);
059                return distinct(list);
060            }
061    
062            static List<Object> distinct(List list) {
063                Set<MemberHelper> set = new HashSet<MemberHelper>(list.size());
064                List<Object> result = new ArrayList<Object>();
065    
066                for (Object element : list) {
067                    MemberHelper lookupObj = new MemberHelper(element);
068    
069                    if (set.add(lookupObj)) {
070                        result.add(element);
071                    }
072                }
073                return result;
074            }
075    
076            public List<Member> evaluateMemberList(Evaluator evaluator) {
077                List<Member> list =
078                    ((MemberListCalc) listCalc).evaluateMemberList(evaluator);
079                Set<Member> set = new HashSet<Member>(list.size());
080                List<Member> result = new ArrayList<Member>();
081                for (Member element : list) {
082                    if (set.add(element)) {
083                        result.add(element);
084                    }
085                }
086                return result;
087            }
088    
089            public List<Member[]> evaluateTupleList(Evaluator evaluator) {
090                List<Member[]> list =
091                    ((TupleListCalc) listCalc).evaluateTupleList(evaluator);
092                Set<List<Member>> set = new HashSet<List<Member>>(list.size());
093                List<Member[]> result = new ArrayList<Member[]>();
094                for (Member[] element : list) {
095                    if (set.add(Arrays.asList(element))) {
096                        result.add(element);
097                    }
098                }
099                return result;
100            }
101        }
102    }
103    
104    // End DistinctFunDef.java