All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opensaml.xml.util.IndexedXMLObjectChildrenList Maven / Gradle / Ivy

Go to download

XMLTooling-J is a low-level library that may be used to construct libraries that allow developers to work with XML in a Java beans manner.

There is a newer version: 1.4.2
Show newest version
/*
 * Licensed to the University Corporation for Advanced Internet Development, 
 * Inc. (UCAID) under one or more contributor license agreements.  See the 
 * NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The UCAID licenses this file to You under the Apache 
 * License, Version 2.0 (the "License"); you may not use this file except in 
 * compliance with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.opensaml.xml.util;

import java.util.AbstractList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import javax.xml.namespace.QName;

import net.jcip.annotations.NotThreadSafe;

import org.opensaml.xml.XMLObject;

/**
 * A list which indexes XMLObjects by their schema type and element QName for quick retrival based on those items.
 * 
 * @param  the type of element added to the list
 */
@NotThreadSafe
public class IndexedXMLObjectChildrenList extends XMLObjectChildrenList {

    /** Index of objects by type and name. */
    private Map> objectIndex;

    /**
     * Constructor.
     * 
     * @param parent the parent of the {@link XMLObject}s added to the list
     */
    public IndexedXMLObjectChildrenList(XMLObject parent) {
        super(parent);
        objectIndex = new LazyMap>();
    }

    /**
     * Constructor.
     * 
     * @param parent the parent of all elements
     * @param col collection to add to this list
     */
    public IndexedXMLObjectChildrenList(XMLObject parent, Collection col) {
        super(parent);
        objectIndex = new LazyMap>();
        addAll(col);
    }

    /**
     * Inserts the specified element at the specified position in this list. Shifts the element currently at that
     * position (if any) and any subsequent elements to the right (adds one to their indices).
     * 
     * @param index index of element to add
     * @param element element to be stored at the specified position
     */
    public void add(int index, ElementType element) {
        super.add(index, element);
        indexElement(element);
    }

    /** {@inheritDoc} */
    public void clear() {
        super.clear();
        objectIndex.clear();
    }

    /**
     * Retrieves all the SAMLObjects that have given schema type or element name.
     * 
     * @param typeOrName the schema type or element name
     * 
     * @return list of SAMLObjects that have given schema type or element name, which may be empty.
     *         Will not be null.
     */
    public List get(QName typeOrName) {
        checkAndCreateIndex(typeOrName);
        return objectIndex.get(typeOrName);
    }

    /**
     * Check for the existence of an index for the specified QName and create it
     * if it doesn't exist.
     * 
     * @param index the index to check
     */
    protected void checkAndCreateIndex(QName index) {
        if (!objectIndex.containsKey(index)) {
            objectIndex.put(index, new LazyList());
        }
    }

    /**
     * Indexes the given SAMLObject by type and element name.
     * 
     * @param element the SAMLObject to index
     */
    protected void indexElement(ElementType element) {
        if (element == null) {
            return;
        }

        QName type = element.getSchemaType();
        if (type != null) {
            indexElement(type, element);
        }

        indexElement(element.getElementQName(), element);
    }

    /**
     * Indexes the given SAMLobject by the given index.
     * 
     * @param index the index for the element
     * @param element the element to be indexed
     */
    protected void indexElement(QName index, ElementType element) {
        List objects = get(index);
        objects.add(element);
    }

    /**
     * Removes a given element from the list and index.
     * 
     * @param element the element to be removed
     * 
     * @return true if the element was in the list and removed, false if not
     */
    public boolean remove(ElementType element) {
        boolean elementRemoved = false;

        elementRemoved = super.remove(element);
        if (elementRemoved) {
            removeElementFromIndex(element);
        }

        return elementRemoved;
    }

    /**
     * Removes the element at the specified position in this list. Shifts any subsequent elements to the left (subtracts
     * one from their indices). Returns the element that was removed from the list
     * 
     * @param index the index of the element to remove
     * 
     * @return the element removed from the list
     */
    public ElementType remove(int index) {
        ElementType returnValue = super.remove(index);

        removeElementFromIndex(returnValue);

        return returnValue;
    }

    /**
     * Removes the given element from the schema type and element qname index.
     * 
     * @param element the element to remove from the index
     */
    protected void removeElementFromIndex(ElementType element) {
        if (element == null) {
            return;
        }

        QName type = element.getSchemaType();
        if (type != null) {
            removeElementFromIndex(type, element);
        }

        removeElementFromIndex(element.getElementQName(), element);
    }

    /**
     * Removes an object from the given index id.
     * 
     * @param index the id of the index
     * @param element the element to be removed from that index
     */
    protected void removeElementFromIndex(QName index, ElementType element) {
        List objects = get(index);
        objects.remove(element);
    }

    /**
     * Replaces the element at the specified position in this list with the specified element.
     * 
     * @param index index of element to replace
     * @param element element to be stored at the specified position
     * 
     * @return the element previously at the specified position
     */
    public ElementType set(int index, ElementType element) {
        ElementType returnValue = super.set(index, element);

        removeElementFromIndex(returnValue);

        indexElement(element);
        return returnValue;
    }

    /**
     * Returns a view of the list that only contains elements stored under the given index. The returned list is backed
     * by this list so and supports all optional operations, so changes made to the returned list are reflected in this
     * list.
     * 
     * @param index index of the elements returned in the list view
     * 
     * @return a view of this list that contains only the elements stored under the given index
     */
    public List subList(QName index) {
        checkAndCreateIndex(index);
        return new ListView(this, index);
    }
}

/**
 * A special list that works as a view of an IndexedXMLObjectChildrenList showing only the sublist associated with a
 * given index. Operations performed on this sublist are reflected in the backing list. Index-based mutation operations
 * are not supported.
 * 
 * @param  the XMLObject type that this list operates on
 */
class ListView extends AbstractList {

    /** List that backs this view. */
    private IndexedXMLObjectChildrenList backingList;

    /** Index that points to the list, in the backing list, that this view operates on. */
    private QName index;

    /** List, in the backing list, that the given index points to. */
    private List indexList;

    /**
     * Constructor.
     * 
     * @param newBackingList the list that backs this view
     * @param newIndex the element schema type or name of the sublist this view operates on
     */
    public ListView(IndexedXMLObjectChildrenList newBackingList, QName newIndex) {
        backingList = newBackingList;
        index = newIndex;
        indexList = backingList.get(index);
    }

    /** {@inheritDoc} */
    public boolean add(ElementType o) {
        boolean result = backingList.add(o);
        indexList = backingList.get(index);
        return result;
    }

    /** {@inheritDoc} */
    public void add(int newIndex, ElementType element) {
        throw new UnsupportedOperationException();
    }

    /** {@inheritDoc} */
    public boolean addAll(Collection c) {
        boolean result = backingList.addAll(c);
        indexList = backingList.get(index);
        return result;
    }

    /** {@inheritDoc} */
    public boolean addAll(int index, Collection c) {
        throw new UnsupportedOperationException();
    }

    /** {@inheritDoc} */
    public void clear() {
        // Create a copy of the current list to avoid a potential concurrent modification error.
        LazyList copy = new LazyList();
        copy.addAll(indexList);
        backingList.removeAll(copy);
        indexList = backingList.get(index);
    }

    /**
     * Checks to see if the given element is contained in this list.
     * 
     * @param element the element to check for
     * 
     * @return true if the element is in this list, false if not
     */
    public boolean contains(Object element) {
        return indexList.contains(element);
    }

    /** {@inheritDoc} */
    public boolean containsAll(Collection c) {
        return indexList.containsAll(c);
    }

    /** {@inheritDoc} */
    public ElementType get(int newIndex) {
        return indexList.get(newIndex);
    }

    /** {@inheritDoc} */
    public int indexOf(Object o) {
        return indexList.indexOf(o);
    }

    /** {@inheritDoc} */
    public boolean isEmpty() {
        return indexList.isEmpty();
    }

    /** {@inheritDoc} */
    public int lastIndexOf(Object o) {
        return indexList.lastIndexOf(o);
    }

    /** {@inheritDoc} */
    public ElementType remove(int newIndex) {
        throw new UnsupportedOperationException();
    }

    /** {@inheritDoc} */
    public boolean remove(Object o) {
        boolean result = backingList.remove(o);
        indexList = backingList.get(index);
        return result;
    }

    /** {@inheritDoc} */
    public boolean removeAll(Collection c) {
        boolean result = backingList.removeAll(c);
        indexList = backingList.get(index);
        return result;
    }

    /** {@inheritDoc} */
    public boolean retainAll(Collection c) {
        boolean result = backingList.retainAll(c);
        indexList = backingList.get(index);
        return result;
    }

    /** {@inheritDoc} */
    public ElementType set(int newIndex, ElementType element) {
        throw new UnsupportedOperationException();
    }

    /** {@inheritDoc} */
    public int size() {
        return indexList.size();
    }

    /** {@inheritDoc} */
    public Object[] toArray() {
        return indexList.toArray();
    }

    /** {@inheritDoc} */
    public  T[] toArray(T[] a) {
        return indexList.toArray(a);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy