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

Generated on Thu Jul 1 06:08:41 2010 for Second Life Viewer by  doxygen 1.4.7