Skip to content

Commit 0f057c2

Browse files
committed
Allow to specify a default value on placeholder
fix gh-852
1 parent 824dde0 commit 0f057c2

File tree

2 files changed

+136
-5
lines changed

2 files changed

+136
-5
lines changed

src/main/java/org/apache/ibatis/parsing/PropertyParser.java

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2009-2015 the original author or authors.
2+
* Copyright 2009-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,9 +19,33 @@
1919

2020
/**
2121
* @author Clinton Begin
22+
* @author Kazuki Shimizu
2223
*/
2324
public class PropertyParser {
2425

26+
private static final String KEY_PREFIX = "org.apache.ibatis.parsing.PropertyParser.";
27+
/**
28+
* The special property key that indicate whether enable a default value on placeholder.
29+
* <p>
30+
* The default value is {@code false} (indicate disable a default value on placeholder)
31+
* If you specify the {@code true}, you can specify key and default value on placeholder (e.g. {@code ${db.username:postgres}}).
32+
* </p>
33+
* @since 3.4.2
34+
*/
35+
public static final String KEY_ENABLE_DEFAULT_VALUE = KEY_PREFIX + "enable-default-value";
36+
37+
/**
38+
* The special property key that specify a separator for key and default value on placeholder.
39+
* <p>
40+
* The default separator is {@code ":"}.
41+
* </p>
42+
* @since 3.4.2
43+
*/
44+
public static final String KEY_DEFAULT_VALUE_SEPARATOR = KEY_PREFIX + "default-value-separator";
45+
46+
private static final String ENABLE_DEFAULT_VALUE = "false";
47+
private static final String DEFAULT_VALUE_SEPARATOR = ":";
48+
2549
private PropertyParser() {
2650
// Prevent Instantiation
2751
}
@@ -33,18 +57,41 @@ public static String parse(String string, Properties variables) {
3357
}
3458

3559
private static class VariableTokenHandler implements TokenHandler {
36-
private Properties variables;
60+
private final Properties variables;
61+
private final boolean enableDefaultValue;
62+
private final String defaultValueSeparator;
3763

38-
public VariableTokenHandler(Properties variables) {
64+
private VariableTokenHandler(Properties variables) {
3965
this.variables = variables;
66+
this.enableDefaultValue = Boolean.parseBoolean(getPropertyValue(KEY_ENABLE_DEFAULT_VALUE, ENABLE_DEFAULT_VALUE));
67+
this.defaultValueSeparator = getPropertyValue(KEY_DEFAULT_VALUE_SEPARATOR, DEFAULT_VALUE_SEPARATOR);
68+
}
69+
70+
private String getPropertyValue(String key, String defaultValue) {
71+
return (variables == null) ? defaultValue : variables.getProperty(key, defaultValue);
4072
}
4173

4274
@Override
4375
public String handleToken(String content) {
44-
if (variables != null && variables.containsKey(content)) {
45-
return variables.getProperty(content);
76+
if (variables != null) {
77+
String key = content;
78+
if (enableDefaultValue) {
79+
final int separatorIndex = content.indexOf(defaultValueSeparator);
80+
String defaultValue = null;
81+
if (separatorIndex >= 0) {
82+
key = content.substring(0, separatorIndex);
83+
defaultValue = content.substring(separatorIndex + defaultValueSeparator.length());
84+
}
85+
if (defaultValue != null) {
86+
return variables.getProperty(key, defaultValue);
87+
}
88+
}
89+
if (variables.containsKey(key)) {
90+
return variables.getProperty(key);
91+
}
4692
}
4793
return "${" + content + "}";
4894
}
4995
}
96+
5097
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/**
2+
* Copyright 2009-2016 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+
* http://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+
import org.hamcrest.core.Is;
19+
import org.junit.Assert;
20+
import org.junit.Test;
21+
22+
import java.util.Properties;
23+
24+
public class PropertyParserTest {
25+
26+
@Test
27+
public void replaceToVariableValue() {
28+
Properties props = new Properties();
29+
props.setProperty(PropertyParser.KEY_ENABLE_DEFAULT_VALUE, "true");
30+
props.setProperty("key", "value");
31+
props.setProperty("tableName", "members");
32+
props.setProperty("orderColumn", "member_id");
33+
props.setProperty("a:b", "c");
34+
Assert.assertThat(PropertyParser.parse("${key}", props), Is.is("value"));
35+
Assert.assertThat(PropertyParser.parse("${key:aaaa}", props), Is.is("value"));
36+
Assert.assertThat(PropertyParser.parse("SELECT * FROM ${tableName:users} ORDER BY ${orderColumn:id}", props), Is.is("SELECT * FROM members ORDER BY member_id"));
37+
38+
props.setProperty(PropertyParser.KEY_ENABLE_DEFAULT_VALUE, "false");
39+
Assert.assertThat(PropertyParser.parse("${a:b}", props), Is.is("c"));
40+
41+
props.remove(PropertyParser.KEY_ENABLE_DEFAULT_VALUE);
42+
Assert.assertThat(PropertyParser.parse("${a:b}", props), Is.is("c"));
43+
44+
}
45+
46+
@Test
47+
public void notReplace() {
48+
Properties props = new Properties();
49+
props.setProperty(PropertyParser.KEY_ENABLE_DEFAULT_VALUE, "true");
50+
Assert.assertThat(PropertyParser.parse("${key}", props), Is.is("${key}"));
51+
Assert.assertThat(PropertyParser.parse("${key}", null), Is.is("${key}"));
52+
53+
props.setProperty(PropertyParser.KEY_ENABLE_DEFAULT_VALUE, "false");
54+
Assert.assertThat(PropertyParser.parse("${a:b}", props), Is.is("${a:b}"));
55+
56+
props.remove(PropertyParser.KEY_ENABLE_DEFAULT_VALUE);
57+
Assert.assertThat(PropertyParser.parse("${a:b}", props), Is.is("${a:b}"));
58+
59+
}
60+
61+
@Test
62+
public void applyDefaultValue() {
63+
Properties props = new Properties();
64+
props.setProperty(PropertyParser.KEY_ENABLE_DEFAULT_VALUE, "true");
65+
Assert.assertThat(PropertyParser.parse("${key:default}", props), Is.is("default"));
66+
Assert.assertThat(PropertyParser.parse("SELECT * FROM ${tableName:users} ORDER BY ${orderColumn:id}", props), Is.is("SELECT * FROM users ORDER BY id"));
67+
Assert.assertThat(PropertyParser.parse("${key:}", props), Is.is(""));
68+
Assert.assertThat(PropertyParser.parse("${key: }", props), Is.is(" "));
69+
Assert.assertThat(PropertyParser.parse("${key::}", props), Is.is(":"));
70+
}
71+
72+
@Test
73+
public void applyCustomSeparator() {
74+
Properties props = new Properties();
75+
props.setProperty(PropertyParser.KEY_ENABLE_DEFAULT_VALUE, "true");
76+
props.setProperty(PropertyParser.KEY_DEFAULT_VALUE_SEPARATOR, "?:");
77+
Assert.assertThat(PropertyParser.parse("${key?:default}", props), Is.is("default"));
78+
Assert.assertThat(PropertyParser.parse("SELECT * FROM ${schema?:prod}.${tableName == null ? 'users' : tableName} ORDER BY ${orderColumn}", props), Is.is("SELECT * FROM prod.${tableName == null ? 'users' : tableName} ORDER BY ${orderColumn}"));
79+
Assert.assertThat(PropertyParser.parse("${key?:}", props), Is.is(""));
80+
Assert.assertThat(PropertyParser.parse("${key?: }", props), Is.is(" "));
81+
Assert.assertThat(PropertyParser.parse("${key?::}", props), Is.is(":"));
82+
}
83+
84+
}

0 commit comments

Comments
 (0)