How to use subclasses (type cast)

Primary tabs

Hello community,

I recently started to work with Ensemble. I defined a subclass of EnsLib.HL7.Message.  In my production I receive HL7v2 messages and transport them using the Message Router to a business operation. The operation class has an OnMessage method with parameter

pObject As MySubclassOfEnsLibHL7Message.

I expected that specifying the parameter type, on receiving the message an implicit type cast would be performed. However, $CLASSNAME reveals that my messages are still of type EnsLib.HL7.Message. How can I convert my messages in ObjectScript (without DTLs or something the like)?

My motivation for doing all of this is the following. I need to store copies of certain messages in a separate database, not in EnsLib_HL7.Message, where all the other messages are stored. So I thought the most intuitive way to achieve this would be to define the abovementioned subclass. Is there a better way to do this?

Any help is very much appreciated. Thank you in advance.

Replies

If I understand you correct you expect something  like

INSERT INTO new.MESSAGE (SELECT * from  EnsLib.HL7.Message  where id = ? )

this may work for rather modest designed relational tables but I doubt it will work for some complex structure as EnsLib.HL7.Message .

Subclassing is not the way to solve your problem for 2 reasons:

  • A subclass has always to match the .IsA() class type of its parent    (e.g. Employee as subclass of Person. Employee is also always a Person)
  • SubClasses share the storage with its parent. There are dirty tricks to avoid this but I assume you do not intend to change  EnsLib.HL7.Message.

There are ways to do something like this if you fiddle around in the storage structures. 
BUT: for reasons of transparency, documentation, and maintainability
I'd strongly recommend to use DTL. 


Fiddling around with COS in Ensemble is a rather tricky exercise.
Based on practical experience I can confirm that your successors will never forget you.

Thank you, Robert Cemper.

In fact, I now do something like your line of inline sql: I retrive my messages from the general EnsLib.HL7.Message database using their id. Although I liked the idea of setting up my own table, I suspect this is not how the system is intended to be used.

I surely did not want to mess with The Enslib message class. The documentation also hinted to some (can't judge if dirty) tricks to do this, but I'd rather not risk crashing the whole system...

Instead of subclassing I now use routing of messages by means of their values (message type, certain textual data) to distinguish different messages.

I hope this works out. What is COS, by the way?

COS is the acronym for Caché Object Script.
It is the oldest programming language in Caché , Ensemble, ... .

BTW. Your new approach looks promising and safe.

Hi Abel,

When we subclass a persistent class and we need that this subclass have a own storage we need to add in the inheritance class list the %Persistent class  first of all classes.

Shared storage

Class sample.MyHL7 Extends EnsLib.HL7.Message
{ 

Storage Default
{
<Type>%Library.CacheStorage</Type>
}

}

Own storage

Class sample.MyHL7 Extends (%Persistent, EnsLib.HL7.Message)
{ 

Storage Default
{
<Data name="MyHL7DefaultData">
<Value name="1">
<Value>%%CLASSNAME</Value>
</Value>
<Value name="2">
<Value>ParentId</Value>
</Value>
<Value name="3">
<Value>DocType</Value>
</Value>
<Value name="4">
<Value>Envelope</Value>
</Value>
<Value name="5">
<Value>Source</Value>
</Value>
<Value name="6">
<Value>IsMutable</Value>
</Value>
<Value name="7">
<Value>OriginalDocId</Value>
</Value>
<Value name="8">
<Value>MessageTypeCategory</Value>
</Value>
<Value name="9">
<Value>TimeCreated</Value>
</Value>
</Data>
<Data name="UserValues">
<Attribute>UserValues</Attribute>
<Structure>subnode</Structure>
<Subscript>"UserValues"</Subscript>
</Data>
<DataLocation>^sample.MyHL7D</DataLocation>
<DefaultData>MyHL7DefaultData</DefaultData>
<IdLocation>^sample.MyHL7D</IdLocation>
<IndexLocation>^sample.MyHL7I</IndexLocation>
<StreamLocation>^sample.MyHL7S</StreamLocation>
<Type>%Library.CacheStorage</Type>
} 

}

Thank you for the hint,

but this is exactly what I tried in the first place. The problem was to convert EnsLib.HL7.Message objects into objects of my derived class. I thought using a DTL was overkill and I hoped for another, simpler way. I think I'll abandon the approach using derived classes altogether.

Hi Abel,

The simplet way to create a new HL7 message form a existing message is call the method OutputToIOStream from the original message and the call the classmethod  ImportFromIOStream  of the subclass.

That sounds very handy indeed. I will try it for sure, as there is still a small caveat in my solution so far, which could be fixed this way. Thank you very much!