/**
   * @param reference
   * @return
   */
  @SuppressWarnings("rawtypes")
  public ActivityHandle getActivityHandle(ActivityHandleReference reference) {

    if (doTraceLogs) {
      logger.trace("getActivityHandle( reference = " + reference + " )");
    }

    ActivityHandle ah = reference.getReference();
    if (ah == null) {
      ah = ref2handle.get(reference);
      if (ah != null) {
        reference.setReference(ah);
      } else {
        // if in tx context it may be in tx data only, due to creation
        final TransactionContext txContext = getTxManager().getTransactionContext();
        if (txContext != null) {
          final Map txData = txContext.getData();
          Handle2RefTxData handle2RefTxData = (Handle2RefTxData) txData.get(reference);
          if (handle2RefTxData != null) {
            ah = handle2RefTxData.handle;
            reference.setReference(ah);
          }
        }
      }
    }
    return ah;
  }
  /**
   * @param handle
   * @return
   */
  @SuppressWarnings({"rawtypes", "unchecked"})
  public ActivityHandleReference createActivityHandleReference(final ActivityHandle handle) {

    if (doTraceLogs) {
      logger.trace("createActivityHandleReference( handle = " + handle + " )");
    }

    ActivityHandleReference reference = handle2ref.get(handle);
    if (reference != null) {
      throw new ActivityAlreadyExistsException(handle.toString());
    }

    String id = null;
    final TransactionContext txContext = getTxManager().getTransactionContext();
    if (txContext != null) {
      // check 1st in the tx
      final Map txData = txContext.getData();
      Handle2RefTxData handle2RefTxData = (Handle2RefTxData) txData.get(handle);
      if (handle2RefTxData != null) {
        // already exists in tx
        throw new ActivityAlreadyExistsException(handle.toString());
      } else {
        id = new VMID().toString();
        // a ref to generated ids are kept while tx exists, so concurrent invocations use the same
        // id
        final PendingId otherPendingId = pendingIds.putIfAbsent(handle, new PendingId(id));
        if (otherPendingId != null) {
          // concurrent tx creating, must allow, it may rollback, reuse id
          otherPendingId.txs.incrementAndGet();
          id = otherPendingId.id;
        }
        // create ref and add to tx
        reference = new ActivityHandleReference(handle, getLocalAddress(), id);
        final Handle2RefTxData newHandle2RefTxData = new Handle2RefTxData(handle, reference);
        txData.put(handle, newHandle2RefTxData);
        txData.put(reference, newHandle2RefTxData);
        // add tx actions
        final TransactionalAction rollbackAction =
            new TransactionalAction() {
              public void execute() {
                if (logger.isDebugEnabled()) {
                  logger.debug(
                      "Rollback of activity handle reference creation, for activity handle "
                          + handle);
                }
                PendingId pendingId = pendingIds.get(handle);
                if (pendingId.txs.decrementAndGet() < 1) {
                  pendingIds.remove(handle);
                }
              }
            };
        final TransactionalAction commitAction =
            new TransactionalAction() {
              public void execute() {
                PendingId pendingId = pendingIds.get(handle);
                if (pendingId.txs.decrementAndGet() < 1) {
                  pendingIds.remove(handle);
                }
                handle2ref.put(handle, newHandle2RefTxData.ref);
                ref2handle.put(newHandle2RefTxData.ref, handle);
              }
            };
        txContext.getAfterCommitActions().add(commitAction);
        txContext.getAfterRollbackActions().add(rollbackAction);
      }
    } else {
      reference = new ActivityHandleReference(handle, getLocalAddress(), new VMID().toString());
      handle2ref.put(handle, reference);
      ref2handle.put(reference, handle);
    }

    if (logger.isDebugEnabled()) {
      logger.debug(
          "Created activity handle reference "
              + reference
              + " for activity handle "
              + reference.getReference());
    }

    return reference;
  }