The business object model of openCRX is specified with UML. This has some important advantages:
IMPORTANT: this document is work in progress. It only describes a subset of
the openCRX 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:
./setenv.sh 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:
The task must meet the following prerequisites:
export GRAPHVIZ_HOME=/usr/bin export ALBUM_HOME=/usr/bin
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.
If you want to learn more about UML modeling for openMDX-based applications then
Introduction to Modeling with openMDX is a good starting point.
kernel is the main model package of openCRX. It contains all classes used by the
openCRX core service:
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,
The main classes of account1 are
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 until
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.
An Activity is a representation of anything what a resource "does". openCRX
supports the following activity types:
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:
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
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.
The model contains abstract classes capturing the different types of addresses:
The abstract classes are used in other models to define concrete address types such
as AccountAddress or ContractAddress.
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.
The base package contains classes and patterns which are used in other model packages. The
most important are
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:
The level determines the user's memberships:
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.
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 and
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
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.
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
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:
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
A sales contract has zero or more contract positions. Important attributes of a
contract position are:
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:
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
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:
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
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.
Cash is managed in bank accounts:
Securities are managed in bank depots:
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.
An international trading company managing multiple warehouses in several branches.
Continue reading Part II.
--- End of Part I ---