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 < 0 || index >
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 < 0 || index >=
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 < 0 || index >=
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 }