You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@turbine.apache.org by "Henning P. Schmiedehausen" <ma...@hometree.net> on 2001/06/01 16:18:52 UTC

SequencedHashtable

Hi,

I might be wrong, but this looks bogus to me in SequencedHashtable.

/**
 * Slightly cheaper implementation of <code>values()</code> method.
 */
public Collection values ()
{
    return keySequence;
}

because in keySequence are the keys stored. This would be some sort
of 

public List keyList()
{
    return keySequence;
}


A demo program seems to confirm this:

--- cut ---
import java.util.Hashtable;
import java.util.Iterator;

import org.apache.turbine.util.SequencedHashtable;

public class sequencetest
{
  public static void main(String[] args)
  {
    Hashtable ht = new Hashtable();
    SequencedHashtable sht = new SequencedHashtable();

    for(int i = 0; i < 10; i++)
    {
      ht.put("Key "+Integer.toString(i), "Value "+Integer.toString(i));
      sht.put("Key "+Integer.toString(i), "Value "+Integer.toString(i));
    }

    Iterator it;

    System.out.println("Hashtable:");
    it = ht.values().iterator();

    while(it.hasNext())
      System.out.println(it.next());

    System.out.println("Seq.Hashtable:");
    it = sht.values().iterator();

    while(it.hasNext())
      System.out.println(it.next());
  }
}
--- cut ---

Hashtable:
Value 4
Value 3
Value 2
Value 1
Value 0
Value 9
Value 8
Value 7
Value 6
Value 5

Seq.Hashtable:
Key 0
Key 1
Key 2
Key 3
Key 4
Key 5
Key 6
Key 7
Key 8
Key 9

Not the same. Patch attached. I thought about deprecation but removing
the values() method makes the original method from Hashtable visible
again which is a good thing.

By applying this patch, the whole SequencedHashtable shebang suddently
gets usable for me to replace lots of "keep list and hashtable around"
situations. ;-)

	Regards
		Henning

Index: SequencedHashtable.java
===================================================================
RCS file: /home/cvspublic/jakarta-turbine/src/java/org/apache/turbine/util/SequencedHashtable.java,v
retrieving revision 1.4
diff -u -r1.4 SequencedHashtable.java
--- SequencedHashtable.java	2001/05/20 02:38:52	1.4
+++ SequencedHashtable.java	2001/06/01 14:18:09
@@ -57,6 +57,7 @@
 import java.util.Collection;
 import java.util.Hashtable;
 import java.util.Iterator;
+import java.util.List;
 import java.util.LinkedList;
 import java.util.Map;
 import java.util.Set;
@@ -73,6 +74,7 @@
  * the use of a list of <code>Map.Entry</code> objects.
  *
  * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
+ * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
  * @version $Id: SequencedHashtable.java,v 1.4 2001/05/20 02:38:52 dlr Exp $
  */
 public class SequencedHashtable extends Hashtable
@@ -261,10 +263,14 @@
     }
 
     /**
-     * Slightly cheaper implementation of <code>values()</code> method.
+     * Returns the keys in the table as a List.
+     *
+     * @return    List of all keys
      */
-    public Collection values ()
+  
+    public List keyList()
     {
         return keySequence;
     }
+
 }
-- 
Dipl.-Inf. (Univ.) Henning P. Schmiedehausen       -- Geschaeftsfuehrer
INTERMETA - Gesellschaft fuer Mehrwertdienste mbH     hps@intermeta.de

Am Schwabachgrund 22  Fon.: 09131 / 50654-0   info@intermeta.de
D-91054 Buckenhof     Fax.: 09131 / 50654-20   

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: SequencedHashtable

Posted by Daniel Rall <dl...@finemaltcoding.com>.
"Henning P. Schmiedehausen" <ma...@hometree.net> writes:

> I checked this into the CVS tree, together with tests for the new
> feature. It is already visible in the WebCVS but I'm somehow missing
> the commit message here. Is it normal, that it is delayed by some
> hours? (First commit; still learning. And yes, I used /home/cvs this
> time. ;-) )

I see it in CVS.  Looks good.  Commit logs do sometimes take quite a
while, as daedalus is quite overloaded.

> >It is a shame.  When you add the sequence() instance method, perhaps
> >you could add a little more to my "cryptic note" about why both
> >interface cannot be implemented.  ;)
> 
> I didn't do this, but I will make some notes about this later.

Okay, thanks.

Do you think that we should deprecated SequencedHashtable's iterator()
method now that sequence() is available?  I was about to, then decided
that it might be useful in templates or what not, so left it be.

Daniel

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: SequencedHashtable

Posted by "Henning P. Schmiedehausen" <ma...@hometree.net>.
Daniel Rall <dl...@finemaltcoding.com> writes:

>> >I agree.  Can we call it keySequence()--or just plain sequence()--
>> >instead of keyList()?
>> 
>> Sure. sequence() is IMHO the best name. 

>Okay, have at it.

I checked this into the CVS tree, together with tests for the new
feature. It is already visible in the WebCVS but I'm somehow missing
the commit message here. Is it normal, that it is delayed by some
hours? (First commit; still learning. And yes, I used /home/cvs this
time. ;-) )

>It is a shame.  When you add the sequence() instance method, perhaps
>you could add a little more to my "cryptic note" about why both
>interface cannot be implemented.  ;)

I didn't do this, but I will make some notes about this later.

	Regards
		Henning

-- 
Dipl.-Inf. (Univ.) Henning P. Schmiedehausen       -- Geschaeftsfuehrer
INTERMETA - Gesellschaft fuer Mehrwertdienste mbH     hps@intermeta.de

Am Schwabachgrund 22  Fon.: 09131 / 50654-0   info@intermeta.de
D-91054 Buckenhof     Fax.: 09131 / 50654-20   

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: SequencedHashtable

Posted by Daniel Rall <dl...@finemaltcoding.com>.
"Henning P. Schmiedehausen" <ma...@hometree.net> writes:

> Daniel Rall <dl...@finemaltcoding.com> writes:
> 
> >[Comments inline.  Sorry for the delay, JavaOne last week and away for
> >the weekend.]
> 
> No prob. I wasn't around anyway, had to visit my parents-in-law =%-)

Heh, next weekend I'll have some of those myself!

> >I agree.  Can we call it keySequence()--or just plain sequence()--
> >instead of keyList()?
> 
> Sure. sequence() is IMHO the best name. 

Okay, have at it.

> >I appreciate you providing such a thorough example, but this would
> >break backwards compatibility by moving SequencedHashtable from the
> >Map to Collection interface.  Though the sequence is a nice by-product
> >of the implementation, I consider SequencedHashtable to intrinsically
> >be a Map implementation.
> 
> Sure. I see it like this, too. A shame that there is no way to
> implement both interfaces. The class itself was more of a by-product of
> some code tinkering.

It is a shame.  When you add the sequence() instance method, perhaps
you could add a little more to my "cryptic note" about why both
interface cannot be implemented.  ;)

                               Thanks,
                                Daniel

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: SequencedHashtable

Posted by "Henning P. Schmiedehausen" <ma...@hometree.net>.
Daniel Rall <dl...@finemaltcoding.com> writes:

>[Comments inline.  Sorry for the delay, JavaOne last week and away for
>the weekend.]

No prob. I wasn't around anyway, had to visit my parents-in-law =%-)

>> So, no, I'm afraid I need my keyList() method. ;-) The iterator simply
>> will not cut it.

>I agree.  Can we call it keySequence()--or just plain sequence()--
>instead of keyList()?

Sure. sequence() is IMHO the best name. 

>I appreciate you providing such a thorough example, but this would
>break backwards compatibility by moving SequencedHashtable from the
>Map to Collection interface.  Though the sequence is a nice by-product
>of the implementation, I consider SequencedHashtable to intrinsically
>be a Map implementation.

Sure. I see it like this, too. A shame that there is no way to
implement both interfaces. The class itself was more of a by-product of
some code tinkering.

	Regards
		Henning

-- 
Henning Schmiedehausen     "They took the credit for your second symphony. 
hps@intermeta.de            Rewritten by machine and "New Technology".         
henning@forge.franken.de    and now I understand the problems you can see."
                                                        -- The Buggles, 1979

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: SequencedHashtable

Posted by Daniel Rall <dl...@finemaltcoding.com>.
[Comments inline.  Sorry for the delay, JavaOne last week and away for
the weekend.]

"Henning P. Schmiedehausen" <ma...@hometree.net> writes:

> Daniel Rall <dl...@finemaltcoding.com> writes:
> >The existing SequencedHashtable iterator() method provides this
> >functionality.
> 
> >> In my application, I first used an Hashtable and an ArrayList in
> >> parallel which I replaced easily with the SequencedHashtable, once I
> >> added the keyList() method. I'm not that sure about keySet() and I
> >> really wanted access to the List to be sure about the sequence.
> 
> >Will iterator() do the trick?  If it does, can you suggest an
> 
> Unfortunately not. Especially as obj.keyList() gives an
> java.util.Collection compatible object which makes it usable in
> Velocity foreach while the SequencedHashtable is not.
> 
> ( I have code like this:
> 
> class foo
> {
>         SequencedHashtable st = new SequencedHashtable();
> 
>         public List getList()
>         {
>                 return this.st.keyList();
>         }
> }
> 
> class baz implements VelocityScreen
> {
> 
>         public void doBuildTemplate(RunData d, Context c)
>         {
>                 foo f = new foo();
>                 c.put("foo", foo);
>         }
> }
> 
> baz.vm:
> 
>         foreach($blqx in $foo.List)
>         {
>                 display_something($blqx);
>         }
> 
> Which works nicely. If I just return the "st" object above in foo,
> then the whole iteration stuff will not work (because Velocity sees
> the "Map" interface, gets the values().iterator() and then goes
> completely in the wrong direction.
> 
> I was thinking about implementing the Collections interface for
> SequencedHashtable and now I understand the somewhat cryptic comment
> "Implementing the List interface is not possible due to a instance
> method name clash.  Java does not support method renaming." :
> 
> Collections:
> 
> boolean remove(Object o)
> 
> Map:
> 
> Object remove(Object o)
> 
> Jeez, what did the guy smoke that designed these classes?

I don't know, but he needs to share.  ;P

I'm sure it was because the Hashtable API has been around since Java
1.0, and the Collections API wasn't introduced until 1.2.

> So, no, I'm afraid I need my keyList() method. ;-) The iterator simply
> will not cut it.

I agree.  Can we call it keySequence()--or just plain sequence()--
instead of keyList()?

> >alternate name which would make its purpose more clear (so that users
> >need not scan the existing JavaDoc)?  I was originally trying to avoid
> >providing direct access to the underlying List (but am not married to
> >the idea).
> 
> If I could get a Collections interface, I wouldn't be either. How
> about the attached SequencedHashtable. ==:-) 

I appreciate you providing such a thorough example, but this would
break backwards compatibility by moving SequencedHashtable from the
Map to Collection interface.  Though the sequence is a nice by-product
of the implementation, I consider SequencedHashtable to intrinsically
be a Map implementation.

> (If you like it, I would check it into the CVS with some more
> comments. The SequencedHashtable and its child is, as far as I can
> see, nowhere used in the Turbine itself, but I would guess that it is
> used by Applications and I would be interested, if people actually use
> the Map interface (if yes, then this change would be a bad idea).)

They are not used in Turbine proper, but are used in Helm
(extensively) and Scarab.

> package org.apache.turbine.util;
> 
> /* ====================================================================
>  * The Apache Software License, Version 1.1
>  *
>  * Copyright (c) 2001 The Apache Software Foundation.  All rights
>  * reserved.
>  *
>  * Redistribution and use in source and binary forms, with or without
>  * modification, are permitted provided that the following conditions
>  * are met:
>  *
>  * 1. Redistributions of source code must retain the above copyright
>  *    notice, this list of conditions and the following disclaimer.
>  *
>  * 2. Redistributions in binary form must reproduce the above copyright
>  *    notice, this list of conditions and the following disclaimer in
>  *    the documentation and/or other materials provided with the
>  *    distribution.
>  *
>  * 3. The end-user documentation included with the redistribution,
>  *    if any, must include the following acknowledgment:
>  *       "This product includes software developed by the
>  *        Apache Software Foundation (http://www.apache.org/)."
>  *    Alternately, this acknowledgment may appear in the software itself,
>  *    if and wherever such third-party acknowledgments normally appear.
>  *
>  * 4. The names "Apache" and "Apache Software Foundation" and 
>  *    "Apache Turbine" must not be used to endorse or promote products 
>  *    derived from this software without prior written permission. For 
>  *    written permission, please contact apache@apache.org.
>  *
>  * 5. Products derived from this software may not be called "Apache",
>  *    "Apache Turbine", nor may "Apache" appear in their name, without 
>  *    prior written permission of the Apache Software Foundation.
>  *
>  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
>  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
>  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
>  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
>  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
>  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
>  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
>  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
>  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
>  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
>  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
>  * SUCH DAMAGE.
>  * ====================================================================
>  *
>  * This software consists of voluntary contributions made by many
>  * individuals on behalf of the Apache Software Foundation.  For more
>  * information on the Apache Software Foundation, please see
>  * <http://www.apache.org/>.
>  */
> 
> import java.util.Collection;
> import java.util.Hashtable;
> import java.util.Iterator;
> import java.util.List;
> import java.util.LinkedList;
> import java.util.Map;
> import java.util.Set;
> 
> /**
>  * A {@link java.util.Hashtable} whose keys are sequenced.  The
>  * sequencing of the keys allow easy access to the values in the order
>  * which they were added in.  This class is thread safe.
>  * <p>
>  * Implementing the List interface is not possible due to a instance
>  * method name clash.  Java does not support method renaming.
>  * <p>
>  * A slightly more complex implementation and interface could involve
>  * the use of a list of <code>Map.Entry</code> objects.
>  *
>  * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
>  * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
>  * @version $Id: SequencedHashtable.java,v 1.4 2001/05/20 02:38:52 dlr Exp $
>  */
> 
> public class SequencedHashtable extends LinkedList
> {
>     /**
>      * Indicator for an unknown index.
>      */
> 
>     private static final int UNKNOWN_INDEX = -1;
> 
>     /**
>      * The table for the keys.
>      */
> 
>     private Hashtable keyMap;
> 
>     /**
>      * Creates a new instance with default storage.
>      */
> 
>     public SequencedHashtable ()
>     {
>         keyMap = new Hashtable();
>     }
> 
>     /**
>      * Creates a new instance with the specified storage.
>      *
>      * @param size The storage to allocate up front.
>      */
> 
>     public SequencedHashtable (int size)
>     {
>         keyMap = new Hashtable(size);
>     }
> 
>     /**
>      * Clears all elements.
>      */
> 
>     public synchronized void clear ()
>     {
>         super.clear();
>         keyMap.clear();
>     }
> 
>     /**
>      * Creates a shallow copy of this object, preserving the internal
>      * structure by copying only references.  The keys, values, and
>      * sequence are not <code>clone()</code>'d.
>      *
>      * @return A clone of this instance.
>      */
> 
>     public synchronized Object clone ()
>     {
>         SequencedHashtable seqList = (SequencedHashtable)super.clone();
>         seqList.keyMap = (Hashtable)keyMap.clone();
>         return seqList;
>     }
> 
>     /**
>      * Stores the provided key/value pair.  Freshens the sequence of existing
>      * elements.
>      *
>      * @param key   The key to the provided value.
>      * @param value The value to store.
>      * @return      The previous value for the specified key, or
>      *              <code>null</code> if none.
>      */
> 
>     public synchronized Object put (Object key, Object value)
>     {
>         Object prevValue = this.keyMap.put(key, value);
>         freshenSequence(key, prevValue);
>         return prevValue;
>     }
> 
>     /**
>      * Freshens the sequence of the element <code>value</code> if
>      * <code>value</code> is not <code>null</code>.
>      *
>      * @param key   The key whose sequence to freshen.
>      * @param value The value whose existance to check before removing the old
>      *              key sequence.
>      */
> 
>     protected void freshenSequence(Object key, Object value)
>     {
>         if (value != null)
>         {
>             // Freshening existing element's sequence.
>             super.remove(key);
>         }
>         super.add(key);
>     }
> 
>     /**
>      * Stores the provided key/value pairs.
>      *
>      * @param t The key/value pairs to store.
>      */
> 
>     public synchronized void putAll (Map t)
>     {
>         Set set = t.entrySet();
>         for (Iterator iter = set.iterator(); iter.hasNext(); )
>         {
>             Map.Entry e = (Map.Entry)iter.next();
>             put(e.getKey(), e.getValue());
>         }
>     }
> 
>     /**
>      * Removes the element at the specified index.
>      *
>      * @param index The index of the object to remove.
>      * @return      The previous value coressponding the <code>key</code>, or
>      *              <code>null</code> if none existed.
>      */
> 
>     public Object remove (int index)
>     {
>         return remove(index, null);
>     }
> 
>     /**
>      * Removes the element with the specified key.
>      *
>      * @param key   The <code>Map</code> key of the object to remove.
>      * @return      The previous value coressponding the <code>key</code>, or
>      *              <code>null</code> if none existed.
>      */
> 
>     public boolean remove (Object key)
>     {
>         Object o = remove(UNKNOWN_INDEX, key);
> 
>         return (o != null);
>     }
> 
>     /**
>      * Removes the element with the specified key or index.
>      *
>      * @param index The index of the object to remove, or
>      *              <code>UNKNOWN_INDEX</code> if not known.
>      * @param key   The <code>Map</code> key of the object to remove.
>      * @return      The previous value coressponding the <code>key</code>, or
>      *              <code>null</code> if none existed.
>      */
> 
>     private final synchronized Object remove (int index, Object key)
>     {
>         Object o = null;
> 
>         if (index == UNKNOWN_INDEX) 
>             index = indexOf(key);
> 
>         if (key == null) 
>             key = super.get(index);
> 
>         if (index != UNKNOWN_INDEX) 
>         {
>             super.remove(index);
>             o = this.keyMap.remove(key); 
>         }
> 
>         return o;
>     }
> 
>     /**
>      * Tests if the specified object is a key in this hashtable
>      *
>      * @param key possible key
>      *
>      * @return <CODE>true</CODE> if and only if the specified object 
>      *          is a key in this hashtable, as determined by the 
>      *          equals method; <CODE>false</CODE> otherwise
>      */
> 
>     public boolean containsKey(Object key)
>     {
>         return contains(key);
>     }
> 
>     public boolean containsValue(Object value)
>     {
>         return this.keyMap.containsValue(value);
>     }
> 
>     public Object get(Object key)
>     {
>         return this.keyMap.get(key);
>     }
> 
>     public Set keySet()
>     {
>         return this.keyMap.keySet();
>     }
> 
>     public Collection values()
>     {
>         return this.keyMap.values();
>     }
> 
>     public Set entrySet()
>     {
>         return this.keyMap.entrySet();
>     }
> 
>     public boolean equals(Object o)
>     {
>         return this.keyMap.entrySet().equals(((Map)o).entrySet());
>     }
> 
>     public int hashCode()
>     {
>         return this.keyMap.hashCode();
>     }
> 
> }
> --- cut --- 
> -- 
> Dipl.-Inf. (Univ.) Henning P. Schmiedehausen       -- Geschaeftsfuehrer
> INTERMETA - Gesellschaft fuer Mehrwertdienste mbH     hps@intermeta.de
> 
> Am Schwabachgrund 22  Fon.: 09131 / 50654-0   info@intermeta.de
> D-91054 Buckenhof     Fax.: 09131 / 50654-20   
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: turbine-dev-help@jakarta.apache.org

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: SequencedHashtable

Posted by "Henning P. Schmiedehausen" <ma...@hometree.net>.
Daniel Rall <dl...@finemaltcoding.com> writes:

>"Henning P. Schmiedehausen" <ma...@hometree.net> writes:

>> As far as I can see, the Set does not gurantee the sequence of the
>> keys.  That's why I added a new method "keyList()". You still get
>> keySet() inherited from the Hashtable.

>The existing SequencedHashtable iterator() method provides this
>functionality.

>> In my application, I first used an Hashtable and an ArrayList in
>> parallel which I replaced easily with the SequencedHashtable, once I
>> added the keyList() method. I'm not that sure about keySet() and I
>> really wanted access to the List to be sure about the sequence.

>Will iterator() do the trick?  If it does, can you suggest an

Unfortunately not. Especially as obj.keyList() gives an
java.util.Collection compatible object which makes it usable in
Velocity foreach while the SequencedHashtable is not.

( I have code like this:

class foo
{
        SequencedHashtable st = new SequencedHashtable();

        public List getList()
        {
                return this.st.keyList();
        }
}

class baz implements VelocityScreen
{

        public void doBuildTemplate(RunData d, Context c)
        {
                foo f = new foo();
                c.put("foo", foo);
        }
}

baz.vm:

        foreach($blqx in $foo.List)
        {
                display_something($blqx);
        }

Which works nicely. If I just return the "st" object above in foo,
then the whole iteration stuff will not work (because Velocity sees
the "Map" interface, gets the values().iterator() and then goes
completely in the wrong direction.

I was thinking about implementing the Collections interface for
SequencedHashtable and now I understand the somewhat cryptic comment
"Implementing the List interface is not possible due to a instance
method name clash.  Java does not support method renaming." :

Collections:

boolean remove(Object o)

Map:

Object remove(Object o)

Jeez, what did the guy smoke that designed these classes?

So, no, I'm afraid I need my keyList() method. ;-) The iterator simply
will not cut it.

>alternate name which would make its purpose more clear (so that users
>need not scan the existing JavaDoc)?  I was originally trying to avoid
>providing direct access to the underlying List (but am not married to
>the idea).

If I could get a Collections interface, I wouldn't be either. How
about the attached SequencedHashtable. ==:-) 

(If you like it, I would check it into the CVS with some more
comments. The SequencedHashtable and its child is, as far as I can
see, nowhere used in the Turbine itself, but I would guess that it is
used by Applications and I would be interested, if people actually use
the Map interface (if yes, then this change would be a bad idea).)

        Regards
                Henning

--- cut --- 
package org.apache.turbine.util;

/* ====================================================================
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Apache" and "Apache Software Foundation" and 
 *    "Apache Turbine" must not be used to endorse or promote products 
 *    derived from this software without prior written permission. For 
 *    written permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    "Apache Turbine", nor may "Apache" appear in their name, without 
 *    prior written permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

import java.util.Collection;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;

/**
 * A {@link java.util.Hashtable} whose keys are sequenced.  The
 * sequencing of the keys allow easy access to the values in the order
 * which they were added in.  This class is thread safe.
 * <p>
 * Implementing the List interface is not possible due to a instance
 * method name clash.  Java does not support method renaming.
 * <p>
 * A slightly more complex implementation and interface could involve
 * the use of a list of <code>Map.Entry</code> objects.
 *
 * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
 * @version $Id: SequencedHashtable.java,v 1.4 2001/05/20 02:38:52 dlr Exp $
 */

public class SequencedHashtable extends LinkedList
{
    /**
     * Indicator for an unknown index.
     */

    private static final int UNKNOWN_INDEX = -1;

    /**
     * The table for the keys.
     */

    private Hashtable keyMap;

    /**
     * Creates a new instance with default storage.
     */

    public SequencedHashtable ()
    {
        keyMap = new Hashtable();
    }

    /**
     * Creates a new instance with the specified storage.
     *
     * @param size The storage to allocate up front.
     */

    public SequencedHashtable (int size)
    {
        keyMap = new Hashtable(size);
    }

    /**
     * Clears all elements.
     */

    public synchronized void clear ()
    {
        super.clear();
        keyMap.clear();
    }

    /**
     * Creates a shallow copy of this object, preserving the internal
     * structure by copying only references.  The keys, values, and
     * sequence are not <code>clone()</code>'d.
     *
     * @return A clone of this instance.
     */

    public synchronized Object clone ()
    {
        SequencedHashtable seqList = (SequencedHashtable)super.clone();
        seqList.keyMap = (Hashtable)keyMap.clone();
        return seqList;
    }

    /**
     * Stores the provided key/value pair.  Freshens the sequence of existing
     * elements.
     *
     * @param key   The key to the provided value.
     * @param value The value to store.
     * @return      The previous value for the specified key, or
     *              <code>null</code> if none.
     */

    public synchronized Object put (Object key, Object value)
    {
        Object prevValue = this.keyMap.put(key, value);
        freshenSequence(key, prevValue);
        return prevValue;
    }

    /**
     * Freshens the sequence of the element <code>value</code> if
     * <code>value</code> is not <code>null</code>.
     *
     * @param key   The key whose sequence to freshen.
     * @param value The value whose existance to check before removing the old
     *              key sequence.
     */

    protected void freshenSequence(Object key, Object value)
    {
        if (value != null)
        {
            // Freshening existing element's sequence.
            super.remove(key);
        }
        super.add(key);
    }

    /**
     * Stores the provided key/value pairs.
     *
     * @param t The key/value pairs to store.
     */

    public synchronized void putAll (Map t)
    {
        Set set = t.entrySet();
        for (Iterator iter = set.iterator(); iter.hasNext(); )
        {
            Map.Entry e = (Map.Entry)iter.next();
            put(e.getKey(), e.getValue());
        }
    }

    /**
     * Removes the element at the specified index.
     *
     * @param index The index of the object to remove.
     * @return      The previous value coressponding the <code>key</code>, or
     *              <code>null</code> if none existed.
     */

    public Object remove (int index)
    {
        return remove(index, null);
    }

    /**
     * Removes the element with the specified key.
     *
     * @param key   The <code>Map</code> key of the object to remove.
     * @return      The previous value coressponding the <code>key</code>, or
     *              <code>null</code> if none existed.
     */

    public boolean remove (Object key)
    {
        Object o = remove(UNKNOWN_INDEX, key);

        return (o != null);
    }

    /**
     * Removes the element with the specified key or index.
     *
     * @param index The index of the object to remove, or
     *              <code>UNKNOWN_INDEX</code> if not known.
     * @param key   The <code>Map</code> key of the object to remove.
     * @return      The previous value coressponding the <code>key</code>, or
     *              <code>null</code> if none existed.
     */

    private final synchronized Object remove (int index, Object key)
    {
        Object o = null;

        if (index == UNKNOWN_INDEX) 
            index = indexOf(key);

        if (key == null) 
            key = super.get(index);

        if (index != UNKNOWN_INDEX) 
        {
            super.remove(index);
            o = this.keyMap.remove(key); 
        }

        return o;
    }

    /**
     * Tests if the specified object is a key in this hashtable
     *
     * @param key possible key
     *
     * @return <CODE>true</CODE> if and only if the specified object 
     *          is a key in this hashtable, as determined by the 
     *          equals method; <CODE>false</CODE> otherwise
     */

    public boolean containsKey(Object key)
    {
        return contains(key);
    }

    public boolean containsValue(Object value)
    {
        return this.keyMap.containsValue(value);
    }

    public Object get(Object key)
    {
        return this.keyMap.get(key);
    }

    public Set keySet()
    {
        return this.keyMap.keySet();
    }

    public Collection values()
    {
        return this.keyMap.values();
    }

    public Set entrySet()
    {
        return this.keyMap.entrySet();
    }

    public boolean equals(Object o)
    {
        return this.keyMap.entrySet().equals(((Map)o).entrySet());
    }

    public int hashCode()
    {
        return this.keyMap.hashCode();
    }

}
--- cut --- 
-- 
Dipl.-Inf. (Univ.) Henning P. Schmiedehausen       -- Geschaeftsfuehrer
INTERMETA - Gesellschaft fuer Mehrwertdienste mbH     hps@intermeta.de

Am Schwabachgrund 22  Fon.: 09131 / 50654-0   info@intermeta.de
D-91054 Buckenhof     Fax.: 09131 / 50654-20   

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: SequencedHashtable

Posted by Daniel Rall <dl...@finemaltcoding.com>.
"Henning P. Schmiedehausen" <ma...@hometree.net> writes:

> As far as I can see, the Set does not gurantee the sequence of the
> keys.  That's why I added a new method "keyList()". You still get
> keySet() inherited from the Hashtable.

The existing SequencedHashtable iterator() method provides this
functionality.

> In my application, I first used an Hashtable and an ArrayList in
> parallel which I replaced easily with the SequencedHashtable, once I
> added the keyList() method. I'm not that sure about keySet() and I
> really wanted access to the List to be sure about the sequence.

Will iterator() do the trick?  If it does, can you suggest an
alternate name which would make its purpose more clear (so that users
need not scan the existing JavaDoc)?  I was originally trying to avoid
providing direct access to the underlying List (but am not married to
the idea).

Daniel

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: SequencedHashtable

Posted by "Henning P. Schmiedehausen" <ma...@hometree.net>.
Daniel Rall <dl...@finemaltcoding.com> writes:

>Hi Henning, you're quite right that this is a bug--thanks for the
>detailed description and sample code.  :)

>The existing values() method should be removed (an implementation of
>it already exists in Hashtable), and a cheaper method which is in line
>with the existing java.util.Map interface:

>public Set keySet()
>{
>    return new HashSet(keySequence);
>}

As far as I can see, the Set does not gurantee the sequence of the
keys.  That's why I added a new method "keyList()". You still get
keySet() inherited from the Hashtable.

In my application, I first used an Hashtable and an ArrayList in
parallel which I replaced easily with the SequencedHashtable, once I
added the keyList() method. I'm not that sure about keySet() and I
really wanted access to the List to be sure about the sequence.

	Regards
		Henning

-- 
Dipl.-Inf. (Univ.) Henning P. Schmiedehausen       -- Geschaeftsfuehrer
INTERMETA - Gesellschaft fuer Mehrwertdienste mbH     hps@intermeta.de

Am Schwabachgrund 22  Fon.: 09131 / 50654-0   info@intermeta.de
D-91054 Buckenhof     Fax.: 09131 / 50654-20   

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: SequencedHashtable

Posted by Daniel Rall <dl...@finemaltcoding.com>.
On second thought, review of the JDK Hashtable source code points out
that my suggested fix modifies the behavior of Hashtable's keySet()
method.  Hashtable's implementation manages to return a sychronized
reference to its Set of keys via some java.util.Collections
machinations.  The proper fix here is to simply remove
SequencedHashtable's values() method over-ride, and to add yourself to
the author's list.  ;)

Dan


Daniel Rall <dl...@finemaltcoding.com> writes:

> Hi Henning, you're quite right that this is a bug--thanks for the
> detailed description and sample code.  :)
> 
> The existing values() method should be removed (an implementation of
> it already exists in Hashtable), and a cheaper method which is in line
> with the existing java.util.Map interface:
> 
> public Set keySet()
> {
>     return new HashSet(keySequence);
> }
> 
> You'll need to import HashSet.
> 
> 
> "Henning P. Schmiedehausen" <ma...@hometree.net> writes:
> 
> > Index: SequencedHashtable.java
> > ===================================================================
> > RCS file: /home/cvspublic/jakarta-turbine/src/java/org/apache/turbine/util/SequencedHashtable.java,v
> > retrieving revision 1.4
> > diff -u -r1.4 SequencedHashtable.java
> > --- SequencedHashtable.java	2001/05/20 02:38:52	1.4
> > +++ SequencedHashtable.java	2001/06/01 14:18:09
> > @@ -57,6 +57,7 @@
> >  import java.util.Collection;
> >  import java.util.Hashtable;
> >  import java.util.Iterator;
> > +import java.util.List;
> >  import java.util.LinkedList;
> >  import java.util.Map;
> >  import java.util.Set;
> > @@ -73,6 +74,7 @@
> >   * the use of a list of <code>Map.Entry</code> objects.
> >   *
> >   * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
> > + * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
> >   * @version $Id: SequencedHashtable.java,v 1.4 2001/05/20 02:38:52 dlr Exp $
> >   */
> >  public class SequencedHashtable extends Hashtable
> > @@ -261,10 +263,14 @@
> >      }
> >  
> >      /**
> > -     * Slightly cheaper implementation of <code>values()</code> method.
> > +     * Returns the keys in the table as a List.
> > +     *
> > +     * @return    List of all keys
> >       */
> > -    public Collection values ()
> > +  
> > +    public List keyList()
> >      {
> >          return keySequence;
> >      }
> > +
> >  }

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: SequencedHashtable

Posted by Daniel Rall <dl...@finemaltcoding.com>.
Hi Henning, you're quite right that this is a bug--thanks for the
detailed description and sample code.  :)

The existing values() method should be removed (an implementation of
it already exists in Hashtable), and a cheaper method which is in line
with the existing java.util.Map interface:

public Set keySet()
{
    return new HashSet(keySequence);
}

You'll need to import HashSet.

Dan


"Henning P. Schmiedehausen" <ma...@hometree.net> writes:

> Hi,
> 
> I might be wrong, but this looks bogus to me in SequencedHashtable.
> 
> /**
>  * Slightly cheaper implementation of <code>values()</code> method.
>  */
> public Collection values ()
> {
>     return keySequence;
> }
> 
> because in keySequence are the keys stored. This would be some sort
> of 
> 
> public List keyList()
> {
>     return keySequence;
> }
> 
> 
> A demo program seems to confirm this:
> 
> --- cut ---
> import java.util.Hashtable;
> import java.util.Iterator;
> 
> import org.apache.turbine.util.SequencedHashtable;
> 
> public class sequencetest
> {
>   public static void main(String[] args)
>   {
>     Hashtable ht = new Hashtable();
>     SequencedHashtable sht = new SequencedHashtable();
> 
>     for(int i = 0; i < 10; i++)
>     {
>       ht.put("Key "+Integer.toString(i), "Value "+Integer.toString(i));
>       sht.put("Key "+Integer.toString(i), "Value "+Integer.toString(i));
>     }
> 
>     Iterator it;
> 
>     System.out.println("Hashtable:");
>     it = ht.values().iterator();
> 
>     while(it.hasNext())
>       System.out.println(it.next());
> 
>     System.out.println("Seq.Hashtable:");
>     it = sht.values().iterator();
> 
>     while(it.hasNext())
>       System.out.println(it.next());
>   }
> }
> --- cut ---
> 
> Hashtable:
> Value 4
> Value 3
> Value 2
> Value 1
> Value 0
> Value 9
> Value 8
> Value 7
> Value 6
> Value 5
> 
> Seq.Hashtable:
> Key 0
> Key 1
> Key 2
> Key 3
> Key 4
> Key 5
> Key 6
> Key 7
> Key 8
> Key 9
> 
> Not the same. Patch attached. I thought about deprecation but removing
> the values() method makes the original method from Hashtable visible
> again which is a good thing.
> 
> By applying this patch, the whole SequencedHashtable shebang suddently
> gets usable for me to replace lots of "keep list and hashtable around"
> situations. ;-)
> 
> 	Regards
> 		Henning
> 
> Index: SequencedHashtable.java
> ===================================================================
> RCS file: /home/cvspublic/jakarta-turbine/src/java/org/apache/turbine/util/SequencedHashtable.java,v
> retrieving revision 1.4
> diff -u -r1.4 SequencedHashtable.java
> --- SequencedHashtable.java	2001/05/20 02:38:52	1.4
> +++ SequencedHashtable.java	2001/06/01 14:18:09
> @@ -57,6 +57,7 @@
>  import java.util.Collection;
>  import java.util.Hashtable;
>  import java.util.Iterator;
> +import java.util.List;
>  import java.util.LinkedList;
>  import java.util.Map;
>  import java.util.Set;
> @@ -73,6 +74,7 @@
>   * the use of a list of <code>Map.Entry</code> objects.
>   *
>   * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
> + * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
>   * @version $Id: SequencedHashtable.java,v 1.4 2001/05/20 02:38:52 dlr Exp $
>   */
>  public class SequencedHashtable extends Hashtable
> @@ -261,10 +263,14 @@
>      }
>  
>      /**
> -     * Slightly cheaper implementation of <code>values()</code> method.
> +     * Returns the keys in the table as a List.
> +     *
> +     * @return    List of all keys
>       */
> -    public Collection values ()
> +  
> +    public List keyList()
>      {
>          return keySequence;
>      }
> +
>  }

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


AW: Mail Api

Posted by Stefan Groschupf <sg...@media-style.com>.
>This is the Turbine list. Not the Mail API list. Also, there is no "for"
>header in emails.

Sorry copy past the wrong adress. I'm sorry. I will set the reselution of my
Display down.

stefan


---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Re: Mail Api

Posted by Jon Stevens <jo...@latchkey.com>.
on 6/1/01 8:24 AM, "Stefan Groschupf" <sg...@media-style.com> wrote:

> Hi all,
> 
> some one kno if ist possible to read the "for" in the header of an email
> with the Mail API?
> I want to read Mails that comes from Mailinglists.
> Majordomo for example don't use the "to" it's only works with "for"
> I cant find something in the doc.
> 
> Thanks for Answers.
> stefan

This is the Turbine list. Not the Mail API list. Also, there is no "for"
header in emails.

-jon

-- 
If you come from a Perl or PHP background, JSP is a way to take
your pain to new levels. --Anonymous
<http://jakarta.apache.org/velocity/ymtd/ymtd.html>


---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org


Mail Api

Posted by Stefan Groschupf <sg...@media-style.com>.
Hi all,

some one kno if ist possible to read the "for" in the header of an email
with the Mail API?
I want to read Mails that comes from Mailinglists.
Majordomo for example don't use the "to" it's only works with "for"
I cant find something in the doc.

Thanks for Answers.
stefan



---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org