/**
   * Method to safely execute a function.
   *
   * @param connection
   * @param input The MappedRecord containing the input arguments.
   * @return The MappedRecord containing the results or null if the call fails.
   */
  public MappedRecord executeFunction(String returnTableKey) {
    /*
     * Create the connection and interaction
     */
    createConnectionInteraction();
    /*
     * Retrieve the mapped record
     */
    MappedRecord outputRecord = null;
    try {
      if (inputRecord == null) {
        getInputRecord();
      }
      outputRecord = (MappedRecord) interaction.execute(null, inputRecord);
    } catch (ResourceException e) {
      TransactionHelper.logAndThrowDataException(
          callingFunctionName, "Failure executing function: ", e);
    }
    if (outputRecord == null) {
      TransactionHelper.logAndThrowDataException(callingFunctionName, "Output record null ", null);
    }
    /*
     * Check for BAPI errors
     */
    TransactionHelper.errorMessagesReturned(
        validationMap, outputRecord, returnTableKey, this.callingFunctionName);

    return outputRecord;
  }
 @Override
 public Result call(final Http.Context context) throws Throwable {
   final TransactionHelper th = new TransactionHelper(context, this.configuration);
   final Result res;
   try {
     th.beforeInvocation();
     res = delegate.call(context);
     th.onInvocationSuccess();
   } catch (Exception e) {
     th.onInvocationException(e);
     throw e;
   } finally {
     th.invocationFinally();
   }
   return res;
 }
 /**
  * This method closes the interaction and the connection to a JRA resource.
  *
  * @return True if successful, false if not.
  */
 public void closeConnectionInteraction() {
   try {
     try {
       if (interaction != null) {
         interaction.close();
       }
     } catch (Throwable e) {
       TransactionHelper.logDataException(
           callingFunctionName, "Failure closing the interaction with: ", e);
     }
     if (connection != null) {
       connection.close();
     }
   } catch (Throwable e) {
     TransactionHelper.logDataException(
         callingFunctionName, "Failure closeConnectionInteraction: ", e);
   }
 }
  /**
   * This function is called in the load phase which is executed using the -load or -loadindex
   * argument. It is used for inserting users and resources. Any field/value pairs in the values
   * HashMap for an entity will be written into the specified entity set with the specified entity
   * key.
   *
   * @param entitySet The name of the entity set with the following two possible values: users and
   *     resources. BG passes these values in lower case. The implementation may manipulate the case
   *     to tailor it for the purposes of a data store.
   * @param entityPK The primary key of the entity to insert.
   * @param values A HashMap of field/value pairs to insert for the entity, these pairs are the
   *     other attributes for an entity and their values. The profile image is identified with the
   *     "pic" key attribute and the thumbnail image is identified with the "tpic" key attribute.
   * @param insertImage Identifies if images should be inserted for users. if set to true the code
   *     should populate each entity with an image; the size of the image is specified using the
   *     imagesize parameter.
   * @return Zero on success, a non-zero error code on error. See this class's description for a
   *     discussion of error codes. The code written for this function call should insert the entity
   *     and its attributes. The code is responsible for inserting the PK and the other attributes
   *     in the appropriate order.
   */
  @Override
  public int insertEntity(
      String entitySet,
      String entityPK,
      HashMap<String, ByteIterator> values,
      boolean insertImage) {
    /** Insert Users and Resources data using JSON-like data model. */
    JsonObject jsonObject = new JsonObject();
    for (Map.Entry<String, ByteIterator> entry : values.entrySet()) {
      if (!entry.getKey().equals("pic") && !entry.getKey().equals("tpic")) {
        jsonObject.add(entry.getKey(), new JsonPrimitive(entry.getValue().toString()));
      }
    }

    try {
      transactionHelper.writeUser(entityPK, jsonObject);
    } catch (ConnectionException | AbortException e) {
      e.printStackTrace();
      return -1;
    }

    /** Update Users data after inserting Resources. */
    if (entitySet.equals(RESOURCES)) {
      try {
        ByteIterator wallUserID = values.get(WALL_USER_ID);
        jsonObject = transactionHelper.readUser(wallUserID.toString());

        JsonArray jsonArray;
        if (jsonObject.has(RESOURCES)) {
          jsonArray = jsonObject.getAsJsonArray(RESOURCES);
        } else {
          jsonArray = new JsonArray();
        }
        jsonArray.add(new JsonPrimitive(entityPK));
        jsonObject.add(RESOURCES, jsonArray);

        transactionHelper.writeUser(wallUserID.toString(), jsonObject);
      } catch (ConnectionException | NotFoundException | AbortException e) {
        e.printStackTrace();
        return -1;
      }
    }
    return 0;
  }
  /**
   * This function is called in the benchmarking phase which is executed with the -t argument.
   *
   * <p>gets the list of friends for a member.
   *
   * @param requesterID The unique identifier of the user who wants to view profile owners friends.
   * @param profileOwnerID The id of the profile for which the friends are listed.
   * @param fields Contains the attribute names required for each friend. This can be set to null to
   *     retrieve all the friend information.
   * @param result A Vector of HashMaps, where each HashMap is a set field/value pairs for one
   *     friend.
   * @param insertImage If set to true the thumbnail images for the friends will be retrieved from
   *     the data store.
   * @param testMode If set to true the thumbnail images of friends will be written to the file
   *     system.
   * @return Zero on success, a non-zero error code on error. See this class's description for a
   *     discussion of error codes.
   *     <p>The code written for this function should retrieve the list of friends for the
   *     profileOwnerID. The information retrieved per friend depends on the fields specified in the
   *     fields set. if fields is set to null all profile information for the friends is retrieved
   *     and the result hashmap is populated. The friend's unique id should be inserted with the
   *     "userid" key into the result hashmap. The lack of this attribute or the lack of the
   *     attribute key in lower case causes BG to raise exceptions. In addition if the insertImage
   *     flag is set to true, the thumbnails for each friend's profile should be retrieved and
   *     inserted into the result hashmap using the "pic" key.
   */
  @Override
  public int listFriends(
      int requesterID,
      int profileOwnerID,
      Set<String> fields,
      Vector<HashMap<String, ByteIterator>> result,
      boolean insertImage,
      boolean testMode) {
    try {
      JsonObject ownerObject = transactionHelper.readUser(String.valueOf(profileOwnerID));

      if (ownerObject.has(CONFIRMED_FRIENDS)) {
        JsonArray jsonArray = ownerObject.getAsJsonArray(CONFIRMED_FRIENDS);
        for (JsonElement element : jsonArray) {
          String friendId = element.getAsJsonPrimitive().getAsString();

          /** Read all the friends. */
          JsonObject friendObject = transactionHelper.readUser(friendId);
          HashMap<String, ByteIterator> hashMap = new HashMap<>();

          if (fields == null) {
            for (Map.Entry<String, JsonElement> entry : friendObject.entrySet()) {
              StringByteIterator stringValue =
                  new StringByteIterator(entry.getValue().getAsJsonPrimitive().getAsString());
              hashMap.put(entry.getKey(), stringValue);
            }
          } else {
            for (String field : fields) {
              StringByteIterator stringValue =
                  new StringByteIterator(friendObject.get(field).getAsString());
              hashMap.put(field, stringValue);
            }
          }
          result.add(hashMap);
        }
      }
    } catch (ConnectionException | NotFoundException e) {
      e.printStackTrace();
      return -1;
    }

    return 0;
  }
  /**
   * This function is called in the benchmarking phase which is executed with the -t argument. Get
   * the profile object for a user.
   *
   * @param requesterID Unique identifier for the requester.
   * @param profileOwnerID unique profile owner's identifier.
   * @param result A HashMap with all data returned. These data are different user information
   *     within the profile such as friend count, friend request count, etc.
   * @param insertImage Identifies if the users have images in the database. If set to true the
   *     images for the users will be retrieved.
   * @param testMode If set to true images will be retrieved and stored on the file system. While
   *     running benchmarks this field should be set to false.
   * @return 0 on success a non-zero error code on error. See this class's description for a
   *     discussion of error codes.
   *     <p>The code written for this function retrieves the user's profile details, friendcount
   *     (number of friends for that user) and resourcecount (number of resources inserted on that
   *     user's wall). In addition if the requesterID is equal to the profileOwnerID, the
   *     pendingcount (number of pending friend requests) needs to be returned as well.
   *     <p>If the insertImage is set to true, the image for the profileOwnerID will be rertrieved.
   *     The insertImage should be set to true only if the user entity has an image in the database.
   *     <p>The friendcount, resourcecount, pendingcount should be put into the results HashMap with
   *     the following keys: "friendcount", "resourcecount" and "pendingcount", respectively. Lack
   *     of these attributes or not returning the attribute keys in lower case causes BG to raise
   *     exceptions. In addition, all other attributes of the profile need to be added to the result
   *     hashmap with the attribute names being the keys and the attribute values being the values
   *     in the hashmap.
   *     <p>If images exist for users, they should be converted to bytearrays and added to the
   *     result hashmap.
   */
  @Override
  public int viewProfile(
      int requesterID,
      int profileOwnerID,
      HashMap<String, ByteIterator> result,
      boolean insertImage,
      boolean testMode) {
    JsonObject jsonObject;
    try {
      jsonObject = transactionHelper.readUser(String.valueOf(profileOwnerID));
    } catch (ConnectionException | NotFoundException e) {
      e.printStackTrace();
      return -1;
    }

    /** Dump data to result. */
    jsonObject
        .entrySet()
        .forEach(
            entry -> {
              if (!entry.getKey().equals(PENDING_FRIENDS)
                  && !entry.getKey().equals(CONFIRMED_FRIENDS)
                  && !entry.getKey().equals(RESOURCES)) {
                result.put(entry.getKey(), new StringByteIterator(entry.getValue().getAsString()));
              }
            });

    /** Count friends. */
    int friendCount = 0;
    if (jsonObject.has(CONFIRMED_FRIENDS)) {
      JsonArray jsonArray = jsonObject.getAsJsonArray(CONFIRMED_FRIENDS);
      friendCount = jsonArray.size();
    }
    result.put(FRIEND_COUNT, new ObjectByteIterator(String.valueOf(friendCount).getBytes()));

    /** Count resources. */
    int resourceCount = 0;
    if (jsonObject.has(RESOURCES)) {
      JsonArray jsonArray = jsonObject.getAsJsonArray(RESOURCES);
      resourceCount = jsonArray.size();
    }
    result.put(RESOURCE_COUNT, new ObjectByteIterator(String.valueOf(resourceCount).getBytes()));

    /** Pending friendships. */
    if (requesterID == profileOwnerID) {
      int pendingCount = 0;
      JsonElement jsonElement = jsonObject.get(PENDING_FRIENDS);
      if (jsonElement != null) {
        pendingCount = jsonElement.getAsJsonArray().size();
      }
      result.put(PENDING_COUNT, new ObjectByteIterator(String.valueOf(pendingCount).getBytes()));
    }
    return 0;
  }
 /**
  * This method opens a connection and the interaction.
  *
  * @return True if successful, false if not.
  */
 public void createConnectionInteraction() {
   if (this.connectionFactory == null) {
     TransactionHelper.logAndThrowDataException(
         callingFunctionName,
         "Failure looking up a connection factory for resource name: " + resourceName,
         null);
   }
   try {
     /*
      * Get a connection from the connection factory. Requires that
      * setupConnectionFactory was called successfully beforehand.
      */
     connection = connectionFactory.getConnection();
     /*
      * Create an interaction object to make a call to an SAP system
      * where you can send your business data and receive data back:
      */
     interaction = connection.createInteraction();
   } catch (Throwable e) {
     TransactionHelper.logAndThrowDataException(
         callingFunctionName, "Failure getting connection for resource name: " + resourceName, e);
   }
 }
 /**
  * This method safely looks up a record factory from the connection factory.
  *
  * <p>If the JRA connection is going to fail, it will fail in this step. For example, if the
  * service account password expires, then there will be an authorization error in the
  * createMappedRecord call.
  *
  * @param transactionObject
  * @param functionName The BAPI name for which we get the mapped record.
  * @return A RecordFactory object or null if there is an error.
  */
 public MappedRecord getInputRecord() {
   try {
     if (null == inputRecord) {
       inputRecord = recordFactory.createMappedRecord(functionName);
     }
   } catch (Throwable e) {
     /*
      * Experience has shown that, if the JRA connection fails, it fails
      * in this method. Usually the problem is that the service account
      * is no longer authenticating.
      */
     TransactionHelper.logAndThrowDataException(
         callingFunctionName,
         "Failure getting a mapped record for function: " + functionName + " in resource: ",
         e);
   }
   return inputRecord;
 }
  @Override
  public void deleteFinancialSource(int id) {
    EntityManager entityManager = this.getSession().getEntityManager();

    TransactionScope transactionScope = this.beginTransaction();

    try {
      entityManager
          .createQuery("DELETE FROM FinancialSource fs WHERE fs.id :finId")
          .setParameter("finId", id)
          .executeUpdate();

      transactionScope.commit();
    } catch (PersistenceException ex) {
      throw TransactionHelper.translateException(ex);
    } finally {
      transactionScope.dispose();
    }
  }
  /**
   * Added by Kunal Jaggi Method to safely execute a function.
   *
   * @param input The MappedRecord containing the input arguments.
   * @return The MappedRecord containing the results or null if the call fails.
   */
  public MappedRecord executeFunction(MappedRecord input) {
    /*
     * Create the connection and interaction
     */
    createConnectionInteraction();
    /*
     * Retrieve the mapped record
     */
    MappedRecord outputRecord = null;

    try {
      outputRecord = (MappedRecord) interaction.execute(null, input);
    } catch (ResourceException e) {
      TransactionHelper.logAndThrowDataException(
          callingFunctionName,
          "Failure executing function: " + functionName + " in resource: " + resourceName,
          e);
    }

    return outputRecord;
  }