001/* 002 * #%L 003 * Netarchivesuite - harvester 004 * %% 005 * Copyright (C) 2005 - 2014 The Royal Danish Library, the Danish State and University Library, 006 * the National Library of France and the Austrian National Library. 007 * %% 008 * This program is free software: you can redistribute it and/or modify 009 * it under the terms of the GNU Lesser General Public License as 010 * published by the Free Software Foundation, either version 2.1 of the 011 * License, or (at your option) any later version. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Lesser Public License for more details. 017 * 018 * You should have received a copy of the GNU General Lesser Public 019 * License along with this program. If not, see 020 * <http://www.gnu.org/licenses/lgpl-2.1.html>. 021 * #L% 022 */ 023package dk.netarkivet.common.xml; 024 025import org.w3c.dom.Document; 026import org.w3c.dom.Element; 027import org.w3c.dom.NamedNodeMap; 028import org.w3c.dom.Node; 029import org.w3c.dom.NodeList; 030 031/** Provides functionality for generating xml document nodes ad-hoc for test purposes. The NodeTraverser 032 * uses a builder pattern to chain childnode calls to create multilevel structures. Example <p> 033 * Node deduplicationNode = NodeTraverser.create(orderxmlDoc).getChildNode("crawl-order", null) 034 .getChildNode("controller", null).getChildNode("map", "write-processors") 035 .getChildNode("newObject", "DeDuplicator").getChildNode("boolean", "enabled").getNode(); 036 * </p> 037 */ 038public class NodeTraverser { 039 private final Document doc; 040 private Node currentNode; 041 042 public NodeTraverser(Document doc) { 043 this.doc = doc; 044 currentNode = doc; 045 } 046 047 public Node getNode() { 048 return currentNode; 049 } 050 051 public static NodeTraverser create(Document doc) { 052 return new NodeTraverser(doc); 053 } 054 055 /** Will create a NodeTraverser for accessing the indicated node. If the current node does 056 * exist it will be created. 057 * @param element The tag for the element to make available. 058 * @param name A optional name attribute to add to the element if created. 059 * @return The NodeTraverser reference, which can be used to create further child nodes. 060 */ 061 public NodeTraverser getChildNode(String element, String name) { 062 Node childNode = null; 063 NodeList nodes = currentNode.getChildNodes(); 064 if (nodes != null) { 065 for (int i = 0; i < nodes.getLength(); i++) { 066 Node node = nodes.item(i); 067 NamedNodeMap attributes = node.getAttributes(); 068 String nameAttr = null; 069 if (attributes != null) { 070 Node attrNode = attributes.getNamedItem("name"); 071 if (attrNode != null && attrNode.getNodeType() == Node.ATTRIBUTE_NODE) { 072 nameAttr = attrNode.getNodeValue(); 073 } 074 } 075 if (element.equals(node.getNodeName()) && (name == null || name.equals(nameAttr))) { 076 childNode = node; 077 break; 078 } 079 } 080 } 081 if (childNode == null) { 082 Element newNode = doc.createElement(element); 083 if (name != null) { 084 newNode.setAttribute("name", name); 085 } 086 currentNode.appendChild(newNode); 087 childNode = newNode; 088 } 089 currentNode = childNode; 090 091 return this; 092 } 093}