FileDocCategorySizeDatePackage
MultiMap.javaAPI DocGlassfish v2 API7407Fri May 04 22:33:14 BST 2007org.apache.tomcat.util.collections

MultiMap

public class MultiMap extends Object
An efficient representation for certain type of map. The keys can have a single or multi values, but most of the time there are single values. The data is of "MessageBytes" type, meaning bytes[] that can be converted to Strings ( if needed, and encoding is lazy-binded ). This is a base class for MimeHeaders, Parameters and Cookies. Data structures: each field is a single-valued key/value. The fields are allocated when needed, and are recycled. The current implementation does linear search, in future we'll also use the hashkey.
author
dac@eng.sun.com
author
James Todd [gonzo@eng.sun.com]
author
Costin Manolache

Fields Summary
protected Field[]
fields
protected int
count
static final int
NEED_NEXT
static final int
LAST
Constructors Summary
public MultiMap(int initial_size)

	fields=new Field[initial_size];
    
Methods Summary
public intaddField()
Create a new, unitialized entry.

	int len = fields.length;
	int pos=count;
	if (count >= len) {
	    // expand header list array
	    Field tmp[] = new Field[pos * 2];
	    System.arraycopy(fields, 0, tmp, 0, len);
	    fields = tmp;
	}
	if (fields[pos] == null) {
	    fields[pos] = new Field();
	}
	count++;
	return pos;
    
public intfind(java.lang.String name, int starting)
Find the index of a field with the given name.

	// We can use a hash - but it's not clear how much
	// benefit you can get - there is an  overhead 
	// and the number of headers is small (4-5 ?)
	// Another problem is that we'll pay the overhead
	// of constructing the hashtable

	// A custom search tree may be better
        for (int i = starting; i < count; i++) {
	    if (fields[i].name.equals(name)) {
                return i;
            }
        }
        return -1;
    
public intfindFirst(java.lang.String name)

        for (int i = 0; i < count; i++) {
	    if (fields[i].name.equals(name)) {
		return i;
	    }
	}
        return -1;
    
public intfindIgnoreCase(java.lang.String name, int starting)
Find the index of a field with the given name.

	// We can use a hash - but it's not clear how much
	// benefit you can get - there is an  overhead 
	// and the number of headers is small (4-5 ?)
	// Another problem is that we'll pay the overhead
	// of constructing the hashtable

	// A custom search tree may be better
        for (int i = starting; i < count; i++) {
	    if (fields[i].name.equalsIgnoreCase(name)) {
                return i;
            }
        }
        return -1;
    
public intfindNext(int startPos)

	int next= fields[startPos].nextPos;
	if( next != MultiMap.NEED_NEXT ) {
	    return next;
	}

	// next==NEED_NEXT, we never searched for this header
	MessageBytes name=fields[startPos].name;
        for (int i = startPos; i < count; i++) {
	    if (fields[i].name.equals(name)) {
		// cache the search result
		fields[startPos].nextPos=i;
		return i;
	    }
	}
	fields[startPos].nextPos= MultiMap.LAST;
        return -1;
    
public org.apache.tomcat.util.buf.MessageBytesget(java.lang.String name)

        for (int i = 0; i < count; i++) {
	    if (fields[i].name.equals(name)) {
		return fields[i].value;
	    }
	}
        return null;
    
public org.apache.tomcat.util.buf.MessageBytesgetName(int n)
Returns the Nth header name This may be used to iterate through all header fields. An exception is thrown if the index is not valid ( <0 or >size )

	// n >= 0 && n < count ? headers[n].getName() : null
	return fields[n].name;
    
public org.apache.tomcat.util.buf.MessageBytesgetValue(int n)
Returns the Nth header value This may be used to iterate through all header fields.

	return fields[n].value;
    
public voidrecycle()
Clears all header fields.

	for (int i = 0; i < count; i++) {
	    fields[i].recycle();
	}
	count = 0;
    
public voidremove(int i)
Removes the field at the specified position. MultiMap will preserve the order of field add unless remove() is called. This is not thread-safe, and will invalidate all iterators. This is not a frequent operation for Headers and Parameters - there are better ways ( like adding a "isValid" field )

	// reset and swap with last header
	Field mh = fields[i];
	// reset the field
	mh.recycle();
	
	fields[i] = fields[count - 1];
	fields[count - 1] = mh;
	count--;
    
public intsize()
Returns the current number of header fields.

	return count;