Cytoscape 3 Documentation : Architecture

Editor(s): MikeSmoot

Date: February 24th 2011

Status: First version

Background

Problems in Cytoscape 2.x

Cytoscape 2.x is the result of several years of coding effort by many people, all with different visions of how to design systems. Unfortunately, all of this work was done without explicit design guidelines or standards. As a result the core code has become increasingly tightly coupled and interdependent, making it very hard to maintain and improve. Some of the problems with Cytoscape 2.x include:

Cytoscape 3 Design

To address these problems we’ve introduced a few new technologies, produced a new API, and have substantially refactored Cytoscape.

New Technologies Used in Cytoscape 3

We’ve introduced a few new technologies to 3.0 to help solve many of our existing problems.

Don't Panic!

Relax! You don’t need to understand everything in depth! A few simple ideas will help, but with the Simple App you don’t even really need those! We’ll provide support!

General Application Structure

Cytoscape 3.0 strives for a modular architecture where the application consists of a set of jar files where each jar contributes a well defined subset of functionality to the application. The design is oriented around the OSGi service model (i.e. micro service) with API and implementation separated into different jar files. The goal is to provide a small number of API jars that define the public Cytoscape programming API. Each API jar will have one or more implementation jars that will consist of entirely private code. Implementation jars will provide instantiations of the service interfaces defined in the API jars. This approach allows different implementations of a given API to be easily switched. It also clearly designates which code is public and which code is private, thereby giving developers clear boundaries about what can and cannot be changed.

API Jars

The goal of an API jar is to provide a simple, complete, and clearly-defined programming interface that will only change in well-understood ways. By carefully constraining how we write APIs, we give ourselves greater flexibility in how the APIs get implemented and how we're able to change the APIs in the future. For our purposes, API jars will only contain a limited subset of Java classes. These include:

Interfaces The majority of the Cytoscape public API will consist of interfaces. Most interfaces will define OSGi services that will be provided by implementation jars. Some interfaces will be Service Provider Interfaces (SPI), which are interfaces meant to be implemented by API consumers.

Abstract Implementations In some cases it will be useful to provide abstract implementations of some interfaces as a convenience for users. Any abstract implementation should be clearly designed for inheritance, meaning all methods will need to be properly documented regarding what other methods they call and what (accessible) internal state gets changed. In general, we shouldn't be providing too many abstract implementations of interfaces.

Stateless Static Classes With the OSGi service model we have very limited need for static singleton classes, as such there will be far fewer classes containing only static methods in 3.0. In the rare case that we do provide a class with only static methods, then the class must be strictly stateless.

Final Classes There are some instances where we do want to provide implementations of certain classes as part of the API. These are generally very simple classes that are referenced by an interface and are free of any external dependencies. One example is the implementation of various event objects paired with their listener interfaces. These classes are best made final so that they cannot be extended. The benefit of making these classes final is that we can add methods to them without breaking backwards compatibility!

Enums Since enums are static and can't be extended or supplemented these are appropriate for inclusion in API jars. However, in contrast with the multiple fairly complicated enums found in 2.x (e.g. VisualPropertyType), we should keep our enums simple in 3.0. Anything complicated should be represented by interfaces (e.g. one type interface combined with one container interface that contains instances of the type interface).

Unit Tests Despite the lack of implementation, the API bundles should contain a large number of unit tests, some that will be executed by the API bundle and some that will be executed by implementation bundles. Any abstract, static, or final class should have full unit test coverage. If enums do anything fancy, they should have tests as well. All interfaces should be coupled with abstract test cases. The intent is for these abstract test cases is to provide implementation independent functional requirements that all implementations of the interface must pass. Implementation code will then be expected to write test cases that extend the abstract test cases provided by the API jar. This has the twin benefits of providing a clear implementation standard as well as making it extremely easy for implementations write a test suite.

Beyond that, very little should be included in API jars. There are very few cases where we will want to include a non-final public class. References to external libraries should be kept to an absolute minimum in API jars. Again, the goal is to have a small, clearly defined API whose implementation is clearly defined and that can be easily switched.

Implementation Jars

Implementation jars are meant to include the majority of the implementation code. The one thing an implementation jar must NOT do is publish its own API! That means all implementation packages should be marked by OSGi as private and should not be exported. Most implementation jars should only expose their implementations to the outside world by registering the services they provide using the OSGi service mechanism.

Utility Jars

There are some situations where it makes sense to bundle API and implementation in the same bundle. If the bundle is narrowly focused and alternative implementations are unlikely or where the implementation needs to be publicly accessible (such as with swing components), then it\'s acceptable to create small utility bundles containing both implementation and API. Any jar like this deserves extra scrutiny to establish that it is not unnecessarily exposing implementation detail.

API Naming Standards

We have adopted a variety of naming standards throughout our API to make the API both comprehensible and consistent.

System Modules

The core Cytoscape system will consist of a variety of modules that each encapsulate some key functionality. The core of the system API currently consists of:

Each module listed consists of (possibly multiple) separate API and implementation jars. The current Cytoscape 3.0 application simply pulls together the necessary jars and starts the jars in an OSGi container. The modules are described below.

Data Model

Cytoscape at it's core supports two kinds of data: networks and tables.

CyNetwork is a the basic network interface. As expected, a CyNetwork contains a set of CyNodes and a set of CyEdges with the usual methods for getting neighbors, adjacent edges and connecting edges. CyNetwork is a mutable object in that nodes and edges can be added to the network.

Each CyNetwork and it's constituent CyNodes and CyEdges are independent objects, meaning the nodes and edges are not shared with other CyNetworks.

CyNetworks can be created using the CyNetworkFactory service.

CyAttributes from 2.X has been re-imagined as CyTable. CyAttributes represented a single (for all intents and purposes) key-value table, where the key was a combination of a node or edge identifier and attribute name. In 3.0 the design adopts a more formal table model allowing many independent tables to be specified. Tables will consist of columns which will identify the values for a given attribute and rows which will identify the different attributes for a given key (i.e. node/edge). In contrast to CyAttributes, where individual attributes are either visible or not, in 3.0 this is a policy controlled by the table. Since there is no restriction on creating tables, it is therefore easy to have public and private tables.

Currently, each network contains default access to a public node, edge, and network table. The default tables contains columns such as name and selection state. Columns may be freely added to the default tables but other tables may also be bound to the network through the CyTableManager interface. We provide a VirtualColumn feature which allows a column from one table to appear as if it were a column in another table. VirtualColumns are cheap in the sense that no data is actually copied between tables and everything is shared by reference.

All tables in Cytoscape 3.0 are managed through the CyTableManager interface. Tables are created from the CyTableFactory service.

Root Network / Subnetwork Framework

Cytoscape 3.0 contains an implementation of a root network/subnetwork model. The idea is to have one root network from which many subnetworks can be created. Both the CySubNetwork and CyRootNetwork interfaces extend the CyNetwork interface. CySubNetworks are just CyNetworks that contain a reference back to its CyRootNetwork along with utility methods for adding existing nodes and edges. A CyRootNetwork has a list of all CySubNetworks that it contains as well as methods for adding or removing CySubNetworks.

The root network/subnetwork framework is designed to be invisible until app writers actually need to use the system. This means that in all but very special cases, code should be written to use the CyNetwork interface!

To use the root network/subnetwork framework, any CyNetwork can be passed into the CyRootNetworkManager and the associated CyRootNetwork for that CyNetwork is returned.

This design is intended to balance two competing approaches for dealing with a collection of networks. In Cytoscape 2.X there was a single root network for the entire system and once a node or edge was defined, it was shared by all subnetworks. This design had some nice properties such as making undoing deleted nodes/edges very simple, making cloning networks very simple, and making changes to nodes/edges consistent across subnetworks. However, these advantages also caused problems. Since each node or edge was only represented once in the system, a change to one may have had consequences in a seemingly unrelated network. The opposite of a single root network approach is to make every network in the system independent. While appealing in its simplicity this approach makes things like cloning networks and handling undo much more complicated. Thus, our design attempts strike a balance between these two approaches. Each CyNetwork is considered independent, however there is an available CyRootNetwork for each that provides key functionality when needed.

Network Pointers

Each CyNode may contain a reference to a CyNetwork. This feature allows networks to be created where all nodes point to different networks, thus describing possible relationships between the networks.

Event Model

Cytoscape 3.0 provides two mechanisms for firing and listening for events. Both should be familiar to developers, although the registration and firing of events occur in a centralized manner.

The first mechanism is the traditional CyEvent which is coupled with a CyListener. A CyListener consists of a single method (handleEvent) which accepts a CyEvent as an argument. All information necessary for the event to be processed should be accessed through the CyEvent interface and no additional methods should be added to CyListener. CyEvent objects are final classes whereas CyListeners are interfaces. By making CyEvent objects final classes, we can easily add methods to support new requirements while maintaining strict backwards compatibility (we cannot remove old methods). The base CyEvent interface consists of two methods. The first is a getSource() method, which simply indicates the source object that has fired the event. The second method is the getListenerClass() method, which returns the Class object of the CyListener that listens for this specific CyEvent.

CyEvents are fired through the centralized CyEventHelper class, which contains the fireEvent(CyEvent e) method, which fires the events synchronously. CyEventHelper searches for all registered CyListener services of the type specified by getListenerClass() and the calls the handleEvent method on each CyListener instance with the specified CyEvent.

CyListeners are registered as OSGi services rather than with event sources directly. This means that the CyListener implementation may need to consider the contents of an event before processing it. For example, it may only want to consider network events associated with the single network it is handling and not events for all possible networks.

The benefit of decoupling the CyListener registration and event firing management is that event source objects no longer need to maintain any infrastructure for managing event listeners or firing events. All they need to do is have a reference to the CyEventHelper service.

The CyEvent/CyListener combination should suffice for the vast majority of use cases as it is simple and extensible. The CyEvent/CyListener combination is the preferred mechanism for event handling!

The one problem with the CyEvent/CyListener pattern is that is requires that a CyEvent object be created each time an event is fired. This can become a burden on system resources for extremely high frequency or high volume events. Therefore, we have developed a second mechanism to aggregate small, frequent event payloads into larger, less frequent events. The CyEventHelper interface provides an addEventPayload() method that specifies a payload object that will be accumulated into an event object. For instance, the addEventPayload() method is called with each node that gets added to a network. These node payloads get aggregated into a single AddedNodeEvent. Payload events such as this are normal events in all respects.

The CyEventHelper fires aggregated payload events at two times. First, it polls the event payload queue at a fixed time interval (currently 200ms) for new payload objects and fires an aggregated payload event if any are found. The CyEventHelper also fires any accumulated payload events before it fires any other events. For instance, this means all AddedNodeEvents will be fired before a NetworkAddedEvent would be fired.

The benefit of the payload approach is that there is minimal additional event overhead for high frequency events. In the end, we provide two choices for events depending on the specific requirements of the situation. The CyEvent/CyListener combination is preferred for its flexibility, but payload events available for those situations where high performance is a concern.

The CyEvent/CyListener mechanism takes advantage of the Whiteboard design pattern for event handling. The goal of this approach is to decouple the object firing the event from the objects listening for the event. This has the added benefit of centralizing all event handling code in one place, rather than duplicating the nearly identical iterate-over-a-list-of-listeners approach all event sources would need. This approach also allows for proper de-registering of listeners. Since listeners are registered as OSGi services, any time a service becomes unregistered, the \"whiteboard\" (i.e. CyEventHelper) will properly remove the reference to the listener which helps ensure that garbage collection can happen efficiently.

View Model

The ViewModel is an attempt to present a common API for different aspects of a network visualization such that everything outside of the rendering code can interact identically with the ViewModel regardless of the rendering engine being used. Rendering code will be necessarily different, whether it is a 3D Processing engine or our current Java2D implementation. The goal is to leave the rendering code as a hidden implementation detail, so that all code will depend only on the ViewModel API.

The central interface of the ViewModel is the VisualProperty. A VisualProperty is an abstract description of some visual attribute like size of node, color of edge, or shape of n!ode. A View<T> is simply a container of VisualProperty objects that apply to an instance of type T. So, a View<CyNode> will contain a set of VisualProperty objects that define the visualization of the node.

The list of possible VisualProperties is provided by the rendering engine in the form of a VisualLexicon. Different rendering engines can provide different VisualProperties. For instance, a 2D rendering engine might provide X coordinate, Y coordinate, color, and shape, while a 3D rendering engine could provide all of that, but also provide a Z coordinate.

The VizMapper is vastly simplified. The primary interface for the VizMapper package is the VisualStyle. A VisualStyle is simply a container for a set of VisualMappingFunctions along with default values for VisualProperties. A VisualMappingFunction provides four primary methods that describe the mapping: the attribute being used for the mapping, the VisualProperty being modified, the type of value resulting from the mapping (i.e. color, number, font), and a method to apply the mapping to a given View<T> object.

Layouts

There is nothing inherently special about layout algorithms that distinguish them from other algorithms than analyze a network and produce some result. However, since layouts are a very common operation and many alternative algorithms exist for them, we have provided a layout API. The goal of the Layout API is to abstract out some of the common operations associated with laying out a network such as finding all partitions in a network. Beyond that, layouts provide a small amount of syntactic sugar atop a basic CyNetworkViewTaskFactory.

Work Model

The central unit of work in Cytoscape 3 is the Task. The Task interface consists of two methods: run() and cancel(). The run method takes a TaskMonitor argument that allows the task to send notification of its status to the user interface. The cancel() method is intended to allow a given task to be canceled if desired. Tasks are meant to be run in separate threads (just like Cytoscape 2.x). Loading a network, applying a layout algorithm, applying a visual style and dozens of other normal Cytoscape operations are Tasks.

Tasks can be combined into sequences by adding them to a TaskIterator. Commonly used sequences of Tasks are provided by TaskFactories through the method: createTaskIterator(). It returns a new instance of a TaskIterator, which contains one or more Task objects that are ready to be executed. TaskFactory objects are all registered as OSGi services. TaskFactory meta data (task name, preferred menu name, hot keys, etc.), is specified as part of the OSGi service properties and used to distinguish tasks.

TaskFactory services are meant to allow client code to access Tasks without requiring specific implementation details about how the Task needs to be configured and constructed. For example, a menu system should be able to create a menu item for any registered TaskFactory service and use the service meta data to determine information like preferred menu name to determine the menu specific details. This allows us to cleanly separate the Task implementation for the context in which the Task is used.

The TaskIterators returned by TaskFactories and containing Tasks are executed by a TaskManager instance. The TaskManager executes the sequence of Tasks returned by the TaskIterator in a separate thread and provides an instance of TaskMonitor that the Task can use notify us of its status. In a GUI context, the TaskManager will be responsible for popping up a status dialog or otherwise notifying users of the Task's progress.

There is currently no infrastructure to support running multiple tasks simultaneously, however this could be easily developed as an extension to TaskManager that instead of executing the Tasks found in a TaskIterator sequentially, execute them in parallel in separate threads. This feature will be added as needed.

Task/TaskFactory Configuration: Core Task API and Tunables

Tasks and TaskFactories need to configured with knowledge specific to that task. For example, a load network task will need to know which network file to load and an apply layout task will need to know which layout algorithm to use and which network view it should be applied to. We classify the type of configuration information necessary for tasks into three specific types. Each type of configuration information is handled in a distinct way and provided to the task using a separate mechanism. The thee types are:

  1. System knowledge available at TaskFactory initialization time.

  2. System knowledge available only at Task execution time (i.e. when getTaskIterator() is called).
  3. User knowledge known available only at Task execution time.

System knowledge available at TaskFactory initialization time (1) should be passed as a reference to the TaskFactory constructor and stored in the TaskFactory object. For example, a task that applies a visual style will need a reference to the VisualMappingManager singleton. Since this object is available at initialization time and is a singleton itself (i.e. there's only one and it doesn't change as Cytoscape runs) it should be passed as a constructor argument into the ApplyVisualStyleTaskFactory.

The constructor code for ApplyVisualStyleTaskFactory constructor will look something like this:

   1 private final VisualMappingManager vm;
   2 
   3 public ApplyVisualStyleTaskFactory(VisualMappingManager vm) {
   4     this.vm = vm;
   5 }
   6 

System knowledge available only at Task execution time (2) should be handled by using one of the specializations of the TaskFactory interface found in the Core Task API. The Core Task API defines several special types of TaskFactories such as NetworkTaskFactory, NetworkViewTaskFactory, and NodeViewTaskFactory (to name but a few). Each specialization adjusts the createTaskIterator() method in TaskFactory such that additional information can be specified for the Task right before the createTaskIterator() method is called (i.e. before the Task itself is created). As you might expect the NetworkTaskFactory allows a network to be specified, a NetworkViewTaskFactory allows a network view to be specified and the NodeViewTaskFactory allow a node view to be specified.

Returning to the ApplyVisualStyleTaskFactory example, the TaskFactory will actually be a NetworkViewTaskFactory, which means that the createTaskIterator() method will actually be createTaskIterator(CyNetworkView v). When a user tries to apply a visual style by selecting the proper menu item from Cytoscape the menu item will first get the current network view (known to the system by which view has focus), and call the createTaskIterator(CyNetworkView v) method.

The code for a menu action would look something like this:

   1 taskIterator = taskFactory.createTaskIterator( getCurrentNetworkView() );
   2 
   3 taskManager.execute( taskIterator );
   4 

The code for the ApplyVisualStyleTaskFactory could look like something like this:

   1 TaskIterator createTaskIterator(CyNetworkView view) {
   2     return new TaskIterator( new ApplyVisualStyleTask(view) );
   3 }
   4 

The last type of configuration information that is often necessary for Tasks is user knowledge that is only available at execution time (3). This sort of information includes things like the name of the file you'd like to save an image to or the spring strength you'd like to use for a spring-embedded layout algorithm. This is information only a user can know, which means Cytoscape must ask the user to provide this information, which in turn means Cytoscape must know what to ask. The way that Tasks and TaskFactories tell Cytoscape what to ask is through the use of Tunables. Tunables are annotations that indicate that specific fields or methods in a class either can or must be set before execution can proceed. The TaskManager uses an implementation of the TunableMutator interface to search an object for tunable annotations and automatically construct a user interface that prompts the user to enter the necessary information to allow task execution. The goal of Tunables is to allow !Task/TaskFactory programmers to completely separate the user interface creation from the task implementation itself.

The code for a SaveGraphicsFileTask might look something like this:

   1 @Tunable(description=\"The name of the file to save to\")
   2 public File saveTo;
   3 
   4 void run(TaskMonitor tm) {
   5     writeGraphics( saveTo );
   6 }
   7 

The work happens behind the scenes in the TaskManager object using instances of the TunableMutator interface. Different TunableMutator instances will be available for different execution contexts. If the task is being executed by a Swing GUI, then an appropriate dialog will be created, while if the Task is being executed in a command line context, a parser will attempt to extract the correct information from the command line text.

The important aspect of this design is that the Task can be written to be completely independent of the user interface and the Task consumer can be completely ignorant of the implementation details of the class.

Session

The Session API contains all interfaces that describe a session and provide events to indicate that a session is being loaded/closed/saved/etc.. The Session API primarily involves the CySession object and the CySessionManager. The CySessionManager which allows the current operating session to be captured or set, meaning a CySession object is returned or used to set the current session. The CySession object itself is an immutable snapshot of a system either created by reading a file or my querying the system. When a session is set, the CySessionManager will configure some key aspects of the system itself and then fire an event, so that any interested party can update themselves as necessary. Similarly, when a session is saved, the CySessionManager will query the system for some information used to construct a CySession object, but then fire a mutable event so that apps can add their state information to be serialized in the session as well.

Presentation

The Presentation API is fairly minimal and provides three primary interfaces: one is a simplified factory that lets a RenderingEngine be created from a View<T>, the second is a description of a RenderingEngine which enumerates the type of graphics that a RenderingEngine must be able to provide (i.e. generate an java.awt.Image, support printing, etc.), and the third is a manager that tracks the various rendering engines being used. Crucially, the RenderingEngine also provides a list of all VisualProperties that it support. This list can also be accessed from the RenderingEngineFactory if no RenderingEngine yet exists.

IO

The IO API package provides interfaces for reading and writing the basic types of Cytoscape data. The implementation package provide implementations for a variety of different file types (e.g. SIF, XGMML, etc.) that are provided as OSGi services.

Application

The application modules are a small set of interfaces that define interfaces common to all applications and then Swing GUI specific extensions. The Swing application API provides hooks to add menus, buttons, panels, and the like. The implementation details of the application layer will, among other things, consist of code to automatically listen for TaskFactory services and dynamically create menus and buttons. The application implementation will only reference TaskFactories in the abstract and never directly reference specific Tasks. Configuration of the menus will be controlled by properly defined service properties.

App Framework

The app framework for 3.0 really consists of two parts. The first is that any valid OSGi bundle can be considered an app. Future versions of Cytoscape (i.e. 3.1 or later) will likely focus on OSGi bundles as the primary app mechanism, but for now the difficulty in creating a valid bundle makes focusing on OSGi specific bundles slightly too complicated.

Therefore, we have the second part of the app framework, the Simplified CyApp API. Just like in Cytoscape 2.X, app writers extend a simple class called CyApp. The difference in 3.0 is that the constructor takes a single argument of type CyAppAdapter. The CyAppAdapter is designed to provide app authors access to all factory and manager objects in the Cytoscape system, thereby giving them access to things that would normally only be available through the OSGi service interface. The goal is to allow app writers to write their code without needing any understanding of OSGi, Maven, or any other advanced feature.

For details on porting existing app see the Cytoscape 3.0 Plugin Porting Guide.

Utilitiy Modules

There will be a variety of other modules that will be part of the application that will be roughly analogous to the core apps in Cytoscape 2.x. Some examples include the Editor framework, layout algorithms, and the VizMapper GUI. Unlike in 2.x, these modules will be able to provide a public API to other programmers.

Versioning

SPI (Implementer) vs. API (Consumer)

It is useful to distinguish APIs meant for consumption (i.e. for those who call methods on an interface) versus those meant to be implemented (i.e. external code implements a given interface). The distinction is that methods can be added to a consumer API without impacting backwards compatibility, however methods cannot be removed. In contrast methods cannot be added to an implementer API (because no one will have yet implemented them). Listener interfaces are good examples of implementer APIs because they are meant to be implemented by client code. You cannot add or change a method in a listener interface without breaking every single client that implements the interface. In contrast, a consumer API where you provide most implementations (e.g. CyNetwork) can have methods relatively safely added, although they can't be removed.

To better distinguish the two kinds of APIs others have introduced the term service provider interface (SPI) to refer to implementer APIs, while confusingly, continuing to refer to consumer APIs as "APIs". This also adds a third possible use of the term "service" in addition to OSGi services and service oriented architecture. Rather than dwell too much on terminology, it is best to simply reflect on the different properties of different part so APIs and how changes to those APIs can affect things.

All classes in the Cytoscape 3.0 API will be documented describing how the class or interface can be expected to change as versions progress.

Semantic Versioning

We will use Semantic Versioning (http://semver.org/) beginning with version 3.0.0 of Cytoscape. Briefly, these rules state that the major version number must be incremented if any backwards incompatible change is introduced, the minor version must be incremented if backwards compatible features are added, and the patch version must be incremented for changes that fix bugs but do not alter the API.

The goal of using Semantic Versioning is to provide API consumers and implementers coherent rules for implementing their code. For instance, if an app writer writes code requiring version 3.1.0 of an API, then their code is guaranteed to work up until version 4.0.0. No methods will ever be removed in the 3.x.y series of releases.

It is very important to distinguish changes that impact APIs (API consumers) and SPIs (API implementers) with respect to semantic versioning. For instance, anyone implementing a listener interface (SPI) will be forced to update their implementation if a method is added to the interface. Because this change impacts all clients, it must be considered a major change, meaning the major version number would need to increase (e.g. to 4 from 3). In contrast, an API consumer, likely won't be impacted by an additional method, so this addition could be considered a minor change (e.g. to 3.5 from 3.4).

Version

Change Type

Client vs. Implementer

API vs. SPI

Major

Backwards incompatibile

Incompatible for implementers AND clients.

Removing or changing a method in an API or adding methods to an SPI.

Minor

Backwards compatible

Incompatible for implementers, compatible for clients.

Adding methods to an API.

Patch

Bug fixes to hidden implementation code only.

Compatible for implementers and clients.

Bug fixes to hidden implementation code only.

Tool Overview

OSGi Basics

Sample Metadata File (MANIFEST.MF)

 Manifest-Version: 1.0
 Export-Package: org.cytoscape.model;uses:="org.cytoscape.model.events"
  ,org.cytoscape.model.events;uses:="org.cytoscape.model,org.cytoscape.
  event",org.cytoscape.model.subnetwork;uses:="org.cytoscape.model"
 Bundle-Version: 3.0.0.alpha4
 Build-Jdk: 1.6.0_24
 Built-By: mes
 Tool: Bnd-0.0.357
 Bnd-LastModified: 1305405728450
 Bundle-Name: org.cytoscape.model-api [org.cytoscape.model]
 Bundle-ManifestVersion: 2
 Created-By: Apache Maven Bundle App
 Import-Package: org.cytoscape.event,org.cytoscape.model,org.cytoscape.
  model.events,org.cytoscape.model.subnetwork
 Bundle-SymbolicName: org.cytoscape.model-api

 Manifest-Version: 1.0
 Bundle-Version: 3.0.0.alpha3
 Build-Jdk: 1.6.0_24
 Built-By: mes
 Tool: Bnd-0.0.357
 Bnd-LastModified: 1305412817147
 Spring-Context: META-INF/spring/*.xml
 Bundle-Name: org.cytoscape.model-impl
 Bundle-ManifestVersion: 2
 Created-By: Apache Maven Bundle App
 Import-Package: org.cytoscape.equations,org.cytoscape.event,org.cytosc
  ape.model,org.cytoscape.model.events,org.cytoscape.model.subnetwork,o
  rg.cytoscape.service.util,org.slf4j;version="1.5"
 Bundle-SymbolicName: org.cytoscape.model-impl

Import/ Export Packages

Public vs. Private Packages

OSGi Services Registry

Maven Basics

Maven is a software construction tool, which have many advantages over Ant.

The main benefits of using Maven

  1. Maven lets you manage your package dependencies easily, especially for large projects, like Cytoscape.
  2. Maven let your share the repository easily on the web.
  3. Maven forces you to have a standard project directory structure

Maven project

  1. must have a specific directory structure.
  2. A “pom.xml” file, the project object model, and called a POM

POM

  1. the app name
  2. version number
  3. build instruction
  4. and all other bundles/libraries this app requires.

Get Maven

  1. Maven is an open-source project. You can download it for free at http://maven.apache.org. Some operating systems support installation via their software package management systems, e.g. various Linux distributions like Ubuntu, and some, e.g. Mac OS, may already have it preinstalled.

  2. Cytoscape is built with Maven 3. So when you download Maven, please make sure to download Maven 3.X.

Compile with maven

  1. use “mvn install” to compile your app
  2. Maven will automatically install it in the local Maven repository (.m2 in your home directory).
  3. Later when you build other apps, which depend on the app you already built, all you need to do is specify the app in your project’s POM, and Maven will look it up in your repository. Therefore you do not need to make an explicit copy.

Local repository vs. remote repositories

  1. The first time you use Maven, Maven may download a lot of bundles and install them in your local Maven repository.
  2. Next time when you use Maven, Maven will check if the bundle you require already exists in your local repository, if not, it will download it from a remote repository.

Add dependency to your app

  1. There are many library bundles already available in remote Maven repositories.
  2. All you need to do is specify which repository to use, the name of the bundle and the version number.

Summary to build your app with Maven

  1. you must have Maven installed on your computer
  2. your project must be a Maven project (directory structure required by Maven).
  3. You must edit your “pom.xml” to define your project and dependencies.

Maven Archetypes

Archetype is a Maven project templating toolkit. An archetype is defined as an original pattern or model from which all other things of the same kind are made. Archetype will help authors create Maven project templates for users, and provides users with the means to generate parametrized versions of those project templates. Cytoscape will also provide some Archetypes to help app developers to create an initial project , for example, “cyaction-app" will create a project to add a new menu item in Cytoscape 3.

Conclusion

Useful Web Sites

Need Help?

Books

Cytoscape_3/CoreDevelopment/Architecture (last edited 2012-04-09 21:14:45 by server2)

Funding for Cytoscape is provided by a federal grant from the U.S. National Institute of General Medical Sciences (NIGMS) of the Na tional Institutes of Health (NIH) under award number GM070743-01. Corporate funding is provided through a contract from Unilever PLC.

MoinMoin Appliance - Powered by TurnKey Linux