/*****************************************************************
JADE - Java Agent DEvelopment Framework is a framework to develop
multi-agent systems in compliance with the FIPA specifications.
Copyright (C) 2000 CSELT S.p.A.
GNU Lesser General Public License
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation,
version 2.1 of the License.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*****************************************************************/
package jade.core;
import jade.util.leap.Serializable;
import jade.util.leap.Comparable;
/*#MIDP_INCLUDE_BEGIN
import jade.content.lang.sl.SimpleSLTokenizer;
#MIDP_INCLUDE_END*/
import jade.util.leap.List;
import jade.util.leap.ArrayList;
import jade.util.leap.Iterator;
import jade.util.leap.Properties;
import jade.util.leap.EnumIterator;
import java.util.Enumeration;
import java.util.Vector;
/**
This class represents a JADE Agent Identifier. JADE internal agent
tables use this class to record agent names and addresses.
*/
public class AID implements Comparable, Serializable {
// Unique ID of the platform, used to build the GUID of resident agents.
private static String platformID;
private String name;
private int hashCode;
private static final int EXPECTED_ADDRESSES_SIZE = 1;
private static final int EXPECTED_RESOLVERS_SIZE = 1;
//#MIDP_EXCLUDE_BEGIN
private List addresses = new ArrayList(EXPECTED_ADDRESSES_SIZE);
private List resolvers = new ArrayList(EXPECTED_RESOLVERS_SIZE);
//#MIDP_EXCLUDE_END
/*#MIDP_INCLUDE_BEGIN
private Vector addresses = new Vector(EXPECTED_ADDRESSES_SIZE,1);
private Vector resolvers = new Vector(EXPECTED_RESOLVERS_SIZE,1);
#MIDP_INCLUDE_END*/
private Properties userDefSlots = new Properties();
/**
* Constructs an Agent-Identifier whose slot name is set to an empty string
*/
public AID() {
this("",ISGUID);
}
/** Constructor for an Agent-identifier
* This constructor (which is deprecated), examines the name
* to see if the "@" chararcter is present. If so, it calls
* <code> this(name, ISGUID)<code>
* otherwise it calls <code>this(name, ISLOCALNAME)</code>
* This ensures better compatibility with JADE2.2 code.
* @param guid is the Globally Unique identifer for the agent. The slot name
* assumes that value in the constructed object.
* @deprecated This constructor might generate a wrong AID, if
* the passed parameter is not a guid (globally unique identifier), but
* the local name of an agent (e.g. "da0").
* @see AID#AID(String boolean)
*/
public AID(String guid) {
this(guid,ISGUID);
}
/** Constructor for an Agent-identifier
* @param name is the value for the slot name for the agent.
* @param isGUID indicates if the passed <code>name</code>
* is already a globally unique identifier or not. Two
* constants <code>ISGUID</code>, <code>ISLOCALNAME</code>
* have also been defined for setting a value for this parameter.
* If the name is a local name, then the HAP (Home Agent Platform)
* is concatenated to the name, separated by "@".
**/
public AID(String name, boolean isGUID) {
if (isGUID)
setName(name);
else
setLocalName(name);
}
static final String getPlatformID() {
return platformID;
}
static final void setPlatformID(String id) {
platformID = id;
}
/** constant to be used in the constructor of the AID **/
public static final boolean ISGUID = true;
/** constant to be used in the constructor of the AID **/
public static final boolean ISLOCALNAME = false;
/**
Key to retrieve the agent class name as a user defined slot of
the AID included in the AMSAgentDescription registered with
the AMS.
*/
public static final String AGENT_CLASSNAME = "JADE-agent-classname";
/**
* This method permits to set the symbolic name of an agent.
* The passed parameter must be a GUID and not a local name.
*/
public void setName(String n){
name = n.trim();
hashCode = name.toLowerCase().hashCode();
}
/**
* This method permits to set the symbolic name of an agent.
* The passed parameter must be a local name.
*/
public void setLocalName(String n){
String hap = getPlatformID();
if (hap == null) {
throw new RuntimeException("Unknown Platform Name");
}
name = n.trim();
// Concatenates the HAP
/*if (! ( (name.length() > hap.length()) &&
name.regionMatches(true, name.length() - hap.length(), hap, 0, hap.length()))) {
name = name.concat("@"+hap);
}*/
name = name.concat("@"+hap);
hashCode = name.toLowerCase().hashCode();
}
/**
* This method returns the name of the agent.
*/
public String getName(){
return name;
}
/**
* This method permits to add a transport address where
* the agent can be contacted.
* The address is added only if not yet present
*/
public void addAddresses(String url) {
if (!addresses.contains(url)) {
//#MIDP_EXCLUDE_BEGIN
addresses.add(url);
//#MIDP_EXCLUDE_END
/*#MIDP_INCLUDE_BEGIN
addresses.addElement(url);
#MIDP_INCLUDE_END*/
}
}
/**
* To remove a transport address.
* @param url the address to remove
* @return true if the addres has been found and removed, false otherwise.
*/
public boolean removeAddresses(String url) {
//#MIDP_EXCLUDE_BEGIN
return addresses.remove(url);
//#MIDP_EXCLUDE_END
/*#MIDP_INCLUDE_BEGIN
return addresses.removeElement(url);
#MIDP_INCLUDE_END*/
}
/**
* To remove all addresses of the agent
*/
public void clearAllAddresses(){
//#MIDP_EXCLUDE_BEGIN
addresses.clear();
//#MIDP_EXCLUDE_END
/*#MIDP_INCLUDE_BEGIN
addresses.removeAllElements();
#MIDP_INCLUDE_END*/
}
/**
* Returns an iterator of all the addresses of the agent.
* @see jade.util.leap.Iterator
*/
public Iterator getAllAddresses(){
//#MIDP_EXCLUDE_BEGIN
return addresses.iterator();
//#MIDP_EXCLUDE_END
/*#MIDP_INCLUDE_BEGIN
return new EnumIterator(addresses.elements());
#MIDP_INCLUDE_END*/
}
/**
* This method permits to add the AID of a resolver (an agent where name
* resolution services for the agent can be contacted)
*/
public void addResolvers(AID aid){
if (!resolvers.contains(aid)) {
//#MIDP_EXCLUDE_BEGIN
resolvers.add(aid);
//#MIDP_EXCLUDE_END
/*#MIDP_INCLUDE_BEGIN
resolvers.addElement(aid);
#MIDP_INCLUDE_END*/
}
}
/**
* To remove a resolver.
* @param aid the AID of the resolver to remove
* @return true if the resolver has been found and removed, false otherwise.
*/
public boolean removeResolvers(AID aid){
//#MIDP_EXCLUDE_BEGIN
return resolvers.remove(aid);
//#MIDP_EXCLUDE_END
/*#MIDP_INCLUDE_BEGIN
return resolvers.removeElement(aid);
#MIDP_INCLUDE_END*/
}
/**
* To remove all resolvers.
*/
public void clearAllResolvers(){
//#MIDP_EXCLUDE_BEGIN
resolvers.clear();
//#MIDP_EXCLUDE_END
/*#MIDP_INCLUDE_BEGIN
resolvers.removeAllElements();
#MIDP_INCLUDE_END*/
}
/**
* Returns an iterator of all the resolvers.
* @see jade.util.leap.Iterator
*/
public Iterator getAllResolvers() {
//#MIDP_EXCLUDE_BEGIN
return resolvers.iterator();
//#MIDP_EXCLUDE_END
/*#MIDP_INCLUDE_BEGIN
return new EnumIterator(resolvers.elements());
#MIDP_INCLUDE_END*/
}
/**
* To add a user defined slot (a pair key, value).
* @param key the name of the property
* @param value the corresponding value of the property
*/
public void addUserDefinedSlot(String key, String value){
userDefSlots.setProperty(key, value);
}
/**
* To remove a user defined slot.
* @param key the name of the property
* @return true if the property has been found and removed, false otherwise
*/
public boolean removeUserDefinedSlot(String key){
return (userDefSlots.remove(key) != null);
}
/**
* Returns an array of string containing all the addresses of the agent
*/
public String[] getAddressesArray() {
//#MIDP_EXCLUDE_BEGIN
Object[] objs = addresses.toArray();
String[] result = new String[objs.length];
System.arraycopy(objs, 0, result, 0, objs.length);
//#MIDP_EXCLUDE_END
/*#MIDP_INCLUDE_BEGIN
String[] result = new String[addresses.size()];
addresses.copyInto(result);
#MIDP_INCLUDE_END*/
return result;
}
// For persistence service
private void setAddressesArray(String[] arr) {
//#MIDP_EXCLUDE_BEGIN
addresses.clear();
//#MIDP_EXCLUDE_END
/*#MIDP_INCLUDE_BEGIN
addresses.removeAllElements();
#MIDP_INCLUDE_END*/
for(int i = 0; i < arr.length; i++) {
addAddresses(arr[i]);
}
}
/**
* Returns an array containing all the AIDs of the resolvers.
*/
public AID[] getResolversArray() {
//#MIDP_EXCLUDE_BEGIN
Object[] objs = resolvers.toArray();
AID[] result = new AID[objs.length];
System.arraycopy(objs, 0, result, 0, objs.length);
//#MIDP_EXCLUDE_END
/*#MIDP_INCLUDE_BEGIN
AID[] result = new AID[resolvers.size()];
resolvers.copyInto(result);
#MIDP_INCLUDE_END*/
return result;
}
// For persistence service
private void setResolversArray(AID[] arr) {
//#MIDP_EXCLUDE_BEGIN
resolvers.clear();
//#MIDP_EXCLUDE_END
/*#MIDP_INCLUDE_BEGIN
resolvers.removeAllElements();
#MIDP_INCLUDE_END*/
for(int i = 0; i < arr.length; i++) {
addResolvers(arr[i]);
}
}
/**
* Returns the user-defined slots as properties.
* @return all the user-defined slots as a <code>jade.util.leap.Properties</code> java Object.
* @see jade.util.leap.Properties
*/
public Properties getAllUserDefinedSlot(){
return userDefSlots;
}
/**
* Converts this agent identifier into a readable string.
* @return the String full representation of this AID
**/
public String toString() {
StringBuffer s = new StringBuffer("( agent-identifier ");
//#MIDP_EXCLUDE_BEGIN
jade.lang.acl.StringACLCodec.appendACLExpression(s,":name",name);
//#MIDP_EXCLUDE_END
/*#MIDP_INCLUDE_BEGIN
s.append(":name ");
s.append(SimpleSLTokenizer.isAWord(name) ? name : SimpleSLTokenizer.quoteString(name));
#MIDP_INCLUDE_END*/
if (addresses.size()>0)
s.append(" :addresses (sequence ");
for (int i=0; i<addresses.size(); i++)
try {
//#MIDP_EXCLUDE_BEGIN
s.append((String)addresses.get(i));
//#MIDP_EXCLUDE_END
/*#MIDP_INCLUDE_BEGIN
s.append((String)addresses.elementAt(i));
#MIDP_INCLUDE_END*/
s.append(" ");
}
catch (IndexOutOfBoundsException e) {e.printStackTrace();}
if (addresses.size()>0)
s.append(")");
if (resolvers.size()>0)
s.append(" :resolvers (sequence ");
for (int i=0; i<resolvers.size(); i++) {
try {
//#MIDP_EXCLUDE_BEGIN
s.append(resolvers.get(i).toString());
//#MIDP_EXCLUDE_END
/*#MIDP_INCLUDE_BEGIN
s.append(resolvers.elementAt(i).toString());
#MIDP_INCLUDE_END*/
}
catch (IndexOutOfBoundsException e) {e.printStackTrace();}
s.append(" ");
}
if (resolvers.size()>0)
s.append(")");
Enumeration e = userDefSlots.propertyNames();
String key, value;
while (e.hasMoreElements()) {
key = (String)e.nextElement();
value = userDefSlots.getProperty(key);
s.append(" :X-");
//#MIDP_EXCLUDE_BEGIN
jade.lang.acl.StringACLCodec.appendACLExpression(s,key,value);
//#MIDP_EXCLUDE_END
/*#MIDP_INCLUDE_BEGIN
s.append(key);
s.append(" ");
s.append(SimpleSLTokenizer.isAWord(value) ? value : SimpleSLTokenizer.quoteString(value));
#MIDP_INCLUDE_END*/
}
s.append(")");
return s.toString();
}
/**
* Clone the AID object.
*/
public synchronized Object clone() {
AID result = new AID(this.name, ISGUID);
result.persistentID = null;
//#MIDP_EXCLUDE_BEGIN
result.addresses = (ArrayList)((ArrayList)addresses).clone();
result.resolvers = (ArrayList)((ArrayList)resolvers).clone();
//#MIDP_EXCLUDE_END
/*#MIDP_INCLUDE_BEGIN
result.addresses = new Vector(addresses.size());
for (int i=0; i<addresses.size(); i++)
result.addresses.addElement(addresses.elementAt(i));
result.resolvers = new Vector(resolvers.size());
for (int i=0; i<resolvers.size(); i++)
result.resolvers.addElement(resolvers.elementAt(i));
#MIDP_INCLUDE_END*/
// Copying user defined slots
//Enumeration enum = userDefSlots.propertyNames();
//while (enum.hasMoreElements()) {
// String key = (String) enum.nextElement();
// result.addUserDefinedSlot(key,
// (String) userDefSlots.getProperty(key));
//}
result.userDefSlots = (Properties) userDefSlots.clone();
return result;
}
/**
Equality operation. This method compares an <code>AID</code> object with
another or with a Java <code>String</code>. The comparison is case
insensitive.
@param o The Java object to compare this <code>AID</code> to.
@return <code>true</code> if one of the following holds:
<ul>
<li> The argument <code>o</code> is an <code>AID</code> object
with the same <em>GUID</em> in its name slot (apart from
differences in case).
<li> The argument <code>o</code> is a <code>String</code> that is
equal to the <em>GUID</em> contained in the name slot of this
Agent ID (apart from differences in case).
</ul>
*/
public boolean equals(Object o) {
if (o == null) {
return false;
}
if (o instanceof AID) {
return CaseInsensitiveString.equalsIgnoreCase(name, ((AID) o).name);
}
if(o instanceof String) {
return CaseInsensitiveString.equalsIgnoreCase(name, (String)o);
}
return false;
}
/**
Comparison operation. This operation imposes a total order
relationship over Agent IDs.
@param o Another <code>AID</code> object, that will be compared
with the current <code>AID</code>.
@return -1, 0 or 1 according to the lexicographical order of the
<em>GUID</em> of the two agent IDs, apart from differences in
case.
*/
public int compareTo(Object o) {
AID id = (AID)o;
return name.toLowerCase().toUpperCase().compareTo(id.name.toLowerCase().toUpperCase());
}
/**
Hash code. This method returns an hash code in such a way that two
<code>AID</code> objects with equal names or with names differing
only in case have the same hash code.
@return The hash code for this <code>AID</code> object.
*/
public int hashCode() {
return hashCode;
}
/**
* Returns the local name of the agent (without the HAP).
* If the agent is not local, then the method returns its GUID.
*/
public String getLocalName() {
int atPos = name.lastIndexOf('@');
if(atPos == -1)
return name;
else
return name.substring(0, atPos);
}
/**
Returns the HAP of the agent or null if the GUID of this
<code>AID</code> is not of the form <local-name>@<platform-name>
*/
public String getHap() {
int atPos = name.lastIndexOf('@');
if(atPos == -1)
return null;
else
return name.substring(atPos + 1);
}
// For persistence service
private transient Long persistentID;
// For persistence service
private Long getPersistentID() {
return persistentID;
}
// For persistence service
private void setPersistentID(Long l) {
persistentID = l;
}
}