Migrate from GitHub to SourceForge with this tool. Check out all of SourceForge's recent improvements.


Introduction to the openCRX UML model - Part I

The business object model of openCRX is specified with UML. This has some important advantages:

  • It is platform- and language-neutral. Changes of the underlying platform or
    programming language do not affect the model.
  • The model is mapped by the build process to various artifacts such as Java APIs and
    JPA persistence classes, XML schemas, etc. and it is used at runtime by generic
    components such as the standard GUI, the REST service or the database access plug-in.
    So the model is not only a picture. It is an integral and essential part of the development
    and runtime environment and it guarantees that all artifacts are always consistent. In
    addition, the automation also saves a lot of programming effort.
  • It is visual. Compared to a textual Java API it can be printed out and discussed with
    business analysts and with advanced users.

IMPORTANT: this document is work in progress. It only describes a subset of
the openCRX model.

Get the model

The complete openCRX class diagrams are published here.

The openCRX model is created using Eclipse Papyrus (for more information see here.
If you have installed the openCRX SDK you will find the corresponding model files in the directories
./opencrx2/core/src/model/emf and ./opencrx2/core/src/model/papyrus. However, the model diagrams are not
created with Papyrus, you won't see any diagrams using Papyrus. Instead, the diagrams are created semi-manually
using the GraphViz utilities. This approach saves a lot of manual layout work and the diagrams
have a consistent layout.

If you want to generate the model diagrams on your local machine as follows you can do this as follows.
Open a shell and go to the openCRX SDK installation directory. Then run the following commands:

cd core
ant -Dalbum.theme.name=Uptight -Dalbum.theme.path="~/opt/album/themes" -Dalbum.theme.url="http://myweb.com/_style/album/themes" model-diagrams

The ant task model-diagrams performs the following operations:

  • It processes the manually created GraphViz templates (.dott) located in ./opencrx2/core/src/model/graphviz.
    It completes the place-holders ${CLASS}, ${ASSOCIATION} and ${INSTANCE_OF}) with the actual
    model information and generates GraphViz compliant .dot files.
  • It runs the GraphViz dot utility for each generated .dot file.
  • It runs the album utility to generate a web-index.
  • The resulting diagrams documentation is store in the directory ./build/model.

The task must meet the following prerequisites:

  • The GraphViz utilities must be installed. See here for more information.
  • The album utility must be installed. See here for more information.
    Also install the theme 'Uptight'.
  • Set the following environment variables
export GRAPHVIZ_HOME=/usr/bin
export ALBUM_HOME=/usr/bin

Why a UML model?

The UML model represents the service interface of openCRX. So if you look at the model
you look at the API of openCRX in UML notation (most of you are probably more familiar
with interfaces expresses as WSDLs, Java interfaces, CORBA IDL_s, etc. In _openCRX
we decided to use UML because of the advantages mentioned in the introduction. This
decision may be a little bit of a hurdle for some programmers to get comfortable with
openCRX. The good news is that as long as you stick to the Java API or
the REST interface you do not have to know that much about UML. Moreover, openCRX
only makes lightweight use of UML. It only uses class diagrams. Business objects are
mapped to UML classes, attributes, operations and associations. Other UML
diagram and element types or not used.

How to read the model?

If you want to learn more about UML modeling for openMDX-based applications then
Introduction to Modeling with openMDX is a good starting point.

Package org.opencrx.kernel

kernel is the main model package of openCRX. It contains all classes used by the
openCRX core service:

Package org.opencrx.kernel.account1

account1 includes all business objects related to account and contact management.
Accounts can be contacts (which are persons), groups or companies. An account has
an arbitrary number of members which allow to create relationships between accounts.
The type of a membership is specified by its role, e.g. is friend of, is employee of,
etc. An account also has an arbitrary number addresses where each address is
specified by its type (postal, e-mail, phone, ...) and usage (business, home, other,
delivery, ...).

The main classes of account1 are

  • Contact: Represents a person.
  • LegalEntity: Represents a company.
  • Group: Represents any kind of account group. Examples are openCRX Developers, Receiver of openCRX Newsletter, VIP Customers.
  • UnspecifiedAccount: Used when the other types do not apply. This type is
    typically used when importing contact information from a 3rd party system.
    In these cases it is sometimes not possible to decide whether an address record
    is a person, a legal entity or a group.

An account has an arbitrary number of addresses. As explained in the
address1 model, an address has a usage and a default flag. This allows
an account to have multiple postal addresses with different usages such as Home,
Business, Invoice, Delivery, etc. It is important to note that
addresses are objects and not only strings. If an EMailAddress is referenced by
an EMailActivity or a PostalAddress is referenced by a Contract, there
is no redundant information or copy stored in the activity or contract management. In
case an address changes it is a good practice not to change the existing address.
Instead, create the new address and set the disabled flag of the existing address to true.
First of all, this allows to keep track of the address changes, but more important old
information is not destroyed. E.g. existing sales orders still show the address where
the items where actually delivered (and not the new).

Member_s allow to create a relationship between two accounts. The relationship
is asymmetric in the sense that one account is the owner of the relationship and
the other account is referenced. The relationship is directed from the owning
account to the referenced account. The composition asserts that all members are
removed when the owning account is removed. A relationship is specified by
its role and quality and has a validity period starting from _validFrom
validTo. If two accounts have relationships in different roles, e.g.
is friend of, is business partner of then a member object has to be created
for each role.

Objects of type Member are persistent, i.e. they are stored on the database.
Objects of type AccountMembership are transient and are calculated by a database
view. AccountMembership_s are the set of all direct and indirect memberships
between two accounts. A _distance < 0
means account is referenced by
and a distance > 0 means account references.

The classes Organization, OrganizationalUnit and OrganizationalUnitRelationship
allow to capture the organizational structure of an account. The organizational
structure is separated from the account / member structure because typically only
a very limited number of organizational units need to be exposed as accounts.
E.g. an international company has several branches worldwide. The main company
and the branches are mapped to legal entities. The maybe complex structure is mapped
to organizations, organizational units and their relationships. Using the relationship
type, any kind of relationship between organizational units can be captured. The
organizational units representing the head quarter or a branch reference the
corresponding legal entity. Separating the organizational structure from the account and
membership structure also reflects the fact that the life-cycle of the organizational
structure and the account and membership structure are typically not in sync.

Package org.opencrx.kernel.activity1

An Activity is a representation of anything what a resource "does". openCRX
supports the following activity types:

  • Absence: Represents holidays or some other kind of unavailability.
  • EMail: Received, sent or archived E-mail.
  • ExternalActivity: Activity which is described in
    detail by an external or 3rd party system.
  • Incident: Incident or support case.
  • Mailing: A mailing.
  • Meeting: A meeting.
  • PhoneCall: A phone call.
  • SalesVisit: A sales visit. Is sub-class of Meeting.
  • Task: A task.

An activity is reported by an account / contact. It has a unique activity number, an
actual start and end, a scheduled start and end, a priority and a due by date. Each
activity has an ICAL VEVENT or VTODO representation. An activity can be assigned to
exactly one person. The assigned person is responsible for the activity. During the
lifetime of the activity, the activity can be reassigned to another person either
by users or by workflows. Moreover, an activity has the following properties:

  • Votes: Users can vote for activities. This may be useful in cases when
    a decision has to be made of how to proceed with the activity.
  • Group assignments: Activities can be assigned to zero or more activity
    groups. This allows to structure the activities and group them to trackers,
    categories and milestones. The shared association ActivityGroupContainsActivity
    allows the reverse lookup: it lists all activities assigned to an activity group.

  • Product references: If the activity management is used for customer support,
    customers typically report issues related to products. _ProductReference_s allow
    to set relationships to products.
  • Effort estimate: If used in the context of project management effort estimates
    can be added to activities.
  • Involved object: A generic way which allows to capture relationships to other objects.
  • Resource assignment: Activities are executed by resources. The workload in % allows to
    define the expected or planned amount of work a resource is working on the activity
    relative to the companies working calendar. The work records reported by each resource
    represent the actual work performed.

Each activity has an activity type. The type contains meta-information about an
activity which all activities of the same type share. Most important, the type
defines the underlying workflow, i.e. the process which controls the execution and
progress of the activity.

An activity's process is represented by a state diagram composed of states and
transitions. By the means of actions a transition defines what has to be done
during the transition. The model defines some predefined actions and the generic
action WfAction (workflow action) which allows to execute a workflow, i.e.
any kind of programmed code.

An activity is always in a current state. A transition is initiated by the operation
doFollowUp(). It can be invoked by the user using the standard GUI
or by programs, workflows or triggers. If a transition is executed, the
corresponding progress is reported as a FollowUp object and the activity
changes to the new state.

Activities are created by _ActivityCreator_s. Activity creators allow to define

  • The type of activity to be created
  • The activity groups to which the activity is initially assigned
  • The resources to which the activity is assigned upon creation

When invoking the operation newActivity() an activity is created with a new activity
number. It is assigned to the configured activity groups and resources.
Moreover, the workflow is initialized and the activity is set to its initial state.

The actual work is performed by resources. In most cases a resource is a person. However,
a Resource is an abstract worker an can also be a part time person, a
group of persons, a machine or a combination of it. A resource has a working
calendar which allows to specify the availability of a resource.

Package org.opencrx.kernel.address1

The model contains abstract classes capturing the different types of addresses:

  • Addressable: abstract type which represents any type of address. Every
    addressable has a main flag and a usage code which allows to specify how the
    address is to be used (Home, Business, Delivery, etc.).
  • RoomAddressable: Room. E.g. can be used to capture the room where employees are
  • PostalAddressable: Postal address.
  • EMailAddressable: E-Mail address.
  • WebAddressable: Address of a web site.
  • PhoneNumberAddressable:: phone and fax numbers.

The abstract classes are used in other models to define concrete address types such
as AccountAddress or ContractAddress.

Package org.opencrx.kernel.admin1

admin1 contains classes required to manage openCRX by the root administrator.
Currently, the model only contains the segment and ComponentConfiguration_s.
Component configurations allow to manage configuration options for the individual
components of _openCRX
. E.g. CalDavServlet, ICalServlet, WorkflowHandler.
The operation createAdministrator() allows to create a new segment including
its segment administrator. The method importLoginPrincipal() allows to import
login principals and subjects from an external file.

Package org.opencrx.kernel.base

The base package contains classes and patterns which are used in other model packages. The
most important are

  • PropertySet and Property
  • SecureObject
  • Auditee
  • Indexable

A property set contains zero or more properties. Property sets are used in many
cases. E.g. a CrxObject is a property set. This allows to attach any number of
property sets and properties to _CrxObject_s.

A SecureObject allows to control read, update and delete access to objects.
An object has an owner and zero or more owning groups. The owner and all users
which are member of one of the groups have access to the object. The level and type
of the access is controlled by the access levels:

  • accessLevelBrowse: controls whether the user has browse permission, i.e. is
    allowed to read composite objects.
  • accessLevelUpdate: controls whether a user has update permission.
  • accessLevelDelete: controls whether the user has delete permission.

The level determines the user's memberships:

  • none: Nobody has access except the root user.
  • private: Only the owning user is granted access.
  • basic: The owning user and all users which are member of the assigned
    groups and their super-groups recursively are granted access.
  • deep: The owning user and all users which are member of the assigned
    groups, their super-groups and their subgroups recursively are granted access.

Classes inheriting from Auditee are subject to audit, i.e. all object
modifications are logged in the form of audit entries. AuditEntry_s are transient
objects which are calculated by a database view. As a consequence they are read-only.
The attribute _auditee
contains the XRI of the modified object. modifiedFeatures
contains the set of features which were modified. beforeImage lists the attributes
and their corresponding values before update.

Classes inheriting from Indexed are subject to indexing. How indexing is done
is implementation-specific. The object's index entry can be updated by invoking
the operation updateIndexEntry(). An object has zero or more index entries
representing the object's index at different times. The class ObjectFinder
defined in model home1 allows to retrieve objects based on their index entries.

Package org.opencrx.kernel.building1

The building1 package allows to capture buildings, building units, facilities
and inventory items. Buildings are composed of building units which itself may be
grouped hierarchically using the relationship BuildingUnitHasParent.

If requied, buildings can be grouped to BuildingComplex_s. _Building_s, _BuildingUnit_s
and _BuildingComplex_s all inherit from the abstract type _AbstractBuildingUnit
as such they can contain facilities.

Besides of that, the model supports InventoryItem_s. Inventory items can be
linked to each other or they can be linked to facilities (both extend _LinkableItem
The purpose of the link-feature is to capture the (mostly) static relationships
between items. E.g. a building has three rooms R1, R2 and R3 (represented as building units).
R1 has the facility meeting area having itself a table, four chairs and a flip-chart as
inventory items.

If the building unit plays more the role of a warehouse and the inventory items are
only stored temporarily in the building it is not recommended to capture the items
as InventoryItem_s. Instead, the items should be represented as products and the
flow of the items as bookings. The reference _InventoryControlledByDepot
can be used
to capture the relationship warehouse - depot.

Package org.opencrx.kernel.code1

The package code1 is used to capture code values or predefined value domains mainly
used to populate drop-downs in GUIs. The CodeValueContainer is the container of
one or more entries. An entry can either be a CodeValueEntry or a SimpleEntry.
An entry has a code value and a validity period specified by validFrom and validTo.
A CodeValueEntry is mainly used to populate drop-downs for code fields of multilingual
GUIs such as the standard GUI of openCRX. A SimpleEntry can be used by applications and
adapters accessing openCRX via the API or REST. Typically they are used to map
stringified values to code values and vice versa. You can find XML samples in the folder

Package org.opencrx.kernel.contract1

The package contract1 contains the business objects to capture in a formal
way any kind of agreements made between contract parties. In the most abstract form
a contract is a document where at least two parties have set up an agreement. contract1
currently is restricted to contracts used in the sales process. These are:

  • Lead: A lead allows to capture the initial sales contact in an informal way.
  • Opportunity: An opportunity allows to capture customer interests which are
    more concrete and more formal than leads. If the customer shows interest in certain
    products, corresponding opportunity positions (or line items) can be created using
    the operation createPosition().
  • Quote: A quote represents the next step in the sales pipeline. A quote can be
    created from scratch or based on an existing opportunity.
  • SalesOrder: A sales order contains all terms and conditions and line items
    including prices, sales taxes and discounts as ordered by the customer. A sales
    order can be created from scratch or based an existing quote.
  • Invoice: Invoices allow to track invoices sent to the customer. In many cases,
    openCRX is not the leading system for invoices. Instead, invoices are created
    by a 3rd party ERP system which are imported automatically by a workflow and linked
    with the corresponding sales order(s).

NOTE: More contract types such as service or support contracts will probably be
added in future versions of openCRX.

All sales contract types inherit from the abstract class AbstractContract. A
sales contract has a sales rep, a customer, a supplier and broker. Competitors and
additional contacts can be added if needed. It is important to note that a contract
has exactly one contract currency. All amounts and totals refer to this contract
currency. A contract has a default pricing rule and a default calculation rule. The
pricing rule defines which price from the set of available product prices is
automatically selected when creating or updating a contract position. The default
pricing rule implements a lowest price algorithm. E.g. if a product has a price
of € 2.- which is valid from 01-01-2010 until 31-12-2010 and a special price of
€ 1.- during 01-08-2010 until 31-08-2010 then the lowest price rule selects the
price € 2.- unless the pricingDate is between 01-08-2010 and 31-08-2010.
The model allows to define any kind of user-specific pricing rules. The algorithms
are implemented in Java.

The calculation rule defines how the totals are calculated. The
getPositionAmountsScript returns the rounded amounts at position-level. The
getContractAmountsScript calculates the total of the rounded positions and
in turn may itself round the calculated totals. The default calculation rule
simply calculates the total of all contract positions without rounding or otherwise
manipulating the totals. The totals are then stored in the fields
AbstractContract.totalBaseAmount, AbstractContract.totalDiscountAmount, etc.
The model allows to define any kind of calculation rule. The algorithms are implemented
in Java.

A sales contract has zero or more contract positions. Important attributes of a
contract position are:

  • Position number: An automatically calculated sequence number.
  • Name: User-defined name of the position.
  • Quantity: Number of ordered units.
  • Product: Product.
  • Uom: Unit to be used such as Piece(s), m2, kg.
  • Price per unit: Price of the product per unit.
  • Sales tax: Reference to the sales tax type object which defines the sales tax rate.

Calculation and pricing rules can be set at position-level. If they are not set the
rules at contract-level are used as default. The operation reprice()
recalculates the pricePerUnit. In a first step the pricing rule determines the
price level and in a second step the corresponding price is retrieved from
the product. The price is then stored as listPrice and the pricePerUnit is
updated correspondingly. The automatically calculated list price can be overriden
by modifying pricePerUnit manually. The derived attributes are
calculated as follows:

  • baseAmount: Calculated as quantity * pricePerUnit.
  • discountAmount: Calculated on the baseAmount by applying discount and discountIsPercentage.
  • taxAmount: Calculated as (baseAmount - discountAmount) * salesTaxRate.
  • amount: Calculated as baseAmount - discountAmount + taxAmount.

Normally Uom (price) and Uom (quantity) are identical. They can be different in
cases when the Uom (quantity) is based on or derived from the Uom (price). E.g. 1 ha #
100 m2 * 100 m2 # 10'000 m2. If in this case Uom (quantity) is set to ha,
Uom (price) to m2 and quantity to 5, the effective quantity used in the
calculation is quantity * Uom (quantity).quantity # 5 * 10'000 # 50'000. This
feature is useful in cases where customer- or market-specific uoms must be used
(e.g. 1 barrel # 158.9873 litres, 1 ha # 10'000 m2, 1 ton # 1000 kg).

Both AbstractContract and AbstractContractPositon are DepotReferenceHolder_s.
This allows to attach depots (see _depot1
for more information about depots) to
contracts and contract positions. Depot references attached at position-level override
depots references at contract-level. The operation updateInventory() executes the
following steps:

  • In case a contract position has been added or the quantity was increased a
    CompoundBooking is created with a DebitBooking for the depot with usage
    01 - supplying goods and a CreditBooking for the depot with usage
    03 - destination for deliveries.
  • In case a contract position has been removed or the quantity has been reduced
    a CompoundBooking is created with a CreditBooking for the depot with usage
    02 - accepting returns and a DebitBooking for the depot with usage
    03 - destination for deliveries.

This way bookings allow to capture the flow of items (or products) from the
warehouse to the customer (when they are sold) and from the customer to the
warehouse (in case when they are returned).

updateInventory() requires the following preconditions to be met:

  • The name of the depot positions must match the product number, i.e.
    updateInventory() creates debit and credit bookings for depot positions
    with depotPosition.name = contractPosition.getProduct().getProductNumber().
    If the product does not have a product number, the product name is used instead.
    If no depot position with that name exists, a depot position is opened on-demand.
  • If the depot reference has set the flag depotHolderQualifiesPosition set to
    true, the depot position name is set to product number # contract position line number.
    This option allows to map a contract position to a depot position.
  • The following booking texts must exist
Name             Infix debit    Infix credit    Infix 1    Infix 2    Credit first
return goods     returns        accepts         returns    to         yes   
deliver goods    delivers       receives        delivers   to         yes

Package org.opencrx.kernel.depot1

depot1 is an abstraction of a bank depot and as such can be used in many different
ways. A Depot allows to store any type of items. Depots can be bank depots, warehouses,
application servers, libraries, etc. Samples for items are securities, electronic
devices, deployed software components, books in a library.

A depot is structured by depot positions. Depot positions are the target of a
booking. As a consequence one always has to specify the depot position when adding
something to it or removing something from it. A depot position must contain
only items of the same kind. E.g. it is not a good idea to store fruit and
computers in the same depot position. If doing so, questions such as
how many computers are stored in the depot? (or in other words calculating the
balance) are difficult to answer. A ProductDepotPosition allows to capture
cases where the underlying of a depot position is a product.

Depot positions can be temporarily locked or closed. In that case no items
can be added to or removed from it.

Booking records are maintained in order to keep track of items which are
removed from and added to depot positions. A standard booking is a special case of
a CompoundBooking and has two legs: a CreditBooking and a DebitBooking. The
same number of items are removed from one position (debit booking leg) and added to
another position (credit booking leg). Compound bookings guarantee that nothing can
get lost in a depot: the sum quantityCredit of all credit bookings must be equal to the sum
quantityDebit of all debit bookings. In cases where this consistency is not
required a SimpleBooking can be used to add or remove items from a depot position.

A booking has a value date and a booking date. The booking date is the date when
the booking was created (or when it should be reported as created). The value date
marks the time when the item is effective for the balance calculation. Bookings are
only accepted if the booking date and the value date are within an existing and
active booking period.

A depot is held by the DepotHolder. In most cases a depot holder is a person.
In this case a DepotContract is used to manage to relationship to the accounts.
A depot holder can also be a Warehouse or a Site.

Another option to structure depots are _DepotGroup_s. The depot group structure
is the abstraction of a chart of accounts.

The DepotEntity is the abstraction of an accounting area. It allows to define
constraints such as the definition of booking texts and booking periods. Depending on a
company's booking policy, booking periods are created quarterly or at least yearly.
Past booking periods typically remain open for a few days or weeks and are closed when
all bookings are complete and controlling is done. As soon as a booking period is
closed, no more bookings are accepted in the corresponding time periods.

Below you find some typical use-cases where depot1 can be used.

Example 1: Banking Cash

Cash is managed in bank accounts:

  • DepotEntity: Booking area or branch
  • DepotHolder: Customer contract
  • Depot: Multi-currency bank account
  • DepotPosition: One depot position for each currency
  • CompoundBooking: Incoming / Outgoing payment
  • SimpleBooking: Not used
  • DepotGroup: Chart of accounts

Example 2: Banking Securities

Securities are managed in bank depots:

  • DepotEntity: Booking area
  • DepotHolder: Customer contract
  • Depot: Depot
  • DepotPosition: Depot position
  • CompoundBooking: Buy / Sell of depot positions.
  • SimpleBooking: Not used
  • DepotGroup: Chart of accounts

Example 3: Telco provider

International Telco provider which offers products such as Internet
Access, TV on-demand, Telephone services, etc. Components are
delivered to or installed on the customer's site.

  • DepotEntity: Branch
  • DepotHolder: Customer's site including the site's address.
  • Depot: Product bundle. Typically a telco product is bundled, e.g. an Internet-Access consists of several components such as Modem, TV set-top box, ADSL link, etc.
  • DepotPosition: Installed component.
  • CompoundBooking: Buy / Sell or Installation / Uninstallation of components.
  • SimpleBooking: Typically used to track usage of services such as duration of mobile phone calls, internet usage, tv usage, etc.
  • DepotGroup: Not used

Example 4: Warehouse

An international trading company managing multiple warehouses in several branches.

  • DepotEntity: Branch
  • DepotHolder: Warehouse including the warehouse's address.
  • Depot: Item group.
  • DepotPosition: Item.
  • CompoundBooking: Delivery of items.
  • SimpleBooking: not used
  • DepotGroup: Not used

Continue reading Part II.

--- End of Part I ---