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) 2006-2011 Pentaho 008// All Rights Reserved. 009*/ 010package mondrian.calc; 011 012import org.apache.commons.collections.map.CompositeMap; 013 014import java.io.PrintWriter; 015import java.util.IdentityHashMap; 016import java.util.Map; 017 018/** 019 * Visitor which serializes an expression to text. 020 * 021 * @author jhyde 022 * @since Dec 23, 2005 023 */ 024public class CalcWriter { 025 private static final int INDENT = 4; 026 private static String BIG_STRING = " "; 027 028 private final PrintWriter writer; 029 private final boolean profiling; 030 private int linePrefixLength; 031 private final Map<Calc, Map<String, Object>> parentArgMap = 032 new IdentityHashMap<Calc, Map<String, Object>>(); 033 034 public CalcWriter(PrintWriter writer, boolean profiling) { 035 this.writer = writer; 036 this.profiling = profiling; 037 } 038 039 public PrintWriter getWriter() { 040 return writer; 041 } 042 043 public void visitChild(int ordinal, Calc calc) { 044 indent(); 045 calc.accept(this); 046 outdent(); 047 } 048 049 public void visitCalc( 050 Calc calc, 051 String name, 052 Map<String, Object> arguments, 053 Calc[] childCalcs) 054 { 055 writer.print(getLinePrefix()); 056 writer.print(name); 057 final Map<String, Object> parentArgs = parentArgMap.get(calc); 058 if (parentArgs != null && !parentArgs.isEmpty()) { 059 //noinspection unchecked 060 arguments = new CompositeMap(arguments, parentArgs); 061 } 062 if (!arguments.isEmpty()) { 063 writer.print("("); 064 int k = 0; 065 for (Map.Entry<String, Object> entry : arguments.entrySet()) { 066 if (k++ > 0) { 067 writer.print(", "); 068 } 069 writer.print(entry.getKey()); 070 writer.print("="); 071 writer.print(entry.getValue()); 072 } 073 writer.print(")"); 074 } 075 writer.println(); 076 int k = 0; 077 for (Calc childCalc : childCalcs) { 078 visitChild(k++, childCalc); 079 } 080 } 081 082 /** 083 * Increases the indentation level. 084 */ 085 public void indent() { 086 linePrefixLength += INDENT; 087 } 088 089 /** 090 * Decreases the indentation level. 091 */ 092 public void outdent() { 093 linePrefixLength -= INDENT; 094 } 095 096 private String getLinePrefix() { 097 return spaces(linePrefixLength); 098 } 099 100 /** 101 * Returns a string of N spaces. 102 * @param n Number of spaces 103 * @return String of N spaces 104 */ 105 private static synchronized String spaces(int n) 106 { 107 while (n > BIG_STRING.length()) { 108 BIG_STRING = BIG_STRING + BIG_STRING; 109 } 110 return BIG_STRING.substring(0, n); 111 } 112 113 public void setParentArgs(Calc calc, Map<String, Object> argumentMap) { 114 parentArgMap.put(calc, argumentMap); 115 } 116 117 /** 118 * Whether to print out attributes relating to how a statement was actually 119 * executed. If false, client should only send attributes relating to the 120 * plan. 121 * 122 * @return Whether client should send attributes about profiling 123 */ 124 public boolean enableProfiling() { 125 return profiling; 126 } 127} 128 129// End CalcWriter.java