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