GenericTokenParser.java

  1. /*
  2.  *    Copyright 2009-2023 the original author or authors.
  3.  *
  4.  *    Licensed under the Apache License, Version 2.0 (the "License");
  5.  *    you may not use this file except in compliance with the License.
  6.  *    You may obtain a copy of the License at
  7.  *
  8.  *       https://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  *    Unless required by applicable law or agreed to in writing, software
  11.  *    distributed under the License is distributed on an "AS IS" BASIS,
  12.  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  *    See the License for the specific language governing permissions and
  14.  *    limitations under the License.
  15.  */
  16. package org.apache.ibatis.parsing;

  17. /**
  18.  * @author Clinton Begin
  19.  */
  20. public class GenericTokenParser {

  21.   private final String openToken;
  22.   private final String closeToken;
  23.   private final TokenHandler handler;

  24.   public GenericTokenParser(String openToken, String closeToken, TokenHandler handler) {
  25.     this.openToken = openToken;
  26.     this.closeToken = closeToken;
  27.     this.handler = handler;
  28.   }

  29.   public String parse(String text) {
  30.     if (text == null || text.isEmpty()) {
  31.       return "";
  32.     }
  33.     // search open token
  34.     int start = text.indexOf(openToken);
  35.     if (start == -1) {
  36.       return text;
  37.     }
  38.     char[] src = text.toCharArray();
  39.     int offset = 0;
  40.     final StringBuilder builder = new StringBuilder();
  41.     StringBuilder expression = null;
  42.     do {
  43.       if (start > 0 && src[start - 1] == '\\') {
  44.         // this open token is escaped. remove the backslash and continue.
  45.         builder.append(src, offset, start - offset - 1).append(openToken);
  46.         offset = start + openToken.length();
  47.       } else {
  48.         // found open token. let's search close token.
  49.         if (expression == null) {
  50.           expression = new StringBuilder();
  51.         } else {
  52.           expression.setLength(0);
  53.         }
  54.         builder.append(src, offset, start - offset);
  55.         offset = start + openToken.length();
  56.         int end = text.indexOf(closeToken, offset);
  57.         while (end > -1) {
  58.           if ((end <= offset) || (src[end - 1] != '\\')) {
  59.             expression.append(src, offset, end - offset);
  60.             break;
  61.           }
  62.           // this close token is escaped. remove the backslash and continue.
  63.           expression.append(src, offset, end - offset - 1).append(closeToken);
  64.           offset = end + closeToken.length();
  65.           end = text.indexOf(closeToken, offset);
  66.         }
  67.         if (end == -1) {
  68.           // close token was not found.
  69.           builder.append(src, start, src.length - start);
  70.           offset = src.length;
  71.         } else {
  72.           builder.append(handler.handleToken(expression.toString()));
  73.           offset = end + closeToken.length();
  74.         }
  75.       }
  76.       start = text.indexOf(openToken, offset);
  77.     } while (start > -1);
  78.     if (offset < src.length) {
  79.       builder.append(src, offset, src.length - offset);
  80.     }
  81.     return builder.toString();
  82.   }
  83. }