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

mybatis / ibatis-2 / 678

27 Dec 2025 01:13AM UTC coverage: 65.584% (+0.05%) from 65.532%
678

push

github

hazendaz
Merge remote-tracking branch 'upstream/master' into support-javax

1606 of 2810 branches covered (57.15%)

167 of 305 new or added lines in 90 files covered. (54.75%)

6 existing lines in 4 files now uncovered.

5067 of 7726 relevant lines covered (65.58%)

0.66 hits per line

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

49.02
/src/main/java/com/ibatis/common/beans/DomProbe.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
package com.ibatis.common.beans;
17

18
import com.ibatis.common.resources.Resources;
19

20
import java.io.PrintWriter;
21
import java.io.StringWriter;
22
import java.util.ArrayList;
23
import java.util.Collection;
24
import java.util.Iterator;
25
import java.util.List;
26
import java.util.StringTokenizer;
27

28
import org.w3c.dom.CharacterData;
29
import org.w3c.dom.Document;
30
import org.w3c.dom.Element;
31
import org.w3c.dom.NamedNodeMap;
32
import org.w3c.dom.Node;
33
import org.w3c.dom.NodeList;
34
import org.w3c.dom.Text;
35

36
/**
37
 * A Probe implementation for working with DOM objects.
38
 */
39
public class DomProbe extends BaseProbe {
1✔
40

41
  @Override
42
  public String[] getReadablePropertyNames(Object object) {
NEW
43
    List props = new ArrayList<>();
×
44
    Element e = resolveElement(object);
×
45
    NodeList nodes = e.getChildNodes();
×
46
    for (int i = 0; i < nodes.getLength(); i++) {
×
47
      props.add(nodes.item(i).getNodeName());
×
48
    }
49
    return (String[]) props.toArray(new String[props.size()]);
×
50
  }
51

52
  @Override
53
  public String[] getWriteablePropertyNames(Object object) {
NEW
54
    List props = new ArrayList<>();
×
55
    Element e = resolveElement(object);
×
56
    NodeList nodes = e.getChildNodes();
×
57
    for (int i = 0; i < nodes.getLength(); i++) {
×
58
      props.add(nodes.item(i).getNodeName());
×
59
    }
60
    return (String[]) props.toArray(new String[props.size()]);
×
61
  }
62

63
  @Override
64
  public Class getPropertyTypeForSetter(Object object, String name) {
65
    Element e = findNestedNodeByName(resolveElement(object), name, false);
×
66
    // todo alias types, don't use exceptions like this
67
    try {
68
      return Resources.classForName(e.getAttribute("type"));
×
69
    } catch (ClassNotFoundException e1) {
×
70
      return Object.class;
×
71
    }
72
  }
73

74
  @Override
75
  public Class getPropertyTypeForGetter(Object object, String name) {
76
    Element e = findNestedNodeByName(resolveElement(object), name, false);
×
77
    // todo alias types, don't use exceptions like this
78
    try {
79
      return Resources.classForName(e.getAttribute("type"));
×
80
    } catch (ClassNotFoundException e1) {
×
81
      return Object.class;
×
82
    }
83
  }
84

85
  @Override
86
  public boolean hasWritableProperty(Object object, String propertyName) {
87
    return findNestedNodeByName(resolveElement(object), propertyName, false) != null;
×
88
  }
89

90
  @Override
91
  public boolean hasReadableProperty(Object object, String propertyName) {
92
    return findNestedNodeByName(resolveElement(object), propertyName, false) != null;
×
93
  }
94

95
  @Override
96
  public Object getObject(Object object, String name) {
97
    Object value = null;
1✔
98
    Element element = findNestedNodeByName(resolveElement(object), name, false);
1✔
99
    if (element != null) {
1!
100
      value = getElementValue(element);
1✔
101
    }
102
    return value;
1✔
103
  }
104

105
  @Override
106
  public void setObject(Object object, String name, Object value) {
107
    Element element = findNestedNodeByName(resolveElement(object), name, true);
1✔
108
    if (element != null) {
1!
109
      setElementValue(element, value);
1✔
110
    }
111
  }
1✔
112

113
  @Override
114
  protected void setProperty(Object object, String property, Object value) {
115
    Element element = findNodeByName(resolveElement(object), property, 0, true);
×
116
    if (element != null) {
×
117
      setElementValue(element, value);
×
118
    }
119
  }
×
120

121
  @Override
122
  protected Object getProperty(Object object, String property) {
123
    Object value = null;
×
124
    Element element = findNodeByName(resolveElement(object), property, 0, false);
×
125
    if (element != null) {
×
126
      value = getElementValue(element);
×
127
    }
128
    return value;
×
129
  }
130

131
  /**
132
   * Resolve element.
133
   *
134
   * @param object
135
   *          the object
136
   *
137
   * @return the element
138
   */
139
  private Element resolveElement(Object object) {
140
    Element element = null;
1✔
141
    if (object instanceof Document) {
1!
142
      element = (Element) ((Document) object).getLastChild();
1✔
143
    } else if (object instanceof Element) {
×
144
      element = (Element) object;
×
145
    } else {
146
      throw new ProbeException("An unknown object type was passed to DomProbe.  Must be a Document.");
×
147
    }
148
    return element;
1✔
149
  }
150

151
  /**
152
   * Sets the element value.
153
   *
154
   * @param element
155
   *          the element
156
   * @param value
157
   *          the value
158
   */
159
  private void setElementValue(Element element, Object value) {
160
    CharacterData data = null;
1✔
161

162
    Element prop = element;
1✔
163

164
    if (value instanceof Collection) {
1✔
165
      Iterator items = ((Collection) value).iterator();
1✔
166
      while (items.hasNext()) {
1✔
167
        Document valdoc = (Document) items.next();
1✔
168
        NodeList list = valdoc.getChildNodes();
1✔
169
        for (int i = 0; i < list.getLength(); i++) {
1✔
170
          Node newNode = element.getOwnerDocument().importNode(list.item(i), true);
1✔
171
          element.appendChild(newNode);
1✔
172
        }
173
      }
1✔
174
    } else if (value instanceof Document) {
1✔
175
      Document valdoc = (Document) value;
1✔
176
      Node lastChild = valdoc.getLastChild();
1✔
177
      NodeList list = lastChild.getChildNodes();
1✔
178
      for (int i = 0; i < list.getLength(); i++) {
1✔
179
        Node newNode = element.getOwnerDocument().importNode(list.item(i), true);
1✔
180
        element.appendChild(newNode);
1✔
181
      }
182
    } else if (value instanceof Element) {
1!
183
      Node newNode = element.getOwnerDocument().importNode((Element) value, true);
×
184
      element.appendChild(newNode);
×
185
    } else {
×
186
      // Find text child element
187
      NodeList texts = prop.getChildNodes();
1✔
188
      if (texts.getLength() == 1) {
1!
189
        Node child = texts.item(0);
×
190
        if (child instanceof CharacterData) {
×
191
          // Use existing text.
192
          data = (CharacterData) child;
×
193
        } else {
194
          // Remove non-text, add text.
195
          prop.removeChild(child);
×
196
          Text text = prop.getOwnerDocument().createTextNode(String.valueOf(value));
×
197
          prop.appendChild(text);
×
198
          data = text;
×
199
        }
200
      } else if (texts.getLength() > 1) {
1!
201
        // Remove all, add text.
202
        for (int i = texts.getLength() - 1; i >= 0; i--) {
×
203
          prop.removeChild(texts.item(i));
×
204
        }
205
        Text text = prop.getOwnerDocument().createTextNode(String.valueOf(value));
×
206
        prop.appendChild(text);
×
207
        data = text;
×
208
      } else {
×
209
        // Add text.
210
        Text text = prop.getOwnerDocument().createTextNode(String.valueOf(value));
1✔
211
        prop.appendChild(text);
1✔
212
        data = text;
1✔
213
      }
214
      data.setData(String.valueOf(value));
1✔
215
    }
216

217
    // Set type attribute
218
    // prop.setAttribute("type", value == null ? "null" : value.getClass().getName());
219

220
  }
1✔
221

222
  /**
223
   * Gets the element value.
224
   *
225
   * @param element
226
   *          the element
227
   *
228
   * @return the element value
229
   */
230
  private Object getElementValue(Element element) {
231
    StringBuilder value = null;
1✔
232

233
    Element prop = element;
1✔
234

235
    if (prop != null) {
1!
236
      // Find text child elements
237
      NodeList texts = prop.getChildNodes();
1✔
238
      if (texts.getLength() > 0) {
1!
239
        value = new StringBuilder();
1✔
240
        for (int i = 0; i < texts.getLength(); i++) {
1✔
241
          Node text = texts.item(i);
1✔
242
          if (text instanceof CharacterData) {
1!
243
            value.append(((CharacterData) text).getData());
1✔
244
          }
245
        }
246
      }
247
    }
248

249
    // convert to proper type
250
    // value = convert(value.toString());
251

252
    if (value == null) {
1!
253
      return null;
×
254
    } else {
255
      return value.toString();
1✔
256
    }
257
  }
258

259
  /**
260
   * Find nested node by name.
261
   *
262
   * @param element
263
   *          the element
264
   * @param name
265
   *          the name
266
   * @param create
267
   *          the create
268
   *
269
   * @return the element
270
   */
271
  private Element findNestedNodeByName(Element element, String name, boolean create) {
272
    Element child = element;
1✔
273

274
    StringTokenizer parser = new StringTokenizer(name, ".", false);
1✔
275
    while (parser.hasMoreTokens()) {
1✔
276
      String childName = parser.nextToken();
1✔
277
      if (childName.indexOf('[') > -1) {
1✔
278
        String propName = childName.substring(0, childName.indexOf('['));
1✔
279
        int i = Integer.parseInt(childName.substring(childName.indexOf('[') + 1, childName.indexOf(']')));
1✔
280
        child = findNodeByName(child, propName, i, create);
1✔
281
      } else {
1✔
282
        child = findNodeByName(child, childName, 0, create);
1✔
283
      }
284
      if (child == null) {
1!
285
        break;
×
286
      }
287
    }
1✔
288

289
    return child;
1✔
290
  }
291

292
  /**
293
   * Find node by name.
294
   *
295
   * @param element
296
   *          the element
297
   * @param name
298
   *          the name
299
   * @param index
300
   *          the index
301
   * @param create
302
   *          the create
303
   *
304
   * @return the element
305
   */
306
  private Element findNodeByName(Element element, String name, int index, boolean create) {
307
    Element prop = null;
1✔
308

309
    // Find named property element
310
    NodeList propNodes = element.getElementsByTagName(name);
1✔
311
    if (propNodes.getLength() > index) {
1✔
312
      prop = (Element) propNodes.item(index);
1✔
313
    } else {
314
      if (create) {
1!
315
        for (int i = 0; i < index + 1; i++) {
1✔
316
          prop = element.getOwnerDocument().createElement(name);
1✔
317
          element.appendChild(prop);
1✔
318
        }
319
      }
320
    }
321
    return prop;
1✔
322
  }
323

324
  /**
325
   * Converts a DOM node to a complete xml string.
326
   *
327
   * @param node
328
   *          - the node to process
329
   * @param indent
330
   *          - how to indent the children of the node
331
   *
332
   * @return The node as a String
333
   */
334
  public static String nodeToString(Node node, String indent) {
335
    StringWriter stringWriter = new StringWriter();
×
336
    PrintWriter printWriter = new PrintWriter(stringWriter);
×
337

338
    switch (node.getNodeType()) {
×
339

340
      case Node.DOCUMENT_NODE:
341
        printWriter.println("<xml version=\"1.0\">\n");
×
342
        // recurse on each child
343
        NodeList nodes = node.getChildNodes();
×
344
        if (nodes != null) {
×
345
          for (int i = 0; i < nodes.getLength(); i++) {
×
346
            printWriter.print(nodeToString(nodes.item(i), ""));
×
347
          }
348
        }
349
        break;
350

351
      case Node.ELEMENT_NODE:
352
        String name = node.getNodeName();
×
353
        printWriter.print(indent + "<" + name);
×
354
        NamedNodeMap attributes = node.getAttributes();
×
355
        for (int i = 0; i < attributes.getLength(); i++) {
×
356
          Node current = attributes.item(i);
×
357
          printWriter.print(" " + current.getNodeName() + "=\"" + current.getNodeValue() + "\"");
×
358
        }
359
        printWriter.print(">");
×
360

361
        // recurse on each child
362
        NodeList children = node.getChildNodes();
×
363
        if (children != null) {
×
364
          for (int i = 0; i < children.getLength(); i++) {
×
365
            printWriter.print(nodeToString(children.item(i), indent + indent));
×
366
          }
367
        }
368

369
        printWriter.print("</" + name + ">");
×
370
        break;
×
371

372
      case Node.TEXT_NODE:
373
        printWriter.print(node.getNodeValue());
×
374
        break;
375
    }
376

377
    printWriter.flush();
×
378
    String result = stringWriter.getBuffer().toString();
×
379
    printWriter.close();
×
380

381
    return result;
×
382
  }
383

384
}
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

© 2026 Coveralls, Inc