OmniMark Extension Components (OMX) are used to extend the functionality of OmniMark the same way Active X and other component types are used to extend other programming languages.
Because OmniMark is a network programming language, its requirements for a software component technology are different from most other languages, in which components are used mainly for user interface building. OMX components are not visual components, nor do they support the drag and drop style of programming found in visual programming environments such as Visual Basic. But OMX components do perform the same essential function as other component technologies: they encapsulate complex functionality and allow the OmniMark programmer to deal simply and elegantly with complex systems such as FTP servers, databases, and TCP/IP connections.
In keeping with the streaming nature of the OmniMark language, many OMX components are capable of acting as sources and sinks. You can read from or write to the OMX just as you would to a file or buffer. This greatly simplifies many aspects of network programming.
OmniMark does not have any special language for addressing and manipulating OMX components. Instead, the methods and properties of OMX components are manipulated by functions in an external function library. This may be slightly unfamiliar if you are used to dealing with components using an object oriented syntax, but it is easy enough to see that the two expressions below are equivalent in intent, and that the syntactical difference is trivial.
With object oriented syntax style:
myTCP.TCPConnectionCloseWith OmniMark's process oriented syntax style:
In OmniMark code, OMX components are referenced just like conventional variables. The name of the OMX becomes the data type for the variable. Anywhere you can declare an OmniMark variable type, you can declare an OMX variable type. The following code declares two OMX variables, one for a TCPService OMX and one for a TCPConnection OMX:
local TCPService my-service local TCPConnection my-connection
In general, you can use an OMX variable just as you would any OmniMark variable. There is one difference, however. All variables are handles to objects of greater or lesser complexity. When you perform an action on a variable, the corresponding object is manipulated in the appropriate way. Usually you can ignore this subtlety (the general point of a high-level programming language is to avoid your having to worry about things like this). Some OMX components, however, serve as proxies for real objects in the external world, and there are limits on what OmniMark or an OMX component can do to those objects.
Consider an ordinary OmniMark variable of type integer, I can make a copy of that integer and have two separate integers:
process local integer a local integer b set a to 12 set b to a
Here I have two separate integers, "a" and "b", each containing the number 12. If I subsequently set "b" to 6, "a" will still be 12. But if I have an FTPConnection OMX variable and I make a copy of it, I obviously don't have two FTP servers. Perhaps less obviously, I also don't have two connections to the same FTP server:
process local FTPConnection c local FTPConnection d set c to FTPConnectionOpen server "ftp.omnimark.com" user "anonymous" password "email@example.com" set d to c
In this code, setting "c" to an open connection involved actually contacting the server and actually logging in. You can't create a new connection without communicating with the server with specific information. Setting d to c, therefore, does not give you two separate connections, d and c. What does it give you? Simply two handles to the same connection -- two OMX variables referring to the same OMX. If I close "d" as follows:
FTPConnectionClose dthen the connection represented by the variable "c" will also be closed because it is the same connection.
This can have an important impact on the operation of the OmniMark
save creates a temporary variable with the same name and value as a global variable. It has the lifespan of a local variable, but the visibility of a global variable. When the temporary variable goes out of scope, the global becomes visible again. Normally, the temporary copy created by a save is just that: a copy. You can change it without worrying about changing the value of the underlying global. But with a non-copyable OMX, doing a save just creates a temporary OMX variable that is a handle to the same OMX as the original. Since it has the same name as the global and references the same thing, the effect of using
save on a non-copyable OMX is, effectively, nothing. The exact same name refers to the exact same object before, during, and after the save.
This is not to say that all OMX components are non-copyable. It depends on the kind of object the component represents and how the component is implemented. For instance, the float OMX, which is used to represent floating point numbers, is copyable. So the following code would work just as in the case of an integer:
process local float a local float b set a to fp_v("12.3") set b to a
Consult the documentation for the OMX you are using to determine whether it is copyable or not.
Copyright © OmniMark Technologies Corporation, 1988-2000.