• 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

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) {
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) {
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
    }
255
    return value.toString();
1✔
256
  }
257

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

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

288
    return child;
1✔
289
  }
290

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

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

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

335
    switch (node.getNodeType()) {
×
336

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

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

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

366
        printWriter.print("</" + name + ">");
×
367
        break;
×
368

369
      case Node.TEXT_NODE:
370
        printWriter.print(node.getNodeValue());
×
371
        break;
372
    }
373

374
    printWriter.flush();
×
375
    String result = stringWriter.getBuffer().toString();
×
376
    printWriter.close();
×
377

378
    return result;
×
379
  }
380

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