In this section, we will give an overview of the extension points defined by BASE. Most extension points are used in the web client to add buttons and menu items, but there are a few for the core API as well.
Menu items can be added to the top-level
MenuItemAction
The MenuItemAction.getMenuType()
provides support
for MENUITEM
, SUBMENU
and
SEPARATOR
menus. Which of the other properties that
are needed depend on the menu type. Read the javadoc for more information.
This extension point doesn't support custom javascripts or stylesheets and
the rendering is internal (eg. extensions can't provide their own renderers).
BASE ships with two action factories:
FixedMenuItemFactory
PermissionMenuItemFactory
Most toolbars on all list and single-item view pages can
be extended with extra buttons. Actions should implement
the interface: ButtonAction
ToolbarButtonRendererFactory
BASE ships with two action factories:
FixedButtonFactory
PermissionButtonFactory
Most item edit dialogs can be extended with additional tabs.
Actions should implement the interface: TabAction
BASE ships with two action factories:
FixedTabFactory
IncludeContentTabFactory
JspContext.ATTRIBUTE_KEY
.
A JSP or servlet should use this to hook into the current flow. Here is a code example:
// Get the JspContext that was created on the main edit page final JspContext jspContext = (JspContext)request.getAttribute(JspContext.ATTRIBUTE_KEY); // The current item is found in the context. NOTE! Can be null if a new item final BasicItem item = (BasicItem)jspContext.getCurrentItem(); // Get the DbControl and SessionControl used to handle the request (do not close!) final DbControl dc = jspContext.getDbControl(); final SessionControl sc = dc.getSessionControl();
The extra tab need to be paired with an extension that is invoked when
the edit form is saved. Each edit-dialog extension point has a corresponding
on-save extension point. Actions should implement the interface: OnSaveAction
OnSaveAction.onSave()
method is called first, but not until all regular properties have been
updated. If the transaction is committed the OnSaveAction.onCommit()
method is also called, otherwise the OnSaveAction.onRollback()
is called. The onSave()
method can throw an exception that
will be displayed to the user. The other callback method should not throw exceptions
at all, since that may result in undefined behaviour and can be confusing for the user.
The bioassay set listing for an experiment has a Tools
column which can be extended by extensions. This extension point is similar
to the toolbar extension points and actions should implement
the interface: ButtonAction
Note that the list can contain
BioAssaySet
Transformation
ExtraValue
JspContext.getItem()
method to examine the
current item.
The bioassay set page has a tab Overview plots.
The contents of this tab is supposed to be some kind of images
that have been generated from the data in the current bioassay set.
What kind of plots that can be generated typically depends on the
kind of data you have. BASE ships with an extension
(MAPlotFactory
OverviewPlotAction
PlotGenerator
Application.getStaticCache()
to get a
StaticCache
PlotServlet
A service is a piece of code that is loaded when the BASE web
server starts up. The service is then running as long as the BASE web
server is running. It is possible to manually stop and start services.
This extension point is different from most others in that it doesn't
affects the visible interface. Since services are loaded at startup time,
this also means that the context passed to ActionFactory methods will
not have any ClientContext
associated with it
(eg. the InvokationContext.getClientContext()
always return null). There is also no meaning for extensions to specify
a RendererFactory
. Service actions should
implement the interface:
ServiceControllerAction
start()
and
stop()
methods for controlling the service.
BASE doesn't ship with any service, but there is an FTP service
available at the BASE plug-ins site:
http://baseplugins.thep.lu.se/wiki/net.sf.basedb.ftp
This extension point adds support for using external files
in BASE. This is a core extension point and is available
independently of the web client. Actions should implement
the interface:
ConnectionManagerFactory
The getDisplayName()
and getDescription()
methods are used in the gui when a user manually selects which connection
manager to use. The supports(URI)
is used when auto-selecting
a connection manager based on the URI of the resource.
BASE ships with factory that supports HTTP and HTTPS file
references: HttpConnectionManagerFactory
See also
In those cases where files are used to store data instead
of importing it to the database, BASE can use extensions to
check that the supplied files are valid and also to extract
metadata from the files. For example, the
CelValidationAction
Validation and metadata extraction actions should implement
the ValidationAction
This extension point is a bit more complex than most other extension
points. To begin with, the factory class will be called with the
owner of the file set as the current item. Eg. the
ClientContext.getCurrentItem()
should return a
FileStoreEnabled
CelValidationFactory
RawBioAssay
Each file in the file set is then passed to the
ValidationAction.acceptFile(FileSetMember)
which may accept or reject the file. If the file is accepted it may
be accepted for immediate validation or later validation. The latter option
is useful in more complex scenarios were files need to be validated as a group.
If the file is accepted the ValidationAction.validateAndExtractMetadata()
is called, which is were the real work should happen.
The extensions for this extension point is also called when a file is replaced
or removed from the file set. The calling sequence to set up the validation is
more or less the same as described above, but the last step is to
call ValidationAction.resetMetadata()
instead
of ValidationAction.validateAndExtractMetadata()
.
This extension point makes it possible to detect changes that are made to item and generate log entries in real time. The core will send notifications for all item creations, updates and deletions to all registered logging managers. It is up to each implementation to decide if an event should be logged, where to log it and how much information that should be stored. The BASE core provides a logging implementation that save some information to the database which can also be viewed through the web interface.
The logging mechanism works on the data layer level and hooks into
callbacks provided by Hibernate. EntityLogger
LogManagerFactory
LogManager
Each registered action factory shoulds create a LogManagerFactory
public LogManager getLogManager(LogControl logControl);
Creates a log manager for a single transaction. Since a transaction is not thread-safe the log manager implementation doesn't have to be either. The factory has the possibility to create new log managers for each transaction.
public boolean isLoggable(Object entity);
Checks if changes to the given entity should be
logged or not. For performance reasons, it usually makes sense to
not log everything. For example, the database logger implementation
only logs changes if the entity implements the LoggableData
getEntityLogger()
.
public EntityLogger getEntityLogger(LogManager logManager,
Object entity);
Create or get an entity logger that knows how to log
changes to the given entity. If the entity should not be
logged, null
can be returned. This method
is called for each modified item in the transaction.
A new log manager is created for each transaction. The log manager is responsible for collecting all changes made in the transaction and store those changes in the appropriate place. The interface doesn't define any methods for this collection, since each implementation may have very different needs.
public LogControl getLogControl();
Get the log control object that was supplied by the BASE core when the transaction was started. The log controller contains methods for accessing information about the transaction, such as the logged in user, executing plug-in, etc. It can also be used to execute queries against the database to get even more information.
![]() |
Warning |
---|---|
Be careful about the queries that are executed by the log controller. Since all logging code is executed at flush time in callbacks from Hibernate we are not allowed to use the regular session. Instead, all queries are sent through the stateless session. The stateless session has no caching functionality which means that Hibernate will use extra queries to load associations. Our recommendation is to avoid quires that return full entities, use scalar queries instead to just load the values that are needed. |
public void afterCommit();
,
public void afterRollback();
An entity logger is responsible for extracting the changes
made to an entity and converting it to something that is useful
as a log entry. In most cases, this is not very complicated, but
in some cases, a change in one entity should actually be logged
as a change in a different entity. For example, changes to
annotations are handled by the AnnotationLogger
public void logChanges(LogManager logManager,
EntityDetails details);
This method is called whenever a change has been detected
in an entity. The details
variable contains
information about the entity and, to a certain degree,
what changes that has been made.
The item overview functionality allow extensions to load more items in the tree
structure. The extension point is a core extension point that is available
independently of the web client. Actions should implement the
ChildNodeLoaderAction
BasicItemNodeLoader
ClientContext
is the parent node. For example:
// From the ActionFactory interface public boolean prepareContext(InvokationContext<? super ChildNodeLoaderAction> context) { Node parentNode = (Node)context.getClientContext().getCurrentItem(); if (parentNode != null) { if (parentNode.getItem() instanceof Ownable) { return true; } } return false; }
The item overview functionality allow extensions to add validation code
to any item in the tree. There are two co-existing extension points, one
for the actual validation code and one for the validation rule defintions.
Both extension points are core extension points that is available
independently of the web client. Validation actions should implement the
NodeValidatorAction
NodeValidator
NameableNodeValidator
BasicNodeValidator
ClientContext
is type of that should be validated.
For example:
// From the ActionFactory interface public boolean prepareContext(InvokationContext<? super NodeValidatorAction> context) { return context.getClientContext().getCurrentItem() == Item.USER; }
Rule definition actions should implement the ValidationRuleAction
Validator
ReflectValidationRuleActionFactory
public static final
rule definition as an
action:
<extension id="validationrule.invalid-url" extends="net.sf.basedb.util.overview.validationrule"> <index>4</index> <about> <name>Invalid URL</name> <description>Checks if an URL has a valid syntax.</description> </about> <action-factory> <factory-class> net.sf.basedb.util.overview.extensions.ReflectValidationRuleActionFactory </factory-class> <parameters> <field>net.sf.basedb.examples.extensions.overview.OwnerValidator.INVALID_URL</field> </parameters> </action-factory> </extension>
The item overview functionality allow extensions to display additional information
about the currently selected node in the right pane in the web interface.
Each SectionAction
ActionFactory.prepareContext()
should be used to enable/disable
the extension depending on the node that is selected. BASE ships with the
IncludeContentSectionFactory
JspContext.ATTRIBUTE_KEY
.
A JSP or servlet should use this to hook into the current flow. Here is a code example:
// Get the JspContext that was created on the main edit page final JspContext jspContext = (JspContext)request.getAttribute(JspContext.ATTRIBUTE_KEY); // The currently selected node is found in the context. final Node node = (Node)jspContext.getCurrentItem(); // Get the DbControl and SessionControl used to handle the request (do not close!) final DbControl dc = jspContext.getDbControl(); final SessionControl sc = dc.getSessionControl();
This extension point makes it possible to add more columns to most major list pages
in the web interface. Actions should implement the ListColumnAction
Metadata methods, for example, the id and title of the column and if the column can be sorted, filtered, etc.
Rendering information, for example, CSS class and style information that is used for the column header.
Worker methods, that retrieve the value from the current item and format it for proper display. Different methods are used for the web display and for exporting to a file.
The AbstractListColumnBean
getValue()
method. Extending from this class makes it easy to your own implementations. BASE ships with the
PropertyPathActionFactory
Metadata