001 /* 002 // $Id: CallNode.java 247 2009-06-20 05:52:40Z jhyde $ 003 // This software is subject to the terms of the Eclipse Public License v1.0 004 // Agreement, available at the following URL: 005 // http://www.eclipse.org/legal/epl-v10.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 org.olap4j.mdx; 011 012 import java.util.List; 013 import java.util.Arrays; 014 015 import org.olap4j.type.Type; 016 017 /** 018 * A parse tree node representing a call to a function or operator. 019 * 020 * <p>Examples of calls include:<ul> 021 * <li><code>5 + 2</code>, a call to the infix arithmetic operator '+'</li> 022 * <li><code>[Measures].[Unit Sales] IS NULL</code>, a call applying the 023 * {@link Syntax#Postfix postfix} operator 024 * <code>IS NULL</code> to a member expression</li> 025 * <li><code>CrossJoin({[Gender].Children}, {[Store]})</code>, a call to the 026 * <code>CrossJoin</code> function</li> 027 * <li><code>[Gender].Children</code>, a call to the <code>Children</code> 028 * operator, which has {@link Syntax#Property property syntax}</li> 029 * <li><code>[Gender].Properties("FORMAT_STRING")</code>, a call to the 030 * <code>Properties</code> operator, which has 031 * {@link Syntax#Method method syntax}</li> 032 * </ul> 033 * 034 * @author jhyde 035 * @version $Id: CallNode.java 247 2009-06-20 05:52:40Z jhyde $ 036 * @since Jan 6, 2006 037 */ 038 public class CallNode implements ParseTreeNode { 039 040 private final String name; 041 private final Syntax syntax; 042 private final List<ParseTreeNode> argList; 043 private final ParseRegion region; 044 private Type type; 045 046 /** 047 * Creates a CallNode. 048 * 049 * <p>The <code>syntax</code> argument determines whether this is a prefix, 050 * infix or postfix operator, a function call, and so forth. 051 * 052 * <p>The list of arguments <code>args</code> must be specified, even if 053 * there are zero arguments, and each argument must be not null. 054 * 055 * <p>The type is initially null, but can be set using {@link #setType} 056 * after validation. 057 * 058 * @param region Region of source code 059 * @param name Name of operator or function 060 * @param syntax Syntax of call 061 * @param args List of zero or more arguments 062 */ 063 public CallNode( 064 ParseRegion region, 065 String name, 066 Syntax syntax, 067 List<ParseTreeNode> args) 068 { 069 this.region = region; 070 assert name != null; 071 assert syntax != null; 072 assert args != null; 073 this.name = name; 074 this.syntax = syntax; 075 this.argList = args; 076 077 // Check special syntaxes. 078 switch (syntax) { 079 case Braces: 080 assert name.equals("{}"); 081 break; 082 case Parentheses: 083 assert name.equals("()"); 084 break; 085 case Internal: 086 assert name.startsWith("$"); 087 break; 088 default: 089 assert !name.startsWith("$") 090 && !name.equals("{}") 091 && !name.equals("()"); 092 break; 093 } 094 } 095 096 /** 097 * Creates an CallNode using a variable number of arguments. 098 * 099 * <p>The <code>syntax</code> argument determines whether this is a prefix, 100 * infix or postfix operator, a function call, and so forth. 101 * 102 * <p>The list of arguments <code>args</code> must be specified, even if 103 * there are zero arguments, and each argument must be not null. 104 * 105 * @param region Region of source code 106 * @param name Name of operator or function 107 * @param syntax Syntax of call 108 * @param args List of zero or more arguments 109 */ 110 public CallNode( 111 ParseRegion region, 112 String name, 113 Syntax syntax, 114 ParseTreeNode... args) 115 { 116 this(region, name, syntax, Arrays.asList(args)); 117 } 118 119 public ParseRegion getRegion() { 120 return region; 121 } 122 123 /** 124 * Sets the type of this CallNode. 125 * 126 * <p>Typically, this method would be called by the validator when it has 127 * deduced the argument types, chosen between any overloaded functions 128 * or operators, and determined the result type of the function or 129 * operator. 130 * 131 * @param type Result type of this call 132 */ 133 public void setType(Type type) { 134 this.type = type; 135 } 136 137 public Type getType() { 138 return type; 139 } 140 141 public void unparse(ParseTreeWriter writer) { 142 syntax.unparse(name, argList, writer); 143 } 144 145 public <T> T accept(ParseTreeVisitor<T> visitor) { 146 final T o = visitor.visit(this); 147 // visit the call's arguments 148 for (ParseTreeNode arg : argList) { 149 arg.accept(visitor); 150 } 151 return o; 152 } 153 154 /** 155 * Returns the name of the function or operator. 156 * 157 * @return name of the function or operator 158 */ 159 public String getOperatorName() { 160 return name; 161 } 162 163 /** 164 * Returns the syntax of this call. 165 * 166 * @return the syntax of the call 167 */ 168 public Syntax getSyntax() { 169 return syntax; 170 } 171 172 /** 173 * Returns the list of arguments to this call. 174 * 175 * @return list of arguments 176 */ 177 public List<ParseTreeNode> getArgList() { 178 return argList; 179 } 180 181 public CallNode deepCopy() { 182 return new CallNode( 183 this.region, 184 this.name, 185 this.syntax, 186 MdxUtil.deepCopyList(argList)); 187 } 188 } 189 190 // End CallNode.java