• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mybatis / ibatis-2 / 730

28 Dec 2025 10:16PM UTC coverage: 65.615% (+0.5%) from 65.146%
730

push

github

web-flow
Update README.md

1602 of 2802 branches covered (57.17%)

5053 of 7701 relevant lines covered (65.61%)

0.66 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.5
/src/main/java/com/ibatis/sqlmap/engine/mapping/sql/dynamic/elements/IterateContext.java
1
/*
2
 * Copyright 2004-2025 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
/*
17
 * Created on Apr 17, 2005
18
 */
19
package com.ibatis.sqlmap.engine.mapping.sql.dynamic.elements;
20

21
import com.ibatis.sqlmap.client.SqlMapException;
22

23
import java.lang.reflect.Array;
24
import java.util.ArrayList;
25
import java.util.Arrays;
26
import java.util.Collection;
27
import java.util.HashMap;
28
import java.util.Iterator;
29
import java.util.List;
30
import java.util.Map;
31

32
/**
33
 * The Class IterateContext.
34
 *
35
 * @author Brandon Goodin
36
 */
37
public class IterateContext implements Iterator {
38

39
  /** The Constant PROCESS_INDEX. */
40
  private static final String PROCESS_INDEX = "ProcessIndex";
41

42
  /** The Constant PROCESS_STRING. */
43
  private static final String PROCESS_STRING = "ProcessString";
44

45
  /** The iterator. */
46
  private Iterator iterator;
47

48
  /** The index. */
49
  private int index = -1;
1✔
50

51
  /** The property. */
52
  private String property;
53

54
  /** The allow next. */
55
  private boolean allowNext = true;
1✔
56

57
  /** The is final. */
58
  private boolean isFinal = false;
1✔
59

60
  /** The tag. */
61
  private SqlTag tag;
62

63
  /** The parent. */
64
  private IterateContext parent;
65

66
  /**
67
   * This variable is true if some of the sub elements have actually produced content. This is used to test whether to
68
   * add the open and conjunction text to the generated statement.
69
   * <p>
70
   * This variable is used to replace the deprecated and dangerous isFirst method.
71
   */
72
  private boolean someSubElementsHaveContent;
73

74
  /**
75
   * This variable is set by the doEndFragment method in IterateTagHandler to specify that the first content producing
76
   * sub element has happened. The doPrepend method will test the value to know whether or not to process the prepend.
77
   * This variable is used to replace the deprecated and dangerous isFirst method.
78
   */
79
  private boolean isPrependEnabled;
80

81
  /**
82
   * Instantiates a new iterate context.
83
   *
84
   * @param collection
85
   *          the collection
86
   * @param tag
87
   *          the tag
88
   * @param parent
89
   *          the parent
90
   */
91
  public IterateContext(Object collection, SqlTag tag, IterateContext parent) {
1✔
92
    this.parent = parent;
1✔
93
    this.tag = tag;
1✔
94
    if (collection instanceof Collection) {
1✔
95
      this.iterator = ((Collection) collection).iterator();
1✔
96
    } else if (collection instanceof Iterator) {
1!
97
      this.iterator = (Iterator) collection;
×
98
    } else if (collection.getClass().isArray()) {
1!
99
      List list = arrayToList(collection);
1✔
100
      this.iterator = list.iterator();
1✔
101
    } else {
1✔
102
      throw new SqlMapException("ParameterObject or property was not a Collection, Array or Iterator.");
×
103
    }
104
  }
1✔
105

106
  @Override
107
  public boolean hasNext() {
108
    return iterator != null && iterator.hasNext();
1!
109
  }
110

111
  @Override
112
  public Object next() {
113
    index++;
1✔
114
    return iterator.next();
1✔
115
  }
116

117
  @Override
118
  public void remove() {
119
    iterator.remove();
×
120
  }
×
121

122
  /**
123
   * Gets the index.
124
   *
125
   * @return the index
126
   */
127
  public int getIndex() {
128
    return index;
1✔
129
  }
130

131
  /**
132
   * Checks if is first.
133
   *
134
   * @return true, if is first
135
   *
136
   * @deprecated This method should not be used to decide whether or not to add prepend and open text to the generated
137
   *             statement. Rather, use the methods isPrependEnabled() and someSubElementsHaveContent().
138
   */
139
  @Deprecated
140
  public boolean isFirst() {
141
    return index == 0;
×
142
  }
143

144
  /**
145
   * Checks if is last.
146
   *
147
   * @return true, if is last
148
   */
149
  public boolean isLast() {
150
    return iterator != null && !iterator.hasNext();
1!
151
  }
152

153
  /**
154
   * Array to list.
155
   *
156
   * @param array
157
   *          the array
158
   *
159
   * @return the list
160
   */
161
  private List arrayToList(Object array) {
162
    List list = null;
1✔
163
    if (array instanceof Object[]) {
1✔
164
      list = Arrays.asList((Object[]) array);
1✔
165
    } else {
166
      list = new ArrayList<>();
1✔
167
      for (int i = 0, n = Array.getLength(array); i < n; i++) {
1✔
168
        list.add(Array.get(array, i));
1✔
169
      }
170
    }
171
    return list;
1✔
172
  }
173

174
  /**
175
   * Gets the property.
176
   *
177
   * @return Returns the property.
178
   */
179
  public String getProperty() {
180
    return property;
1✔
181
  }
182

183
  /**
184
   * This property specifies whether to increment the iterate in the doEndFragment. The ConditionalTagHandler has the
185
   * ability to increment the IterateContext, so it is neccessary to avoid incrementing in both the ConditionalTag and
186
   * the IterateTag.
187
   *
188
   * @param property
189
   *          The property to set.
190
   */
191
  public void setProperty(String property) {
192
    this.property = property;
1✔
193
  }
1✔
194

195
  /**
196
   * Checks if is allow next.
197
   *
198
   * @return Returns the allowNext.
199
   */
200
  public boolean isAllowNext() {
201
    return allowNext;
1✔
202
  }
203

204
  /**
205
   * Sets the allow next.
206
   *
207
   * @param performIterate
208
   *          The allowNext to set.
209
   */
210
  public void setAllowNext(boolean performIterate) {
211
    this.allowNext = performIterate;
1✔
212
  }
1✔
213

214
  /**
215
   * Gets the tag.
216
   *
217
   * @return Returns the tag.
218
   */
219
  public SqlTag getTag() {
220
    return tag;
1✔
221
  }
222

223
  /**
224
   * Sets the tag.
225
   *
226
   * @param tag
227
   *          The tag to set.
228
   */
229
  public void setTag(SqlTag tag) {
230
    this.tag = tag;
×
231
  }
×
232

233
  /**
234
   * Checks if is final.
235
   *
236
   * @return true, if is final
237
   */
238
  public boolean isFinal() {
239
    return isFinal;
1✔
240
  }
241

242
  /**
243
   * This attribute is used to mark whether an iterate tag is in it's final iteration. Since the ConditionalTagHandler
244
   * can increment the iterate the final iterate in the doEndFragment of the IterateTagHandler needs to know it is in
245
   * it's final iterate.
246
   *
247
   * @param aFinal
248
   *          the new final
249
   */
250
  public void setFinal(boolean aFinal) {
251
    isFinal = aFinal;
1✔
252
  }
1✔
253

254
  /**
255
   * Returns the last property of any bean specified in this IterateContext.
256
   *
257
   * @return The last property of any bean specified in this IterateContext.
258
   */
259
  public String getEndProperty() {
260
    if (parent != null) {
1✔
261
      int parentPropertyIndex = property.indexOf(parent.getProperty());
1✔
262
      if (parentPropertyIndex > -1) {
1✔
263
        int endPropertyIndex1 = property.indexOf(']', parentPropertyIndex);
1✔
264
        int endPropertyIndex2 = property.indexOf('.', parentPropertyIndex);
1✔
265
        return property.substring(parentPropertyIndex + Math.max(endPropertyIndex1, endPropertyIndex2) + 1,
1✔
266
            property.length());
1✔
267
      } else {
268
        return property;
1✔
269
      }
270
    } else {
271
      return property;
1✔
272
    }
273
  }
274

275
  /**
276
   * Replaces value of a tag property to match it's value with current iteration and all other iterations.
277
   *
278
   * @param tagProperty
279
   *          the property of a TagHandler.
280
   *
281
   * @return A Map containing the modified tag property in PROCESS_STRING key and the index where the modification
282
   *         occured in PROCESS_INDEX key.
283
   */
284
  protected Map processTagProperty(String tagProperty) {
285
    if (parent != null) {
1✔
286
      Map parentResult = parent.processTagProperty(tagProperty);
1✔
287
      return this.addIndex((String) parentResult.get(PROCESS_STRING),
1✔
288
          ((Integer) parentResult.get(PROCESS_INDEX)).intValue());
1✔
289
    }
290
    return this.addIndex(tagProperty, 0);
1✔
291
  }
292

293
  /**
294
   * Replaces value of a tag property to match it's value with current iteration and all other iterations.
295
   *
296
   * @param tagProperty
297
   *          the property of a TagHandler.
298
   *
299
   * @return The tag property with all "[]" replaced with the correct iteration value.
300
   */
301
  public String addIndexToTagProperty(String tagProperty) {
302
    Map map = this.processTagProperty(tagProperty);
1✔
303
    return (String) map.get(PROCESS_STRING);
1✔
304
  }
305

306
  /**
307
   * Adds index value to the first found property matching this Iteration starting at index startIndex.
308
   *
309
   * @param input
310
   *          The input String.
311
   * @param startIndex
312
   *          The index where search for property begins.
313
   *
314
   * @return A Map containing the modified tag property in PROCESS_STRING key and the index where the modification
315
   *         occured in PROCESS_INDEX key.
316
   */
317
  protected Map addIndex(String input, int startIndex) {
318
    String endProperty = getEndProperty() + "[";
1✔
319
    int propertyIndex = input.indexOf(endProperty, startIndex);
1✔
320
    int modificationIndex = 0;
1✔
321
    // Is the iterate property in the tag property at all?
322
    if (propertyIndex > -1) {
1✔
323
      // Make sure the tag property does not already have a number.
324
      if (input.charAt(propertyIndex + endProperty.length()) == ']') {
1✔
325
        // Add iteration number to property.
326
        input = input.substring(0, propertyIndex + endProperty.length()) + this.getIndex()
1✔
327
            + input.substring(propertyIndex + endProperty.length());
1✔
328
        modificationIndex = propertyIndex + endProperty.length();
1✔
329
      }
330
    }
331
    Map ret = new HashMap<>();
1✔
332
    ret.put(PROCESS_INDEX, Integer.valueOf(modificationIndex));
1✔
333
    ret.put(PROCESS_STRING, input);
1✔
334
    return ret;
1✔
335
  }
336

337
  /**
338
   * Gets the parent.
339
   *
340
   * @return the parent
341
   */
342
  public IterateContext getParent() {
343
    return parent;
×
344
  }
345

346
  /**
347
   * Sets the parent.
348
   *
349
   * @param parent
350
   *          the new parent
351
   */
352
  public void setParent(IterateContext parent) {
353
    this.parent = parent;
×
354
  }
×
355

356
  /**
357
   * Some sub elements have content.
358
   *
359
   * @return true, if successful
360
   */
361
  public boolean someSubElementsHaveContent() {
362
    return someSubElementsHaveContent;
1✔
363
  }
364

365
  /**
366
   * Sets the some sub elements have content.
367
   *
368
   * @param someSubElementsHaveContent
369
   *          the new some sub elements have content
370
   */
371
  public void setSomeSubElementsHaveContent(boolean someSubElementsHaveContent) {
372
    this.someSubElementsHaveContent = someSubElementsHaveContent;
1✔
373
  }
1✔
374

375
  /**
376
   * Checks if is prepend enabled.
377
   *
378
   * @return true, if is prepend enabled
379
   */
380
  public boolean isPrependEnabled() {
381
    return isPrependEnabled;
1✔
382
  }
383

384
  /**
385
   * Sets the prepend enabled.
386
   *
387
   * @param isPrependEnabled
388
   *          the new prepend enabled
389
   */
390
  public void setPrependEnabled(boolean isPrependEnabled) {
391
    this.isPrependEnabled = isPrependEnabled;
1✔
392
  }
1✔
393
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc