1 /******************************************************************
2 JADE - Java Agent DEvelopment Framework is a framework to develop
3 multi-agent systems in compliance with the FIPA specifications.
4 Copyright (C) 2000 CSELT S.p.A.
5
6 GNU Lesser General Public License
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation,
11 version 2.1 of the License.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with this library; if not, write to the
20 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.
22 *****************************************************************/
23
24 package JADE_SL;
25
26
27 import java.io.Writer;
28 import java.io.IOException;
29
30 import java.util.*;
31
32 /***
33 This class represents a JADE Agent Identifier. JADE internal agent
34 tables use this class to record agent names and addresses.
35 */
36 public class AID {
37
38 /***
39 @serial
40 */
41 private String name = new String();
42
43 /***
44 @serial
45 */
46 private List addresses = new ArrayList();
47
48 /***
49 @serial
50 */
51 private List resolvers = new ArrayList();
52
53 /***
54 @serial
55 */
56 private Properties userDefSlots = new Properties();
57
58
59 /***
60 * Constructs an Agent-Identifier whose slot name is set to an empty string
61 */
62 public AID() {
63 this("",ISGUID);
64 }
65
66 /*** Constructor for an Agent-identifier
67 * This constructor (which is deprecated), examines the name
68 * to see if the "@" chararcter is present. If so, it calls
69 * <code> this(name, ISGUID)<code>
70 * otherwise it calls <code>this(name, ISLOCALNAME)</code>
71 * This ensures better compatibility with JADE2.2 code.
72 * @param guid is the Globally Unique identifer for the agent. The slot name
73 * assumes that value in the constructed object.
74 * @deprecated This constructor might generate a wrong AID, if
75 * the passed parameter is not a guid (globally unique identifier), but
76 * the local name of an agent (e.g. "da0").
77 * @see AID#AID(String boolean)
78 */
79 public AID(String guid) {
80 this(guid,ISGUID);
81 }
82
83
84 /*** Constructor for an Agent-identifier
85 * @param name is the value for the slot name for the agent.
86 * @param isGUID indicates if the passed <code>name</code>
87 * is already a globally unique identifier or not. Two
88 * constants <code>ISGUID</code>, <code>ISLOCALNAME</code>
89 * have also been defined for setting a value for this parameter.
90 * If the name is a local name, then the HAP (Home Agent Platform)
91 * is concatenated to the name, separated by "@".
92 **/
93 public AID(String name, boolean isGUID) {
94
95 if (atHAP == null)
96 atHAP = "@"+zeus.util.SystemProps.getProperty("HAP.address");
97 if (isGUID)
98 setName(name);
99 else
100 setLocalName(name);
101 }
102
103 /*** constant to be used in the constructor of the AID **/
104 public static final boolean ISGUID = true;
105 /*** constant to be used in the constructor of the AID **/
106 public static final boolean ISLOCALNAME = false;
107
108 /*** private variable containing the right part of a local name **/
109 private static String atHAP = null;
110
111 /***
112 * This method permits to set the symbolic name of an agent.
113 * The passed parameter must be a GUID and not a local name.
114 */
115 public void setName(String n){
116 name = n.trim();
117 }
118
119 /***
120 * This method permits to set the symbolic name of an agent.
121 * The passed parameter must be a local name.
122 */
123 public void setLocalName(String n){
124 name = n.trim();
125 if ((name != null) && (!name.endsWith(atHAP)))
126 name = name.concat(atHAP);
127 }
128
129 /***
130 * This method returns the name of the agent.
131 */
132 public String getName(){
133 return name;
134 }
135
136 /***
137 * This method permits to add a transport address where
138 * the agent can be contacted.
139 * The address is added only if not yet present
140 */
141 public void addAddresses(String url) {
142 if (!addresses.contains(url)) {
143 addresses.add(url);
144 }
145 }
146
147 /***
148 * To remove a transport address.
149 * @param url the address to remove
150 * @return true if the addres has been found and removed, false otherwise.
151 */
152 public boolean removeAddresses(String url) {
153 return addresses.remove(url);
154 }
155
156 /***
157 * To remove all addresses of the agent
158 */
159 public void clearAllAddresses(){
160 addresses.clear();
161 }
162
163 /***
164 * Returns an iterator of all the addresses of the agent.
165 * @see jade.util.leap.Iterator
166 */
167 public Iterator getAllAddresses(){
168 return addresses.iterator();
169 }
170
171 /***
172 * This method permits to add the AID of a resolver (an agent where name
173 * resolution services for the agent can be contacted)
174 */
175 public void addResolvers(AID aid){
176 resolvers.add(aid);
177 }
178
179 /***
180 * To remove a resolver.
181 * @param aid the AID of the resolver to remove
182 * @return true if the resolver has been found and removed, false otherwise.
183 */
184 public boolean removeResolvers(AID aid){
185 return resolvers.remove(aid);
186 }
187
188 /***
189 * To remove all resolvers.
190 */
191 public void clearAllResolvers(){
192 resolvers.clear();
193 }
194
195 /***
196 * Returns an iterator of all the resolvers.
197 * @see jade.util.leap.Iterator
198 */
199 public Iterator getAllResolvers() {
200 return resolvers.iterator();
201 }
202
203 /***
204 * To add a user defined slot (a pair key, value).
205 * @param key the name of the property
206 * @param value the corresponding value of the property
207 */
208 public void addUserDefinedSlot(String key, String value){
209 userDefSlots.setProperty(key, value);
210 }
211
212
213 /***
214 * Returns an array of string containing all the addresses of the agent
215 */
216 public String[] getAddressesArray() {
217 Object[] objs = addresses.toArray();
218 String[] result = new String[objs.length];
219 System.arraycopy(objs, 0, result, 0, objs.length);
220 return result;
221 }
222
223 /***
224 * Returns an array containing all the AIDs of the resolvers.
225 */
226 public AID[] getResolversArray() {
227 Object[] objs = resolvers.toArray();
228 AID[] result = new AID[objs.length];
229 System.arraycopy(objs, 0, result, 0, objs.length);
230 return result;
231 }
232
233 /***
234 * Returns the user-defined slots as properties.
235 * @return all the user-defined slots as a <code>jade.util.leap.Properties</code> java Object.
236 * @see jade.util.leap.Properties
237 */
238 public Properties getAllUserDefinedSlot(){
239 return userDefSlots;
240 }
241
242
243 /***
244 * @return the String full representation of this AID
245 **/
246 public String toString() {
247 StringBuffer s = new StringBuffer("( agent-identifier ");
248 if ((name!=null)&&(name.length()>0)) {
249 s.append(" :name ");
250 s.append(name);
251 }
252 if (addresses.size()>0)
253 s.append(" :addresses (sequence ");
254 for (int i=0; i<addresses.size(); i++)
255 try {
256 s.append((String)addresses.get(i));
257 s.append(" ");
258 }
259 catch (IndexOutOfBoundsException e) {e.printStackTrace();}
260 if (addresses.size()>0)
261 s.append(")");
262 if (resolvers.size()>0)
263 s.append(" :resolvers (sequence ");
264 for (int i=0; i<resolvers.size(); i++) {
265 try {
266 s.append(resolvers.get(i).toString());
267 }
268 catch (IndexOutOfBoundsException e) {e.printStackTrace();}
269 s.append(" ");
270 }
271 if (resolvers.size()>0)
272 s.append(")");
273 Enumeration e = userDefSlots.propertyNames();
274 String tmp;
275 while (e.hasMoreElements()) {
276 tmp = (String)e.nextElement();
277 s.append(" :X-");
278 s.append(tmp);
279 s.append(" ");
280 s.append(userDefSlots.getProperty(tmp));
281 }
282 s.append(")");
283 return s.toString();
284 }
285
286 /***
287 * This method is called from ACLMessage in order to create
288 * the String encoding of an ACLMessage.
289 * @deprecated replaced by the method toString
290 */
291 public void toText(Writer w) {
292 try {
293 w.write(toString());
294 w.flush();
295 } catch(IOException ioe) {
296 ioe.printStackTrace();
297 }
298 }
299
300
301
302 /***
303 * Clone the AID object.
304 */
305 public synchronized Object clone() {
306 AID result = new AID(this.name);
307
308 result.addresses = (ArrayList)((ArrayList)addresses).clone();
309
310 result.resolvers = (ArrayList)((ArrayList)resolvers).clone();
311
312
313
314
315
316
317
318
319 result.userDefSlots = userDefSlots;
320
321 return result;
322 }
323
324
325
326
327
328
329
330
331
332
333
334
335
336 /***
337 Equality operation. This method compares an <code>AID</code> object with
338 another or with a Java <code>String</code>. The comparison is case
339 insensitive.
340 @param o The Java object to compare this <code>AID</code> to.
341 @return <code>true</code> if one of the following holds:
342 <ul>
343 <li> The argument <code>o</code> is an <code>AID</code> object
344 with the same <em>GUID</em> in its name slot (apart from
345 differences in case).
346 <li> The argument <code>o</code> is a <code>String</code> that is
347 equal to the <em>GUID</em> contained in the name slot of this
348 Agent ID (apart from differences in case).
349 </ul>
350 */
351 public boolean equals(Object o) {
352
353 if (o == null)
354 return false;
355 if(o instanceof String) {
356 return CaseInsensitiveString.equalsIgnoreCase(name, (String)o);
357 }
358 try {
359 AID id = (AID)o;
360 return CaseInsensitiveString.equalsIgnoreCase(name, id.name);
361 }
362 catch(ClassCastException cce) {
363 return false;
364 }
365
366 }
367
368
369 /***
370 Comparison operation. This operation imposes a total order
371 relationship over Agent IDs.
372 @param o Another <code>AID</code> object, that will be compared
373 with the current <code>AID</code>.
374 @return -1, 0 or 1 according to the lexicographical order of the
375 <em>GUID</em> of the two agent IDs, apart from differences in
376 case.
377 */
378 public int compareTo(Object o) {
379 AID id = (AID)o;
380 return name.toLowerCase().toUpperCase().compareTo(id.name.toLowerCase().toUpperCase());
381 }
382
383
384 /***
385 Hash code. This method returns an hash code in such a way that two
386 <code>AID</code> objects with equal names or with names differing
387 only in case have the same hash code.
388 @return The hash code for this <code>AID</code> object.
389 */
390 public int hashCode() {
391 return name.toLowerCase().hashCode();
392 }
393
394 /***
395 * Returns the local name of the agent (without the HAP).
396 * If the agent is not local, then the method returns its GUID.
397 */
398 public String getLocalName() {
399 int atPos = name.lastIndexOf('@');
400 if(atPos == -1)
401 return name;
402 else
403 return name.substring(0, atPos);
404 }
405
406 /***
407 * Returns the HAP of the agent.
408 */
409 String getHap() {
410 int atPos = name.lastIndexOf('@');
411 if(atPos == -1)
412 return name;
413 else
414 return name.substring(atPos + 1);
415 }
416
417 }