Description
Entity exposes
- setBody: sets the body of the entity
- setHeader: sets the header
Inconsistency: setBody throws an exception if the body already exists, setHeader does not show this behaviour
Correctness: setBody does not provide consistency at the dom level: e.g: if you previously added a Content-Type field saying it is a multipart it happily accept a plain text body and will fail when the body is written out.
AbstractEntity adds:
- setMessage(Message message)
- setMultipart(Multipart multipart)
- setMultipart(Multipart multipart, Map<String, String> parameters)
- setText(TextBody textBody)
- setText(TextBody textBody, String subtype)
- setBody(Body body, String mimeType)
They all prepare parameters and call the internal method - setBody(Body body, String mimeType, Map<String, String> parameters)
All of these methods document they behaviour saying "A Header is created if this entity does not already have one but they don't say that the Content-Type field is replaced by a new content-type created using the parameters. These methods are only used by example code and not by the parser. The parser will only use the Entity.setBody method when parsing.
Inconsistency: Multipart interface expose "subtype" but not "boundary". I think that technically the boundary is a part of a multipart body instead subtype is only something used when the full entity is used (it is only in the header). So it seems inconsistent that a Multipart knows its subtype, its raw epilogue but doesn't know the boundary: should we add it?
Inconsistency: Multipart knows its own subtype, instead TextBody doesn't know it.
Weirdness: If you call the public method "setBody()" and you pass a Multipart object Entity doesn't do anything to ensure the dom object is valid. Instead if you call setMultipart() and you pass the very same Multipart it will take care of adding the content-type using the subtype from the Multipart object and a new generated Boundary. If you call the third method "setMultipart(multipart,parameters)" then you also ensure a new contenttype is generated starting using the subtype and parameters as input. the setMultipart methods always rewrite the original contenttype added previously to the header.
It doesn't sound good that the public interface exposes the only method (setBody) that doesn't provide "content-type-header vs body content consistency".
I'm not sure what is the best way to make the whole thing consistent, so I hope we can discuss the logic here. At the very least I hope we can define if "subtype" is something belonging to the body or not (and maybe other properties like boundary, charset, ....).
Should mime4j dom api care about consistency between content-type/content-transfer-encoding and the entity body? What object should care? How should it react when we change one or the other to become incompatible? e.g: if I add a Multipart then I change the Content-Type header to say text/plain what should it do? (change Multipart body with a TextBody on the fly? Keep the inconsistency and simply dump the text/plain header and the multipart stream?).
I think answers to this issue will also help understand how we should expose message building public API. Currently we only expose MessageBuilder.newMessage. The Message exposes a setBody but we don't publish a way to create new bodies. Now an API user have to go in the internals and create e.g: a new MultipartImpl then call the setBody and then make sure to add a content-type header (how does it do?) matching the multipart just added.