| /* |
| * $Id$ |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF 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.apache.tiles.request.collection; |
| |
| import static org.apache.tiles.request.util.RequestUtil.*; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Enumeration; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.apache.tiles.request.attribute.EnumeratedValuesExtractor; |
| |
| |
| /** |
| * Exposes an {@link EnumeratedValuesExtractor} object as a read-only map. |
| * |
| * @version $Rev$ $Date$ |
| */ |
| public class HeaderValuesMap implements Map<String, String[]> { |
| |
| /** |
| * The request. |
| */ |
| private EnumeratedValuesExtractor request; |
| |
| /** |
| * Constructor. |
| * |
| * @param request The request object to use. |
| */ |
| public HeaderValuesMap(EnumeratedValuesExtractor request) { |
| this.request = request; |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public void clear() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public boolean containsKey(Object key) { |
| return (request.getValue(key(key)) != null); |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public boolean containsValue(Object value) { |
| if (!(value instanceof String[])) { |
| return (false); |
| } |
| String[] test = (String[]) value; |
| Enumeration<String> names = request.getKeys(); |
| while (names.hasMoreElements()) { |
| String name = names.nextElement(); |
| if (compareHeaders(name, array2set(test))) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public Set<Map.Entry<String, String[]>> entrySet() { |
| return new HeadersEntrySet(); |
| } |
| |
| |
| /** {@inheritDoc} */ |
| @Override |
| public boolean equals(Object o) { |
| EnumeratedValuesExtractor otherRequest = ((HeaderValuesMap) o).request; |
| boolean retValue = true; |
| for (Enumeration<String> attribs = request.getKeys(); attribs |
| .hasMoreElements() |
| && retValue;) { |
| String parameterName = attribs.nextElement(); |
| Set<String> valueSet = enumeration2set(otherRequest.getValues(parameterName)); |
| retValue = compareHeaders(parameterName, valueSet); |
| } |
| |
| return retValue; |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public String[] get(Object key) { |
| return getHeaderValues(key(key)); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public int hashCode() { |
| int retValue = 0; |
| for (Enumeration<String> attribs = request.getKeys(); attribs |
| .hasMoreElements();) { |
| String parameterName = attribs.nextElement(); |
| Enumeration<String> values = request.getValues(parameterName); |
| int valueHash = 0; |
| while (values.hasMoreElements()) { |
| valueHash += values.nextElement().hashCode(); |
| } |
| retValue += parameterName.hashCode() ^ valueHash; |
| } |
| return retValue; |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public boolean isEmpty() { |
| return !request.getKeys().hasMoreElements(); |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public Set<String> keySet() { |
| return new KeySet(request); |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public String[] put(String key, String[] value) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public void putAll(Map<? extends String, ? extends String[]> map) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public String[] remove(Object key) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| |
| |
| /** {@inheritDoc} */ |
| public int size() { |
| return enumerationSize(request.getKeys()); |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public Collection<String[]> values() { |
| return new HeaderValuesCollection(); |
| } |
| |
| /** |
| * Extracts values enumeration of an attribute and returns the corresponding array of values. |
| * |
| * @param key The key of the attribute. |
| * @return The values of the attribute. |
| */ |
| private String[] getHeaderValues(String key) { |
| List<String> list = new ArrayList<String>(); |
| Enumeration<String> values = request.getValues(key); |
| while (values.hasMoreElements()) { |
| list.add(values.nextElement()); |
| } |
| String[] retValue = list.toArray(new String[list.size()]); |
| return retValue; |
| } |
| |
| /** |
| * Converts the content of a string enumeration to an array of strings. |
| * |
| * @param enumeration The enumeration to convert. |
| * @return The corresponding array. |
| */ |
| private Set<String> enumeration2set(Enumeration<String> enumeration) { |
| Set<String> retValue = new HashSet<String>(); |
| while (enumeration.hasMoreElements()) { |
| retValue.add(enumeration.nextElement()); |
| } |
| return retValue; |
| } |
| |
| /** |
| * Transforms a string array in a string set. |
| * |
| * @param valueArray The array to convert. |
| * @return The corresponding set. |
| */ |
| private Set<String> array2set(String[] valueArray) { |
| Set<String> values = new HashSet<String>(); |
| for (int i = 0; i < valueArray.length; i++) { |
| values.add(valueArray[i]); |
| } |
| return values; |
| } |
| |
| /** |
| * Checks if values of a header attribute are the same as the one passed in |
| * the set. |
| * |
| * @param name The name of the header. |
| * @param testSet The set of values it must contain. |
| * @return <code>true</code> if all the values, and only them, are present |
| * in the header values. |
| */ |
| private boolean compareHeaders(String name, Set<String> testSet) { |
| Enumeration<String> values = request.getValues(name); |
| boolean matched = true; |
| while (values.hasMoreElements() && matched) { |
| String currentValue = values.nextElement(); |
| matched = testSet.remove(currentValue); |
| } |
| matched = matched && testSet.isEmpty(); |
| return matched; |
| } |
| |
| /** |
| * Entry set implementation for {@link HeaderValuesMap}. |
| */ |
| private class HeadersEntrySet implements Set<Map.Entry<String, String[]>> { |
| |
| @Override |
| public boolean add(java.util.Map.Entry<String, String[]> e) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public boolean addAll( |
| Collection<? extends java.util.Map.Entry<String, String[]>> c) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public void clear() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @SuppressWarnings("unchecked") |
| @Override |
| public boolean contains(Object o) { |
| return containsEntry((java.util.Map.Entry<String, String[]>) o); |
| } |
| |
| @SuppressWarnings("unchecked") |
| @Override |
| public boolean containsAll(Collection<?> c) { |
| Collection<Map.Entry<String, String[]>> realCollection = |
| (Collection<Map.Entry<String, String[]>>) c; |
| for (Map.Entry<String, String[]> entry : realCollection) { |
| if (!containsEntry(entry)) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| @Override |
| public boolean isEmpty() { |
| return HeaderValuesMap.this.isEmpty(); |
| } |
| |
| @Override |
| public Iterator<java.util.Map.Entry<String, String[]>> iterator() { |
| return new HeadersEntrySetIterator(); |
| } |
| |
| @Override |
| public boolean remove(Object o) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public boolean removeAll(Collection<?> c) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public boolean retainAll(Collection<?> c) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public int size() { |
| return HeaderValuesMap.this.size(); |
| } |
| |
| @Override |
| public Object[] toArray() { |
| return toList().toArray(); |
| } |
| |
| @Override |
| public <T> T[] toArray(T[] a) { |
| return toList().toArray(a); |
| } |
| |
| /** |
| * Checks whether the given entry is present in the headers. |
| * |
| * @param entry The entry to check. |
| * @return <code></code> if the key and the values of the entry are present. |
| */ |
| private boolean containsEntry(Map.Entry<String, String[]> entry) { |
| Enumeration<String> entryValues = request.getValues(key(entry.getKey())); |
| String[] valueArray = entry.getValue(); |
| Set<String> values = array2set(valueArray); |
| while (entryValues.hasMoreElements()) { |
| if (!values.remove(entryValues.nextElement())) { |
| return false; |
| } |
| } |
| return values.isEmpty(); |
| } |
| |
| /** |
| * Turns this entry set into a list. |
| * |
| * @return The collection, turned into a list. |
| */ |
| private List<Map.Entry<String, String[]>> toList() { |
| List<Map.Entry<String, String[]>> entries = new ArrayList<Map.Entry<String, String[]>>(); |
| Enumeration<String> names = request.getKeys(); |
| while (names.hasMoreElements()) { |
| entries.add(extractNextEntry(names)); |
| } |
| return entries; |
| } |
| |
| /** |
| * Returns the next entry, by getting the next element in the given enumeration. |
| * |
| * @param names The enumeration to get the next name from.. |
| * @return The next map entry. |
| */ |
| private MapEntry<String, String[]> extractNextEntry( |
| Enumeration<String> names) { |
| String name = names.nextElement(); |
| return new MapEntryArrayValues<String, String>(name, getHeaderValues(name), false); |
| } |
| |
| /** |
| * Iterates {@link HeadersEntrySet} elements. |
| */ |
| private class HeadersEntrySetIterator implements Iterator<Map.Entry<String, String[]>> { |
| |
| /** |
| * The enumeration to use. |
| */ |
| private Enumeration<String> namesEnumeration = request.getKeys(); |
| |
| @Override |
| public boolean hasNext() { |
| return namesEnumeration.hasMoreElements(); |
| } |
| |
| @Override |
| public Map.Entry<String, String[]> next() { |
| return extractNextEntry(namesEnumeration); |
| } |
| |
| @Override |
| public void remove() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| } |
| } |
| |
| /** |
| * It is a collection of all values of the header. Each element is an array |
| * of values of a single header. |
| */ |
| private class HeaderValuesCollection implements Collection<String[]> { |
| |
| @Override |
| public boolean add(String[] e) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public boolean addAll(Collection<? extends String[]> c) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public void clear() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public boolean contains(Object o) { |
| return containsValue(o); |
| } |
| |
| @SuppressWarnings("unchecked") |
| @Override |
| public boolean containsAll(Collection<?> c) { |
| Collection<String[]> realCollection = (Collection<String[]>) c; |
| for (String[] value : realCollection) { |
| if (!containsValue(value)) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| @Override |
| public boolean isEmpty() { |
| return HeaderValuesMap.this.isEmpty(); |
| } |
| |
| @Override |
| public Iterator<String[]> iterator() { |
| return new HeaderValuesCollectionIterator(); |
| } |
| |
| @Override |
| public boolean remove(Object o) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public boolean removeAll(Collection<?> c) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public boolean retainAll(Collection<?> c) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public int size() { |
| return HeaderValuesMap.this.size(); |
| } |
| |
| @Override |
| public Object[] toArray() { |
| return toList().toArray(); |
| } |
| |
| @Override |
| public <T> T[] toArray(T[] a) { |
| return toList().toArray(a); |
| } |
| |
| /** |
| * Turns this collection into a list. |
| * |
| * @return The list. |
| */ |
| private List<String[]> toList() { |
| List<String[]> entries = new ArrayList<String[]>(); |
| Enumeration<String> names = request.getKeys(); |
| while (names.hasMoreElements()) { |
| entries.add(enumeration2array(request.getValues(names.nextElement()))); |
| } |
| return entries; |
| } |
| |
| /** |
| * Converts the content of a string enumeration to an array of strings. |
| * |
| * @param enumeration The enumeration to convert. |
| * @return The corresponding array. |
| */ |
| private String[] enumeration2array(Enumeration<String> enumeration) { |
| List<String> list1 = new ArrayList<String>(); |
| while (enumeration.hasMoreElements()) { |
| list1.add(enumeration.nextElement()); |
| } |
| |
| return list1.toArray(new String[list1.size()]); |
| } |
| |
| /** |
| * Iterates elements of {@link HeaderValuesCollection}. |
| */ |
| private class HeaderValuesCollectionIterator implements Iterator<String[]> { |
| |
| /** |
| * The enumeration of the name of header attributes. |
| */ |
| private Enumeration<String> namesEnumeration = request.getKeys(); |
| |
| @Override |
| public boolean hasNext() { |
| return namesEnumeration.hasMoreElements(); |
| } |
| |
| @Override |
| public String[] next() { |
| return enumeration2array(request.getValues(namesEnumeration.nextElement())); |
| } |
| |
| @Override |
| public void remove() { |
| throw new UnsupportedOperationException(); |
| } |
| } |
| } |
| } |