Click here to add PLEX WORLD. METATASKS: WORKING WITH OBSYDIAN (Cool:Plex, Advantage Plex) META CODE to your list of favorites
This section is intended for intermediate/advanced Plex users. If you are new
to metacode you would benefit from reading the following Meta
Code Tutorial written by Adrian Slade (let me know if you cannot
find the tutorial at this location. File is also posted at Yury
Lesiuk's site).
If you have questions, don't hesitate to drop me an email. I provide on-demand remote (100% via the internet) hourly consulting for the entire Development and Project Lifecycles at the best cost in the market.
Developed by: Lucio Gayosso, MIS/M, BS, PLEX Expert (1999-2010)
Other resources:
Solution: Enter the following meta-code to retrieve the implementation
name in the function being called. Metacode:
+For Each Property Target FNC impl name NME
_+++Define Field: Impl_Name_Field
_+++Set Value To Current Field: Impl_Name_Field
_++Name Defined Field: Impl_Name_Field, Output < Impl_Name_Field >
Where:
Impl_Name_Field IS A Fields/Identifier (suggested)
The output field Impl_Name_Field can then be retrieved in the calling
function and displayed in a message.
2b. How can I get the Impl Name for a given Function B withing a
Function A:
Set Work<Function Impl Name> = <Function Impl Name.*Blank>
+++Define Function: MyFunctionFullyQualifiedName
+++Define Field: FIELDS/+Name
+For Defined Value Function: MyFunctionFullyQualifiedName
> +For Each Property Target FNC impl name NME
>> +++Set Value To Current Field: FIELDS/+Name
>> ++Name Defined Field: FIELDS/+Name, Environment<*Object>
>> Cast Work<Function Impl Name>, Environment<*Object>
Work<Function Impl Name> contains the implementation name of "MyFunctionFullyQualifiedName"
In addition, to develop pattern-based functionality to retrieve Impl Names of many functions follow the guidelines in the following CA's PLEX Forum thread:
Solution: Wrap all the logic in a meta-defined subroutine. Add Edit Points
that will allow the inheriting function to bypass this code by "Undefining"
the meta-variable. Metacode:
Sub TestSubroutine
+++Define Field: FIELDS/+Subroutine
Edit Point Begin TestSubroutine
+If Field: FIELDS/+Subroutine
Add your logic here
Edit Point End TestSubroutine
+++Undefine Field: FIELDS/+Subroutine
Use the "Begin TestSubroutine" Edit Point in any inheriting function to Undefine
and this way, bypass this logic.
Solution: Create the following subroutine and call it in your Action Diagram
whenever you want to remove the spaces for all the fields in the requested
variable:
Sub Remove Trailing Blanks from LOCALVAR Fields
Removes the trailing blanks from all of the character
fields in the LOCALVAR local variable
+For Each Field LOCALVAR
+++Define Field: OBASE/Field
+++Set Value To Current
Field: OBASE/Field
++If Not Empty
+For
Defined Value Field: OBASE/Field
+If
FLD type SYS, System: Character
++Cast
To String<Character string>
API
Call Source code: STDRBASE/Remove trailing blanks
+++Define
Field: OBASE/Field name
++Name
Defined Field: OBASE/Field name, String<Field name>
++Cast
From String<Returned string>
+++Undefine Field: OBASE/Field name
+++Undefine Field: OBASE/Field
"STDRBASE/Remove trailing blanks" Source Code object:
// Removes trailing (right) blanks from a character string with TrimRight
function inherited from CString.
{
&(1:) = &(2:);
&(1:).TrimRight();
}
Where:
&(1:) = Returned string
&(2:) = Character string
The parameters are strings (long enough to handle fields with trailing spaces)
for both input/output.
Alternatively, a universal trim function (that trims on both sides of the strings) could be used:
{
&(1:).TrimLeft();
&(1:).TrimRight();
}
Solution: The following MetaCode retieves the name of MyMessage Message
object.
+++Define Field: OBJECTS/*Message ID
+++Define Field: OBJECTS/*Message
+++Define Message: MyMessage
+++Set Value Field: OBJECTS/*Message, Message: MyMessage
+For Defined Value Field: OBJECTS/*Message
+For Each Property MSG impl name NME
+++Set Value To Current
Field: OBJECTS/*Message ID, .Target
++Name Defined Field:
OBJECTS/*Message ID, Environment<*Message ID>
Solution: Define all the functons that can possibly be called by Function
A by adding "Function A Calls FNC" triples.
On the Action Digram add the following Meta Code:
Seq Meta Code
+++Define Field: FIELDS/Function
+For Each Property FNC calls FNC
+++Set Value To Current Field:
FIELDS/Function, .Target
++Name Defined Field: FIELDS/Function,
Local<USR Web Calling Function>
If Local<USR Web Calling
Function> == WebInput<USR Web Calling Function>
++Call
Field: FIELDS/Function, MetaParameters
Terminate
The field WebInput Solution: Use the following meta-code. Name retrieved will be stored in
Work
+++Define Field: FIELDS/+Function Note: It is a good idea to encapsulate all metacode in a SEQ contruct. For
example: Seq FunctionOptions
+++Define Field: Current entity +For Each Object Entity //Loops around all the entities
in the model +If Query Object Library +If Query Object Scope +If Query Object Real // Only include real entities
+++Define Field: FIELDS/+Name +If Query Object Library +++Set Value To Current Field: FIELDS/+Name +If Query Object Library +For Each Property Target FNC impl name NME +++Set Value To Current Name: OBJECTS/+Meta +++Undefine Field: +Include +For Each Property Target FNC file name NME +++Set Value To Current Name: OBJECTS/+Meta +++Undefine Field: +Include +For Each Property Target FNC name NME +++Set Value To Current Name: OBJECTS/+Meta +++Undefine Field: +Include +If Field: +Include +For Each Object Field +If Query Object Library +For Each Property Target FLD impl name NME +++Set Value To Current Name: OBJECTS/+Meta +++Undefine Field: +Include +For Each Property Target FLD special type
NME +++Set Value To Current Name: OBJECTS/+Meta +++Undefine Field: +Include +If Field: +Include Notes:
+++Define Field: FIELDS/+Name Set Work<AllBlanksField> = <AllBlanksField.BLANKS> // This field contains a string with the maximum length of the longest field
in the variable and is defaulted to all blanks +For Each Field VariableName Additionally, for this task it was required to fill will trailing
blanks all fields that did have a value to meet a fixed-length field format.
The code was enhanced to fill with trailing BLANKS in the following manner: +For Each Field VariableName A vital component of the previous metacode is the ++Cast From statement
that generates a Cast statement from a specified field, or the
field returned by a meta-query, to the current field. Full syntax:
CUSTOMER refers to ADDRESS
...for BILLING. Need the Imp Name for attribute: 'BILLING | ADDRESS ID')
+For Each View
+For Each Entity Relation
+For Each Attribute
+++Set
Value To Current Field: FIELDS/+Field
+For
Defined Value Field: FIELDS/+Field
+If
ATR impl name NME
++Set
Value Field: FIELDS/+Name, FLD impl name NME
++Name
Defined Field: FIELDS/+Name, Work<AttributeName>
+++Set Value To Current Field: FIELDS/+Function
+For Defined Value Field: FIELDS/+Function
+If FNC language SYS, System: RPG400
Call Function1
+If FNC language SYS, System: WinNTC
Call Function2
+++Define Field: FIELDS/+Function
+++Set Value To Current Field: FIELDS/+Function
+For Defined Value Field: FIELDS/+Function
+If FNC language
SYS,
System: RPG400
+++Define
Field: FIELDS/+RPG400
+If FNC language SYS, System:
WinC
+++Define
Field: FIELDS/+WinC
+If FNC language
SYS,
System: WinNTC
+++Define
Field: OBASE/+WinNTC
+If FNC language
SYS,
System: Java
+++Define
Field: FIELDS/+JAVA
+If FNC language
SYS,
System: Oracle
+++Define
Field: FIELDS/+Oracle
+If FNC language
SYS, System: OracleWinNT
+++Define
Field: FIELDS/+Oracle
// Exclude library objects
+Else
// Exclude scoped entities
+Else
+++Set Value To Current Field: Current Entity
++Name Defined Field: Current Entity, Report<Object
Name>
Print Report
++Undefine Field: Current Entity
+++Define Name: OBJECTS/+Meta
+For Each Object Name
// Check every NAME Object in the Model
// Do nothing if the NAME Object Belongs to a library
+Else
+++Define Field: +Include
+For Each Object Function
// Do nothing if the Function Object Belongs to a library
+Else
+If EQ Name: OBJECTS/+Meta, Field: FIELDS/+Name
// Don't include if NAME is target of a FNC impl name NME triple
+If EQ Name: OBJECTS/+Meta, Field: FIELDS/+Name
// Don't include if NAME is target of a FNC file name NME triple
+If EQ Name: OBJECTS/+Meta, Field: FIELDS/+Name
// Don't include if NAME is target of a FNC name NME triple
// Do nothing if the Field Object Belongs to a library
+Else
+If EQ Name: OBJECTS/+Meta, Field: FIELDS/+Name
// Don't include if NAME is target of a FLD impl name NME
triple
+If EQ Name: OBJECTS/+Meta, Field: FIELDS/+Name
// Don't include if NAME is target of a FLD special type
NME
++Name Defined Field: FIELDS/+Name, Environment<*Object>
Print Report
// The Name has not been found as the target of any triple, issue a
report
+++Define Field: FIELDS/+Entity
+++Define View: YourEntity.Update
+For Defined Value View: YourEntity.Update
+++Set Value Field: FIELDS/+Entity, Query
Object Scope
+For Defined Value Field: FIELDS/+Entity
+For Each Property Target
ENT table TBL
+For
Each Property Target TBL impl name NME
+++Set
Value To Current Field: FIELDS/+Name
++Name
Defined Field: FIELDS/+Name, Work<TableName>
+++Define Field: OBASE/Field
+++Set Value To Current Field: OBASE/Field
++If Empty
+If FLD type SYS,
System: Character
++Cast
From Work<AllBlanksField>
+++Define Field: OBASE/Field
+++Set Value To Current Field: OBASE/Field
++If Empty
+If FLD type SYS,
System: Character
++Cast
From Work<AllBlanksField>
++Else
Fill out with trailing blanks
all fields that were assigned a value
++Cast To Work<Character
string>
Set Work<2nd string
| Character string> = <Character string.BLANKS>
Format Message Message:
Concatenate 2 strings, Work<Character string>
++Cast From Work<Character
string>
Solution: Create a subroutine in your Action Diagram that contains the following metacode:
Sub Capitalize all FieldsInVariableName
+For Each Field VariableName
+++Define Field: OBASE/Field
+++Set Value To Current Field:
OBASE/Field
++If Not Empty
+If FLD type SYS,
System:
Character
++Cast
To Work<VaryCharacter>
API
Call Source code: WINAPI/MakeAllUpper
++Cast
From Work<VaryCharacter>
The metacode looks for all character field in variable VariableName to then cast them to a work VaryCharacter field that is then used by the MakeAllUpper Souce Code to be capitalized. After capitalization values cast back to their original field.
Solution: In the following example all fields within variable FirstParty that inherit from a common ancestor (Amount) are initialized to empty value (zero, as the ancestor is numeric)
+++Define Field: CTABLES/(Amount)
+++Define Field: FIELDS/Current
+For Each Field FirstParty
++If Not Empty
+For Each Property Target
FLD is a FLD
+++Set
Value To Current Field: FIELDS/Current
+If
EQ Field: FIELDS/Current, Field: CTABLES/(Amount)
++Set
Empty
+++Undefine Field: CTABLES/(Amount)
+++Undefine Field: FIELDS/Current
The meta-loop checks each current field's FLD is a FLD triple and gets the name of the target field. If such value is (Amount) -Current field IS A FLD (Amount)- then the field is set to empty value.
Solution: The following Remove Nulls sequence loops through all fields in the VariableName variable and assigned the default valid EMPTY or NULL value or seeting to EMPTY to avoid the <NULL>
+For Each Field VariableName
++If Empty
+Case
+When
FLD null VAL
++Set Value FLD null VAL
+When
FLD empty VAL
++Set Value FLD empty VAL
+Otherwise
++Set Empty
Solution: Create the following subroutine:
Sub Validate Dates are ISO
+For Each Field FetchedData
+++Define Field: OBASE/Field
+++Set Value To Current Field: OBASE/Field
+For Defined Value Field: OBASE/Field
+If FLD type SYS, System: Date
++Cast To Work<Ref ISO Date>
// Input<DateISO> Work<Ref ISO Date>
Call DATE/ValidateDateISO
If Environment<*Returned status> != <*Returned status.*Successful>
Comment Invalid ISO Date. Set to BLANK
Set Work<Ref ISO Date> = <Ref ISO Date.*Blank>
Else
Comment Valid date. Continue processing it
+++Define Field: OBASE/Field name
++Name Defined Field: OBASE/Field name, Work<Field name>
++Cast From Work<Ref ISO Date>
+++Undefine Field: OBASE/Field name
+++Undefine Field: OBASE/Field
You can create explicit logic to get the field's value on the panel (i.e.
Get DetailP<Field>) and when the Updated event occurs (i.e. user has
entered the value then left the edit box) then trigger the associated process.
The problem with this approach is that you have to specify this logic for
each field on the pane that would trigger logic in this way.
Another 'abstract' approach is through the use of metalogic associated to
the Gained Focus event, to determine what field is currently being updated,
and the Updated Event, to trigger the processing with the value just entered
after the user leaves the Edit Box.
On the Panel Edit, associate both the Gained Focus and Updated Events to
the Edit Box of each control that will process similar logic then define
the following events (logic obtained from Plex's FOUNDATION Pattern Library
Help|Abstract Event Handling and the common processing defined in the Updated
Event is for retrieving Virtual fields associated to the ID/Key entered by
the user)
Edit Point Additional events
Event Event: Gained Focus
+For Each Field Details
++If Focus
+++Define Field: focus field // focus field is a varying length char field
+++Set Value To Current Field: focus field
++Name Defined Field: focus field, Local.focus field>, .Scoped //Current field getting focus is assigned to work field
Event Event: Updated
+For Each View Details
+For Each Entity Relation
+++Undefine Field: Virtuals Exist
+For Each Attribute
+If Query View Virtual
+++Define Field: Virtuals Exist // At least one virtual is on the panel
+If Field: Virtuals Exist
Set Local.Full key specified> = .Full key specified.*True>
+For Each Attribute
+If Query View Foreign Key
++If Empty
Set Local.Full key specified> = .Full key specified.*False>
If Local.Full key specified> == .Full key specified.*True>
++Call ENT checked by FNC, .Target
If Environment.*Returned status> == .*Returned status.*Error>
// Blank out virtuals if no record found
+For Each Attribute
+If Query View Virtual
++Set Empty
Put Details
1) Create a field 'ValueLabelConversion' which will scope a new function 'ConvertValueToLabel'
2) Scoped function can be either internal/external, client/server.
3) Add the scoping field as an Input parameter, and another field like *Object or appropriate as a Dual Parameter. This field will hold the returned string (the Value Label)
4) Add the scoping field as a Local field to the function, and also, if you did not use *Object, the field you used as a Dual.
5) Define the following Metalogic. Also create the fields +Label and +Value or use another appropriate field as these are used to hold the meta-variables
+++Define Field:+Label
+++Define Field:+Value
+++Define Field:ValueLabelConversion
+For Defined Value Field:ValueLabelConversion
+For Each Property Target FLD value Val+++Set Value To Current Field: +Value
++Text Defined Field: +Value, Environment<*Object> // The field may not be character so use *object and then cast
Cast Local<ValueLabelConversion>, Environment<*Object>
If Input<ValueLabelConversion> == Local<ValueLabelConversion>
+If Val label LBL
+For Each Property Target VAL label LBL
+++Set Value To Current Field: +Label
++Text Defined Field: +Label, Input<*Object>,.Text
+Else
++Name Defined Field +Value, Input<*Object>, .Language
Go Sub Terminate
Whenever this functionality for a field is required make MyField IS A ValueLabelConversion with continuation triple ... LIMIT SYS ALL and call the function for the field to convert its value to its label, or the name of the value. More details at:
http://caforums.ca.com/ca/board/message?board.id=caplexgeneraldiscussion&thread.id=1210
Do you have any problem/solution you would like to share? Send me an e-mail
and I'll get it posted.
If you found any information interesting or useful please mention it on the
Guestbook on the main page of Plex world.
If you could contribute to keep this site free, personal checks or paypal
payment are gladly accepted (no matter how small the contribution)
Developed by: Lucio Gayosso, MIS/M (1999-2010)
Background music: Tangerine Dream's "Sun Gate" (same album's name)
Use the controls to Stop, Start, Play the music
Listen to: R@DIO
DIMENSION and let your mind fly... |
||
Escucha: R@DIO
DIMENSION y deja a tu mente volar...
|