1f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling//================================================================================================= 2f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling// ADOBE SYSTEMS INCORPORATED 3f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling// Copyright 2006 Adobe Systems Incorporated 4f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling// All Rights Reserved 5f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling// 6f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms 7f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling// of the Adobe license agreement accompanying it. 8f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling// ================================================================================================= 9f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 10f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingpackage com.adobe.xmp.impl; 11f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 12f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport java.util.ArrayList; 13f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport java.util.Arrays; 14f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport java.util.Collections; 15f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport java.util.Iterator; 16f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport java.util.List; 17f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport java.util.ListIterator; 18f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 19f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport com.adobe.xmp.XMPConst; 20f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport com.adobe.xmp.XMPError; 21f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport com.adobe.xmp.XMPException; 22f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingimport com.adobe.xmp.options.PropertyOptions; 23f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 24f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 25f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling/** 26f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * A node in the internally XMP tree, which can be a schema node, a property node, an array node, 27f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * an array item, a struct node or a qualifier node (without '?'). 28f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * 29f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * Possible improvements: 30f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * 31f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * 1. The kind Node of node might be better represented by a class-hierarchy of different nodes. 32f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * 2. The array type should be an enum 33f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * 3. isImplicitNode should be removed completely and replaced by return values of fi. 34f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * 4. hasLanguage, hasType should be automatically maintained by XMPNode 35f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * 36f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @since 21.02.2006 37f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 38f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberlingclass XMPNode implements Comparable 39f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling{ 40f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** name of the node, contains different information depending of the node kind */ 41f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling private String name; 42f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** value of the node, contains different information depending of the node kind */ 43f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling private String value; 44f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** link to the parent node */ 45f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling private XMPNode parent; 46f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** list of child nodes, lazy initialized */ 47f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling private List children = null; 48f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** list of qualifier of the node, lazy initialized */ 49f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling private List qualifier = null; 50f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** options describing the kind of the node */ 51f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling private PropertyOptions options = null; 52f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 53f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling // internal processing options 54f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 55f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** flag if the node is implicitly created */ 56f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling private boolean implicit; 57f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** flag if the node has aliases */ 58f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling private boolean hasAliases; 59f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** flag if the node is an alias */ 60f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling private boolean alias; 61f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** flag if the node has an "rdf:value" child node. */ 62f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling private boolean hasValueChild; 63f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 64f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 65f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 66f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 67f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * Creates an <code>XMPNode</code> with initial values. 68f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * 69f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param name the name of the node 70f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param value the value of the node 71f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param options the options of the node 72f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 73f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public XMPNode(String name, String value, PropertyOptions options) 74f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 75f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling this.name = name; 76f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling this.value = value; 77f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling this.options = options; 78f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 79f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 80f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 81f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 82f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * Constructor for the node without value. 83f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * 84f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param name the name of the node 85f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param options the options of the node 86f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 87f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public XMPNode(String name, PropertyOptions options) 88f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 89f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling this(name, null, options); 90f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 91f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 92f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 93f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 94f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * Resets the node. 95f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 96f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public void clear() 97f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 98f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling options = null; 99f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling name = null; 100f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling value = null; 101f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling children = null; 102f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling qualifier = null; 103f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 104f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 105f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 106f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 107f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @return Returns the parent node. 108f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 109f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public XMPNode getParent() 110f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 111f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return parent; 112f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 113f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 114f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 115f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 116f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param index an index [1..size] 117f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @return Returns the child with the requested index. 118f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 119f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public XMPNode getChild(int index) 120f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 121f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return (XMPNode) getChildren().get(index - 1); 122f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 123f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 124f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 125f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 126f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * Adds a node as child to this node. 127f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param node an XMPNode 128f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @throws XMPException 129f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 130f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public void addChild(XMPNode node) throws XMPException 131f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 132f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling // check for duplicate properties 133f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling assertChildNotExisting(node.getName()); 134f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling node.setParent(this); 135f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling getChildren().add(node); 136f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 137f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 138f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 139f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 140f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * Adds a node as child to this node. 141f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param index the index of the node <em>before</em> which the new one is inserted. 142f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * <em>Note:</em> The node children are indexed from [1..size]! 143f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * An index of size + 1 appends a node. 144f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param node an XMPNode 145f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @throws XMPException 146f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 147f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public void addChild(int index, XMPNode node) throws XMPException 148f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 149f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling assertChildNotExisting(node.getName()); 150f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling node.setParent(this); 151f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling getChildren().add(index - 1, node); 152f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 153f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 154f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 155f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 156f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * Replaces a node with another one. 157f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param index the index of the node that will be replaced. 158f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * <em>Note:</em> The node children are indexed from [1..size]! 159f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param node the replacement XMPNode 160f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 161f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public void replaceChild(int index, XMPNode node) 162f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 163f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling node.setParent(this); 164f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling getChildren().set(index - 1, node); 165f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 166f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 167f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 168f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 169f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * Removes a child at the requested index. 170f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param itemIndex the index to remove [1..size] 171f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 172f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public void removeChild(int itemIndex) 173f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 174f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling getChildren().remove(itemIndex - 1); 175f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling cleanupChildren(); 176f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 177f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 178f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 179f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 180f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * Removes a child node. 181f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * If its a schema node and doesn't have any children anymore, its deleted. 182f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * 183f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param node the child node to delete. 184f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 185f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public void removeChild(XMPNode node) 186f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 187f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling getChildren().remove(node); 188f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling cleanupChildren(); 189f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 190f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 191f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 192f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 193f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * Removes the children list if this node has no children anymore; 194f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * checks if the provided node is a schema node and doesn't have any children anymore, 195f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * its deleted. 196f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 197f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling protected void cleanupChildren() 198f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 199f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling if (children.isEmpty()) 200f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 201f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling children = null; 202f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 203f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 204f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 205f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 206f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 207f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * Removes all children from the node. 208f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 209f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public void removeChildren() 210f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 211f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling children = null; 212f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 213f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 214f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 215f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 216f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @return Returns the number of children without neccessarily creating a list. 217f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 218f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public int getChildrenLength() 219f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 220f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return children != null ? 221f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling children.size() : 222f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 0; 223f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 224f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 225f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 226f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 227f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param expr child node name to look for 228f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @return Returns an <code>XMPNode</code> if node has been found, <code>null</code> otherwise. 229f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 230f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public XMPNode findChildByName(String expr) 231f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 232f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return find(getChildren(), expr); 233f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 234f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 235f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 236f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 237f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param index an index [1..size] 238f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @return Returns the qualifier with the requested index. 239f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 240f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public XMPNode getQualifier(int index) 241f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 242f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return (XMPNode) getQualifier().get(index - 1); 243f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 244f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 245f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 246f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 247f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @return Returns the number of qualifier without neccessarily creating a list. 248f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 249f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public int getQualifierLength() 250f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 251f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return qualifier != null ? 252f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling qualifier.size() : 253f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 0; 254f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 255f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 256f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 257f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 258f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * Appends a qualifier to the qualifier list and sets respective options. 259f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param qualNode a qualifier node. 260f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @throws XMPException 261f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 262f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public void addQualifier(XMPNode qualNode) throws XMPException 263f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 264f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling assertQualifierNotExisting(qualNode.getName()); 265f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling qualNode.setParent(this); 266f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling qualNode.getOptions().setQualifier(true); 267f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling getOptions().setHasQualifiers(true); 268f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 269f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling // contraints 270f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling if (qualNode.isLanguageNode()) 271f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 272f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling // "xml:lang" is always first and the option "hasLanguage" is set 273f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling options.setHasLanguage(true); 274f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling getQualifier().add(0, qualNode); 275f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 276f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling else if (qualNode.isTypeNode()) 277f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 278f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling // "rdf:type" must be first or second after "xml:lang" and the option "hasType" is set 279f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling options.setHasType(true); 280f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling getQualifier().add( 281f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling !options.getHasLanguage() ? 0 : 1, 282f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling qualNode); 283f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 284f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling else 285f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 286f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling // other qualifiers are appended 287f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling getQualifier().add(qualNode); 288f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 289f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 290f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 291f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 292f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 293f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * Removes one qualifier node and fixes the options. 294f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param qualNode qualifier to remove 295f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 296f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public void removeQualifier(XMPNode qualNode) 297f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 298f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling PropertyOptions opts = getOptions(); 299f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling if (qualNode.isLanguageNode()) 300f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 301f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling // if "xml:lang" is removed, remove hasLanguage-flag too 302f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling opts.setHasLanguage(false); 303f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 304f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling else if (qualNode.isTypeNode()) 305f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 306f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling // if "rdf:type" is removed, remove hasType-flag too 307f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling opts.setHasType(false); 308f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 309f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 310f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling getQualifier().remove(qualNode); 311f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling if (qualifier.isEmpty()) 312f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 313f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling opts.setHasQualifiers(false); 314f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling qualifier = null; 315f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 316f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 317f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 318f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 319f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 320f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 321f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * Removes all qualifiers from the node and sets the options appropriate. 322f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 323f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public void removeQualifiers() 324f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 325f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling PropertyOptions opts = getOptions(); 326f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling // clear qualifier related options 327f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling opts.setHasQualifiers(false); 328f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling opts.setHasLanguage(false); 329f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling opts.setHasType(false); 330f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling qualifier = null; 331f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 332f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 333f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 334f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 335f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param expr qualifier node name to look for 336f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @return Returns a qualifier <code>XMPNode</code> if node has been found, 337f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * <code>null</code> otherwise. 338f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 339f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public XMPNode findQualifierByName(String expr) 340f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 341f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return find(qualifier, expr); 342f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 343f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 344f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 345f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 346f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @return Returns whether the node has children. 347f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 348f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public boolean hasChildren() 349f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 350f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return children != null && children.size() > 0; 351f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 352f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 353f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 354f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 355f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @return Returns an iterator for the children. 356f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * <em>Note:</em> take care to use it.remove(), as the flag are not adjusted in that case. 357f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 358f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public Iterator iterateChildren() 359f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 360f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling if (children != null) 361f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 362f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return getChildren().iterator(); 363f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 364f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling else 365f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 366f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return Collections.EMPTY_LIST.listIterator(); 367f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 368f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 369f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 370f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 371f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 372f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @return Returns whether the node has qualifier attached. 373f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 374f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public boolean hasQualifier() 375f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 376f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return qualifier != null && qualifier.size() > 0; 377f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 378f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 379f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 380f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 381f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @return Returns an iterator for the qualifier. 382f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * <em>Note:</em> take care to use it.remove(), as the flag are not adjusted in that case. 383f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 384f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public Iterator iterateQualifier() 385f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 386f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling if (qualifier != null) 387f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 388f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling final Iterator it = getQualifier().iterator(); 389f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 390f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return new Iterator() 391f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 392f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public boolean hasNext() 393f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 394f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return it.hasNext(); 395f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 396f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 397f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public Object next() 398f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 399f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return it.next(); 400f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 401f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 402f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public void remove() 403f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 404f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling throw new UnsupportedOperationException( 405f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling "remove() is not allowed due to the internal contraints"); 406f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 407f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 408f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling }; 409f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 410f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling else 411f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 412f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return Collections.EMPTY_LIST.iterator(); 413f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 414f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 415f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 416f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 417f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 418f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * Performs a <b>deep clone</b> of the node and the complete subtree. 419f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * 420f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @see java.lang.Object#clone() 421f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 422f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public Object clone() 423f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 424f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling PropertyOptions newOptions; 425f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling try 426f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 427f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling newOptions = new PropertyOptions(getOptions().getOptions()); 428f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 429f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling catch (XMPException e) 430f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 431f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling // cannot happen 432f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling newOptions = new PropertyOptions(); 433f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 434f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 435f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling XMPNode newNode = new XMPNode(name, value, newOptions); 436f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling cloneSubtree(newNode); 437f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 438f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return newNode; 439f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 440f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 441f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 442f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 443f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * Performs a <b>deep clone</b> of the complete subtree (children and 444f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * qualifier )into and add it to the destination node. 445f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * 446f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param destination the node to add the cloned subtree 447f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 448f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public void cloneSubtree(XMPNode destination) 449f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 450f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling try 451f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 452f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling for (Iterator it = iterateChildren(); it.hasNext();) 453f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 454f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling XMPNode child = (XMPNode) it.next(); 455f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling destination.addChild((XMPNode) child.clone()); 456f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 457f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 458f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling for (Iterator it = iterateQualifier(); it.hasNext();) 459f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 460f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling XMPNode qualifier = (XMPNode) it.next(); 461f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling destination.addQualifier((XMPNode) qualifier.clone()); 462f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 463f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 464f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling catch (XMPException e) 465f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 466f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling // cannot happen (duplicate childs/quals do not exist in this node) 467f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling assert false; 468f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 469f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 470f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 471f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 472f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 473f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 474f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * Renders this node and the tree unter this node in a human readable form. 475f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param recursive Flag is qualifier and child nodes shall be rendered too 476f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @return Returns a multiline string containing the dump. 477f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 478f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public String dumpNode(boolean recursive) 479f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 480f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling StringBuffer result = new StringBuffer(512); 481f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling this.dumpNode(result, recursive, 0, 0); 482f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return result.toString(); 483f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 484f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 485f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 486f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 487f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @see Comparable#compareTo(Object) 488f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 489f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public int compareTo(Object xmpNode) 490f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 491f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling if (getOptions().isSchemaNode()) 492f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 493f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return this.value.compareTo(((XMPNode) xmpNode).getValue()); 494f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 495f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling else 496f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 497f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return this.name.compareTo(((XMPNode) xmpNode).getName()); 498f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 499f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 500f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 501f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 502f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 503f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @return Returns the name. 504f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 505f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public String getName() 506f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 507f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return name; 508f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 509f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 510f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 511f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 512f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param name The name to set. 513f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 514f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public void setName(String name) 515f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 516f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling this.name = name; 517f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 518f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 519f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 520f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 521f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @return Returns the value. 522f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 523f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public String getValue() 524f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 525f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return value; 526f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 527f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 528f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 529f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 530f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param value The value to set. 531f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 532f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public void setValue(String value) 533f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 534f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling this.value = value; 535f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 536f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 537f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 538f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 539f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @return Returns the options. 540f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 541f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public PropertyOptions getOptions() 542f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 543f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling if (options == null) 544f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 545f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling options = new PropertyOptions(); 546f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 547f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return options; 548f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 549f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 550f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 551f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 552f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * Updates the options of the node. 553f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param options the options to set. 554f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 555f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public void setOptions(PropertyOptions options) 556f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 557f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling this.options = options; 558f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 559f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 560f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 561f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 562f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @return Returns the implicit flag 563f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 564f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public boolean isImplicit() 565f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 566f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return implicit; 567f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 568f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 569f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 570f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 571f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param implicit Sets the implicit node flag 572f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 573f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public void setImplicit(boolean implicit) 574f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 575f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling this.implicit = implicit; 576f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 577f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 578f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 579f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 580f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @return Returns if the node contains aliases (applies only to schema nodes) 581f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 582f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public boolean getHasAliases() 583f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 584f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return hasAliases; 585f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 586f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 587f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 588f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 589f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param hasAliases sets the flag that the node contains aliases 590f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 591f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public void setHasAliases(boolean hasAliases) 592f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 593f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling this.hasAliases = hasAliases; 594f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 595f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 596f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 597f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 598f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @return Returns if the node contains aliases (applies only to schema nodes) 599f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 600f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public boolean isAlias() 601f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 602f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return alias; 603f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 604f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 605f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 606f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 607f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param alias sets the flag that the node is an alias 608f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 609f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public void setAlias(boolean alias) 610f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 611f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling this.alias = alias; 612f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 613f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 614f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 615f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 616f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @return the hasValueChild 617f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 618f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public boolean getHasValueChild() 619f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 620f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return hasValueChild; 621f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 622f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 623f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 624f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 625f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param hasValueChild the hasValueChild to set 626f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 627f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public void setHasValueChild(boolean hasValueChild) 628f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 629f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling this.hasValueChild = hasValueChild; 630f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 631f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 632f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 633f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 634f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 635f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * Sorts the complete datamodel according to the following rules: 636f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * <ul> 637f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * <li>Nodes at one level are sorted by name, that is prefix + local name 638f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * <li>Starting at the root node the children and qualifier are sorted recursively, 639f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * which the following exceptions. 640f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * <li>Sorting will not be used for arrays. 641f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * <li>Within qualifier "xml:lang" and/or "rdf:type" stay at the top in that order, 642f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * all others are sorted. 643f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * </ul> 644f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 645f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public void sort() 646f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 647f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling // sort qualifier 648f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling if (hasQualifier()) 649f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 650f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling XMPNode[] quals = (XMPNode[]) getQualifier() 651f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling .toArray(new XMPNode[getQualifierLength()]); 652f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling int sortFrom = 0; 653f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling while ( 654f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling quals.length > sortFrom && 655f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling (XMPConst.XML_LANG.equals(quals[sortFrom].getName()) || 656f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling "rdf:type".equals(quals[sortFrom].getName())) 657f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling ) 658f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 659f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling quals[sortFrom].sort(); 660f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling sortFrom++; 661f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 662f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 663f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling Arrays.sort(quals, sortFrom, quals.length); 664f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling ListIterator it = qualifier.listIterator(); 665f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling for (int j = 0; j < quals.length; j++) 666f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 667f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling it.next(); 668f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling it.set(quals[j]); 669f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling quals[j].sort(); 670f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 671f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 672f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 673f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling // sort children 674f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling if (hasChildren()) 675f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 676f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling if (!getOptions().isArray()) 677f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 678f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling Collections.sort(children); 679f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 680f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling for (Iterator it = iterateChildren(); it.hasNext();) 681f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 682f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling ((XMPNode) it.next()).sort(); 683f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 684f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 685f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 686f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 687f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 688f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 689f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 690f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling //------------------------------------------------------------------------------ private methods 691f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 692f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 693f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 694f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * Dumps this node and its qualifier and children recursively. 695f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * <em>Note:</em> It creats empty options on every node. 696f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * 697f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param result the buffer to append the dump. 698f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param recursive Flag is qualifier and child nodes shall be rendered too 699f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param indent the current indent level. 700f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param index the index within the parent node (important for arrays) 701f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 702f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling private void dumpNode(StringBuffer result, boolean recursive, int indent, int index) 703f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 704f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling // write indent 705f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling for (int i = 0; i < indent; i++) 706f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 707f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling result.append('\t'); 708f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 709f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 710f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling // render Node 711f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling if (parent != null) 712f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 713f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling if (getOptions().isQualifier()) 714f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 715f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling result.append('?'); 716f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling result.append(name); 717f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 718f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling else if (getParent().getOptions().isArray()) 719f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 720f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling result.append('['); 721f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling result.append(index); 722f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling result.append(']'); 723f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 724f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling else 725f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 726f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling result.append(name); 727f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 728f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 729f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling else 730f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 731f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling // applies only to the root node 732f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling result.append("ROOT NODE"); 733f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling if (name != null && name.length() > 0) 734f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 735f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling // the "about" attribute 736f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling result.append(" ("); 737f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling result.append(name); 738f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling result.append(')'); 739f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 740f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 741f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 742f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling if (value != null && value.length() > 0) 743f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 744f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling result.append(" = \""); 745f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling result.append(value); 746f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling result.append('"'); 747f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 748f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 749f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling // render options if at least one is set 750f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling if (getOptions().containsOneOf(0xffffffff)) 751f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 752f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling result.append("\t("); 753f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling result.append(getOptions().toString()); 754f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling result.append(" : "); 755f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling result.append(getOptions().getOptionsString()); 756f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling result.append(')'); 757f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 758f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 759f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling result.append('\n'); 760f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 761f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling // render qualifier 762f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling if (recursive && hasQualifier()) 763f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 764f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling XMPNode[] quals = (XMPNode[]) getQualifier() 765f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling .toArray(new XMPNode[getQualifierLength()]); 766f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling int i = 0; 767f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling while (quals.length > i && 768f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling (XMPConst.XML_LANG.equals(quals[i].getName()) || 769f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling "rdf:type".equals(quals[i].getName())) 770f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling ) 771f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 772f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling i++; 773f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 774f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling Arrays.sort(quals, i, quals.length); 775f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling for (i = 0; i < quals.length; i++) 776f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 777f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling XMPNode qualifier = quals[i]; 778f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling qualifier.dumpNode(result, recursive, indent + 2, i + 1); 779f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 780f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 781f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 782f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling // render children 783f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling if (recursive && hasChildren()) 784f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 785f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling XMPNode[] children = (XMPNode[]) getChildren() 786f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling .toArray(new XMPNode[getChildrenLength()]); 787f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling if (!getOptions().isArray()) 788f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 789f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling Arrays.sort(children); 790f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 791f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling for (int i = 0; i < children.length; i++) 792f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 793f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling XMPNode child = children[i]; 794f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling child.dumpNode(result, recursive, indent + 1, i + 1); 795f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 796f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 797f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 798f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 799f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 800f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 801f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @return Returns whether this node is a language qualifier. 802f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 803f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling private boolean isLanguageNode() 804f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 805f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return XMPConst.XML_LANG.equals(name); 806f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 807f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 808f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 809f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 810f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @return Returns whether this node is a type qualifier. 811f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 812f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling private boolean isTypeNode() 813f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 814f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return "rdf:type".equals(name); 815f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 816f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 817f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 818f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 819f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * <em>Note:</em> This method should always be called when accessing 'children' to be sure 820f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * that its initialized. 821f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @return Returns list of children that is lazy initialized. 822f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 823f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling private List getChildren() 824f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 825f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling if (children == null) 826f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 827f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling children = new ArrayList(0); 828f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 829f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return children; 830f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 831f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 832f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 833f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 834f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @return Returns a read-only copy of child nodes list. 835f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 836f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling public List getUnmodifiableChildren() 837f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 838f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return Collections.unmodifiableList(new ArrayList(getChildren())); 839f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 840f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 841f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 842f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 843f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @return Returns list of qualifier that is lazy initialized. 844f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 845f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling private List getQualifier() 846f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 847f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling if (qualifier == null) 848f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 849f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling qualifier = new ArrayList(0); 850f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 851f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return qualifier; 852f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 853f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 854f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 855f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 856f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * Sets the parent node, this is solely done by <code>addChild(...)</code> 857f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * and <code>addQualifier()</code>. 858f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * 859f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param parent 860f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * Sets the parent node. 861f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 862f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling protected void setParent(XMPNode parent) 863f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 864f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling this.parent = parent; 865f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 866f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 867f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 868f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 869f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * Internal find. 870f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param list the list to search in 871f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param expr the search expression 872f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @return Returns the found node or <code>nulls</code>. 873f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 874f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling private XMPNode find(List list, String expr) 875f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 876f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 877f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling if (list != null) 878f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 879f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling for (Iterator it = list.iterator(); it.hasNext();) 880f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 881f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling XMPNode child = (XMPNode) it.next(); 882f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling if (child.getName().equals(expr)) 883f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 884f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return child; 885f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 886f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 887f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 888f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling return null; 889f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 890f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 891f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 892f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 893f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * Checks that a node name is not existing on the same level, except for array items. 894f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param childName the node name to check 895f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @throws XMPException Thrown if a node with the same name is existing. 896f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 897f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling private void assertChildNotExisting(String childName) throws XMPException 898f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 899f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling if (!XMPConst.ARRAY_ITEM_NAME.equals(childName) && 900f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling findChildByName(childName) != null) 901f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 902f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling throw new XMPException("Duplicate property or field node '" + childName + "'", 903f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling XMPError.BADXMP); 904f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 905f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 906f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 907f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling 908f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling /** 909f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * Checks that a qualifier name is not existing on the same level. 910f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @param qualifierName the new qualifier name 911f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling * @throws XMPException Thrown if a node with the same name is existing. 912f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling */ 913f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling private void assertQualifierNotExisting(String qualifierName) throws XMPException 914f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 915f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling if (!XMPConst.ARRAY_ITEM_NAME.equals(qualifierName) && 916f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling findQualifierByName(qualifierName) != null) 917f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling { 918f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling throw new XMPException("Duplicate '" + qualifierName + "' qualifier", XMPError.BADXMP); 919f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 920f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling } 921f12f744843a67c910ec325fc6dfa73988f67b97cSascha Haeberling}