package mil.navy.nps.relate; import java.util.*; /******************************************************************************* *

RelationshipManager is the heart of the RELATE simulation * package.

* *

RelationshipManager is an example of the "singleton" programming pattern. * "Singleton" means that there is one, and only one, instance of this class per * application. This is accomplished by the static, synchronized * getRelationshipManager() method. This method creates a new * RelationshipManager upon the first request, or returns the existing, unique * RelationshipManager if it has already been created. The RelationshipManager * is the only complete Java class in RELATE. All other classes are either * abstract or interfaces. An abstract class contains one or more abstract * methods that are required to be defined by the developer. An interface has * no data members and all methods must be defined by the developer.

* *

The RelationshipManager handles the formation and administration of all * relationships by requiring agents to form relationships with the * checkForRelationships() method. This method is the most significant method * in this class. It checks for every possible relationship that can be formed * between the requesting, passed in agent and other agents in its * sensedEnvironment. Since the requirements for formation of new relationships * are defined within the individual relationships, the RelationshipManager * instantiates the requested relationship using the createRelationship() * method. This is possible due to the no-argument constructor used in the * Relationship interface. If conditions are met, it adds the agent to this new * Relationship. Otherwise, the relationship is never utilized and it is * cleaned up with the automatic garbage collection feature of Java. * Relationship administration is accomplished by maintaining a current list, or * vector, of active relationships, available through a getter method. The * RelationshipManager adds relationships to this vector, but they are removed * by the individual relationships.

* *

See the Relationship class for more * details on how relationships interact with the RelationshipManager.

* * @author Michael R. Dickson * @author Kimberly A. Roddy * @version 1.0, 17 Aug 00 * @since JDK1.3 ******************************************************************************* */ public class RelationshipManager { /******************************************************************************* *Contains all currently active relationships in the simulation. ******************************************************************************* */ public Vector activeRelationshipVec; /******************************************************************************* *Contains all agents that have made the checkForRelationships() call. ******************************************************************************* */ public Hashtable agentTable; /******************************************************************************* *The static relationshipManager that is passed to all agents. ******************************************************************************* */ private static RelationshipManager relMan; /**************************************************************************** * Private no-argument constructor called from within the class via the * "singleton" pattern. **************************************************************************** */ private RelationshipManager() { activeRelationshipVec = new Vector(); agentTable = new Hashtable(); }// end RelationshipManager() /******************************************************************************* * Method that returns the singleton relationshipManager. * @return: A singleton RelationshipManager ******************************************************************************* */ public static synchronized RelationshipManager getRelationshipManager() { if( relMan == null ) { relMan = new RelationshipManager(); }// end if return relMan; }// end getRelationshipManager() /******************************************************************************* * Adds the passed in agent to the agentTable Hashtable. * @param pAgent: The agent to be added to Hashtable ******************************************************************************* */ public void addAgent( Agent pAgent ) { //Agent ID as key for Hashtable Long tempAgentID = new Long( pAgent.getAgentID() ); agentTable.put( tempAgentID, pAgent ); }// end addAgent() /******************************************************************************* * Checks for all possible relationships between the passed in agent and all * of the agent's sensed agents. If the agent can join a perviously formed * relationship, it is added and further checking for that relationship is * stopped. If no perviously formed relationships can be joined, a new * relationship is formed and tested to see if its conditions are met with the * agent and all sensed agents that are not currently in that realtionship. If * they are, then the relationship is added to the active realtionship vector * and the agents are issued roles/goals/rules from the new relationship. If * conditions are not met the relationship is destroyed and the agent does not * join a relationship. * * @param pAgent: The agent to be checked for relationships ******************************************************************************* */ public void checkForRelationships( Agent pAgent ) { //this is to stop the checking once each relationship has been joined boolean joined; //temporary agent relationship HashTable Hashtable pAgentRelTable = pAgent.getRelationshipTable(); Enumeration relEnum = pAgentRelTable.keys(); //loop through to see if there are any relationships to be formed while( relEnum.hasMoreElements() ) { joined = false; String relationshipClassName = (String)relEnum.nextElement(); //form a vector of (relationship common) agents in the sensed environment SensedEnvironment copySEnv = pAgent.getSensedEnvironment(); Vector copySAgents = copySEnv.getSensedAgents(); //container for agents that can form this type of relationship Vector commonAgents = new Vector(); for( int ax = 0; ax < copySAgents.size(); ax++ ) { Agent testAgent = (Agent)copySAgents.elementAt( ax ); Hashtable testSAgentHash = testAgent.getRelationshipTable(); if( testSAgentHash.containsKey( relationshipClassName ) ) { commonAgents.add( testAgent ); }//end if }//end for //continue testing Object temp = (Object)pAgentRelTable.get(relationshipClassName); //if pAgent doesn't have this relationship object yet if( !( temp instanceof Relationship ) ) { //cycle through the common agents to see if any of them are already //members of this type of relationship, if so try to join for( int bx = 0; bx < commonAgents.size(); bx++ ) { Agent testAgent = (Agent)commonAgents.elementAt(bx); Hashtable testSAgentHash = testAgent.getRelationshipTable(); Object temp2 = (Object)testSAgentHash.get(relationshipClassName); //try to join the common agents relationship if( ( temp2 instanceof Relationship )&& ( !joined ) ) { //remove this agent from consideration if we have to //create a new instance of this relationship commonAgents.remove(testAgent); bx--; Relationship formedRelationship = (Relationship)temp2; if(formedRelationship.addAgent(pAgent)) { pAgentRelTable.put(relationshipClassName,formedRelationship); joined = true; }//end if }//end if }//end for //at this point pAgent has joined an existing relationship or not. //If it hasn't joined, create an instance of the relationship //and try to join that if( !joined ) { //now we have already weeded out the agents that are already in //this relationship before we pass it to the new instance of the //relationship in question Relationship tempRelationship = createRelationship( relationshipClassName ); tempRelationship.setClassName( relationshipClassName ); if( tempRelationship.conditionsMet( pAgent, commonAgents ) ) { //relationshipManager bookkeeping activeRelationshipVec.add( tempRelationship ); //cycle through the agents that the relationship has added //and update their hashtables Vector relMembers = tempRelationship.getMembers(); for( int cx = 0; cx < relMembers.size(); cx++ ) { Agent relAgent = (Agent)relMembers.elementAt( cx ); Hashtable agentHash = relAgent.getRelationshipTable(); agentHash.put( relationshipClassName, tempRelationship ); //don't really need this but I'm throwing it in anyway //for robustness if( relAgent == pAgent ) { joined = true; }// end if }// end for }// end if }// end if }// end if }// end while }//end checkForRelationships() /******************************************************************************* * Creates the Relationship the corresponds to the passed in class name. * Relationships have no-argument constructors, thus they have the ability to * be formed with this method. * * @param className: The className of the Relationship to be created * @return: The created Relationship. ******************************************************************************* */ private Relationship createRelationship( String className ) { Class cl = null; try { cl = Class.forName( className ); }//end try catch( ClassNotFoundException e ) { System.err.println( "Can't find your darned class." ); System.exit( 0 ); }//end catch Object o = null; try { o = cl.newInstance(); }//end try catch( InstantiationException e ) { System.err.println( "Can't make your darned class." ); System.exit( 0 ); }//end catch catch( IllegalAccessException e ) { System.err.println( "Can't access your darned class." ); System.exit( 0 ); }//end catch return (Relationship)o; }// end createRelationship() /******************************************************************************* * Simple getter method for getting the active relationship vector. * @return: The active relationship vector. ******************************************************************************* */ public Vector getFormedRelationships() { return activeRelationshipVec; } }// end RelationshipManager class