Working on JAXB, @XmlElements to allow polymorphic type handling.

diff --git a/build.xml b/build.xml
index b385c00..334fd78 100644
--- a/build.xml
+++ b/build.xml
@@ -44,7 +44,7 @@
     <property name="IMPL_TITLE_JAXRS" value="JAX-RS provider for Json content type, using Jackson data binding" />
     <property name="IMPL_TITLE_XC" value="XML Compatibility extensions for Jackson data binding" />
 
-    <property name="IMPL_VERSION" value="1.4.0" />
+    <property name="IMPL_VERSION" value="1.5.0" />
     <property name="IMPL_VENDOR" value="http://fasterxml.com" />
 
     <patternset id="dist-all-source-files">
diff --git a/src/mapper/java/org/codehaus/jackson/map/AnnotationIntrospector.java b/src/mapper/java/org/codehaus/jackson/map/AnnotationIntrospector.java
index bccac35..5e0a464 100644
--- a/src/mapper/java/org/codehaus/jackson/map/AnnotationIntrospector.java
+++ b/src/mapper/java/org/codehaus/jackson/map/AnnotationIntrospector.java
@@ -140,22 +140,42 @@
 
     /**
      * Method for checking if given class has annotations that indicate
-     * that specific type resolver is to be used. This includes not only
+     * that specific type resolver is to be used for handling instances.
+     * This includes not only
      * instantiating resolver builder, but also configuring it based on
      * relevant annotations (not including ones checked with a call to
-     * {@link #findAndAddSubtypes}
+     * {@link #findSubtypes}
      * 
-     * @param a Annotated entity (class, field/method) to check for annotations
-     * @param baseType Base java type of property for which resolver is to be found
+     * @param ac Annotated class to check for annotations
+     * @param baseType Base java type of value for which resolver is to be found
      * 
      * @return Type resolver builder for given type, if one found; null if none
      * 
      * @since 1.5
      */
-    public abstract TypeResolverBuilder<?> findTypeResolver(Annotated a, JavaType baseType);
+    public abstract TypeResolverBuilder<?> findTypeResolver(AnnotatedClass ac, JavaType baseType);
 
     /**
-     * Method for locating annotation-specified subtypes of given class.
+     * Method for checking if given property entity (field or method) has annotations
+     * that indicate that specific type resolver is to be used for handling instances.
+     * This includes not only
+     * instantiating resolver builder, but also configuring it based on
+     * relevant annotations (not including ones checked with a call to
+     * {@link #findSubtypes}
+     * 
+     * @param am Annotated member (field or method) to check for annotations
+     * @param baseType Base java type of property for which resolver is to be found
+     * 
+     * @return Type resolver builder for properties of given entity, if one found;
+     *    null if none
+     * 
+     * @since 1.5
+     */
+    public abstract TypeResolverBuilder<?> findPropertyTypeResolver(AnnotatedMember am, JavaType baseType);
+    
+    /**
+     * Method for locating annotation-specified subtypes related to annotated
+     * entity (class, method, field)
      * 
      * @param a Annotated entity (class, field/method) to check for annotations
      * 
@@ -676,16 +696,26 @@
         }        
 
         @Override
-        public TypeResolverBuilder<?> findTypeResolver(Annotated a, JavaType baseType)
+        public TypeResolverBuilder<?> findTypeResolver(AnnotatedClass ac, JavaType baseType)
         {
-            TypeResolverBuilder<?> b = _primary.findTypeResolver(a, baseType);
+            TypeResolverBuilder<?> b = _primary.findTypeResolver(ac, baseType);
             if (b == null) {
-                b = _secondary.findTypeResolver(a, baseType);
+                b = _secondary.findTypeResolver(ac, baseType);
             }
             return b;
         }
 
         @Override
+        public TypeResolverBuilder<?> findPropertyTypeResolver(AnnotatedMember am, JavaType baseType)
+        {
+            TypeResolverBuilder<?> b = _primary.findPropertyTypeResolver(am, baseType);
+            if (b == null) {
+                b = _secondary.findPropertyTypeResolver(am, baseType);
+            }
+            return b;
+        }
+        
+        @Override
         public List<NamedType> findSubtypes(Annotated a)
         {
             List<NamedType> types1 = _primary.findSubtypes(a);
diff --git a/src/mapper/java/org/codehaus/jackson/map/DeserializerFactory.java b/src/mapper/java/org/codehaus/jackson/map/DeserializerFactory.java
index 6b650bc..133b87d 100644
--- a/src/mapper/java/org/codehaus/jackson/map/DeserializerFactory.java
+++ b/src/mapper/java/org/codehaus/jackson/map/DeserializerFactory.java
@@ -1,6 +1,7 @@
 package org.codehaus.jackson.map;
 
 import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.map.introspect.AnnotatedMember;
 import org.codehaus.jackson.map.type.*;
 import org.codehaus.jackson.type.JavaType;
 
@@ -84,6 +85,9 @@
      * Method called to create a type information deserializer for given base type,
      * if one is needed. If not needed (no polymorphic handling configured for type),
      * should return null.
+     *<p>
+     * Note that this method is only called for values of container (Collection, array, Map)
+     * types and root values, but not for bean property values.
      *
      * @param baseType Declared base type of the value to deserializer (actual
      *    deserializer type will be this type or its subtype)
@@ -98,4 +102,28 @@
         // Default implementation returns null for backwards compatibility reasons
         return null;
     }
+
+    /**
+     * Method called to create a type information deserializer for given property entity,
+     * if one is needed. If not needed (no polymorphic handling configured for property),
+     * should return null.
+     *<p>
+     * Note that this method is only called for bean properties, and not for values in
+     * container types or root values.
+     *
+     * @param baseType Declared base type of the value to deserializer (actual
+     *    deserializer type will be this type or its subtype)
+     * @param deser Deserializer used for base type deserialization 
+     * 
+     * @return Type deserializer to use for given base type, if one is needed; null if not.
+     * 
+     * @since 1.5
+     */
+    public TypeDeserializer createPropertyTypeDeserializer(DeserializationConfig config, JavaType baseType,
+            AnnotatedMember propertyEntity)
+    {
+        // Default implementation returns null for backwards compatibility reasons
+        return null;
+    }
+
 }
diff --git a/src/mapper/java/org/codehaus/jackson/map/SerializerFactory.java b/src/mapper/java/org/codehaus/jackson/map/SerializerFactory.java
index 53338bd..c9d2c90 100644
--- a/src/mapper/java/org/codehaus/jackson/map/SerializerFactory.java
+++ b/src/mapper/java/org/codehaus/jackson/map/SerializerFactory.java
@@ -1,5 +1,6 @@
 package org.codehaus.jackson.map;
 
+import org.codehaus.jackson.map.introspect.AnnotatedMember;
 import org.codehaus.jackson.map.type.TypeFactory;
 import org.codehaus.jackson.type.JavaType;
 
@@ -61,4 +62,12 @@
         // Default implementation returns null for backwards compatibility reasons.
         return null;
     }
+
+    public TypeSerializer createPropertyTypeSerializer(JavaType baseType, SerializationConfig config,
+            AnnotatedMember property)
+    {
+        // Default implementation returns null for backwards compatibility reasons.
+        return null;
+    }
+
 }
diff --git a/src/mapper/java/org/codehaus/jackson/map/deser/BasicDeserializerFactory.java b/src/mapper/java/org/codehaus/jackson/map/deser/BasicDeserializerFactory.java
index b0d2729..7c50c52 100644
--- a/src/mapper/java/org/codehaus/jackson/map/deser/BasicDeserializerFactory.java
+++ b/src/mapper/java/org/codehaus/jackson/map/deser/BasicDeserializerFactory.java
@@ -10,6 +10,7 @@
 import org.codehaus.jackson.map.introspect.Annotated;
 import org.codehaus.jackson.map.introspect.AnnotatedClass;
 import org.codehaus.jackson.map.introspect.AnnotatedConstructor;
+import org.codehaus.jackson.map.introspect.AnnotatedMember;
 import org.codehaus.jackson.map.introspect.AnnotatedMethod;
 import org.codehaus.jackson.map.introspect.AnnotatedParameter;
 import org.codehaus.jackson.map.introspect.BasicBeanDescription;
@@ -328,6 +329,30 @@
         return (b == null) ? null : b.buildTypeDeserializer(baseType, subtypes);
     }    
 
+    
+    /**
+     * Method called to construct a type serializer for property values with given declared
+     * base type. This is only called for bean property values.
+     */
+    @Override
+    public TypeDeserializer createPropertyTypeDeserializer(DeserializationConfig config, JavaType baseType,
+            AnnotatedMember propertyEntity)
+    {
+        AnnotationIntrospector ai = config.getAnnotationIntrospector();
+        TypeResolverBuilder<?> b = ai.findPropertyTypeResolver(propertyEntity, baseType);        
+        Collection<NamedType> subtypes = null;
+        // Defaulting: if no annotations on member, check value class
+        if (b == null) {
+            return createTypeDeserializer(config, baseType);
+        }
+        // but if annotations found, may need to resolve subtypes:
+        Collection<NamedType> st = ai.findSubtypes(propertyEntity);
+        if (st != null && st.size() > 0) {
+            subtypes = _collectAndResolveSubtypes(config, ai, st);
+        }
+        return b.buildTypeDeserializer(baseType, subtypes);
+    }
+    
     protected Collection<NamedType> _collectAndResolveSubtypes(MapperConfig<?> config,
             AnnotationIntrospector ai, Collection<NamedType> subtypeList)
     {
diff --git a/src/mapper/java/org/codehaus/jackson/map/deser/BeanDeserializerFactory.java b/src/mapper/java/org/codehaus/jackson/map/deser/BeanDeserializerFactory.java
index 9b0e426..1908e7c 100644
--- a/src/mapper/java/org/codehaus/jackson/map/deser/BeanDeserializerFactory.java
+++ b/src/mapper/java/org/codehaus/jackson/map/deser/BeanDeserializerFactory.java
@@ -540,7 +540,7 @@
         
         Method m = setter.getAnnotated();
         type = modifyTypeByAnnotation(config, setter, type);
-        TypeDeserializer typeDeser = createTypeDeserializer(config, type);
+        TypeDeserializer typeDeser = createPropertyTypeDeserializer(config, type, setter);
         SettableBeanProperty prop = new SettableBeanProperty.MethodProperty(name, type, typeDeser, m);
         if (propDeser != null) {
             prop.setValueDeserializer(propDeser);
@@ -565,7 +565,7 @@
         JsonDeserializer<Object> propDeser = findDeserializerFromAnnotation(config, field);
         Field f = field.getAnnotated();
         type = modifyTypeByAnnotation(config, field, type);
-        TypeDeserializer typeDeser = createTypeDeserializer(config, type);
+        TypeDeserializer typeDeser = createPropertyTypeDeserializer(config, type, field);
         SettableBeanProperty prop = new SettableBeanProperty.FieldProperty(name, type, typeDeser, f);
         if (propDeser != null) {
             prop.setValueDeserializer(propDeser);
diff --git a/src/mapper/java/org/codehaus/jackson/map/introspect/Annotated.java b/src/mapper/java/org/codehaus/jackson/map/introspect/Annotated.java
index f9adf5a..c83cca4 100644
--- a/src/mapper/java/org/codehaus/jackson/map/introspect/Annotated.java
+++ b/src/mapper/java/org/codehaus/jackson/map/introspect/Annotated.java
@@ -14,6 +14,8 @@
  */
 public abstract class Annotated
 {
+    protected Annotated() { }
+    
     public abstract <A extends Annotation> A getAnnotation(Class<A> acls);
 
     public final <A extends Annotation> boolean hasAnnotation(Class<A> acls)
@@ -31,19 +33,30 @@
 
     public abstract String getName();
 
+    /**
+     * Full generic type of the annotated element; definition
+     * of what exactly this means depends on sub-class.
+     * 
+     * @return
+     */
     public JavaType getType() {
         return TypeFactory.type(getGenericType());
     }
 
     /**
+     * Full generic type of the annotated element; definition
+     * of what exactly this means depends on sub-class.
+     * 
      * @since 1.5
      */
     public abstract Type getGenericType();
 
     /**
+     * "Raw" type (type-erased class) of the annotated element; definition
+     * of what exactly this means depends on sub-class.
+     * 
      * @since 1.5
      */
     public abstract Class<?> getRawType();
-
 }
 
diff --git a/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedConstructor.java b/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedConstructor.java
index 2847365..9597087 100644
--- a/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedConstructor.java
+++ b/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedConstructor.java
@@ -91,7 +91,7 @@
 
     public String toString()
     {
-        return "[constructor for "+getName()+", annotations: "+_classAnnotations+"]";
+        return "[constructor for "+getName()+", annotations: "+_annotations+"]";
     }
 }
 
diff --git a/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedField.java b/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedField.java
index 693aa12..2d1e693 100644
--- a/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedField.java
+++ b/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedField.java
@@ -6,12 +6,18 @@
 
 import org.codehaus.jackson.map.util.ClassUtil;
 
+/**
+ * Object that represents non-static (and usually non-transient/volatile)
+ * fields of a class.
+ * 
+ * @author tatu
+ */
 public final class AnnotatedField
-    extends Annotated
+    extends AnnotatedMember
 {
-    final Field _field;
+    protected final Field _field;
 
-    final AnnotationMap _annotations;
+    protected final AnnotationMap _annotations;
 
     /*
     //////////////////////////////////////////////////////
diff --git a/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedMember.java b/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedMember.java
new file mode 100644
index 0000000..28b76a1
--- /dev/null
+++ b/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedMember.java
@@ -0,0 +1,15 @@
+package org.codehaus.jackson.map.introspect;
+
+/**
+ * Intermediate base class for annotated entities that are members of
+ * a class; fields, methods and constructors. This is a superset
+ * of things that can represent logical properties as it contains
+ * constructores in addition to fields and methods.
+ * 
+ * @author tatu
+ * @since 1.5
+ */
+public abstract class AnnotatedMember extends Annotated
+{
+    protected AnnotatedMember() { super(); }
+}
diff --git a/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedMethod.java b/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedMethod.java
index 10260da..b36616c 100644
--- a/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedMethod.java
+++ b/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedMethod.java
@@ -120,7 +120,7 @@
 
     public String toString()
     {
-        return "[method "+getName()+", annotations: "+_classAnnotations+"]";
+        return "[method "+getName()+", annotations: "+_annotations+"]";
     }
 }
 
diff --git a/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedWithParams.java b/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedWithParams.java
index d970b30..1b47db3 100644
--- a/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedWithParams.java
+++ b/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedWithParams.java
@@ -8,10 +8,18 @@
  * constructors and methods share.
  */
 public abstract class AnnotatedWithParams
-    extends Annotated
+    extends AnnotatedMember
 {
-    protected final AnnotationMap _classAnnotations;
+    /**
+     * Annotations directly associated with the annotated
+     * entity.
+     */
+    protected final AnnotationMap _annotations;
 
+    /**
+     * Annotations associated with parameters of the annotated
+     * entity (method or constructor parameters)
+     */
     protected final AnnotationMap[] _paramAnnotations;
 
     /*
@@ -22,7 +30,7 @@
 
     protected AnnotatedWithParams(AnnotationMap classAnn, AnnotationMap[] paramAnn)
     {
-        _classAnnotations = classAnn;
+        _annotations = classAnn;
         _paramAnnotations = paramAnn;
     }
 
@@ -32,7 +40,7 @@
      */
     public final void addOrOverride(Annotation a)
     {
-        _classAnnotations.add(a);
+        _annotations.add(a);
     }
 
     /**
@@ -58,7 +66,7 @@
      */
     public final void addIfNotPresent(Annotation a)
     {
-        _classAnnotations.addIfNotPresent(a);
+        _annotations.addIfNotPresent(a);
     }
 
     /*
@@ -69,7 +77,7 @@
 
     public final <A extends Annotation> A getAnnotation(Class<A> acls)
     {
-        return _classAnnotations.get(acls);
+        return _annotations.get(acls);
     }
 
     /*
@@ -96,5 +104,5 @@
 
     public abstract Type getParameterType(int index);
 
-    public final int getAnnotationCount() { return _classAnnotations.size(); }
+    public final int getAnnotationCount() { return _annotations.size(); }
 }
diff --git a/src/mapper/java/org/codehaus/jackson/map/introspect/JacksonAnnotationIntrospector.java b/src/mapper/java/org/codehaus/jackson/map/introspect/JacksonAnnotationIntrospector.java
index 8814f32..a8f3402 100644
--- a/src/mapper/java/org/codehaus/jackson/map/introspect/JacksonAnnotationIntrospector.java
+++ b/src/mapper/java/org/codehaus/jackson/map/introspect/JacksonAnnotationIntrospector.java
@@ -119,14 +119,19 @@
         return (ignore == null) ? null : ignore.ignoreUnknown();
     }
 
+    /*
+    /****************************************************
+    /* Class annotations for PM type handling (1.5+)
+    /****************************************************
+    */
     
     @Override
-    public TypeResolverBuilder<?> findTypeResolver(Annotated a, JavaType baseType)
+    public TypeResolverBuilder<?> findTypeResolver(AnnotatedClass ac, JavaType baseType)
     {
         // First: maybe we have explicit type resolver?
         TypeResolverBuilder<?> b;
-        JsonTypeInfo info = a.getAnnotation(JsonTypeInfo.class);
-        JsonTypeResolver resAnn = a.getAnnotation(JsonTypeResolver.class);
+        JsonTypeInfo info = ac.getAnnotation(JsonTypeInfo.class);
+        JsonTypeResolver resAnn = ac.getAnnotation(JsonTypeResolver.class);
         if (resAnn != null) {
             /* let's not try to force access override (would need to pass
              * settings through if we did, since that's not doable on some
@@ -140,7 +145,7 @@
             b = new StdTypeResolverBuilder();
         }
         // Does it define a custom type id resolver?
-        JsonTypeIdResolver idResInfo = a.getAnnotation(JsonTypeIdResolver.class);
+        JsonTypeIdResolver idResInfo = ac.getAnnotation(JsonTypeIdResolver.class);
         TypeIdResolver idRes = (idResInfo == null) ? null
                 : ClassUtil.createInstance(idResInfo.value(), false);
         b = b.init(info.use(), idRes);
@@ -150,6 +155,13 @@
     }
 
     @Override
+    public TypeResolverBuilder<?> findPropertyTypeResolver(AnnotatedMember am, JavaType baseType)
+    {
+        // No per-member type overrides (yet)
+        return null;
+    }
+    
+    @Override
     public List<NamedType> findSubtypes(Annotated a)
     {
         JsonSubTypes t = a.getAnnotation(JsonSubTypes.class);
diff --git a/src/mapper/java/org/codehaus/jackson/map/introspect/NopAnnotationIntrospector.java b/src/mapper/java/org/codehaus/jackson/map/introspect/NopAnnotationIntrospector.java
index a415f0a..6b97a44 100644
--- a/src/mapper/java/org/codehaus/jackson/map/introspect/NopAnnotationIntrospector.java
+++ b/src/mapper/java/org/codehaus/jackson/map/introspect/NopAnnotationIntrospector.java
@@ -85,8 +85,19 @@
         return null;
     }
 
+    /*
+    /****************************************************
+    /* Class annotations for PM type handling (1.5+)
+    /****************************************************
+    */
+
     @Override
-    public TypeResolverBuilder<?> findTypeResolver(Annotated a, JavaType baseType) {
+    public TypeResolverBuilder<?> findTypeResolver(AnnotatedClass ac, JavaType baseType) {
+        return null;
+    }
+
+    @Override
+    public TypeResolverBuilder<?> findPropertyTypeResolver(AnnotatedMember am, JavaType baseType) {
         return null;
     }
 
diff --git a/src/mapper/java/org/codehaus/jackson/map/ser/BasicSerializerFactory.java b/src/mapper/java/org/codehaus/jackson/map/ser/BasicSerializerFactory.java
index b44448e..abd0eee 100644
--- a/src/mapper/java/org/codehaus/jackson/map/ser/BasicSerializerFactory.java
+++ b/src/mapper/java/org/codehaus/jackson/map/ser/BasicSerializerFactory.java
@@ -8,6 +8,7 @@
 import org.codehaus.jackson.map.annotate.JsonSerialize;
 import org.codehaus.jackson.map.introspect.Annotated;
 import org.codehaus.jackson.map.introspect.AnnotatedClass;
+import org.codehaus.jackson.map.introspect.AnnotatedMember;
 import org.codehaus.jackson.map.introspect.BasicBeanDescription;
 import org.codehaus.jackson.map.jsontype.NamedType;
 import org.codehaus.jackson.map.jsontype.TypeResolverBuilder;
@@ -249,6 +250,11 @@
         return (JsonSerializer<Object>)ser;
     }
 
+    /**
+     * Method called to construct a type serializer for values with given declared
+     * base type. This is called for values other than those of bean property
+     * types.
+     */
     @Override
     public TypeSerializer createTypeSerializer(JavaType baseType, SerializationConfig config)
     {
@@ -272,6 +278,29 @@
         return (b == null) ? null : b.buildTypeSerializer(baseType, subtypes);
     }
 
+    /**
+     * Method called to construct a type serializer for property values with given declared
+     * base type. This is only called for bean property values.
+     */
+    @Override
+    public TypeSerializer createPropertyTypeSerializer(JavaType baseType, SerializationConfig config,
+            AnnotatedMember propertyEntity)
+    {
+        AnnotationIntrospector ai = config.getAnnotationIntrospector();
+        TypeResolverBuilder<?> b = ai.findPropertyTypeResolver(propertyEntity, baseType);        
+        Collection<NamedType> subtypes = null;
+        // Defaulting: if no annotations on member, check value class
+        if (b == null) {
+            return createTypeSerializer(baseType, config);
+        }
+        // but if annotations found, may need to resolve subtypes:
+        Collection<NamedType> st = ai.findSubtypes(propertyEntity);
+        if (st != null && st.size() > 0) {
+            subtypes = _collectAndResolveSubtypes(config, ai, st);
+        }
+        return b.buildTypeSerializer(baseType, subtypes);
+    }
+    
     protected Collection<NamedType> _collectAndResolveSubtypes(MapperConfig<?> config,
             AnnotationIntrospector ai, Collection<NamedType> subtypeList)
     {
diff --git a/src/mapper/java/org/codehaus/jackson/map/ser/BeanSerializerFactory.java b/src/mapper/java/org/codehaus/jackson/map/ser/BeanSerializerFactory.java
index f879ff3..78aa0cf 100644
--- a/src/mapper/java/org/codehaus/jackson/map/ser/BeanSerializerFactory.java
+++ b/src/mapper/java/org/codehaus/jackson/map/ser/BeanSerializerFactory.java
@@ -224,7 +224,7 @@
             // Does Method specify a serializer? If so, let's use it.
             JsonSerializer<Object> annotatedSerializer = findSerializerFromAnnotation(config, af);
             // And how about polymorphic typing?
-            TypeSerializer ts = createTypeSerializer(af.getType(), config);
+            TypeSerializer ts = createPropertyTypeSerializer(af.getType(), config, af);
             BeanPropertyWriter pbw = pb.buildProperty(en.getKey(), annotatedSerializer, ts, af, staticTyping);
             // how about views? (1.4+)
             pbw.setViews(intr.findSerializationViews(af));
@@ -239,7 +239,7 @@
             // Does Method specify a serializer? If so, let's use it.
             JsonSerializer<Object> annotatedSerializer = findSerializerFromAnnotation(config, am);
             // And how about polymorphic typing?
-            TypeSerializer ts = createTypeSerializer(am.getType(), config);
+            TypeSerializer ts = createPropertyTypeSerializer(am.getType(), config, am);
             BeanPropertyWriter pbw = pb.buildProperty(en.getKey(), annotatedSerializer, ts, am, staticTyping);
             pbw.setViews(intr.findSerializationViews(am));
             props.add(pbw);
diff --git a/src/mapper/java/org/codehaus/jackson/map/ser/ContainerSerializers.java b/src/mapper/java/org/codehaus/jackson/map/ser/ContainerSerializers.java
index 54448cd..3cc9a85 100644
--- a/src/mapper/java/org/codehaus/jackson/map/ser/ContainerSerializers.java
+++ b/src/mapper/java/org/codehaus/jackson/map/ser/ContainerSerializers.java
@@ -88,7 +88,7 @@
             // typing with generics is messy... have to resort to this:
             super(cls, false);
             _elementType = et;
-            // static if explicitly requested, or we got final type
+            // static if explicitly requested, or if element type is final
             _staticTyping = staticTyping || (et != null && et.isFinal());
         }
 
diff --git a/src/mapper/java/org/codehaus/jackson/map/ser/MapSerializer.java b/src/mapper/java/org/codehaus/jackson/map/ser/MapSerializer.java
index f8c9184..0517d53 100644
--- a/src/mapper/java/org/codehaus/jackson/map/ser/MapSerializer.java
+++ b/src/mapper/java/org/codehaus/jackson/map/ser/MapSerializer.java
@@ -110,7 +110,7 @@
     }
 
     @Override
-    public final void serializeWithType(Map<?,?> value, JsonGenerator jgen, SerializerProvider provider,
+    public void serializeWithType(Map<?,?> value, JsonGenerator jgen, SerializerProvider provider,
             TypeSerializer typeSer)
         throws IOException, JsonGenerationException
     {
diff --git a/src/test/org/codehaus/jackson/jaxb/BaseJaxbTest.java b/src/test/org/codehaus/jackson/jaxb/BaseJaxbTest.java
new file mode 100644
index 0000000..8d2d2ca
--- /dev/null
+++ b/src/test/org/codehaus/jackson/jaxb/BaseJaxbTest.java
@@ -0,0 +1,25 @@
+package org.codehaus.jackson.jaxb;
+
+import org.codehaus.jackson.map.*;
+import org.codehaus.jackson.xc.JaxbAnnotationIntrospector;
+
+public class BaseJaxbTest
+    extends org.codehaus.jackson.map.BaseMapTest
+{
+    protected BaseJaxbTest() { }
+    
+    /*
+     **************************************************************
+     * Helper methods
+     **************************************************************
+     */
+
+     protected ObjectMapper getJaxbMapper()
+     {
+         ObjectMapper mapper = new ObjectMapper();
+         AnnotationIntrospector intr = new JaxbAnnotationIntrospector();
+         mapper.getDeserializationConfig().setAnnotationIntrospector(intr);
+         mapper.getSerializationConfig().setAnnotationIntrospector(intr);
+         return mapper;
+     }
+}
diff --git a/src/test/org/codehaus/jackson/map/introspect/TestIntrospectorPair.java b/src/test/org/codehaus/jackson/jaxb/TestIntrospectorPair.java
similarity index 98%
rename from src/test/org/codehaus/jackson/map/introspect/TestIntrospectorPair.java
rename to src/test/org/codehaus/jackson/jaxb/TestIntrospectorPair.java
index 7b1e328..e5667d7 100644
--- a/src/test/org/codehaus/jackson/map/introspect/TestIntrospectorPair.java
+++ b/src/test/org/codehaus/jackson/jaxb/TestIntrospectorPair.java
@@ -1,4 +1,4 @@
-package org.codehaus.jackson.map.introspect;
+package org.codehaus.jackson.jaxb;
 
 import java.util.*;
 
@@ -6,6 +6,8 @@
 
 import org.codehaus.jackson.annotate.*;
 import org.codehaus.jackson.map.*;
+import org.codehaus.jackson.map.introspect.AnnotatedClass;
+import org.codehaus.jackson.map.introspect.JacksonAnnotationIntrospector;
 import org.codehaus.jackson.xc.JaxbAnnotationIntrospector;
 
 /**
diff --git a/src/test/org/codehaus/jackson/map/introspect/TestJaxbAnnotationIntrospector.java b/src/test/org/codehaus/jackson/jaxb/TestJaxbAnnotationIntrospector.java
similarity index 99%
rename from src/test/org/codehaus/jackson/map/introspect/TestJaxbAnnotationIntrospector.java
rename to src/test/org/codehaus/jackson/jaxb/TestJaxbAnnotationIntrospector.java
index ecaed53..3714cb9 100644
--- a/src/test/org/codehaus/jackson/map/introspect/TestJaxbAnnotationIntrospector.java
+++ b/src/test/org/codehaus/jackson/jaxb/TestJaxbAnnotationIntrospector.java
@@ -1,4 +1,4 @@
-package org.codehaus.jackson.map.introspect;
+package org.codehaus.jackson.jaxb;
 
 import java.io.StringWriter;
 import java.util.*;
diff --git a/src/test/org/codehaus/jackson/map/introspect/TestJaxbAutoDetect.java b/src/test/org/codehaus/jackson/jaxb/TestJaxbAutoDetect.java
similarity index 97%
rename from src/test/org/codehaus/jackson/map/introspect/TestJaxbAutoDetect.java
rename to src/test/org/codehaus/jackson/jaxb/TestJaxbAutoDetect.java
index e0f12b9..857ad13 100644
--- a/src/test/org/codehaus/jackson/map/introspect/TestJaxbAutoDetect.java
+++ b/src/test/org/codehaus/jackson/jaxb/TestJaxbAutoDetect.java
@@ -1,4 +1,4 @@
-package org.codehaus.jackson.map.introspect;
+package org.codehaus.jackson.jaxb;
 
 import java.util.*;
 import javax.xml.bind.annotation.*;
diff --git a/src/test/org/codehaus/jackson/map/introspect/TestJaxbFieldAccess.java b/src/test/org/codehaus/jackson/jaxb/TestJaxbFieldAccess.java
similarity index 96%
rename from src/test/org/codehaus/jackson/map/introspect/TestJaxbFieldAccess.java
rename to src/test/org/codehaus/jackson/jaxb/TestJaxbFieldAccess.java
index 91f423c..459baaa 100644
--- a/src/test/org/codehaus/jackson/map/introspect/TestJaxbFieldAccess.java
+++ b/src/test/org/codehaus/jackson/jaxb/TestJaxbFieldAccess.java
@@ -1,4 +1,4 @@
-package org.codehaus.jackson.map.introspect;
+package org.codehaus.jackson.jaxb;
 
 import java.io.IOException;
 
diff --git a/src/test/org/codehaus/jackson/jaxb/TestJaxbPolymorphic.java b/src/test/org/codehaus/jackson/jaxb/TestJaxbPolymorphic.java
new file mode 100644
index 0000000..5a20db3
--- /dev/null
+++ b/src/test/org/codehaus/jackson/jaxb/TestJaxbPolymorphic.java
@@ -0,0 +1,92 @@
+package org.codehaus.jackson.jaxb;
+
+import java.util.*;
+import javax.xml.bind.annotation.*;
+
+import org.codehaus.jackson.map.ObjectMapper;
+
+/**
+ * Tests for handling of type-related JAXB annotations 
+ */
+public class TestJaxbPolymorphic 
+    extends BaseJaxbTest
+{
+    /*
+     **************************************************************
+     * Helper beans
+     **************************************************************
+     */
+
+     static class Bean 
+     {
+         @XmlElements({
+                 @XmlElement(type=Buffalo.class, name="beefalot"),
+                 @XmlElement(type=Whale.class, name="whale")
+         })
+         public Animal animal;
+
+         public Bean() { }
+         public Bean(Animal a) { animal = a; }
+     }
+
+     static abstract class Animal {
+         public String nickname;
+
+         protected Animal() { }
+         protected Animal(String n) { nickname = n; }
+     }
+
+     static class Buffalo extends Animal {
+         public String hairColor;
+
+         public Buffalo() { }
+         public Buffalo(String name, String hc) {
+             super(name);
+             hairColor = hc;
+         }
+     }
+
+     static class Whale extends Animal {
+         int weightInTons;
+         public Whale() { }
+         public Whale(String n, int w) {
+             super(n);
+             weightInTons = w;
+         }
+     }
+
+     /*
+      **************************************************************
+      * Tests
+      **************************************************************
+      */
+
+     /**
+      * First a simple test with non-collection field
+      */
+     @SuppressWarnings("unchecked")
+    public void testXmlElementTypeDeser() throws Exception
+     {
+         ObjectMapper mapper = getJaxbMapper();
+         Bean input = new Bean(new Buffalo("Billy", "brown"));
+         String str = mapper.writeValueAsString(input);
+         // First: let's verify output looks like what we expect:
+         Map<String,Object> map = mapper.readValue(str, Map.class);
+         assertEquals(1, map.size());
+         Map<String,Object> map2 = (Map<String,Object>) map.get("animal");
+         assertNotNull(map2);
+         // second level, should have type info as WRAPPER_OBJECT
+         assertEquals(1, map2.size());
+         assertTrue(map2.containsKey("beefalot"));
+         Map<String,Object> map3 = (Map<String,Object>) map2.get("beefalot");
+         assertEquals(2, map3.size());
+         // good enough, let's deserialize
+         
+         Bean result = mapper.readValue(str, Bean.class);
+         Animal a = result.animal;
+         assertNotNull(a);
+         assertEquals(Buffalo.class, a.getClass());
+         assertEquals("Billy", a.nickname);
+         assertEquals("brown", ((Buffalo) a).hairColor);
+     }
+}
diff --git a/src/test/org/codehaus/jackson/map/introspect/TestJaxbTypes.java b/src/test/org/codehaus/jackson/jaxb/TestJaxbTypes.java
similarity index 67%
rename from src/test/org/codehaus/jackson/map/introspect/TestJaxbTypes.java
rename to src/test/org/codehaus/jackson/jaxb/TestJaxbTypes.java
index b4b9ac4..0e944af 100644
--- a/src/test/org/codehaus/jackson/map/introspect/TestJaxbTypes.java
+++ b/src/test/org/codehaus/jackson/jaxb/TestJaxbTypes.java
@@ -1,15 +1,14 @@
-package org.codehaus.jackson.map.introspect;
+package org.codehaus.jackson.jaxb;
 
 import javax.xml.bind.annotation.*;
 
 import org.codehaus.jackson.map.*;
-import org.codehaus.jackson.xc.JaxbAnnotationIntrospector;
 
 /**
  * Tests for handling of type-related JAXB annotations 
  */
 public class TestJaxbTypes
-    extends org.codehaus.jackson.map.BaseMapTest
+    extends BaseJaxbTest
 {
     /*
     **************************************************************
@@ -53,19 +52,4 @@
         assertEquals(13, bean.a);
         assertEquals("...", bean.b);
     }
-
-    /*
-    **************************************************************
-    * Helper methods
-    **************************************************************
-    */
-
-    public ObjectMapper getJaxbMapper()
-    {
-        ObjectMapper mapper = new ObjectMapper();
-        AnnotationIntrospector intr = new JaxbAnnotationIntrospector();
-        mapper.getDeserializationConfig().setAnnotationIntrospector(intr);
-        mapper.getSerializationConfig().setAnnotationIntrospector(intr);
-        return mapper;
-    }
 }
diff --git a/src/xc/java/org/codehaus/jackson/xc/JaxbAnnotationIntrospector.java b/src/xc/java/org/codehaus/jackson/xc/JaxbAnnotationIntrospector.java
index 5225668..b7442d4 100644
--- a/src/xc/java/org/codehaus/jackson/xc/JaxbAnnotationIntrospector.java
+++ b/src/xc/java/org/codehaus/jackson/xc/JaxbAnnotationIntrospector.java
@@ -228,13 +228,26 @@
         return null;
     }
 
+    /*
+    /****************************************************
+    /* Class annotations for PM type handling (1.5+)
+    /****************************************************
+    */
+    
     @Override
-    public TypeResolverBuilder<?> findTypeResolver(Annotated a, JavaType baseType)
+    public TypeResolverBuilder<?> findTypeResolver(AnnotatedClass ac, JavaType baseType)
+    {
+        // no per-class type resolvers, right?
+        return null;
+    }
+
+    @Override
+    public TypeResolverBuilder<?> findPropertyTypeResolver(AnnotatedMember am, JavaType baseType)
     {
         /* Assumption: existence of @XmlElements implies need to add
          * type information.
          */
-        XmlElements elems = findAnnotation(XmlElements.class, a, false, false, false);
+        XmlElements elems = findAnnotation(XmlElements.class, am, false, false, false);
         if (elems == null) {
             return null;
         }