<REVISED>

ROOTS Type System

The documentation is intended for developers. Knowledge about Java and OSGi might be helpful for understanding the document.

ROOTS provides a type system based on Java types to persist any Java data, and to transport Java data between heterogeneous computer platforms. Here, we give a brief introduction to this type system and the supporting bundles of ROOTS.

The document is structured as follows:

  1. ROOTS Type System
    1. Introduction
      1. Motivation
      2. Summary of Requirements
      3. Discussion of Implementation Options
      4. SERS Overview
    2. Major Bundles Involved
    3. SERS in Detail
      1. Type Names and Identifiers
      2. Pre-defined Types
        1. Base Types
        2. Multi-Value Base types
      3. Extension Types
        1. Step 1: Define Extension Type
        2. Step 2: Define Application Type Factory
        3. Step 3: Provide Extension Type to SERS
      4. Miscellaneous
    4. The Extension Type SersMap
    5. HINO
  2. Appendix A: Byte Value Text Representation

Introduction

Motivation

One of the design goals of ROOTS was to provide a platform for event centric processing (short: ECP). ECP is based on the publish-subscribe-pattern is the core concept for any application programming with ROOTS. Besides others, ECP introduces the features persistence of events as well as an event process concept on top of single events.

For both features persistence of data is required. We decided to do persistence transparently for any event applications. Thus ECP applications are allowed to use any Java type for events and processes. The ECP implementation persists these data at relevant internal processing points without application interference.

Finally, another requirement was on the table: support of remote events. Events may be thrown at location one and processed at location two. That forces to support a interchange of event data between heterogeneous computers in a network. Again, this should work in a transparent way for applications.

Summary of Requirements

In the section above the motivation for the ROOTS type system was given. It stated the following requirements which are relevant for an implementation of the type system:

  1. use of Java types
  2. transparently persist Java type values
  3. transparently interchange of type values based on remote communications between heterogeneous platforms

Since ROOTS is OSGi based, it is obvious that OSGi conformance is an overall requirement.

Based on these requirements a short discussion of implementation options is given in the next section.

Discussion of Implementation Options

Regarding the requirements 1 and 2 of the previous section, support is given by Java itself through the Serialization interface and the concepts behind. Any Java object may be persisted in a transparent way by this approach. Since it uses a binary format, requirement 3 is not well supported. Furthermore, since Java object serialization is known for bad performance we skipped this approach.

Regarding requirement 3 we took a look at JSON. JSON is a good solution for data interchange. It also supports requirements 1 and 2 in general. However, it lacks of

Other non-light-way data interchange format like XML are too chatty, so, we skipped them too.

Finally, we decided to use a text based format of our own for the ROOTS type system. Currently, we name it SERS which is a acronym for Serialization by Strings. A more older name found in our documentation is 'StrObjects' for String Objects.
We not only use SERS as the name for serialized format, but, also as the name for the complete ROOTS type system.

SERS Overview

In SERS there is a distinction between pre-defined types and extension types. Pre-defined types include all Java base object types, i.e. the object form, and collections and arrays of base types. SERS is able to serialize and de-serialize pre-defined types without any additional effort from application developers side.

SERS provides a service interface for introducing application-defined types. Here, any Java type (class) can be introduced together with methods for converting object to string and vice versa.

Any type, whether pre-defined or not, has a unique type id in SERS.

Major Bundles Involved

In this section an overview of bundles related to SERS is provides. Bundles are as follows (here, + is shortcut for biz.kachel.roots):

Bundle Name Relation to SERS
+strobjects.type SERS bundle providing interfaces for application types as well as common SERS definitions.
+strobjects SERS bundle implementing the type system.
+.store Type definition for Store identifiers. ROOTS Store is the persistent object cache.
+.store.dss Type definition for the persistent hashing of objects in ROOTS Store.
+.hino.hm Type definition for the Hino Node Model. HINO is the Hierarchical Nodes Database of ROOTS. Each node allows storing of a persistent property set. According of the central role of Hino for ROOTS, there is a separate section below.
+.ecp.console.common Type definitions for exchange data with ROOTS clients. See also here.

SERS in Detail

The overview section at the beginning of this document gave a brief introduction to SERS. Here, SERS is documented in more details.

Type Names and Identifiers

Each type in SERS has a unique type name which is represented by a String value. These type names are called RSOID (Roots String Object IDentifier). Type names are unique across ROOTS Server instances (ROOTS server installation). However, since it is a string representation it is too long for some storage purposes. Therefore, the Short RSOID is introduced which is represented by a Long value. Short RSOID are only unique on a ROOTS Server instance, but may differ from instance to instance.

The allow the interpretation of a short RSOID outside of the ROOTS instance an application must be aware of the system-specific RSOID to short RSOID mapping. For the moment this mapping information is stored as Java property file under _<ROOTS Installation Path>/databases/sers/sers.properties with first ROOTS start.

Pre-defined Types

Base Types

The following table provides all pre-defined SERS base types, their RSOIDs, and the text representation of type values:

Java Type RSOID Value Text Representation
null SONull ""
String SOString by value.toString()
Integer SOInteger by value.toString()
Long SOLong by value.toString()
Float SOFloat by value.toString()
Double SODouble by value.toString()
Byte SOByte see Appendix A below
Short SOShort by value.toString()
Character SOCharacter by value.toString()
Boolean SOBoolean "t" for true, "f" for false
Date SODate by value.getTime().toString()

For the concrete String representation for value.toString() see the Java documentation.

Types not known by SERS have the RSOID SOUnsupported. Even if the system may not know them, they may have a valid value text representation.

Multi-Value Base types

Collections or arrays of any of the SERS base types, except SOUnsupported, are also part of the SERS pre-defined types. The RSOID of a collection or an array is the concatenation of either SOArray or SOCollection followed by . and the RSOID of the base type.

Example: The RSOID of String[] is SOAray.SOString.

Extension Types

Any ROOTS application may define its own SERS type, called extension type. Once declared, extension types can be used by SERS resp. applications using SERS.
The definition of an extension type consists of three steps. As an example for these steps the type SersMap is used.

The class SersMap is the essential class for handling values by ROOTS. For that reason there is a separate section for this type below.

Step 1: Define Extension Type

Each extension type must implement the StrSerialzed interface. In case of SersMap it looks like the following.


public class SersMap<T extends Object> extends Hashtable<String, T> implements StrSerialized

The interface is defined as follows:


/**
 * Common interface for all classes implementing serialization by string (SERS) objects.
 * For any class implementing this interface also a factory have to be provided implementing StrSerializedFactory.
 * A StrSerialized type has an type identifier, the RSOId (Roots string object type identifier).
 * The string value format of StrSeruialized type is <RSOId>:<value>.
 */
public interface StrSerialized {

	/**
	 * Provides the object value as string.
	 * @return object as string.
	 * @throws UnsupportedType in case the object is not well initialized.
	 */
	public String toStr() throws UnsupportedType;
	
	/**
	 * Reads object from string.
	 * @param objectValue string representation of the object as provided by toStr().
	 * @throws UnsupportedType in case obejctValue does not represent this type.
	 */
	public void fromStr(String objectValue) throws UnsupportedType;
	
	/**
	 * Provides the unique ROOTS SERS type identifier.
	 * @return ROOTS SERS type identifier.
	 */
	public RSOID getRSOId();
		
}


The JavaDoc of the interface definition declares the meaning of the interface methods. toStr() and fromStr() have to be implemented in the way that the operations must be inverse for each other. The sequence object.fromStr(object.toStr()) must keep the object value as is.

SERS uses the interface methods to perform string serialization operations and be aware of the type without knowing any implementation details. The RSOID provided by the interface is application defined and must be unique. It is up to conventions to define type name strategies (if nothing defined use full qualified class names for RSOIDs). However, type names are restricted in the way that they are not allowed to contain a '.'.

The RSOID provided by the interface is a plain name, e.g. MyType. Internally, SERS uses an expanded, full qualified name representation with SOSerialized as prefix. In this example it will be SOSerialized.MyType.

Step 2: Define Application Type Factory

Stefan: "multi-value objects" das klingt ganz seltsam. Kann man das wirklich so sagen? Klingt für mich wie ein Integer der 5 und 12 gleichzeitig als Wert hat.

Besides plain extension types, arrays and collections of these types are also allowed. To give SERS the ability to create objects and arrays or collections of objects on its own, the extension type factory interface is introduced as follows:


/**
 * Factory interface for SERS (Serialization by String) types.
 * @author gerd
 *
 */
public interface StrSerializedFactory {
	
	/**
	 * Service property name. 
	 */
	public static final String RSOID_SERVICE_PROPERTY_NAME = "RSOID"; 
	
	/**
	 * Creates a new object of the SERS type.
	 * The object is provided by its StrSerialized interface.
	 * @return new object created.
	 */
	public StrSerialized create();

	/**
	 * Creates a new empty object array of the SERS type.
	 * The object array is provided by its StrSerialized interface.
	 * @param dimension the dimension of the array.
	 * @return new object array created.
	 */
	public StrSerialized[] createArray(int dimension);

	/**
	 * Creates a new empty object collection of the SERS type.
	 * The object collection is provided by its StrSerialized interface.
	 * @param initialSize the initial size of the collection.
	 * @return new object collection created.
	 */
	public Collection<StrSerialized> createCollection(int initialSize);

}

For the type SersMap the factory definition is:


public class SersMapFactory implements StrSerializedFactory {

	/**
	 * Constructor.
	 */
	public SersMapFactory() {
		super();
	}

	/* (non-Javadoc)
	 * @see biz.kachel.roots.strobjects.StrSerializedFactory#create()
	 */
	@Override
	public StrSerialized create() {
		return new SersMap<>();
	}

	/* (non-Javadoc)
	 * @see biz.kachel.roots.strobjects.StrSerializedFactory#createArray(int)
	 */
	@Override
	public StrSerialized[] createArray(int dimension) {
		return new SersMap[dimension];
	}

	/* (non-Javadoc)
	 * @see biz.kachel.roots.strobjects.StrSerializedFactory#createCollection(int)
	 */
	@Override
	public Collection<StrSerialized> createCollection(int initialSize) {
		return new ArrayList<>(initialSize);
	}

}

As you see the implementation of the interface methods is very straight-forward.

The use of this factory is content of the next section.

The full qualified type name of MyType[] is SOArray.SOSerialized.MyType (see also above).

Step 3: Provide Extension Type to SERS

The extension type is provided to SERS by defining an OSGi service which provides the factory interface StrSerializedFactory together with the service property name RSOID holding the type name as value. SERS implementation listen on the service registry and tracks defined type on the fly.

The factory interface StrSerializedFactory provides a constant definition for service property name RSOID, namely by StrSerializedFactory.RSOID_SERVICE_PROPERTY_NAME (see above).

By using the OSGi service annotation and component system of ROOTS the definition of the SersMap extension type looks as follows.

For the service definition:


	@Component(type = Type.COMPONENT)
	@Provides(interfaces={StrSerializedFactory.class})
	public class SersMapFactory implements StrSerializedFactory

For the type instantiation within the bundle activator:


		Dictionary dic = new Hashtable<>();
		dic.put(StrSerializedFactory.RSOID_SERVICE_PROPERTY_NAME,
				SersMap.MY_RSOID.toString());
		this.instantiate(SersMapFactory.class, dic);

Miscellaneous

For implementing own extension types there is a set of serialization utilities provided by the package biz.kachel.roots.strobjects.util.

The Extension Type SersMap

In the previous section SersMap was used as an example for extension type definitions. SersMap is the key extension type in ROOTS. It provides a string serialized implementation of Java class Hashtable with a string key. By that it can be used in many Java places where objects of type Map or Dictionary are required. On the other hand, SersMap can be constructed using a Map or a Dictionary object. Thus, it is the a big bridge between Java and SERS.

You will find that SersMap is used in multiple ROOTS places like HINO (see below) or the remote system. For the latter, it is of value to know the string representation of SersMap to allow non Java clients to access ROOTS remotely.

The SersMap implementation uses the utility class StringSerializationByLE provided in package biz.kachel.roots.strobjects.util. The text representation of a SersMap is as follows:

  1. Each property value pair is stored in one text line (ends with EOL character).
  2. A property value pair is mapped to text by using a separator ':'. The mapped result is <property name>:<short RSOID>:<string serialized value>.
  3. Occurrences of ':' in either names or string serialized values are masked by '/:/'.

HINO

HINO (Hierarchical Nodes) is the ROOTS database system. It is a hierarchical node database where any node consists of a name and a set of key value pairs. At the HINO interface each type is allowed which is known by SERS. Besides that there is the so called HINO Node Model (shortly HNM) which is also an extension type (with RSOID = HNM). HNM is a type to define HINO data transiently.

TODO: Add HINO reference as far as HINO documentation is available.

Appendix A: Byte Value Text Representation

Byte data is represented as text by an own calculation which performs better than known codings like BASE64. Furthermore, it keeps mostly human readable for byte data representing text itself. Calculation is done as follows.

Dec Char
0 {@
1 {A
2 {B
3 {C
4 {D
5 {E
6 {F
7 {G
8 {H
9 {I
10 {J
11 {K
12 {L
13 {M
14 {N
15 {O
16 {P
17 {Q
18 {R
19 {S
20 {T
21 {U
22 {V
23 {W
24 {X
25 {Y
26 {Z
27 {
28 {#
29 {]
30 {^
31 {_
32
33 !
34 \"
35 #C
36 $
37 %
38 &
39 \'
40 (
41 )
42 *
43 +
44 #L
45 -
46 .
47 /
48 0
49 1
50 2
51 3
52 4
53 5
54 6
55 7
56 8
57 9
58 \:
59 ;
60 <
61 =
62 >
63 ?
64 @
65 A
66 B
67 C
68 D
69 E
70 F
71 G
72 H
73 I
74 J
75 K
76 L
77 M
78 N
79 O
80 P
81 Q
82 R
83 S
84 T
85 U
86 V
87 W
88 X
89 Y
90 Z
91
92 #
93 ]
94 ^
95 _
96 `
97 a
98 b
99 c
100 d
101 e
102 f
103 g
104 h
105 i
106 j
107 k
108 l
109 m
110 n
111 o
112 p
113 q
114 r
115 s
116 t
117 u
118 v
119 w
120 x
121 y
122 z
123 {
124
125 }
126 ~
127 \
128 \@
129 \A
130 \B
131 \C
132 \D
133 \E
134 \F
135 \G
136 \H
137 \I
138 \J
139 \K
140 \L
141 \M
142 \N
143 \O
144 \P
145 \Q
146 \R
147 \S
148 \T
149 \U
150 \V
151 \W
152 \X
153 \Y
154 \Z
155 \
156 \#
157 \]
158 \^
159 \_
160 }
161 }!
162 }\"
163 }#C
164 }$
165 }%
166 }&
167 }\'
168 }(
169 })
170 }*
171 }+
172 }#L
173 }-
174 }.
175 }/
176 }0
177 }1
178 }2
179 }3
180 }4
181 }5
182 }6
183 }7
184 }8
185 }9
186 }\:
187 };
188 }<
189 }=
190 }>
191 }?
192 }@
193 }A
194 }B
195 }C
196 }D
197 }E
198 }F
199 }G
200 }H
201 }I
202 }J
203 }K
204 }L
205 }M
206 }N
207 }O
208 }P
209 }Q
210 }R
211 }S
212 }T
213 }U
214 }V
215 }W
216 }X
217 }Y
218 }Z
219 }
220 }#
221 }]
222 }^
223 }_
224 }`
225 }a
226 }b
227 }c
228 }d
229 }e
230 }f
231 }g
232 }h
233 }i
234 }j
235 }k
236 }l
237 }m
238 }n
239 }o
240 }p
241 }q
242 }r
243 }s
244 }t
245 }u
246 }v
247 }w
248 }x
249 }y
250 }z
251 }{
252 }
253 }}
254 }~
255 }\