-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7 from Paulanerus/dev
Dev
- Loading branch information
Showing
13 changed files
with
477 additions
and
88 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,279 @@ | ||
# API Development | ||
|
||
This ReadMe provides an overview of the TextExplorer API and guides you through developing your own plugin. A sample | ||
implementation is available in [plugins/demo](../plugins/demo). | ||
|
||
While using a build tool is not mandatory, this documentation employs [Gradle](https://gradle.org/) in its examples to | ||
align with the project's overall setup. | ||
|
||
## Environment setup | ||
|
||
1. Install Java 21. | ||
2. Create a new Gradle (Kotlin DSL) project. | ||
3. Download the latest [API release](https://github.com/Paulanerus/TextExplorer/releases/latest) and add the JAR as a | ||
local dependency: | ||
|
||
```kotlin | ||
implementation(files("libs/api-0.32.2.jar")) | ||
``` | ||
|
||
4. Reload the Gradle project. | ||
|
||
## First plugin | ||
|
||
To create your first plugin, follow these steps: | ||
|
||
1. Create a Kotlin class, e.g., `PluginMain`, and implement the `IPlugin` interface: | ||
|
||
```kotlin | ||
class PluginMain : IPlugin { | ||
override fun init() { | ||
println("Hello world from plugin.") | ||
} | ||
} | ||
``` | ||
|
||
The `init` function is executed when the application starts or the plugin is loaded via the interface. Use this function | ||
to initialize external services or perform setup tasks. | ||
|
||
2. Annotate the class with `@PluginMetadata` to declare the plugin's metadata. You can include additional information | ||
like the version, author, or a short description. | ||
|
||
3. Optionally, use the `@PluginOrder` annotation to specify the load order for the plugin. | ||
|
||
4. Update the Gradle `jar` task to include the plugin's main class in the JAR file manifest: | ||
|
||
```kotlin | ||
tasks.jar { | ||
manifest { | ||
attributes["Main-Class"] = "PluginMain" // Adjust the path if necessary | ||
} | ||
} | ||
``` | ||
|
||
## Provide data | ||
|
||
To connect existing data to your plugin, annotate it with `@RequiresData` and specify the identifier of the data pool. | ||
For example, to connect to `demo_data`, annotate the class with: | ||
`@RequiresData("demo_data")`. | ||
|
||
To import your own data, a "data-layout" is required. It's recommended to create a separate Kotlin file (e.g., | ||
`Data.kt`) containing the relevant classes for the data structure. | ||
|
||
Consider the following CSV files: | ||
|
||
**authors.csv:** | ||
|
||
```text | ||
author_id,full_name,year_born,birth_place | ||
...,...,...,... | ||
... | ||
``` | ||
|
||
**quotes.csv:** | ||
|
||
```text | ||
quote,date,author_id | ||
...,...,...,... | ||
... | ||
``` | ||
|
||
In Data.kt, define your data classes to match the column names in the CSV files: | ||
|
||
```kotlin | ||
@DataSource("authors") | ||
data class Author( | ||
@Unique(true) val author_id: Long, | ||
val full_name: String, | ||
val year_born: String | ||
) | ||
|
||
@DataSource("quotes") | ||
data class Quote( | ||
@Index(Language.ENGLISH) val quote: String, | ||
val date: String, | ||
@Link(Author::class) val author_id: Long | ||
) | ||
``` | ||
|
||
+ `@DataSource`: Links the respective CSV file to the class. Ensure the class name matches the CSV name (the file | ||
extension is optional). | ||
|
||
+ `@Unique`: Marks the field as unique. If `true` and the type is `Long`, it will serve as the identifier and will not | ||
be auto-generated by TextExplorer. | ||
|
||
+ `@Index`: Marks the field as indexed in the specified language, which is essential for search functionality. It can be | ||
marked as the default value and must occur at least once in any class. | ||
|
||
+ `@Link`: Establishes a relationship between two classes. Use this with `@Index` to enable related data display in the | ||
interface. The field name must be the same in both classes. | ||
|
||
Finally, update the plugin to include the created data classes as part of its data requirements: | ||
|
||
```kotlin | ||
@RequiresData("demo_data", sources = [Author::class, Quote::class]) | ||
class PluginMain : IPlugin { | ||
... | ||
} | ||
``` | ||
|
||
This will import the data appropriately, making it available for use in TextExplorer. | ||
|
||
**Currently only data in csv-files is supported.** | ||
|
||
## Variants | ||
|
||
Different terms can refer to the same entity, such as "USA," "US," "United States," or "America" for the country. | ||
TextExplorer provides the `Variant API` to handle these cases. | ||
|
||
With the Variant API, you can define a column in a CSV file as the "base" term (the one the user will search for), and | ||
additional columns can store variant terms. This allows users to search for any variant. | ||
|
||
**Example: Countries** | ||
|
||
**countries.csv** | ||
|
||
```text | ||
base,variant | ||
USA,USA | ||
USA,US | ||
USA,United States | ||
USA,America | ||
... | ||
``` | ||
|
||
In this example, "USA" is the base term, and the other terms are variants. The TextExplorer representation would look | ||
like this: | ||
|
||
```kotlin | ||
@Variant(base = "base", ["variant"]) | ||
@DataSource("countries") | ||
data class Country(val base: String, val variant: String) | ||
``` | ||
|
||
To connect this data to your plugin, you need to update the `@RequiresData` annotation to include the `Country` class: | ||
|
||
```kotlin | ||
@RequiresData("countries", sources = [Country::class, Author::class, Quote::class]) | ||
class PluginMain : IPlugin { | ||
... | ||
} | ||
``` | ||
|
||
This setup allows the user to search for `@countries:USA`, and TextExplorer will return all entries that match any of | ||
the variants declared for "USA." | ||
|
||
## Tagging API | ||
|
||
The Tagging API allows you to highlight specific words (e.g., names) within the Tagging View. | ||
|
||
To implement this functionality, simply implement the tag function from the Taggable interface in your Plugin Main class. | ||
This function takes the field name and its corresponding value as parameters. | ||
|
||
Additionally, annotate the function with `@ViewFilter`, which specifies a filter name and the fields it accepts. | ||
Optionally, you can use the global parameter to apply the tags to the DiffView. | ||
|
||
To highlight the name "Tom" in every field, the implementation would look like this: | ||
|
||
```kotlin | ||
@ViewFilter("Name Highlighter", fields = ["quote"], global = true) | ||
override fun tag(field: String, value: String): Map<String, Tag> = mapOf("Tom" to Tag("NAME", Color.blue)) | ||
``` | ||
|
||
In this example: | ||
|
||
+ Only the quote field is passed to the tag function. | ||
+ The word "Tom" is mapped to the Tag with the identifier `NAME` and the color blue. | ||
+ Every occurrence of "Tom" in the quote field will be highlighted in blue. | ||
|
||
## Pre filtering | ||
|
||
**Not yet implemented** | ||
|
||
## Access plugin data | ||
|
||
**Not yet implemented** | ||
|
||
## Export plugin | ||
|
||
To export the plugin, run the Gradle `jar` task: | ||
|
||
```shell | ||
./gradlew jar | ||
``` | ||
|
||
For Windows use: | ||
|
||
```shell | ||
gradlew.bat jar | ||
``` | ||
|
||
### A full example: | ||
|
||
**PluginMain:** | ||
|
||
```kotlin | ||
@PluginOrder(3) | ||
@RequiresData("demo_data", sources = [Country::class, Author::class, Quote::class]) | ||
@PluginMetadata("demo", author = "Author", version = "1.0.0", description = "A short description.") | ||
class PluginMain : IPlugin, Taggable { | ||
|
||
override fun init() { | ||
println("Hello world from plugin.") | ||
} | ||
|
||
@ViewFilter("Name Highlighter", fields = ["quote"], global = true) | ||
override fun tag(field: String, value: String): Map<String, Tag> = mapOf("Tom" to Tag("NAME", Color.blue)) | ||
} | ||
``` | ||
|
||
**Data.kt:** | ||
|
||
```kotlin | ||
@Variant(base = "base", ["variant"]) | ||
@DataSource("countries") | ||
data class Country(val base: String, val variant: String) | ||
|
||
@DataSource("authors") | ||
data class Author( | ||
@Unique(true) val author_id: Long, | ||
val full_name: String, | ||
val year_born: String | ||
) | ||
|
||
@DataSource("quotes") | ||
data class Quote( | ||
@Index(Language.ENGLISH) val quote: String, | ||
val date: String, | ||
@Link(Author::class) val author_id: Long | ||
) | ||
``` | ||
|
||
**build.gradle.kts** | ||
|
||
```kotlin | ||
plugins { | ||
kotlin("jvm") version "2.0.21" | ||
} | ||
|
||
group = "com.example" | ||
version = "1.0-SNAPSHOT" | ||
|
||
repositories { | ||
mavenCentral() | ||
} | ||
|
||
dependencies { | ||
implementation(files("libs/api-0.32.2.jar")) | ||
} | ||
|
||
tasks.jar { | ||
manifest { | ||
attributes["Main-Class"] = "PluginMain" | ||
} | ||
} | ||
|
||
kotlin { | ||
jvmToolchain(21) | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.