View Javadoc
1   /*
2    *    Copyright 2012-2022 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.mybatis.scripting.velocity;
17  
18  import java.io.IOException;
19  import java.io.StringWriter;
20  import java.io.Writer;
21  import java.util.Locale;
22  
23  import org.apache.velocity.context.InternalContextAdapter;
24  import org.apache.velocity.runtime.directive.Directive;
25  import org.apache.velocity.runtime.parser.node.ASTBlock;
26  import org.apache.velocity.runtime.parser.node.Node;
27  
28  public class TrimDirective extends Directive {
29  
30    @Override
31    public String getName() {
32      return "trim";
33    }
34  
35    @Override
36    public final int getType() {
37      return BLOCK;
38    }
39  
40    @Override
41    public final boolean render(InternalContextAdapter ica, Writer writer, Node node) throws IOException {
42      Params p = getParams(ica, node);
43      if (p == null) {
44        return false;
45      }
46      return render(p, writer);
47    }
48  
49    public boolean render(final Params params, final Writer writer) throws IOException {
50      int leftIndex = 0;
51      int rightIndex = params.maxBody;
52      if (rightIndex == 0) {
53        return false;
54      }
55      if (!params.prefixOverrides.isEmpty()) {
56        final String LEFT = params.body
57            .substring(0, params.maxPrefixLength < params.maxBody ? params.maxPrefixLength : params.maxBody)
58            .toUpperCase(Locale.ENGLISH);
59        FastLinkedList<String>.Node n = params.prefixOverrides.start();
60        while (n != null) {
61          if (LEFT.startsWith(n.data)) {
62            leftIndex = n.data.length();
63            break;
64          }
65          n = n.next;
66        }
67      }
68      if (!params.suffixOverrides.isEmpty()) {
69        final String RIGHT = params.body
70            .substring(rightIndex > params.maxSuffixLength ? rightIndex - params.maxSuffixLength : 0)
71            .toUpperCase(Locale.ENGLISH);
72        FastLinkedList<String>.Node n = params.suffixOverrides.start();
73        while (n != null) {
74          if (RIGHT.endsWith(n.data)) {
75            rightIndex = rightIndex - n.data.length();
76            break;
77          }
78          n = n.next;
79        }
80      }
81      if (rightIndex > leftIndex) {
82        String content = params.body.substring(leftIndex, rightIndex).trim();
83        if (!"".equals(content)) {
84          writer.append(params.prefix).append(' ');
85          writer.append(params.body, leftIndex, rightIndex).append(' ');
86          writer.append(params.suffix);
87        }
88      }
89      return true;
90    }
91  
92    protected static final class Params {
93  
94      String prefix = "";
95  
96      String suffix = "";
97  
98      FastLinkedList<String> prefixOverrides = new FastLinkedList<>();
99  
100     FastLinkedList<String> suffixOverrides = new FastLinkedList<>();
101 
102     String body = "";
103 
104     int maxPrefixLength = 0;
105 
106     int maxSuffixLength = 0;
107 
108     int maxBody = 0;
109 
110     public String getBody() {
111       return this.body;
112     }
113 
114     public void setBody(String value) {
115       if (value == null) {
116         this.body = "";
117       } else {
118         this.body = value.trim();
119       }
120       this.maxBody = this.body.length();
121     }
122 
123     public String getPrefix() {
124       return this.prefix;
125     }
126 
127     public void setPrefix(String value) {
128       this.prefix = value;
129     }
130 
131     public FastLinkedList<String> getPrefixOverrides() {
132       return this.prefixOverrides;
133     }
134 
135     public void setPrefixOverrides(String list) {
136       this.maxPrefixLength = fromStringList(list, '|', this.prefixOverrides);
137     }
138 
139     public FastLinkedList<String> getSuffixOverrides() {
140       return this.suffixOverrides;
141     }
142 
143     public void setSuffixOverrides(String list) {
144       this.maxSuffixLength = fromStringList(list, '|', this.suffixOverrides);
145     }
146 
147     public String getSuffix() {
148       return this.suffix;
149     }
150 
151     public void setSuffix(String value) {
152       this.suffix = value;
153     }
154 
155   }
156 
157   protected Params getParams(final InternalContextAdapter context, final Node node) throws IOException {
158     final Params params = new Params();
159     final int nodes = node.jjtGetNumChildren();
160     for (int i = 0; i < nodes; i++) {
161       Node child = node.jjtGetChild(i);
162       if (child != null) {
163         if (!(child instanceof ASTBlock)) {
164           if (i == 0) {
165             params.setPrefix(String.valueOf(child.value(context)));
166           } else if (i == 1) {
167             params.setPrefixOverrides(String.valueOf(child.value(context)).toUpperCase(Locale.ENGLISH));
168           } else if (i == 2) {
169             params.setSuffix(String.valueOf(child.value(context)));
170           } else if (i == 3) {
171             params.setSuffixOverrides(String.valueOf(child.value(context)).toUpperCase(Locale.ENGLISH));
172           } else {
173             break;
174           }
175         } else {
176           StringWriter blockContent = new StringWriter();
177           child.render(context, blockContent);
178           params.setBody(blockContent.toString().trim());
179           break;
180         }
181       }
182     }
183     return params;
184   }
185 
186   static int fromStringList(final String list, final char sep, final FastLinkedList<String> fll) {
187     int max = 0;
188     if (list != null) {
189       final int n = list.length();
190       int i = 0;
191       while (i < n) {
192         int r = list.indexOf(sep, i);
193         if (i < r) {
194           fll.add(list.substring(i, r));
195           int len = r - i;
196           if (len > max) {
197             max = len;
198           }
199           i = r + 1;
200         } else {
201           break;
202         }
203       }
204       if (i < n) {
205         fll.add(list.substring(i));
206         int len = n - i;
207         if (len > max) {
208           max = len;
209         }
210       }
211     }
212     return max;
213   }
214 
215 }