Package com.sissi.ucenter.relation.muc.impl

Source Code of com.sissi.ucenter.relation.muc.impl.MongoMucRelationContext

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);
    }
  }
}
TOP

Related Classes of com.sissi.ucenter.relation.muc.impl.MongoMucRelationContext

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.