Source for org.jfree.report.util.PropertyLookupParser

   1: /**
   2:  * ========================================
   3:  * JFreeReport : a free Java report library
   4:  * ========================================
   5:  *
   6:  * Project Info:  http://reporting.pentaho.org/
   7:  *
   8:  * (C) Copyright 2000-2007, by Object Refinery Limited, Pentaho Corporation and Contributors.
   9:  *
  10:  * This library is free software; you can redistribute it and/or modify it under the terms
  11:  * of the GNU Lesser General Public License as published by the Free Software Foundation;
  12:  * either version 2.1 of the License, or (at your option) any later version.
  13:  *
  14:  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  15:  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  16:  * See the GNU Lesser General Public License for more details.
  17:  *
  18:  * You should have received a copy of the GNU Lesser General Public License along with this
  19:  * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  20:  * Boston, MA 02111-1307, USA.
  21:  *
  22:  * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
  23:  * in the United States and other countries.]
  24:  *
  25:  * ------------
  26:  * $Id: PropertyLookupParser.java 2725 2007-04-01 18:49:29Z taqua $
  27:  * ------------
  28:  * (C) Copyright 2000-2005, by Object Refinery Limited.
  29:  * (C) Copyright 2005-2007, by Pentaho Corporation.
  30:  */
  31: 
  32: package org.jfree.report.util;
  33: 
  34: import java.io.Serializable;
  35: 
  36: /**
  37:  * The property lookup parser is used to resolve embedded references to
  38:  * properties within strings.
  39:  * <p>
  40:  * The default format of the property specification is:
  41:  * <code>${property-name}</code> where 'property-name is the name of the
  42:  * property. If this construct is found within the text, it is replaced with
  43:  * the value returned from a call to "lookupVariable".
  44:  *
  45:  * @author Thomas Morgner
  46:  */
  47: public abstract class PropertyLookupParser implements Serializable
  48: {
  49:   /** A parse state indicator signaling that the parser is outside a property. */
  50:   private static final int EXPECT_DOLLAR = 0;
  51:   /** A parse state indicator signaling that an open brace is expected. */
  52:   private static final int EXPECT_OPEN_BRACE = 1;
  53: 
  54:   /**
  55:    * A parse state indicator signaling that a closed brace is expected. All chars
  56:    * received, which are not equal to the closed brace, count as property name.
  57:    */
  58:   private static final int EXPECT_CLOSE_BRACE = 2;
  59:   /** The initial marker char, a $ by default. */
  60:   private char markerChar;
  61:   /** The closing brace char. */
  62:   private char closingBraceChar;
  63:   /** The opening brace char. */
  64:   private char openingBraceChar;
  65:   /** The escape char. */
  66:   private char escapeChar;
  67: 
  68:   /**
  69:    * Initializes the parser to the default format of "${..}". The
  70:    * escape char will be a backslash.
  71:    */
  72:   protected PropertyLookupParser ()
  73:   {
  74:     markerChar = '$';
  75:     closingBraceChar = '}';
  76:     openingBraceChar = '{';
  77:     escapeChar = '\\';
  78:   }
  79: 
  80:   /**
  81:    * Returns the currently defined closed-brace char.
  82:    *
  83:    * @return the closed-brace char.
  84:    */
  85:   public char getClosingBraceChar ()
  86:   {
  87:     return closingBraceChar;
  88:   }
  89: 
  90:   /**
  91:    * Defines the closing brace character.
  92:    * @param closingBraceChar the closed-brace character.
  93:    */
  94:   public void setClosingBraceChar (final char closingBraceChar)
  95:   {
  96:     this.closingBraceChar = closingBraceChar;
  97:   }
  98: 
  99:   /**
 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: }