llgroupmgr.cpp

Go to the documentation of this file.
00001 
00037 #include "llviewerprecompiledheaders.h"
00038 
00039 #include "llgroupmgr.h"
00040 
00041 #include <vector>
00042 #include <algorithm>
00043 
00044 #include "llagent.h"
00045 #include "llui.h"
00046 #include "message.h"
00047 #include "roles_constants.h"
00048 #include "lltransactiontypes.h"
00049 #include "llstatusbar.h"
00050 #include "lleconomy.h"
00051 #include "llviewerwindow.h"
00052 #include "llfloaterdirectory.h"
00053 #include "llfloatergroupinfo.h"
00054 #include "lluictrlfactory.h"
00055 
00056 
00057 const U32 MAX_CACHED_GROUPS = 10;
00058 
00059 //
00060 // LLRoleActionSet
00061 //
00062 LLRoleActionSet::LLRoleActionSet()
00063 : mActionSetData(NULL)
00064 { }
00065 
00066 LLRoleActionSet::~LLRoleActionSet()
00067 {
00068         delete mActionSetData;
00069         std::for_each(mActions.begin(), mActions.end(), DeletePointer());
00070 }
00071 
00072 //
00073 // LLGroupMemberData
00074 //
00075 
00076 LLGroupMemberData::LLGroupMemberData(const LLUUID& id, 
00077                                                                                 S32 contribution,
00078                                                                                 U64 agent_powers,
00079                                                                                 const std::string& title,
00080                                                                                 const std::string& online_status,
00081                                                                                 BOOL is_owner) : 
00082         mID(id), 
00083         mContribution(contribution), 
00084         mAgentPowers(agent_powers), 
00085         mTitle(title), 
00086         mOnlineStatus(online_status),
00087         mIsOwner(is_owner)
00088 {
00089 }
00090 
00091 LLGroupMemberData::~LLGroupMemberData()
00092 {
00093 }
00094 
00095 void LLGroupMemberData::addRole(const LLUUID& role, LLGroupRoleData* rd)
00096 {
00097         mRolesList[role] = rd;
00098 }
00099 
00100 bool LLGroupMemberData::removeRole(const LLUUID& role)
00101 {
00102         role_list_t::iterator it = mRolesList.find(role);
00103 
00104         if (it != mRolesList.end())
00105         {
00106                 mRolesList.erase(it);
00107                 return true;
00108         }
00109 
00110         return false;
00111 }
00112 
00113 //
00114 // LLGroupRoleData
00115 //
00116 
00117 LLGroupRoleData::LLGroupRoleData(const LLUUID& role_id, 
00118                                                                 const std::string& role_name,
00119                                                                 const std::string& role_title,
00120                                                                 const std::string& role_desc,
00121                                                                 const U64 role_powers,
00122                                                                 const S32 member_count) :
00123         mRoleID(role_id),
00124         mMemberCount(member_count),
00125         mMembersNeedsSort(FALSE)
00126 {
00127         mRoleData.mRoleName = role_name;
00128         mRoleData.mRoleTitle = role_title;
00129         mRoleData.mRoleDescription = role_desc;
00130         mRoleData.mRolePowers = role_powers;
00131         mRoleData.mChangeType = RC_UPDATE_NONE;
00132 }
00133 
00134 LLGroupRoleData::LLGroupRoleData(const LLUUID& role_id, 
00135                                                                 LLRoleData role_data,
00136                                                                 const S32 member_count) :
00137         mRoleID(role_id),
00138         mRoleData(role_data),
00139         mMemberCount(member_count),
00140         mMembersNeedsSort(FALSE)
00141 {
00142 
00143 }
00144 
00145 LLGroupRoleData::~LLGroupRoleData()
00146 {       
00147 }
00148 
00149 S32 LLGroupRoleData::getMembersInRole(std::vector<LLUUID> members,
00150                                                                           BOOL needs_sort)
00151 {
00152         if (mRoleID.isNull())
00153         {
00154                 // This is the everyone role, just return the size of members, 
00155                 // because everyone is in the everyone role.
00156                 return members.size();
00157         }
00158 
00159         // Sort the members list, if needed.
00160         if (mMembersNeedsSort)
00161         {
00162                 std::sort(mMemberIDs.begin(), mMemberIDs.end());
00163                 mMembersNeedsSort = FALSE;
00164         }
00165         if (needs_sort)
00166         {
00167                 // Sort the members parameter.
00168                 std::sort(members.begin(), members.end());
00169         }
00170 
00171         // Return the number of members in the intersection.
00172         S32 max_size = llmin( members.size(), mMemberIDs.size() );
00173         std::vector<LLUUID> in_role( max_size );
00174         std::vector<LLUUID>::iterator in_role_end;
00175         in_role_end = std::set_intersection(mMemberIDs.begin(), mMemberIDs.end(),
00176                                                                         members.begin(), members.end(),
00177                                                                         in_role.begin());
00178         return in_role_end - in_role.begin();
00179 }
00180                           
00181 void LLGroupRoleData::addMember(const LLUUID& member)
00182 {
00183         mMembersNeedsSort = TRUE;
00184         mMemberIDs.push_back(member);
00185 }
00186 
00187 bool LLGroupRoleData::removeMember(const LLUUID& member)
00188 {
00189         std::vector<LLUUID>::iterator it = std::find(mMemberIDs.begin(),mMemberIDs.end(),member);
00190 
00191         if (it != mMemberIDs.end())
00192         {
00193                 mMembersNeedsSort = TRUE;
00194                 mMemberIDs.erase(it);
00195                 return true;
00196         }
00197 
00198         return false;
00199 }
00200 
00201 void LLGroupRoleData::clearMembers()
00202 {
00203         mMembersNeedsSort = FALSE;
00204         mMemberIDs.clear();
00205 }
00206 
00207 
00208 //
00209 // LLGroupMgrGroupData
00210 //
00211 
00212 LLGroupMgrGroupData::LLGroupMgrGroupData(const LLUUID& id) : 
00213         mID(id), 
00214         mShowInList(TRUE), 
00215         mOpenEnrollment(FALSE), 
00216         mMembershipFee(0),
00217         mAllowPublish(FALSE),
00218         mListInProfile(FALSE),
00219         mMaturePublish(FALSE),
00220         mChanged(FALSE),
00221         mMemberCount(0),
00222         mRoleCount(0),
00223         mReceivedRoleMemberPairs(0),
00224         mMemberDataComplete(FALSE),
00225         mRoleDataComplete(FALSE),
00226         mRoleMemberDataComplete(FALSE),
00227         mGroupPropertiesDataComplete(FALSE),
00228         mPendingRoleMemberRequest(FALSE)
00229 {
00230 }
00231 
00232 BOOL LLGroupMgrGroupData::getRoleData(const LLUUID& role_id, LLRoleData& role_data)
00233 {
00234         role_data_map_t::const_iterator it;
00235 
00236         // Do we have changes for it?
00237         it = mRoleChanges.find(role_id);
00238         if (it != mRoleChanges.end()) 
00239         {
00240                 if ((*it).second.mChangeType == RC_DELETE) return FALSE;
00241 
00242                 role_data = (*it).second;
00243                 return TRUE;
00244         }
00245 
00246         // Ok, no changes, hasn't been deleted, isn't a new role, just find the role.
00247         role_list_t::const_iterator rit = mRoles.find(role_id);
00248         if (rit != mRoles.end())
00249         {
00250                 role_data = (*rit).second->getRoleData();
00251                 return TRUE;
00252         }
00253 
00254         // This role must not exist.
00255         return FALSE;
00256 }
00257 
00258 
00259 void LLGroupMgrGroupData::setRoleData(const LLUUID& role_id, LLRoleData role_data)
00260 {
00261         // If this is a newly created group, we need to change the data in the created list.
00262         role_data_map_t::iterator it;
00263         it = mRoleChanges.find(role_id);
00264         if (it != mRoleChanges.end())
00265         {
00266                 if ((*it).second.mChangeType == RC_CREATE)
00267                 {
00268                         role_data.mChangeType = RC_CREATE;
00269                         mRoleChanges[role_id] = role_data;
00270                         return;
00271                 }
00272                 else if ((*it).second.mChangeType == RC_DELETE)
00273                 {
00274                         // Don't do anything for a role being deleted.
00275                         return;
00276                 }
00277         }
00278 
00279         // Not a new role, so put it in the changes list.
00280         LLRoleData old_role_data;
00281         role_list_t::iterator rit = mRoles.find(role_id);
00282         if (rit != mRoles.end())
00283         {
00284                 bool data_change = ( ((*rit).second->mRoleData.mRoleDescription != role_data.mRoleDescription)
00285                                                         || ((*rit).second->mRoleData.mRoleName != role_data.mRoleName)
00286                                                         || ((*rit).second->mRoleData.mRoleTitle != role_data.mRoleTitle) );
00287                 bool powers_change = ((*rit).second->mRoleData.mRolePowers != role_data.mRolePowers);
00288                 
00289                 if (!data_change && !powers_change)
00290                 {
00291                         // We are back to the original state, the changes have been 'undone' so take out the change.
00292                         mRoleChanges.erase(role_id);
00293                         return;
00294                 }
00295 
00296                 if (data_change && powers_change)
00297                 {
00298                         role_data.mChangeType = RC_UPDATE_ALL;
00299                 }
00300                 else if (data_change)
00301                 {
00302                         role_data.mChangeType = RC_UPDATE_DATA;
00303                 }
00304                 else
00305         {
00306                         role_data.mChangeType = RC_UPDATE_POWERS;
00307                 }
00308 
00309                 mRoleChanges[role_id] = role_data;
00310         }
00311         else
00312                 {
00313                 llwarns << "Change being made to non-existant role " << role_id << llendl;
00314         }
00315 }
00316 
00317 BOOL LLGroupMgrGroupData::pendingRoleChanges()
00318 {
00319         return (!mRoleChanges.empty());
00320 }
00321 
00322 // This is a no-op if the role has already been created.
00323 void LLGroupMgrGroupData::createRole(const LLUUID& role_id, LLRoleData role_data)
00324 {
00325         if (mRoleChanges.find(role_id) != mRoleChanges.end())
00326         {
00327                 llwarns << "create role for existing role! " << role_id << llendl;
00328         }
00329         else
00330         {
00331                 role_data.mChangeType = RC_CREATE;
00332                 mRoleChanges[role_id] = role_data;
00333         }
00334 }
00335 
00336 void LLGroupMgrGroupData::deleteRole(const LLUUID& role_id)
00337 {
00338         role_data_map_t::iterator it;
00339 
00340         // If this was a new role, just discard it.
00341         it = mRoleChanges.find(role_id);
00342         if (it != mRoleChanges.end() 
00343                 && (*it).second.mChangeType == RC_CREATE)
00344         {
00345                 mRoleChanges.erase(it);
00346                 return;
00347         }
00348 
00349         LLRoleData rd;
00350         rd.mChangeType = RC_DELETE;
00351         mRoleChanges[role_id] = rd;
00352 }
00353 
00354 void LLGroupMgrGroupData::addRolePower(const LLUUID &role_id, U64 power)
00355 {
00356         LLRoleData rd;
00357         if (getRoleData(role_id,rd))
00358         {       
00359                 rd.mRolePowers |= power;
00360                 setRoleData(role_id,rd);
00361         }
00362         else
00363         {
00364                 llwarns << "addRolePower: no role data found for " << role_id << llendl;
00365         }
00366 }
00367 
00368 void LLGroupMgrGroupData::removeRolePower(const LLUUID &role_id, U64 power)
00369 {
00370         LLRoleData rd;
00371         if (getRoleData(role_id,rd))
00372         {
00373                 rd.mRolePowers &= ~power;
00374                 setRoleData(role_id,rd);
00375         }
00376         else
00377         {
00378                 llwarns << "removeRolePower: no role data found for " << role_id << llendl;
00379         }
00380 }
00381 
00382 U64 LLGroupMgrGroupData::getRolePowers(const LLUUID& role_id)
00383 {
00384         LLRoleData rd;
00385         if (getRoleData(role_id,rd))
00386         {
00387                 return rd.mRolePowers;
00388         }
00389         else
00390         {
00391                 llwarns << "getRolePowers: no role data found for " << role_id << llendl;
00392                 return GP_NO_POWERS;
00393         }
00394 }
00395 
00396 void LLGroupMgrGroupData::removeData()
00397 {
00398         // Remove member data first, because removeRoleData will walk the member list
00399         removeMemberData();
00400         removeRoleData();
00401 }
00402 
00403 void LLGroupMgrGroupData::removeMemberData()
00404 {
00405         for (member_list_t::iterator mi = mMembers.begin(); mi != mMembers.end(); ++mi)
00406         {
00407                 delete mi->second;
00408         }
00409         mMembers.clear();
00410         mMemberDataComplete = FALSE;
00411 }
00412 
00413 void LLGroupMgrGroupData::removeRoleData()
00414 {
00415         for (member_list_t::iterator mi = mMembers.begin(); mi != mMembers.end(); ++mi)
00416         {
00417                 LLGroupMemberData* data = mi->second;
00418                 if (data)
00419                 {
00420                         data->clearRoles();
00421                 }
00422         }
00423 
00424         for (role_list_t::iterator ri = mRoles.begin(); ri != mRoles.end(); ++ri)
00425         {
00426                 LLGroupRoleData* data = ri->second;
00427                 delete data;
00428         }
00429         mRoles.clear();
00430         mReceivedRoleMemberPairs = 0;
00431         mRoleDataComplete = FALSE;
00432         mRoleMemberDataComplete = FALSE;
00433 }
00434 
00435 void LLGroupMgrGroupData::removeRoleMemberData()
00436 {
00437         for (member_list_t::iterator mi = mMembers.begin(); mi != mMembers.end(); ++mi)
00438         {
00439                 LLGroupMemberData* data = mi->second;
00440                 if (data)
00441                 {
00442                         data->clearRoles();
00443                 }
00444         }
00445 
00446         for (role_list_t::iterator ri = mRoles.begin(); ri != mRoles.end(); ++ri)
00447         {
00448                 LLGroupRoleData* data = ri->second;
00449                 if (data)
00450                 {
00451                         data->clearMembers();
00452                 }
00453         }
00454 
00455         mReceivedRoleMemberPairs = 0;
00456         mRoleMemberDataComplete = FALSE;
00457 }
00458 
00459 LLGroupMgrGroupData::~LLGroupMgrGroupData()
00460 {
00461         removeData();
00462 }
00463 
00464 bool LLGroupMgrGroupData::changeRoleMember(const LLUUID& role_id, 
00465                                                                                    const LLUUID& member_id, 
00466                                                                                    LLRoleMemberChangeType rmc)
00467 {
00468         role_list_t::iterator ri = mRoles.find(role_id);
00469         member_list_t::iterator mi = mMembers.find(member_id);
00470 
00471         if (ri == mRoles.end()
00472                 || mi == mMembers.end() )
00473         {
00474                 if (ri == mRoles.end()) llwarns << "LLGroupMgrGroupData::changeRoleMember couldn't find role " << role_id << llendl;
00475                 if (mi == mMembers.end()) llwarns << "LLGroupMgrGroupData::changeRoleMember couldn't find member " << member_id << llendl;
00476                 return false;
00477         }
00478 
00479         LLGroupRoleData* grd = ri->second;
00480         LLGroupMemberData* gmd = mi->second;
00481 
00482         if (!grd || !gmd)
00483         {
00484                 llwarns << "LLGroupMgrGroupData::changeRoleMember couldn't get member or role data." << llendl;
00485                 return false;
00486         }
00487 
00488         if (RMC_ADD == rmc)
00489         {
00490                 llinfos << " adding member to role." << llendl;
00491                 grd->addMember(member_id);
00492                 gmd->addRole(role_id,grd);
00493 
00494                 //TODO move this into addrole function
00495                 //see if they added someone to the owner role and update isOwner
00496                 gmd->mIsOwner = (role_id == mOwnerRole) ? TRUE : gmd->mIsOwner;
00497         }
00498         else if (RMC_REMOVE == rmc)
00499         {
00500                 llinfos << " removing member from role." << llendl;
00501                 grd->removeMember(member_id);
00502                 gmd->removeRole(role_id);
00503 
00504                 //see if they removed someone from the owner role and update isOwner
00505                 gmd->mIsOwner = (role_id == mOwnerRole) ? FALSE : gmd->mIsOwner;
00506         }
00507 
00508         lluuid_pair role_member;
00509         role_member.first = role_id;
00510         role_member.second = member_id;
00511 
00512         change_map_t::iterator it = mRoleMemberChanges.find(role_member);
00513         if (it != mRoleMemberChanges.end())
00514         {
00515                 // There was already a role change for this role_member
00516                 if (it->second.mChange == rmc)
00517                 {
00518                         // Already recorded this change?  Weird.
00519                         llinfos << "Received duplicate change for "
00520                                         << " role: " << role_id << " member " << member_id 
00521                                         << " change " << (rmc == RMC_ADD ? "ADD" : "REMOVE") << llendl;
00522                 }
00523                 else
00524                 {
00525                         // The only two operations (add and remove) currently cancel each other out
00526                         // If that changes this will need more logic
00527                         if (rmc == RMC_NONE)
00528                         {
00529                                 llwarns << "changeRoleMember: existing entry with 'RMC_NONE' change! This shouldn't happen." << llendl;
00530                                 LLRoleMemberChange rc(role_id,member_id,rmc);
00531                                 mRoleMemberChanges[role_member] = rc;
00532                         }
00533                         else
00534                         {
00535                                 mRoleMemberChanges.erase(it);
00536                         }
00537                 }
00538         }
00539         else
00540         {
00541                 LLRoleMemberChange rc(role_id,member_id,rmc);
00542                 mRoleMemberChanges[role_member] = rc;
00543         }
00544 
00545         recalcAgentPowers(member_id);
00546 
00547         mChanged = TRUE;
00548         return true;
00549 }
00550 
00551 void LLGroupMgrGroupData::recalcAllAgentPowers()
00552 {
00553         LLGroupMemberData* gmd;
00554 
00555         for (member_list_t::iterator mit = mMembers.begin();
00556                  mit != mMembers.end(); ++mit)
00557         {
00558                 gmd = mit->second;
00559                 if (!gmd) continue;
00560 
00561                 gmd->mAgentPowers = 0;
00562                 for (LLGroupMemberData::role_list_t::iterator it = gmd->mRolesList.begin();
00563                          it != gmd->mRolesList.end(); ++it)
00564                 {
00565                         LLGroupRoleData* grd = (*it).second;
00566                         if (!grd) continue;
00567 
00568                         gmd->mAgentPowers |= grd->mRoleData.mRolePowers;
00569                 }
00570         }
00571 }
00572 
00573 void LLGroupMgrGroupData::recalcAgentPowers(const LLUUID& agent_id)
00574 {
00575         member_list_t::iterator mi = mMembers.find(agent_id);
00576         if (mi == mMembers.end()) return;
00577 
00578         LLGroupMemberData* gmd = mi->second;
00579 
00580         if (!gmd) return;
00581 
00582         gmd->mAgentPowers = 0;
00583         for (LLGroupMemberData::role_list_t::iterator it = gmd->mRolesList.begin();
00584                  it != gmd->mRolesList.end(); ++it)
00585         {
00586                 LLGroupRoleData* grd = (*it).second;
00587                 if (!grd) continue;
00588 
00589                 gmd->mAgentPowers |= grd->mRoleData.mRolePowers;
00590         }
00591 }
00592 
00593 bool packRoleUpdateMessageBlock(LLMessageSystem* msg, 
00594                                                                 const LLUUID& group_id,
00595                                                                 const LLUUID& role_id, 
00596                                                                 const LLRoleData& role_data, 
00597                                                                 bool start_message)
00598 {
00599         if (start_message)
00600         {
00601                 msg->newMessage("GroupRoleUpdate");
00602                 msg->nextBlock("AgentData");
00603                 msg->addUUID("AgentID",gAgent.getID());
00604                 msg->addUUID("SessionID",gAgent.getSessionID());
00605                 msg->addUUID("GroupID",group_id);
00606                 start_message = false;
00607         }
00608 
00609         msg->nextBlock("RoleData");
00610         msg->addUUID("RoleID",role_id);
00611         msg->addString("Name", role_data.mRoleName);
00612         msg->addString("Description", role_data.mRoleDescription);
00613         msg->addString("Title", role_data.mRoleTitle);
00614         msg->addU64("Powers", role_data.mRolePowers);
00615         msg->addU8("UpdateType", (U8)role_data.mChangeType);
00616 
00617         if (msg->isSendFullFast())
00618         {
00619                 gAgent.sendReliableMessage();
00620                 start_message = true;
00621         }
00622 
00623         return start_message;
00624 }
00625 
00626 void LLGroupMgrGroupData::sendRoleChanges()
00627 {
00628         // Commit changes locally
00629         LLGroupRoleData* grd;
00630         role_list_t::iterator role_it;
00631         LLMessageSystem* msg = gMessageSystem;
00632         bool start_message = true;
00633 
00634         bool need_role_cleanup = false;
00635         bool need_role_data = false;
00636         bool need_power_recalc = false;
00637 
00638         // Apply all changes
00639         for (role_data_map_t::iterator iter = mRoleChanges.begin();
00640                  iter != mRoleChanges.end(); )
00641         {
00642                 role_data_map_t::iterator it = iter++; // safely incrament iter
00643                 const LLUUID& role_id = (*it).first;
00644                 const LLRoleData& role_data = (*it).second;
00645 
00646                 // Commit to local data set
00647                 role_it = mRoles.find((*it).first);
00648                 if ( (mRoles.end() == role_it 
00649                                 && RC_CREATE != role_data.mChangeType)
00650                         || (mRoles.end() != role_it
00651                                 && RC_CREATE == role_data.mChangeType))
00652                 {
00653                         continue;
00654                 }
00655         
00656                 // NOTE: role_it is valid EXCEPT for the RC_CREATE case
00657                 switch (role_data.mChangeType)
00658                 {
00659                         case RC_CREATE:
00660                         {
00661                                 // NOTE: role_it is NOT valid in this case
00662                                 grd = new LLGroupRoleData(role_id, role_data, 0);
00663                                 mRoles[role_id] = grd;
00664                                 need_role_data = true;
00665                                 break;
00666                         }
00667                         case RC_DELETE:
00668                         {
00669                                 LLGroupRoleData* group_role_data = (*role_it).second;
00670                                 delete group_role_data;
00671                                 mRoles.erase(role_it);
00672                                 need_role_cleanup = true;
00673                                 need_power_recalc = true;
00674                                 break;
00675                         }
00676                         case RC_UPDATE_ALL:
00677                         case RC_UPDATE_POWERS:
00678                                 need_power_recalc = true;
00679                         case RC_UPDATE_DATA:
00680                         default: 
00681                         {
00682                                 LLGroupRoleData* group_role_data = (*role_it).second;
00683                                 group_role_data->setRoleData(role_data); // NOTE! might modify mRoleChanges!
00684                                 break;
00685                         }
00686                 }
00687 
00688                 // Update dataserver
00689                 start_message = packRoleUpdateMessageBlock(msg,getID(),role_id,role_data,start_message);
00690         }
00691 
00692         if (!start_message)
00693         {
00694                 gAgent.sendReliableMessage();
00695         }
00696 
00697         // If we delete a role then all the role-member pairs are invalid!
00698         if (need_role_cleanup)
00699         {
00700                 removeRoleMemberData();
00701         }
00702 
00703         // If we create a new role, then we need to re-fetch all the role data.
00704         if (need_role_data)
00705         {
00706                 LLGroupMgr::getInstance()->sendGroupRoleDataRequest(getID());
00707         }
00708 
00709         // Clean up change lists        
00710         mRoleChanges.clear();
00711 
00712         // Recalculate all the agent powers because role powers have now changed.
00713         if (need_power_recalc)
00714         {
00715                 recalcAllAgentPowers();
00716         }
00717 }
00718 
00719 void LLGroupMgrGroupData::cancelRoleChanges()
00720 {
00721         // Clear out all changes!
00722         mRoleChanges.clear();
00723 }
00724 //
00725 // LLGroupMgr
00726 //
00727 
00728 LLGroupMgr::LLGroupMgr()
00729 {
00730 }
00731 
00732 LLGroupMgr::~LLGroupMgr()
00733 {
00734         clearGroups();
00735 }
00736 
00737 void LLGroupMgr::clearGroups()
00738 {
00739         std::for_each(mRoleActionSets.begin(), mRoleActionSets.end(), DeletePointer());
00740         mRoleActionSets.clear();
00741         std::for_each(mGroups.begin(), mGroups.end(), DeletePairedPointer());
00742         mGroups.clear();
00743         mObservers.clear();
00744 }
00745 
00746 void LLGroupMgr::clearGroupData(const LLUUID& group_id)
00747 {
00748         group_map_t::iterator iter = mGroups.find(group_id);
00749         if (iter != mGroups.end())
00750         {
00751                 delete (*iter).second;
00752                 mGroups.erase(iter);
00753         }
00754 }
00755 
00756 void LLGroupMgr::addObserver(LLGroupMgrObserver* observer) 
00757 { 
00758         mObservers.insert(std::pair<LLUUID, LLGroupMgrObserver*>(observer->getID(), observer));
00759 }
00760 
00761 void LLGroupMgr::removeObserver(LLGroupMgrObserver* observer)
00762 {
00763         if (!observer)
00764         {
00765                 return;
00766         }
00767         observer_multimap_t::iterator it;
00768         it = mObservers.find(observer->getID());
00769         while (it != mObservers.end())
00770         {
00771                 if (it->second == observer)
00772                 {
00773                         mObservers.erase(it);
00774                         break;
00775                 }
00776                 else
00777                 {
00778                         ++it;
00779                 }
00780         }
00781 }
00782 
00783 LLGroupMgrGroupData* LLGroupMgr::getGroupData(const LLUUID& id)
00784 {
00785         group_map_t::iterator gi = mGroups.find(id);
00786 
00787         if (gi != mGroups.end())
00788         {
00789                 return gi->second;
00790         }
00791         return NULL;
00792 }
00793 
00794 // static
00795 void LLGroupMgr::processGroupMembersReply(LLMessageSystem* msg, void** data)
00796 {
00797         lldebugs << "LLGroupMgr::processGroupMembersReply" << llendl;
00798         LLUUID agent_id;
00799         msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
00800         if (gAgent.getID() != agent_id)
00801         {
00802                 llwarns << "Got group properties reply for another agent!" << llendl;
00803                 return;
00804         }
00805 
00806         LLUUID group_id;
00807         msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group_id );
00808 
00809         LLUUID request_id;
00810         msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_RequestID, request_id);
00811 
00812         LLGroupMgrGroupData* group_datap = LLGroupMgr::getInstance()->createGroupData(group_id);
00813         if (group_datap->mMemberRequestID != request_id)
00814         {
00815                 llwarns << "processGroupMembersReply: Received incorrect (stale?) request id" << llendl;
00816                 return;
00817         }
00818 
00819         msg->getS32(_PREHASH_GroupData, "MemberCount", group_datap->mMemberCount );
00820 
00821         if (group_datap->mMemberCount > 0)
00822         {
00823                 S32 contribution = 0;
00824                 char online_status[DB_DATETIME_BUF_SIZE];               /* Flawfinder: ignore */
00825                 char title[DB_GROUP_TITLE_BUF_SIZE];            /* Flawfinder: ignore */
00826                 U64 agent_powers = 0;
00827                 BOOL is_owner = FALSE;
00828 
00829                 S32 num_members = msg->getNumberOfBlocksFast(_PREHASH_MemberData);
00830                 for (S32 i = 0; i < num_members; i++)
00831                 {
00832                         LLUUID member_id;
00833 
00834                         msg->getUUIDFast(_PREHASH_MemberData, _PREHASH_AgentID, member_id, i );
00835                         msg->getS32(_PREHASH_MemberData, _PREHASH_Contribution, contribution, i);
00836                         msg->getU64(_PREHASH_MemberData, "AgentPowers", agent_powers, i);
00837                         msg->getStringFast(_PREHASH_MemberData, _PREHASH_OnlineStatus, DB_DATETIME_BUF_SIZE, online_status, i);
00838                         msg->getString(_PREHASH_MemberData, "Title", DB_GROUP_TITLE_BUF_SIZE, title, i);
00839                         msg->getBOOL(_PREHASH_MemberData,"IsOwner",is_owner,i);
00840 
00841                         if (member_id.notNull())
00842                         {
00843                                 //llinfos << "Member " << member_id << " has powers " << std::hex << agent_powers << std::dec << llendl;
00844                                 LLGroupMemberData* newdata = new LLGroupMemberData(member_id, 
00845                                                                                                                                         contribution, 
00846                                                                                                                                         agent_powers, 
00847                                                                                                                                         std::string(title),
00848                                                                                                                                         std::string(online_status),
00849                                                                                                                                         is_owner);
00850 #if LL_DEBUG
00851                                 LLGroupMgrGroupData::member_list_t::iterator mit = group_datap->mMembers.find(member_id);
00852                                 if (mit != group_datap->mMembers.end())
00853                                 {
00854                                         llinfos << " *** Received duplicate member data for agent " << member_id << llendl;
00855                                 }
00856 #endif
00857                                 group_datap->mMembers[member_id] = newdata;
00858                         }
00859                         else
00860                         {
00861                                 llinfos << "Received null group member data." << llendl;
00862                         }
00863                 }
00864 
00865                 //if group members are loaded while titles are missing, load the titles.
00866                 if(group_datap->mTitles.size() < 1)
00867                 {
00868                         LLGroupMgr::getInstance()->sendGroupTitlesRequest(group_id);
00869                 }
00870         }
00871 
00872         if (group_datap->mMembers.size() ==  (U32)group_datap->mMemberCount)
00873         {
00874                 group_datap->mMemberDataComplete = TRUE;
00875                 group_datap->mMemberRequestID.setNull();
00876                 // We don't want to make role-member data requests until we have all the members
00877                 if (group_datap->mPendingRoleMemberRequest)
00878                 {
00879                         group_datap->mPendingRoleMemberRequest = FALSE;
00880                         LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(group_datap->mID);
00881                 }
00882         }
00883 
00884         group_datap->mChanged = TRUE;
00885         LLGroupMgr::getInstance()->notifyObservers(GC_MEMBER_DATA);
00886 }
00887 
00888 //static 
00889 void LLGroupMgr::processGroupPropertiesReply(LLMessageSystem* msg, void** data)
00890 {
00891         lldebugs << "LLGroupMgr::processGroupPropertiesReply" << llendl;
00892         LLUUID agent_id;
00893         msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
00894         if (gAgent.getID() != agent_id)
00895         {
00896                 llwarns << "Got group properties reply for another agent!" << llendl;
00897                 return;
00898         }
00899 
00900         LLUUID group_id;
00901         char    name[DB_GROUP_NAME_BUF_SIZE];           /* Flawfinder: ignore */
00902         char    charter[DB_GROUP_CHARTER_BUF_SIZE];             /* Flawfinder: ignore */
00903         BOOL    show_in_list = FALSE;
00904         LLUUID  founder_id;
00905         U64             powers_mask = GP_NO_POWERS;
00906         S32             money = 0;
00907         char    member_title[DB_GROUP_TITLE_BUF_SIZE];          /* Flawfinder: ignore */
00908         LLUUID  insignia_id;
00909         LLUUID  owner_role;
00910         U32             membership_fee = 0;
00911         BOOL    open_enrollment = FALSE;
00912         S32             num_group_members = 0;
00913         S32             num_group_roles = 0;
00914         BOOL    allow_publish = FALSE;
00915         BOOL    mature = FALSE;
00916 
00917         msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group_id );
00918         msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_FounderID,                founder_id);    
00919         msg->getStringFast(_PREHASH_GroupData, _PREHASH_Name,                   DB_GROUP_NAME_BUF_SIZE, name );
00920         msg->getStringFast(_PREHASH_GroupData, _PREHASH_Charter,                        DB_GROUP_CHARTER_BUF_SIZE, charter );
00921         msg->getBOOLFast(_PREHASH_GroupData, _PREHASH_ShowInList,               show_in_list );
00922         msg->getStringFast(_PREHASH_GroupData, _PREHASH_MemberTitle, DB_GROUP_TITLE_BUF_SIZE, member_title );
00923         msg->getUUIDFast(_PREHASH_GroupData,    _PREHASH_InsigniaID,                    insignia_id );
00924         msg->getU64Fast(_PREHASH_GroupData,             _PREHASH_PowersMask,                    powers_mask );
00925         msg->getU32Fast(_PREHASH_GroupData,             _PREHASH_MembershipFee,                 membership_fee );
00926         msg->getBOOLFast(_PREHASH_GroupData,    _PREHASH_OpenEnrollment,                open_enrollment );
00927         msg->getS32Fast(_PREHASH_GroupData,             _PREHASH_GroupMembershipCount,  num_group_members);
00928         msg->getS32(_PREHASH_GroupData,         "GroupRolesCount",              num_group_roles);
00929         msg->getS32Fast(_PREHASH_GroupData,             _PREHASH_Money,                                 money);
00930         msg->getBOOL("GroupData", "AllowPublish", allow_publish);
00931         msg->getBOOL("GroupData", "MaturePublish", mature);
00932         msg->getUUID(_PREHASH_GroupData, "OwnerRole", owner_role);
00933 
00934         LLGroupMgrGroupData* group_datap = LLGroupMgr::getInstance()->createGroupData(group_id);
00935 
00936         group_datap->mName = name;
00937         group_datap->mCharter = charter;
00938         group_datap->mShowInList = show_in_list;
00939         group_datap->mInsigniaID = insignia_id;
00940         group_datap->mFounderID = founder_id;
00941         group_datap->mMembershipFee = membership_fee;
00942         group_datap->mOpenEnrollment = open_enrollment;
00943         group_datap->mAllowPublish = allow_publish;
00944         group_datap->mMaturePublish = mature;
00945         group_datap->mOwnerRole = owner_role;
00946         group_datap->mMemberCount = num_group_members;
00947         group_datap->mRoleCount = num_group_roles + 1; // Add the everyone role.
00948         
00949         group_datap->mGroupPropertiesDataComplete = TRUE;
00950         group_datap->mChanged = TRUE;
00951 
00952         LLGroupMgr::getInstance()->notifyObservers(GC_PROPERTIES);
00953 }
00954 
00955 // static
00956 void LLGroupMgr::processGroupRoleDataReply(LLMessageSystem* msg, void** data)
00957 {
00958         lldebugs << "LLGroupMgr::processGroupRoleDataReply" << llendl;
00959         LLUUID agent_id;
00960         msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
00961         if (gAgent.getID() != agent_id)
00962         {
00963                 llwarns << "Got group properties reply for another agent!" << llendl;
00964                 return;
00965         }
00966 
00967         LLUUID group_id;
00968         msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group_id );
00969 
00970         LLUUID request_id;
00971         msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_RequestID, request_id);
00972 
00973         LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->createGroupData(group_id);
00974         if (group_data->mRoleDataRequestID != request_id)
00975         {
00976                 llwarns << "processGroupRoleDataReply: Received incorrect (stale?) request id" << llendl;
00977                 return;
00978         }
00979 
00980         msg->getS32(_PREHASH_GroupData, "RoleCount", group_data->mRoleCount );
00981 
00982         char    name[DB_GROUP_NAME_BUF_SIZE];           /* Flawfinder: ignore */
00983         char    title[DB_GROUP_TITLE_BUF_SIZE];         /* Flawfinder: ignore */
00984         char    desc[DB_GROUP_CHARTER_BUF_SIZE];                /* Flawfinder: ignore */
00985         U64             powers = 0;
00986         U32             member_count = 0;
00987         LLUUID role_id;
00988 
00989         U32 num_blocks = msg->getNumberOfBlocks("RoleData");
00990         U32 i = 0;
00991         for (i=0; i< num_blocks; ++i)
00992         {
00993                 msg->getUUID("RoleData", "RoleID", role_id, i );
00994                 
00995                 msg->getString("RoleData","Name",DB_GROUP_NAME_BUF_SIZE,name,i);
00996                 msg->getString("RoleData","Title",DB_GROUP_TITLE_BUF_SIZE,title,i);
00997                 msg->getString("RoleData","Description",DB_GROUP_CHARTER_BUF_SIZE,desc,i);
00998                 msg->getU64("RoleData","Powers",powers,i);
00999                 msg->getU32("RoleData","Members",member_count,i);
01000 
01001                 lldebugs << "Adding role data: " << name << " {" << role_id << "}" << llendl;
01002                 LLGroupRoleData* rd = new LLGroupRoleData(role_id,name,title,desc,powers,member_count);
01003                 group_data->mRoles[role_id] = rd;
01004         }
01005 
01006         if (group_data->mRoles.size() == (U32)group_data->mRoleCount)
01007         {
01008                 group_data->mRoleDataComplete = TRUE;
01009                 group_data->mRoleDataRequestID.setNull();
01010                 // We don't want to make role-member data requests until we have all the role data
01011                 if (group_data->mPendingRoleMemberRequest)
01012                 {
01013                         group_data->mPendingRoleMemberRequest = FALSE;
01014                         LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(group_data->mID);
01015                 }
01016         }
01017 
01018         group_data->mChanged = TRUE;
01019         LLGroupMgr::getInstance()->notifyObservers(GC_ROLE_DATA);
01020 }
01021 
01022 // static
01023 void LLGroupMgr::processGroupRoleMembersReply(LLMessageSystem* msg, void** data)
01024 {
01025         lldebugs << "LLGroupMgr::processGroupRoleMembersReply" << llendl;
01026         LLUUID agent_id;
01027         msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
01028         if (gAgent.getID() != agent_id)
01029         {
01030                 llwarns << "Got group properties reply for another agent!" << llendl;
01031                 return;
01032         }
01033 
01034         LLUUID request_id;
01035         msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_RequestID, request_id);
01036 
01037         LLUUID group_id;
01038         msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_GroupID, group_id );
01039 
01040         U32 total_pairs;
01041         msg->getU32(_PREHASH_AgentData, "TotalPairs", total_pairs);
01042 
01043         LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->createGroupData(group_id);
01044 
01045         if (group_data->mRoleMembersRequestID != request_id)
01046         {
01047                 llwarns << "processGroupRoleMembersReply: Received incorrect (stale?) role member request id" << llendl;
01048                 return;
01049         }
01050 
01051         U32 num_blocks = msg->getNumberOfBlocks("MemberData");
01052         U32 i;
01053         LLUUID member_id;
01054         LLUUID role_id;
01055         LLGroupRoleData* rd = NULL;
01056         LLGroupMemberData* md = NULL;
01057 
01058         LLGroupMgrGroupData::role_list_t::iterator ri;
01059         LLGroupMgrGroupData::member_list_t::iterator mi;
01060 
01061         // If total_pairs == 0, there are no members in any custom roles.
01062         if (total_pairs > 0)
01063         {
01064                 for (i = 0;i < num_blocks; ++i)
01065                 {
01066                         msg->getUUID("MemberData","RoleID",role_id,i);
01067                         msg->getUUID("MemberData","MemberID",member_id,i);
01068 
01069                         if (role_id.notNull() && member_id.notNull() )
01070                         {
01071                                 rd = NULL;
01072                                 ri = group_data->mRoles.find(role_id);
01073                                 if (ri != group_data->mRoles.end())
01074                                 {
01075                                         rd = ri->second;
01076                                 }
01077 
01078                                 md = NULL;
01079                                 mi = group_data->mMembers.find(member_id);
01080                                 if (mi != group_data->mMembers.end())
01081                                 {
01082                                         md = mi->second;
01083                                 }
01084 
01085                                 if (rd && md)
01086                                 {
01087                                         lldebugs << "Adding role-member pair: " << role_id << ", " << member_id << llendl;
01088                                         rd->addMember(member_id);
01089                                         md->addRole(role_id,rd);
01090                                 }
01091                                 else
01092                                 {
01093                                         if (!rd) llwarns << "Received role data for unkown role " << role_id << " in group " << group_id << llendl;
01094                                         if (!md) llwarns << "Received role data for unkown member " << member_id << " in group " << group_id << llendl;
01095                                 }
01096                         }
01097                 }
01098 
01099                 group_data->mReceivedRoleMemberPairs += num_blocks;
01100         }
01101 
01102         if (group_data->mReceivedRoleMemberPairs == total_pairs)
01103         {
01104                 // Add role data for the 'everyone' role to all members
01105                 LLGroupRoleData* everyone = group_data->mRoles[LLUUID::null];
01106                 if (!everyone)
01107                 {
01108                         llwarns << "Everyone role not found!" << llendl;
01109                 }
01110                 else
01111                 {
01112                         for (LLGroupMgrGroupData::member_list_t::iterator mi = group_data->mMembers.begin();
01113                                  mi != group_data->mMembers.end(); ++mi)
01114                         {
01115                                 LLGroupMemberData* data = mi->second;
01116                                 if (data)
01117                                 {
01118                                         data->addRole(LLUUID::null,everyone);
01119                                 }
01120                         }
01121                 }
01122                 
01123         group_data->mRoleMemberDataComplete = TRUE;
01124                 group_data->mRoleMembersRequestID.setNull();
01125         }
01126 
01127         group_data->mChanged = TRUE;
01128         LLGroupMgr::getInstance()->notifyObservers(GC_ROLE_MEMBER_DATA);
01129 }
01130 
01131 // static
01132 void LLGroupMgr::processGroupTitlesReply(LLMessageSystem* msg, void** data)
01133 {
01134         lldebugs << "LLGroupMgr::processGroupTitlesReply" << llendl;
01135         LLUUID agent_id;
01136         msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
01137         if (gAgent.getID() != agent_id)
01138         {
01139                 llwarns << "Got group properties reply for another agent!" << llendl;
01140                 return;
01141         }
01142 
01143         LLUUID group_id;
01144         msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_GroupID, group_id );
01145 
01146         LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->createGroupData(group_id);
01147 
01148         LLUUID request_id;
01149         msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_RequestID, request_id);
01150 
01151         if (group_data->mTitlesRequestID != request_id)
01152         {
01153                 llwarns << "processGroupTitlesReply: Received incorrect (stale?) title request id" << llendl;
01154                 return;
01155         }
01156 
01157         char title_buf[DB_GROUP_TITLE_BUF_SIZE];                /* Flawfinder: ignore */
01158 
01159         LLGroupTitle title;
01160 
01161         S32 i = 0;
01162         S32 blocks = msg->getNumberOfBlocksFast(_PREHASH_GroupData);
01163         for (i=0; i<blocks; ++i)
01164         {
01165                 msg->getString("GroupData","Title",DB_GROUP_TITLE_BUF_SIZE,title_buf,i);
01166                 title.mTitle = title_buf;
01167                 msg->getUUID("GroupData","RoleID",title.mRoleID,i);
01168                 msg->getBOOL("GroupData","Selected",title.mSelected,i);
01169 
01170                 if (title_buf[0] != '\0')
01171                 {
01172                         lldebugs << "LLGroupMgr adding title: " << title.mTitle << ", " << title.mRoleID << ", " << (title.mSelected ? 'Y' : 'N') << llendl;
01173                         group_data->mTitles.push_back(title);
01174                 }
01175         }
01176 
01177         group_data->mChanged = TRUE;
01178         LLGroupMgr::getInstance()->notifyObservers(GC_TITLES);
01179 }
01180 
01181 // static
01182 void LLGroupMgr::processEjectGroupMemberReply(LLMessageSystem* msg, void ** data)
01183 {
01184         lldebugs << "processEjectGroupMemberReply" << llendl;
01185         LLUUID group_id;
01186         msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group_id);
01187         BOOL success;
01188         msg->getBOOLFast(_PREHASH_EjectData, _PREHASH_Success, success);
01189 
01190         // If we had a failure, the group panel needs to be updated.
01191         if (!success)
01192         {
01193                 LLFloaterGroupInfo::refreshGroup(group_id);
01194         }
01195 }
01196 
01197 // static
01198 void LLGroupMgr::processJoinGroupReply(LLMessageSystem* msg, void ** data)
01199 {
01200         lldebugs << "processJoinGroupReply" << llendl;
01201         LLUUID group_id;
01202         BOOL success;
01203         msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group_id);
01204         msg->getBOOLFast(_PREHASH_GroupData, _PREHASH_Success, success);
01205 
01206         if (success)
01207         {
01208                 // refresh all group information
01209                 gAgent.sendAgentDataUpdateRequest();
01210 
01211                 LLGroupMgr::getInstance()->clearGroupData(group_id);
01212                 // refresh the floater for this group, if any.
01213                 LLFloaterGroupInfo::refreshGroup(group_id);
01214                 // refresh the group panel of the search window, if necessary.
01215                 LLFloaterDirectory::refreshGroup(group_id);
01216         }
01217 }
01218 
01219 // static
01220 void LLGroupMgr::processLeaveGroupReply(LLMessageSystem* msg, void ** data)
01221 {
01222         lldebugs << "processLeaveGroupReply" << llendl;
01223         LLUUID group_id;
01224         BOOL success;
01225         msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group_id);
01226         msg->getBOOLFast(_PREHASH_GroupData, _PREHASH_Success, success);
01227 
01228         if (success)
01229         {
01230                 // refresh all group information
01231                 gAgent.sendAgentDataUpdateRequest();
01232 
01233                 LLGroupMgr::getInstance()->clearGroupData(group_id);
01234                 // close the floater for this group, if any.
01235                 LLFloaterGroupInfo::closeGroup(group_id);
01236                 // refresh the group panel of the search window, if necessary.
01237                 LLFloaterDirectory::refreshGroup(group_id);
01238         }
01239 }
01240 
01241 // static
01242 void LLGroupMgr::processCreateGroupReply(LLMessageSystem* msg, void ** data)
01243 {
01244         LLUUID group_id;
01245         BOOL success;
01246         char message[MAX_STRING];               /* Flawfinder: ignore */
01247 
01248         msg->getUUIDFast(_PREHASH_ReplyData, _PREHASH_GroupID, group_id );
01249 
01250         msg->getBOOLFast(_PREHASH_ReplyData, _PREHASH_Success,  success );
01251         msg->getStringFast(_PREHASH_ReplyData, _PREHASH_Message, MAX_STRING, message );
01252 
01253         if (success)
01254         {
01255                 // refresh all group information
01256                 gAgent.sendAgentDataUpdateRequest();
01257 
01258                 // HACK! We haven't gotten the agent group update yet, so ... um ... fake it.
01259                 // This is so when we go to modify the group we will be able to do so.
01260                 // This isn't actually too bad because real data will come down in 2 or 3 miliseconds and replace this.
01261                 LLGroupData gd;
01262                 gd.mAcceptNotices = TRUE;
01263                 gd.mListInProfile = TRUE;
01264                 gd.mContribution = 0;
01265                 gd.mID = group_id;
01266                 gd.mName = "new group";
01267                 gd.mPowers = GP_ALL_POWERS;
01268 
01269                 gAgent.mGroups.push_back(gd);
01270 
01271                 LLFloaterGroupInfo::closeCreateGroup();
01272                 LLFloaterGroupInfo::showFromUUID(group_id,"roles_tab");
01273         }
01274         else
01275         {
01276                 // *TODO:translate
01277                 LLString::format_map_t args;
01278                 args["[MESSAGE]"] = message;
01279                 gViewerWindow->alertXml("UnableToCreateGroup", args);
01280         }
01281 }
01282 
01283 LLGroupMgrGroupData* LLGroupMgr::createGroupData(const LLUUID& id)
01284 {
01285         LLGroupMgrGroupData* group_datap;
01286 
01287         group_map_t::iterator existing_group = LLGroupMgr::getInstance()->mGroups.find(id);
01288         if (existing_group == LLGroupMgr::getInstance()->mGroups.end())
01289         {
01290                 group_datap = new LLGroupMgrGroupData(id);
01291                 LLGroupMgr::getInstance()->addGroup(group_datap);
01292         }
01293         else
01294         {
01295                 group_datap = existing_group->second;
01296         }
01297 
01298         return group_datap;
01299 }
01300 
01301 void LLGroupMgr::notifyObservers(LLGroupChange gc)
01302 {
01303         for (group_map_t::iterator gi = mGroups.begin(); gi != mGroups.end(); ++gi)
01304         {
01305                 if (gi->second->mChanged)
01306                 {
01307                         // find all observers for this group id
01308                         observer_multimap_t::iterator oi = mObservers.find(gi->first);
01309                         for (; oi != mObservers.end(); ++oi)
01310                         {
01311                                 oi->second->changed(gc);
01312                         }
01313                         gi->second->mChanged = FALSE;
01314                 }
01315         }
01316 }
01317 
01318 void LLGroupMgr::addGroup(LLGroupMgrGroupData* group_datap)
01319 {
01320         if (mGroups.size() > MAX_CACHED_GROUPS)
01321         {
01322                 // get rid of groups that aren't observed
01323                 for (group_map_t::iterator gi = mGroups.begin(); gi != mGroups.end() && mGroups.size() > MAX_CACHED_GROUPS / 2; )
01324                 {
01325                         observer_multimap_t::iterator oi = mObservers.find(gi->first);
01326                         if (oi == mObservers.end())
01327                         {
01328                                 // not observed
01329                                 LLGroupMgrGroupData* unobserved_groupp = gi->second;
01330                                 delete unobserved_groupp;
01331                                 mGroups.erase(gi++);
01332                         }
01333                         else
01334                         {
01335                                 ++gi;
01336                         }
01337                 }
01338         }
01339         mGroups[group_datap->getID()] = group_datap;
01340 }
01341 
01342 
01343 void LLGroupMgr::sendGroupPropertiesRequest(const LLUUID& group_id)
01344 {
01345         lldebugs << "LLGroupMgr::sendGroupPropertiesRequest" << llendl;
01346         // This will happen when we get the reply
01347         //LLGroupMgrGroupData* group_datap = createGroupData(group_id);
01348         
01349         LLMessageSystem* msg = gMessageSystem;
01350         msg->newMessage("GroupProfileRequest");
01351         msg->nextBlock("AgentData");
01352         msg->addUUID("AgentID",gAgent.getID());
01353         msg->addUUID("SessionID",gAgent.getSessionID());
01354         msg->nextBlock("GroupData");
01355         msg->addUUID("GroupID",group_id);
01356         gAgent.sendReliableMessage();
01357 }
01358 
01359 void LLGroupMgr::sendGroupMembersRequest(const LLUUID& group_id)
01360 {
01361         lldebugs << "LLGroupMgr::sendGroupMembersRequest" << llendl;
01362         LLGroupMgrGroupData* group_datap = createGroupData(group_id);
01363         if (group_datap->mMemberRequestID.isNull())
01364         {
01365                 group_datap->removeMemberData();
01366                 group_datap->mMemberRequestID.generate();
01367 
01368                 LLMessageSystem* msg = gMessageSystem;
01369                 msg->newMessage("GroupMembersRequest");
01370                 msg->nextBlock("AgentData");
01371                 msg->addUUID("AgentID",gAgent.getID());
01372                 msg->addUUID("SessionID",gAgent.getSessionID());
01373                 msg->nextBlock("GroupData");
01374                 msg->addUUID("GroupID",group_id);
01375                 msg->addUUID("RequestID",group_datap->mMemberRequestID);
01376                 gAgent.sendReliableMessage();
01377         }
01378 }
01379 
01380 void LLGroupMgr::sendGroupRoleDataRequest(const LLUUID& group_id)
01381 {
01382         lldebugs << "LLGroupMgr::sendGroupRoleDataRequest" << llendl;
01383         LLGroupMgrGroupData* group_datap = createGroupData(group_id);
01384         if (group_datap->mRoleDataRequestID.isNull())
01385         {
01386                 group_datap->removeRoleData();
01387                 group_datap->mRoleDataRequestID.generate();
01388 
01389                 LLMessageSystem* msg = gMessageSystem;
01390                 msg->newMessage("GroupRoleDataRequest");
01391                 msg->nextBlock("AgentData");
01392                 msg->addUUID("AgentID",gAgent.getID());
01393                 msg->addUUID("SessionID",gAgent.getSessionID());
01394                 msg->nextBlock("GroupData");
01395                 msg->addUUID("GroupID",group_id);
01396                 msg->addUUID("RequestID",group_datap->mRoleDataRequestID);
01397                 gAgent.sendReliableMessage();
01398         }
01399 }
01400 
01401 void LLGroupMgr::sendGroupRoleMembersRequest(const LLUUID& group_id)
01402 {
01403         lldebugs << "LLGroupMgr::sendGroupRoleMembersRequest" << llendl;
01404         LLGroupMgrGroupData* group_datap = createGroupData(group_id);
01405         
01406         if (group_datap->mRoleMembersRequestID.isNull())
01407         {
01408                 // Don't send the request if we don't have all the member or role data
01409                 if (!group_datap->isMemberDataComplete()
01410                         || !group_datap->isRoleDataComplete())
01411                 {
01412                         // *TODO: KLW FIXME: Should we start a member or role data request?
01413                         llinfos << " Pending: " << (group_datap->mPendingRoleMemberRequest ? "Y" : "N")
01414                                 << " MemberDataComplete: " << (group_datap->mMemberDataComplete ? "Y" : "N")
01415                                 << " RoleDataComplete: " << (group_datap->mRoleDataComplete ? "Y" : "N") << llendl;
01416                         group_datap->mPendingRoleMemberRequest = TRUE;
01417                         return;
01418                 }
01419 
01420                 group_datap->removeRoleMemberData();
01421                 group_datap->mRoleMembersRequestID.generate();
01422 
01423                 LLMessageSystem* msg = gMessageSystem;
01424                 msg->newMessage("GroupRoleMembersRequest");
01425                 msg->nextBlock("AgentData");
01426                 msg->addUUID("AgentID",gAgent.getID());
01427                 msg->addUUID("SessionID",gAgent.getSessionID());
01428                 msg->nextBlock("GroupData");
01429                 msg->addUUID("GroupID",group_id);
01430                 msg->addUUID("RequestID",group_datap->mRoleMembersRequestID);
01431                 gAgent.sendReliableMessage();
01432         }
01433 }
01434 
01435 void LLGroupMgr::sendGroupTitlesRequest(const LLUUID& group_id)
01436 {
01437         lldebugs << "LLGroupMgr::sendGroupTitlesRequest" << llendl;
01438         LLGroupMgrGroupData* group_datap = createGroupData(group_id);
01439         
01440         group_datap->mTitles.clear();
01441         group_datap->mTitlesRequestID.generate();
01442 
01443         LLMessageSystem* msg = gMessageSystem;
01444         msg->newMessage("GroupTitlesRequest");
01445         msg->nextBlock("AgentData");
01446         msg->addUUID("AgentID",gAgent.getID());
01447         msg->addUUID("SessionID",gAgent.getSessionID());
01448         msg->addUUID("GroupID",group_id);
01449         msg->addUUID("RequestID",group_datap->mTitlesRequestID);
01450 
01451         gAgent.sendReliableMessage();
01452 }
01453 
01454 void LLGroupMgr::sendGroupTitleUpdate(const LLUUID& group_id, const LLUUID& title_role_id)
01455 {
01456         lldebugs << "LLGroupMgr::sendGroupTitleUpdate" << llendl;
01457 
01458         LLMessageSystem* msg = gMessageSystem;
01459         msg->newMessage("GroupTitleUpdate");
01460         msg->nextBlock("AgentData");
01461         msg->addUUID("AgentID",gAgent.getID());
01462         msg->addUUID("SessionID",gAgent.getSessionID());
01463         msg->addUUID("GroupID",group_id);
01464         msg->addUUID("TitleRoleID",title_role_id);
01465 
01466         gAgent.sendReliableMessage();
01467 
01468         // Save the change locally
01469         LLGroupMgrGroupData* group_datap = createGroupData(group_id);
01470         for (std::vector<LLGroupTitle>::iterator iter = group_datap->mTitles.begin();
01471                  iter != group_datap->mTitles.end(); ++iter)
01472         {
01473                 if (iter->mRoleID == title_role_id)
01474                 {
01475                         iter->mSelected = TRUE;
01476                 }
01477                 else if (iter->mSelected)
01478                 {
01479                         iter->mSelected = FALSE;
01480                 }
01481         }
01482 }
01483 
01484 // static
01485 void LLGroupMgr::sendCreateGroupRequest(const std::string& name,
01486                                                                                 const std::string& charter,
01487                                                                                 U8 show_in_list,
01488                                                                                 const LLUUID& insignia,
01489                                                                                 S32 membership_fee,
01490                                                                                 BOOL open_enrollment,
01491                                                                                 BOOL allow_publish,
01492                                                                                 BOOL mature_publish)
01493 {
01494         LLMessageSystem* msg = gMessageSystem;
01495         msg->newMessage("CreateGroupRequest");
01496         msg->nextBlock("AgentData");
01497         msg->addUUID("AgentID",gAgent.getID());
01498         msg->addUUID("SessionID",gAgent.getSessionID());
01499 
01500         msg->nextBlock("GroupData");
01501         msg->addString("Name",name);
01502         msg->addString("Charter",charter);
01503         msg->addBOOL("ShowInList",show_in_list);
01504         msg->addUUID("InsigniaID",insignia);
01505         msg->addS32("MembershipFee",membership_fee);
01506         msg->addBOOL("OpenEnrollment",open_enrollment);
01507         msg->addBOOL("AllowPublish",allow_publish);
01508         msg->addBOOL("MaturePublish",mature_publish);
01509 
01510         gAgent.sendReliableMessage();
01511 }
01512 
01513 void LLGroupMgr::sendUpdateGroupInfo(const LLUUID& group_id)
01514 {
01515         lldebugs << "LLGroupMgr::sendUpdateGroupInfo" << llendl;
01516         LLGroupMgrGroupData* group_datap = createGroupData(group_id);
01517 
01518         LLMessageSystem* msg = gMessageSystem;
01519 
01520         msg->newMessageFast(_PREHASH_UpdateGroupInfo);
01521         msg->nextBlockFast(_PREHASH_AgentData);
01522         msg->addUUIDFast(_PREHASH_AgentID,gAgent.getID());
01523         msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID());
01524 
01525         msg->nextBlockFast(_PREHASH_GroupData);
01526         msg->addUUIDFast(_PREHASH_GroupID,group_datap->getID());
01527         msg->addStringFast(_PREHASH_Charter,group_datap->mCharter);
01528         msg->addBOOLFast(_PREHASH_ShowInList,group_datap->mShowInList);
01529         msg->addUUIDFast(_PREHASH_InsigniaID,group_datap->mInsigniaID);
01530         msg->addS32Fast(_PREHASH_MembershipFee,group_datap->mMembershipFee);
01531         msg->addBOOLFast(_PREHASH_OpenEnrollment,group_datap->mOpenEnrollment);
01532         msg->addBOOLFast(_PREHASH_AllowPublish,group_datap->mAllowPublish);
01533         msg->addBOOLFast(_PREHASH_MaturePublish,group_datap->mMaturePublish);
01534 
01535         gAgent.sendReliableMessage();
01536 
01537         // Not expecting a response, so let anyone else watching know the data has changed.
01538         group_datap->mChanged = TRUE;
01539         notifyObservers(GC_PROPERTIES);
01540 }
01541 
01542 void LLGroupMgr::sendGroupRoleMemberChanges(const LLUUID& group_id)
01543 {
01544         lldebugs << "LLGroupMgr::sendGroupRoleMemberChanges" << llendl;
01545         LLGroupMgrGroupData* group_datap = createGroupData(group_id);
01546 
01547         if (group_datap->mRoleMemberChanges.empty()) return;
01548 
01549         LLMessageSystem* msg = gMessageSystem;
01550 
01551         bool start_message = true;
01552         for (LLGroupMgrGroupData::change_map_t::const_iterator citer = group_datap->mRoleMemberChanges.begin();
01553                  citer != group_datap->mRoleMemberChanges.end(); ++citer)
01554         {
01555                 if (start_message)
01556                 {
01557                         msg->newMessage("GroupRoleChanges");
01558                         msg->nextBlockFast(_PREHASH_AgentData);
01559                         msg->addUUIDFast(_PREHASH_AgentID,gAgent.getID());
01560                         msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID());
01561                         msg->addUUIDFast(_PREHASH_GroupID,group_id);
01562                         start_message = false;
01563                 }
01564                 msg->nextBlock("RoleChange");
01565                 msg->addUUID("RoleID",citer->second.mRole);
01566                 msg->addUUID("MemberID",citer->second.mMember);
01567                 msg->addU32("Change",(U32)citer->second.mChange);
01568 
01569                 if (msg->isSendFullFast())
01570                 {
01571                         gAgent.sendReliableMessage();
01572                         start_message = true;
01573                 }
01574         }
01575 
01576         if (!start_message)
01577         {
01578                 gAgent.sendReliableMessage();
01579         }
01580 
01581         group_datap->mRoleMemberChanges.clear();
01582 
01583         // Not expecting a response, so let anyone else watching know the data has changed.
01584         group_datap->mChanged = TRUE;
01585         notifyObservers(GC_ROLE_MEMBER_DATA);
01586 }
01587 
01588 //static
01589 void LLGroupMgr::sendGroupMemberJoin(const LLUUID& group_id)
01590 {
01591         LLMessageSystem *msg = gMessageSystem;
01592 
01593         msg->newMessageFast(_PREHASH_JoinGroupRequest);
01594         msg->nextBlockFast(_PREHASH_AgentData);
01595         msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
01596         msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
01597         msg->nextBlockFast(_PREHASH_GroupData);
01598         msg->addUUIDFast(_PREHASH_GroupID, group_id);
01599 
01600         gAgent.sendReliableMessage();
01601 }
01602 
01603 // member_role_pairs is <member_id,role_id>
01604 // static
01605 void LLGroupMgr::sendGroupMemberInvites(const LLUUID& group_id, std::map<LLUUID,LLUUID>& member_role_pairs)
01606 {
01607         bool start_message = true;
01608         LLMessageSystem* msg = gMessageSystem;
01609 
01610         for (std::map<LLUUID,LLUUID>::iterator it = member_role_pairs.begin();
01611                  it != member_role_pairs.end(); ++it)
01612         {
01613                 if (start_message)
01614                 {
01615                         msg->newMessage("InviteGroupRequest");
01616                         msg->nextBlock("AgentData");
01617                         msg->addUUID("AgentID",gAgent.getID());
01618                         msg->addUUID("SessionID",gAgent.getSessionID());
01619                         msg->nextBlock("GroupData");
01620                         msg->addUUID("GroupID",group_id);
01621                         start_message = false;
01622                 }
01623 
01624                 msg->nextBlock("InviteData");
01625                 msg->addUUID("InviteeID",(*it).first);
01626                 msg->addUUID("RoleID",(*it).second);
01627 
01628                 if (msg->isSendFull())
01629                 {
01630                         gAgent.sendReliableMessage();
01631                         start_message = true;
01632                 }
01633         }
01634 
01635         if (!start_message)
01636         {
01637                 gAgent.sendReliableMessage();
01638         }
01639 }
01640 
01641 //static
01642 void LLGroupMgr::sendGroupMemberEjects(const LLUUID& group_id,
01643                                                                            std::vector<LLUUID>& member_ids)
01644 {
01645         bool start_message = true;
01646         LLMessageSystem* msg = gMessageSystem;
01647 
01648         LLGroupMgrGroupData* group_datap = LLGroupMgr::getInstance()->getGroupData(group_id);
01649         if (!group_datap) return;
01650 
01651         for (std::vector<LLUUID>::iterator it = member_ids.begin();
01652                  it != member_ids.end(); ++it)
01653         {
01654                 // Can't use 'eject' to leave a group.
01655                 if ((*it) == gAgent.getID()) continue;
01656 
01657                 // Make sure they are in the group, and we need the member data
01658                 LLGroupMgrGroupData::member_list_t::iterator mit = group_datap->mMembers.find(*it);
01659                 if (mit != group_datap->mMembers.end())
01660                 {
01661                         // Add them to the message
01662                         if (start_message)
01663                         {
01664                                 msg->newMessage("EjectGroupMemberRequest");
01665                                 msg->nextBlock("AgentData");
01666                                 msg->addUUID("AgentID",gAgent.getID());
01667                                 msg->addUUID("SessionID",gAgent.getSessionID());
01668                                 msg->nextBlock("GroupData");
01669                                 msg->addUUID("GroupID",group_id);
01670                                 start_message = false;
01671                         }
01672                         
01673                         msg->nextBlock("EjectData");
01674                         msg->addUUID("EjecteeID",(*it));
01675 
01676                         if (msg->isSendFull())
01677                         {
01678                                 gAgent.sendReliableMessage();
01679                                 start_message = true;
01680                         }
01681 
01682                         // Clean up groupmgr
01683                         for (LLGroupMemberData::role_list_t::iterator rit = (*mit).second->roleBegin();
01684                                  rit != (*mit).second->roleEnd(); ++rit)
01685                         {
01686                                 if ((*rit).first.notNull())
01687                                 {
01688                                         (*rit).second->removeMember(*it);
01689                                 }
01690                         }
01691                         delete (*mit).second;
01692                         group_datap->mMembers.erase(*it);
01693                 }
01694         }
01695 
01696         if (!start_message)
01697         {
01698                 gAgent.sendReliableMessage();
01699         }
01700 }
01701 
01702 void LLGroupMgr::sendGroupRoleChanges(const LLUUID& group_id)
01703 {
01704         lldebugs << "LLGroupMgr::sendGroupRoleChanges" << llendl;
01705         LLGroupMgrGroupData* group_datap = getGroupData(group_id);
01706 
01707         if (group_datap && group_datap->pendingRoleChanges())
01708         {
01709                 group_datap->sendRoleChanges();
01710         
01711                 // Not expecting a response, so let anyone else watching know the data has changed.
01712                 group_datap->mChanged = TRUE;
01713                 notifyObservers(GC_ROLE_DATA);
01714         }
01715 }
01716 
01717 void LLGroupMgr::cancelGroupRoleChanges(const LLUUID& group_id)
01718 {
01719         lldebugs << "LLGroupMgr::cancelGroupRoleChanges" << llendl;
01720         LLGroupMgrGroupData* group_datap = getGroupData(group_id);
01721 
01722         if (group_datap) group_datap->cancelRoleChanges();
01723 }
01724 
01725 //static
01726 bool LLGroupMgr::parseRoleActions(const LLString& xml_filename)
01727 {
01728         LLXMLNodePtr root;
01729 
01730         BOOL success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root);  
01731         
01732         if (!success || !root || !root->hasName( "role_actions" ))
01733         {
01734                 llerrs << "Problem reading UI role_actions file: " << xml_filename << llendl;
01735                 return false;
01736         }
01737 
01738         LLXMLNodeList role_list;
01739 
01740         root->getChildren("action_set", role_list, false);
01741         
01742         for (LLXMLNodeList::iterator role_iter = role_list.begin(); role_iter != role_list.end(); ++role_iter)
01743         {
01744                 LLXMLNodePtr action_set = role_iter->second;
01745 
01746                 LLRoleActionSet* role_action_set = new LLRoleActionSet();
01747                 LLRoleAction* role_action_data = new LLRoleAction();
01748                 
01749                 // name=
01750                 LLString action_set_name;
01751                 if (action_set->getAttributeString("name", action_set_name))
01752                 {
01753                         lldebugs << "Loading action set " << action_set_name << llendl;
01754                         role_action_data->mName = action_set_name;
01755                 }
01756                 else
01757                 {
01758                         llwarns << "Unable to parse action set with no name" << llendl;
01759                         delete role_action_set;
01760                         delete role_action_data;
01761                         continue;
01762                 }
01763                 // description=
01764                 LLString set_description;
01765                 if (action_set->getAttributeString("description", set_description))
01766                 {
01767                         role_action_data->mDescription = set_description;
01768                 }
01769                 // long description=
01770                 LLString set_longdescription;
01771                 if (action_set->getAttributeString("longdescription", set_longdescription))
01772                 {
01773                         role_action_data->mLongDescription = set_longdescription;
01774                 }
01775 
01776                 // power mask=
01777                 U64 set_power_mask = 0;
01778 
01779                 LLXMLNodeList action_list;
01780                 LLXMLNodeList::iterator action_iter;
01781 
01782                 action_set->getChildren("action", action_list, false);
01783 
01784                 for (action_iter = action_list.begin(); action_iter != action_list.end(); ++action_iter)
01785                 {
01786                         LLXMLNodePtr action = action_iter->second;
01787 
01788                         LLRoleAction* role_action = new LLRoleAction();
01789 
01790                         // name=
01791                         LLString action_name;
01792                         if (action->getAttributeString("name", action_name))
01793                         {
01794                                 lldebugs << "Loading action " << action_name << llendl;
01795                                 role_action->mName = action_name;
01796                         }
01797                         else
01798                         {
01799                                 llwarns << "Unable to parse action with no name" << llendl;
01800                                 delete role_action;
01801                                 continue;
01802                         }
01803                         // description=
01804                         LLString description;
01805                         if (action->getAttributeString("description", description))
01806                         {
01807                                 role_action->mDescription = description;
01808                         }
01809                         // long description=
01810                         LLString longdescription;
01811                         if (action->getAttributeString("longdescription", longdescription))
01812                         {
01813                                 role_action->mLongDescription = longdescription;
01814                         }
01815                         // description=
01816                         S32 power_bit = 0;
01817                         if (action->getAttributeS32("value", power_bit))
01818                         {
01819                                 if (0 <= power_bit && power_bit < 64)
01820                                 {
01821                                         role_action->mPowerBit = 0x1LL << power_bit;
01822                                 }
01823                         }
01824 
01825                         set_power_mask |= role_action->mPowerBit;
01826         
01827                         role_action_set->mActions.push_back(role_action);
01828                 }
01829 
01830                 role_action_data->mPowerBit = set_power_mask;
01831                 role_action_set->mActionSetData = role_action_data;
01832 
01833                 LLGroupMgr::getInstance()->mRoleActionSets.push_back(role_action_set);
01834         }
01835         return true;
01836 }
01837 
01838 // static
01839 void LLGroupMgr::debugClearAllGroups(void*)
01840 {
01841         LLGroupMgr::getInstance()->clearGroups();
01842         LLGroupMgr::parseRoleActions("role_actions.xml");
01843 }
01844 
01845 

Generated on Fri May 16 08:33:38 2008 for SecondLife by  doxygen 1.5.5