About the Caché Populate Utility
Once you have defined your first few classes, you probably want to start testing them. To do that, you need to put some data into the database. This can be done using Caché ObjectScript commands, such as
    Set obj=##class(Person).%New()
Set obj.Name="Kerouac,Jack"
Set obj.DOB=+$h
Write obj.%Save()
Do obj.%Close()
But this soon becomes boring and slow for most developers. As development proceeds, you may need to build a series of methods (or a routine) that inserts valid and meaningful data into the database, or perhaps even loads some real data itself.
Before doing this, you may want to just load some almost-random data into the database, so that you can exercise your classes and the User Interface. This is where the %Populate class can help.
Simple Use
Using the %Populate class can be very simple, or you can go to a lot of trouble to 'customize' the data that it creates, to make it look more realistic and complete. In the simplest case, you simply add %Populate as an additional superclass of your new class, such as:
super = %Persistent, %Populate;
Once your class has been recompiled, you will have access to a new method, Populate, which can be called as follows:
Do ##class(Person).Populate()
This will create 10 instances of your class and store them within the database, which you can see by running an SQL query against your object or by using a utility (such as the Caché Explorer) on the global oo<class>D, in this case ooPersonD (and ooPersonI, if you have defined any indices).
The Populate method takes, as an argument, an integer specifying how many instances to create, and returns a value showing how many were saved successfully (you may have defined some constraints on your class that are not satisfied by all randomly-generated data). In the following case:
Write ##class(Person).Populate(20)
19
The Populate method tried to insert another 20 instances to the class, but one insert operation failed.
Note that you must manually delete the class extent (set of all object instances) if you want to start with an empty one. You can do this using the %DeleteExtent method of the persistent interface.
The current version of %Populate will assign random values to most 'simple' attributes and references (as long as the referenced class has some instances), but will not give values to collections, etc. (see below).
Thus an attribute defined as type %Integer will be assigned a random integer (obeying the values of the MINVAL and MAXVAL parameters), while a %Date attribute will get a random date.
A %String will be assigned a random string value (see below).
Embedded Serial Classes
If your class contains an embedded serial class, such as a Home attribute within a Person class, which might be an instance of an Address class, then by default this will not be given a value by %Populate.
You can cause random values to be assigned to embedded classes by defining the POPSPEC parameter for both the embedded and the host class. The POPSPEC parameter tells %Populate which method to use when populating a particular attribute.
So, for example, if the Address class contains the attributes City and State, you might define:
parameter POPSPEC { default = "City:City(),State:USState()"; }
This specifies that for the City attribute, you want to use the City method in the class %PopulateUtils, and for the State attribute you want to use the USState method in %PopulateUtils.
The class %PopulateUtils provides a library of commonly-used data generation methods.
Then, within your main class (Person) you would define POPSPEC as:
parameter POPSPEC { default="Home:.Home.PopulateSerial()"; }
which specifies that for the Home attribute, you want to use the PopulateSerial method of the Home attribute.
Advanced Use
Sometimes, you want more control over the data that is generated, and you can achieve this by using the POPSPEC parameter introduced above and a method selected from the %PopulateUtils library or written yourself.
The POPSPEC parameter uses the following syntax :
Parameter POPSPEC { default="<att>:<spec>,<att>:<spec>,. . . "; }
Where:
Any attributes not listed in POPSPEC will get default data generated as described above.
For example if POPSPEC is specified as:
Parameter POPSPEC { default="PName:Name(""F""),Code:.MakeCode(),SSN:##class(Utils).MakeSSN()"; }
Then attribute PName will be populated by calling the method ##class(%PopulateUtils).Name("F").
The attribute Code will be valued using obj.MakeCode() where obj is the handle to the object being created, so this expects you to code the method MakeCode into your class.
The attribute SSN will be populated using ##class(Utils).MakeSSN().
The attribute Number (defined as type %Integer) will receive a random integer.
Note: You can achieve the same level of control by defining the POPSPEC parameter on a per-property basis. The usage is the same as described above but only specifies the behavior of a single property:
	attribute Name  { type = %String(MAXLEN=50, POPSPEC=.FirstName()); }
The OnPopulate Method
For additional control over the generated data you can define an OnPopulate method within your class. If an OnPopulate method is defined then the Populate method will call it for each object it generates. The method is called after assigning values to the properties but before the object is saved to disk. When you call the Populate method it, in turn, checks for the existence of the OnPopulate method and calls it for each object it generates. The method is called after assigning values to the properties but before they are saved.
For example, if you have a stream attribute, Memo, and you would like to assign a value to when populating, you can provide an OnPopulate method:
	method OnPopulate()
		returntype = %Status;
		code = {
			Do ..Memo.Write("Default value");

			QUIT $$$OK
		}
	}
Details
This section describes in some detail how %Populate works, so that you can understand what it does, and how to influence it
The %Populate class contains two method generators Populate and PopulateSerial, which are quite similar. Each persistent or serial class inheriting from %Populate will get one or the other of these two methods included.
We will describe only the Populate method here.
The Populate method is a loop, repeated for the requested number of objects.
Inside the loop, the code
A simple attribute with no overriding POPSPEC parameter is populated using code similar to:
Set obj.Description=##class(%PopulateUtils).String(50)
While using a library method from %PopulateUtils via a "Name:Name()" specification would generate:
Set obj.Name=##class(%PopulateUtils).Name()
An embedded Home attribute might create code like:
Do obj.HomeSetObject(obj.Home.PopulateSerial())
The generator loops through all the properties of the class, and creates code for some of the properties, as follows:
Refer to the %PopulateUtils class for a list of available methods.