package com.sissi.ucenter.relation.muc.room.impl; import java.util.HashMap; import java.util.List; import java.util.Map; import com.mongodb.AggregationOutput; import com.mongodb.BasicDBObjectBuilder; import com.mongodb.DBObject; 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.field.Field; import com.sissi.field.Fields; import com.sissi.protocol.muc.ItemAffiliation; import com.sissi.protocol.muc.ItemRole; import com.sissi.ucenter.relation.RelationContext; import com.sissi.ucenter.relation.muc.MucRelation; import com.sissi.ucenter.relation.muc.room.Room; import com.sissi.ucenter.relation.muc.room.RoomBuilder; import com.sissi.ucenter.relation.muc.room.RoomConfig; import com.sissi.ucenter.relation.muc.room.RoomConfigApprover; import com.sissi.ucenter.relation.muc.room.RoomConfigParam; import com.sissi.ucenter.relation.muc.room.RoomConfigParser; /** * 索引策略1: {"jid":1}</p>索引策略2: {"affiliations.jid":1} * * @author kim 2014年2月20日 */ public class MongoRoomBuilder implements RoomBuilder { private final Map<String, Object> configs = new HashMap<String, Object>(); private final Map<String, RoomConfigParser> parsers = new HashMap<String, RoomConfigParser>(); private final Map<RoomConfig, RoomConfigApprover> readers = new HashMap<RoomConfig, RoomConfigApprover>(); /** * {"$unwind":"$affiliations"} */ private final DBObject unwind = BasicDBObjectBuilder.start().add("$unwind", "$" + Dictionary.FIELD_AFFILIATIONS).get(); /** * {"configs":1,"creator":1,"activate":1} */ private final DBObject filter = BasicDBObjectBuilder.start().add(Dictionary.FIELD_CONFIGS, 1).add(Dictionary.FIELD_CREATOR, 1).add(Dictionary.FIELD_ACTIVATE, 1).get(); /** * {"$project":{"nick":"$affiliations.nick"}} */ private final DBObject project = BasicDBObjectBuilder.start("$project", BasicDBObjectBuilder.start(Dictionary.FIELD_NICK, "$" + Dictionary.FIELD_AFFILIATIONS + "." + Dictionary.FIELD_NICK).get()).get(); private final MongoConfig config; private final JIDBuilder jidBuilder; private final RelationContext relationContext; public MongoRoomBuilder(MongoConfig config, JIDBuilder jidBuilder, RelationContext relationContext, List<RoomConfigParser> parsers, List<RoomConfigApprover> readers) { super(); this.config = config; this.jidBuilder = jidBuilder; this.relationContext = relationContext; for (RoomConfigParser each : parsers) { this.parsers.put(each.support(), each); } for (RoomConfigApprover each : readers) { this.readers.put(each.support(), each); } } /* * {"jid":group.bare},{"configs":1,"creator":1,"activate":1} * * @see com.sissi.ucenter.relation.muc.room.RoomBuilder#build(com.sissi.context.JID) */ @Override public Room build(JID group) { DBObject db = this.config.collection().findOne(BasicDBObjectBuilder.start(Dictionary.FIELD_JID, group.asStringWithBare()).get(), this.filter); return new MongoRoom(group, this.jidBuilder.build(MongoUtils.asString(db, Dictionary.FIELD_CREATOR)), MongoUtils.asDBObject(db, Dictionary.FIELD_CONFIGS)); } private class MucConfigParamImpl implements RoomConfigParam { private final JID user; private final JID group; private final JID creator; private final DBObject configs; public MucConfigParamImpl(JID user, JID group, JID creator, DBObject configs) { super(); this.user = user; this.group = group; this.creator = creator; this.configs = configs; } public JID user() { return this.user; } public boolean affiliation() { return this.affiliation(MongoUtils.asString(this.configs, Dictionary.FIELD_AFFILIATION)); } public boolean affiliation(String affiliation) { return this.creator() || ItemAffiliation.parse(this.relation().affiliation()).contains(affiliation); } public boolean hidden(boolean compute) { boolean whois = MongoUtils.asBoolean(this.configs, Dictionary.FIELD_WHOIS); return compute ? !this.creator() && !ItemRole.parse(MongoRoomBuilder.this.relationContext.ourRelation(this.user, this.group).cast(MucRelation.class).role()).contains(ItemRole.MODERATOR) && whois : whois; } /* * JID为创建者或房间不存在 * * @see com.sissi.ucenter.relation.muc.room.RoomConfigParam#creator() */ @Override public boolean creator() { return this.user.like(this.creator) || MongoRoomBuilder.this.config.collection().findOne(BasicDBObjectBuilder.start(Dictionary.FIELD_JID, this.group.asStringWithBare()).get()) == null; } public boolean activate(boolean compute) { boolean activate = MongoUtils.asBoolean(this.configs, Dictionary.FIELD_ACTIVATE, true); return compute ? this.creator() || activate : activate; } public MucRelation relation() { return MongoRoomBuilder.this.relationContext.ourRelation(this.user, this.group).cast(MucRelation.class); } @SuppressWarnings("unchecked") public Map<String, Object> configs() { return this.configs != null ? this.configs.toMap() : MongoRoomBuilder.this.configs; } } private class MongoRoom implements Room { private final JID group; private final JID creator; private final DBObject configs; private MongoRoom(JID group, JID creator, DBObject configs) { super(); this.group = group; this.creator = creator; this.configs = configs; } /** * {"jid":group.bare} * * @return */ private DBObject build() { return BasicDBObjectBuilder.start(Dictionary.FIELD_JID, this.group.asStringWithBare()).get(); } public <T> T pull(String key, Class<T> clazz) { return this.configs != null ? clazz.cast(this.configs.get(key)) : null; } /* * {"jid":group.bare} * * @see com.sissi.ucenter.relation.muc.room.Room#destory() */ public Room destory() { MongoRoomBuilder.this.config.collection().remove(this.build()); return this; } /* * {"$set":{"configs.Xxx1":Xxx,"configs.Xxx2":Xxx}} * * @see com.sissi.ucenter.relation.muc.room.Room#push(com.sissi.field.Fields) */ public Room push(Fields fields) { BasicDBObjectBuilder update = BasicDBObjectBuilder.start(); for (Field<?> field : fields) { RoomConfigParser parser = MongoRoomBuilder.this.parsers.get(field.getName()); if (parser != null) { update.add(Dictionary.FIELD_CONFIGS + "." + parser.field(), parser.parse(field)); } } if (!update.isEmpty()) { MongoRoomBuilder.this.config.collection().update(this.build(), BasicDBObjectBuilder.start("$set", update.get()).get()); } return this; } /* * {"$set":{"configs.Xxx":Xxx}} * * @see com.sissi.ucenter.relation.muc.room.Room#push(com.sissi.field.Field) */ public Room push(Field<?> field) { RoomConfigParser parser = MongoRoomBuilder.this.parsers.get(field.getName()); if (parser != null) { MongoRoomBuilder.this.config.collection().update(this.build(), BasicDBObjectBuilder.start("$set", BasicDBObjectBuilder.start(Dictionary.FIELD_CONFIGS + "." + parser.field(), parser.parse(field)).get()).get()); } return this; } public String reserved(JID jid) { // {"$match":{"jid":group.bare}}, {"$unwind":"$affiliations"}, {"$match":{"affiliations.jid":jid.bare}}, {"$project":{"nick":"$affiliations.nick"}} AggregationOutput output = MongoRoomBuilder.this.config.collection().aggregate(BasicDBObjectBuilder.start("$match", BasicDBObjectBuilder.start(Dictionary.FIELD_JID, this.group.asStringWithBare()).get()).get(), MongoRoomBuilder.this.unwind, BasicDBObjectBuilder.start("$match", BasicDBObjectBuilder.start(Dictionary.FIELD_AFFILIATIONS + "." + Dictionary.FIELD_JID, jid.asStringWithBare()).get()).get(), MongoRoomBuilder.this.project); @SuppressWarnings("deprecation") List<?> result = MongoUtils.asList(output.getCommandResult(), Dictionary.FIELD_RESULT); return result.isEmpty() ? null : MongoUtils.asString(DBObject.class.cast(result.get(0)), Dictionary.FIELD_NICK); } @Override public boolean allowed(JID jid, RoomConfig key) { return this.allowed(jid, key, null); } @Override public boolean allowed(JID jid, RoomConfig key, Object value) { RoomConfigApprover approver = MongoRoomBuilder.this.readers.get(key); return approver != null ? approver.approve(new MucConfigParamImpl(jid, this.group, this.creator, this.configs), value) : false; } } }