# Source Adapter Interface

### 1. Adapter structure

**ISourceAdapter**: The data source (DB, service etc.) is configured based on the necessary attributes and credentials. After that, the source can be configured.\
**ISource**: The capabilities of an adapter instance can be retrieved from the business logic. This information comes from the adapter itself, not from the source.\
**IActionCapabiliy**: If this interface is implemented, then actions on classes, methods or instances can be performed.\
**ISchemaCapability**: With this schema interface the adapter analyzes the information/data source and returns the available schema. For example, the schema could be considered for a database source.

![](/files/-M8ukOvcGcntH62sVLcD)

### 2. Adapter interfaces

### 2.1 Transfer models (common)

**2.1.1 SourceResult**

Every method call of the API returns an SourceResult object. There is always a property "Messages" in this object, which represents a list of error messages. In addition the SourceResult object could be contain a Result object from the current context.

```csharp
public class SourceResult<TValue>
{
        public TValue Value { get; private set; }
        public List<SourceResultMessage> Messages { get; private set; }
}
```

> SourceResult is the base result object that is beeing used for inheritance.

**2.1.2 SourceRequest**

In a SourceRequest object, a list of credentials for identification, authenticate and authorization of a data source can be entered. If a source or adapter supports transactions, You can also enter a transaction key here.

```csharp
public class SourceRequest
{
    public List<SourceCredential> Credentials { get; set; }
       public object TransactionKey { get; set; }
}
```

**2.1.3 Translation**

The Translation object supports the multi-lingualism of the TIVITY platform. It is a list of Key-Value pairs, which contains:

| parameter name | type | description                     |
| -------------- | ---- | ------------------------------- |
| Key            | str  | country code                    |
| Value          | str  | text in the respective language |

Example: *translationObj\[„en-EN“] = "text in language"*

```csharp
public class Translation : Dictionary <string, string> { }
```

### 2.2 ISourceAdapter

The interface must be implemented in every adapter.\
It provides basic methods:

* pass back information about the adapter ("define")
* allow configurations ("config")
* initializes the adapter ("connect")

**2.2.1 Define**

The *Define* method returns meta-information about the adapter: the name of the adapter, the description and a thumbnail (e.g. logo). All three properties are translation objects. Therefore, the information can be supported in all languages.

```csharp
Task<SourceResult<AdapterDefinition>> Define(AdapterDefineRequest request);
```

Define Result:

```csharp
    public sealed class AdapterDefinition
    {
        public Translation Name { get; set; }
        public Translation Description { get; set; }
        public Translation Thumbnail { get; set; }
    }
```

**2.2.2 Config**

The two *Config* methods can be used to control the configuration process. The process starts with a request object (*AdapterConfigLaunchRequest*), which can submit inital parameters to the adapter, but not necessarily required. Then you get back a list of parameters. They will be displayed on the plattform UI as formular fields. The required configuration settings are made on this form.\
With the second method the settings are sended as Key-Value pairs (Dictionary) to the adapter/service (request object "AdapterConfigHandleRequest").

```csharp
Task<SourceResult<ConfigurationStep>> Config(AdapterConfigLaunchRequest request);
Task<SourceResult<ConfigurationStep>> Config(AdapterConfigHandleRequest request)
```

You now have the opportunity to check these inputs in the adapter itself and send back error messages or to send further parameters based on the previous entries. When the configuration is complete, a *ConfigurationSuccess* must be returned.

Success Response:

```csharp
    public sealed class ConfigurationSuccess : ConfigurationStep
    {
        public string Configuration { get; private set; }

        public ConfigurationSuccess(string configuration)
        {
            Configuration = configuration;
        }
    }
```

**2.2.3 Connect**

A "Connect" initializes an adapter for an information source. The request object ("AdapterConnectRequest") contains the information of the previous configurations. As a result the interface *ISource* is returned, which represents the adapter. In fact, however, an map object ("SourceCapabilityMap") is expected in the server variant, which listed the information about the supported capabilities.

```csharp
    Task<SourceResult<ISource>> Connect(AdapterConnectRequest request);
```

The *AdapterConnectRequest* has a Configuration property which structure and content is adapter dependent. Additionally an service factory can be transferred. This factory gives access to different services by querying them by their interface definition. Of course, this option cannot be used in the REST service.

```csharp
    public class AdapterConnectRequest
    {
        public string Configuration { get; set; }
        public IServiceFactory ServiceFactory { get; set; }
    }
```

### 2.3 ISource

The interface retrieves information about the supported adapter capabilities. In addition, the concrete adapter can be returned as ISource interface (**not** the server variant!).\
Should be implemented with every adapter. Without the information of the capabilities an adapter can be present (initialized and configured), but has no functionality.

**2.3.1 GetCapabilityMap**

The *GetCapabilityMap* method returns a list of capability types. These types represent the capability interfaces implemented by the adapter. This information is important for the platform to know what capabilities an adapter brings.

```csharp
Task<SourceResult<SourceCapabilityMap>> GetCapabilityMap(SourceCapabilityRequest request);
```

All available capability types:

| Capability type | Interface                 |
| --------------- | ------------------------- |
| Action          | IActionCapability         |
| Authentication  | IAuthenticationCapability |
| Document        | IDocumentCapability       |
| Model           | IModelCapability          |
| Preview         | IPreviewCapability        |
| Query           | IQueryCapability          |
| Schema          | ISchemaCapability         |
| Search          | ISearchCapability         |
| Thumbnail       | IThumbnailCapability      |
| Version         | IVersionCapability        |

**2.3.2 GetCapability\<TCapability>**

This Method is **not** supported in a adapter service (see example REST service). The interface of an adapter instance is returned. This is only possible with a straight adapter instantiation.

```csharp
TCapability GetCapability<TCapability>()
```

> NOT supported in REST Service!

### 2.4 IActionCapability

The interface *IActionCapability* has only one method "Execute" and belongs to the adapter capabilities. That means, this interface does not need to be implemented.

**2.4.1 Execute**

The method "Execute" is to be understood as a generic method call. On the one hand, in the object ("ActionExecuteRequest") it'll be specified the context for the call. These are the classes ("ClassName") that has the action, the Name of the action itself ("ActionName") and optinal the class instance identifier ("Key"). This allows different "Execute" calls to be performed on a particular class. These calls can be handled differently in the adapter instance.\
In addition, it is possible to pass a list of parameters (Dictionary). These correspond to the return parameters of a class method.

```csharp
public class ActionExecuteRequest : SourceRequest
{
        public string ClassName { get; set; }
        public string ActionName { get; set; }
        public object Key { get; set; }
        public Dictionary<string, object> Parameters { get; set; }
}
```

The result returns an object of type *object*. In the server variant this could be a simple data type like string or integer. But also a serialized object in json format is possible. It should only be ensured that the calling class/instance inside the TIVITY platform can handle it.

```csharp
Task<SourceResult<object>> Execute(ActionExecuteRequest request);
```

### 2.5 ISchemaCapability

There is only one method defined in the interface *ISchemaCapability*. This interface does not need to be implemented. It belongs to the adapter capabilities.

**2.5.1 Get**

(Meta-)Information about the object structure (class, fields and links) is determined with the method *Get*. No parameters are transferred in the request. The object *SchemaGetRequest* is empty and it doesn't necessary transmit data. The request model is also derived from SourceRequest as well. So it is possible to pass the credentials/transactions with the request.

```csharp
Task<SourceResult<Schema>> Get(SchemaGetRequest request);
```

The result is a schema object. This contains the metadata of the available objects. These are the classes and links, each written as a list in the schema.

```csharp
public class Schema
{
     public List<Class> Classes { get; set; }
    public List<Link> Links { get; set; }
}
```

**Class**: in every class exist the class name ("Name") and the class properties ("fields"). The *fields* are a list of field objects. A Field object contains the description data of the field:

| parameter name   | type | description                                              |
| ---------------- | ---- | -------------------------------------------------------- |
| Name             | str  | Name of the field                                        |
| Length           | str  | Max. field length (null = no limit)                      |
| DefaultValue     | str  | The value that set on a new instance                     |
| IsNullable       | bool | If true, than the field is nullable (database)           |
| NameIntern       | str  | label as known field                                     |
| DataSourceOption | str  | Options that apply to the field (separated by semicolon) |
| IsReadOnly       | bool | If true, than the field cannot changed.                  |
| DataType         | enum | Type of the field (string, integer etc.)                 |

**Link**: the link objects represent a class and field link. a Link has the following description data;

| parameter name   | type | description                       |
| ---------------- | ---- | --------------------------------- |
| Name             | str  | Name of the Link                  |
| PrimaryClassName | str  | Name/ID of the main class         |
| ForeignClassName | str  | Name/ID of the linked class       |
| PrimaryFieldName | str  | Name/ID of the main class field   |
| ForeignFieldName | str  | Name/ID of the linked class field |

The meta-information in the Result schema now allows instances to be created and forwarded to the adapter with the [CRUD operations](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete).

### 2.6 IQueryCapability

The QueryCapability interface ensures that the desired class instances (model) are selected by using a filter. A model list (the class instances) is returned as the result. For this operation we need only one method.

**2.6.1 Execute**

The execute method searches for class instances in a repository or external source using a query object in request. This Query can be used in many ways. As a SQL statement or maybe a mapped filter object.

```csharp
Task<SourceResult<ModelList>> Execute(QueryExecuteRequest request);
```

The *QueryExecuteRequest* has a query. This *Query* object consist of different query parts:

```csharp
    public class Query
    {
        public From From { get; set; }
        public List<Join> Joins { get; set; }
        public List<Column> Columns { get; set; }
        public List<Condition> Conditions { get; set; }
        public Pagination Pagination { get; set; }
    }
```

| parameter name | type | description                                           |
| -------------- | ---- | ----------------------------------------------------- |
| From           | obj  | defines a class to query data from                    |
| Columns        | list | list of column objects to get from data to query      |
| Conditions     | list | list of conditions to filter the data                 |
| Joins          | list | list of joins with filter and class                   |
| Pagination     | obj  | pagination data to reduce the amount of data to query |

**From**

| parameter name | type | description                              |
| -------------- | ---- | ---------------------------------------- |
| ClassName      | str  | Name of the class                        |
| Alias          | str  | could be used for alias in SQL statement |

**Column**

| parameter name | type | description                                    |
| -------------- | ---- | ---------------------------------------------- |
| Expression     | obj  | ExpressionField with Fieldname and class alias |
| Alias          | str  | could be used for alias in SQL statement       |

**Condition**

| parameter name   | type       | description                       |
| ---------------- | ---------- | --------------------------------- |
| LeftParentheses  | int        | set parentheses on left site      |
| LeftExpression   | Expression | the expression on left site       |
| IsNegated        | bool       | true OR false                     |
| Operator         | enum       | well defined comparison operators |
| RightExpression  | Expression | the expression on right site      |
| RightParentheses | int        | set parentheses on right site     |
| LogicalOperator  | enum       | None, And, Or                     |

As a result, a list of model objects is returned. The *Model* represents a dictionary with Key = FieldName and Value = FieldValue.

### 2.7 IModelCapability

The model capability united the basic function of persistent storage. These functions are:

* create or add a new entry
* update or edit existing entries
* delete or remove existing entries

This interface facilitate searching and changing information. For read/retrieve, view or search information please use the *IQueryCapability* interface. Usually the source is used to connect to databases. The IModelCapability interface consists of three methods.

```csharp
    Task<SourceResult<Model>> Create(ModelCreateRequest request);
    Task<SourceResult> Update(ModelUpdateRequest request);
    Task<SourceResult> Delete(ModelDeleteRequest request);
```

**2.7.1 Create**

If you want to create or add a new entry, you need to transfer a class name and the entry (Model). The *Model* is in fact a simple dictionary consisting of class fields (Key) and the values. These details are included in the *ModelCreateRequest*. You get the information about the classes and the model structure when the schema capability method is called (see 5.5). As result the created model is returned.

```csharp
    public class ModelCreateRequest : SourceRequest
    {
        public string ClassName { get; set; }
        public Model Model { get; set; }
    }
```

**2.7.2 Update**

To update an existing entry, send the class name of the class to be manipulated. Additional a key for value of the field to identify the model. And of course the entry with all changed fields.

```csharp
    public class ModelUpdateRequest : SourceRequest
    {
        public string ClassName { get; set; }
        public object Key { get; set; }
        public Model Model { get; set; }
    }
```

**2.7.3 Delete**

At last you want delete the entry. Use the delete method and fill the *ModelDeleteRequest* with the class name and the key for value of the field to identify the model to delete.

```csharp
    public class ModelDeleteRequest : SourceRequest
    {
        public string ClassName { get; set; }
        public object Key { get; set; }
    }
```

### 2.8 IDocumentCapability

This capability is used for getting a document content. The only method in the interface is a download method.\
If you need the properties for the document, such as the name of the document or the type, these can be saved in an instance of a class. This instance can then be retrieved using the *Query* method. After that you call the download method to get the content of the document.

```csharp
    Task<SourceResult<Document>> Download(DocumentDownloadRequest request);
```

**2.8.1 Download**

To get a document, use the *Download* method. The request model has two properties. The name is used to specify the class assigned to the requested document. The Key value is the document identifier. This identifier can be a unique name, a path or a GUID. As result you get a document object. This (base) class is modified as abstract, so you can create your own document class that is inherited from the abstract class.

> ! The REST service returns a stream, not the document object.

```csharp
    public class DocumentDownloadRequest : SourceRequest
    {
        public string ClassName { get; set; }
        public object Key { get; set; }
    }
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.tivity.one/extensibility-and-integration/source-adapter/source-adapter-interface.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
