/**
   * Saves and outgoing transaction into the database
   *
   * @param hash
   * @param cryptoStatus
   * @param blockDepth
   * @param addressTo
   * @param addressFrom
   * @param value
   * @param op_Return
   * @param protocolStatus
   * @throws CantExecuteDatabaseOperationException
   */
  public void saveNewOutgoingTransaction(
      String hash,
      CryptoStatus cryptoStatus,
      int blockDepth,
      CryptoAddress addressTo,
      CryptoAddress addressFrom,
      long value,
      String op_Return,
      ProtocolStatus protocolStatus)
      throws CantExecuteDatabaseOperationException {
    DatabaseTable databaseTable =
        database.getTable(BitcoinCryptoNetworkDatabaseConstants.OUTGOING_TRANSACTIONS_TABLE_NAME);
    DatabaseTableRecord record = databaseTable.getEmptyRecord();

    /** generates the trx_id */
    UUID trxId = UUID.randomUUID();

    record.setUUIDValue(
        BitcoinCryptoNetworkDatabaseConstants.INCOMING_TRANSACTIONS_TRX_ID_COLUMN_NAME, trxId);
    record.setStringValue(
        BitcoinCryptoNetworkDatabaseConstants.INCOMING_TRANSACTIONS_HASH_COLUMN_NAME, hash);
    record.setStringValue(
        BitcoinCryptoNetworkDatabaseConstants.INCOMING_TRANSACTIONS_CRYPTO_STATUS_COLUMN_NAME,
        cryptoStatus.getCode());
    record.setIntegerValue(
        BitcoinCryptoNetworkDatabaseConstants.INCOMING_TRANSACTIONS_BLOCK_DEPTH_COLUMN_NAME,
        blockDepth);
    record.setStringValue(
        BitcoinCryptoNetworkDatabaseConstants.INCOMING_TRANSACTIONS_ADDRESS_TO_COLUMN_NAME,
        addressTo.getAddress());
    record.setStringValue(
        BitcoinCryptoNetworkDatabaseConstants.INCOMING_TRANSACTIONS_ADDRESS_FROM_COLUMN_NAME,
        addressFrom.getAddress());
    record.setDoubleValue(
        BitcoinCryptoNetworkDatabaseConstants.INCOMING_TRANSACTIONS_VALUE_COLUMN_NAME, value);
    record.setStringValue(
        BitcoinCryptoNetworkDatabaseConstants.INCOMING_TRANSACTIONS_OP_RETURN_COLUMN_NAME,
        op_Return);
    record.setStringValue(
        BitcoinCryptoNetworkDatabaseConstants.INCOMING_TRANSACTIONS_PROTOCOL_STATUS_COLUMN_NAME,
        protocolStatus.getCode());
    record.setStringValue(
        BitcoinCryptoNetworkDatabaseConstants.INCOMING_TRANSACTIONS_LAST_UPDATE_COLUMN_NAME,
        getCurrentDateTime());
    try {
      databaseTable.insertRecord(record);
    } catch (CantInsertRecordException e) {
      StringBuilder outputMessage =
          new StringBuilder(
              "There was an error inserting a new transaction in the Outgoing Transactions Table. Transaction record is:");
      outputMessage.append(System.lineSeparator());
      outputMessage.append(XMLParser.parseObject(record));

      throw new CantExecuteDatabaseOperationException(
          CantExecuteDatabaseOperationException.DEFAULT_MESSAGE,
          e,
          outputMessage.toString(),
          "database issue.");
    }
  }
  /**
   * Sets the new depth of the current Used keys value
   *
   * @param accountId
   * @param newValue
   * @throws CantExecuteDatabaseOperationException
   */
  public void setNewCurrentUsedKeyValue(int accountId, int newValue)
      throws CantExecuteDatabaseOperationException {
    DatabaseTable databaseTable =
        getDatabaseTable(AssetsOverBitcoinCryptoVaultDatabaseConstants.KEY_MAINTENANCE_TABLE_NAME);

    /** I will check to see if I already have a value for this account so i can updated it. */
    databaseTable.addStringFilter(
        AssetsOverBitcoinCryptoVaultDatabaseConstants.KEY_MAINTENANCE_ACCOUNT_ID_COLUMN_NAME,
        String.valueOf(accountId),
        DatabaseFilterType.EQUAL);
    try {
      databaseTable.loadToMemory();
    } catch (CantLoadTableToMemoryException e) {
      throwLoadToMemoryException(e, databaseTable.getTableName());
    }

    DatabaseTableRecord record = null;
    try {
      if (databaseTable.getRecords().size() == 0) {
        // I will insert the new value
        record = databaseTable.getEmptyRecord();
        record.setIntegerValue(
            AssetsOverBitcoinCryptoVaultDatabaseConstants.KEY_MAINTENANCE_ACCOUNT_ID_COLUMN_NAME,
            accountId);
        record.setIntegerValue(
            AssetsOverBitcoinCryptoVaultDatabaseConstants
                .KEY_MAINTENANCE_GENERATED_KEYS_COLUMN_NAME,
            0);
        record.setIntegerValue(
            AssetsOverBitcoinCryptoVaultDatabaseConstants.KEY_MAINTENANCE_USED_KEYS_COLUMN_NAME,
            newValue);

        databaseTable.insertRecord(record);
      } else {
        // I will update the existing value
        record = databaseTable.getRecords().get(0);
        record.setIntegerValue(
            AssetsOverBitcoinCryptoVaultDatabaseConstants.KEY_MAINTENANCE_USED_KEYS_COLUMN_NAME,
            newValue);
        databaseTable.updateRecord(record);
      }
    } catch (CantInsertRecordException | CantUpdateRecordException e) {
      StringBuilder outputMessage =
          new StringBuilder(
              "There was an error inserting or updating the key depth value in the database.");
      outputMessage.append(System.lineSeparator());
      outputMessage.append("The record is:");
      outputMessage.append(System.lineSeparator());
      outputMessage.append(XMLParser.parseObject(record));

      throw new CantExecuteDatabaseOperationException(
          CantExecuteDatabaseOperationException.DEFAULT_MESSAGE,
          e,
          outputMessage.toString(),
          "database issue");
    }
  }
  /**
   * Sets the active network type that the Bitcoin Network will need to listen too. Network types
   * are MainNet, TestNet and RegTest
   *
   * @param blockchainNetworkType
   * @throws CantExecuteDatabaseOperationException
   */
  public void setActiveNetworkType(BlockchainNetworkType blockchainNetworkType)
      throws CantExecuteDatabaseOperationException {
    DatabaseTable databaseTable =
        getDatabaseTable(AssetsOverBitcoinCryptoVaultDatabaseConstants.ACTIVE_NETWORKS_TABLE_NAME);

    /** I will check to see if I already have a value for this account so i can updated it. */
    databaseTable.addStringFilter(
        AssetsOverBitcoinCryptoVaultDatabaseConstants.ACTIVE_NETWORKS_NETWORKTYPE_COLUMN_NAME,
        blockchainNetworkType.getCode(),
        DatabaseFilterType.EQUAL);
    try {
      databaseTable.loadToMemory();
    } catch (CantLoadTableToMemoryException e) {
      throwLoadToMemoryException(e, databaseTable.getTableName());
    }
    DatabaseTableRecord record = null;
    String date = new SimpleDateFormat("yyyyMMdd_HHmmss").format(Calendar.getInstance().getTime());
    try {
      if (databaseTable.getRecords().size() == 0) {
        // I will insert the new value
        record = databaseTable.getEmptyRecord();
        record.setStringValue(
            AssetsOverBitcoinCryptoVaultDatabaseConstants.ACTIVE_NETWORKS_NETWORKTYPE_COLUMN_NAME,
            blockchainNetworkType.getCode());
        record.setStringValue(
            AssetsOverBitcoinCryptoVaultDatabaseConstants
                .ACTIVE_NETWORKS_ACTIVATION_DATE_COLUMN_NAME,
            date);
        databaseTable.insertRecord(record);
      } else {
        // I will update the existing value
        record = databaseTable.getRecords().get(0);
        record.setStringValue(
            AssetsOverBitcoinCryptoVaultDatabaseConstants
                .ACTIVE_NETWORKS_ACTIVATION_DATE_COLUMN_NAME,
            date);
        databaseTable.updateRecord(record);
      }
    } catch (CantInsertRecordException | CantUpdateRecordException e) {
      StringBuilder outputMessage =
          new StringBuilder(
              "There was an error inserting or updating the network type in the database.");
      outputMessage.append(System.lineSeparator());
      outputMessage.append("The record is:");
      outputMessage.append(System.lineSeparator());
      outputMessage.append(XMLParser.parseObject(record));

      throw new CantExecuteDatabaseOperationException(
          CantExecuteDatabaseOperationException.DEFAULT_MESSAGE,
          e,
          outputMessage.toString(),
          "database issue");
    }
  }
  /**
   * Sets the new value of how many keys have been generated by the Key Maintainer
   *
   * @param accountId the account id
   * @param value the amount of keys generated. This value accumulates to the one that existed.
   * @throws CantExecuteDatabaseOperationException
   */
  public void setGeneratedKeysValue(int accountId, int value)
      throws CantExecuteDatabaseOperationException {
    DatabaseTable databaseTable =
        getDatabaseTable(AssetsOverBitcoinCryptoVaultDatabaseConstants.KEY_MAINTENANCE_TABLE_NAME);

    /**
     * first I see if we already have records for this account by setting a filter and getting the
     * values
     */
    databaseTable.addStringFilter(
        AssetsOverBitcoinCryptoVaultDatabaseConstants.KEY_MAINTENANCE_ACCOUNT_ID_COLUMN_NAME,
        String.valueOf(accountId),
        DatabaseFilterType.EQUAL);
    try {
      databaseTable.loadToMemory();
    } catch (CantLoadTableToMemoryException e) {
      throwLoadToMemoryException(e, databaseTable.getTableName());
    }

    /** I will insert or update the record */
    DatabaseTableRecord record = null;
    try {
      if (databaseTable.getRecords().size() == 0) {
        // insert
        record = databaseTable.getEmptyRecord();
        record.setIntegerValue(
            AssetsOverBitcoinCryptoVaultDatabaseConstants.KEY_MAINTENANCE_ACCOUNT_ID_COLUMN_NAME,
            accountId);
        record.setIntegerValue(
            AssetsOverBitcoinCryptoVaultDatabaseConstants
                .KEY_MAINTENANCE_GENERATED_KEYS_COLUMN_NAME,
            value);
        record.setIntegerValue(
            AssetsOverBitcoinCryptoVaultDatabaseConstants.KEY_MAINTENANCE_USED_KEYS_COLUMN_NAME, 0);
        databaseTable.insertRecord(record);
      } else {
        // update
        record = databaseTable.getRecords().get(0);
        record.setIntegerValue(
            AssetsOverBitcoinCryptoVaultDatabaseConstants
                .KEY_MAINTENANCE_GENERATED_KEYS_COLUMN_NAME,
            value);
        databaseTable.updateRecord(record);
      }
    } catch (CantInsertRecordException | CantUpdateRecordException e) {
      StringBuilder outputMessage =
          new StringBuilder("There was an error inserting or updating the following table: ");
      outputMessage.append(databaseTable.getTableName());
      outputMessage.append(System.lineSeparator());
      outputMessage.append("The record is:");
      outputMessage.append(System.lineSeparator());
      outputMessage.append(XMLParser.parseObject(record));
    }
  }
  /**
   * Inserts into the database new statistics from the key maintainer
   *
   * @param hierarchyAccountId
   * @param date
   * @param currentGeneratedKeys
   * @param currentUsedKeys
   * @param currentThreshold
   * @throws CantExecuteDatabaseOperationException
   */
  private void insertNewMaintainerStatistics(
      int hierarchyAccountId,
      String date,
      int currentGeneratedKeys,
      int currentUsedKeys,
      int currentThreshold)
      throws CantExecuteDatabaseOperationException {
    DatabaseTable databaseTable =
        getDatabaseTable(
            AssetsOverBitcoinCryptoVaultDatabaseConstants.KEY_MAINTENANCE_MONITOR_TABLE_NAME);

    DatabaseTableRecord databaseTableRecord = databaseTable.getEmptyRecord();
    databaseTableRecord.setIntegerValue(
        AssetsOverBitcoinCryptoVaultDatabaseConstants
            .KEY_MAINTENANCE_MONITOR_EXECUTION_NUMBER_COLUMN_NAME,
        1);
    databaseTableRecord.setIntegerValue(
        AssetsOverBitcoinCryptoVaultDatabaseConstants
            .KEY_MAINTENANCE_MONITOR_ACCOUNT_ID_COLUMN_NAME,
        hierarchyAccountId);
    databaseTableRecord.setStringValue(
        AssetsOverBitcoinCryptoVaultDatabaseConstants
            .KEY_MAINTENANCE_MONITOR_EXECUTION_DATE_COLUMN_NAME,
        date);
    databaseTableRecord.setIntegerValue(
        AssetsOverBitcoinCryptoVaultDatabaseConstants
            .KEY_MAINTENANCE_MONITOR_GENERATED_KEYS_COLUMN_NAME,
        currentGeneratedKeys);
    databaseTableRecord.setIntegerValue(
        AssetsOverBitcoinCryptoVaultDatabaseConstants.KEY_MAINTENANCE_MONITOR_USED_KEYS_COLUMN_NAME,
        currentUsedKeys);
    databaseTableRecord.setIntegerValue(
        AssetsOverBitcoinCryptoVaultDatabaseConstants.KEY_MAINTENANCE_MONITOR_THRESHOLD_COLUMN_NAME,
        currentThreshold);

    try {
      databaseTable.insertRecord(databaseTableRecord);
    } catch (CantInsertRecordException e) {
      /** I will create the output meessage */
      StringBuilder outputMessage =
          new StringBuilder("there was an error inserting a new record into ");
      outputMessage.append(
          AssetsOverBitcoinCryptoVaultDatabaseConstants.KEY_MAINTENANCE_MONITOR_TABLE_NAME);
      outputMessage.append(System.lineSeparator());
      outputMessage.append("The record to insert is: ");
      outputMessage.append(XMLParser.parseObject(databaseTableRecord));

      throw new CantExecuteDatabaseOperationException(
          CantExecuteDatabaseOperationException.DEFAULT_MESSAGE,
          e,
          outputMessage.toString(),
          "Database issue");
    }
  }
  /**
   * Updates existing key maintainer statistics.
   *
   * @param date
   * @param currentGeneratedKeys
   * @param currentUsedKeys
   * @param currentThreshold
   * @throws CantExecuteDatabaseOperationException
   */
  private void updateExistingMaintainerStatistics(
      DatabaseTableRecord recordToUpdate,
      String date,
      int currentGeneratedKeys,
      int currentUsedKeys,
      int currentThreshold)
      throws CantExecuteDatabaseOperationException {
    int previousExecNumber =
        recordToUpdate.getIntegerValue(
            AssetsOverBitcoinCryptoVaultDatabaseConstants
                .KEY_MAINTENANCE_MONITOR_EXECUTION_NUMBER_COLUMN_NAME);
    recordToUpdate.setIntegerValue(
        AssetsOverBitcoinCryptoVaultDatabaseConstants
            .KEY_MAINTENANCE_MONITOR_EXECUTION_NUMBER_COLUMN_NAME,
        previousExecNumber + 1);
    recordToUpdate.setStringValue(
        AssetsOverBitcoinCryptoVaultDatabaseConstants
            .KEY_MAINTENANCE_MONITOR_EXECUTION_DATE_COLUMN_NAME,
        date);
    recordToUpdate.setIntegerValue(
        AssetsOverBitcoinCryptoVaultDatabaseConstants
            .KEY_MAINTENANCE_MONITOR_GENERATED_KEYS_COLUMN_NAME,
        currentGeneratedKeys);
    recordToUpdate.setIntegerValue(
        AssetsOverBitcoinCryptoVaultDatabaseConstants.KEY_MAINTENANCE_MONITOR_USED_KEYS_COLUMN_NAME,
        currentUsedKeys);
    recordToUpdate.setIntegerValue(
        AssetsOverBitcoinCryptoVaultDatabaseConstants.KEY_MAINTENANCE_MONITOR_THRESHOLD_COLUMN_NAME,
        currentThreshold);

    try {
      getDatabaseTable(
              AssetsOverBitcoinCryptoVaultDatabaseConstants.KEY_MAINTENANCE_MONITOR_TABLE_NAME)
          .updateRecord(recordToUpdate);
    } catch (CantUpdateRecordException e) {
      /** I will create the output meessage */
      StringBuilder outputMessage =
          new StringBuilder("there was an error updating an existing record from ");
      outputMessage.append(
          AssetsOverBitcoinCryptoVaultDatabaseConstants.KEY_MAINTENANCE_MONITOR_TABLE_NAME);
      outputMessage.append(System.lineSeparator());
      outputMessage.append("The record to insert is: ");
      outputMessage.append(XMLParser.parseObject(recordToUpdate));

      throw new CantExecuteDatabaseOperationException(
          CantExecuteDatabaseOperationException.DEFAULT_MESSAGE,
          e,
          outputMessage.toString(),
          "Database issue");
    }
  }
 @Override
 public Language getLanguageFromXmlString(String languageStructure)
     throws CantGetLanguageException {
   try {
     Language language = new Language();
     language = (Language) XMLParser.parseXML(languageStructure, language);
     return language;
   } catch (Exception e) {
     errorManager.reportUnexpectedPluginException(
         Plugins.BITDUBAI_WALLET_LANGUAGE_MIDDLEWARE,
         UnexpectedPluginExceptionSeverity.DISABLES_SOME_FUNCTIONALITY_WITHIN_THIS_PLUGIN,
         e);
     throw new CantGetLanguageException(
         CantGetLanguageException.DEFAULT_MESSAGE, e, "Cant get language", "");
   }
 }
 @Override
 public String getLanguageXmlFromClassStructure(Language language)
     throws CantGetLanguageException {
   try {
     String xml = null;
     if (language != null) {
       xml = XMLParser.parseObject(language);
     }
     return xml;
   } catch (Exception e) {
     errorManager.reportUnexpectedPluginException(
         Plugins.BITDUBAI_WALLET_LANGUAGE_MIDDLEWARE,
         UnexpectedPluginExceptionSeverity.DISABLES_SOME_FUNCTIONALITY_WITHIN_THIS_PLUGIN,
         e);
     throw new CantGetLanguageException(
         CantGetLanguageException.DEFAULT_MESSAGE, e, "Cant get language", "");
   }
 }
  /**
   * Marks to RECEPTION_NOTIFIED the protocol status of this Outgoing transaction if found.
   *
   * @param transactionID
   */
  private void confirmOutgoingTransactionReception(UUID transactionID)
      throws CantExecuteDatabaseOperationException {
    DatabaseTable databaseTable =
        database.getTable(BitcoinCryptoNetworkDatabaseConstants.OUTGOING_TRANSACTIONS_TABLE_NAME);
    databaseTable.setStringFilter(
        BitcoinCryptoNetworkDatabaseConstants.OUTGOING_TRANSACTIONS_TRX_ID_COLUMN_NAME,
        transactionID.toString(),
        DatabaseFilterType.EQUAL);

    try {
      databaseTable.loadToMemory();
    } catch (CantLoadTableToMemoryException e) {
      throwLoadToMemoryException(e, databaseTable.getTableName());
    }

    /** set the value to RECEPTION_NOTIFIED and the Last_update_time to now */
    if (databaseTable.getRecords().size() > 0) {
      DatabaseTableRecord record = databaseTable.getRecords().get(0);
      record.setStringValue(
          BitcoinCryptoNetworkDatabaseConstants.OUTGOING_TRANSACTIONS_PROTOCOL_STATUS_COLUMN_NAME,
          ProtocolStatus.RECEPTION_NOTIFIED.getCode());
      record.setStringValue(
          BitcoinCryptoNetworkDatabaseConstants.OUTGOING_TRANSACTIONS_LAST_UPDATE_COLUMN_NAME,
          getCurrentDateTime());

      try {
        databaseTable.updateRecord(record);
      } catch (CantUpdateRecordException e) {
        StringBuilder errorOutput =
            new StringBuilder(
                "There was a problem setting to RECEPTION_NOTIFIED the following transaction:");
        errorOutput.append(System.lineSeparator());
        errorOutput.append(XMLParser.parseObject(record));
        throw new CantExecuteDatabaseOperationException(
            CantExecuteDatabaseOperationException.DEFAULT_MESSAGE,
            e,
            errorOutput.toString(),
            "database issue");
      }
    }
  }
 /**
  * i get the path and name of the file and i load it
  *
  * @param walletLanguage of the language you're trying to get
  * @return language class structure
  * @throws CantGetLanguageException
  * @throws LanguageNotFoundException
  */
 @Override
 public Language getLanguage(WalletLanguage walletLanguage)
     throws CantGetLanguageException, LanguageNotFoundException {
   if (walletLanguage != null) {
     try {
       String languageFileName = getLanguageFileName(walletLanguage);
       PluginTextFile pluginTextFile =
           pluginFileSystem.getTextFile(
               pluginId,
               WALLET_LANGUAGES_PATH,
               languageFileName,
               FilePrivacy.PRIVATE,
               FileLifeSpan.PERMANENT);
       pluginTextFile.loadFromMedia();
       String xml = pluginTextFile.getContent();
       Language language = new Language();
       language = (Language) XMLParser.parseXML(xml, language);
       return language;
     } catch (CantCreateFileException | CantLoadFileException e) {
       errorManager.reportUnexpectedPluginException(
           Plugins.BITDUBAI_WALLET_LANGUAGE_MIDDLEWARE,
           UnexpectedPluginExceptionSeverity.DISABLES_SOME_FUNCTIONALITY_WITHIN_THIS_PLUGIN,
           e);
       throw new CantGetLanguageException(
           CantGetLanguageException.DEFAULT_MESSAGE, e, "Cant get language", "");
     } catch (FileNotFoundException e) {
       errorManager.reportUnexpectedPluginException(
           Plugins.BITDUBAI_WALLET_LANGUAGE_MIDDLEWARE,
           UnexpectedPluginExceptionSeverity.DISABLES_SOME_FUNCTIONALITY_WITHIN_THIS_PLUGIN,
           e);
       throw new LanguageNotFoundException(
           LanguageNotFoundException.DEFAULT_MESSAGE, e, "Language not found.", "");
     }
   } else {
     throw new CantGetLanguageException(
         CantGetLanguageException.DEFAULT_MESSAGE, null, "Wallet Language is null.", "");
   }
 }
  /**
   * Inserts a new HierarchyAccount into the database
   *
   * @param hierarchyAccount
   * @throws CantExecuteDatabaseOperationException
   * @throws CantInsertRecordException
   */
  public void addNewHierarchyAccount(HierarchyAccount hierarchyAccount)
      throws CantExecuteDatabaseOperationException {
    DatabaseTable databaseTable =
        getDatabaseTable(AssetsOverBitcoinCryptoVaultDatabaseConstants.KEY_ACCOUNTS_TABLE_NAME);
    DatabaseTableRecord record = databaseTable.getEmptyRecord();

    record.setIntegerValue(
        AssetsOverBitcoinCryptoVaultDatabaseConstants.KEY_ACCOUNTS_ID_COLUMN_NAME,
        hierarchyAccount.getId());
    record.setStringValue(
        AssetsOverBitcoinCryptoVaultDatabaseConstants.KEY_ACCOUNTS_DESCRIPTION_COLUMN_NAME,
        hierarchyAccount.getDescription());
    record.setStringValue(
        AssetsOverBitcoinCryptoVaultDatabaseConstants.KEY_ACCOUNTS_TYPE_COLUMN_NAME,
        hierarchyAccount.getHierarchyAccountType().getCode());

    try {
      databaseTable.insertRecord(record);
    } catch (CantInsertRecordException e) {
      /**
       * if there was an error inserting the object, I will prepare the error message and throw it.
       */
      StringBuilder outputMessage =
          new StringBuilder("There was an error inserting a new HierarchyAccount value.");
      outputMessage.append(System.lineSeparator());
      outputMessage.append("HierarchyAccount value:");
      outputMessage.append(System.lineSeparator());
      outputMessage.append(XMLParser.parseObject(hierarchyAccount));

      throw new CantExecuteDatabaseOperationException(
          CantExecuteDatabaseOperationException.DEFAULT_MESSAGE,
          e,
          outputMessage.toString(),
          "A database error.");
    }
  }
    private void doTheMainTask() throws CannotSendContractHashException, CantUpdateRecordException {

      try {
        openContractBusinessTransactionDao =
            new OpenContractBusinessTransactionDao(pluginDatabaseSystem, pluginId, database);
        /** Check if exist in database new contracts to send */
        List<String> contractPendingToSubmitList =
            openContractBusinessTransactionDao.getPendingToSubmitContractHash();
        String contractXML;
        ContractPurchaseRecord purchaseContract = new ContractPurchaseRecord();
        ContractSaleRecord saleContract = new ContractSaleRecord();
        ContractType contractType;
        UUID transactionId;
        if (!contractPendingToSubmitList.isEmpty()) {
          for (String hashToSubmit : contractPendingToSubmitList) {
            System.out.println("OPEN CONTRACT - Hash to submit:\n" + hashToSubmit);
            contractXML = openContractBusinessTransactionDao.getContractXML(hashToSubmit);
            contractType = openContractBusinessTransactionDao.getContractType(hashToSubmit);
            transactionId = openContractBusinessTransactionDao.getTransactionId(hashToSubmit);
            switch (contractType) {
              case PURCHASE:
                purchaseContract =
                    (ContractPurchaseRecord) XMLParser.parseXML(contractXML, purchaseContract);
                transactionTransmissionManager.sendContractHashToCryptoBroker(
                    transactionId,
                    purchaseContract.getPublicKeyCustomer(),
                    purchaseContract.getPublicKeyBroker(),
                    hashToSubmit,
                    purchaseContract.getNegotiationId());
                break;
              case SALE:
                saleContract = (ContractSaleRecord) XMLParser.parseXML(contractXML, saleContract);
                transactionTransmissionManager.sendContractHashToCryptoCustomer(
                    transactionId,
                    saleContract.getPublicKeyBroker(),
                    saleContract.getPublicKeyCustomer(),
                    hashToSubmit,
                    saleContract.getNegotiationId());
                break;
            }
            // Update the ContractTransactionStatus
            openContractBusinessTransactionDao.updateContractTransactionStatus(
                hashToSubmit, ContractTransactionStatus.CHECKING_HASH);
          }
        }

        /** Check if pending contract to confirm */
        List<String> contractPendingToConfirmList =
            openContractBusinessTransactionDao.getPendingToConfirmContractHash();
        if (!contractPendingToConfirmList.isEmpty()) {
          for (String hashToSubmit : contractPendingToSubmitList) {
            System.out.println("OPEN CONTRACT - Hash to confirm:\n" + hashToSubmit);
            contractXML = openContractBusinessTransactionDao.getContractXML(hashToSubmit);
            contractType = openContractBusinessTransactionDao.getContractType(hashToSubmit);
            switch (contractType) {
              case PURCHASE:
                purchaseContract =
                    (ContractPurchaseRecord) XMLParser.parseXML(contractXML, purchaseContract);
                transactionTransmissionManager.sendTransactionNewStatusNotification(
                    purchaseContract.getPublicKeyCustomer(),
                    purchaseContract.getPublicKeyBroker(),
                    hashToSubmit,
                    ContractTransactionStatus.CONTRACT_CONFIRMED);
                break;
              case SALE:
                saleContract = (ContractSaleRecord) XMLParser.parseXML(contractXML, saleContract);
                transactionTransmissionManager.sendTransactionNewStatusNotification(
                    purchaseContract.getPublicKeyBroker(),
                    purchaseContract.getPublicKeyCustomer(),
                    hashToSubmit,
                    ContractTransactionStatus.CONTRACT_CONFIRMED);
                break;
            }
            // Update the ContractTransactionStatus
            openContractBusinessTransactionDao.updateContractTransactionStatus(
                hashToSubmit, ContractTransactionStatus.CONTRACT_CONFIRMED);
          }
        }

        /** Check if pending events */
        List<String> pendingEventsIdList = openContractBusinessTransactionDao.getPendingEvents();
        for (String eventId : pendingEventsIdList) {
          checkPendingEvent(eventId);
        }

      } catch (CantGetContractListException e) {
        throw new CannotSendContractHashException(
            e, "Sending contract hash", "Cannot get the contract list from database");
      } catch (UnexpectedResultReturnedFromDatabaseException e) {
        throw new CannotSendContractHashException(
            e, "Sending contract hash", "Unexpected result in database");
      } catch (CantSendBusinessTransactionHashException e) {
        throw new CannotSendContractHashException(
            e, "Sending contract hash", "Error in Transaction Transmission Network Service");
      }
    }
  /**
   * Update the crypto vault statistics when called to start monitoring the network.
   *
   * @param cryptoVault
   * @param monitoredPublicKeys
   * @throws CantExecuteDatabaseOperationException
   */
  public void updateCryptoVaultsStatistics(CryptoVaults cryptoVault, int monitoredPublicKeys)
      throws CantExecuteDatabaseOperationException {
    DatabaseTable databaseTable =
        database.getTable(BitcoinCryptoNetworkDatabaseConstants.CRYPTOVAULTS_STATS_TABLE_NAME);
    databaseTable.setStringFilter(
        BitcoinCryptoNetworkDatabaseConstants.CRYPTOVAULTS_STATS_CRYPTO_VAULT_COLUMN_NAME,
        cryptoVault.getCode(),
        DatabaseFilterType.EQUAL);
    /** I will check if I have the record to update it */
    try {
      databaseTable.loadToMemory();
    } catch (CantLoadTableToMemoryException e) {
      throwLoadToMemoryException(e, databaseTable.getTableName());
    }

    DatabaseTableRecord record = null;
    try {
      if (databaseTable.getRecords().size() == 0) {
        /** I will insert a new record */
        record = databaseTable.getEmptyRecord();
        record.setStringValue(
            BitcoinCryptoNetworkDatabaseConstants.CRYPTOVAULTS_STATS_CRYPTO_VAULT_COLUMN_NAME,
            cryptoVault.getCode());
        record.setStringValue(
            BitcoinCryptoNetworkDatabaseConstants
                .CRYPTOVAULTS_STATS_LAST_CONNECTION_REQUEST_COLUMN_NAME,
            getCurrentDateTime());
        record.setIntegerValue(
            BitcoinCryptoNetworkDatabaseConstants
                .CRYPTOVAULTS_STATS_MONITORED_PUBLICKEYS_COLUMN_NAME,
            monitoredPublicKeys);

        databaseTable.insertRecord(record);
      } else {
        /** I will update an existing record. */
        record = databaseTable.getRecords().get(0);
        record.setStringValue(
            BitcoinCryptoNetworkDatabaseConstants
                .CRYPTOVAULTS_STATS_LAST_CONNECTION_REQUEST_COLUMN_NAME,
            getCurrentDateTime());
        record.setIntegerValue(
            BitcoinCryptoNetworkDatabaseConstants
                .CRYPTOVAULTS_STATS_MONITORED_PUBLICKEYS_COLUMN_NAME,
            monitoredPublicKeys);

        databaseTable.updateRecord(record);
      }
    } catch (CantInsertRecordException | CantUpdateRecordException e) {
      StringBuilder outputMessage =
          new StringBuilder("There was an error inserting or updating a record in table ");
      outputMessage.append(databaseTable.getTableName());
      outputMessage.append("Record is:");
      outputMessage.append(System.lineSeparator());
      outputMessage.append(XMLParser.parseObject(record));

      throw new CantExecuteDatabaseOperationException(
          CantExecuteDatabaseOperationException.DEFAULT_MESSAGE,
          e,
          outputMessage.toString(),
          "database issue.");
    }
  }
  /**
   * (non-javadoc)
   *
   * @see FermatMessageProcessor#processingMessage(FermatMessage, JsonObject)
   */
  @Override
  public void processingMessage(FermatMessage fermatMessage, JsonObject jsonMsjContent) {

    try {

      /*
       * Get the XML representation of the Digital Asset Metadata
       */
      String digitalAssetMetadataXml =
          jsonMsjContent.get(AssetTransmissionJsonAttNames.DIGITAL_ASSET_METADATA).getAsString();
      PlatformComponentType senderType =
          gson.fromJson(
              jsonMsjContent.get(AssetTransmissionJsonAttNames.SENDER_TYPE).getAsString(),
              PlatformComponentType.class);
      PlatformComponentType receiverType =
          gson.fromJson(
              jsonMsjContent.get(AssetTransmissionJsonAttNames.RECEIVER_TYPE).getAsString(),
              PlatformComponentType.class);

      /*
       * Convert the xml to object
       */
      DigitalAssetMetadata digitalAssetMetadata =
          (DigitalAssetMetadata)
              XMLParser.parseXML(digitalAssetMetadataXml, new DigitalAssetMetadata());

      /*
       * Construct a new digitalAssetMetadataTransaction
       */
      DigitalAssetMetadataTransactionImpl digitalAssetMetadataTransaction =
          new DigitalAssetMetadataTransactionImpl();
      digitalAssetMetadataTransaction.setGenesisTransaction(
          digitalAssetMetadata.getGenesisTransaction());
      digitalAssetMetadataTransaction.setSenderId(fermatMessage.getSender());
      digitalAssetMetadataTransaction.setSenderType(senderType);
      digitalAssetMetadataTransaction.setReceiverId(fermatMessage.getReceiver());
      digitalAssetMetadataTransaction.setReceiverType(receiverType);
      digitalAssetMetadataTransaction.setDigitalAssetMetadata(digitalAssetMetadata);
      digitalAssetMetadataTransaction.setDistributionStatus(DistributionStatus.ASSET_DISTRIBUTED);
      digitalAssetMetadataTransaction.setType(
          DigitalAssetMetadataTransactionType.META_DATA_TRANSMIT);
      digitalAssetMetadataTransaction.setProcessed(
          DigitalAssetMetadataTransactionImpl.NO_PROCESSED);

      /*
       * Save into data base for audit control
       */
      getAssetTransmissionNetworkServicePluginRoot()
          .getDigitalAssetMetaDataTransactionDao()
          .create(digitalAssetMetadataTransaction);

      /*
       * Mark the message as read
       */
      ((FermatMessageCommunication) fermatMessage)
          .setFermatMessagesStatus(FermatMessagesStatus.READ);
      ((CommunicationNetworkServiceConnectionManager)
              getAssetTransmissionNetworkServicePluginRoot().getNetworkServiceConnectionManager())
          .getIncomingMessageDao()
          .update(fermatMessage);

      /*
       * Notify to the interested
       */
      FermatEvent event =
          getAssetTransmissionNetworkServicePluginRoot()
              .getEventManager()
              .getNewEvent(EventType.RECEIVED_NEW_DIGITAL_ASSET_METADATA_NOTIFICATION);
      event.setSource(AssetTransmissionNetworkServicePluginRoot.EVENT_SOURCE);
      getAssetTransmissionNetworkServicePluginRoot().getEventManager().raiseEvent(event);

    } catch (Exception e) {
      getAssetTransmissionNetworkServicePluginRoot()
          .getErrorManager()
          .reportUnexpectedPluginException(
              Plugins.BITDUBAI_DAP_ASSET_TRANSMISSION_NETWORK_SERVICE,
              UnexpectedPluginExceptionSeverity.DISABLES_SOME_FUNCTIONALITY_WITHIN_THIS_PLUGIN,
              e);
    }
  }
  // CREATE SEND NEW NEGOTIATION TRANSACTION
  public void createCustomerBrokerCloseNegotiationTransaction(
      UUID transactionId,
      Negotiation negotiation,
      NegotiationType negotiationType,
      NegotiationTransactionStatus statusTransaction)
      throws CantRegisterCustomerBrokerCloseNegotiationTransactionException {

    Date time = new Date();
    long timestamp = time.getTime();
    String negotiationXML = XMLParser.parseObject(negotiation);

    try {

      DatabaseTable table =
          this.database.getTable(
              CustomerBrokerCloseNegotiationTransactionDatabaseConstants
                  .CUSTOMER_BROKER_CLOSE_TABLE_NAME);
      DatabaseTableRecord record = table.getEmptyRecord();

      record.setUUIDValue(
          CustomerBrokerCloseNegotiationTransactionDatabaseConstants
              .CUSTOMER_BROKER_CLOSE_TRANSACTION_ID_COLUMN_NAME,
          transactionId);
      record.setUUIDValue(
          CustomerBrokerCloseNegotiationTransactionDatabaseConstants
              .CUSTOMER_BROKER_CLOSE_NEGOTIATION_ID_COLUMN_NAME,
          negotiation.getNegotiationId());
      record.setStringValue(
          CustomerBrokerCloseNegotiationTransactionDatabaseConstants
              .CUSTOMER_BROKER_CLOSE_PUBLIC_KEY_BROKER_COLUMN_NAME,
          negotiation.getBrokerPublicKey());
      record.setStringValue(
          CustomerBrokerCloseNegotiationTransactionDatabaseConstants
              .CUSTOMER_BROKER_CLOSE_PUBLIC_KEY_CUSTOMER_COLUMN_NAME,
          negotiation.getCustomerPublicKey());
      record.setStringValue(
          CustomerBrokerCloseNegotiationTransactionDatabaseConstants
              .CUSTOMER_BROKER_CLOSE_STATUS_COLUMN_NAME,
          statusTransaction.getCode());
      record.setStringValue(
          CustomerBrokerCloseNegotiationTransactionDatabaseConstants
              .CUSTOMER_BROKER_CLOSE_NEGOTIATION_TYPE_COLUMN_NAME,
          negotiationType.getCode());
      record.setStringValue(
          CustomerBrokerCloseNegotiationTransactionDatabaseConstants
              .CUSTOMER_BROKER_CLOSE_NEGOTIATION_XML_COLUMN_NAME,
          negotiationXML);
      record.setLongValue(
          CustomerBrokerCloseNegotiationTransactionDatabaseConstants
              .CUSTOMER_BROKER_CLOSE_TIMESTAMP_COLUMN_NAME,
          timestamp);

      table.insertRecord(record);

      if (statusTransaction.getCode()
          == NegotiationTransactionStatus.PENDING_SUBMIT_CONFIRM.getCode()) {
        System.out.print(
            "\n\n**** 22) MOCK NEGOTIATION TRANSACTION - CUSTOMER BROKER CLOSE - DAO. CONFIRM negotiationType: "
                + negotiationType.getCode()
                + " transactionId: "
                + transactionId
                + " ****\n");
      } else {
        System.out.print(
            "\n\n**** 4) MOCK NEGOTIATION TRANSACTION - CUSTOMER BROKER CLOSE - DAO. NEGOTIATION negotiationType: "
                + negotiationType.getCode()
                + "transactionId: "
                + transactionId
                + " ****\n");
      }

    } catch (CantInsertRecordException e) {
      throw new CantRegisterCustomerBrokerCloseNegotiationTransactionException(
          e.getMessage(),
          e,
          "customer broker close Negotiation Transaction",
          "Cant create new customer broker close Negotiation Transaction, insert database problems.");
    } catch (Exception e) {
      throw new CantRegisterCustomerBrokerCloseNegotiationTransactionException(
          e.getMessage(),
          FermatException.wrapException(e),
          "customer broker close Negotiation Transaction",
          "Cant create new customer broker close Negotiation Transaction, unknown failure.");
    }
  }
Beispiel #16
0
 /**
  * This method returns a String in XML format containing all this object information
  *
  * @return
  */
 public String toString() {
   return XMLParser.parseObject(this);
 }
  /**
   * Updates the execution statistics of the event Agent it will insert a new record if we have
   * pending transactions, and update the existing value if we have zero transactions.
   *
   * @param pendingIncoming
   * @param pendingOutgoing
   */
  public void updateEventAgentStats(int pendingIncoming, int pendingOutgoing)
      throws CantExecuteDatabaseOperationException {
    DatabaseTable databaseTable =
        database.getTable(BitcoinCryptoNetworkDatabaseConstants.EVENTAGENT_STATS_TABLE_NAME);

    /** I will get the current execution number */
    int currentExecutionNumber;
    databaseTable.setFilterOrder(
        BitcoinCryptoNetworkDatabaseConstants.EVENTAGENT_STATS_EXECUTION_NUMBER_COLUMN_NAME,
        DatabaseFilterOrder.DESCENDING);
    try {
      databaseTable.loadToMemory();
    } catch (CantLoadTableToMemoryException e) {
      throwLoadToMemoryException(e, databaseTable.getTableName());
    }

    if (databaseTable.getRecords().size() != 0)
      currentExecutionNumber =
          databaseTable
              .getRecords()
              .get(0)
              .getIntegerValue(
                  BitcoinCryptoNetworkDatabaseConstants
                      .EVENTAGENT_STATS_EXECUTION_NUMBER_COLUMN_NAME);
    else currentExecutionNumber = 0;

    /**
     * if I have pending transactions, I will insert a new record, also if this is the first time
     * I'm executing.
     */
    DatabaseTableRecord record = null;
    try {
      if (pendingIncoming != 0 || pendingOutgoing != 0 || currentExecutionNumber == 0) {
        record = databaseTable.getEmptyRecord();
        record.setIntegerValue(
            BitcoinCryptoNetworkDatabaseConstants.EVENTAGENT_STATS_EXECUTION_NUMBER_COLUMN_NAME,
            currentExecutionNumber + 1);
        record.setStringValue(
            BitcoinCryptoNetworkDatabaseConstants.EVENTAGENT_STATS_LAST_EXECUTION_DATE_COLUMN_NAME,
            getCurrentDateTime());
        record.setIntegerValue(
            BitcoinCryptoNetworkDatabaseConstants
                .EVENTAGENT_STATS_PENDING_INCOMING_TRANSACTIONS_COLUMN_NAME,
            pendingIncoming);
        record.setIntegerValue(
            BitcoinCryptoNetworkDatabaseConstants
                .EVENTAGENT_STATS_PENDING_OUTGOING_TRANSACTIONS_COLUMN_NAME,
            pendingOutgoing);

        databaseTable.insertRecord(record);

      } else {
        /** I will update existing value with zero pending transactions */
        DatabaseTableFilter filterIncoming = databaseTable.getEmptyTableFilter();
        filterIncoming.setColumn(
            BitcoinCryptoNetworkDatabaseConstants
                .EVENTAGENT_STATS_PENDING_INCOMING_TRANSACTIONS_COLUMN_NAME);
        filterIncoming.setValue("0");
        filterIncoming.setType(DatabaseFilterType.EQUAL);

        DatabaseTableFilter filterOutgoing = databaseTable.getEmptyTableFilter();
        filterOutgoing.setColumn(
            BitcoinCryptoNetworkDatabaseConstants
                .EVENTAGENT_STATS_PENDING_OUTGOING_TRANSACTIONS_COLUMN_NAME);
        filterOutgoing.setValue("0");
        filterOutgoing.setType(DatabaseFilterType.EQUAL);

        /** I create the two filters and add them to form a filter group. */
        List<DatabaseTableFilter> filters = new ArrayList<>();
        filters.add(filterIncoming);
        filters.add(filterOutgoing);

        List<DatabaseTableFilterGroup> filterGroups = new ArrayList<>();
        databaseTable.setFilterGroup(
            databaseTable.getNewFilterGroup(filters, filterGroups, DatabaseFilterOperator.AND));
        databaseTable.loadToMemory();

        record = databaseTable.getRecords().get(0);
        record.setIntegerValue(
            BitcoinCryptoNetworkDatabaseConstants.EVENTAGENT_STATS_EXECUTION_NUMBER_COLUMN_NAME,
            currentExecutionNumber + 1);
        record.setStringValue(
            BitcoinCryptoNetworkDatabaseConstants.EVENTAGENT_STATS_LAST_EXECUTION_DATE_COLUMN_NAME,
            getCurrentDateTime());

        databaseTable.updateRecord(record);
      }
    } catch (CantLoadTableToMemoryException e) {
      throwLoadToMemoryException(e, databaseTable.getTableName());
    } catch (CantInsertRecordException | CantUpdateRecordException e) {
      StringBuilder outputMessage =
          new StringBuilder("There was an error inserting or modifying a record. The record is:");
      outputMessage.append(System.lineSeparator());
      outputMessage.append(XMLParser.parseObject(record));

      throw new CantExecuteDatabaseOperationException(
          CantExecuteDatabaseOperationException.DEFAULT_MESSAGE,
          e,
          outputMessage.toString(),
          "database issue");
    }
  }