Package com.sissi.ucenter.relation.roster.impl

Source Code of com.sissi.ucenter.relation.roster.impl.MongoRelationRosterContext$RelationUpdate

package com.sissi.ucenter.relation.roster.impl;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.mongodb.BasicDBObjectBuilder;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
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.protocol.iq.roster.RosterSubscription;
import com.sissi.ucenter.relation.Relation;
import com.sissi.ucenter.relation.RelationContext;
import com.sissi.ucenter.relation.roster.RelationAck;
import com.sissi.ucenter.relation.roster.RelationCascade;

/**
* 索引策略1: {"master":1,"slave":1}</p> 索引策略2: {"slave":1,"master":1}</p> 索引策略3: {"master":1,"activate":1}</p> 索引策略4: {"slave":1,"activate":1}</p> 索引策略5: {"master":1,"activate":1,"status":1}</p> 索引策略6: {"slave":1,"activate":1,"status":1}</p> 索引策略7: {"slave":1,"ack":1}
* @author kim 2014年4月22日
*/
public class MongoRelationRosterContext implements RelationContext, RelationAck {

  private final Log log = LogFactory.getLog(this.getClass());

  private final Map<String, RelationUpdate> update = new HashMap<String, RelationUpdate>();

  private final Map<String, Object> plus = Collections.unmodifiableMap(new HashMap<String, Object>());

  /**
   * {"slave":1}
   */
  private final DBObject filterSlave = BasicDBObjectBuilder.start(Dictionary.FIELD_SLAVE, 1).get();

  /**
   * {"master":1}
   */
  private final DBObject filterMaster = BasicDBObjectBuilder.start(Dictionary.FIELD_MASTER, 1).get();

  /**
   * 初始化Master,{"status":0}
   */
  private final DBObject initMaster = BasicDBObjectBuilder.start(Dictionary.FIELD_STATUS, 0).get();

  /**
   * 初始化Salve,{"activate":false,"status":0}
   */
  private final DBObject initSlave = BasicDBObjectBuilder.start().add(Dictionary.FIELD_ACTIVATE, false).add(Dictionary.FIELD_STATUS, 0).get();

  /**
   * 建立订阅To,{"or":1}
   */
  private final DBObject establishTo = BasicDBObjectBuilder.start("or", 1).get();

  /**
   * 建立订阅From,{"or":2}
   */
  private final DBObject establishFrom = BasicDBObjectBuilder.start("or", 2).get();

  /**
   * 删除订阅To,{"and":1}
   */
  private final DBObject brokeTo = BasicDBObjectBuilder.start("and", 1).get();

  /**
   * 删除订阅From,{"and":1}
   */
  private final DBObject brokeFrom = BasicDBObjectBuilder.start("and", 2).get();

  /**
   * 有效的订阅关系,[{"status":1},{"status":3}]
   */
  private final DBObject[] states = new DBObject[] { BasicDBObjectBuilder.start(Dictionary.FIELD_STATUS, 1).get(), BasicDBObjectBuilder.start(Dictionary.FIELD_STATUS, 3).get() };

  /**
   * 默认Group
   */
  private final String[] groups;

  private final MongoConfig config;

  private final JIDBuilder jidBuilder;

  private final MongoOurRelation ourRelation;

  private final RelationCascade relationCascade;

  public MongoRelationRosterContext(String group, MongoConfig config, JIDBuilder jidBuilder, MongoOurRelation ourRelation, RelationCascade relationCascade) {
    super();
    this.config = config;
    this.jidBuilder = jidBuilder;
    this.ourRelation = ourRelation;
    this.relationCascade = relationCascade;
    this.groups = new String[] { group };
    this.update.put(RosterSubscription.NONE.toString(), new RelationUpdate(this.brokeTo, this.brokeFrom));
    this.update.put(RosterSubscription.TO.toString(), new RelationUpdate(this.establishFrom, this.establishTo));
  }

  /**
   * {"master":1,"slave":1}
   *
   * @param master
   * @param slave
   * @return
   */
  private DBObject buildQuery(String master, String slave) {
    return this.ourRelation.buildQuery(master, slave);
  }

  /**
   * {角色:jid,"activate":true}
   *
   * @param role
   * @param jid
   * @return
   */
  private DBObject buildQueryWithRole(String role, String jid) {
    return BasicDBObjectBuilder.start().add(role, jid).add(Dictionary.FIELD_ACTIVATE, true).get();
  }

  /**
   * {角色:jid,"activate":true,"$or":有效的订阅关系,[{"status":1},{"status":3}]}
   *
   * @param role
   * @param jid
   * @param status
   * @return
   */
  private DBObject buildQueryWithStates(String role, String jid, DBObject[] status) {
    DBObject query = this.buildQueryWithRole(role, jid);
    query.put("$or", status);
    return query;
  }

  @Override
  public MongoRelationRosterContext establish(JID from, Relation relation) {
    // {"$set":{(...relation.plus()...),"nick":relation.name(),"activate":true},"$setOnInsert":{"status":0}}
    // {"$setOnInsert":{"activate":false,"status":0}}
    if (MongoUtils.success(this.config.collection().update(this.buildQuery(from.asStringWithBare(), relation.jid()), BasicDBObjectBuilder.start().add("$set", BasicDBObjectBuilder.start(relation.plus()).add(Dictionary.FIELD_NICK, relation.name()).add(Dictionary.FIELD_ACTIVATE, true).get()).add("$setOnInsert", this.initMaster).get(), true, false, WriteConcern.SAFE)) && MongoUtils.success(this.config.collection().update(this.buildQuery(relation.jid(), from.asStringWithBare()), BasicDBObjectBuilder.start("$setOnInsert", this.initSlave).get(), true, false, WriteConcern.SAFE))) {
      return this;
    }
    this.log.error("Establish warning: " + from.asStringWithBare() + " / " + relation.jid());
    return this;
  }

  @Override
  public MongoRelationRosterContext update(JID from, JID to, String state) {
    // {"$unset":{"ack":true},"$bit":{"status",this.update.Xxx}}
    // {"$bit":{"status",this.update.Xxx}}
    if (MongoUtils.success(this.config.collection().update(this.buildQuery(from.asStringWithBare(), to.asStringWithBare()), BasicDBObjectBuilder.start().add("$unset", BasicDBObjectBuilder.start(Dictionary.FIELD_ACK, true).get()).add("$bit", BasicDBObjectBuilder.start().add(Dictionary.FIELD_STATUS, this.update.get(state).getTo()).get()).get(), true, false, WriteConcern.SAFE)) && MongoUtils.success(this.config.collection().update(this.buildQuery(to.asStringWithBare(), from.asStringWithBare()), BasicDBObjectBuilder.start("$bit", BasicDBObjectBuilder.start().add(Dictionary.FIELD_STATUS, this.update.get(state).getFrom()).get()).get(), true, false, WriteConcern.SAFE))) {
      this.relationCascade.update(to, from);
      return this;
    }
    this.log.error("Update warning: " + from.asStringWithBare() + " / " + to.asStringWithBare() + " / " + state);
    return this;
  }

  public MongoRelationRosterContext remove(JID from, JID to) {
    if (MongoUtils.success(this.config.collection().remove(this.buildQuery(from.asStringWithBare(), to.asStringWithBare()), WriteConcern.SAFE)) && MongoUtils.success(this.config.collection().remove(this.buildQuery(to.asStringWithBare(), from.asStringWithBare()), WriteConcern.SAFE))) {
      this.relationCascade.remove(to, from);
    } else {
      this.log.error("Remove warning: " + from.asStringWithBare() + " / " + to.asStringWithBare());
    }
    return this;
  }

  /*
   * {"master":jid.bare,"activate":true}
   *
   * @see com.sissi.ucenter.relation.RelationContext#myRelations(com.sissi.context.JID)
   */
  @Override
  public Set<Relation> myRelations(JID from) {
    return new MongoRelations(this.config.collection().find(this.buildQueryWithRole(Dictionary.FIELD_MASTER, from.asStringWithBare())));
  }

  @Override
  public Relation ourRelation(JID from, JID to) {
    return this.ourRelation.ourRelation(from, to);
  }

  @Override
  public Set<JID> whoSubscribedMe(JID from) {
    return new MongoJIDGroup(this.config.collection().find(this.buildQueryWithStates(Dictionary.FIELD_SLAVE, from.asStringWithBare(), this.states), this.filterMaster), Dictionary.FIELD_MASTER);
  }

  public Set<JID> iSubscribedWho(JID from) {
    return new MongoJIDGroup(this.config.collection().find(this.buildQueryWithStates(Dictionary.FIELD_MASTER, from.asStringWithBare(), this.states), this.filterSlave), Dictionary.FIELD_SLAVE);
  }

  /*
   * {"slave":jid.bare,"ack":true}
   *
   * @see com.sissi.ucenter.relation.roster.RelationAck#ack(com.sissi.context.JID)
   */
  @Override
  public Set<Relation> ack(JID jid) {
    return new MongoRelations(this.config.collection().find(BasicDBObjectBuilder.start().add(Dictionary.FIELD_SLAVE, jid.asStringWithBare()).add(Dictionary.FIELD_ACK, true).get()), Dictionary.FIELD_MASTER);
  }

  private class RelationUpdate {

    private final DBObject from;

    private final DBObject to;

    public RelationUpdate(DBObject from, DBObject to) {
      super();
      this.from = from;
      this.to = to;
    }

    public DBObject getFrom() {
      return this.from;
    }

    public DBObject getTo() {
      return this.to;
    }
  }

  private class MongoRelations extends HashSet<Relation> {

    private final static long serialVersionUID = 1L;

    private MongoRelations(DBCursor cursor) {
      this(cursor, Dictionary.FIELD_SLAVE);
    }

    /**
     * @param cursor
     * @param field
     */
    private MongoRelations(DBCursor cursor, String field) {
      try (DBCursor iterator = cursor) {
        if (iterator == null) {
          return;
        }
        while (iterator.hasNext()) {
          this.add(new MongoRosterRelation(iterator.next(), field, MongoRelationRosterContext.this.groups, MongoRelationRosterContext.this.plus));
        }
      }
    }
  }

  private class MongoJIDGroup extends HashSet<JID> {

    private final static long serialVersionUID = 1L;

    private MongoJIDGroup(DBCursor cursor, String key) {
      try (DBCursor iterator = cursor) {
        if (iterator == null) {
          return;
        }
        while (iterator.hasNext()) {
          this.add(MongoRelationRosterContext.this.jidBuilder.build(iterator.next().get(key).toString()));
        }
      }
    }
  }
}
TOP

Related Classes of com.sissi.ucenter.relation.roster.impl.MongoRelationRosterContext$RelationUpdate

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.