001 /** 002 * ======================================== 003 * JFreeReport : a free Java report library 004 * ======================================== 005 * 006 * Project Info: http://reporting.pentaho.org/ 007 * 008 * (C) Copyright 2000-2007, by Object Refinery Limited, Pentaho Corporation and Contributors. 009 * 010 * This library is free software; you can redistribute it and/or modify it under the terms 011 * of the GNU Lesser General Public License as published by the Free Software Foundation; 012 * either version 2.1 of the License, or (at your option) any later version. 013 * 014 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 015 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 016 * See the GNU Lesser General Public License for more details. 017 * 018 * You should have received a copy of the GNU Lesser General Public License along with this 019 * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, 020 * Boston, MA 02111-1307, USA. 021 * 022 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 023 * in the United States and other countries.] 024 * 025 * ------------ 026 * $Id: PropertyLookupParser.java 2725 2007-04-01 18:49:29Z taqua $ 027 * ------------ 028 * (C) Copyright 2000-2005, by Object Refinery Limited. 029 * (C) Copyright 2005-2007, by Pentaho Corporation. 030 */ 031 032 package org.jfree.report.util; 033 034 import java.io.Serializable; 035 036 /** 037 * The property lookup parser is used to resolve embedded references to 038 * properties within strings. 039 * <p> 040 * The default format of the property specification is: 041 * <code>${property-name}</code> where 'property-name is the name of the 042 * property. If this construct is found within the text, it is replaced with 043 * the value returned from a call to "lookupVariable". 044 * 045 * @author Thomas Morgner 046 */ 047 public abstract class PropertyLookupParser implements Serializable 048 { 049 /** A parse state indicator signaling that the parser is outside a property. */ 050 private static final int EXPECT_DOLLAR = 0; 051 /** A parse state indicator signaling that an open brace is expected. */ 052 private static final int EXPECT_OPEN_BRACE = 1; 053 054 /** 055 * A parse state indicator signaling that a closed brace is expected. All chars 056 * received, which are not equal to the closed brace, count as property name. 057 */ 058 private static final int EXPECT_CLOSE_BRACE = 2; 059 /** The initial marker char, a $ by default. */ 060 private char markerChar; 061 /** The closing brace char. */ 062 private char closingBraceChar; 063 /** The opening brace char. */ 064 private char openingBraceChar; 065 /** The escape char. */ 066 private char escapeChar; 067 068 /** 069 * Initializes the parser to the default format of "${..}". The 070 * escape char will be a backslash. 071 */ 072 protected PropertyLookupParser () 073 { 074 markerChar = '$'; 075 closingBraceChar = '}'; 076 openingBraceChar = '{'; 077 escapeChar = '\\'; 078 } 079 080 /** 081 * Returns the currently defined closed-brace char. 082 * 083 * @return the closed-brace char. 084 */ 085 public char getClosingBraceChar () 086 { 087 return closingBraceChar; 088 } 089 090 /** 091 * Defines the closing brace character. 092 * @param closingBraceChar the closed-brace character. 093 */ 094 public void setClosingBraceChar (final char closingBraceChar) 095 { 096 this.closingBraceChar = closingBraceChar; 097 } 098 099 /** 100 * Returns the escape char. 101 * @return the escape char. 102 */ 103 public char getEscapeChar () 104 { 105 return escapeChar; 106 } 107 108 /** 109 * Defines the escape char. 110 * 111 * @param escapeChar the escape char 112 */ 113 public void setEscapeChar (final char escapeChar) 114 { 115 this.escapeChar = escapeChar; 116 } 117 118 /** 119 * Returns the currently defined opening-brace char. 120 * 121 * @return the opening-brace char. 122 */ 123 public char getOpeningBraceChar () 124 { 125 return openingBraceChar; 126 } 127 128 /** 129 * Defines the opening brace character. 130 * @param openingBraceChar the opening-brace character. 131 */ 132 public void setOpeningBraceChar (final char openingBraceChar) 133 { 134 this.openingBraceChar = openingBraceChar; 135 } 136 137 /** 138 * Returns initial property marker char. 139 * @return the initial property marker character. 140 */ 141 public char getMarkerChar () 142 { 143 return markerChar; 144 } 145 146 /** 147 * Defines initial property marker char. 148 * @param markerChar the initial property marker character. 149 */ 150 public void setMarkerChar (final char markerChar) 151 { 152 this.markerChar = markerChar; 153 } 154 155 /** 156 * Translates the given string and resolves the embedded property references. 157 * 158 * @param value the raw value, 159 * @return the fully translated string. 160 */ 161 public String translateAndLookup (final String value) 162 { 163 if (value == null) 164 { 165 return null; 166 } 167 168 final char[] chars = value.toCharArray(); 169 final StringBuffer result = new StringBuffer(chars.length); 170 boolean haveEscape = false; 171 int state = EXPECT_DOLLAR; 172 final StringBuffer propertyName = new StringBuffer(); 173 174 for (int i = 0; i < chars.length; i++) 175 { 176 final char c = chars[i]; 177 178 if (haveEscape) 179 { 180 haveEscape = false; 181 if (state == EXPECT_CLOSE_BRACE) 182 { 183 propertyName.append(c); 184 } 185 else 186 { 187 result.append(c); 188 } 189 continue; 190 } 191 192 if (state == EXPECT_DOLLAR && c == markerChar) 193 { 194 state = EXPECT_OPEN_BRACE; 195 continue; 196 } 197 if (state == EXPECT_OPEN_BRACE) 198 { 199 if (c == openingBraceChar) 200 { 201 state = EXPECT_CLOSE_BRACE; 202 continue; 203 } 204 else 205 { 206 result.append(markerChar); 207 state = 0; 208 } 209 } 210 if (state == EXPECT_CLOSE_BRACE && c == closingBraceChar) 211 { 212 final String s = lookupVariable(propertyName.toString()); 213 if (s == null) 214 { 215 result.append(markerChar); 216 result.append(openingBraceChar); 217 result.append(propertyName); 218 result.append(closingBraceChar); 219 } 220 else 221 { 222 result.append(s); 223 } 224 propertyName.delete(0, propertyName.length()); 225 state = 0; 226 continue; 227 } 228 229 if (c == escapeChar) 230 { 231 haveEscape = true; 232 continue; 233 } 234 235 if (state == EXPECT_CLOSE_BRACE) 236 { 237 propertyName.append(c); 238 } 239 else 240 { 241 result.append(c); 242 } 243 } 244 245 if (state >= EXPECT_OPEN_BRACE) 246 { 247 result.append(markerChar); 248 if (state >= EXPECT_CLOSE_BRACE) 249 { 250 result.append(openingBraceChar); 251 result.append(propertyName); 252 } 253 } 254 return result.toString(); 255 } 256 257 /** 258 * Looks up the property with the given name. 259 * 260 * @param property the name of the property to look up. 261 * @return the translated value. 262 */ 263 protected abstract String lookupVariable (String property); 264 }