/**
  * Connects this member to the cluster using the given <code>loadFactor</code>. The <code>
  * loadFactor</code> defines the (approximate) relative load that this member will receive.
  *
  * <p>A good default value is 100, which will give this member 100 nodes on the distributed hash
  * ring. Giving all members (proportionally) lower values will result in a less evenly distributed
  * hash.
  *
  * @param loadFactor The load factor for this node.
  * @throws ConnectionFailedException when an error occurs while connecting
  */
 public synchronized void connect(int loadFactor) throws ConnectionFailedException {
   this.currentLoadFactor = loadFactor;
   Assert.isTrue(loadFactor >= 0, "Load Factor must be a positive integer value.");
   Assert.isTrue(
       channel.getReceiver() == null || channel.getReceiver() == messageReceiver,
       "The given channel already has a receiver configured. "
           + "Has the channel been reused with other Connectors?");
   try {
     channel.setReceiver(messageReceiver);
     if (channel.isConnected() && !clusterName.equals(channel.getClusterName())) {
       throw new AxonConfigurationException(
           "The Channel that has been configured with this JGroupsConnector "
               + "is already connected to another cluster.");
     } else if (channel.isConnected()) {
       // we need to fetch state now that we have attached our MessageReceiver
       channel.getState(null, 10000);
     } else {
       // we need to connect. This will automatically fetch state as well.
       channel.connect(clusterName, null, 10000);
     }
     updateMembership();
   } catch (Exception e) {
     joinedCondition.markJoined(false);
     channel.disconnect();
     throw new ConnectionFailedException("Failed to connect to JGroupsConnectorFactoryBean", e);
   }
 }
 /**
  * Returns a new {@link GapAwareTrackingToken} instance based on the given {@code index} and
  * collection of {@code gaps}.
  *
  * @param index the highest global sequence number of events up until (and including) this
  *     tracking token
  * @param gaps global sequence numbers of events that have not been seen yet even though these
  *     sequence numbers are smaller than the current index. These missing sequence numbers may be
  *     filled in later when those events get committed to the store or may never be filled in if
  *     those events never get committed.
  * @return a new tracking token from given index and gaps
  */
 public static GapAwareTrackingToken newInstance(long index, Collection<Long> gaps) {
   if (gaps.isEmpty()) {
     return new GapAwareTrackingToken(index, Collections.emptySortedSet());
   }
   SortedSet<Long> gapSet = new TreeSet<>(gaps);
   Assert.isTrue(
       gapSet.last() < index,
       () ->
           String.format(
               "Gap indices [%s] should all be smaller than head index [%d]", gaps, index));
   return new GapAwareTrackingToken(index, gapSet);
 }
 @Override
 public Object invoke(Object target, Message message)
     throws InvocationTargetException, IllegalAccessException {
   Assert.isTrue(
       method.getDeclaringClass().isInstance(target),
       "Given target is not an instance of the method's owner.");
   Assert.notNull(message, "Event may not be null");
   Object[] parameterValues = new Object[getParameterValueResolvers().length];
   for (int i = 0; i < parameterValues.length; i++) {
     parameterValues[i] = getParameterValueResolvers()[i].resolveParameterValue(message);
   }
   return method.invoke(target, parameterValues);
 }
 /**
  * Sets the interface that describes the gateway instance to describe. If no interface is
  * provided, it defaults to {@link CommandGateway}.
  *
  * @param gatewayInterface The interface describing the gateway
  * @throws IllegalArgumentException if the given <code>gatewayInterface</code> is <code>null
  *     </code> or not an interface.
  */
 public void setGatewayInterface(Class<T> gatewayInterface) {
   Assert.notNull(gatewayInterface, "The given gateway interface may not be null");
   Assert.isTrue(
       gatewayInterface.isInterface(), "The given gateway interface must be an interface");
   this.gatewayInterface = gatewayInterface;
 }
 /**
  * Initialize the writer to write the object structure to the given <code>root</code> DBObject.
  *
  * <p>Note that the given <code>root</code> DBObject must not contain any data yet.
  *
  * @param root The root DBObject to which the serialized structure will be added. Must not contain
  *     any data.
  */
 public DBObjectHierarchicalStreamWriter(DBObject root) {
   Assert.isTrue(root.keySet().isEmpty(), "The given root object must be empty.");
   this.root = root;
 }