1 /*
2 * Copyright 2018-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.thymeleaf;
17
18 import java.util.ArrayList;
19 import java.util.HashMap;
20 import java.util.List;
21 import java.util.Map;
22
23 import org.thymeleaf.context.IContext;
24 import org.thymeleaf.engine.IterationStatusVar;
25
26 /**
27 * The context object for integrating with MyBatis and Thymeleaf template engine.
28 *
29 * @author Kazuki Shimizu
30 *
31 * @version 1.0.0
32 */
33 public class MyBatisBindingContext {
34
35 static final String CONTEXT_VARIABLE_NAME = "_" + MyBatisBindingContext.class.getName();
36
37 private final Map<String, Object> customBindVariables = new HashMap<>();
38 private final IterationStatusManager iterationStatusManager = new IterationStatusManager();
39 private final boolean fallbackParameterObject;
40
41 /**
42 * Load instance from {@link IContext} provided by Thymeleaf.
43 *
44 * @param context
45 * a context of thymeleaf template processing
46 *
47 * @return instance of this class
48 */
49 public static MyBatisBindingContext load(IContext context) {
50 return (MyBatisBindingContext) context.getVariable(CONTEXT_VARIABLE_NAME);
51 }
52
53 /**
54 * Constructor.
55 *
56 * @param fallbackParameterObject
57 * whether use fallback parameter object when parameter is value object
58 */
59 MyBatisBindingContext(boolean fallbackParameterObject) {
60 this.fallbackParameterObject = fallbackParameterObject;
61 }
62
63 /**
64 * Get custom bind variables.
65 *
66 * @return custom bind variables
67 */
68 Map<String, Object> getCustomBindVariables() {
69 return customBindVariables;
70 }
71
72 /**
73 * Set a value into custom bind variable.
74 *
75 * @param name
76 * variable name
77 * @param value
78 * variable value
79 */
80 public void setCustomBindVariable(String name, Object value) {
81 customBindVariables.put(name, value);
82 }
83
84 /**
85 * Return whether contains specified variable into custom bind variables.
86 *
87 * @param name
88 * variable name
89 *
90 * @return If specified variable exists, return {@code true}
91 */
92 public boolean containsCustomBindVariable(String name) {
93 return customBindVariables.containsKey(name);
94 }
95
96 /**
97 * Generate an unique variable name per iteration object. <br>
98 * Variable name rule is {@code {objectName}_{status list index}_{status.getIndex()}}.
99 *
100 * @param objectName
101 * base object name
102 * @param status
103 * iteration status object
104 *
105 * @return an unique variable name per iteration object
106 */
107 public String generateUniqueName(String objectName, IterationStatusVar status) {
108 return iterationStatusManager.generateUniqueName(objectName, status);
109 }
110
111 /**
112 * Return whether use fallback parameter object when parameter is value object.
113 *
114 * @return If use fallback parameter object, return {@code true}
115 */
116 boolean isFallbackParameterObject() {
117 return fallbackParameterObject;
118 }
119
120 private static class IterationStatusManager {
121
122 private final Map<String, List<IterationStatusVar>> statusListMapping = new HashMap<>();
123
124 private String generateUniqueName(String objectName, IterationStatusVar status) {
125 List<IterationStatusVar> statusList = statusListMapping.computeIfAbsent(objectName, k -> new ArrayList<>());
126 int index;
127 if (!statusList.contains(status)) {
128 index = statusList.size();
129 statusList.add(status);
130 } else {
131 index = statusList.indexOf(status);
132 }
133 return objectName + "_" + index + "_" + status.getIndex();
134 }
135
136 }
137
138 }