Proposed refactoring for MIME4J-116.
FieldParser has been moved to the dom package and field parsing is expected to happen inside the MutableBodyDescriptor implementation.
Minimal/MaximalBodyDescriptor implementations takes a FieldParser instance and a boolean saying if they are expected to parse every field supported by the FieldParser or only the one used for the descriptor results, so that EntityBuilder doesn't have to know the FieldParser again.

git-svn-id: https://svn.apache.org/repos/asf/james/mime4j/branches/mime4j-116-refactoring@1138155 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/core/src/main/java/org/apache/james/mime4j/parser/MimeStreamParser.java b/core/src/main/java/org/apache/james/mime4j/parser/MimeStreamParser.java
index ad10e5b..2625673 100644
--- a/core/src/main/java/org/apache/james/mime4j/parser/MimeStreamParser.java
+++ b/core/src/main/java/org/apache/james/mime4j/parser/MimeStreamParser.java
@@ -26,7 +26,7 @@
 import org.apache.james.mime4j.codec.DecodeMonitor;
 import org.apache.james.mime4j.stream.BodyDescriptor;
 import org.apache.james.mime4j.stream.EntityState;
-import org.apache.james.mime4j.stream.FieldParser;
+import org.apache.james.mime4j.stream.Field;
 import org.apache.james.mime4j.stream.MimeEntityConfig;
 import org.apache.james.mime4j.stream.MimeTokenStream;
 import org.apache.james.mime4j.stream.MutableBodyDescriptorFactory;
@@ -66,9 +66,8 @@
             final MimeEntityConfig config, 
             boolean clone,
             final DecodeMonitor monitor,
-            final FieldParser<?> fieldParser,
             final MutableBodyDescriptorFactory bodyDescFactory) {
-        this(new MimeTokenStream(clone ? config.clone() : config, monitor, fieldParser, bodyDescFactory));
+        this(new MimeTokenStream(clone ? config.clone() : config, monitor, bodyDescFactory));
     }
 
     public MimeStreamParser(final MimeEntityConfig config, boolean clone) {
@@ -78,18 +77,17 @@
     public MimeStreamParser(
             final MimeEntityConfig config,
             final DecodeMonitor monitor,
-            final FieldParser<?> fieldParser,
             final MutableBodyDescriptorFactory bodyDescFactory) {
         this(config != null ? config : new MimeEntityConfig(), config != null, 
-                monitor, fieldParser, bodyDescFactory);
+                monitor, bodyDescFactory);
     }
 
     public MimeStreamParser(final MimeEntityConfig config) {
-        this(config, null, null, null);
+        this(config, null, null);
     }
 
     public MimeStreamParser() {
-        this(new MimeEntityConfig(), false, null, null, null);
+        this(new MimeEntityConfig(), false, null, null);
     }
     
     /**
@@ -119,10 +117,10 @@
      */
     public void parse(InputStream inputStream) throws MimeException, IOException {
         if (mimeEntityConfig.getHeadlessParsing() != null) {
-            mimeTokenStream.parseHeadless(inputStream, mimeEntityConfig.getHeadlessParsing());
+            Field contentType = mimeTokenStream.parseHeadless(inputStream, mimeEntityConfig.getHeadlessParsing());
             handler.startMessage();
             handler.startHeader();
-            handler.field(new RawField("Content-Type", mimeEntityConfig.getHeadlessParsing()));
+            handler.field(contentType);
             handler.endHeader();
         } else {
             mimeTokenStream.parse(inputStream);
diff --git a/core/src/main/java/org/apache/james/mime4j/stream/AbstractEntity.java b/core/src/main/java/org/apache/james/mime4j/stream/AbstractEntity.java
index 04a8bd9..bb52ef7 100644
--- a/core/src/main/java/org/apache/james/mime4j/stream/AbstractEntity.java
+++ b/core/src/main/java/org/apache/james/mime4j/stream/AbstractEntity.java
@@ -39,7 +39,6 @@
     protected final MimeEntityConfig config;
     protected final DecodeMonitor monitor;
     protected final FieldBuilder fieldBuilder;
-    protected final FieldParser<?> fieldParser;
     protected final MutableBodyDescriptor body;
 
     private final ByteArrayBuffer linebuf;
@@ -56,7 +55,6 @@
             EntityState endState,
             DecodeMonitor monitor,
             FieldBuilder fieldBuilder,
-            FieldParser<?> fieldParser,
             MutableBodyDescriptor body) {
         this.config = config;
         this.state = startState;
@@ -64,7 +62,6 @@
         this.endState = endState;
         this.monitor = monitor;
         this.fieldBuilder = fieldBuilder;
-        this.fieldParser = fieldParser;
         this.body = body;
         this.linebuf = new ByteArrayBuffer(64);
         this.lineCount = 0;
@@ -149,12 +146,9 @@
                 if (rawfield.getDelimiterIdx() != rawfield.getName().length()) {
                     monitor(Event.OBSOLETE_HEADER);
                 }
-                if (fieldParser != null) {
-                    field = fieldParser.parse(rawfield, monitor);
-                } else {
-                    field = rawfield;
-                }
-                body.addField(field);
+                Field newfield = body.addField(rawfield);
+                if (newfield != null) field = newfield;
+                else field = rawfield;
                 return true;
             } catch (MimeException e) {
                 monitor(Event.INVALID_HEADER);
diff --git a/core/src/main/java/org/apache/james/mime4j/stream/DefaultBodyDescriptor.java b/core/src/main/java/org/apache/james/mime4j/stream/DefaultBodyDescriptor.java
index 7025d5b..f11fb9e 100644
--- a/core/src/main/java/org/apache/james/mime4j/stream/DefaultBodyDescriptor.java
+++ b/core/src/main/java/org/apache/james/mime4j/stream/DefaultBodyDescriptor.java
@@ -101,7 +101,7 @@
      * 
      * @param field the MIME field.
      */
-    public void addField(Field field) throws MimeException {
+    public Field addField(RawField field) throws MimeException {
         String name = field.getName().toLowerCase(Locale.US);
         
         if (name.equals("content-transfer-encoding") && !contentTransferEncSet) {
@@ -129,6 +129,7 @@
         } else if (name.equals("content-type") && !contentTypeSet) {
             parseContentType(field);
         }
+        return null;
     }
 
     private void parseContentType(Field field) throws MimeException {
diff --git a/core/src/main/java/org/apache/james/mime4j/stream/MimeEntity.java b/core/src/main/java/org/apache/james/mime4j/stream/MimeEntity.java
index 0a82f9c..ea03e6e 100644
--- a/core/src/main/java/org/apache/james/mime4j/stream/MimeEntity.java
+++ b/core/src/main/java/org/apache/james/mime4j/stream/MimeEntity.java
@@ -53,9 +53,8 @@
             EntityState endState,
             DecodeMonitor monitor,
             FieldBuilder fieldBuilder,
-            FieldParser<?> fieldParser,
             MutableBodyDescriptor body) {
-        super(config, startState, endState, monitor, fieldBuilder, fieldParser, body);
+        super(config, startState, endState, monitor, fieldBuilder, body);
         this.lineSource = lineSource;
         this.inbuffer = new BufferedLineReaderInputStream(
                 instream,
@@ -75,7 +74,7 @@
             MutableBodyDescriptor body) {
         this(lineSource, instream, config, startState, endState,
                 config.isStrictParsing() ? DecodeMonitor.STRICT : DecodeMonitor.SILENT,
-                new DefaultFieldBuilder(config.getMaxHeaderLen()), null, body);
+                new DefaultFieldBuilder(config.getMaxHeaderLen()), body);
     }
 
     MimeEntity(
@@ -86,19 +85,18 @@
         this(lineSource, instream, config,
                 EntityState.T_START_MESSAGE, EntityState.T_END_MESSAGE,
                 config.isStrictParsing() ? DecodeMonitor.STRICT : DecodeMonitor.SILENT,
-                new DefaultFieldBuilder(config.getMaxHeaderLen()), null, body);
+                new DefaultFieldBuilder(config.getMaxHeaderLen()), body);
     }
 
     MimeEntity(
             LineNumberSource lineSource,
             InputStream instream,
             FieldBuilder fieldBuilder,
-            FieldParser<?> fieldParser,
             MutableBodyDescriptor body) {
         this(lineSource, instream, new MimeEntityConfig(),
                 EntityState.T_START_MESSAGE, EntityState.T_END_MESSAGE,
                 DecodeMonitor.SILENT,
-                fieldBuilder, fieldParser, body);
+                fieldBuilder, body);
     }
 
     MimeEntity(
@@ -108,7 +106,7 @@
         this(lineSource, instream, new MimeEntityConfig(),
                 EntityState.T_START_MESSAGE, EntityState.T_END_MESSAGE,
                 DecodeMonitor.SILENT,
-                new DefaultFieldBuilder(-1), null, body);
+                new DefaultFieldBuilder(-1), body);
     }
 
     public RecursionMode getRecursionMode() {
@@ -279,7 +277,6 @@
                     endState,
                     monitor,
                     fieldBuilder,
-                    fieldParser,
                     body.newChild());
             mimeentity.setRecursionMode(recursionMode);
             return mimeentity;
diff --git a/core/src/main/java/org/apache/james/mime4j/stream/MimeTokenStream.java b/core/src/main/java/org/apache/james/mime4j/stream/MimeTokenStream.java
index fdfe952..14c3a66 100644
--- a/core/src/main/java/org/apache/james/mime4j/stream/MimeTokenStream.java
+++ b/core/src/main/java/org/apache/james/mime4j/stream/MimeTokenStream.java
@@ -75,7 +75,6 @@
     private final MimeEntityConfig config;
     private final DecodeMonitor monitor;
     private final FieldBuilder fieldBuilder;
-    private final FieldParser<?> fieldParser;
     private final MutableBodyDescriptorFactory bodyDescFactory;
     private final LinkedList<EntityStateMachine> entities = new LinkedList<EntityStateMachine>();
     
@@ -97,35 +96,31 @@
     }
 
     public MimeTokenStream(final MimeEntityConfig config) {
-        this(config, null, null, null, null);
+        this(config, null, null, null);
     }
         
     public MimeTokenStream(
             final MimeEntityConfig config, 
-            final FieldParser<?> fieldParser,
             final MutableBodyDescriptorFactory bodyDescFactory) {
-        this(config, null, null, fieldParser, bodyDescFactory);
+        this(config, null, null, bodyDescFactory);
     }
 
     public MimeTokenStream(
             final MimeEntityConfig config, 
             final DecodeMonitor monitor,
-            final FieldParser<?> fieldParser,
             final MutableBodyDescriptorFactory bodyDescFactory) {
-        this(config, monitor, null, fieldParser, bodyDescFactory);
+        this(config, monitor, null, bodyDescFactory);
     }
 
     public MimeTokenStream(
             final MimeEntityConfig config, 
             final DecodeMonitor monitor,
             final FieldBuilder fieldBuilder,
-            final FieldParser<?> fieldParser,
             final MutableBodyDescriptorFactory bodyDescFactory) {
         super();
         this.config = config;
         this.fieldBuilder = fieldBuilder != null ? fieldBuilder : 
             new DefaultFieldBuilder(config.getMaxHeaderLen());
-        this.fieldParser = fieldParser;
         this.monitor = monitor != null ? monitor : 
             (config.isStrictParsing() ? DecodeMonitor.STRICT : DecodeMonitor.SILENT);
         this.bodyDescFactory = bodyDescFactory;
@@ -139,26 +134,31 @@
         doParse(stream, newBodyDescriptor(), EntityState.T_START_MESSAGE);
     }
 
-    /** Instructs the {@code MimeTokenStream} to parse the given content with 
+    /** 
+     * <p>Instructs the {@code MimeTokenStream} to parse the given content with 
      * the content type. The message stream is assumed to have no message header
      * and is expected to begin with a message body. This can be the case when 
      * the message content is transmitted using a different transport protocol 
-     * such as HTTP.
-     * <p/>
-     * If the {@code MimeTokenStream} has already been in use, resets the streams
-     * internal state.
+     * such as HTTP.</p>
+     * <p>If the {@code MimeTokenStream} has already been in use, resets the 
+     * streams internal state.</p>
+     * @return a parsed Field representing the input contentType
      */    
-    public void parseHeadless(InputStream stream, String contentType) {
+    public Field parseHeadless(InputStream stream, String contentType) {
         if (contentType == null) {
             throw new IllegalArgumentException("Content type may not be null");
         }
+        Field newContentType;
         MutableBodyDescriptor newBodyDescriptor = newBodyDescriptor();
         try {
-            newBodyDescriptor.addField(new RawField("Content-Type", contentType));
+            RawField rawContentType = new RawField("Content-Type", contentType);
+            newContentType = newBodyDescriptor.addField(rawContentType);
+            if (newContentType == null) newContentType = rawContentType;
         } catch (MimeException ex) {
             // should never happen
             throw new IllegalArgumentException(ex.getMessage());
         }
+        
         doParse(stream, newBodyDescriptor, EntityState.T_END_HEADER);
         try {
             next();
@@ -169,6 +169,7 @@
             // This should never happen
             throw new IllegalStateException(e);
         }
+        return newContentType;
     }
 
     /**
@@ -203,7 +204,6 @@
                 EntityState.T_END_MESSAGE,
                 monitor,
                 fieldBuilder,
-                fieldParser,
                 newBodyDescriptor);
 
         rootentity.setRecursionMode(recursionMode);
diff --git a/core/src/main/java/org/apache/james/mime4j/stream/MutableBodyDescriptor.java b/core/src/main/java/org/apache/james/mime4j/stream/MutableBodyDescriptor.java
index 04c2861..b571119 100644
--- a/core/src/main/java/org/apache/james/mime4j/stream/MutableBodyDescriptor.java
+++ b/core/src/main/java/org/apache/james/mime4j/stream/MutableBodyDescriptor.java
@@ -30,8 +30,10 @@
     /**
      * Adds a field to the body descriptor.
      * @param field the MIME field.
+     * 
+     * @return null or an elaborated field representing the same data.
      */
-    void addField(Field field) throws MimeException;
+    Field addField(RawField field) throws MimeException;
     
     MutableBodyDescriptor newChild();
 
diff --git a/core/src/test/java/org/apache/james/mime4j/stream/MimeEntityTest.java b/core/src/test/java/org/apache/james/mime4j/stream/MimeEntityTest.java
index 8937a11..528ae1c 100644
--- a/core/src/test/java/org/apache/james/mime4j/stream/MimeEntityTest.java
+++ b/core/src/test/java/org/apache/james/mime4j/stream/MimeEntityTest.java
@@ -666,7 +666,7 @@
 
         MimeEntity entity = new MimeEntity(
                 lineInput,
-                rawstream, fieldBuilder, null, new DefaultBodyDescriptor());
+                rawstream, fieldBuilder, new DefaultBodyDescriptor());
 
 
         assertEquals(EntityState.T_START_MESSAGE, entity.getState());
diff --git a/core/src/main/java/org/apache/james/mime4j/stream/FieldParser.java b/dom/src/main/java/org/apache/james/mime4j/dom/FieldParser.java
similarity index 86%
rename from core/src/main/java/org/apache/james/mime4j/stream/FieldParser.java
rename to dom/src/main/java/org/apache/james/mime4j/dom/FieldParser.java
index 322d3b4..b30516e 100644
--- a/core/src/main/java/org/apache/james/mime4j/stream/FieldParser.java
+++ b/dom/src/main/java/org/apache/james/mime4j/dom/FieldParser.java
@@ -17,11 +17,13 @@
  * under the License.                                           *
  ****************************************************************/
 
-package org.apache.james.mime4j.stream;
+package org.apache.james.mime4j.dom;
 
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.field.ParsedField;
+import org.apache.james.mime4j.stream.Field;
 
-public interface FieldParser<T extends Field> {
+public interface FieldParser<T extends ParsedField> {
     
     T parse(Field rawField, DecodeMonitor monitor);
     
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/AddressListFieldImpl.java b/dom/src/main/java/org/apache/james/mime4j/field/AddressListFieldImpl.java
index df6d618..f45c15b 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/AddressListFieldImpl.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/AddressListFieldImpl.java
@@ -20,12 +20,12 @@
 package org.apache.james.mime4j.field;
 
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.address.AddressList;
 import org.apache.james.mime4j.dom.field.AddressListField;
 import org.apache.james.mime4j.field.address.AddressBuilder;
 import org.apache.james.mime4j.field.address.ParseException;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 
 /**
  * Address list field such as <code>To</code> or <code>Reply-To</code>.
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/AddressListFieldLenientImpl.java b/dom/src/main/java/org/apache/james/mime4j/field/AddressListFieldLenientImpl.java
index 0dabe4c..6be4474 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/AddressListFieldLenientImpl.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/AddressListFieldLenientImpl.java
@@ -22,12 +22,12 @@
 import java.util.Collections;
 
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.address.AddressList;
 import org.apache.james.mime4j.dom.address.Mailbox;
 import org.apache.james.mime4j.dom.field.AddressListField;
 import org.apache.james.mime4j.field.address.LenientAddressBuilder;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 import org.apache.james.mime4j.stream.ParserCursor;
 import org.apache.james.mime4j.stream.RawField;
 import org.apache.james.mime4j.util.ByteSequence;
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/ContentDescriptionFieldImpl.java b/dom/src/main/java/org/apache/james/mime4j/field/ContentDescriptionFieldImpl.java
index 1536771..86333e8 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/ContentDescriptionFieldImpl.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/ContentDescriptionFieldImpl.java
@@ -20,9 +20,9 @@
 package org.apache.james.mime4j.field;
 
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.field.ContentDescriptionField;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 
 /**
  * Represents a <code>Content-Description</code> field.
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/ContentDispositionFieldImpl.java b/dom/src/main/java/org/apache/james/mime4j/field/ContentDispositionFieldImpl.java
index 295c874..de5a225 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/ContentDispositionFieldImpl.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/ContentDispositionFieldImpl.java
@@ -28,13 +28,13 @@
 import java.util.Map;
 
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.field.ContentDispositionField;
 import org.apache.james.mime4j.field.contentdisposition.parser.ContentDispositionParser;
 import org.apache.james.mime4j.field.contentdisposition.parser.ParseException;
 import org.apache.james.mime4j.field.contentdisposition.parser.TokenMgrError;
 import org.apache.james.mime4j.field.datetime.parser.DateTimeParser;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 
 /**
  * Represents a <code>Content-Disposition</code> field.
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/ContentDispositionFieldLenientImpl.java b/dom/src/main/java/org/apache/james/mime4j/field/ContentDispositionFieldLenientImpl.java
index c37c0e8..4bb5e70 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/ContentDispositionFieldLenientImpl.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/ContentDispositionFieldLenientImpl.java
@@ -32,9 +32,9 @@
 import java.util.TimeZone;
 
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.field.ContentDispositionField;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 import org.apache.james.mime4j.stream.NameValuePair;
 import org.apache.james.mime4j.stream.RawBody;
 import org.apache.james.mime4j.stream.RawField;
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/ContentIdFieldImpl.java b/dom/src/main/java/org/apache/james/mime4j/field/ContentIdFieldImpl.java
index 5e90e0c..0d47f06 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/ContentIdFieldImpl.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/ContentIdFieldImpl.java
@@ -20,9 +20,9 @@
 package org.apache.james.mime4j.field;
 
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.field.ContentIdField;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 
 /**
  * Represents a <code>Content-Transfer-Encoding</code> field.
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/ContentLanguageFieldImpl.java b/dom/src/main/java/org/apache/james/mime4j/field/ContentLanguageFieldImpl.java
index 0739e9e..3546b71 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/ContentLanguageFieldImpl.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/ContentLanguageFieldImpl.java
@@ -25,11 +25,11 @@
 import java.util.List;
 
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.field.ContentLanguageField;
 import org.apache.james.mime4j.field.language.parser.ContentLanguageParser;
 import org.apache.james.mime4j.field.language.parser.ParseException;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 
 /**
  * Represents a <code>Content-Transfer-Encoding</code> field.
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/ContentLanguageFieldLenientImpl.java b/dom/src/main/java/org/apache/james/mime4j/field/ContentLanguageFieldLenientImpl.java
index 6618fa2..b5c3c26 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/ContentLanguageFieldLenientImpl.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/ContentLanguageFieldLenientImpl.java
@@ -24,9 +24,9 @@
 import java.util.List;
 
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.field.ContentLanguageField;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 import org.apache.james.mime4j.stream.ParserCursor;
 import org.apache.james.mime4j.stream.RawField;
 import org.apache.james.mime4j.stream.RawFieldParser;
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/ContentLengthFieldImpl.java b/dom/src/main/java/org/apache/james/mime4j/field/ContentLengthFieldImpl.java
index 136c11b..e9f22ea 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/ContentLengthFieldImpl.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/ContentLengthFieldImpl.java
@@ -20,9 +20,9 @@
 package org.apache.james.mime4j.field;
 
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.field.ContentLengthField;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 
 /**
  * Represents a <code>Content-Length</code> field.
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/ContentLocationFieldImpl.java b/dom/src/main/java/org/apache/james/mime4j/field/ContentLocationFieldImpl.java
index 69e5827..87a34ae 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/ContentLocationFieldImpl.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/ContentLocationFieldImpl.java
@@ -22,11 +22,11 @@
 import java.io.StringReader;
 
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.field.ContentLocationField;
 import org.apache.james.mime4j.field.structured.parser.ParseException;
 import org.apache.james.mime4j.field.structured.parser.StructuredFieldParser;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 
 /**
  * Represents a <code>Content-Location</code> field.
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/ContentLocationFieldLenientImpl.java b/dom/src/main/java/org/apache/james/mime4j/field/ContentLocationFieldLenientImpl.java
index 6a22dc0..04be41e 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/ContentLocationFieldLenientImpl.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/ContentLocationFieldLenientImpl.java
@@ -20,9 +20,9 @@
 package org.apache.james.mime4j.field;
 
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.field.ContentLocationField;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 import org.apache.james.mime4j.stream.ParserCursor;
 import org.apache.james.mime4j.stream.RawField;
 import org.apache.james.mime4j.stream.RawFieldParser;
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/ContentMD5FieldImpl.java b/dom/src/main/java/org/apache/james/mime4j/field/ContentMD5FieldImpl.java
index ba178ed..f1d47d3 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/ContentMD5FieldImpl.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/ContentMD5FieldImpl.java
@@ -20,9 +20,9 @@
 package org.apache.james.mime4j.field;
 
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.field.ContentMD5Field;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 
 /**
  * Represents a <code>Content-MD5</code> field.
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/ContentTransferEncodingFieldImpl.java b/dom/src/main/java/org/apache/james/mime4j/field/ContentTransferEncodingFieldImpl.java
index 57c7315..d4e96cf 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/ContentTransferEncodingFieldImpl.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/ContentTransferEncodingFieldImpl.java
@@ -22,9 +22,9 @@
 import java.util.Locale;
 
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.field.ContentTransferEncodingField;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 import org.apache.james.mime4j.util.MimeUtil;
 
 /**
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/ContentTypeFieldImpl.java b/dom/src/main/java/org/apache/james/mime4j/field/ContentTypeFieldImpl.java
index 495cd03..6704ed4 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/ContentTypeFieldImpl.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/ContentTypeFieldImpl.java
@@ -26,12 +26,12 @@
 import java.util.Map;
 
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.field.ContentTypeField;
 import org.apache.james.mime4j.field.contenttype.parser.ContentTypeParser;
 import org.apache.james.mime4j.field.contenttype.parser.ParseException;
 import org.apache.james.mime4j.field.contenttype.parser.TokenMgrError;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 
 /**
  * Represents a <code>Content-Type</code> field.
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/ContentTypeFieldLenientImpl.java b/dom/src/main/java/org/apache/james/mime4j/field/ContentTypeFieldLenientImpl.java
index 0730544..309f98a 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/ContentTypeFieldLenientImpl.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/ContentTypeFieldLenientImpl.java
@@ -25,9 +25,9 @@
 import java.util.Map;
 
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.field.ContentTypeField;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 import org.apache.james.mime4j.stream.NameValuePair;
 import org.apache.james.mime4j.stream.RawBody;
 import org.apache.james.mime4j.stream.RawField;
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/DateTimeFieldImpl.java b/dom/src/main/java/org/apache/james/mime4j/field/DateTimeFieldImpl.java
index 0b6f398..7317732 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/DateTimeFieldImpl.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/DateTimeFieldImpl.java
@@ -23,12 +23,12 @@
 import java.util.Date;
 
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.field.DateTimeField;
 import org.apache.james.mime4j.field.datetime.parser.DateTimeParser;
 import org.apache.james.mime4j.field.datetime.parser.ParseException;
 import org.apache.james.mime4j.field.datetime.parser.TokenMgrError;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 
 /**
  * Date-time field such as <code>Date</code> or <code>Resent-Date</code>.
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/DateTimeFieldLenientImpl.java b/dom/src/main/java/org/apache/james/mime4j/field/DateTimeFieldLenientImpl.java
index 897e1ff..be8659d 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/DateTimeFieldLenientImpl.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/DateTimeFieldLenientImpl.java
@@ -29,9 +29,9 @@
 import java.util.TimeZone;
 
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.field.DateTimeField;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 
 /**
  * Date-time field such as <code>Date</code> or <code>Resent-Date</code>.
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/DefaultFieldParser.java b/dom/src/main/java/org/apache/james/mime4j/field/DefaultFieldParser.java
index 58e6278..a834bc2 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/DefaultFieldParser.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/DefaultFieldParser.java
@@ -21,6 +21,7 @@
 
 import org.apache.james.mime4j.MimeException;
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.field.AddressListField;
 import org.apache.james.mime4j.dom.field.DateTimeField;
 import org.apache.james.mime4j.dom.field.FieldName;
@@ -28,7 +29,6 @@
 import org.apache.james.mime4j.dom.field.MailboxListField;
 import org.apache.james.mime4j.dom.field.ParsedField;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 import org.apache.james.mime4j.stream.RawField;
 import org.apache.james.mime4j.stream.RawFieldParser;
 import org.apache.james.mime4j.util.ByteSequence;
@@ -113,7 +113,7 @@
         setFieldParser(FieldName.CONTENT_DISPOSITION,
                 ContentDispositionFieldImpl.PARSER);
         setFieldParser(FieldName.CONTENT_ID,
-                ContentDispositionFieldImpl.PARSER);
+                ContentIdFieldImpl.PARSER);
         setFieldParser(FieldName.CONTENT_MD5,
                 ContentMD5FieldImpl.PARSER);
         setFieldParser(FieldName.CONTENT_DESCRIPTION,
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/DelegatingFieldParser.java b/dom/src/main/java/org/apache/james/mime4j/field/DelegatingFieldParser.java
index 2171963..47fadfb 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/DelegatingFieldParser.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/DelegatingFieldParser.java
@@ -23,9 +23,9 @@
 import java.util.Map;
 
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.field.ParsedField;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 
 public class DelegatingFieldParser implements FieldParser<ParsedField> {
 
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/Fields.java b/dom/src/main/java/org/apache/james/mime4j/field/Fields.java
index 3d92d60..4deaedb 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/Fields.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/Fields.java
@@ -29,6 +29,7 @@
 
 import org.apache.james.mime4j.codec.DecodeMonitor;
 import org.apache.james.mime4j.codec.EncoderUtil;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.address.Address;
 import org.apache.james.mime4j.dom.address.Mailbox;
 import org.apache.james.mime4j.dom.field.AddressListField;
@@ -43,7 +44,6 @@
 import org.apache.james.mime4j.dom.field.UnstructuredField;
 import org.apache.james.mime4j.field.address.AddressFormatter;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 import org.apache.james.mime4j.stream.RawField;
 import org.apache.james.mime4j.util.MimeUtil;
 
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/LenientFieldParser.java b/dom/src/main/java/org/apache/james/mime4j/field/LenientFieldParser.java
index 7d5f36c..47fdd4e 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/LenientFieldParser.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/LenientFieldParser.java
@@ -21,6 +21,7 @@
 
 import org.apache.james.mime4j.MimeException;
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.field.AddressListField;
 import org.apache.james.mime4j.dom.field.DateTimeField;
 import org.apache.james.mime4j.dom.field.FieldName;
@@ -28,7 +29,6 @@
 import org.apache.james.mime4j.dom.field.MailboxListField;
 import org.apache.james.mime4j.dom.field.ParsedField;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 import org.apache.james.mime4j.stream.RawField;
 import org.apache.james.mime4j.stream.RawFieldParser;
 import org.apache.james.mime4j.util.ByteSequence;
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/MailboxFieldImpl.java b/dom/src/main/java/org/apache/james/mime4j/field/MailboxFieldImpl.java
index 531f99f..77c7237 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/MailboxFieldImpl.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/MailboxFieldImpl.java
@@ -20,12 +20,12 @@
 package org.apache.james.mime4j.field;
 
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.address.Mailbox;
 import org.apache.james.mime4j.dom.field.MailboxField;
 import org.apache.james.mime4j.field.address.AddressBuilder;
 import org.apache.james.mime4j.field.address.ParseException;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 
 /**
  * Mailbox field such as <code>Sender</code> or <code>Resent-Sender</code>.
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/MailboxFieldLenientImpl.java b/dom/src/main/java/org/apache/james/mime4j/field/MailboxFieldLenientImpl.java
index a2a2874..f2a862d 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/MailboxFieldLenientImpl.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/MailboxFieldLenientImpl.java
@@ -20,11 +20,11 @@
 package org.apache.james.mime4j.field;
 
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.address.Mailbox;
 import org.apache.james.mime4j.dom.field.MailboxField;
 import org.apache.james.mime4j.field.address.LenientAddressBuilder;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 import org.apache.james.mime4j.stream.ParserCursor;
 import org.apache.james.mime4j.stream.RawField;
 import org.apache.james.mime4j.util.ByteSequence;
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/MailboxListFieldImpl.java b/dom/src/main/java/org/apache/james/mime4j/field/MailboxListFieldImpl.java
index 449ec4f..a0a21a8 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/MailboxListFieldImpl.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/MailboxListFieldImpl.java
@@ -20,12 +20,12 @@
 package org.apache.james.mime4j.field;
 
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.address.MailboxList;
 import org.apache.james.mime4j.dom.field.MailboxListField;
 import org.apache.james.mime4j.field.address.AddressBuilder;
 import org.apache.james.mime4j.field.address.ParseException;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 
 /**
  * Mailbox-list field such as <code>From</code> or <code>Resent-From</code>.
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/MailboxListFieldLenientImpl.java b/dom/src/main/java/org/apache/james/mime4j/field/MailboxListFieldLenientImpl.java
index 2023c8f..efee65e 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/MailboxListFieldLenientImpl.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/MailboxListFieldLenientImpl.java
@@ -22,12 +22,12 @@
 import java.util.Collections;
 
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.address.Mailbox;
 import org.apache.james.mime4j.dom.address.MailboxList;
 import org.apache.james.mime4j.dom.field.MailboxListField;
 import org.apache.james.mime4j.field.address.LenientAddressBuilder;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 import org.apache.james.mime4j.stream.ParserCursor;
 import org.apache.james.mime4j.stream.RawField;
 import org.apache.james.mime4j.util.ByteSequence;
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/MimeVersionFieldImpl.java b/dom/src/main/java/org/apache/james/mime4j/field/MimeVersionFieldImpl.java
index 8642364..c119b20 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/MimeVersionFieldImpl.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/MimeVersionFieldImpl.java
@@ -23,11 +23,11 @@
 
 import org.apache.james.mime4j.MimeException;
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.field.MimeVersionField;
 import org.apache.james.mime4j.field.mimeversion.parser.MimeVersionParser;
 import org.apache.james.mime4j.field.mimeversion.parser.ParseException;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 
 /**
  * Represents a <code>MIME-Version</code> field.
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/MimeVersionFieldLenientImpl.java b/dom/src/main/java/org/apache/james/mime4j/field/MimeVersionFieldLenientImpl.java
index eabacc8..194214c 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/MimeVersionFieldLenientImpl.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/MimeVersionFieldLenientImpl.java
@@ -22,9 +22,9 @@
 import java.util.BitSet;
 
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.field.MimeVersionField;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 import org.apache.james.mime4j.stream.ParserCursor;
 import org.apache.james.mime4j.stream.RawField;
 import org.apache.james.mime4j.stream.RawFieldParser;
diff --git a/dom/src/main/java/org/apache/james/mime4j/field/UnstructuredFieldImpl.java b/dom/src/main/java/org/apache/james/mime4j/field/UnstructuredFieldImpl.java
index 7d52d85..fb9e0c5 100644
--- a/dom/src/main/java/org/apache/james/mime4j/field/UnstructuredFieldImpl.java
+++ b/dom/src/main/java/org/apache/james/mime4j/field/UnstructuredFieldImpl.java
@@ -21,9 +21,9 @@
 
 import org.apache.james.mime4j.codec.DecodeMonitor;
 import org.apache.james.mime4j.codec.DecoderUtil;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.field.UnstructuredField;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 
 /**
  * Simple unstructured field such as <code>Subject</code>.
diff --git a/dom/src/main/java/org/apache/james/mime4j/message/AbstractEntity.java b/dom/src/main/java/org/apache/james/mime4j/message/AbstractEntity.java
index dfb11a3..d053055 100644
--- a/dom/src/main/java/org/apache/james/mime4j/message/AbstractEntity.java
+++ b/dom/src/main/java/org/apache/james/mime4j/message/AbstractEntity.java
@@ -35,7 +35,7 @@
 import org.apache.james.mime4j.dom.field.ContentTransferEncodingField;
 import org.apache.james.mime4j.dom.field.ContentTypeField;
 import org.apache.james.mime4j.dom.field.FieldName;
-import org.apache.james.mime4j.stream.Field;
+import org.apache.james.mime4j.dom.field.ParsedField;
 
 /**
  * MIME entity. An entity has a header and a body (see RFC 2045).
@@ -524,7 +524,7 @@
      * @return the header field or <code>null</code> if this entity has no
      *         header or the header contains no such field.
      */
-    <F extends Field> F obtainField(String fieldName) {
+    <F extends ParsedField> F obtainField(String fieldName) {
         Header header = getHeader();
         if (header == null)
             return null;
diff --git a/dom/src/main/java/org/apache/james/mime4j/message/AbstractMessage.java b/dom/src/main/java/org/apache/james/mime4j/message/AbstractMessage.java
index e79c9cd..cb44a53 100644
--- a/dom/src/main/java/org/apache/james/mime4j/message/AbstractMessage.java
+++ b/dom/src/main/java/org/apache/james/mime4j/message/AbstractMessage.java
@@ -36,6 +36,7 @@
 import org.apache.james.mime4j.dom.field.FieldName;
 import org.apache.james.mime4j.dom.field.MailboxField;
 import org.apache.james.mime4j.dom.field.MailboxListField;
+import org.apache.james.mime4j.dom.field.ParsedField;
 import org.apache.james.mime4j.dom.field.UnstructuredField;
 import org.apache.james.mime4j.stream.Field;
 
@@ -70,7 +71,7 @@
         header.setField(newMessageId(hostname));
     }
 
-    protected abstract Field newMessageId(String hostname);
+    protected abstract ParsedField newMessageId(String hostname);
 
     /**
      * Returns the (decoded) value of the <i>Subject</i> header field of this
diff --git a/dom/src/main/java/org/apache/james/mime4j/message/DefaultMessageBuilder.java b/dom/src/main/java/org/apache/james/mime4j/message/DefaultMessageBuilder.java
index 8604a91..fa27ac6 100644
--- a/dom/src/main/java/org/apache/james/mime4j/message/DefaultMessageBuilder.java
+++ b/dom/src/main/java/org/apache/james/mime4j/message/DefaultMessageBuilder.java
@@ -28,6 +28,7 @@
 import org.apache.james.mime4j.dom.Body;
 import org.apache.james.mime4j.dom.Disposable;
 import org.apache.james.mime4j.dom.Entity;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.Header;
 import org.apache.james.mime4j.dom.Message;
 import org.apache.james.mime4j.dom.MessageBuilder;
@@ -39,7 +40,6 @@
 import org.apache.james.mime4j.parser.AbstractContentHandler;
 import org.apache.james.mime4j.parser.MimeStreamParser;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 import org.apache.james.mime4j.stream.MimeEntityConfig;
 import org.apache.james.mime4j.stream.MutableBodyDescriptorFactory;
 
@@ -298,10 +298,12 @@
             FieldParser<? extends ParsedField> fp = fieldParser != null ? fieldParser : 
                 strict ? DefaultFieldParser.getParser() : LenientFieldParser.getParser();
             MutableBodyDescriptorFactory bdf = bodyDescFactory != null ? bodyDescFactory :
-                new MinimalBodyDescriptorFactory();
-            BodyFactory bf = bodyFactory != null ? bodyFactory : new BasicBodyFactory(); 
-            MimeStreamParser parser = new MimeStreamParser(cfg, mon, fp, bdf);
-            parser.setContentHandler(new EntityBuilder(message, mon, fp, bf));
+                new MinimalBodyDescriptorFactory(fp, true);
+            BodyFactory bf = bodyFactory != null ? bodyFactory : new BasicBodyFactory();
+            MimeStreamParser parser = new MimeStreamParser(cfg, mon, bdf);
+            // EntityBuilder expect the parser will send ParserFields for the well known fields
+            // It will throw exceptions, otherwise.
+            parser.setContentHandler(new EntityBuilder(message, bf));
             parser.setContentDecoding(contentDecoding);
             if (flatMode) {
                 parser.setFlat();
diff --git a/dom/src/main/java/org/apache/james/mime4j/message/EntityBuilder.java b/dom/src/main/java/org/apache/james/mime4j/message/EntityBuilder.java
index 9037264..07ccfdd 100644
--- a/dom/src/main/java/org/apache/james/mime4j/message/EntityBuilder.java
+++ b/dom/src/main/java/org/apache/james/mime4j/message/EntityBuilder.java
@@ -24,17 +24,14 @@
 import java.util.Stack;
 
 import org.apache.james.mime4j.MimeException;
-import org.apache.james.mime4j.codec.DecodeMonitor;
 import org.apache.james.mime4j.dom.Body;
 import org.apache.james.mime4j.dom.Entity;
 import org.apache.james.mime4j.dom.Header;
 import org.apache.james.mime4j.dom.Message;
 import org.apache.james.mime4j.dom.Multipart;
-import org.apache.james.mime4j.dom.field.ParsedField;
 import org.apache.james.mime4j.parser.ContentHandler;
 import org.apache.james.mime4j.stream.BodyDescriptor;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 import org.apache.james.mime4j.stream.RawField;
 import org.apache.james.mime4j.util.ByteArrayBuffer;
 import org.apache.james.mime4j.util.ByteSequence;
@@ -46,19 +43,13 @@
 class EntityBuilder implements ContentHandler {
 
     private final Entity entity;
-    private final DecodeMonitor monitor;
-    private final FieldParser<? extends ParsedField> fieldParser; 
     private final BodyFactory bodyFactory;
     private final Stack<Object> stack;
     
     EntityBuilder(
             final Entity entity,
-            final DecodeMonitor monitor,
-            final FieldParser<? extends ParsedField> fieldParser, 
             final BodyFactory bodyFactory) {
         this.entity = entity;
-        this.monitor = monitor;
-        this.fieldParser = fieldParser;
         this.bodyFactory = bodyFactory;
         this.stack = new Stack<Object>();
     }
@@ -105,13 +96,7 @@
      */
     public void field(Field field) throws MimeException {
         expect(Header.class);
-        ParsedField parsedField;
-        if (field instanceof ParsedField) {
-            parsedField = (ParsedField) field;
-        } else {
-            parsedField = fieldParser.parse(field, monitor);
-        }
-        ((Header) stack.peek()).addField(parsedField);
+        ((Header) stack.peek()).addField(field);
     }
     
     /**
diff --git a/dom/src/main/java/org/apache/james/mime4j/message/MaximalBodyDescriptor.java b/dom/src/main/java/org/apache/james/mime4j/message/MaximalBodyDescriptor.java
index afcaa03..a2c5ccd 100644
--- a/dom/src/main/java/org/apache/james/mime4j/message/MaximalBodyDescriptor.java
+++ b/dom/src/main/java/org/apache/james/mime4j/message/MaximalBodyDescriptor.java
@@ -26,6 +26,7 @@
 
 import org.apache.james.mime4j.MimeException;
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.field.ContentDescriptionField;
 import org.apache.james.mime4j.dom.field.ContentDispositionField;
 import org.apache.james.mime4j.dom.field.ContentIdField;
@@ -34,16 +35,12 @@
 import org.apache.james.mime4j.dom.field.ContentMD5Field;
 import org.apache.james.mime4j.dom.field.FieldName;
 import org.apache.james.mime4j.dom.field.MimeVersionField;
-import org.apache.james.mime4j.field.ContentDescriptionFieldImpl;
-import org.apache.james.mime4j.field.ContentDispositionFieldImpl;
-import org.apache.james.mime4j.field.ContentIdFieldImpl;
-import org.apache.james.mime4j.field.ContentLanguageFieldImpl;
-import org.apache.james.mime4j.field.ContentLocationFieldImpl;
-import org.apache.james.mime4j.field.ContentMD5FieldImpl;
+import org.apache.james.mime4j.dom.field.ParsedField;
 import org.apache.james.mime4j.field.MimeVersionFieldImpl;
 import org.apache.james.mime4j.stream.BodyDescriptor;
 import org.apache.james.mime4j.stream.Field;
 import org.apache.james.mime4j.stream.MutableBodyDescriptor;
+import org.apache.james.mime4j.stream.RawField;
 
 /**
  * Parses and stores values for standard MIME header values.
@@ -60,101 +57,77 @@
     private ContentMD5Field contentMD5Field;
     
     protected MaximalBodyDescriptor() {
-        this(null, null);
+        this(null);
+    }
+    
+    protected MaximalBodyDescriptor(final BodyDescriptor parent) {
+        this(parent, null, true, null);
     }
 
-    public MaximalBodyDescriptor(final BodyDescriptor parent, final DecodeMonitor monitor) {
-        super(parent, monitor);
+    public MaximalBodyDescriptor(final BodyDescriptor parent, final FieldParser<?> fieldParser, final boolean parseAllFields, final DecodeMonitor monitor) {
+        super(parent, fieldParser, parseAllFields, monitor);
     }
 
     @Override
     public MutableBodyDescriptor newChild() {
-        return new MaximalBodyDescriptor(this, getDecodeMonitor());
+        return new MaximalBodyDescriptor(this, getFieldParser(), getParseAllFields(), getDecodeMonitor());
     }
 
     @Override
-    public void addField(Field field) throws MimeException {
+    public Field addField(RawField field) throws MimeException {
         String name = field.getName();
         if (name.equalsIgnoreCase(FieldName.MIME_VERSION) && mimeVersionField == null) {
-            parseMimeVersion(field);
+            return parseMimeVersion(field);
         } else if (name.equalsIgnoreCase(FieldName.CONTENT_ID) && contentIdField == null) {
-            parseContentId(field);
+            return parseContentId(field);
         } else if (name.equalsIgnoreCase(FieldName.CONTENT_DESCRIPTION) && contentDescriptionField == null) {
-            parseContentDescription(field);
+            return parseContentDescription(field);
         } else if (name.equalsIgnoreCase(FieldName.CONTENT_DISPOSITION) && contentDispositionField == null) {
-            parseContentDisposition(field);
+            return parseContentDisposition(field);
         } else if (name.equalsIgnoreCase(FieldName.CONTENT_LANGUAGE) && contentLanguageField == null) {
-            parseLanguage(field);
+            return parseLanguage(field);
         } else if (name.equalsIgnoreCase(FieldName.CONTENT_LOCATION) && contentLocationField == null) {
-            parseLocation(field);
+            return parseLocation(field);
         } else if (name.equalsIgnoreCase(FieldName.CONTENT_MD5) && contentMD5Field == null) {
-            parseMD5(field);
+            return parseMD5(field);
         } else {
-            super.addField(field);
+            return super.addField(field);
         }
     }
     
-    private void parseMD5(final Field field) {
-        if (field instanceof ContentMD5Field) {
-            contentMD5Field = (ContentMD5Field) field;
-        } else {
-            contentMD5Field = ContentMD5FieldImpl.PARSER.parse(
-                    field, getDecodeMonitor());
-        }
+    private ContentMD5Field parseMD5(final Field field) {
+        contentMD5Field = (ContentMD5Field) getFieldParser().parse(field, getDecodeMonitor());
+        return contentMD5Field;
     }
 
-    private void parseLocation(final Field field) {
-        if (field instanceof ContentLocationField) {
-            contentLocationField = (ContentLocationField) field;
-        } else {
-            contentLocationField = ContentLocationFieldImpl.PARSER.parse(
-                    field, getDecodeMonitor());
-        }
+    private ContentLocationField parseLocation(final Field field) {
+        contentLocationField = (ContentLocationField) getFieldParser().parse(field, getDecodeMonitor());
+        return contentLocationField;
     }
     
-    private void parseLanguage(final Field field) {
-        if (field instanceof ContentLanguageField) {
-            contentLanguageField = (ContentLanguageField) field;
-        } else {
-            contentLanguageField = ContentLanguageFieldImpl.PARSER.parse(
-                    field, getDecodeMonitor());
-        }
+    private ParsedField parseLanguage(final Field field) {
+        contentLanguageField = (ContentLanguageField) getFieldParser().parse(field, getDecodeMonitor());
+        return contentLanguageField;
     }
 
-    private void parseContentDisposition(final Field field) throws MimeException {
-        if (field instanceof ContentDispositionField) {
-            contentDispositionField = (ContentDispositionField) field;
-        } else {
-            contentDispositionField = ContentDispositionFieldImpl.PARSER.parse(
-                    field, getDecodeMonitor());
-        }
+    private ParsedField parseContentDisposition(final Field field) throws MimeException {
+        contentDispositionField = (ContentDispositionField) getFieldParser().parse(field, getDecodeMonitor());
+        return contentDispositionField;
     }
 
-    private void parseContentDescription(final Field field) {
-        if (field instanceof ContentDescriptionField) {
-            contentDescriptionField = (ContentDescriptionField) field;
-        } else {
-            contentDescriptionField = ContentDescriptionFieldImpl.PARSER.parse(
-                    field, getDecodeMonitor());
-        }
+    private ParsedField parseContentDescription(final Field field) {
+        contentDescriptionField = (ContentDescriptionField) getFieldParser().parse(field, getDecodeMonitor());
+        return contentDescriptionField;
     }
 
-    private void parseContentId(final Field field) {
-        if (field instanceof ContentIdField) {
-            contentIdField = (ContentIdField) field;
-        } else {
-            contentIdField = ContentIdFieldImpl.PARSER.parse(
-                    field, getDecodeMonitor());
-        }
+    private ContentIdField parseContentId(final Field field) {
+        contentIdField = (ContentIdField) getFieldParser().parse(field, getDecodeMonitor());
+        return contentIdField;
     }
 
-    private void parseMimeVersion(final Field field) {
-        if (field instanceof MimeVersionField) {
-            mimeVersionField = (MimeVersionField) field;
-        } else {
-            mimeVersionField = MimeVersionFieldImpl.PARSER.parse(
-                    field, getDecodeMonitor());
-        }
+    private MimeVersionField parseMimeVersion(final Field field) {
+        mimeVersionField = (MimeVersionField) getFieldParser().parse(field, getDecodeMonitor());
+        return mimeVersionField;
     }
     
     /**
diff --git a/dom/src/main/java/org/apache/james/mime4j/message/MaximalBodyDescriptorFactory.java b/dom/src/main/java/org/apache/james/mime4j/message/MaximalBodyDescriptorFactory.java
index 8cdfbc5..f2a4d5e 100644
--- a/dom/src/main/java/org/apache/james/mime4j/message/MaximalBodyDescriptorFactory.java
+++ b/dom/src/main/java/org/apache/james/mime4j/message/MaximalBodyDescriptorFactory.java
@@ -20,13 +20,27 @@
 package org.apache.james.mime4j.message;
 
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.stream.MutableBodyDescriptor;
 import org.apache.james.mime4j.stream.MutableBodyDescriptorFactory;
 
 public class MaximalBodyDescriptorFactory implements MutableBodyDescriptorFactory {
 
+    private final FieldParser<?> fieldParser;
+    private final boolean parseAllFields;
+
+    public MaximalBodyDescriptorFactory() {
+        this(null, false);
+    }
+
+    public MaximalBodyDescriptorFactory(final 
+            FieldParser<?> fieldParser, final boolean parseAllFields) {
+        this.fieldParser = fieldParser;
+        this.parseAllFields = parseAllFields;
+    }
+
     public MutableBodyDescriptor newInstance(DecodeMonitor monitor) {
-        return new MaximalBodyDescriptor(null, monitor);
+        return new MaximalBodyDescriptor(null, fieldParser, parseAllFields, monitor);
     }
     
 } 
diff --git a/dom/src/main/java/org/apache/james/mime4j/message/MinimalBodyDescriptor.java b/dom/src/main/java/org/apache/james/mime4j/message/MinimalBodyDescriptor.java
index a7b0f0f..7953316 100644
--- a/dom/src/main/java/org/apache/james/mime4j/message/MinimalBodyDescriptor.java
+++ b/dom/src/main/java/org/apache/james/mime4j/message/MinimalBodyDescriptor.java
@@ -24,16 +24,17 @@
 
 import org.apache.james.mime4j.MimeException;
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.field.ContentLengthField;
 import org.apache.james.mime4j.dom.field.ContentTransferEncodingField;
 import org.apache.james.mime4j.dom.field.ContentTypeField;
 import org.apache.james.mime4j.dom.field.FieldName;
-import org.apache.james.mime4j.field.ContentLengthFieldImpl;
-import org.apache.james.mime4j.field.ContentTransferEncodingFieldImpl;
-import org.apache.james.mime4j.field.ContentTypeFieldImpl;
+import org.apache.james.mime4j.dom.field.ParsedField;
+import org.apache.james.mime4j.field.DefaultFieldParser;
 import org.apache.james.mime4j.stream.BodyDescriptor;
 import org.apache.james.mime4j.stream.Field;
 import org.apache.james.mime4j.stream.MutableBodyDescriptor;
+import org.apache.james.mime4j.stream.RawField;
 import org.apache.james.mime4j.util.MimeUtil;
 
 /**
@@ -70,12 +71,23 @@
     private ContentTypeField contentTypeField;
     private ContentLengthField contentLengthField;
     private ContentTransferEncodingField contentTransferEncodingField;
+
+    private final FieldParser<?> fieldParser;
+
+    private final boolean parseAllFields;
     
     /**
      * Creates a new root <code>BodyDescriptor</code> instance.
      */
     public MinimalBodyDescriptor() {
-        this(null, null);
+        this(null);
+    }
+
+    /**
+     * Creates a new root <code>BodyDescriptor</code> instance with the given parent
+     */
+    public MinimalBodyDescriptor(final BodyDescriptor parent) {
+        this(parent, null, false, null);
     }
 
     /**
@@ -84,7 +96,7 @@
      * @param parent the descriptor of the parent or <code>null</code> if this
      *        is the root descriptor.
      */
-    public MinimalBodyDescriptor(final BodyDescriptor parent, final DecodeMonitor monitor) {
+    public MinimalBodyDescriptor(final BodyDescriptor parent, final FieldParser<?> fieldParser, boolean parseAllFields, final DecodeMonitor monitor) {
         if (parent != null && MimeUtil.isSameMimeType("multipart/digest", parent.getMimeType())) {
             this.mimeType = EMAIL_MESSAGE_MIME_TYPE;
             this.subType = SUB_TYPE_EMAIL;
@@ -94,6 +106,8 @@
             this.subType = DEFAULT_SUB_TYPE;
             this.mediaType = DEFAULT_MEDIA_TYPE;
         }
+        this.fieldParser = fieldParser != null ? fieldParser : DefaultFieldParser.getParser();
+        this.parseAllFields = parseAllFields;
         this.monitor = monitor != null ? monitor : DecodeMonitor.SILENT;
     }
     
@@ -101,8 +115,16 @@
         return monitor;
     }
     
+    protected FieldParser<?> getFieldParser() {
+        return fieldParser;
+    }
+    
+    protected boolean getParseAllFields() {
+        return parseAllFields;
+    }
+    
     public MutableBodyDescriptor newChild() {
-		return new MinimalBodyDescriptor(this, getDecodeMonitor());
+        return new MinimalBodyDescriptor(this, getFieldParser(), getParseAllFields(), getDecodeMonitor());
     }
     
     /**
@@ -111,42 +133,32 @@
      * 
      * @param field the MIME field.
      */
-    public void addField(Field field) throws MimeException {
+    public Field addField(RawField field) throws MimeException {
         String name = field.getName();
         if (name.equalsIgnoreCase(FieldName.CONTENT_TRANSFER_ENCODING)&& contentTransferEncodingField == null) {
-            parseContentTransferEncoding(field);
+            return parseContentTransferEncoding(field);
         } else if (name.equalsIgnoreCase(FieldName.CONTENT_LENGTH) && contentLengthField == null) {
-            parseContentLength(field);
+            return parseContentLength(field);
         } else if (name.equalsIgnoreCase(FieldName.CONTENT_TYPE) && contentTypeField == null) {
-            parseContentType(field);
-        }
+            return parseContentType(field);
+        } else if (getParseAllFields()) {
+            return getFieldParser().parse(field, monitor);
+        } else return null;
     }
 
-    private void parseContentTransferEncoding(Field field) throws MimeException {
-        if (field instanceof ContentTransferEncodingField) {
-            contentTransferEncodingField = (ContentTransferEncodingField) field;
-        } else {
-            contentTransferEncodingField = ContentTransferEncodingFieldImpl.PARSER.parse(
-                    field, monitor);
-        }
+    private ParsedField parseContentTransferEncoding(Field field) throws MimeException {
+        contentTransferEncodingField = (ContentTransferEncodingField) fieldParser.parse(field, monitor);
+        return contentTransferEncodingField;
     }
 
-    private void parseContentLength(Field field) throws MimeException {
-        if (field instanceof ContentLengthField) {
-            contentLengthField = (ContentLengthField) field;
-        } else {
-            contentLengthField = ContentLengthFieldImpl.PARSER.parse(
-                    field, monitor);
-        }
+    private ParsedField parseContentLength(Field field) throws MimeException {
+        contentLengthField = (ContentLengthField) fieldParser.parse(field, monitor);
+        return contentLengthField;
     }
 
-    private void parseContentType(Field field) throws MimeException {
-        if (field instanceof ContentTypeField) {
-            contentTypeField = (ContentTypeField) field;
-        } else {
-            contentTypeField = ContentTypeFieldImpl.PARSER.parse(
-                    field, monitor);
-        }
+    private ParsedField parseContentType(Field field) throws MimeException {
+        contentTypeField = (ContentTypeField) fieldParser.parse(field, monitor);
+
         String mimetype = contentTypeField.getMimeType();
         if (mimetype != null) {
             mimeType = mimetype;
@@ -163,6 +175,7 @@
         parameters.putAll(contentTypeField.getParameters());
         parameters.remove("charset");
         parameters.remove("boundary");
+        return contentTypeField;
     }
 
     /**
diff --git a/dom/src/main/java/org/apache/james/mime4j/message/MinimalBodyDescriptorFactory.java b/dom/src/main/java/org/apache/james/mime4j/message/MinimalBodyDescriptorFactory.java
index ea73d51..ec17d61 100644
--- a/dom/src/main/java/org/apache/james/mime4j/message/MinimalBodyDescriptorFactory.java
+++ b/dom/src/main/java/org/apache/james/mime4j/message/MinimalBodyDescriptorFactory.java
@@ -20,13 +20,23 @@
 package org.apache.james.mime4j.message;
 
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.stream.MutableBodyDescriptor;
 import org.apache.james.mime4j.stream.MutableBodyDescriptorFactory;
 
 public class MinimalBodyDescriptorFactory implements MutableBodyDescriptorFactory {
 
+    private final FieldParser<?> fieldParser;
+    private final boolean parseAllFields;
+
+    public MinimalBodyDescriptorFactory(final 
+            FieldParser<?> fieldParser, final boolean parseAllFields) {
+        this.fieldParser = fieldParser;
+        this.parseAllFields = parseAllFields;
+    }
+
     public MutableBodyDescriptor newInstance(DecodeMonitor monitor) {
-        return new MinimalBodyDescriptor(null, monitor);
+        return new MinimalBodyDescriptor(null, fieldParser, parseAllFields, monitor);
     }
     
 } 
diff --git a/dom/src/main/java/org/apache/james/mime4j/message/SimpleContentHandler.java b/dom/src/main/java/org/apache/james/mime4j/message/SimpleContentHandler.java
index 33c4247..ca256ff 100644
--- a/dom/src/main/java/org/apache/james/mime4j/message/SimpleContentHandler.java
+++ b/dom/src/main/java/org/apache/james/mime4j/message/SimpleContentHandler.java
@@ -21,12 +21,12 @@
 
 import org.apache.james.mime4j.MimeException;
 import org.apache.james.mime4j.codec.DecodeMonitor;
+import org.apache.james.mime4j.dom.FieldParser;
 import org.apache.james.mime4j.dom.Header;
 import org.apache.james.mime4j.dom.field.ParsedField;
 import org.apache.james.mime4j.field.LenientFieldParser;
 import org.apache.james.mime4j.parser.AbstractContentHandler;
 import org.apache.james.mime4j.stream.Field;
-import org.apache.james.mime4j.stream.FieldParser;
 import org.apache.james.mime4j.stream.RawField;
 
 /**
diff --git a/dom/src/test/java/org/apache/james/mime4j/message/MaximalBodyDescriptorTest.java b/dom/src/test/java/org/apache/james/mime4j/message/MaximalBodyDescriptorTest.java
index 9ff2ecb..2d85bcf 100644
--- a/dom/src/test/java/org/apache/james/mime4j/message/MaximalBodyDescriptorTest.java
+++ b/dom/src/test/java/org/apache/james/mime4j/message/MaximalBodyDescriptorTest.java
@@ -24,9 +24,6 @@
 import java.util.TimeZone;
 
 import org.apache.james.mime4j.ExampleMail;
-import org.apache.james.mime4j.field.DefaultFieldParser;
-import org.apache.james.mime4j.message.MaximalBodyDescriptor;
-import org.apache.james.mime4j.message.MaximalBodyDescriptorFactory;
 import org.apache.james.mime4j.stream.BaseTestForBodyDescriptors;
 import org.apache.james.mime4j.stream.BodyDescriptor;
 import org.apache.james.mime4j.stream.EntityState;
@@ -44,7 +41,7 @@
         MimeEntityConfig config = new MimeEntityConfig();
         config.setStrictParsing(true);
         parser = new MimeTokenStream(config, 
-                DefaultFieldParser.getParser(), new MaximalBodyDescriptorFactory());
+                new MaximalBodyDescriptorFactory(null, false));
     }
 
     @Override
@@ -195,6 +192,6 @@
 
     @Override
     protected MutableBodyDescriptor newBodyDescriptor(BodyDescriptor parent) {
-        return new MaximalBodyDescriptor(parent, null);
+        return new MaximalBodyDescriptor(parent);
     }
 }