Funkcje pozwalają na deklaratywne przetwarzanie danych bez konieczności pisania własnego kodu. Rozwiązanie to opiera się na wywoływaniu wybranej funkcji (użytkownicy mogą dostarczać własne specyficzne implementacje) i przekazaniu wyniku tej funkcji dalej np. do zadania automatycznego. W przypadku podstawowych działań matematycznych, kwotowych, tekstowych czy logicznych możliwe jest zrealizowanie prostych przekształceń bez napisania linijki kodu.
Tworzone funkcje powinny być ja najbardziej ogólne i elastyczne. Pozwoli to na wykorzystanie ich w większej liczbie przypadków. System pozwala na rejestrowanie i wykorzystywanie predefiniowanych funkcji zarówno po stronie serwera jak i po stronie przeglądarki.
Spis wbudowanych funkcji systemowych dostępny jest na stronie: Dostępne funkcje |
Wszystkie operacje związane z działaniami na funkcjach stanowią FunctionAPI.
W tworzonych akcjach po stronie przeglądarki wspierany jest standard ECMAScript 6. |
Funkcja musi zawsze być zarejestrowana po stronie serwera oraz może dodatkowo być zarejestrowana po stronie przeglądarki, gdy chcemy, aby była też tam wykorzystywana. |
Rejestracja funkcji dostępnych w systemie odbywa się podczas uruchomienia systemu oraz dynamicznie dla dynamicznych zasobów, takich jak wtyczki. Za rejestrację i przechowywanie funkcji odpowiada . Podczas rejestracji wyszukiwane są najpierw wszystkie klasy oznaczone adnotacją @
, następnie w tych klasach wyszukiwane są metody oznaczone adnotacją @
i zostają one zarejestrowane jako funkcje.
Rejestrowana funkcja musi:
Poniższy przykład przedstawia definicję prostej funkcji zwracającej wartość większej liczby.
@Functions public class BasicFunctions { @Function public Integer maxOf( Integer a, Integer b ) { return Math.max( a, b ); } } |
Można określić, czy funkcja dotyczy tylko serwera (można jej użyć tylko na serwerze), czy tylko przeglądarki (można jej użyć tylko w javascript), czy obu miejsc. Odpowiada za to parametr accessibility, który można ustawić w adnotacji @. Parametr jest typu @
i może przyjmować następujące wartości:
Brak ustawionego parametru accessibility odpowiada wartości ALL.
Poniższy przykład pokazuje definicję funkcji, która jest dostępna tylko dla komponentów serwerowych. Funkcja zwraca imię i nazwisko użytkownika na podstawie jego loginu.
@Functions public class BasicFunctions { @Function( accessibility = FunctionAccessibility.SERVER ) public String userFullName( String userName ) { User user = userService.getUser( userName ); if ( user == null ) { return null; } return user.getFullName(); } } |
Jeżeli robimy funkcję tylko dla przeglądarki, to na serwerze również musi być funkcja zdefiniowana, ale jej implementacja nie musi nic robić. Służyć ona ma tylko do pobrania nazwy i parametrów funkcji i wyświetlania jej w PWE.
Kontekst funkcji zawiera identyfikator oraz definicję aktualnie przetwarzanego procesu i zadania. Pobranie kontekstu możliwe jest tylko po stronie serwera za pomocą poniższego kodu.
FunctionContext context = FunctionContext.current(); // statyczne pobranie kontekstu String processId = context.getProcessId(); // id procesu String activityId = context.getActivityId(); // id zadania String processDefId = context.getProcessDefId(); // id definicji procesu String activityDefId = context.getActivityDefId(); // id definicji zadania |
Używanie stworzonej funkcji po stronie przeglądarki (na formularzu zadania) wymaga od programisty dostarczenia jej implementacji w języku JavaScript. Taka implementacja wykorzystywana jest podczas dynamicznych obliczeń po stronie przeglądarki klienta.
W przypadku funkcji z implementacją JavaScript należy dodatkowo wskazać poprzez adnotację gdzie znajduje się skrypt, który zawiera implementacje tych funkcji. Należy wskazać bezwzględną ścieżkę do zasobu w
classpath
. Zasób przechowywany w src/main/resources/functions/basic-functions.js
wskażemy tak:
@Functions @FunctionsScript("/functions/basic-functions.js") public class BasicFunctions { ... } |
Funkcje rejestrowane są z wykorzystaniem API (skrócona nazwa
PW.Functions
):
// funkcja "max" która zwraca obiekt typu "float" i przyjmuje 2 parametry typu "float" PW.Functions.register("max", "float", ["float", "float"], function(value1, value2){ return Math.max(value1, value2); }); // funkcja "upper" która zwraca obiekt typu "string" i przyjmuje 1 parametry typu "string" PW.Functions.register("upper", "string", ["string"], function(text){ return text.toUpperCase(); }); |
Podczas rejestracji funkcji niezbędne jest zdefiniowanie:
Tak zarejestrowana funkcja zostanie wywołana tylko dla wywołań z argumentami które będą pasowały do zdefiniowanych typów. Możliwe typy opisane są w Wbudowane typy.
Rejestracja funkcji we wtyczce jest taka sama jak zostało to opisane powyżej, jednak należy dodatkowo zaznaczyć, że wtyczka ta udostępnia funkcje do zarejestrowania. W tym celu należy w pliku suncode-plugin.xml dodać wpis:
<functions key="functions" /> |
Taki wpis spowoduje automatyczne wyszukanie wszystkich zdefiniowanych we wtyczce funkcji.
Funkcje tłumaczone są automatycznie, jeżeli dostępne są tłumaczenia funkcji stworzone z wykorzystaniem mechanizmu internacjonalizacji. Poniżej opisano zasady tworzenia kluczy tłumaczeń.
Tłumaczeniu podlegają:
Klucze tłumaczeń funkcji muszą być tworzone z zachowaniem następujących zasad:
Tłumaczony element | Szablon |
---|---|
Opis funkcji |
gdzie
|
Nazwa parametru |
gdzie
|
Opis parametru |
gdzie
|
Opis dla przestarzałej funkcji | function.<name>.deprecated.description gdzie
|
Przykład:
Dla funkcji zdefiniowanej w następujący sposób:
@Function public boolean isHoliday(LocalDate date) { // implementacja } |
Tłumaczenia wyglądały będą następująco:
function.isHoliday=Sprawdza czy data wskazuje dzień wolny od pracy function.isHoliday.param.date.name=Data function.isHoliday.param.date.desc=Sprawdzana data |
Dla przestarzałej funkcji zdefiniowanej w następujący sposób:
@Function @Deprecated public boolean isHoliday(LocalDate date) { // implementacja } |
Tłumaczenia wyglądały będą następująco:
function.isHoliday=Sprawdza czy data wskazuje dzień wolny od pracy function.isHoliday.param.date.name=Data function.isHoliday.param.date.desc=Sprawdzana data function.isHoliday.deprecated.description=Funkcja jest przestarzała i należy korzystać z funkcji isHoliday(LocalDate date, Locale locale) |
Każda funkcja może mieć wiele przeciążeń, które przyjmują inne parametry. Może istnieć potrzeba nadania innych opisów dla tych parametrów lub innego opisu funkcji. Jest to możliwe poprzez dodanie do nazwy funkcji wykorzystywanej w kluczu tłumaczenia typów parametrów rozdzielonych podkreślnikiem (_). Domyślnym tłumaczeniem jest to bez typów parametrów.
Nazwy typów dostępne są tutaj: Wbudowane typy
Przykład:
Dla funkcji zdefiniowanej w następujący sposób:
@Function public boolean isHoliday(LocalDate date) { // implementacja } @Function public boolean isHoliday(LocalDate[] dates) { // implementacja } @Function public boolean isHoliday(LocalDate[] dates, boolean all) { // implementacja } |
Tłumaczenia wyglądały będą następująco:
function.isHoliday=Sprawdza czy data wskazuje dzień wolny od pracy function.isHoliday.param.date.name=Data function.isHoliday.param.date.desc=Sprawdzana data function.isHoliday_date[]=Sprawdza czy wszystkie podane daty to dni wolne od pracy function.isHoliday_date[].param.dates.name=Daty function.isHoliday_date[].param.dates.desc=Sprawdzane daty function.isHoliday_date[]_boolean=Sprawdza czy podane daty to dni wolne od pracy function.isHoliday_date[]_boolean.param.dates.name=Daty function.isHoliday_date[]_boolean.param.dates.desc=Sprawdzane daty function.isHoliday_date[]_boolean.param.all.name=Wszystkie function.isHoliday_date[]_boolean.param.all.desc=Zaznacz jeżeli chcesz aby wszystkie daty były dniami wolnymi od pracy |