15
15
*/
16
16
package org .apache .ibatis .builder .xml ;
17
17
18
+ import java .util .HashMap ;
19
+ import java .util .Map ;
20
+ import java .util .Properties ;
21
+
18
22
import org .apache .ibatis .builder .BuilderException ;
19
23
import org .apache .ibatis .builder .IncompleteElementException ;
20
24
import org .apache .ibatis .builder .MapperBuilderAssistant ;
24
28
import org .w3c .dom .Node ;
25
29
import org .w3c .dom .NodeList ;
26
30
27
- import java .util .Properties ;
28
-
29
31
/**
30
32
* @author Frank D. Martinez [mnesarco]
31
33
*/
@@ -45,34 +47,19 @@ public void applyIncludes(Node source) {
45
47
if (configurationVariables != null ) {
46
48
variablesContext .putAll (configurationVariables );
47
49
}
48
- applyIncludes (source , variablesContext );
50
+ applyIncludes (source , variablesContext , false );
49
51
}
50
52
51
53
/**
52
54
* Recursively apply includes through all SQL fragments.
53
55
* @param source Include node in DOM tree
54
56
* @param variablesContext Current context for static variables with values
55
57
*/
56
- private void applyIncludes (Node source , final Properties variablesContext ) {
58
+ private void applyIncludes (Node source , final Properties variablesContext , boolean included ) {
57
59
if (source .getNodeName ().equals ("include" )) {
58
- // new full context for included SQL - contains inherited context and new variables from current include node
59
- Properties fullContext ;
60
-
61
- String refid = getStringAttribute (source , "refid" );
62
- // replace variables in include refid value
63
- refid = PropertyParser .parse (refid , variablesContext );
64
- Node toInclude = findSqlFragment (refid );
65
- Properties newVariablesContext = getVariablesContext (source , variablesContext );
66
- if (!newVariablesContext .isEmpty ()) {
67
- // merge contexts
68
- fullContext = new Properties ();
69
- fullContext .putAll (variablesContext );
70
- fullContext .putAll (newVariablesContext );
71
- } else {
72
- // no new context - use inherited fully
73
- fullContext = variablesContext ;
74
- }
75
- applyIncludes (toInclude , fullContext );
60
+ Node toInclude = findSqlFragment (getStringAttribute (source , "refid" ), variablesContext );
61
+ Properties toIncludeContext = getVariablesContext (source , variablesContext );
62
+ applyIncludes (toInclude , toIncludeContext , true );
76
63
if (toInclude .getOwnerDocument () != source .getOwnerDocument ()) {
77
64
toInclude = source .getOwnerDocument ().importNode (toInclude , true );
78
65
}
@@ -83,19 +70,18 @@ private void applyIncludes(Node source, final Properties variablesContext) {
83
70
toInclude .getParentNode ().removeChild (toInclude );
84
71
} else if (source .getNodeType () == Node .ELEMENT_NODE ) {
85
72
NodeList children = source .getChildNodes ();
86
- for (int i = 0 ; i < children .getLength (); i ++) {
87
- applyIncludes (children .item (i ), variablesContext );
73
+ for (int i = 0 ; i < children .getLength (); i ++) {
74
+ applyIncludes (children .item (i ), variablesContext , included );
88
75
}
89
- } else if (source .getNodeType () == Node .ATTRIBUTE_NODE && !variablesContext .isEmpty ()) {
90
- // replace variables in all attribute values
91
- source .setNodeValue (PropertyParser .parse (source .getNodeValue (), variablesContext ));
92
- } else if (source .getNodeType () == Node .TEXT_NODE && !variablesContext .isEmpty ()) {
76
+ } else if (included && source .getNodeType () == Node .TEXT_NODE
77
+ && !variablesContext .isEmpty ()) {
93
78
// replace variables ins all text nodes
94
79
source .setNodeValue (PropertyParser .parse (source .getNodeValue (), variablesContext ));
95
80
}
96
81
}
97
82
98
- private Node findSqlFragment (String refid ) {
83
+ private Node findSqlFragment (String refid , Properties variables ) {
84
+ refid = PropertyParser .parse (refid , variables );
99
85
refid = builderAssistant .applyCurrentNamespace (refid , true );
100
86
try {
101
87
XNode nodeToInclude = configuration .getSqlFragments ().get (refid );
@@ -116,23 +102,29 @@ private String getStringAttribute(Node node, String name) {
116
102
* @return variables context from include instance (no inherited values)
117
103
*/
118
104
private Properties getVariablesContext (Node node , Properties inheritedVariablesContext ) {
119
- Properties variablesContext = new Properties () ;
105
+ Map < String , String > declaredProperties = null ;
120
106
NodeList children = node .getChildNodes ();
121
107
for (int i = 0 ; i < children .getLength (); i ++) {
122
108
Node n = children .item (i );
123
109
if (n .getNodeType () == Node .ELEMENT_NODE ) {
124
110
String name = getStringAttribute (n , "name" );
125
- String value = getStringAttribute (n , "value" );
126
111
// Replace variables inside
127
- value = PropertyParser .parse (value , inheritedVariablesContext );
128
- // Push new value
129
- Object originalValue = variablesContext .put (name , value );
130
- if (originalValue != null ) {
112
+ String value = PropertyParser .parse (getStringAttribute (n , "value" ), inheritedVariablesContext );
113
+ if (declaredProperties == null ) {
114
+ declaredProperties = new HashMap <String , String >();
115
+ }
116
+ if (declaredProperties .put (name , value ) != null ) {
131
117
throw new BuilderException ("Variable " + name + " defined twice in the same include definition" );
132
118
}
133
119
}
134
120
}
135
- return variablesContext ;
121
+ if (declaredProperties == null ) {
122
+ return inheritedVariablesContext ;
123
+ } else {
124
+ Properties newProperties = new Properties ();
125
+ newProperties .putAll (inheritedVariablesContext );
126
+ newProperties .putAll (declaredProperties );
127
+ return newProperties ;
128
+ }
136
129
}
137
-
138
130
}
0 commit comments