Package com.sissi.addressing.impl

Source Code of com.sissi.addressing.impl.MongoAddressing$MongoJIDContexts

package com.sissi.addressing.impl;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.mongodb.BasicDBObjectBuilder;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.WriteConcern;
import com.sissi.addressing.Addressing;
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.JIDContext;
import com.sissi.context.JIDContextBuilder;
import com.sissi.context.JIDContextParam;
import com.sissi.context.JIDs;
import com.sissi.context.impl.JIDContexts;
import com.sissi.context.impl.ShareJIDs;

/**
* 基于ConcurrentHashMap的寻址策略</p>索引策略1:{"jid":1},索引策略2:{"jid":1,"resource":1,"priority":-1},索引策略3:{"index":-1,"jid":1,"resource":1}</p>
*
* @author kim 2014年1月29日
*/
public class MongoAddressing implements Addressing {

  private final String fieldAddress = "address";

  /**
   * 过滤策略,{"index":1}
   */
  private final DBObject filterIndex = BasicDBObjectBuilder.start(Dictionary.FIELD_INDEX, 1).get();

  /**
   * 过滤策略,{"resource":1}
   */
  private final DBObject filterResource = BasicDBObjectBuilder.start(Dictionary.FIELD_RESOURCE, 1).get();

  /**
   * 排序策略,{"priority":-1}
   */
  private final DBObject querySort = BasicDBObjectBuilder.start(Dictionary.FIELD_PRIORITY, -1).get();

  private final JIDContextParam nothing = new NothingJIDContextParam();

  private final Map<Long, JIDContext> contexts = new ConcurrentHashMap<Long, JIDContext>();

  private final MongoConfig config;

  private final JIDContextBuilder offline;

  public MongoAddressing(MongoConfig config, JIDContextBuilder offline) {
    super();
    this.offline = offline;
    this.config = config.reset();
  }

  @Override
  public Addressing join(JIDContext context) {
    if (MongoUtils.success(this.config.collection().save(this.buildQueryWithNecessaryFields(context), WriteConcern.SAFE))) {
      this.contexts.put(context.index(), context);
    }
    return this;
  }

  @Override
  public Addressing leave(JIDContext context) {
    if (MongoUtils.success(this.config.collection().remove(this.buildQueryWithNecessaryFields(context), WriteConcern.SAFE))) {
      this.contexts.remove(context.index());
    }
    return this;
  }

  /*
   * {"$set":{"priority":Xxx}}
   *
   * @see com.sissi.addressing.Addressing#priority(com.sissi.context.JIDContext)
   */
  public Addressing priority(JIDContext context) {
    this.config.collection().update(this.buildQueryWithSmartResource(context.jid(), true), BasicDBObjectBuilder.start("$set", BasicDBObjectBuilder.start(Dictionary.FIELD_PRIORITY, context.priority()).get()).get());
    return this;
  }

  @Override
  public JIDContexts find(JID jid) {
    return this.find(jid, false);
  }

  @Override
  public JIDContexts find(JID jid, boolean usingResource) {
    return this.find(jid, usingResource, true);
  }

  @Override
  public JIDContext findOne(JID jid) {
    return this.findOne(jid, false);
  }

  public JIDContext findOne(JID jid, boolean usingResource) {
    return this.findOne(jid, usingResource, false);
  }

  /*
   * 1,符合条件唯一JIDContext</p>2,不存在则</p>2.1,使用离线JIDContext</p>2.2,使用Find(All)
   *
   * @see com.sissi.addressing.Addressing#findOne(com.sissi.context.JID, boolean, boolean)
   */
  public JIDContext findOne(JID jid, boolean usingResource, boolean offline) {
    DBObject entity = this.config.collection().findOne(this.buildQueryWithSmartResource(jid, usingResource), this.filterIndex);
    return entity != null ? this.contexts.get(MongoUtils.asLong(entity, Dictionary.FIELD_INDEX)) : offline ? this.offline.build(jid, this.nothing) : this.find(jid);
  }

  public JIDs resources(JID jid) {
    return this.resources(jid, false);
  }

  public JIDs resources(JID jid, boolean usingResource) {
    return new ShareJIDs(jid, this.config.collection().find(this.buildQueryWithSmartResource(jid, usingResource), this.filterResource));
  }

  private JIDContexts find(JID jid, boolean usingResource, boolean usingOffline) {
    return new MongoJIDContexts(jid, usingOffline, this.config.collection().find(this.buildQueryWithSmartResource(jid, usingResource), this.filterIndex).sort(this.querySort));
  }

  /**
   * For Join / Remove</p>{"index":Xxx,"jid":Xxx,"resource":Xxx,"address":Xxx}
   *
   * @param context
   * @return
   */
  private DBObject buildQueryWithNecessaryFields(JIDContext context) {
    return BasicDBObjectBuilder.start().add(Dictionary.FIELD_INDEX, context.index()).add(Dictionary.FIELD_JID, context.jid().asStringWithBare()).add(Dictionary.FIELD_RESOURCE, context.jid().resource()).add(this.fieldAddress, context.address().toString()).get();
  }

  /**
   * For FindXxx</p>{"jid",Xxx,"resource":Xxx(如果使用资源)}
   *
   * @param jid
   * @param usingResource
   * @return
   */
  private DBObject buildQueryWithSmartResource(JID jid, boolean usingResource) {
    // JID,Resource
    BasicDBObjectBuilder query = BasicDBObjectBuilder.start(Dictionary.FIELD_JID, jid.asStringWithBare());
    if (usingResource && !jid.isBare()) {
      query.add(Dictionary.FIELD_RESOURCE, jid.resource());
    }
    return query.get();
  }

  private class MongoJIDContexts extends JIDContexts {

    private final static long serialVersionUID = 1L;

    private MongoJIDContexts(JID jid, boolean usingOffline, DBCursor cursor) {
      this.read(cursor).usingOffline(jid, usingOffline);
    }

    private MongoJIDContexts read(DBCursor cursor) {
      try (DBCursor iterator = cursor) {
        while (iterator.hasNext()) {
          JIDContext context = MongoAddressing.this.contexts.get(MongoUtils.asLong(iterator.next(), Dictionary.FIELD_INDEX));
          // Double check 4 multi thread
          if (context != null) {
            super.add(context);
          }
        }
      }
      return this;
    }

    private MongoJIDContexts usingOffline(JID jid, boolean usingOffline) {
      if (usingOffline && super.isEmpty()) {
        super.add(MongoAddressing.this.offline.build(jid, MongoAddressing.this.nothing));
      }
      return this;
    }
  }

  private class NothingJIDContextParam implements JIDContextParam {

    @Override
    public <T> T find(String key, Class<T> clazz) {
      return null;
    }
  }
}
TOP

Related Classes of com.sissi.addressing.impl.MongoAddressing$MongoJIDContexts

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.
ga('send', 'pageview');