Created APIv5 - DataExtension API (markdown)
parent
041d115dd4
commit
2c279ac8a0
|
@ -0,0 +1,634 @@
|
|||
![Plan Header](http://puu.sh/AXSg7/5f2f78c06c.jpg)
|
||||
# Plan API version 5 - DataExtension API
|
||||
|
||||
> This API is still under development and special providers are not available yet.
|
||||
|
||||
This page is about API that is available in **version 4.8.0** and above.
|
||||
API can be called on all platforms.
|
||||
|
||||
### Table of contents
|
||||
|
||||
- [Dependency information](https://github.com/Rsl1122/Plan-PlayerAnalytics/wiki/APIv5#dependency-information)
|
||||
- DataExtension API
|
||||
- 🔔 [How to register a DataExtension](https://github.com/Rsl1122/Plan-PlayerAnalytics/wiki/APIv5#-how-to-register-a-dataextension)
|
||||
- ℹ️ [PluginInfo Annotation](https://github.com/Rsl1122/Plan-PlayerAnalytics/wiki/APIv5#%E2%84%B9%EF%B8%8F-plugininfo-annotation)
|
||||
- 📏 [Provider Annotations](https://github.com/Rsl1122/Plan-PlayerAnalytics/wiki/APIv5#-provider-annotations)
|
||||
- 🔨 [Special Provider Annotations](https://github.com/plan-player-analytics/Plan/wiki/APIv5#-special-provider-annotations)
|
||||
- 👥 [`@GroupProvider`](https://github.com/plan-player-analytics/Plan/wiki/APIv5#groupprovider)
|
||||
- 📐 [Extra annotations](https://github.com/Rsl1122/Plan-PlayerAnalytics/wiki/APIv5#-extra-annotations)
|
||||
- ❕ [Preventing runtime errors](https://github.com/Rsl1122/Plan-PlayerAnalytics/wiki/APIv5#-preventing-runtime-errors)
|
||||
- Implementation violations
|
||||
- API in Action
|
||||
|
||||
## Dependency information
|
||||
|
||||
> The API is still under heavy development and details might be subject to change,
|
||||
use at your own risk.
|
||||
|
||||
Plan API is distributed via Bintray repository:
|
||||
```
|
||||
<repository>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
<id>bintray-rsl1122-Plan-repository</id>
|
||||
<name>bintray</name>
|
||||
<url>https://dl.bintray.com/rsl1122/Plan-repository</url>
|
||||
</repository>
|
||||
```
|
||||
|
||||
```
|
||||
<dependency>
|
||||
<groupId>com.djrapitops</groupId>
|
||||
<artifactId>Plan-api</artifactId>
|
||||
<version>...</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
Dependency version information can be found here:
|
||||
https://bintray.com/rsl1122/Plan-repository/Plan-API
|
||||
|
||||
Remember to add `"Plan"` as a softdependency to your plugin information (plugin.yml / Plugin annotation).
|
||||
|
||||
# DataExtension API
|
||||
|
||||
DataExtension API is used for providing Plan with data of your plugin, so that the data can be viewed on the web panel.
|
||||
This makes it easier for users to reason about their server.
|
||||
|
||||
## 🔔 How to register a DataExtension
|
||||
|
||||
1. Create a new object that implements `DataExtension`.
|
||||
2. Obtain instance of `ExtensionService` and register using `ExtensionService#register(DataExtension)`
|
||||
|
||||
```
|
||||
DataExtension yourExtension = new YourDataExtensionImplementation();
|
||||
try {
|
||||
|
||||
ExtensionService.getInstance().register(yourExtension);
|
||||
|
||||
} catch (NoClassDefFoundError planIsNotInstalled) {
|
||||
// Plan is not installed, handle exception
|
||||
} catch (IllegalStateException planIsNotEnabled) {
|
||||
// Plan is not enabled, handle exception
|
||||
} catch (IllegalArgumentException dataExtensionImplementationIsInvalid) {
|
||||
// The DataExtension implementation has an implementation error, handle exception
|
||||
}
|
||||
```
|
||||
|
||||
> Registration should be done in it's own class to avoid `NoClassDefFoundError` if Plan is not installed.
|
||||
You might need to catch the error when calling your method that does the registering.
|
||||
|
||||
## ℹ️ `@PluginInfo` annotation
|
||||
|
||||
Every `DataExtension` implementation **requires** `@PluginInfo` annotation.
|
||||
|
||||
> **Notation:**
|
||||
> `*` means required parameter
|
||||
|
||||
<details>
|
||||
<summary>Usage & Parameters</summary>
|
||||
|
||||
```
|
||||
@PluginInfo(
|
||||
name* = "Your Plugin",
|
||||
iconName = "cube"
|
||||
iconFamily = Family.SOLID,
|
||||
color = Color.NONE
|
||||
)
|
||||
public class YourExtension implements DataExtension {}
|
||||
```
|
||||
|
||||
- `name` - Name of your plugin
|
||||
- `iconName` - Icon names can be found from https://fontawesome.com/icons?d=gallery&m=free
|
||||
- `iconFamily` - Icon family should match details on the site above
|
||||
- `color` - Colors are available here *Link to be added*
|
||||
|
||||
</details>
|
||||
|
||||
## 📏 Provider Annotations
|
||||
|
||||
Provider annotations are method annotations that tell Plan what kind of data methods in your `DataExtension` class provide.
|
||||
|
||||
> **Notation:**
|
||||
> `*` means required parameter
|
||||
|
||||
The name of the methods are used for storing information the methods provide.
|
||||
|
||||
Methods can have 4 different parameters (**But only one**):
|
||||
```
|
||||
T method(); // The value is about the server as a whole
|
||||
T method(UUID playerUUID); // The value is about a player
|
||||
T method(String playerName); // The value is about a player
|
||||
T method(Group group); // The value is about a Group a player is in
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Controlling when Plan calls your DataExtension methods</summary>
|
||||
|
||||
```
|
||||
@Override
|
||||
public CallEvents[] callExtensionMethodsOn() {
|
||||
return new CallEvents[]{
|
||||
CallEvents.PLAYER_JOIN,
|
||||
CallEvents.PLAYER_LEAVE,
|
||||
CallEvents.SERVER_EXTENSION_REGISTER,
|
||||
CallEvents.SERVER_PERIODICAL
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
- `DataExtension#callExtensionMethodsOn` can be overridden to change default event call behavior.
|
||||
- Explanations
|
||||
- Empty array: Plan will not call the methods automatically, see below for manual calls.
|
||||
- `PLAYER_JOIN`: Plan calls player methods after a Join event (Bukkit/Bungee: MONITOR, Sponge: POST)
|
||||
- `PLAYER_LEAVE`: Plan calls player methods after a Quit event (Bukkit/Bungee: NORMAL, Sponge: DEFAULT)
|
||||
- `SERVER_EXTENSION_REGISTER` Plan calls server methods after registering the `DataExtension`
|
||||
- `SERVER_PERIODICAL` Plan calls server methods periodically via a task
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>Manual update calls</summary>
|
||||
|
||||
```
|
||||
DataExtension yourExtension;
|
||||
Optional<Caller> caller = extensionService.register(yourExtension);
|
||||
```
|
||||
|
||||
- `ExtensionService#register` returns a `Optional<Caller>`. The Caller is present if the extension was registered.
|
||||
- You can use the `Caller` methods in your listeners when your data is updated.
|
||||
|
||||
> **HOX** Do not use `Caller` inside `DataExtension` - This might lead to unbound recursion!
|
||||
|
||||
```
|
||||
Caller caller;
|
||||
|
||||
caller.updatePlayerData(playerUUID, playerName);
|
||||
caller.updateServerData();
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### `@BooleanProvider`
|
||||
|
||||
**Speciality:** `boolean` values, Can work with `@Conditional`-annotation for conditional execution
|
||||
|
||||
<details>
|
||||
<summary>Usage & Parameters</summary>
|
||||
|
||||
```
|
||||
@BooleanProvider(
|
||||
text* = "Has Island",
|
||||
description = "Whether or not the player has an island in the island world",
|
||||
priority = 5,
|
||||
iconName = "question",
|
||||
iconFamily = Family.SOLID,
|
||||
iconColor = Color.NONE,
|
||||
conditionName = "islandCondition",
|
||||
hidden = false
|
||||
)
|
||||
public boolean hasIsland(UUID playerUUID) {...}
|
||||
```
|
||||
|
||||
- `text` - Text that appears next to the value, for example "Has Island: No"
|
||||
- `description` - Text that appears when hovering over the value
|
||||
- `priority` - Ordering number, highest value is placed top most
|
||||
- `iconName` - Icon names can be found from https://fontawesome.com/icons?d=gallery&m=free
|
||||
- `iconFamily` - Icon family should match details on the site above
|
||||
- `iconColor` - Color of the icon that appears next to the value
|
||||
- `conditionName` - Name of a condition this boolean represents, used with `@Conditional` annotations
|
||||
- `hidden` - Should this value be hidden from the web panel?
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>Usage with @Conditional</summary>
|
||||
|
||||
```
|
||||
@BooleanProvider(
|
||||
...
|
||||
conditionName = "hasIsland"
|
||||
)
|
||||
public boolean hasIsland(UUID playerUUID) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Conditional("hasIsland)
|
||||
@StringProvider(...) // Another provider is required, can be any Provider.
|
||||
public String islandName(UUID playerUUID) {...}
|
||||
```
|
||||
|
||||
- `conditionName` is provided by a `@BooleanProvider`.
|
||||
- If the value is `true`, other methods with `@Conditional(conditionName)` will be called.
|
||||
- See [Conditional](https://github.com/plan-player-analytics/Plan/wiki/APIv5#conditional) for more
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>Hiding "Yes"/"No" results</summary>
|
||||
|
||||
```
|
||||
@BooleanProvider(
|
||||
...
|
||||
conditionName* = "hasLinkedAccount",
|
||||
hidden = true
|
||||
)
|
||||
public boolean hasLinkedAccount(UUID playerUUID) {...}
|
||||
```
|
||||
|
||||
- If `hidden` is `true`, the `conditionName` parameter is required.
|
||||
- "Yes" / "No" for this method will not appear on the web panel.
|
||||
|
||||
</details>
|
||||
|
||||
### `@NumberProvider`
|
||||
|
||||
**Speciality:** Whole numbers, Time amounts, Timestamps
|
||||
|
||||
<details>
|
||||
<summary>Usage & Parameters</summary>
|
||||
|
||||
```
|
||||
@NumberProvider(
|
||||
text* = "Number of Islands",
|
||||
description = "How many islands does the player own",
|
||||
priority = 4,
|
||||
iconName = "question",
|
||||
iconFamily = Family.SOLID,
|
||||
iconColor = Color.NONE,
|
||||
format = FormatType.NONE
|
||||
)
|
||||
public long islandCount(UUID playerUUID) {...}
|
||||
```
|
||||
|
||||
- `text` - Text that appears next to the value, for example "Has Island: No"
|
||||
- `description` - Text that appears when hovering over the value
|
||||
- `priority` - Ordering number, highest value is placed top most
|
||||
- `iconName` - Icon names can be found from https://fontawesome.com/icons?d=gallery&m=free
|
||||
- `iconFamily` - Icon family should match details on the site above
|
||||
- `iconColor` - Color of the icon that appears next to the value
|
||||
- `format` - `FormatType` tells that the value is time amount (milliseconds) or a timestamp
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>FormatTypes (Dates / Time amounts)</summary>
|
||||
|
||||
```
|
||||
@NumberProvider(
|
||||
...
|
||||
format = FormatType.DATE_YEAR
|
||||
)
|
||||
public long banDate(UUID playerUUID) {...}
|
||||
```
|
||||
|
||||
- `DATE_YEAR` - Value is an Epoch Millisecond, Formats the date based on Plan settings. Year is given importance
|
||||
- `DATE_SECOND` - Value is an Epoch Millisecond, Formats the date based on Plan settings. Seconds are given importance
|
||||
- `TIME_MILLISECOND` - Value is amount of milliseconds, Formats time amount based on Plan settings.
|
||||
- `NONE` - Value is not formatted
|
||||
|
||||
</details>
|
||||
|
||||
### `@DoubleProvider`
|
||||
|
||||
**Speciality:** Floating point numbers
|
||||
|
||||
<details>
|
||||
<summary>Usage & Parameters</summary>
|
||||
|
||||
```
|
||||
@DoubleProvider(
|
||||
text* = "Balance",
|
||||
description = "Amount of money the player has",
|
||||
priority = 3,
|
||||
iconName = "question",
|
||||
iconFamily = Family.SOLID,
|
||||
iconColor = Color.NONE
|
||||
)
|
||||
public double balance(UUID playerUUID) {...}
|
||||
```
|
||||
|
||||
- `text` - Text that appears next to the value, for example "Has Island: No"
|
||||
- `description` - Text that appears when hovering over the value
|
||||
- `priority` - Ordering number, highest value is placed top most
|
||||
- `iconName` - Icon names can be found from https://fontawesome.com/icons?d=gallery&m=free
|
||||
- `iconFamily` - Icon family should match details on the site above
|
||||
- `iconColor` - Color of the icon that appears next to the value
|
||||
|
||||
</details>
|
||||
|
||||
### `@PercentageProvider`
|
||||
|
||||
**Speciality:** Percentages between 0% and 100%. Requires return values between 0.0 and 1.0.
|
||||
|
||||
<details>
|
||||
<summary>Usage & Parameters</summary>
|
||||
|
||||
```
|
||||
@PercentageProvider(
|
||||
text* = "Quest completion",
|
||||
description = "Quest completion percentage",
|
||||
priority = 5,
|
||||
iconName = "question",
|
||||
iconFamily = Family.SOLID,
|
||||
iconColor = Color.NONE
|
||||
)
|
||||
public double questCompletion(UUID playerUUID) {...}
|
||||
```
|
||||
|
||||
- `text` - Text that appears next to the value, for example "Has Island: No"
|
||||
- `description` - Text that appears when hovering over the value
|
||||
- `priority` - Ordering number, highest value is placed top most
|
||||
- `iconName` - Icon names can be found from https://fontawesome.com/icons?d=gallery&m=free
|
||||
- `iconFamily` - Icon family should match details on the site above
|
||||
- `iconColor` - Color of the icon that appears next to the value
|
||||
|
||||
</details>
|
||||
|
||||
### `@StringProvider`
|
||||
|
||||
**Speciality:** String values, Links to player page when `playerName` is `true`
|
||||
|
||||
<details>
|
||||
<summary>Usage & Parameters</summary>
|
||||
|
||||
```
|
||||
@StringProvider(
|
||||
text* = "Town Name",
|
||||
description = "What town the player has residency in.",
|
||||
priority = 5,
|
||||
iconName = "question",
|
||||
iconFamily = Family.SOLID,
|
||||
iconColor = Color.NONE,
|
||||
playerName = false
|
||||
)
|
||||
public String townName(UUID playerUUID) {...}
|
||||
```
|
||||
|
||||
- `text` - Text that appears next to the value, for example "Has Island: No"
|
||||
- `description` - Text that appears when hovering over the value
|
||||
- `priority` - Ordering number, highest value is placed top most
|
||||
- `iconName` - Icon names can be found from https://fontawesome.com/icons?d=gallery&m=free
|
||||
- `iconFamily` - Icon family should match details on the site above
|
||||
- `iconColor` - Color of the icon that appears next to the value
|
||||
- `playerName` - Does this provider return a player name that can be linked to? Links are automatic
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Links to player pages</summary>
|
||||
|
||||
```
|
||||
@StringProvider(
|
||||
...
|
||||
playerName = true
|
||||
)
|
||||
public String townMayor(Group town) {...}
|
||||
```
|
||||
|
||||
- If `playerName` is `true`, the returned value will be formatted to display a link to a player's page.
|
||||
|
||||
</details>
|
||||
|
||||
## 🔨 Special Provider annotations
|
||||
|
||||
These annotations can be used to add information structures. They might have different limitations than other providers.
|
||||
|
||||
### `@GroupProvider`
|
||||
|
||||
> `@GroupProvider` will be included in the second update for DataExtension API.
|
||||
|
||||
**Speciality:** Multiple `Group`s the player is in. Any providers with `Group` parameter will be called with the groups that this method provides.
|
||||
|
||||
<details>
|
||||
<summary>Limitations and Additional data</summary>
|
||||
|
||||
- There can only be one GroupProvider per DataExtension - If you need multiple kinds of groups, create another `DataExtension` class.
|
||||
- Method requires UUID or String as method parameter.
|
||||
- Does not work with `@Tab` annotations
|
||||
|
||||
Plan will construct following from given group data:
|
||||
|
||||
- Players in different groups are counted
|
||||
- Additional data given by `Group` parameter methods about each group.
|
||||
- Additional data about players is grouped based on groups.
|
||||
- Additional data is displayed under a dropdown of the group.
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>Usage & Parameters</summary>
|
||||
|
||||
```
|
||||
@GroupProvider(
|
||||
text* = "Jobs",
|
||||
description = "What jobs the player has",
|
||||
priority = 5,
|
||||
iconName = "question",
|
||||
iconFamily = Family.SOLID,
|
||||
iconColor = Color.NONE
|
||||
)
|
||||
public String[] playerJobs(UUID playerUUID) {...}
|
||||
```
|
||||
|
||||
- `text` - Text that appears next to the value on Player's page, for example "Jobs: None"
|
||||
- `description` - Text that appears when hovering over the value
|
||||
- `priority` - Ordering number, highest value is placed top most
|
||||
- `iconName` - Icon names can be found from https://fontawesome.com/icons?d=gallery&m=free
|
||||
- `iconFamily` - Icon family should match details on the site above
|
||||
- `iconColor` - Color of the icon that appears next to the value
|
||||
|
||||
</details>
|
||||
|
||||
### `@TableProvider`
|
||||
|
||||
> `@TableProvider` will be included in the second update for DataExtension API.
|
||||
|
||||
**Speciality:** Table structures.
|
||||
|
||||
<details>
|
||||
<summary>Limitations</summary>
|
||||
|
||||
- Player tables can have 4 columns.
|
||||
- Server tables can have 5 columns.
|
||||
|
||||
> If you want to display a table that lists how many players are using something (or data about groups), eg. Players on each version, use `@GroupProvider` (and `Group` parameter methods) instead.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Usage & Parameters</summary>
|
||||
|
||||
```
|
||||
@TableProvider(tableColor = Color.NONE)
|
||||
public Table banHistory(UUID playerUUID) {
|
||||
Table.Factory banTable = Table.builder()
|
||||
.columnOne("When", new Icon(Family.SOLID, "gavel")) // Define column names and icons
|
||||
.columnTwo("...", new Icon(...)) // Icon colors are ignored.
|
||||
.columnThree("...", new Icon(...))
|
||||
.columnFour("...", new Icon(...));
|
||||
|
||||
for (YourData data : yourData) {
|
||||
banTable.addRow(String...);
|
||||
}
|
||||
|
||||
return banTable.build();
|
||||
}
|
||||
```
|
||||
|
||||
- `tableColor` - Color of the table header.
|
||||
|
||||
</details>
|
||||
|
||||
### `@GraphProvider`
|
||||
|
||||
**Speciality:** Graphs.
|
||||
|
||||
This will be implemented later.
|
||||
|
||||
## 📐 Extra annotations
|
||||
|
||||
These annotations can be used to further control how the values are displayed.
|
||||
|
||||
### `@Tab`, `@TabInfo` and `@TabOrder`
|
||||
|
||||
**Specialilty:** Control what plugin-tab the provided value appears in.
|
||||
|
||||
<details>
|
||||
<summary>Usage & Parameters</summary>
|
||||
|
||||
```
|
||||
@TabInfo(
|
||||
tab* = "Economy",
|
||||
iconName = "circle",
|
||||
iconFamily = Family.SOLID,
|
||||
elementOrder = {ElementOrder.VALUES, ElementOrder.TABLE, ElementOrder.GRAPH}
|
||||
)
|
||||
@TabInfo(tab* = "Second Tab")
|
||||
@TabOrder({"Economy", "Second Tab"})
|
||||
@PluginInfo(...)
|
||||
public class YourExtension implements DataExtension {
|
||||
|
||||
@BooleanProvider(text = "Has Pet")
|
||||
@Tab("Second Tab")
|
||||
public boolean hasPet(UUID playerUUID) {...}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
- `tab` - Name of the tab
|
||||
- `iconName` - Icon names can be found from https://fontawesome.com/icons?d=gallery&m=free
|
||||
- `iconFamily` - Icon family should match details on the site above
|
||||
- `elementOrder` - Order different elements are placed inside the tab. `VALUES` represents all single values
|
||||
|
||||
</details>
|
||||
|
||||
### `@Conditional`
|
||||
|
||||
**Specialilty:** Control execution of another methods. If provided `boolean` is `true` the method with `@Conditional` annotation will be called.
|
||||
|
||||
<details>
|
||||
<summary>Usage & Parameters</summary>
|
||||
|
||||
```
|
||||
@BooleanProvider(..., conditionName="hasPet")
|
||||
public boolean hasPet(UUID playerUUID) {...}
|
||||
|
||||
@Conditional("hasPet")
|
||||
@StringProvider(text = "Pet Name")
|
||||
public String petName(UUID playerUUID) {...}
|
||||
```
|
||||
|
||||
- `value` - Name of the condition
|
||||
- `negated` - Require the condition to be `false` for this method to be called.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Reversed Conditions</summary>
|
||||
|
||||
```
|
||||
@BooleanProvider(..., conditionName="permanentBan")
|
||||
public boolean isPermanentlyBanned(UUID playerUUID) {...}
|
||||
|
||||
@Conditional(value = "permanentBan", negated = true)
|
||||
@NumberProvider(...)
|
||||
public long expiryDate(UUID playerUUID) {...}
|
||||
```
|
||||
|
||||
- Negated Conditionals are only called when the provided condition is `false`.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Nested Conditions (Conjunction / AND)</summary>
|
||||
|
||||
```
|
||||
@BooleanProvider(..., conditionName="isBanned")
|
||||
public boolean isBanned(UUID playerUUID) {...}
|
||||
|
||||
@Conditional("isBanned")
|
||||
@BooleanProvider(..., conditionName="isTemporaryBan")
|
||||
public boolean isTemporaryBan(UUID playerUUID) {...}
|
||||
|
||||
@Conditional("isTemporaryBan")
|
||||
@NumberProvider(...)
|
||||
public long expireDate(UUID playerUUID) {...}
|
||||
```
|
||||
|
||||
- Conditions can be nested by adding a `@Conditional` `@BooleanProvider` that returns a second condition.
|
||||
|
||||
</details>
|
||||
|
||||
### `@InvalidateMethod`
|
||||
|
||||
**Speciality:** Removes old values from database if you decide to rename a method. The method name is used when storing the values, so this annotation exists to remove the old values.
|
||||
|
||||
<details>
|
||||
<summary>Usage & Parameters</summary>
|
||||
|
||||
```
|
||||
@InvalidateMethod("oldMethodName")
|
||||
@PluginInfo(...)
|
||||
public class YourExtension implements DataExtension {
|
||||
@BooleanProvider(...)
|
||||
public boolean newMethodName(UUID playerUUID) {...}
|
||||
}
|
||||
```
|
||||
|
||||
- `value` - Name of a removed method, for removing stored results of that method.
|
||||
|
||||
</details>
|
||||
|
||||
## ❕ Preventing runtime errors
|
||||
|
||||
Since annotations do not have any compiler checks, invalid implementation can not be enforced at compile time, and runtime exceptions are used instead.
|
||||
|
||||
To make implementation easier it is possible to Unit test against the implementation errors.
|
||||
|
||||
How:
|
||||
```
|
||||
@Test
|
||||
public void noImplementationErrors() {
|
||||
DataExtension yourExtension = new YourExtensionImplementation();
|
||||
|
||||
// Throws IllegalArgumentException if there is an implementation error or warning.
|
||||
new ExtensionExtractor(yourExtension).validateAnnotations();
|
||||
}
|
||||
```
|
||||
|
||||
### Implementation violations
|
||||
|
||||
Here is a short list of what throws an exception
|
||||
|
||||
- No `@PluginInfo` class annotation
|
||||
- Class contains no public methods with Provider annotations
|
||||
- Class contains private method with Provider annotation
|
||||
- Non-primitive return type when primitive is required (eg. `Boolean` instead of `boolean`)
|
||||
- Method doesn't have correct parameters (none, UUID, String or Group)
|
||||
- `@BooleanProvider` is annotated with a `@Conditional` that requires same condition the provider provides.
|
||||
- `@Conditional` without a `@BooleanProvider` that provides value for the condition
|
||||
|
||||
Warnings:
|
||||
|
||||
- An annotation String `<variable>` is over 50 characters (Or over 150 if `description`)
|
||||
- Method name is over 50 characters (Used as an identifier for storage)
|
||||
|
||||
## API in action
|
||||
|
||||
If you would like to see how the API is being used in built in plugin support, [check out implementations in repositories that start with Extension](https://github.com/plan-player-analytics)
|
Loading…
Reference in New Issue