This chapter describes how data type classes work and describes how to define them. It discusses the following topics:
When viewing this book online, use the preface
of this book to quickly find other topics.
The purpose of a data type class is to be used as the type of a literal property
in an object class
. Data type classes provide the following features:
They provide for SQL, ODBC, ActiveX, and Java interoperability by providing SQL logical operation, client data type, and translation information.
They provide validation for literal data values, which you can extend or customize by using data type class parameters.
They manage the translation of literal data for its stored (on disk), logical (in memory), and display formats.
Data type classes differ from other classes in a number of ways:
They cannot be instantiated or stored independently.
They cannot contain properties.
They support a specific set of methods (called the data type interface), which is described below.
Because it is useful to be aware of some internal details, this section briefly discusses how data type classes work.
As noted previously, the purpose of a data type class is to be used as the type of a property, particularly within a class that extends one of the core object classes. The following shows an example object class that has three properties. Each property uses a data type class as its type.
Class Datatypes.Container Extends %RegisteredObject
Property P1 As %String;
Property P2 As %Integer;
Property P3 As %Boolean;
When you add literal properties to a class and compile the class, Caché adds property methods
to that class. For reference, let us use the term container class
to refer to the class that contains the properties. The property methods control how the container class handles the data for those properties. This system works as follows:
In the example shown here, when we compile the Datatypes.Container
, the compiler uses the method generators of the %String
, and %Boolean
data type classes. These method generators create methods for each property and add these methods to the container class. As noted above, these methods are called property methods
. Their names start with the name of the property to which they apply. For example, for the P1
property, the compiler generates methods such as P1IsValid()
The container class automatically calls the property methods at suitable points in processing. For example, when you call the %ValidateObject()
instance method for an instance of the class shown above, the method in turn calls P1IsValid()
, and P3IsValid()
that is, it calls the IsValid()
method for each property. For another example, if the container class is persistent, and you use Caché SQL to access all the fields in the associated table, and the SQL runtime mode is ODBC, Caché calls the LogicalToODBC()
method for each property, so that the query returns results in ODBC format.
Note that the property methods are not visible in the class definition.
Many of the property methods translate data from one format to another, for example when displaying data in a human-readable format or when accessing data via ODBC. The formats are:
The format in which data can be input and displayed. For instance, a date in the form of April 3, 1998 or 23 November, 1977.
The in-memory format of data, which is the format upon which operations are performed. While dates have the display format described above, their logical format is integer; for the sample dates above, their values in logical format are 57436 and 50000, respectively.
The on-disk format of data the format in which data is stored to the database. Typically this is identical to the logical format.
The format in which data can be presented via ODBC or JDBC. This format is used when data is exposed to ODBC/SQL. The available formats correspond to those defined by ODBC.
SOAP-encoded format. This format is used when you export to or import from XML. This applies only to classes that are XML-enabled
Class parameters have a special behavior when used with data type classes. With data type classes, class parameters are used to provide a way to customize the behavior of any properties based on the data type.
Property NumKids As %Integer(MAXVAL=10);
Internally, this works as follows: the validation methods for the standard data type classes are all implemented as method generators and use their various class parameters to control the generation of these validation methods. In this example, this property definition generates content for a NumKidsIsValid()
method that tests whether the value of NumKids
exceeds 10. Without the use of class parameters, creating this functionality would require the definition of an IntegerLessThanTen
To easily define a data type class, first identify an existing data type class that is close to your needs. Create a subclass of this class. In your subclass:
Override any class parameters as needed. For example, you might override the MAXLEN
parameter so that there is no length limit for the property.
If needed, add your own class parameters as well.
Override the methods of the data type class as needed. In your implementations, refer to the parameters of this class as needed.
If you do not base your data type class on an existing data type class, be sure to add [ ClassType=datatype ]
to the class definition. This declaration is not needed if you do base your class on another data type class.
Depending on your needs, you should define some or all of the following class methods in your data type classes:
If the data type class includes the DISPLAYLIST
parameters, these methods must first check for the presence of these class parameters and include code to process these lists if present. The logic is similar for other methods.
The following shows an example:
ClassMethod LogicalToDate(%val As %MV.Date) As %Library.Date [ CodeMode = expression, ServerOnly = 1 ]
Note that the data format and translation methods cannot include embedded SQL. If you need to call embedded SQL within this logic, then you can place the embedded SQL in a separate routine, and the method can call this routine.
You can also add instance methods to the data type class, and these methods can use the variable %val
, which contains the current value of the property. The compiler uses these to generate the associated property methods in any class that uses the data type class. For example, consider the following example data type class:
Class Datatypes.MyDate Extends %Date
Method ToMyDate() As %String [ CodeMode = expression ]
Suppose that we have another class as follows:
Class Datatypes.Container Extends %Persistent
Property DOB As Datatypes.MyDate;
/// additional class members
When we compile these classes, Caché adds the instance method DOBToMyDate()
to the container class. Then when we create an instance of the container class, we can invoke this method. For example:
© 1997-2019 InterSystems Corporation, Cambridge, MA