1 /* 2 * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.] 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 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package org.opensaml.xml.util; 18 19 import java.util.AbstractList; 20 import java.util.Collection; 21 import java.util.LinkedList; 22 import java.util.List; 23 24 import org.opensaml.xml.XMLObject; 25 26 /** 27 * Resizable list for the children of XMLObjects. This list implements all optional List operations and does not all for 28 * null elements. XMLObjects added to, or removed from, this list will have their parent object appropriately set and, 29 * the underlying DOM will be released during mutation opertions. 30 * 31 * @param <ElementType> type of elements added to the list 32 */ 33 public class XMLObjectChildrenList<ElementType extends XMLObject> extends AbstractList<ElementType> { 34 35 /** Parent to the elements in this list. */ 36 private XMLObject parent; 37 38 /** List of elements. */ 39 private List<ElementType> elements; 40 41 /** 42 * Constructs an empty list with all added XMLObjects being assigned the given parent XMLObject. 43 * 44 * @param newParent the parent for all the added XMLObjects 45 * 46 * @throws NullPointerException thrown if the parent is null 47 */ 48 public XMLObjectChildrenList(XMLObject newParent) throws NullPointerException { 49 if (newParent == null) { 50 throw new NullPointerException("Parent may not be null"); 51 } 52 53 parent = newParent; 54 elements = new LinkedList<ElementType>(); 55 } 56 57 /** 58 * Constructs a list containing the elements in the specified collection, in the order they are returned by the 59 * collection's iterator, with each added XMLObject assigned the given parent XMLObject. 60 * 61 * @param newParent the parent for all the added XMLObjects 62 * @param newElements the elements to be added 63 * 64 * @throws NullPointerException thrown if the parent is null 65 * @throws IllegalArgumentException thrown if any of the XMLObjects in the given collection already have a parent 66 * that is different from the given parent 67 */ 68 public XMLObjectChildrenList(XMLObject newParent, Collection<ElementType> newElements) throws NullPointerException { 69 if (newParent == null) { 70 throw new NullPointerException("Parent may not be null"); 71 } 72 73 parent = newParent; 74 elements = new LinkedList<ElementType>(); 75 76 addAll(newElements); 77 } 78 79 /** {@inheritDoc} */ 80 public int size() { 81 return elements.size(); 82 } 83 84 /** 85 * Checks to see if the given element is contained in this list. 86 * 87 * @param element the element to check for 88 * 89 * @return true if the element is in this list, false if not 90 */ 91 public boolean contains(ElementType element) { 92 return elements.contains(element); 93 } 94 95 /** {@inheritDoc} */ 96 public ElementType get(int index) { 97 return elements.get(index); 98 } 99 100 /** 101 * Replaces the XMLObject at the specified index with the given element. 102 * 103 * @param index index of the XMLObject to be replaced 104 * @param element element to be stored at the given index 105 * 106 * @return the replaced XMLObject 107 * 108 * @throws IllegalArgumentException thrown if the given XMLObject already has a parent that is different from the 109 * XMLObject given at list construction time 110 */ 111 public ElementType set(int index, ElementType element) throws IllegalArgumentException { 112 if (element == null) { 113 return null; 114 } 115 116 setParent(element); 117 118 ElementType removedElement = elements.set(index, element); 119 if (removedElement != null) { 120 removedElement.setParent(null); 121 parent.getIDIndex().deregisterIDMappings(removedElement.getIDIndex()); 122 } 123 124 // Note: to avoid ordering problems, this needs to be called after 125 // the deregistration, in case the added element has a same ID string 126 // value as the removed one, else you will lose it. 127 parent.getIDIndex().registerIDMappings(element.getIDIndex()); 128 129 modCount++; 130 return removedElement; 131 } 132 133 /** 134 * Adds the given XMLObject to this list. 135 * 136 * @param index index at which to add the given XMLObject 137 * @param element element to be stored at the given index 138 * 139 * @throws IllegalArgumentException thrown if the given XMLObject already has a parent that is different from the 140 * XMLObject given at list construction time 141 */ 142 public void add(int index, ElementType element) throws IllegalArgumentException { 143 if (element == null || elements.contains(element)) { 144 return; 145 } 146 147 setParent(element); 148 parent.getIDIndex().registerIDMappings(element.getIDIndex()); 149 150 modCount++; 151 elements.add(index, element); 152 } 153 154 /** {@inheritDoc} */ 155 public ElementType remove(int index) { 156 ElementType element = elements.remove(index); 157 158 if (element != null) { 159 element.releaseParentDOM(true); 160 element.setParent(null); 161 parent.getIDIndex().deregisterIDMappings(element.getIDIndex()); 162 } 163 164 modCount++; 165 return element; 166 } 167 168 /** 169 * Removes the element from the list. 170 * 171 * @param element the element to be removed 172 * 173 * @return true if the element was in the list and removed, false if not 174 */ 175 public boolean remove(ElementType element) { 176 boolean elementRemoved = false; 177 178 elementRemoved = elements.remove(element); 179 if (elementRemoved) { 180 if (element != null) { 181 element.releaseParentDOM(true); 182 element.setParent(null); 183 parent.getIDIndex().deregisterIDMappings(element.getIDIndex()); 184 } 185 } 186 187 return elementRemoved; 188 } 189 190 /** 191 * Assigned the parent, given at list construction, to the given element if the element does not have a parent or 192 * its parent matches the one given at list construction time. 193 * 194 * @param element the element to set the parent on 195 * 196 * @throws IllegalArgumentException thrown if the given element already has a parent and it is different than the 197 * parent given at list construction time 198 */ 199 protected void setParent(ElementType element) throws IllegalArgumentException { 200 XMLObject elemParent = element.getParent(); 201 if (elemParent != null && elemParent != parent) { 202 throw new IllegalArgumentException(element.getElementQName() 203 + " is already the child of another XMLObject and may not be inserted in to this list"); 204 } 205 206 element.setParent(parent); 207 element.releaseParentDOM(true); 208 } 209 }