001/*
002// This software is subject to the terms of the Eclipse Public License v1.0
003// Agreement, available at the following URL:
004// http://www.eclipse.org/legal/epl-v10.html.
005// You must accept the terms of that agreement to use this software.
006//
007// Copyright (C) 2002-2005 Julian Hyde and others
008// Copyright (C) 2005-2011 Pentaho and others
009// All Rights Reserved.
010*/
011package mondrian.olap.fun;
012
013import mondrian.olap.*;
014
015import java.util.List;
016
017/**
018 * A <code>MultiResolver</code> considers several overloadings of the same
019 * function. If one of these overloadings matches the actual arguments, it
020 * calls the factory method {@link #createFunDef}.
021 *
022 * @author jhyde
023 * @since Feb 12, 2003
024 */
025public abstract class MultiResolver extends FunUtil implements Resolver {
026    private final String name;
027    private final String signature;
028    private final String description;
029    private final String[] signatures;
030    private final Syntax syntax;
031
032    /**
033     * Creates a <code>MultiResolver</code>.
034     *
035     * @param name Name of function or operator
036     * @param signature Signature of function or operator
037     * @param description Description of function or operator
038     * @param signatures Array of possible signatures, each of which is an
039     *     encoding of the syntactic type, return type, and parameter
040     *     types of this operator. The "Members" operator has a syntactic
041     *     type "pxd" which means "an operator with
042     *     {@link Syntax#Property property} syntax (p) which returns a set
043     *     (x) and takes a dimension (d) as its argument".
044     *     See {@link FunUtil#decodeSyntacticType(String)},
045     *     {@link FunUtil#decodeReturnCategory(String)},
046     *     {@link FunUtil#decodeParameterCategories(String)}.
047     */
048    protected MultiResolver(
049        String name,
050        String signature,
051        String description,
052        String[] signatures)
053    {
054        this.name = name;
055        this.signature = signature;
056        this.description = description;
057        this.signatures = signatures;
058        Util.assertTrue(signatures.length > 0);
059        this.syntax = decodeSyntacticType(signatures[0]);
060        for (int i = 1; i < signatures.length; i++) {
061            Util.assertTrue(decodeSyntacticType(signatures[i]) == syntax);
062        }
063    }
064
065    public String getName() {
066        return name;
067    }
068
069    public String getDescription() {
070        return description;
071    }
072
073    public String getSignature() {
074        return signature;
075    }
076
077    public Syntax getSyntax() {
078        return syntax;
079    }
080
081    public String[] getReservedWords() {
082        return emptyStringArray;
083    }
084
085    public String[] getSignatures() {
086        return signatures;
087    }
088
089    public FunDef getFunDef() {
090        return null;
091    }
092
093    public FunDef resolve(
094        Exp[] args,
095        Validator validator,
096        List<Conversion> conversions)
097    {
098outer:
099        for (String signature : signatures) {
100            int[] parameterTypes = decodeParameterCategories(signature);
101            if (parameterTypes.length != args.length) {
102                continue;
103            }
104            conversions.clear();
105            for (int i = 0; i < args.length; i++) {
106                if (!validator.canConvert(
107                        i, args[i], parameterTypes[i], conversions))
108                {
109                    continue outer;
110                }
111            }
112            int returnType = decodeReturnCategory(signature);
113            FunDef dummy = createDummyFunDef(this, returnType, args);
114            return createFunDef(args, dummy);
115        }
116        return null;
117    }
118
119    public boolean requiresExpression(int k) {
120        for (String signature : signatures) {
121            int[] parameterTypes = decodeParameterCategories(signature);
122            if ((k < parameterTypes.length)
123                && parameterTypes[k] == Category.Set)
124            {
125                return false;
126            }
127        }
128        return true;
129    }
130
131    protected abstract FunDef createFunDef(Exp[] args, FunDef dummyFunDef);
132}
133
134// End MultiResolver.java