001    /****************************************************************
002     * Licensed to the Apache Software Foundation (ASF) under one   *
003     * or more contributor license agreements.  See the NOTICE file *
004     * distributed with this work for additional information        *
005     * regarding copyright ownership.  The ASF licenses this file   *
006     * to you under the Apache License, Version 2.0 (the            *
007     * "License"); you may not use this file except in compliance   *
008     * with the License.  You may obtain a copy of the License at   *
009     *                                                              *
010     *   http://www.apache.org/licenses/LICENSE-2.0                 *
011     *                                                              *
012     * Unless required by applicable law or agreed to in writing,   *
013     * software distributed under the License is distributed on an  *
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
015     * KIND, either express or implied.  See the License for the    *
016     * specific language governing permissions and limitations      *
017     * under the License.                                           *
018     ****************************************************************/
019    
020    package org.apache.james.mime4j.message;
021    
022    import java.util.Collections;
023    import java.util.LinkedList;
024    import java.util.List;
025    
026    import org.apache.james.mime4j.dom.Entity;
027    import org.apache.james.mime4j.dom.Multipart;
028    
029    /**
030     * Abstract MIME multipart body.
031     */
032    public abstract class AbstractMultipart implements Multipart {
033    
034        protected List<Entity> bodyParts = new LinkedList<Entity>();
035        private Entity parent = null;
036    
037        private String subType;
038    
039        /**
040         * Creates a new empty <code>Multipart</code> instance.
041         */
042        public AbstractMultipart(String subType) {
043            this.subType = subType;
044        }
045    
046        /**
047         * Gets the multipart sub-type. E.g. <code>alternative</code> (the
048         * default) or <code>parallel</code>. See RFC 2045 for common sub-types
049         * and their meaning.
050         *
051         * @return the multipart sub-type.
052         */
053        public String getSubType() {
054            return subType;
055        }
056    
057        /**
058         * Sets the multipart sub-type. E.g. <code>alternative</code> or
059         * <code>parallel</code>. See RFC 2045 for common sub-types and their
060         * meaning.
061         *
062         * @param subType
063         *            the sub-type.
064         */
065        public void setSubType(String subType) {
066            this.subType = subType;
067        }
068    
069        /**
070         * @see org.apache.james.mime4j.dom.Body#getParent()
071         */
072        public Entity getParent() {
073            return parent;
074        }
075    
076        /**
077         * @see org.apache.james.mime4j.dom.Body#setParent(org.apache.james.mime4j.dom.Entity)
078         */
079        public void setParent(Entity parent) {
080            this.parent = parent;
081            for (Entity bodyPart : bodyParts) {
082                bodyPart.setParent(parent);
083            }
084        }
085    
086        /**
087         * Returns the number of body parts.
088         *
089         * @return number of <code>Entity</code> objects.
090         */
091        public int getCount() {
092            return bodyParts.size();
093        }
094    
095        /**
096         * Gets the list of body parts. The list is immutable.
097         *
098         * @return the list of <code>Entity</code> objects.
099         */
100        public List<Entity> getBodyParts() {
101            return Collections.unmodifiableList(bodyParts);
102        }
103    
104        /**
105         * Sets the list of body parts.
106         *
107         * @param bodyParts
108         *            the new list of <code>Entity</code> objects.
109         */
110        public void setBodyParts(List<Entity> bodyParts) {
111            this.bodyParts = bodyParts;
112            for (Entity bodyPart : bodyParts) {
113                bodyPart.setParent(parent);
114            }
115        }
116    
117        /**
118         * Adds a body part to the end of the list of body parts.
119         *
120         * @param bodyPart
121         *            the body part.
122         */
123        public void addBodyPart(Entity bodyPart) {
124            if (bodyPart == null)
125                throw new IllegalArgumentException();
126    
127            bodyParts.add(bodyPart);
128            bodyPart.setParent(parent);
129        }
130    
131        /**
132         * Inserts a body part at the specified position in the list of body parts.
133         *
134         * @param bodyPart
135         *            the body part.
136         * @param index
137         *            index at which the specified body part is to be inserted.
138         * @throws IndexOutOfBoundsException
139         *             if the index is out of range (index &lt; 0 || index &gt;
140         *             getCount()).
141         */
142        public void addBodyPart(Entity bodyPart, int index) {
143            if (bodyPart == null)
144                throw new IllegalArgumentException();
145    
146            bodyParts.add(index, bodyPart);
147            bodyPart.setParent(parent);
148        }
149    
150        /**
151         * Removes the body part at the specified position in the list of body
152         * parts.
153         *
154         * @param index
155         *            index of the body part to be removed.
156         * @return the removed body part.
157         * @throws IndexOutOfBoundsException
158         *             if the index is out of range (index &lt; 0 || index &gt;=
159         *             getCount()).
160         */
161        public Entity removeBodyPart(int index) {
162            Entity bodyPart = bodyParts.remove(index);
163            bodyPart.setParent(null);
164            return bodyPart;
165        }
166    
167        /**
168         * Replaces the body part at the specified position in the list of body
169         * parts with the specified body part.
170         *
171         * @param bodyPart
172         *            body part to be stored at the specified position.
173         * @param index
174         *            index of body part to replace.
175         * @return the replaced body part.
176         * @throws IndexOutOfBoundsException
177         *             if the index is out of range (index &lt; 0 || index &gt;=
178         *             getCount()).
179         */
180        public Entity replaceBodyPart(Entity bodyPart, int index) {
181            if (bodyPart == null)
182                throw new IllegalArgumentException();
183    
184            Entity replacedEntity = bodyParts.set(index, bodyPart);
185            if (bodyPart == replacedEntity)
186                throw new IllegalArgumentException(
187                        "Cannot replace body part with itself");
188    
189            bodyPart.setParent(parent);
190            replacedEntity.setParent(null);
191    
192            return replacedEntity;
193        }
194    
195        /**
196         * Gets the preamble or null if the message has no preamble.
197         *
198         * @return the preamble.
199         */
200        public abstract String getPreamble();
201    
202        /**
203         * Sets the preamble with a value or null to remove the preamble.
204         *
205         * @param preamble
206         *            the preamble.
207         */
208        public abstract void setPreamble(String preamble);
209    
210        /**
211         * Gets the epilogue or null if the message has no epilogue
212         *
213         * @return the epilogue.
214         */
215        public abstract String getEpilogue();
216    
217        /**
218         * Sets the epilogue value, or remove it if the value passed is null.
219         *
220         * @param epilogue
221         *            the epilogue.
222         */
223        public abstract void setEpilogue(String epilogue);
224    
225        /**
226         * Disposes of the BodyParts of this Multipart. Note that the dispose call
227         * does not get forwarded to the parent entity of this Multipart.
228         *
229         * @see org.apache.james.mime4j.dom.Disposable#dispose()
230         */
231        public void dispose() {
232            for (Entity bodyPart : bodyParts) {
233                bodyPart.dispose();
234            }
235        }
236    
237    }