package com.sissi.ucenter.relation.muc.impl;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.mongodb.AggregationOutput;
import com.mongodb.BasicDBObjectBuilder;
import com.mongodb.DBCursor;
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.protocol.muc.ItemAffiliation;
import com.sissi.ucenter.relation.Relation;
import com.sissi.ucenter.relation.muc.affiliation.AffiliationBuilder;
import com.sissi.ucenter.vcard.VCardContext;
/**
* 索引策略1: {"affiliations.jid":1,"affiliations.nick":1}</p>索引策略2: {"affiliations.jid":1}</p>索引策略3: {"jid":1}</p>索引策略4: {"affiliations.affiliation":1}</p>索引策略5: {"configs.persistent":1}
*
* @author kim 2014年4月25日
*/
public class MongoMucRelation4AffiliationContext extends MongoMucRelationContext {
/**
* 默认Relation.name
*/
private final String name = "n/a";
/**
* {"$match":"configs.persistent":true}
*/
private final DBObject matchPersistent = BasicDBObjectBuilder.start("$match", BasicDBObjectBuilder.start(Dictionary.FIELD_CONFIGS + "." + Dictionary.FIELD_PERSISTENT, true).get()).get();
/**
* {"$project":{"affiliation":"$affiliations"}}
*/
private final DBObject projectAffiliation = BasicDBObjectBuilder.start("$project", BasicDBObjectBuilder.start().add(Dictionary.FIELD_AFFILIATION, "$" + Dictionary.FIELD_AFFILIATIONS).get()).get();
/**
* {"$project":{"jid":"$jid","resource":"$affiliations.nick"}}
*/
private final DBObject projectSubscribed = BasicDBObjectBuilder.start("$project", BasicDBObjectBuilder.start().add(Dictionary.FIELD_JID, "$" + Dictionary.FIELD_JID).add(Dictionary.FIELD_RESOURCE, "$" + Dictionary.FIELD_AFFILIATIONS + "." + Dictionary.FIELD_NICK).get()).get();
/**
* {"configs":1}
*/
private final DBObject filterUpdate = BasicDBObjectBuilder.start().add(Dictionary.FIELD_CONFIGS, 1).get();
/**
* {"jid":1,"configs.subject":1,"creator":1}
*/
private final DBObject filterRelations = BasicDBObjectBuilder.start().add(Dictionary.FIELD_JID, 1).add(Dictionary.FIELD_CONFIGS + "." + Dictionary.FIELD_SUBJECT, 1).add(Dictionary.FIELD_CREATOR, 1).get();
private final AffiliationBuilder affiliationBuilder;
private final boolean cascade;
/**
* @param activate
* @param cascade 是否Update时级联删除
* @param mapping
* @param finder
* @param config
* @param jidBuilder
* @param vcardContext
* @param affiliationBuilder
* @throws Exception
*/
public MongoMucRelation4AffiliationContext(boolean cascade, String mapping, MongoConfig config, JIDBuilder jidBuilder, VCardContext vcardContext, AffiliationBuilder affiliationBuilder) throws Exception {
super(mapping, config, jidBuilder, vcardContext);
this.affiliationBuilder = affiliationBuilder;
this.cascade = cascade;
}
/*
* 我订阅的所有房间(存在岗位)
*
* @see com.sissi.ucenter.relation.RelationContext#iSubscribedWho(com.sissi.context.JID)
*/
@SuppressWarnings("deprecation")
public Set<JID> iSubscribedWho(JID from) {
// {"$match":{"affiliations.jid",from.bare,"affiliations.nick":{"$exists":true}}}
DBObject match = BasicDBObjectBuilder.start("$match", BasicDBObjectBuilder.start().add(MongoConfig.FIELD_AFFILIATIONS + "." + MongoConfig.FIELD_JID, from.asStringWithBare()).add(MongoConfig.FIELD_AFFILIATIONS + "." + MongoConfig.FIELD_NICK, BasicDBObjectBuilder.start("$exists", true).get()).get()).get();
return new JIDGroup(MongoUtils.asList(this.config.collection().aggregate(this.matchPersistent, match, super.unwindAffiliation, match, this.projectSubscribed).getCommandResult(), Dictionary.FIELD_RESULT));
}
/*
* JID已加入所有房间(存在岗位)
*
* @see com.sissi.ucenter.relation.muc.impl.MongoRelationMucContext#myRelations(com.sissi.context.JID)
*/
public Set<Relation> myRelations(JID from) {
// {"affiliations.jid":from.bare}, {"jid":1,"configs.subject":1,"creator":1}, 只需要JID和房间名称
return new Relations(this.config.collection().find(BasicDBObjectBuilder.start(Dictionary.FIELD_AFFILIATIONS + "." + Dictionary.FIELD_JID, from.asStringWithBare()).get(), this.filterRelations));
}
/*
* 岗位相符的订阅关系
*
* @see com.sissi.ucenter.relation.muc.MucRelationContext#myRelations(com.sissi.context.JID, java.lang.String)
*/
public Set<Relation> myRelations(JID from, String affiliation) {
// {"$match":{"jid":group.bare}}, {"$unwind":"$affiliations"}, {"$match":{"affiliations.affiliation":Xxx}}, {"$project":{"affiliation":"$affiliations"}}
AggregationOutput output = super.config.collection().aggregate(super.buildMatcher(from), super.unwindAffiliation, BasicDBObjectBuilder.start("$match", BasicDBObjectBuilder.start(Dictionary.FIELD_AFFILIATIONS + "." + Dictionary.FIELD_AFFILIATION, affiliation).get()).get(), this.projectAffiliation);
@SuppressWarnings("deprecation")
List<?> result = MongoUtils.asList(output.getCommandResult(), Dictionary.FIELD_RESULT);
return result.isEmpty() ? super.relations : new AffiliationRelations(result);
}
/*
* 删除订阅关系
*
* @see com.sissi.ucenter.relation.muc.impl.MongoRelationMucContext#remove(com.sissi.context.JID, com.sissi.context.JID)
*/
public MongoMucRelationContext remove(JID from, JID to) {
// {"jid":jid}, {"$pull":{"affiliations.jid":Xxx}}
super.config.collection().update(super.buildQuery(to.asStringWithBare()), BasicDBObjectBuilder.start("$pull", BasicDBObjectBuilder.start(Dictionary.FIELD_AFFILIATIONS, BasicDBObjectBuilder.start(Dictionary.FIELD_JID, from.asStringWithBare()).get()).get()).get());
return this;
}
@Override
public MongoMucRelationContext update(JID from, JID to, String status) {
// 1,更新成功 2,允许级联 3,岗位为Outcast或岗位受限制
if (this.affiliationBuilder.build(to).update(from, status) && this.cascade && (ItemAffiliation.OUTCAST.equals(status) || !ItemAffiliation.parse(status).contains(MongoUtils.asString(MongoUtils.asDBObject(this.config.collection().findOne(BasicDBObjectBuilder.start(Dictionary.FIELD_JID, to.asStringWithBare()).get(), this.filterUpdate), Dictionary.FIELD_CONFIGS), Dictionary.FIELD_AFFILIATION)))) {
super.remove(from, to, true);
}
return this;
}
/**
* 房间-用户反向订阅关系
*
* @author kim 2014年4月25日
*/
private final class RoomRelation implements Relation {
private final DBObject db;
private RoomRelation(DBObject db) {
super();
this.db = db;
}
@Override
public String jid() {
return MongoUtils.asString(this.db, Dictionary.FIELD_JID);
}
/*
* 使用Config.subject作为名词,如果不存在则使用默认
*
* @see com.sissi.ucenter.relation.Relation#name()
*/
@Override
public String name() {
return MongoUtils.asString(MongoUtils.asDBObject(this.db, Dictionary.FIELD_CONFIGS), Dictionary.FIELD_SUBJECT, MongoMucRelation4AffiliationContext.this.name);
}
@Override
public boolean activate() {
return true;
}
@Override
public Map<String, Object> plus() {
return MongoMucRelation4AffiliationContext.super.plus;
}
@Override
public <T extends Relation> T cast(Class<T> clazz) {
return clazz.cast(this);
}
}
private final class Relations extends HashSet<Relation> {
private static final long serialVersionUID = 1L;
public Relations(DBCursor cursor) {
try (DBCursor iterator = cursor) {
while (iterator.hasNext()) {
super.add(new RoomRelation(iterator.next()));
}
}
}
}
/**
* 岗位相符的订阅关系
*
* @author kim 2014年4月25日
*/
private final class AffiliationRelations extends HashSet<Relation> {
private static final long serialVersionUID = 1L;
private AffiliationRelations(List<?> affiliations) {
for (Object each : affiliations) {
DBObject affiliation = MongoUtils.asDBObject(DBObject.class.cast(each), Dictionary.FIELD_AFFILIATION);
super.add(new NoneRelation(MongoMucRelation4AffiliationContext.this.jidBuilder.build(MongoUtils.asString(affiliation, Dictionary.FIELD_JID)), ItemAffiliation.parse(MongoUtils.asString(affiliation, Dictionary.FIELD_AFFILIATION))));
}
}
}
}