View Javadoc
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 }