001 /* 002 // $Id: //open/mondrian/src/main/mondrian/mdx/ParameterExpr.java#6 $ 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) 2006-2007 Julian Hyde 007 // All Rights Reserved. 008 // You must accept the terms of that agreement to use this software. 009 */ 010 package mondrian.mdx; 011 012 import mondrian.olap.*; 013 import mondrian.olap.type.Type; 014 import mondrian.olap.type.TypeUtil; 015 import mondrian.calc.Calc; 016 import mondrian.calc.ExpCompiler; 017 import mondrian.calc.ParameterCompilable; 018 019 import java.io.PrintWriter; 020 021 /** 022 * MDX expression which is a usage of a {@link mondrian.olap.Parameter}. 023 * 024 * @author jhyde 025 * @version $Id: //open/mondrian/src/main/mondrian/mdx/ParameterExpr.java#6 $ 026 */ 027 public class ParameterExpr extends ExpBase { 028 029 private Parameter parameter; 030 031 public ParameterExpr(Parameter parameter) 032 { 033 this.parameter = parameter; 034 } 035 036 public Type getType() { 037 return parameter.getType(); 038 } 039 040 public int getCategory() { 041 return TypeUtil.typeToCategory(parameter.getType()); 042 } 043 044 public Exp accept(Validator validator) { 045 // There must be some Parameter with this name registered with the 046 // Query. After clone(), there will be many copies of the same 047 // parameter, and we rely on this method to bring them down to one. 048 // So if this object is not the registered vesion, that's fine, go with 049 // the other one. The registered one will be resolved after everything 050 // else in the query has been resolved. 051 String parameterName = parameter.getName(); 052 final SchemaReader schemaReader = 053 validator.getQuery().getSchemaReader(false); 054 Parameter p = schemaReader.getParameter(parameterName); 055 if (p == null) { 056 this.parameter = 057 validator.createOrLookupParam( 058 true, 059 parameter.getName(), 060 parameter.getType(), 061 parameter.getDefaultExp(), 062 parameter.getDescription()); 063 } else { 064 this.parameter = p; 065 } 066 return this; 067 } 068 069 public Calc accept(ExpCompiler compiler) { 070 return ((ParameterCompilable) parameter).compile(compiler); 071 } 072 073 public Object accept(MdxVisitor visitor) { 074 return visitor.visit(this); 075 } 076 077 public ParameterExpr clone() { 078 return new ParameterExpr(parameter); 079 } 080 081 /** 082 * Unparses the definition of this Parameter. 083 * 084 * <p>The first usage of a parameter in a query becomes a call to the 085 * <code>Parameter(paramName, description, defaultValue)</code> 086 * function, and subsequent usages become calls to 087 * <code>ParamRef(paramName)</code> 088 * 089 * @param pw PrintWriter 090 */ 091 public void unparse(PrintWriter pw) { 092 // Is this the first time we've seen a statement parameter? If so, 093 // we will generate a call to the Parameter() function, to define 094 // the parameter. 095 final boolean def; 096 if (pw instanceof QueryPrintWriter && 097 parameter.getScope() == Parameter.Scope.Statement) { 098 def = ((QueryPrintWriter) pw).parameters.add(parameter); 099 } else { 100 def = false; 101 } 102 final String name = parameter.getName(); 103 final Type type = parameter.getType(); 104 final int category = TypeUtil.typeToCategory(type); 105 if (def) { 106 pw.print("Parameter(" + Util.quoteForMdx(name) + ", "); 107 switch (category) { 108 case Category.String: 109 case Category.Numeric: 110 pw.print(Category.instance.getName(category).toUpperCase()); 111 break; 112 case Category.Member: 113 String memberName = 114 type.getLevel() != null ? 115 type.getLevel().getUniqueName() : 116 type.getHierarchy() != null ? 117 type.getHierarchy().getUniqueName() : 118 type.getDimension().getUniqueName(); 119 pw.print(memberName); 120 break; 121 default: 122 throw Category.instance.badValue(category); 123 } 124 pw.print(", "); 125 final Object value = parameter.getValue(); 126 if (value == null) { 127 parameter.getDefaultExp().unparse(pw); 128 } else if (value instanceof String) { 129 String s = (String) value; 130 pw.print(Util.quoteForMdx(s)); 131 } else { 132 pw.print(value); 133 } 134 final String description = parameter.getDescription(); 135 if (description != null) { 136 pw.print(", " + Util.quoteForMdx(description)); 137 } 138 pw.print(")"); 139 } else { 140 pw.print("ParamRef(" + Util.quoteForMdx(name) + ")"); 141 } 142 } 143 144 // For the purposes of type inference and expression substitution, a 145 // parameter is atomic; therefore, we ignore the child member, if any. 146 public Object[] getChildren() { 147 return null; 148 } 149 150 /** 151 * Returns whether this parameter is equal to another, based upon name, 152 * type and value 153 */ 154 public boolean equals(Object other) { 155 if (!(other instanceof ParameterExpr)) { 156 return false; 157 } 158 ParameterExpr that = (ParameterExpr) other; 159 return this.parameter == that.parameter; 160 } 161 162 public int hashCode() { 163 return parameter.hashCode(); 164 } 165 166 /** 167 * Returns whether the parameter can be modified. 168 * 169 * @return whether parameter can be modified 170 */ 171 public boolean isModifiable() { 172 return true; 173 } 174 175 /** 176 * Returns the parameter used by this expression. 177 * 178 * @return parameter used by this expression 179 */ 180 public Parameter getParameter() { 181 return parameter; 182 } 183 } 184 185 // End ParameterExpr.java