During an import, the database levels are created in memory and then written to disk. During a load, the database levels are read from disk and stored in memory. This internal representation of the database is comprised of objects. The classes that create these objects are named after the corresponding tree levels. For example, the Base class creates an object at the base level.
In the Janis code, the objects corresponding to these database levels are typically not handled directly. Instead, id objects are used to identify these database level objects. As a result, there are two parallel structures in memory: the database tree and the databaseId tree. The objects in the databaseId tree contain only enough information to identify the level. These classes are also named after the corresponding tree level but with a suffix of Id. For example, the class Base has an associated id class of BaseId. These classes are located in the package janus.database, shown in Figure 1-6.
Each node in the tree contains links to its children, except at the datablock level. For the Base class, these children are instantiations of the DataType classes. These links are maintained in the field datatypesMap as a HashMap. A HashMap is comprised of a list of keys and their associated values. In this case, the keys are DataTypeId instances and the values are DataType instances. A hash function, as illustrated in Figure 1-9, is applied to the key to derive the hash address or code. With the hash code, the correct value or DataType instance can be obtained. A notation for this relationship is XXXXId -> XXXX where XXXX is database level class. For example, the Base object created during a load, has two entries in the datatypesMap field: radio(Radioactive data) and inter_n (Interaction Data(incident neutron)).
![]() |
Figure 1-9. Hash function
To avoid loading the entire database into memory, Janis only loads the levels that are needed. When the method load is invoked, only the keys are loaded into the HashMap, not the values. These keys provide a list of existing sub-levels in the database tree. If a value is needed, the method getXXXX(XXXXId) is invoked. At the base level, this method is getDataType(DataTypeId). Given the DataTypeId object or key, one of three conditions may occur:
· the key does not exist in the HashMap causing an error.
· the key does exist and the value has been previously loaded, that is the value is non-NULL. The value is then returned by this method.
· the key exists but the value is NULL. In this case the value is loaded from disk and stored in the HashMap. The value is then returned by the method.
Another method getOrCreateXXXX(XXXXId) is similar to getXXXX(XXXXId) but it is invoked only during an import. If a key does not exist with this method, then one is created and added to the HashMap. The value is then obtained in the same manner as in method getXXXX(XXXXId).
The method isXXXXPresent returns true if the given XXXXId object or key exists in the HashMap. The method getXXXXsList creates a sorted list of all the XXXXId instances from the HashMap. This method is used for setting the field parentId in each element of the list during an import. Another method removeXXXX removes the mapping or value from the HashMap for a given XXXXId instance or key.
Other methods for class XXXX are:
· init creates an empty HashMap.
· load reads the contents of file XXXX.dat from the location specified in the “Database/Load” dialog box. The information is loaded into the corresponding XXXX and XXXXId objects. Only the children of XXXXId instances or keys are added to the HashMap field. The associated value for each key is initially NULL because the levels are not yet loaded into memory. Once the database is loaded these values are updated.
· create is invoked during an import with the name from field directoryHandle. This method creates the file directory if it does not exist. Then the file XXXX.dat is created.
· save writes the contents of the XXXX instance to the XXXX.dat file. The method save is invoked by saveRecursive. Method saveRecursive is typically invoked to perform global saves. This approach minimizes the time spent writing to disk.
An accesor method for class XXXXId is:
· getOSName returns the content of field path.
Other methods for class XXXXId are:
· compareTo compares the path fields in two XXXXId instances.
· equals compares two XXXXId instances.
· streamLoad reads from a DataInputStream and creates a new XXXXId object.
· streamSave writes the field path to the DataOutputStream.
· toString returns the value of field path.