package org.jacorb.poa;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import org.jacorb.poa.AGM.TGTCWrapper;
import org.omg.PortableGroup.TagGroupTaggedComponent;
/**
* Active Group Map Map groups with its members oids.
*
* @author Alysson Neves Bessani
* @author Nick Cross
* @version 1.0
* @see GOA
*/
public class AGM
{
private static final byte [][]EMPTYBYTE = new byte[0][];
private HashMap<TGTCWrapper, ArrayList<byte[]>> groupTable = new HashMap<TGTCWrapper, ArrayList<byte[]>> ();
/**
* Adds an oid to a group represented by the TagGroupTaggedComponent
*
* @param tagGroupTaggedComponent
* @param oid
* @return the size of the group
*/
synchronized int addToGroup (TagGroupTaggedComponent tagGroupTaggedComponent, byte[] oid)
{
TGTCWrapper t = new TGTCWrapper (tagGroupTaggedComponent);
ArrayList members = (ArrayList)groupTable.get (t);
if (members == null)
{
members = new ArrayList ();
groupTable.put (t, members);
}
// If it does not contain the OID insert it
if (!members.contains (oid))
{
members.add (oid);
}
return members.size ();
}
/**
* Removes a stringfied oid to a group (represented by the stringfied group
* key)
*
* @param tagGroupTaggedComponent
* @param oid
* @return the size of the group
*/
synchronized int removeFromGroup (TagGroupTaggedComponent tagGroupTaggedComponent, byte[] oid)
{
TGTCWrapper t = new TGTCWrapper (tagGroupTaggedComponent);
ArrayList members = (ArrayList)groupTable.get (t);
if (members == null)
{
// no group exists in the table so return 0 for no members.
return 0;
}
members.remove (oid);
int nMembers = members.size ();
// check if there members in this group (group empty), if empty
// remove the entry from the group table.
if (nMembers == 0)
{
groupTable.remove (t);
}
return nMembers;
}
/**
* Returns the group members
*
* @param tagGroup
* @return the group members oids as strings
*/
final byte[][] getMembersFromGroup (TagGroupTaggedComponent tagGroup)
{
TGTCWrapper t = new TGTCWrapper (tagGroup);
ArrayList members = (ArrayList)groupTable.get (t);
return
(
members == null ?
// no group in the table, has no members
EMPTYBYTE
:
// group exists, return the array of members
(byte[][])members.toArray (EMPTYBYTE)
);
}
/**
* Returns the groups in which the object is registered.
*
* @param oid
* @return the groups that have this object as a member
*/
final ArrayList<TGTCWrapper> getGroupsWithMember (byte[] oid)
{
ArrayList<TGTCWrapper> keyList = new ArrayList<TGTCWrapper> ();
for (Iterator<TGTCWrapper> iterator = groupTable.keySet ().iterator (); iterator.hasNext ();)
{
TGTCWrapper t = (TGTCWrapper)iterator.next ();
byte [][]oids = getMembersFromGroup (t.tcgtc);
for (int i = 0; i < oids.length; i++)
{
if (Arrays.equals (oids[i], oid))
{
keyList.add (t);
continue;
}
}
}
return keyList;
}
/**
* TGTCWrapper is a simple wrapper around a TagGroupTaggedComponent. It
* allows a TagGroupTaggedComponent to be used as a key in a hashmap as its
* implementation of hashCode and equals actually is an implementation for
* the component not the wrapper.
*/
static class TGTCWrapper
{
TagGroupTaggedComponent tcgtc;
public TGTCWrapper (TagGroupTaggedComponent tagGroupTaggedComponent)
{
tcgtc = tagGroupTaggedComponent;
}
/**
* This implementation manually generates hashcode on the contained component
* rather than delegating to its implementation (as its generated code it doesn't have one).
*
* @see java.lang.Object#hashCode()
*/
public int hashCode ()
{
final int prime = 31;
int result = 1;
result = prime * result +
((tcgtc.group_domain_id == null) ? 0 : tcgtc.group_domain_id.hashCode ());
result = prime * result + ((tcgtc.group_version == null) ? 0 : tcgtc.group_version.major);
result = prime * result + ((tcgtc.group_version == null) ? 0 : tcgtc.group_version.minor);
result = prime * result + (int)(tcgtc.object_group_id ^ (tcgtc.object_group_id >>> 32));
result = prime * result + tcgtc.object_group_ref_version;
return result;
}
/**
* This implementation manually checks for equality on the contained component
* rather than delegating to its implementation (as its generated code it doesn't have one).
*
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals (Object obj)
{
if (this == obj)
{
return true;
}
if (obj == null)
{
return false;
}
if (!(obj instanceof TGTCWrapper))
{
return false;
}
TagGroupTaggedComponent other = ((TGTCWrapper)obj).tcgtc;
if (tcgtc == null || other == null)
{
return false;
}
if (tcgtc.group_domain_id == null)
{
if (other.group_domain_id != null)
{
return false;
}
}
else if (!tcgtc.group_domain_id.equals (other.group_domain_id))
{
return false;
}
if (tcgtc.group_version == null)
{
if (other.group_version != null)
{
return false;
}
}
else if (!(tcgtc.group_version.major == other.group_version.major && tcgtc.group_version.minor == other.group_version.minor))
{
return false;
}
if (tcgtc.object_group_id != other.object_group_id)
{
return false;
}
if (tcgtc.object_group_ref_version != other.object_group_ref_version)
{
return false;
}
return true;
}
}
}