Example of ConnectionExtension Implementation
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Sana.Extensions.Connection;
using System.Xml.XPath;
namespace Sana.ProductClassifier
{
public class ProductClassifierExtension : ConnectionExtension
{
const string ClassFieldName = "Custom_Class";
const string ClassFieldXPath = "/field[@name=\"" + ClassFieldName + "\"]";
const string EntityField = "<Field>" +
"<field name=\"Name\" value=\"" + ClassFieldName + "\"/>" +
"<field name=\"Caption\" value=\"Discovered class\"/>" +
"<field name=\"Type\" value=\"String\"/>" +
"</Field>";
public override XDocument ExecuteRequest(string operation, IList<XElement> parameters, ExecuteRequestMethod execute)
{
if (operation.Equals("GetEntityFields", StringComparison.Ordinal) && parameters.Any(param => param.Name.LocalName == "Table" && param.Value == "Product"))
return InterceptGetEntityFields(parameters, execute);
if (operation.Equals("GetProducts", StringComparison.Ordinal))
return InterceptGetProducts(parameters, execute);
return execute(operation, parameters);
}
protected virtual XDocument InterceptGetEntityFields(IList<XElement> parameters, ExecuteRequestMethod execute)
{
var document = execute("GetEntityFields", parameters);
XElement resultNode = GetResultNode(document);
if (resultNode != null && resultNode.HasElements)
resultNode.Add(XElement.Parse(EntityField));
return document;
}
protected virtual XDocument InterceptGetProducts(IList<XElement> parameters, ExecuteRequestMethod execute)
{
var fieldsNode = parameters.FirstOrDefault(e => e.Name.LocalName == "ExtraFields");
var classField = fieldsNode?.XPathSelectElement(ClassFieldXPath);
if (classField == null)
return execute("GetProducts", parameters);
// Prevent ERP error on not found field.
classField.Remove();
var document = execute("GetProducts", parameters);
XElement resultNode = GetResultNode(document);
if (resultNode != null && resultNode.HasElements)
{
foreach (var product in resultNode.Elements("Product"))
{
// Assume GetClass method is some ML-based algorithm or advanced text search function.
var txt = "<field name=\"" + ClassFieldName + "\" value=\"" + GetClass(product) + "\"/>";
product.Add(XElement.Parse(txt));
}
}
// Restore original parameters state.
fieldsNode.Add(classField);
return document;
}
XElement GetResultNode(XDocument document) => document.Root.Element("Result");
protected virtual string GetClass(XElement product)
{
var title = (string)product.XPathEvaluate("string(field[@name=\"Title\"]/@value)");
return GetClass(title);
}
string GetClass(string title)
{
bool contains(params string[] strings) => strings.Any(sub => title.IndexOf(sub, StringComparison.CurrentCultureIgnoreCase) != -1);
return contains("Bicycle", "cycle", "bike")
? "bike"
: "other";
}
}
}