Please ensure Javascript is enabled for purposes of website accessibility
Powered by Zoomin Software. For more details please contactZoomin

AVEVA Pipeline Operations for Liquids

Example implementation

  • Last UpdatedApr 24, 2025
  • 2 minute read

A snippet of the sample plugin appears below.

#include "pch.h"

#include "customFieldProcessor.h"

#include "BuilderFactory.h"

#include <map>

using namespace System;

/// <summary>

/// This is the plugin's entry point for our customers to implement their custom field setters for btc.

/// </summary>

/// <remarks>

/// You could either use std::exceptions or error codes to communicate errors to BTC.

/// Any error will stop BTC's execution.

/// </remarks>

/// <param name="record"> The pointer to the record.</param>

/// <param name="key"> The field to be set.</param>

/// <param name="value"> The value to be assigned. It could contain additional information such as comments.</param>

/// <returns> The error code: zero if there were no errors. Otherwise, non-zero value. </returns>

extern "C" OAS_EXPORT int process_custom_field(

RealTimeRecord& record,

const char* key,

const char* value)

{

// No error code.

int returnCode = 0;

std::string fieldName(key);

std::string strValue(value);

// As values can have any format, in this example the values' comments are removed before its processing.

auto cleanValue = remove_comment(strValue);

RealTimeTable* table;

record.GetRealTimeTable(table);

TFlexString tableName = table->GetTableName();

std::shared_ptr<ICustomFieldSetter> builder;

BuilderFactory factory(&record);

if (has_expected_format(cleanValue))

{

if (factory.GetBuilder(tableName.Get(), builder))

{

cpu_debug(CPU_DEBUG_INFO, "%s custom builder was retrieved.", tableName.Get());

// Try to write value into record.

// If operation succeded, use zero as return code. Otherwise, use non-zero as failure code.

if (builder->PutField(fieldName, cleanValue) == false)

{

// Log the error to help the user.

cpu_debug(CPU_DEBUG_ERROR, "An error happened while writing custom field %s.", fieldName.c_str());

// Use non-zero failure code to stop BTC execution.

returnCode = 1;

}

}

else

{

// Any std::exception will be handled by BTC. The error message will be logged and the execution of BTC will be stopped.

throw std::runtime_error("Table " + std::string(tableName.Get()) + " does not have custom builder.");

}

}

else

{

// In this example, we won't allow any unexpected format.

// Log the issue to warn the user.

cpu_debug(CPU_DEBUG_ALWAYS, "The custom field value has an unexpected format: %s. Line ignored", cleanValue.c_str());

// By returning zero value, BTC execution will continue.

// You can use it for warning scenarios were the execution of BTC can continue.

returnCode = 0;

}

return returnCode;

}

std::string remove_comment(const std::string& value)

{

// Removes all characters after the semicolon.

std::string commentDelimiter = ";";

auto pos = value.find(commentDelimiter);

std::string cleanedValue = value;

if (pos != std::string::npos)

{

// Remove the comment from value

cleanedValue = cleanedValue.substr(0, pos);

}

return cleanedValue;

}

bool has_expected_format(const std::string& value)

{

// In this example, we are considering curly braces as invalid characters.

std::string invalidCharacters = "{}";

bool isValid = true;

for (auto c : invalidCharacters)

{

auto pos = value.find(c);

if (pos != std::string::npos)

{

isValid = false;

break;

}

}

return isValid;

}