working on serializer refactoring.

diff --git a/build.xml b/build.xml
index dfefb44..e8b4181 100644
--- a/build.xml
+++ b/build.xml
@@ -207,12 +207,14 @@
 ,org.codehaus.jackson.io;version=${IMPL_VERSION}
 ,org.codehaus.jackson.map;version=${IMPL_VERSION}
 ,org.codehaus.jackson.map.node;version=${IMPL_VERSION}
+,org.codehaus.jackson.map.ser;version=${IMPL_VERSION}
 '
          privatePackage="!test
 ,!org.codehaus.jackson
 ,!org.codehaus.jackson.io
 ,!org.codehaus.jackson.map
 ,!org.codehaus.jackson.map.node
+,!org.codehaus.jackson.map.ser
 ,*"
          includeResource="META-INF=release-notes/asl"
          includeIncludeResourceHeader="false"
diff --git a/src/java/org/codehaus/jackson/map/JsonSerializer.java b/src/java/org/codehaus/jackson/map/JsonSerializer.java
index 88d8053..257d2aa 100644
--- a/src/java/org/codehaus/jackson/map/JsonSerializer.java
+++ b/src/java/org/codehaus/jackson/map/JsonSerializer.java
@@ -16,7 +16,7 @@
      * values of type this serializer handles.
      *
      * @param value Value to serialize
-     * @param gen Generator used to output resulting Json content
+     * @param jgen Generator used to output resulting Json content
      * @param provider Provider that can be used to get serializers for
      *   serializing Objects value contains, if any.
      */
diff --git a/src/java/org/codehaus/jackson/map/JsonSerializerFactory.java b/src/java/org/codehaus/jackson/map/JsonSerializerFactory.java
index 6e600ae..623bb36 100644
--- a/src/java/org/codehaus/jackson/map/JsonSerializerFactory.java
+++ b/src/java/org/codehaus/jackson/map/JsonSerializerFactory.java
@@ -13,4 +13,3 @@
      */
     public abstract <T> JsonSerializer<T> createSerializer(Class<T> type);
 }
-
diff --git a/src/java/org/codehaus/jackson/map/JsonSerializerProvider.java b/src/java/org/codehaus/jackson/map/JsonSerializerProvider.java
index 007616c..6d8d101 100644
--- a/src/java/org/codehaus/jackson/map/JsonSerializerProvider.java
+++ b/src/java/org/codehaus/jackson/map/JsonSerializerProvider.java
@@ -32,14 +32,15 @@
 
     /**
      * Method called to get the serializer to use for serializing
-     * Map keys that are not nulls (for null keys,
-     * {@link #getNullKeySerializer} is called instead).
-     * Separation from regular
-     * {@link #findSerializer} method is due to Json only allowing
-     * Json Strings as field names; and hence different serialization
-     * strategy may be needed.
+     * non-null Map keys. Separation from regular
+     * {@link #findValueSerializer} method is because actual write
+     * method must be different (@link JsonGenerator#writeFieldName};
+     * but also since behavior for some key types may differ.
+     *<p>
+     * Note that the serializer itself can be called with instances
+     * of any Java object, but not nulls.
      */
-    public abstract JsonSerializer<?> findNonNullKeySerializer(Class<?> type);
+    public abstract JsonSerializer<Object> getKeySerializer();
 
     /**
      * Method called to get the serializer to use for serializing
@@ -50,7 +51,7 @@
      * will either throw an exception, or use an empty String; but
      * other behaviors are possible.
      */
-    public abstract JsonSerializer<?> getNullKeySerializer();
+    public abstract JsonSerializer<Object> getNullKeySerializer();
 
     /**
      * Method called to get the serializer to use for serializing
@@ -61,5 +62,5 @@
      * Typically returned serializer just writes out Json literal
      * null value.
      */
-    public abstract JsonSerializer<?> getNullValueSerializer();
+    public abstract JsonSerializer<Object> getNullValueSerializer();
 }
diff --git a/src/java/org/codehaus/jackson/map/ser/BeanSerializerFactory.java b/src/java/org/codehaus/jackson/map/ser/BeanSerializerFactory.java
index fe0ac2d..14c0e30 100644
--- a/src/java/org/codehaus/jackson/map/ser/BeanSerializerFactory.java
+++ b/src/java/org/codehaus/jackson/map/ser/BeanSerializerFactory.java
@@ -1,13 +1,6 @@
 package org.codehaus.jackson.map.ser;
 
-import java.io.IOException;
-import java.util.*;
-
-import org.codehaus.jackson.JsonGenerationException;
-import org.codehaus.jackson.JsonGenerator;
 import org.codehaus.jackson.map.JsonSerializer;
-import org.codehaus.jackson.map.JsonSerializerFactory;
-import org.codehaus.jackson.map.JsonSerializerProvider;
 
 /**
  * Factory class that can provide serializers for any regular Java beans
diff --git a/src/java/org/codehaus/jackson/map/ser/FailingSerializer.java b/src/java/org/codehaus/jackson/map/ser/FailingSerializer.java
new file mode 100644
index 0000000..c3e2dda
--- /dev/null
+++ b/src/java/org/codehaus/jackson/map/ser/FailingSerializer.java
@@ -0,0 +1,29 @@
+package org.codehaus.jackson.map.ser;
+
+import java.io.IOException;
+
+import org.codehaus.jackson.JsonGenerationException;
+import org.codehaus.jackson.JsonGenerator;
+import org.codehaus.jackson.map.JsonSerializer;
+import org.codehaus.jackson.map.JsonSerializerProvider;
+
+/**
+ * Special bogus "serializer" that will throw
+ * {@link JsonGenerationException} if its {@link #serialize}
+ * gets invoeked. Most commonly registered as handler for unknown types,
+ * as well as for catching unintended usage (like trying to use null
+ * as Map/Object key).
+ */
+public final class FailingSerializer
+    extends JsonSerializer<Object>
+{
+    final String _msg;
+    
+    public FailingSerializer(String msg) { _msg = msg; }
+    
+    public void serialize(Object value, JsonGenerator jgen, JsonSerializerProvider provider)
+        throws IOException, JsonGenerationException
+    {
+        throw new JsonGenerationException(_msg);
+    }
+}
diff --git a/src/java/org/codehaus/jackson/map/ser/SerializerProviderBase.java b/src/java/org/codehaus/jackson/map/ser/SerializerProviderBase.java
index 52b8923..6bba0b4 100644
--- a/src/java/org/codehaus/jackson/map/ser/SerializerProviderBase.java
+++ b/src/java/org/codehaus/jackson/map/ser/SerializerProviderBase.java
@@ -1,14 +1,13 @@
 package org.codehaus.jackson.map.ser;
 
-import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
+//import java.util.concurrent.ConcurrentHashMap;
 
 import org.codehaus.jackson.map.JsonSerializer;
 import org.codehaus.jackson.map.JsonSerializerProvider;
 
 /**
  * Abstract base class that defines lowest-level common feature of most
- * implementations of {@JsonSerializerProvider}: that of locally
+ * implementations of {@link JsonSerializerProvider}: that of locally
  * storing references to serializers once they have been succesfully
  * constructed.
  */
@@ -24,13 +23,13 @@
     }
 
     @Override
-    public abstract JsonSerializer<?> findNonNullKeySerializer(Class<?> type);
+    public abstract JsonSerializer<Object> getKeySerializer();
 
     @Override
-    public abstract JsonSerializer<?> getNullKeySerializer();
+    public abstract JsonSerializer<Object> getNullKeySerializer();
 
     @Override
-    public abstract JsonSerializer<?> getNullValueSerializer();
+    public abstract JsonSerializer<Object> getNullValueSerializer();
 
     /*
     //////////////////////////////////////////////////
diff --git a/src/java/org/codehaus/jackson/map/ser/StdKeySerializer.java b/src/java/org/codehaus/jackson/map/ser/StdKeySerializer.java
new file mode 100644
index 0000000..0c524ea
--- /dev/null
+++ b/src/java/org/codehaus/jackson/map/ser/StdKeySerializer.java
@@ -0,0 +1,27 @@
+package org.codehaus.jackson.map.ser;
+
+import java.io.IOException;
+
+import org.codehaus.jackson.JsonGenerationException;
+import org.codehaus.jackson.JsonGenerator;
+import org.codehaus.jackson.map.JsonSerializer;
+import org.codehaus.jackson.map.JsonSerializerProvider;
+
+/**
+ * Specialized serializer that can be used as the generic key
+ * serializer, when serializing {@link java.util.Map}s to Json
+ * Objects.
+ */
+public final class StdKeySerializer
+    extends JsonSerializer<Object>
+{
+    final static StdKeySerializer instace = new StdKeySerializer();
+    
+    public void serialize(Object value, JsonGenerator jgen, JsonSerializerProvider provider)
+        throws IOException, JsonGenerationException
+    {
+        String keyStr = (value.getClass() == String.class) ?
+            ((String) value) : value.toString();
+        jgen.writeFieldName(keyStr);
+    }
+}
diff --git a/src/java/org/codehaus/jackson/map/ser/StdSerializerFactory.java b/src/java/org/codehaus/jackson/map/ser/StdSerializerFactory.java
index 9e2c288..60988fb 100644
--- a/src/java/org/codehaus/jackson/map/ser/StdSerializerFactory.java
+++ b/src/java/org/codehaus/jackson/map/ser/StdSerializerFactory.java
@@ -39,11 +39,12 @@
         // String and string-like types (note: date types explicitly
         // not included -- can use either textual or numeric serialization)
         _concrete.put(String.class.getName(), new StringSerializer());
-        _concrete.put(StringBuffer.class.getName(), StringLikeSerializer.instance);
-        _concrete.put(StringBuilder.class.getName(), StringLikeSerializer.instance);
-        _concrete.put(Character.class.getName(), StringLikeSerializer.instance);
+        ToStringSerializer sls = ToStringSerializer.instance;
+        _concrete.put(StringBuffer.class.getName(), sls);
+        _concrete.put(StringBuilder.class.getName(), sls);
+        _concrete.put(Character.class.getName(), sls);
         // including things best serialized as Strings
-        _concrete.put(UUID.class.getName(), StringLikeSerializer.instance);
+        _concrete.put(UUID.class.getName(), sls);
         
         // Numbers, limited length integral
         final IntegerSerializer intS = new IntegerSerializer();
@@ -89,13 +90,16 @@
         _concrete.put(Hashtable.class.getName(), mapS);
         _concrete.put(LinkedHashMap.class.getName(), mapS);
         _concrete.put(TreeMap.class.getName(), mapS);
-        _concrete.put(EnumMap.class.getName(), mapS);
         _concrete.put(Properties.class.getName(), mapS);
 
         _concrete.put(HashSet.class.getName(), collectionS);
         _concrete.put(LinkedHashSet.class.getName(), collectionS);
         _concrete.put(TreeSet.class.getName(), collectionS);
 
+        // and Enum-variations of set/map
+        _concrete.put(EnumMap.class.getName(), new EnumMapSerializer());
+        _concrete.put(EnumSet.class.getName(), new EnumSetSerializer());
+
         /* Finally, couple of oddball types. Not sure if these are
          * really needed...
          */
@@ -206,12 +210,15 @@
             }
             return CollectionSerializer.instance;
         }
-        if (Collection.class.isAssignableFrom(type)) {
-            return CollectionSerializer.instance;
-        }
         if (Number.class.isAssignableFrom(type)) {
             return NumberSerializer.instance;
         }
+        if (Enum.class.isAssignableFrom(type)) {
+            return new EnumSerializer();
+        }
+        if (Collection.class.isAssignableFrom(type)) {
+            return CollectionSerializer.instance;
+        }
         return null;
     }
 
@@ -514,6 +521,22 @@
         }
     }
 
+    public final static class EnumSetSerializer
+        extends JsonSerializer<EnumSet<? extends Enum<?>>>
+    {
+        public final static CollectionSerializer instance = new CollectionSerializer();
+
+        public void serialize(EnumSet<? extends Enum<?>> value, JsonGenerator jgen, JsonSerializerProvider provider)
+            throws IOException, JsonGenerationException
+        {
+            jgen.writeStartArray();
+            for (Enum<?> en : value) {
+                jgen.writeString(en.name());
+            }
+            jgen.writeEndArray();
+        }
+    }
+
     /*
     ////////////////////////////////////////////////////////////
     // Concrete serializers, Maps
@@ -534,9 +557,8 @@
             final int len = value.size();
 
             if (len > 0) {
-                JsonSerializer<Object> prevKeySerializer = null;
+                final JsonSerializer<Object> keySerializer = provider.getKeySerializer();
                 JsonSerializer<Object> prevValueSerializer = null;
-                Class<?> prevKeyClass = null;
                 Class<?> prevValueClass = null;
 
                 for (Map.Entry<?,?> entry : value.entrySet()) {
@@ -545,16 +567,7 @@
                     if (keyElem == null) {
                         provider.getNullKeySerializer().serialize(null, jgen, provider);
                     } else {
-                        Class<?> cc = keyElem.getClass();
-                        JsonSerializer<Object> currSerializer;
-                        if (cc == prevKeyClass) {
-                            currSerializer = prevKeySerializer;
-                        } else {
-                            currSerializer = (JsonSerializer<Object>)provider.findNonNullKeySerializer(cc);
-                            prevKeySerializer = currSerializer;
-                            prevKeyClass = cc;
-                        }
-                        currSerializer.serialize(keyElem, jgen, provider);
+                        keySerializer.serialize(keyElem, jgen, provider);
                     }
 
                     // And then value
@@ -580,6 +593,42 @@
         }
     }
 
+    public final static class EnumMapSerializer
+        extends JsonSerializer<EnumMap<? extends Enum<?>, ?>>
+    {
+        @SuppressWarnings("unchecked")
+		public void serialize(EnumMap<? extends Enum<?>,?> value, JsonGenerator jgen, JsonSerializerProvider provider)
+            throws IOException, JsonGenerationException
+        {
+            jgen.writeStartArray();
+            JsonSerializer<Object> prevSerializer = null;
+            Class<?> prevClass = null;
+
+            for (Map.Entry<? extends Enum<?>,?> entry : value.entrySet()) {
+                // First, serialize key
+                jgen.writeFieldName(entry.getKey().name());
+                // And then value
+                Object valueElem = entry.getKey();
+                if (valueElem == null) {
+                    provider.getNullValueSerializer().serialize(null, jgen, provider);
+                } else {
+                    Class<?> cc = valueElem.getClass();
+                    JsonSerializer<Object> currSerializer;
+                    if (cc == prevClass) {
+                        currSerializer = prevSerializer;
+                    } else {
+                        currSerializer = (JsonSerializer<Object>)provider.findValueSerializer(cc);
+                        prevSerializer = currSerializer;
+                        prevClass = cc;
+                    }
+                    currSerializer.serialize(valueElem, jgen, provider);
+                }
+            }
+                
+            jgen.writeEndArray();
+        }
+    }
+
     /*
     ////////////////////////////////////////////////////////////
     // Concrete serializers, arrays
@@ -765,10 +814,20 @@
 
     /*
     ////////////////////////////////////////////////////////////
-    // Other odd-ball special purpose serializers
+    // Other odd-ball special-purpose serializers
     ////////////////////////////////////////////////////////////
      */
 
+    public final static class EnumSerializer
+        extends JsonSerializer<Enum<?>>
+    {
+        public void serialize(Enum<?> value, JsonGenerator jgen, JsonSerializerProvider provider)
+            throws IOException, JsonGenerationException
+        {
+            jgen.writeString(value.name());
+        }
+    }
+
     /**
      * To allow for special handling for null values (in Objects, Arrays,
      * root-level), handling for nulls is done via serializers too.
diff --git a/src/java/org/codehaus/jackson/map/ser/StdSerializerProvider.java b/src/java/org/codehaus/jackson/map/ser/StdSerializerProvider.java
index 8da4729..163f340 100644
--- a/src/java/org/codehaus/jackson/map/ser/StdSerializerProvider.java
+++ b/src/java/org/codehaus/jackson/map/ser/StdSerializerProvider.java
@@ -1,8 +1,5 @@
 package org.codehaus.jackson.map.ser;
 
-import java.io.IOException;
-
-import org.codehaus.jackson.JsonGenerationException;
 import org.codehaus.jackson.JsonGenerator;
 
 import org.codehaus.jackson.map.JsonSerializer;
@@ -20,12 +17,14 @@
 public class StdSerializerProvider
     extends SerializerProviderBase
 {
-    public final static JsonSerializer<?> DEFAULT_NULL_KEY_SERIALIZER =
+    public final static JsonSerializer<Object> DEFAULT_NULL_KEY_SERIALIZER =
         new StdSerializerFactory.FailingSerializer("Null key for a Map not allower in Json (use a converting NullKeySerializer?)");
 
+    public final static JsonSerializer<Object> DEFAULT_KEY_SERIALIZER = new StdKeySerializer();
+
     /*
     ////////////////////////////////////////////////////
-    // Configuration
+    // Configuration, factories
     ////////////////////////////////////////////////////
      */
 
@@ -41,20 +40,42 @@
      */
     protected JsonSerializerFactory _overrideSerializerFactory = null;
 
+    /*
+    ////////////////////////////////////////////////////
+    // Configuration, specialized serializers
+    ////////////////////////////////////////////////////
+     */
+
+    /**
+     * Serializer that gets called for values of types for which no
+     * serializers can be constructed.
+     *<p>
+     * The default serializer will thrown an exception; a possible
+     * alternative that can be used would be
+     * {@link ToStringSerializer}.
+     */
+    protected JsonSerializer<Object> _unknownTypeSerializer;
+
+    /**
+     * Serializer used to output non-null keys of Maps (which will get
+     * output as Json Objects).
+     */
+    protected JsonSerializer<Object> _keySerializer = DEFAULT_KEY_SERIALIZER;
+
     /**
      * Serializer used to output a null value. Default implementation
      * writes nulls using {@link JsonGenerator#writeNull}.
      */
-    protected JsonSerializer<?> _nullValueSerializer = StdSerializerFactory.NullSerializer.instance;
+    protected JsonSerializer<Object> _nullValueSerializer = StdSerializerFactory.NullSerializer.instance;
 
     /**
      * Serializer used to (try to) output a null key, due to an entry of
-     * {@link Map} having null key.
+     * {@link java.util.Map} having null key.
      * The default implementation will throw an exception if this happens;
      * alternative implementation (like one that would write an Empty String)
      * can be defined.
      */
-    protected JsonSerializer<?> _nullKeySerializer = DEFAULT_NULL_KEY_SERIALIZER;
+    protected JsonSerializer<Object> _nullKeySerializer = DEFAULT_NULL_KEY_SERIALIZER;
 
     /*
     ////////////////////////////////////////////////////
@@ -86,7 +107,15 @@
         _overrideSerializerFactory = jf;
     }
 
-    public void setNullValueSerializer(JsonSerializer<?> nvs)
+    public void setKeySerializer(JsonSerializer<Object> ks)
+    {
+        if (ks == null) {
+            throw new IllegalArgumentException("Can not pass null JsonSerializer");
+        }
+        _keySerializer = ks;
+    }
+
+    public void setNullValueSerializer(JsonSerializer<Object> nvs)
     {
         if (nvs == null) {
             throw new IllegalArgumentException("Can not pass null JsonSerializer");
@@ -94,7 +123,7 @@
         _nullValueSerializer = nvs;
     }
 
-    public void setNullKeySerializer(JsonSerializer<?> nks)
+    public void setNullKeySerializer(JsonSerializer<Object> nks)
     {
         if (nks == null) {
             throw new IllegalArgumentException("Can not pass null JsonSerializer");
@@ -111,24 +140,35 @@
     @Override
     protected JsonSerializer<?> constructValueSerializer(Class<?> type)
     {
-        // !!! TBI
-        return null;
+        if (_overrideSerializerFactory != null) {
+            JsonSerializer<?> ser = _overrideSerializerFactory.createSerializer(type);
+            if (ser != null) {
+                return ser;
+            }
+        }
+        JsonSerializer<?> ser = _serializerFactory.createSerializer(type);
+        if (ser != null) {
+            return ser;
+        }
+        /* No match yet? Need to return the fallback serializer, which
+         * most likely will report an error
+         */
+        return _unknownTypeSerializer;
     }
 
     @Override
-    public final JsonSerializer<?> findNonNullKeySerializer(Class<?> type)
+    public final JsonSerializer<Object> getKeySerializer()
     {
-        // !!! TBI
-        return null;
+        return _keySerializer;
     }
 
     @Override
-    public final JsonSerializer<?> getNullKeySerializer() {
+    public final JsonSerializer<Object> getNullKeySerializer() {
         return _nullKeySerializer;
     }
 
     @Override
-    public final JsonSerializer<?> getNullValueSerializer() {
+    public final JsonSerializer<Object> getNullValueSerializer() {
         return _nullValueSerializer;
     }
 }
diff --git a/src/java/org/codehaus/jackson/map/ser/ToStringSerializer.java b/src/java/org/codehaus/jackson/map/ser/ToStringSerializer.java
new file mode 100644
index 0000000..8186607
--- /dev/null
+++ b/src/java/org/codehaus/jackson/map/ser/ToStringSerializer.java
@@ -0,0 +1,30 @@
+package org.codehaus.jackson.map.ser;
+
+import java.io.IOException;
+
+import org.codehaus.jackson.JsonGenerationException;
+import org.codehaus.jackson.JsonGenerator;
+import org.codehaus.jackson.map.JsonSerializer;
+import org.codehaus.jackson.map.JsonSerializerProvider;
+
+/**
+ * Simple general purpose serializer, useful for any
+ * type for which {@link Object#toString} returns the desired Json
+ * value.
+ */
+public final class ToStringSerializer
+    extends JsonSerializer<Object>
+{
+    /**
+     * Singleton instance to use.
+     */
+    public final static ToStringSerializer instance = new ToStringSerializer();
+
+    private ToStringSerializer() { } // no instantiation, use singleton
+    
+    public void serialize(Object value, JsonGenerator jgen, JsonSerializerProvider provider)
+        throws IOException, JsonGenerationException
+    {
+        jgen.writeString(value.toString());
+    }
+}