Guide to Annotations

NeuroKernel Applications may use a list of annotations to ease the code generation, configuration and caching. Here you will find the detailed explanation of each annotation used in NeuroKernel API. Some of these annotations can only be used with the main application class that extends the NApplication class.

1. Configure Annotation

Configure annotation is used to set the runtime preferences of a task. This annotation can only be used with application main class to be effective.

Method Description
value Name of the application
pluggable if true, application can be plugged into another application
compileIn Modules to include
compileOut Modules to exclude for smaller size
socketTransport If true and running at server, use web sockets to communicate
target Target NeuroKernel version
import com.neurokernel.client.*;
import com.neurokernel.client.annotation.Configure;
import com.neurokernel.client.annotation.LoadResources;
import com.neurokernel.client.annotation.Source;
 
@LoadResources(
     resources = {
        @Source(value = "resources/banner.png", name = "banner")
     }
)
@Configure(socketTransport=true)
public class ConfigureExample extends NApplication {
      @Override
      public void main(int argc, String[] argv) {
          NFrame mainFrame=getMainFrame();
          new NImageView(mainFrame, (NImage)getResource("banner"));
 
          mainFrame.setTitle("Configure");
          mainFrame.setBounds(20,20,200,200);
          mainFrame.setVisible(true);
      }
}

2. Executable Annotation

This annotation is used to create necessary bootstrap files for an application. It can only be used with classes extending NApplication. Both Remote and Executable annotations can be used at the same time. Remote annotation is used as target for generating bootstrap files if both are defined. Applications solely deployed to servlet container and require JRE to run at server side, does not need this annotation.

Method Description
value Name of the application
archives Resources to pre-load if any
cache Caches entire application to an offline storage
compress Also compress the generated files
developerMode Sets the developer mode
mergedExecutable Merge compiled code to a single file
version Application Version
whiteList List of whiteList sites
workerOnly Support executing application only in a worker
workerSupport Support executing application in a worker
import com.neurokernel.client.*;
import com.neurokernel.client.constants.CodeSegment;
import com.neurokernel.client.annotation.Executable;
import com.neurokernel.client.annotation.LoadResources;
import com.neurokernel.client.annotation.Source;
 
@Executable (
        value = "Banner",
        version= "0.1",
        workerSupport=true,
)
@LoadResources(
     resources = {
        @Source(value = "resources/banner.png", name = "banner")
     }
)
public class ExecutableExample extends NApplication {
      @Override
      public void main(int argc, String[] argv) {
          NFrame mainFrame=getMainFrame();
          new NImageView(mainFrame, (NImage)getResource("banner"));
 
          mainFrame.setTitle("Executable");
          mainFrame.setBounds(20,20,200,200);
          mainFrame.setVisible(true);
      }
}

2.1 Exclude Annotation

This annotation tells generator to exclude specified task container modules from the executable code to shrink the produced code size. This is for advanced development because wrong doing will break execution at some point. It is important to note that there must be either Excludes or Includes. Both can not be used, and first one defined will be taken and processed.

Method Description
value type of code segment

2.2 Include Annotation

This annotation tells generator which task container modules to include in the executable code and omit the others to shrink the generated code size. This is for advanced development because wrong doing will break execution at some point.

Method Description
value type of code segment

2.3 Code Segment Types

Code segments are the designators of sub modules available in a task container which can be included or excluded from the executable code to shrink the size of the file generated. This enum class is used with Exclude and Include annotations.

Code Segment Description
CALLBACKS Callback support
DEVICES Device support
FILESYSTEMS File System support
GAMEPAD Gamepad support
MAINFRAME Main frame and UI support
PEERPORTS Peer ports support
PLUGIN Plugin support
PLUGIN_BRANCHES Plugin Branch support
PLUGIN_CANVAS Plugin Canvas support
PLUGIN_DEVICES Plugin Device support
PLUGIN_FILESYSTEM Plugin File System support
PORTS Port handling support
PROTOCOL_CACHE Protocol cache support
SERVICES Service call support
STORAGE Client Storage support
TERMINAL Terminal IO support
TORRENTS Torrents support
WEBSOCKET Web Socket support
WORKERS Web Worker support

3. Remote Annotation

This annotation is used to create necessary remotely accessible bootstrap files for an application. It can only be used with classes extending NApplication. Executable annotation will be ignored when Remote annotation is used. There is an internal Executable annotation definition in Remote annotation.

Method Description
value Name of the application
executable Executable annotation for remote application
addMetaData Adds meta data to the boot strapping page
arguments Information about the arguments allowed
author Author of the application
description Description of the application
desktopMode Application may execute in desktop mode if available
execCommand Execute command of the application
image base64 URI encoded application icon image
keywords Keywords for the application for indexing by search engines
title Application title

NeuroKernel meta tags generated for the remote application are listed below depending on the annotation configuration entered. An application may have more than one device implementation including a file system.

Meta Tag Description
neurokernel:title Name of the application
neurokernel:version Application title
neurokernel:description Description of the application
neurokernel:image base64 url encoded application icon image
neurokernel:author Author of the application
keywords Keywords for the application for indexing by search engines
neurokernel:exec Execute command of the application
neurokernel:arguments Information about the arguments allowed
neurokernel:filesystem file system is any implemented
neurokernel:deviceX Device X (X being the device number)
neurokernel:deviceXname Device X name
neurokernel:deviceXversion Device X version
neurokernel:deviceXvendor Device X vendor
neurokernel:deviceXicon Device X icon in base64 URI encoded format
neurokernel:deviceXmethod Device X method (multiple of these tags are allowed)
import com.neurokernel.client.*;
import com.neurokernel.client.annotation.*;
 
@LoadResources(
     resources = {
        @Source(value = "resources/banner.png", name = "banner")
     }
)
@Remote( 
     value="appcachedemo",
     executable = @Executable (
           version= "0.1",
           workerSupport=true,
     )
);
public class RemoteExample extends NApplication {
      @Override
      public void main(int argc, String[] argv) {
          NFrame mainFrame=getMainFrame();
          new NImageView(mainFrame, (NImage)getResource("banner"));
 
          mainFrame.setTitle("Remote Example");
          mainFrame.setBounds(20,20,200,200);
          mainFrame.setVisible(true);
      }
}

4. LoadResources Annotation

LoadResources tells bootstrap file generator to include the resources in the executable so that task can automatically load resources and make them available from getResource method of NApplication class. This includes all runtime targets. This annotation can only be used with application and container classes. For applications, which require JRE to execute at server side, this annotation can still be used but the resources must be manually put the required folders in the class path of the application.

Method Description
value name of the application
loadIcon Application icon is automatically searched
resources Resources to pre-load
import com.neurokernel.client.*;
import com.neurokernel.client.annotation.LoadResources;
import com.neurokernel.client.annotation.Source;
 
@LoadResources(
        resources = {
            @Source(value = "resources/myicon.gif", name = "appicon")
            @Source(value = "resources/banner.png", name = "banner"),
        }, 
        loadIcon = false
)
public class ResourcesExample extends NApplication {
      @Override
      public void main(int argc, String[] argv) {
          loadIcon((NImage)getResource("appicon"));
 
          NFrame mainFrame=getMainFrame();
          new NImageView(mainFrame, (NImage)getResource("banner"));
 
          mainFrame.setTitle("Resources");
          mainFrame.setBounds(20,20,200,200);
          mainFrame.setVisible(true);
      }
}

4.1 Source Annotation

Source annotation is used to define a source for a resource such as Image in LoadResources annotation

Method Description
value Source data path
binary Resource is Binary or Text
name Resource name
merge Merge source to executable or deploy to server

5. Device Annotation

A Plugin application can define one or more devices to be used by the parent application. The advantage of using a device is the way the IPC is used. Although the event based communication is still available to use, devices also introduce RPC methods that can be called by parents. This makes the use same type devices by different applications from different authors to be used for the same purpose. The devices must have the same footprint by their name and method definitions. Some commonly used devices may be standardized by NeuroKernel Research via an NDR (NeuroKernel Device Request). NDRs will be considered after NeuroKernel is widely adapted by the community.

Method Description
value Name of the device
icon Base64 URI encoded device icon
methods List of device methods
target Minimum targeted NeuroKernel version
title Short description of the device
type Device type
vendor Device vendor
version Device version
visual Device has visual either as an interface or presentation
import com.neurokernel.client.system.ICallback;
import com.neurokernel.client.device.*;
import com.neurokernel.client.NApplication;
import com.neurokernel.client.constants.DataType;
import com.neurokernel.client.annotation.Device;
import com.neurokernel.client.annotation.Method;
import java.util.Date;
 
@Device(
        value="NDayTime", 
        type="DayTimeDevice", 
        methods={
            @Method(value="getTime",returnType=DataType.LONG),
            @Method(value="getDate",returnType=DataType.DATE)
        }
)
public class NDayTimeDevice extends NApplication {
    Date currentDate=new Date();
    NMethod getTime;
 
    @Override
    public void main(int argc, String[] argv) {
         NDevice deviceInfo=getSystem().getDevice();
 
         if(deviceInfo!=null) {
             getTime=deviceInfo.getDeviceMethod("getTime").setCallProcessor(new IMethodCall() {
                 @Override
                 public Object process(IAsyncResponse response,Object... args) {
                     return currentDate.getTime();
                 }
             });
 
             deviceInfo.getDeviceMethod("getDate").setCallProcessor(new IMethodCall() {
                 @Override
                 public Object process(IAsyncResponse response,Object... args) {
                     return currentDate;
                 }
             });
         }
    }
}

5.1 Method Annotation

Devices can define any number of methods which are used for RPC (Remote Procedure Call). It is not used for implementation. It is used to create a device definition info so that it can be easily recognized and used by plugin container and plugin system itself.

Method Description
value Device method name
description Method description
returnType Return type of the method
params List of parameter types

6. DeviceArray Annotation

An application can defined and handle any number of devices in itself. This annotation is used to define multiple device profiles.

Method Description
devices List of devices
import com.neurokernel.client.*;
import com.neurokernel.annotation.*;
 
@DeviceArray(
        devices={
            @Device(
                    value="TempGauge", 
                    type="GaugeDevice", 
                    title="Temperature Gauge",
                    visual=true,
                    methods={
                        @Method(value="setValue",params=DataType.INTEGER),
                    }
            ),
            @Device(
                    value="NDayTime", 
                    type="DayTimeDevice", 
                    methods={
                         @Method(value="getTime",returnType=DataType.LONG),
                         @Method(value="getDate",returnType=DataType.DATE)
                    }
            )
        }
)
public class DeviceArray extends NApplication {
    Date currentDate=new Date();
    NMethod getTime;
    NGauge gauge;
 
    @Override
    public void main(int argc, String[] argv) {
        NFrame mainFrame=getMainFrame();
        renderGauge(mainFrame);
 
        NDevice deviceInfo=getSystem(). getDeviceByType("DayTimeDevice");
 
        getTime=deviceInfo.getDeviceMethod("getTime").setCallProcessor(new IMethodCall() {
            @Override
            public Object process(IAsyncResponse response,Object... args) {
                return currentDate.getTime();
            }
        });
 
        deviceInfo.getDeviceMethod("getDate").setCallProcessor(new IMethodCall() {
            @Override
            public Object process(IAsyncResponse response,Object... args) {
                return currentDate;
            }
        });
 
        deviceInfo=getSystem().getDeviceByType("GaugeDevice");
 
        deviceInfo.getDeviceMethod("setValue").setCallProcessor(new IMethodCall() {
            @Override
            public Object process(IAsyncResponse response,Object... args) {
               gauge.setValue((Integer)args[0],false);
               return null;
            }
        });
    }
 
    private void renderGauge(NContainer container) {
        gauge=new NGauge(container);
        gauge.setMinimum(-50);
        gauge.setMaximum(50);
        gauge.setName("Temperature");
        gauge.setStrokeTicks(false);
        gauge.setShadowGlow(true);
        gauge.setUnits("°C");
 
        gauge.setColor(NGauge.GaugePart.PLATE, new NColor(0x22,0x22,0x22));
        gauge.setColor(NGauge.GaugePart.MAJOR_TICKS, new NColor(0xf5,0xf5,0xf5));
        gauge.setColor(NGauge.GaugePart.MINOR_TICKS, new NColor(0xdd,0xdd,0xdd));
        gauge.setColor(NGauge.GaugePart.TITLE, NColor.WHITE);
        gauge.setColor(NGauge.GaugePart.NUMBERS, new NColor(0xee,0xee,0xee));
        gauge.setMajorTicks("-50","-40","-30","-20","-10","0","10","20","30","40","50");
        gauge.setValueBox(new NGaugeValueBox().setValueFormat(2,2));
        gauge.addColorRange(-50, 0, new NColor(0,255,0,50));
        gauge.addColorRange(0, 50, new NColor(255,0,0,50));
        gauge.setValue(0,false);
 
        container.setBackground(NColor.BLACK);
    }
}

7. ProtocolCache Annotation

Applications can cache their protocol from the initial launch to up until the main window is fully visible on the screen. This will increase the launch speed of the applications because protocol is already created for the main window and stored. Protocol can be stored to persistent storage if available so that when the same application is executed again in a new session, system will pick its initial protocol from the persistent storage and immediately process it. Initial protocol for each window can also be cached to persistent storage. For remote applications, request to access to the data storage may be asked by the browser.

Method Description
value Name of the protocol cache point
clearif Clears the protocol cache from storage if given name exists
dynamic Protocol cache is allowed to take multiple paths if true
persist Stores the protocol to persistent client storage if true
import com.neurokernel.client.*;
import com.neurokernel.client.annotation.*;
 
@ProtocolCache("ProtocolCache")
public class ProtocolCacheExample extends NApplication {
      @Override
      public void main(int argc, String[] argv) {
          NFrame mainFrame=getMainFrame();
          new NButton(mainFrame, "Hello");
 
          mainFrame.setTitle("Protocol Cache Example");
          mainFrame.setBounds(20,20,200,200);
          mainFrame.setVisible(true);
      }
}

8. ApplicationCache Annotation

NeuroKernel client side applications can be cached to the browser for offline access. This may be particularly useful if the site to the application is down. Service workers are supported including fallback to AppCache mode. There may be client based limitations that could be solved in a later version. Please take note that, the site must have an HTTPS certification for this to work.

Method Description
value Name of the service installer
cacheAll List of files to cache
fallback Allow falling back to AppCache
rootURL AppCache manifest only
version Cache version
import com.neurokernel.client.*;
import com.neurokernel.client.annotation.*;
 
@LoadResources(
        resources = {
            @Source(value = "resources/banner.png", name = "banner"),
        }
)
@Executable(
        cache = {
            @ApplicationCache(version = "1.0")
        }
)
public class AppCacheExample extends NApplication {
      @Override
      public void main(int argc, String[] argv) {
          NFrame mainFrame=getMainFrame();
          new NImageView(mainFrame, (NImage)getResource("banner"));
 
          mainFrame.setTitle("AppCache Example");
          mainFrame.setBounds(20,20,200,200);
          mainFrame.setVisible(true);
      }
}