KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > dream > message > MessageTypeImpl


1 /**
2  * Dream
3  * Copyright (C) 2003-2004 INRIA Rhone-Alpes
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Contact : dream@objectweb.org
20  *
21  * Initial developer(s): Matthieu Leclercq
22  * Contributor(s):
23  */

24
25 package org.objectweb.dream.message;
26
27 import java.util.Hashtable JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import java.util.LinkedList JavaDoc;
30
31 import org.objectweb.dream.util.EmptyIterator;
32 import org.objectweb.dream.util.EmptyStringArray;
33
34 /**
35  * Basic Implementation of {@link org.objectweb.dream.message.MessageType}
36  */

37 public class MessageTypeImpl implements MessageType, EmptyStringArray
38 {
39
40   /** A constant designating the empty message type. */
41   public static final MessageType EMPTY_MESSAGE_TYPE = new MessageTypeImpl();
42
43   /** Hashtable associating names and chunk types */
44   protected Hashtable JavaDoc chunkTypes = null;
45   /** List of sub message types */
46   protected LinkedList JavaDoc subMessageTypes = null;
47
48   /** The chunk names */
49   protected String JavaDoc[] chkNames = null;
50   /** The sub message types */
51   protected MessageType[] subMessageTypesArray = null;
52
53   /**
54    * Creates an empty message type. This constructor is protected. To manipulate
55    * the empty message type, components should use the
56    * {@link #EMPTY_MESSAGE_TYPE}constant.
57    */

58   protected MessageTypeImpl()
59   {
60   }
61
62   /**
63    * Creates a message type with the specified chunk types and sub message
64    * types. <code>chkNames</code> array contains the name of chunk types,
65    * which are specified in <code>chkTypes</code> array (as a consequence
66    * these two arrays must have the same length). Names and types are associated
67    * following their order in arrays.
68    *
69    * @param chkNames array of chunk names can be <code>null</code>.
70    * @param chkTypes array of chunk types (ignored if <code>chkNames</code> is
71    * <code>null</code>).
72    * @param msgTypes array of sub message types can be <code>null</code>.
73    * @throws IllegalArgumentException If <code>chkNames</code> and
74    * <code>chkTypes</code> do not have the same length.
75    * @throws ChunkAlreadyExistsException If the same name appears twice in
76    * <code>chkNames</code>
77    */

78   public MessageTypeImpl(String JavaDoc[] chkNames, ChunkType[] chkTypes,
79       MessageType[] msgTypes) throws ChunkAlreadyExistsException
80   {
81     ChunkAlreadyExistsException chunkAlreadyExistException = null;
82     if (chkNames != null)
83     {
84       if (chkNames.length != chkTypes.length)
85       {
86         throw new IllegalArgumentException JavaDoc(
87             "chkNames and chkTypes do not have the same length");
88       }
89
90       for (int i = 0; i < chkNames.length; i++)
91       {
92         try
93         {
94           addChunkType(chkNames[i], chkTypes[i]);
95         }
96         catch (ChunkAlreadyExistsException e)
97         {
98           chunkAlreadyExistException = e;
99         }
100       }
101     }
102
103     if (msgTypes != null)
104     {
105       for (int i = 0; i < msgTypes.length; i++)
106       {
107         addSubMessageType(msgTypes[i]);
108       }
109     }
110     if (chunkAlreadyExistException != null)
111     {
112       throw chunkAlreadyExistException;
113     }
114   }
115
116   /**
117    * Creates a message type that contains a chunk type. This constructor is
118    * provided for convenience
119    *
120    * @param chkName the name of the chunk type
121    * @param chkType the chunk type
122    */

123   public MessageTypeImpl(String JavaDoc chkName, ChunkType chkType)
124   {
125     chunkTypes = new Hashtable JavaDoc();
126     chunkTypes.put(chkName, chkType);
127   }
128
129   /**
130    * Creates a message type that contains two chunk types. This constructor is
131    * provided for convenience
132    *
133    * @param chkName1 the name of the first chunk type
134    * @param chkType1 the first chunk type
135    * @param chkName2 the name of the second chunk type
136    * @param chkType2 the second chunk type
137    * @throws ChunkAlreadyExistsException if <code>chkname1</code> and
138    * <code>chkName2</code> are equals
139    */

140   public MessageTypeImpl(String JavaDoc chkName1, ChunkType chkType1, String JavaDoc chkName2,
141       ChunkType chkType2) throws ChunkAlreadyExistsException
142   {
143     addChunkType(chkName1, chkType1);
144     addChunkType(chkName2, chkType2);
145   }
146
147   /**
148    * @see org.objectweb.dream.message.MessageType#getChunkType(java.lang.String)
149    */

150   public ChunkType getChunkType(String JavaDoc name)
151   {
152     if (chunkTypes == null)
153     {
154       return null;
155     }
156     return (ChunkType) chunkTypes.get(name);
157
158   }
159
160   /**
161    * @see org.objectweb.dream.message.MessageType#getChunkNames()
162    */

163   public String JavaDoc[] getChunkNames()
164   {
165     if (chkNames == null)
166     {
167       if (chunkTypes == null)
168       {
169         chkNames = EMPTY_STRING_ARRAY;
170       }
171       else
172       {
173         chkNames = (String JavaDoc[]) chunkTypes.keySet().toArray(EMPTY_STRING_ARRAY);
174       }
175     }
176     return chkNames;
177   }
178
179   /**
180    * @see org.objectweb.dream.message.MessageType#getChunkNamesIterator()
181    */

182   public Iterator JavaDoc getChunkNamesIterator()
183   {
184     if (chunkTypes == null)
185     {
186       return EmptyIterator.INSTANCE;
187     }
188     return chunkTypes.keySet().iterator();
189   }
190
191   /**
192    * @see org.objectweb.dream.message.MessageType#getSubMessageTypes()
193    */

194   public MessageType[] getSubMessageTypes()
195   {
196     if (subMessageTypesArray == null)
197     {
198       if (subMessageTypes == null)
199       {
200         subMessageTypesArray = EMPTY_MESSAGE_TYPE_ARRAY;
201       }
202       else
203       {
204         subMessageTypesArray = (MessageType[]) subMessageTypes
205             .toArray(EMPTY_MESSAGE_TYPE_ARRAY);
206       }
207     }
208     return subMessageTypesArray;
209   }
210
211   /**
212    * @see org.objectweb.dream.message.MessageType#getSubMessageTypesIterator()
213    */

214   public Iterator JavaDoc getSubMessageTypesIterator()
215   {
216     if (subMessageTypes == null)
217     {
218       return EmptyIterator.INSTANCE;
219     }
220     return subMessageTypes.iterator();
221   }
222
223   /**
224    * @see org.objectweb.dream.message.MessageType#isEmpty()
225    */

226   public boolean isEmpty()
227   {
228     return chunkTypes == null && subMessageTypes == null;
229   }
230
231   /**
232    * @see org.objectweb.dream.message.MessageType#isSubTypeOf(org.objectweb.dream.message.MessageType)
233    */

234   public boolean isSubTypeOf(MessageType t)
235   {
236     if (t.isEmpty())
237     {
238       return true;
239     }
240
241     // test if every chunk types in t are in this type, and are sub types
242
String JavaDoc[] tChkNames = t.getChunkNames();
243     for (int i = 0; i < tChkNames.length; i++)
244     {
245       String JavaDoc name = tChkNames[i];
246       ChunkType thisChkType = (ChunkType) chunkTypes.get(name);
247       if (thisChkType == null)
248       {
249         // type t contains a chunk with a name that is not known as a chunk
250
// name of this type.
251
return false;
252       }
253       ChunkType tChkType = t.getChunkType(name);
254       if (tChkType == null)
255       {
256         return false;
257       }
258       if (!thisChkType.isSubTypeOf(tChkType))
259       {
260         return false;
261       }
262     }
263
264     // test if every message types in t are in this type, and are sub types
265
// NOT IMPLEMENTED for sub message types
266
return true;
267   }
268
269   /**
270    * Adds a chunk type
271    *
272    * @param chunkName the name of the chunk type
273    * @param chunkType the chunk type
274    * @throws ChunkAlreadyExistsException if this type already contains a chunk
275    * type with the specified name
276    */

277   public void addChunkType(String JavaDoc chunkName, ChunkType chunkType)
278       throws ChunkAlreadyExistsException
279   {
280     if (chunkTypes == null)
281     {
282       chunkTypes = new Hashtable JavaDoc();
283     }
284     Object JavaDoc previousChunk = chunkTypes.put(chunkName, chunkType);
285     if (previousChunk != null)
286     {
287       chunkTypes.put(chunkName, chunkType);
288       throw new ChunkAlreadyExistsException(
289           "Chunk type with the same name already exist");
290     }
291     // invalidate chkNames array
292
chkNames = null;
293   }
294
295   /**
296    * Adds a sub message type
297    *
298    * @param msgType the message type to add
299    */

300   public void addSubMessageType(MessageType msgType)
301   {
302     if (subMessageTypes == null)
303     {
304       subMessageTypes = new LinkedList JavaDoc();
305     }
306     subMessageTypes.add(msgType);
307     // invalidate subMessageTypeArray
308
subMessageTypesArray = null;
309   }
310
311   /**
312    * removes a chunk type
313    *
314    * @param name the name of the chunk type.
315    * @return the chunk type or <code>null</code> if no chunk type with the
316    * specified name exists.
317    */

318   public ChunkType removeChunkType(String JavaDoc name)
319   {
320     if (chunkTypes == null)
321     {
322       return null;
323     }
324     ChunkType t = (ChunkType) chunkTypes.remove(name);
325     if (t != null)
326     {
327       // invalidate chkNames array
328
chkNames = null;
329       if (chunkTypes.isEmpty())
330       {
331         chunkTypes = null;
332       }
333     }
334     return t;
335   }
336
337   /**
338    * Removes a sub message type
339    *
340    * @param msgType the message type to remove
341    * @return <code>true</code> if the specified message type can be removed
342    */

343   public boolean removeSubMessageType(MessageType msgType)
344   {
345     if (subMessageTypes == null)
346     {
347       return false;
348     }
349     if (subMessageTypes.remove(msgType))
350     {
351       // invalidate subMessageTypeArray
352
subMessageTypesArray = null;
353       if (subMessageTypes.isEmpty())
354       {
355         subMessageTypes = null;
356       }
357       return true;
358     }
359     return false;
360   }
361 }
Popular Tags