package com.sissi.ucenter.relation.muc.impl; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import com.mongodb.AggregationOutput; import com.mongodb.BasicDBObject; import com.mongodb.BasicDBObjectBuilder; import com.mongodb.DBObject; import com.mongodb.MongoException; import com.mongodb.WriteConcern; import com.sissi.config.Dictionary; import com.sissi.config.MongoConfig; import com.sissi.config.impl.MongoUtils; import com.sissi.context.JID; import com.sissi.context.JIDBuilder; import com.sissi.context.JIDs; import com.sissi.context.impl.OfflineJID; import com.sissi.context.impl.ShareJIDs; import com.sissi.protocol.muc.ItemAffiliation; import com.sissi.protocol.muc.ItemRole; import com.sissi.ucenter.relation.Relation; import com.sissi.ucenter.relation.impl.DefaultRelation; import com.sissi.ucenter.relation.muc.MucRelation; import com.sissi.ucenter.relation.muc.MucRelationContext; import com.sissi.ucenter.relation.muc.MucRelationMapping; import com.sissi.ucenter.vcard.VCardContext; /** * 索引策略1: {"affiliations.affiliation":1}</p> 索引策略2: {"jid":1}</p>索引策略3: {"jid":1,"role.path":1}</p>索引策略4: {"affiliations.jid":1}</p>索引策略5: {"jid":1,"affiliations.jid":1}</p>索引策略6: {"roles.jid":1,"roles.resource":1}</p>索引策略7: {"roles.jid":1}</p>索引策略8: {"roles.nick":1} * * @author kim 2014年4月25日 */ abstract class MongoMucRelationContext implements MucRelationContext, MucRelationMapping { /** * {"$sort":{"affiliation":-1}} */ private final DBObject sort = BasicDBObjectBuilder.start("$sort", BasicDBObjectBuilder.start(Dictionary.FIELD_AFFILIATION, -1).get()).get(); /** * {"$match":{"affiliation":{"$exists":true}}} */ private final DBObject match = BasicDBObjectBuilder.start("$match", BasicDBObjectBuilder.start(Dictionary.FIELD_AFFILIATION, BasicDBObjectBuilder.start("$exists", true).get()).get()).get(); /** * {"$project":{"roles":"$roles"}} */ private final DBObject projectRoles = BasicDBObjectBuilder.start("$project", BasicDBObjectBuilder.start(Dictionary.FIELD_ROLES, "$" + Dictionary.FIELD_ROLES).get()).get(); /** * {"$group":{"_id":"$roles.jid","resource":{"$push":"$roles.resource"}}} */ private final DBObject groupMapping = BasicDBObjectBuilder.start("$group", BasicDBObjectBuilder.start().add(Dictionary.FIELD_ID, "$" + Dictionary.FIELD_ROLES + "." + Dictionary.FIELD_JID).add(Dictionary.FIELD_RESOURCE, BasicDBObjectBuilder.start("$push", "$" + Dictionary.FIELD_ROLES + "." + Dictionary.FIELD_RESOURCE).get()).get()).get(); /** * {"$group":{"_id":{"jid":"$jid","creator":"$creator","activate":"$activate","affiliations":"$affiliations"},"roles":{"$addToSet":"$roles"}}} */ private final DBObject groupRelations = BasicDBObjectBuilder.start("$group", BasicDBObjectBuilder.start().add(Dictionary.FIELD_ID, BasicDBObjectBuilder.start().add(Dictionary.FIELD_JID, "$" + Dictionary.FIELD_JID).add(Dictionary.FIELD_CREATOR, "$" + Dictionary.FIELD_CREATOR).add(Dictionary.FIELD_ACTIVATE, "$" + Dictionary.FIELD_ACTIVATE).add(Dictionary.FIELD_AFFILIATIONS, "$" + Dictionary.FIELD_AFFILIATIONS).get()).add(Dictionary.FIELD_ROLES, BasicDBObjectBuilder.start("$addToSet", "$" + Dictionary.FIELD_ROLES).get()).get()).get(); /** * {"$group":{"_id":"$_id","roles":{"$addToSet":"$roles"}}} */ private final DBObject groupSubscribe = BasicDBObjectBuilder.start("$group", BasicDBObjectBuilder.start().add(Dictionary.FIELD_ID, "$" + Dictionary.FIELD_ID).add(Dictionary.FIELD_ROLES, BasicDBObjectBuilder.start("$addToSet", "$" + Dictionary.FIELD_ROLES).get()).get()).get(); /** * {"$project":{"jid":"$_id.jid","creator":"$_id.creator","activate":"$_id.activate","affiliations":"$_id.affiliations","roles":"$roles"}} */ private final DBObject projectRelations = BasicDBObjectBuilder.start("$project", BasicDBObjectBuilder.start().add(Dictionary.FIELD_JID, "$" + Dictionary.FIELD_ID + "." + Dictionary.FIELD_JID).add(Dictionary.FIELD_CREATOR, "$" + Dictionary.FIELD_ID + "." + Dictionary.FIELD_CREATOR).add(Dictionary.FIELD_ACTIVATE, "$" + Dictionary.FIELD_ID + "." + Dictionary.FIELD_ACTIVATE).add(Dictionary.FIELD_AFFILIATIONS, "$" + Dictionary.FIELD_ID + "." + Dictionary.FIELD_AFFILIATIONS).add(Dictionary.FIELD_ROLES, "$" + Dictionary.FIELD_ROLES).get()).get(); /** * {"$project":{"jid":"$jid","activate":"$activate","creator":"$creator","roles":"$roles","affiliation":{"$cond":[{"$eq":["$affiliations.jid","$roles.jid"]},"$affiliations.affiliation",null]}}} */ private final DBObject projectRelation = BasicDBObjectBuilder.start().add("$project", BasicDBObjectBuilder.start().add(Dictionary.FIELD_JID, "$" + Dictionary.FIELD_JID).add(Dictionary.FIELD_ACTIVATE, "$" + Dictionary.FIELD_ACTIVATE).add(Dictionary.FIELD_CREATOR, "$" + Dictionary.FIELD_CREATOR).add(Dictionary.FIELD_ROLES, "$" + Dictionary.FIELD_ROLES).add(Dictionary.FIELD_AFFILIATION, BasicDBObjectBuilder.start().add("$cond", new Object[] { BasicDBObjectBuilder.start("$eq", new String[] { "$" + Dictionary.FIELD_AFFILIATIONS + "." + Dictionary.FIELD_JID, "$" + Dictionary.FIELD_ROLES + "." + Dictionary.FIELD_JID }).get(), "$" + Dictionary.FIELD_AFFILIATIONS + "." + Dictionary.FIELD_AFFILIATION, null }).get()).get()).get(); /** * {"$project":{"affiliation":"$affiliations.affiliation"}} */ private final DBObject projectAffiliations = BasicDBObjectBuilder.start("$project", BasicDBObjectBuilder.start(Dictionary.FIELD_AFFILIATION, "$" + Dictionary.FIELD_AFFILIATIONS + "." + Dictionary.FIELD_AFFILIATION).get()).get(); /** * {"configs.maxusers":1} */ private final DBObject countIncMaxUsers = BasicDBObjectBuilder.start(Dictionary.FIELD_CONFIGS + "." + Dictionary.FIELD_MAXUSERS, 1).get(); /** * {"configs.maxusers":-1} */ private final DBObject countDecMaxUsers = BasicDBObjectBuilder.start(Dictionary.FIELD_CONFIGS + "." + Dictionary.FIELD_MAXUSERS, -1).get(); private final JIDs jids = new EmptyJIDs(); private final Set<JID> jidset = new HashSet<JID>(); protected final Set<Relation> relations = new HashSet<Relation>(); protected final Map<String, Object> plus = Collections.unmodifiableMap(new HashMap<String, Object>()); /** * {"$limit":1} */ protected final DBObject limit = BasicDBObjectBuilder.start("$limit", 1).get(); /** * {"$unwind":"$roles"} */ protected final DBObject unwindRoles = BasicDBObjectBuilder.start().add("$unwind", "$" + Dictionary.FIELD_ROLES).get(); /** * {"$unwind":"$affiliations"} */ protected final DBObject unwindAffiliation = BasicDBObjectBuilder.start().add("$unwind", "$" + Dictionary.FIELD_AFFILIATIONS).get(); private final int[] mapping; private final VCardContext vcardContext; protected final MongoConfig config; protected final JIDBuilder jidBuilder; public MongoMucRelationContext(String mapping, MongoConfig config, JIDBuilder jidBuilder, VCardContext vcardContext) throws Exception { super(); this.config = config; this.jidBuilder = jidBuilder; this.vcardContext = vcardContext; String[] mappings = mapping.split(","); this.mapping = new int[mappings.length]; for (int index = 0; index < mappings.length; index++) { this.mapping[index] = Integer.valueOf(mappings[index]); } } /** * {"jid":jid} * * @param jid * @return */ protected DBObject buildQuery(String jid) { return BasicDBObjectBuilder.start().add(Dictionary.FIELD_JID, jid).get(); } /** * {"$match":{"jid":group.bare}} * * @param group * @return */ protected DBObject buildMatcher(JID group) { return BasicDBObjectBuilder.start().add("$match", BasicDBObjectBuilder.start(Dictionary.FIELD_JID, group.asStringWithBare()).get()).get(); } /** * 如果岗位 = NONE, 则同时删除Affiliations.jid, Informaitons.jid * * @param from * @param to * @param bare * @return */ protected MongoMucRelationContext remove(JID from, JID to, boolean bare) { // {"roles":bare == true ? jid:from.bare : path:from} DBObject remove = BasicDBObjectBuilder.start(Dictionary.FIELD_ROLES, bare ? BasicDBObjectBuilder.start(Dictionary.FIELD_JID, from.asStringWithBare()).get() : BasicDBObjectBuilder.start(Dictionary.FIELD_PATH, from.asString()).get()).get(); if (ItemAffiliation.NONE.equals(this.ourRelation(from, to).cast(MucRelation.class).affiliation())) { // {"affiliations.jid":from.bare} // {"informaitons.jid":from.bare} remove.put(Dictionary.FIELD_AFFILIATIONS, BasicDBObjectBuilder.start(Dictionary.FIELD_JID, from.asStringWithBare()).get()); remove.put(Dictionary.FIELD_INFORMATIONS, BasicDBObjectBuilder.start(Dictionary.FIELD_JID, from.asStringWithBare()).get()); } // {"jid":to.bare,"role.path":from}, {"$inc":{"configs.maxusers":-1}, "$pull":...remove...} this.config.collection().update(BasicDBObjectBuilder.start().add(Dictionary.FIELD_JID, to.asStringWithBare()).add(Dictionary.FIELD_ROLES + "." + Dictionary.FIELD_PATH, from.asString()).get(), BasicDBObjectBuilder.start().add("$inc", this.countDecMaxUsers).add("$pull", remove).get(), false, false, WriteConcern.SAFE); return this; } private ItemAffiliation affiliation(JID from, JID to) { return this.affiliation(from, to, ItemAffiliation.NONE); } /** * 获取岗位 * * @param from * @param to * @param def 默认值 * @return */ private ItemAffiliation affiliation(JID from, JID to, ItemAffiliation def) { // {"$match":{"jid":to.bare}},{"$unwind":"$affiliations"},{"$match":{"affiliations.jid":from.bare}},{"$project":{"affiliation":"$affiliations.affiliation"}} AggregationOutput output = this.config.collection().aggregate(BasicDBObjectBuilder.start("$match", BasicDBObjectBuilder.start(Dictionary.FIELD_JID, to.asStringWithBare()).get()).get(), this.unwindAffiliation, BasicDBObjectBuilder.start("$match", BasicDBObjectBuilder.start(Dictionary.FIELD_AFFILIATIONS + "." + Dictionary.FIELD_JID, from.asStringWithBare()).get()).get(), this.projectAffiliations); @SuppressWarnings("deprecation") List<?> result = MongoUtils.asList(output.getCommandResult(), Dictionary.FIELD_RESULT); return result.isEmpty() ? def : ItemAffiliation.parse(MongoUtils.asString(DBObject.class.cast(result.get(0)), Dictionary.FIELD_AFFILIATION).toString()); } /* * 1, 假设已为房客尝试$更新角色昵称和岗位昵称</p>2, 如果已存在岗位则更新岗位昵称并AddToSet角色</p>3, 如果不存在岗位则AddToSet岗位和角色并SetOnInsert房间基本信息 * * @see com.sissi.ucenter.relation.RelationContext#establish(com.sissi.context.JID, com.sissi.ucenter.relation.Relation) */ @Override public MongoMucRelationContext establish(JID from, Relation relation) { try { // {"jid":relation.jid,"roles.path":from.asString}, {"$set":{"roles.nick":relation.name}} if (MongoUtils.success(this.config.collection().update(BasicDBObjectBuilder.start(this.buildQuery(relation.jid()).toMap()).add(Dictionary.FIELD_ROLES + "." + Dictionary.FIELD_PATH, from.asString()).get(), BasicDBObjectBuilder.start("$set", BasicDBObjectBuilder.start().add(Dictionary.FIELD_ROLES + ".$." + Dictionary.FIELD_NICK, relation.name()).get()).get(), true, false, WriteConcern.SAFE))) { // The positional $ operator cannot be used for queries which traverse more than one array // https://jira.mongodb.org/browse/SERVER-13509 // {"jid":relation.jid,"affiliations.jid":from.bare}, {"$set":{"affiliations.nick":relation.name}} this.config.collection().update(BasicDBObjectBuilder.start(this.buildQuery(relation.jid()).toMap()).add(Dictionary.FIELD_AFFILIATIONS + "." + Dictionary.FIELD_JID, from.asStringWithBare()).get(), BasicDBObjectBuilder.start("$set", BasicDBObjectBuilder.start().add(Dictionary.FIELD_AFFILIATIONS + ".$." + Dictionary.FIELD_NICK, relation.name()).get()).get()); } } catch (MongoException e) { String role = ItemRole.toString(this.mapping[this.vcardContext.exists(this.jidBuilder.build(relation.jid())) ? ItemAffiliation.parse(relation.cast(MucRelation.class).affiliation()).ordinal() : ItemAffiliation.OWNER.ordinal()]); // 如果已存在岗位(新增用户) if (this.affiliation(from, this.jidBuilder.build(relation.jid()), null) != null) { DBObject query = this.buildQuery(relation.jid()); query.put(Dictionary.FIELD_AFFILIATIONS + "." + Dictionary.FIELD_JID, from.asStringWithBare()); // {"jid":jid,"affiliations.jid":from.bare}, {"$inc":{"configs.maxusers":1},"$set":{"affiliations.nick":relation.name,"$addToSet":{"roles":全部属性}} this.config.collection().update(query, BasicDBObjectBuilder.start().add("$inc", this.countIncMaxUsers).add("$set", BasicDBObjectBuilder.start(Dictionary.FIELD_AFFILIATIONS + ".$." + Dictionary.FIELD_NICK, relation.name()).get()).add("$addToSet", BasicDBObjectBuilder.start().add(Dictionary.FIELD_ROLES, BasicDBObjectBuilder.start().add(Dictionary.FIELD_JID, from.asStringWithBare()).add(Dictionary.FIELD_PATH, from.asString()).add(Dictionary.FIELD_RESOURCE, from.resource()).add(Dictionary.FIELD_NICK, relation.name()).add(Dictionary.FIELD_ROLE, role).add(Dictionary.FIELD_ACTIVATE, System.currentTimeMillis()).get()).get()).get(), true, false, WriteConcern.SAFE); } else { // {"jid":jid}, {"$setOnInsert", {...plus...,"configs.activate":true,"creator":from.bare,"$inc":{"configs.maxusers":1},"$addToSet":{"affiliations":...全部属性...,"roles":...全部属性...} this.config.collection().update(this.buildQuery(relation.jid()), BasicDBObjectBuilder.start().add("$setOnInsert", BasicDBObjectBuilder.start(relation.plus()).add(Dictionary.FIELD_CONFIGS + "." + Dictionary.FIELD_ACTIVATE, false).add(Dictionary.FIELD_CREATOR, from.asStringWithBare()).get()).add("$inc", this.countIncMaxUsers).add("$addToSet", BasicDBObjectBuilder.start().add(Dictionary.FIELD_AFFILIATIONS, BasicDBObjectBuilder.start().add(Dictionary.FIELD_JID, from.asStringWithBare()).add(Dictionary.FIELD_AFFILIATION, relation.cast(MucRelation.class).affiliation()).add(Dictionary.FIELD_NICK, relation.name()).get()).add(Dictionary.FIELD_ROLES, BasicDBObjectBuilder.start().add(Dictionary.FIELD_JID, from.asStringWithBare()).add(Dictionary.FIELD_PATH, from.asString()).add(Dictionary.FIELD_RESOURCE, from.resource()).add(Dictionary.FIELD_NICK, relation.name()).add(Dictionary.FIELD_ROLE, role).add(Dictionary.FIELD_ACTIVATE, System.currentTimeMillis()).get()).get()).get(), true, false, WriteConcern.SAFE); } } return this; } /* * 如果岗位 = NONE, 则同时删除Affiliations.jid, Informaitons.jid * * @see com.sissi.ucenter.relation.RelationContext#remove(com.sissi.context.JID, com.sissi.context.JID) */ @Override public MongoMucRelationContext remove(JID from, JID to) { return this.remove(from, to, false); } /* * {"$match":{"jid":group.bare}}, {"$unwind":"$roles"}, {"$unwind":"$affiliations"}, {"$match":{"roles.jid":Xxx,"roles.resource":Xxx}}, {"$project":{"jid":"$jid","activate":"$activate","creator":"$creator","roles":"$roles","affiliation":{"$cond":[{"$eq":["$affiliations.jid","$roles.jid"]},"$affiliations.affiliation",null]}}}, {"$match":{"affiliation":{"$exists":true}}}, {"$limit":1} * * @see com.sissi.ucenter.relation.RelationContext#ourRelation(com.sissi.context.JID, com.sissi.context.JID) */ @Override public Relation ourRelation(JID from, JID to) { AggregationOutput output = this.config.collection().aggregate(this.buildMatcher(to), this.unwindRoles, this.unwindAffiliation, BasicDBObjectBuilder.start().add("$match", BasicDBObjectBuilder.start().add(Dictionary.FIELD_ROLES + "." + Dictionary.FIELD_JID, from.asStringWithBare()).add(Dictionary.FIELD_ROLES + "." + Dictionary.FIELD_RESOURCE, from.resource()).get()).get(), this.projectRelation, this.match, this.sort, this.limit); @SuppressWarnings("deprecation") List<?> result = MongoUtils.asList(output.getCommandResult(), Dictionary.FIELD_RESULT); return result.isEmpty() ? new NoneRelation(from, to, this.affiliation(from, to)) : new MongoRelation(DBObject.class.cast(result.get(0))); } /* * {"$match":{"jid":group.bare}}, {"$unwind":"$roles"}, {"$match":{"roles.jid":Xxx}}, {"$group":{"_id":{"jid":"$jid","creator":"$creator","activate":"$activate","affiliations":"$affiliations"},"roles":{"$addToSet":"$roles"}}}, {"$project":{"jid":"$_id.jid","creator":"$_id.creator","activate":"$_id.activate","affiliations":"$_id.affiliations","roles":"$roles"}} * * @see com.sissi.ucenter.relation.muc.MucRelationContext#ourRelations(com.sissi.context.JID, com.sissi.context.JID) */ public Set<Relation> ourRelations(JID from, JID to) { AggregationOutput output = this.config.collection().aggregate(this.buildMatcher(to), this.unwindRoles, BasicDBObjectBuilder.start().add("$match", BasicDBObjectBuilder.start().add(Dictionary.FIELD_ROLES + "." + Dictionary.FIELD_JID, from.asStringWithBare()).get()).get(), this.groupRelations, this.projectRelations); @SuppressWarnings("deprecation") List<?> result = MongoUtils.asList(output.getCommandResult(), Dictionary.FIELD_RESULT); return result.isEmpty() ? this.relations : new MongoRelations(DBObject.class.cast(result.get(0))); } /* * {"jid":jid} * * @see com.sissi.ucenter.relation.RelationContext#myRelations(com.sissi.context.JID) */ @Override public Set<Relation> myRelations(JID from) { return new MongoRelations(this.config.collection().findOne(this.buildQuery(from.asStringWithBare()))); } /* * {"$match":{"jid":group.bare}}, {"$project":{"roles":"$roles"}}, {"$unwind":"$roles"}, {"$group":{"_id":"$_id","roles":{"$addToSet":"$roles"}}} * * @see com.sissi.ucenter.relation.RelationContext#whoSubscribedMe(com.sissi.context.JID) */ @Override public Set<JID> whoSubscribedMe(JID from) { AggregationOutput output = this.config.collection().aggregate(this.buildMatcher(from), this.projectRoles, this.unwindRoles, this.groupSubscribe); @SuppressWarnings("deprecation") List<?> result = MongoUtils.asList(output.getCommandResult(), Dictionary.FIELD_RESULT); return result.isEmpty() ? this.jidset : new JIDGroup(MongoUtils.asList(DBObject.class.cast(result.get(0)), Dictionary.FIELD_ROLES)); } @Override public JIDs mapping(JID group) { // {"$match":{"jid":group.bare}}, {"$unwind":"$roles"}, {"$match":{"roles.nick":Xxx}}, {"$project":{"roles":"$roles"}}, {"$group":{"_id":"$roles.jid","resource":{"$push":"$roles.resource"}}} AggregationOutput output = this.config.collection().aggregate(this.buildMatcher(group), this.unwindRoles, BasicDBObjectBuilder.start().add("$match", BasicDBObjectBuilder.start(Dictionary.FIELD_ROLES + "." + Dictionary.FIELD_NICK, group.resource()).get()).get(), this.projectRoles, this.groupMapping); @SuppressWarnings("deprecation") List<?> result = MongoUtils.asList(output.getCommandResult(), Dictionary.FIELD_RESULT); return result.isEmpty() ? this.jids : this.extract(DBObject.class.cast(result.get(0))); } private JIDs extract(DBObject db) { return new ShareJIDs(this.jidBuilder.build(MongoUtils.asString(db, Dictionary.FIELD_ID)), MongoUtils.asStrings(db, Dictionary.FIELD_RESOURCE)); } /** * 不存在订阅关系 * * @author kim 2014年4月25日 */ protected class NoneRelation extends DefaultRelation { private final static String zero = "0"; protected NoneRelation(JID jid, ItemAffiliation affiliation) { this(jid, OfflineJID.OFFLINE, affiliation); } /** * 1, 岗位 = None则房间存在性校验 2, 房间不存在岗位 = Owner 3, 房间存在岗位 = Affiliation * * @param jid * @param group * @param affiliation */ protected NoneRelation(JID jid, JID group, ItemAffiliation affiliation) { super(jid, zero); super.affiliation(ItemAffiliation.NONE.equals(affiliation) ? MongoMucRelationContext.this.vcardContext.exists(group) ? affiliation.toString() : ItemAffiliation.OWNER.toString() : affiliation.toString()); } /* * 当前角色和映射角色取最大值 * * @see com.sissi.ucenter.relation.impl.DefaultRelation#role() */ public String role() { return ItemRole.max(ItemRole.toString(MongoMucRelationContext.this.mapping[ItemAffiliation.parse(this.affiliation()).ordinal()]), super.role()); } } private class EmptyJIDs implements JIDs { public JID jid() { return OfflineJID.OFFLINE; } @Override public boolean isEmpty() { return true; } @Override public boolean lessThan(Integer counter) { return false; } @Override public Iterator<JID> iterator() { return new EmptyIterator(); } public boolean same(JID jid) { return false; } @Override public boolean like(JID jid) { return false; } private class EmptyIterator implements Iterator<JID> { @Override public boolean hasNext() { return false; } @Override public JID next() { return null; } @Override public void remove() { } } } protected class JIDGroup extends HashSet<JID> { private final static long serialVersionUID = 1L; protected JIDGroup(List<?> db) { if (db == null) { return; } for (Object each : db) { DBObject jid = DBObject.class.cast(each); super.add(MongoMucRelationContext.this.jidBuilder.build(MongoUtils.asString(jid, Dictionary.FIELD_JID)).resource(MongoUtils.asString(jid, Dictionary.FIELD_RESOURCE))); } } } protected class MongoRelations extends HashSet<Relation> { private final static long serialVersionUID = 1L; private final Map<String, String> affiliations = new HashMap<String, String>(); protected MongoRelations(DBObject db) { if (db == null) { return; } this.prepareAffiliations(db).prepareRelations(db); } /** * 拆分JID-岗位 * * @param db * @return */ private MongoRelations prepareAffiliations(DBObject db) { List<?> affiliations = MongoUtils.asList(db, Dictionary.FIELD_AFFILIATIONS); for (Object each : affiliations) { DBObject affiliation = DBObject.class.cast(each); this.affiliations.put(MongoUtils.asString(affiliation, Dictionary.FIELD_JID), MongoUtils.asString(affiliation, Dictionary.FIELD_AFFILIATION)); } return this; } private MongoRelations prepareRelations(DBObject db) { DBObject relation = new BasicDBObject(); // 恒定信息: JID, 创建者 relation.put(Dictionary.FIELD_JID, MongoUtils.asString(db, Dictionary.FIELD_JID)); relation.put(Dictionary.FIELD_CREATOR, MongoUtils.asString(db, Dictionary.FIELD_CREATOR)); // 加载Roles for (Object each : MongoUtils.asList(db, Dictionary.FIELD_ROLES)) { DBObject roles = DBObject.class.cast(each); relation.put(Dictionary.FIELD_ROLES, roles); // 加载岗位 relation.put(Dictionary.FIELD_AFFILIATION, this.affiliations.get(roles.get(Dictionary.FIELD_JID))); super.add(new MongoRelation(relation)); } return this; } } private class MongoRelation implements MucRelation { private final String jid; private final String creator; private final String resource; private boolean noneRole; private boolean forceRole; private boolean forceAffiliation; private String affiliation; private String role; private String name; public MongoRelation(DBObject db) { this.creator = MongoUtils.asString(db, Dictionary.FIELD_CREATOR); this.affiliation = MongoUtils.asString(db, Dictionary.FIELD_AFFILIATION); DBObject roles = MongoUtils.asDBObject(db, Dictionary.FIELD_ROLES); this.jid = MongoUtils.asString(roles, Dictionary.FIELD_JID); this.role = MongoUtils.asString(roles, Dictionary.FIELD_ROLE); this.name = MongoUtils.asString(roles, Dictionary.FIELD_NICK); this.resource = MongoUtils.asString(roles, Dictionary.FIELD_RESOURCE); } /* * 包含资源的真实JID * * @see com.sissi.ucenter.relation.Relation#jid() */ public String jid() { return MongoMucRelationContext.this.jidBuilder.build(this.jid + "/" + this.resource).asString(); } public String name() { return this.name; } public boolean name(String name, boolean allowNull) { return name.equals(this.name()) || (this.name() == null && allowNull); } public boolean outcast() { return ItemAffiliation.OUTCAST.equals(this.affiliation); } public boolean activate() { return true; } /* * 如果使用强制岗位则返回当前岗位, 否则比较是否为创建者并返回Owner * * @see com.sissi.ucenter.relation.muc.MucRelation#affiliation() */ public String affiliation() { return this.forceAffiliation ? ItemAffiliation.parse(this.affiliation).toString() : this.creator.equals(this.jid) ? ItemAffiliation.OWNER.toString() : ItemAffiliation.parse(this.affiliation).toString(); } public MucRelation affiliation(String affiliation) { this.affiliation = affiliation; return this; } public MucRelation affiliation(String affiliation, boolean force) { this.forceAffiliation = force; return this.affiliation(affiliation); } /* * 如果使用强制角色则返回当前角色, 如果NoneRole则返回None, 否则使用岗位-角色映射与当前角色的最大值 * * @see com.sissi.ucenter.relation.muc.MucRelation#role() */ @Override public String role() { if (this.forceRole) { return ItemRole.parse(this.role).toString(); } String role = ItemRole.toString(MongoMucRelationContext.this.mapping[ItemAffiliation.parse(this.affiliation()).ordinal()]); return this.noneRole ? ItemRole.NONE.toString() : ItemRole.max(this.role, role); } public MongoRelation role(String role) { this.role = role; return this; } public MongoRelation role(String role, boolean force) { this.forceRole = force; return this.role(role); } @Override public MongoRelation noneRole() { this.noneRole = true; return this; } public Map<String, Object> plus() { return MongoMucRelationContext.this.plus; } @Override public <T extends Relation> T cast(Class<T> clazz) { return clazz.cast(this); } } }