Skip to main content

PROTOCLASS

The PROTOCLASS command maps MultiValue dictionary definitions to corresponding Caché class definitions. It is used to import a MultiValue file’s data dictionary to Caché. PROTOCLASS creates a Caché class for the file, providing the corresponding object representation. PROTOCLASS creates and compiles the class definition, It generate both SQL and Object projections of MultiValue data. The dictionary items (or a specified subset of them) are mapped to corresponding Caché class properties.

Caution:

When creating a Caché class definition for a MultiValue file, it is strongly recommended that every unique attribute have a corresponding class property. Any field/attribute that does not have a corresponding class property will become empty when the %Save() method is invoked. (Attributes that are mere synonyms do not require a corresponding class property.)

Caché MVBasic object syntax can be used with an imported MultiValue file after the PROTOCLASS utility has been run on its dictionary.

PROTOCLASS provides the following types of access to MultiValue data:

  • Server access through Caché object syntax: MVBasic, ObjectScript, and Caché Basic.

  • Server access through Caché SQL via either Embedded SQL or Dynamic SQL.

  • Client access through projections: Java, .NET, C++, Perl, Python, and others.

  • Client access through JDBC and ODBC: standard tools, applications.

Note:

The name PROTOCLASS is meant to emphasize that typically the resulting class definition is a prototype or starting point. Frequently, you will have to run the utility repeatedly, each time making adjustments to the MV dictionaries, until you get your desired result. In addition, you may have to edit the class definition manually. You are free to make copies of PROTOCLASS (an MVBasic program) and modify it to suit your own application requirements.

In order to use PROTOCLASS you must perform the following steps:

  1. Load PROTOCLASS into the desired account (namespace).

  2. Configure PROTOCLASS to specify how the classes should be named.

  3. Check the data dictionary with CHECK.DICT.

  4. Run PROTOCLASS against the data dictionary.

Loading PROTOCLASS

The source code for PROTOCLASS is located in <cachesys>\Dev\mv\samples. (In a standard Windows Caché installation, <cachesys> is C:\InterSystems\Cache.) The code is fully customizable and contains extensive documentation describing how to customize it.

Use the Caché MultiValue shell to load PROTOCLASS into the current account (namespace).

The following Windows example uses the MV Shell to load PROTOCLASS into the USER account.

USER:;file = "C:\InterSystems\Cache\dev\mv\samples\PROTOCLASS.xml"
USER:;stat = "%SYSTEM.OBJ"->Load(file,"c")
 
Load started on 03/03/2011 12:51:06
Loading file C:\InterSystems\Cache\dev\mv\samples\PROTOCLASS.xml as xml
Creating file BP
Imported document: PROTOCLASS.mvb
Compiling BP PROTOCLASS
 
Load finished successfully.
USER:

After loading, PROTOCLASS appears as a verb in the VOC for the account.

USER:LIST.ITEM VOC "PROTOCLASS"
 
 
 
LIST.ITEM VOC "PROTOCLASS"                  01:00:18pm  03 Mar 2011  PAGE    1
 
 
     PROTOCLASS
0001 V
0002 PROTOCLASSýUSER
0003 B
0004
0005
0006
0007 L
0008 PROTOCLASS
0009 BP
0010 USER
 
 One item listed.
USER:

Setting Attribute 5

Before using PROTOCLASS, you must set the PROTOCLASS verb attribute 5 to “2D”. You can use the MultiValue ED line editor to set attribute 5, as shown in the following example:

USER:ED VOC PROTOCLASS
PROTOCLASS
10 lines long.
----:5
0005:
----:R 2D
0005: 2D
----:FI
"PROTOCLASS" filed in file "VOC".

When completed, the VOC entry for PROTOCLASS should look like this:

     PROTOCLASS
0001 V
0002 PROTOCLASSýUSER
0003 B
0004
0005 2D
0006
0007 L
0008 PROTOCLASS
0009 BP
0010 USER

Package and Class Naming

Before using PROTOCLASS, you must specify how it is to handle package and class name assignment. The default package and class is MVFILE.dictfilename. Using this default, PROTOCLASS creates classes in package MVFILE and assigns the MultiValue dictionary file name as the class name. For example, MVFILE.PERSON.

You can override this default by setting the dictionary file attribute 5 setting. When setting a package and class, a name to the left of a period is treated as a package name. A name without a period, or a name to the right of a period is treated as a class name. If either the package name or the class name is not specified, PROTOCLASS uses the default for that name.

Checking the Dictionary with CHECK.DICT

Before running PROTOCLASS on your file’s dictionary, use the CHECK.DICT command to validate the dictionary entries that you intend to represent in your Caché class. CHECK.DICT verifies the following:

  • The validity of conversion and correlative codes. Caché is somewhat stricter than many MultiValue platforms with regard to validity of correlative and conversion codes. In addition, there may be some codes that are not supported by Caché. Any such codes that CHECK.DICT finds invalid need to be removed or fixed prior to running PROTOCLASS.

  • The existence of dictionary items referenced by itypes and correlatives in your dictionary. If such items do not exist, then PROTOCLASS cannot generate a valid Caché class.

Running PROTOCLASS

You run PROTOCLASS against a MultiValue file using the following syntax:

PROTOCLASS filename {item1 [item2 [itemn]] | *} [(D]

Arguments

filename The MultiValue dictionary file to be mapped to a corresponding class.
item One or more dictionary items to be mapped to class properties. Multiple items are separated by blank spaces.
* A wildcard specifying that all dictionary items be mapped to class properties.
(D The optional (D letter code causes PROTOCLASS to delete an existing class. The default is to update an existing class.

By default, PROTOCLASS creates a class named MVFILE.filename, then creates a class property for each specified item. If you specified asterisk (*), PROTOCLASS creates a class property for each of the items in filename. PROTOCLASS then compiles the class it has just created. Only in the case of extremely clean dictionaries will PROTOCLASS generate properties for all items. Ensuring the dictionary entries are properly marked as Single or Multivalued prevents extraneous “list of” properties.

The resulting class definition includes parameter, property, and index declarations. The property definitions correspond to the attributes defined in the original MultiValue file. Single-value attributes are commonly assigned the Caché %String data type and MultiValue attributes are commonly assigned a list of %String data type strings. A property may be assigned a %MV.Date, %Time, or %MV.Numeric data type, based on the conversion codes in the attribute definition.

Run PROTOCLASS Example

The generation of Caché class definitions using PROTOCLASS is best done as an iterative process, rather than as a single bulk conversion of the entire MultiValue file. First run PROTOCLASS on the simple attributes (D-type attributes or A and S types without A or F correlatives) that you want represented in Caché. Use Studio to view the resulting Caché property declarations and make any needed modifications. Then run PROTOCLASS on a few of the complex attributes. View and modify the results. Repeat until you are done.

The following example runs PROTOCLASS against simple attributes of the PERSON file:

MyAccount:PROTOCLASS PERSON NAME AGE HAIR PHONE

Processing simple attribute definitions
Creating property called Name from NAME
Creating property called Age from AGE
Creating property called Hair from HAIR
Creating property called Phone from PHONE
Processing computed attribute definitions
Saving the generated class...
Compiling the generated class...

Compilation started on 11/11/2011 09:38:47 with qualifiers 'cfvko3'
Compiling class MVFILE.PERSON
Compiling table MVFILE.PERSON
Compiling routine MVFILE.PERSON.1
Processing MV projection...
MV file name is 'PERSON'
MVREPOPULATE is False, skipping DICT update

Compilation finished successfully in 1.228s.
Class generation and compilation was successful!

Which yields the following class definition:

  Class MVFILE.PERSON Extends (%Persistent, %MV.Adaptor, %XML.Adaptor)
  [ ClassType = persistent, Inheritance = right, ProcedureBlock, SqlRowIdPrivate ]
  {
  Parameter MVAUTOLOCK = 0;
  Parameter MVCLEARDICT = 0;
  Parameter MVCREATE As BOOLEAN = 0;
  Parameter MVFILENAME As STRING = "PERSON";
  Parameter MVREPOPULATE = 0;

  Property Age As %String(COLLATION = "MVR", MVATTRIBUTE = 1, MVAUTO ="P", MVNAME = "AGE", 
       MVPROJECTED = 0, MVTYPE = "D");
  Property Hair As %String(COLLATION = "Space", MVATTRIBUTE = 2,MVAUTO = "P", MVNAME = "HAIR", 
       MVPROJECTED = 0, MVTYPE = "D");
  Property ItemId As %String;
  Property Name As %String(COLLATION = "Space", MVATTRIBUTE = 3,MVAUTO = "P", MVNAME = "NAME", 
      MVPROJECTED = 0, MVTYPE = "D");
  Property Phone As list Of %String(COLLATION = "Space", MVATTRIBUTE = 4, MVAUTO = "P", MVNAME = "PHONE", 
      MVPROJECTED = 0, MVTYPE = "D");

  Index indexItemId On ItemId [ IdKey, PrimaryKey ];
  }

Once your Caché class contains properties that adequately represent your simple attributes, you can continue by running PROTOCLASS on your complex attributes (I-types and A or S types with A or F correlatives in attribute 8). For a complex attribute, PROTOCLASS generates two different Caché class members:

  • A calculated property. Properties of this type have no stored or in-memory values. Their values are calculated based on the values of other properties. One of the parameters of the property declaration is SqlComputeCode. This parameter identifies code (a Caché method) which calculates the value for the property.

  • A method containing the code that calculates a value for the property.

In the following example, PERSON contains an I-type property named ITEST. To add a property to your Caché class to represent ITEST invoke the following command:

MyAccount: PROTOCLASS PERSON ITEST

PROTOCLASS adds the following property declaration to the class definition. Note that the MVITYPE parameter contains the actual MultiValue code that defines the property. Note also the SqlComputeCode parameter. This parameter contains code that invokes a Caché method that calculates the value of the property.

Property Itest As %String(COLLATION = "Space", MVAUTO = "P",MVHEADING = "TYPE-I",MVITYPE = "TYPE;
@1[1,1];
IF @2=""F"" THEN ""FILE"" 
ELSE IF @2=""V"" THEN ""VERB"" 
ELSE IF @2=""K"" THEN ""KEYWORD"" 
ELSE IF @2=""S"" THEN ""MACRO"" 
ELSE IF @1=""PA"" THEN ""PARAGRAPH"" 
ELSE IF @1=""PH"" THEN ""PHRASE"" 
ELSE ""OTHER"";
TYPE:'-':@3",MVNAME = "ITEST", MVPROJECTED = 0, MVTYPE= "I", MVWIDTH = 20)
[ Calculated, SqlComputeCode = {Set {Itest}=##class(MVFILE.PERSON).calcItest({%%ID},{%RECORD})},
  SqlComputed ];

Here is the method that PROTOCLASS generates to calculate the property's value:

/// Calculates property Itest from the raw ref, using the itype routine
/// IMPORTANT!!! This routine should be recoded to use explicit properties rather than @Record.
ClassMethod calcItest(ItemID As %String, Item As %String) As %String
[ Language = mvbasic ]
  {
  @ID =ItemID
  @RECORD=Item
  MV$ITYPE$1 = @RECORD<1>
  MV$ITYPE$2 = MV$ITYPE$1[1,1]
  MV$ITYPE$3 = IF MV$ITYPE$2 = "F" THEN "FILE"
    ELSE IF MV$ITYPE$2 = "V" THEN "VERB"
    ELSE IF MV$ITYPE$2 = "K" THEN "KEYWORD"
    ELSE IF MV$ITYPE$2 = "S" THEN "MACRO"
    ELSE IF MV$ITYPE$1 = "PA" THEN "PARAGRAPH"
    ELSE IF MV$ITYPE$1 = "PH" THEN "PHRASE"
    ELSE "OTHER"
  MV$ITYPE$4 = @RECORD<1>:'-': MV$ITYPE$3
  RETURN MV$ITYPE$4
  }

@RECORD is a system variable. In the above method, it contains the current record as a delimited string. Notice that the automatically generated comments that precede the method definition suggest that you recode the method to use actual property names rather than the @RECORD syntax. This can dramatically simplify the method. In the example, the I-type property ITEST is calculated based on the value of TYPE. The method can be recoded as follows:

ClassMethod calcItest(TYPE As %String) As %String
[ Language = mvbasic ]
  {
  IF TYPE = "F" THEN RETURN "FILE"
    ELSE IF TYPE = "V" THEN RETURN "VERB"
    ELSE IF TYPE = "K" THEN RETURN "KEYWORD"
    ELSE IF TYPE = "S" THEN RETURN "MACRO"
    ELSE IF TYPE = "PA" THEN RETURN "PARAGRAPH"
    ELSE IF TYPE = "PH" THEN RETURN "PHRASE"
    ELSE "OTHER"
  }

You would then also need to change the SqlComputeCode in the property declaration to the following:

SqlComputeCode = {Set {Itest}=##class(MVFILE.PERSON).calcItest({TYPE})}

Property Naming

PROTOCLASS creates a class property that corresponds to each specified item. Because of the different naming conventions in MultiValue and Caché, the following naming conversions are performed:

  • If the first character of item is a number, prefix the property name with the letter “P”.

  • If the first character of item is a letter, capitalize that letter.

  • If the first character of item is a non-alphanumeric character, delete that character, then follow the naming rules above.

  • If item contains a non-alphanumeric character, delete that character and capitalize the letter that follows it. Lowercase all other letters except the first letter.

  • If item does not contains non-alphanumeric characters, retain the letter case as specified in item.

MVAUTO Parameter

Each resulting class property contains an MVAUTO parameter. MVAUTO contains a string of one or more letter codes indicating the source of the property definition and whether another property relies on it. MVAUTO prevents PROTOCLASS or CREATE.INDEX from overwriting any manual modifications that you may have made to a class.

PROTOCLASS sets MVAUTO to one or more of the following letter codes:

Value Meaning
P Property defined by PROTOCLASS.
I Property is defined by or is being used by an index.
R Another property references this property.
M The property has been defined through manual intervention. None of the automatic tools will modify it. You must add the M manually.

For further details on index properties, refer to the CREATE.INDEX command.

ItemId Property

The ItemId property of the generated Caché class represents the original MultiValue file’s item-id field. The ItemId property has an index defined on it. This index gives ItemId the following characteristics:

  • ItemId is an IDKEY and serves as the Caché objects ObjectID. Use ItemId to open objects. When you create a new object, you must assign a unique value to its ItemId property before saving the object.

  • ItemId is also the SQL primary key, so each record must have a unique value. Note that the SQL representation also includes the RowID field (named ID). Its values are always identical to the ItemID values.

PROTOCLASS creates a class with a property named ItemId, which describes the item id of the original MultiValue file. You can change the names of other properties in the generated class (assuming that you also change the name anywhere that the property is referenced by other properties, indices, or methods) but the ItemId property must be named ItemId. Otherwise subsequent CREATE.INDEX commands will fail and leave the class in an uncompileable state.

MVSVASSOCIATION Parameters

If the MultiValue dictionary definition contains at least 10 lines, PROTOCLASS generates MVSVASSOCIATION parameters for the properties when the controlling/dependent attribute is multivalued. This permits subvalue selection. For further details refer to Subvalue Considerations.

dummyAttribute Property

If the dictionary items to be mapped to a class consist entirely of virtual fields, PROTOCLASS automatically creates an additional property called dummyAttribute. Virtual fields include calculated fields and transient fields.

The dummyAttribute property is not created if the class contains one or more real (storage) attributes. If PROTOCLASS later adds a real attribute to the class, the dummyAttribute is automatically deleted. If you manually add a real attribute to a class that contains the dummyAttribute property, you should manually delete the dummyAttribute property and associated storage.

FeedbackOpens in a new tab