MN8 Tutorial
Concepts
      :: contents :: next

Back to > Overview > MN8 Tutorial

Concepts

Author: Remus Pereni <remus@nolimits.ro>
Table of Contents
1. Introduction
2. What is a concept ?
3. Attributes Definition
4. Elements Definition


1. Introduction

There is huge amount of information available out there on the net; unfortunately most of this information is only available for human consumption and not automated processing. Just imagine receiving an email, in order to find more about the author of the email you will have to copy paste the name of the author into an search engine, filter out his home page and read his bio information and maybe what other articles or mails he has published. The same is true for finding out information about a movie, news list, discussion group or the program guide of a TV channel.

There are some attempts to automate this process, custom wrappers are written in several programming languages to parse TV sites for their channel listing or personal sites in order to produce RSS news syndication feeds. While for syndication there are well-established formats to store and syndicate the information for other wrapped information there not so well established methods to do that.

The whole process could be broken down to 4 separate stages:

The MN8 scripting language was built with the sole purpose of making all this stages as easy as possible. In that sense it could be seen more as a tool or glue language than as a full blown programming or scripting language, MN8 will not be the fastest, neither will it build the nicest graphical user interfaces, as a matter of fact MN8 will not build GUI's at all. It will help you get information from sites, mailboxes, documents, databases or web services and transform, filter or enrich that information making it ready for consumption in various XML based formats as files, database fields or other web services.

What makes MN8 special? It's ability to work with semi-structured information. XML became the lingua franca of the Internet, there is no doubt about that, it is good enough to represent almost any kind of information and there are tools for working with it in almost every environment and programming language, it's the perfect candidate for information exchange and interoperability. While XML is good for machines it is a bit hard on humans, that's the reason MN8 was built to work with XML, but in a transparent way, human friendly. If your mental image of a person is correct, the person concept will output the proper XML, even more, the person concept will be able to load it's data instantly from any person XML. No more brackets editing, SAX or DOM parsers!

Being designed to work with semi-structured information, navigation, sorting, information extraction and manipulation is much simplified and comes naturally. Being built to work with the Net it has concepts for HTML, forms, cookies, mail, RSS handling and HTTP, FTP, POP3, SMTP, Jabber, BEEP, XML-RPC and SOAP protocol support. Being built on top of Java means that is portable and has huge amounts of libraries for wrapping easily even more functionality. And finally it's been built to be simple and easy to use, it is wanted to be the Basic of the Internet and information extraction.

top

2. What is a concept ?

Concepts are objects, since most of the time we will work with information, with mental representations of persons, news, TV guides, the notion of concept suits better than the one of object.

Being an object oriented scripting language all the power and functionality of an object oriented programming language is accessible: inheritance, composition, polymorphism, constructors and operator overloading, this if issued properly can help a lot in reusing code and customizing functionality.

But first let's have a look at a simple concept:

        
        # -------- Person.mn8 ---------
        	define Person label "PersonalPersonDefinition" [
        		@firstName
        		@lastName	typeof String label "lastName"
        		email label "Email.Address"
        		address [
        			street
        			city
        			state	
        			country [
        				@code
        				value typeof String
        			]
        		]
        		
        		: getMyPerson [
        			@firstName = "Remus"
        			@lastName = "Pereni"
        			/email = "remus@nolimits.ro"
        			/address/street = "Some street"
        			/address/city = "Satu Mare"
        			/address/state = "no state J"
        			/address/country@code = "RO"
        			/address/country/value = "Romania"
        		]
        		
        		static : main ( $args typeof Series ) [
        			$me typeof Person
        			$me.getMyPerson
        			print $me.toXML
        		]
        	]

The result of this little concept is:

        
        <personalPersonDefinition lastName="Pereni" firstName="Remus">
        <Email.Address>remus@nolimits.ro</Email.Address>
        <address>
        <street>Some street</street>
        <city>Satu Mare</city>
        <state>no state J</state>
        <country code="RO">
        Romania
        </country>
        </address>
        </PersonalPersonDefinition>

Every object-oriented language has variables and methods, MN8 has them too, what MN8 has in plus is elements and attributes, everything beginning with an @ is an attribute, with : is a method the rest are element definitions. Blocks and sub-elements are delimited by [].

So, let's analyze that piece of code. You'll notice that the Person concept is defined in an Person.mn8 file, that is a requirement, the name of the file should be the name of the main concept, case sensitive. Why of the main concept, can there be other kind of concepts? Yes, of course, a script file can hold one main concept and any number of sub-concepts will talk about them in another subchapter.

Another reason why is important to have the name of the file match the name of the concept because we can write quick script files with no concepts defined in them.

Small example:

        
        #---- SayHello.mn8 ----
        print "Hello this is my XML card"
        $me = Person.create
        $me.getMyPerson
        print $me.toXML              
        

In the above case the MN8 interpreter actually creates a dummy concept with all the code in an ad-hoc created main method.

Here it is how the synopsis of an MN8 concept looks:

        
        DEFINE ConceptName (EXTENDS concept(, concept)*)? (LABEL "label string")? [ eol 
        	({Attribute definitions} eol )*
        	({Element definitions} eol )*
        	({constructor declaration} eol )*
        	({operator declaration} eol )*
        	({methods declaration} eol )*
        ]
        

As you could seen in the first example the first is the DEFINE keyword followed by the concept name, then it comes the inheritance list. Specified with the optional keyword EXTENDS it allows the specification of a list of concepts name separated with coma, concepts whose attribute, elements and methods will be inherited by the newly defined concept.

Because it is possible to extend multiple concepts with the same attribute and element names also methods with the same signature the order of extension is important. The order of extension is from left to right, meaning that a method inherited from the left most concept will be overridden by a method with the same signature of the right most concept.

The last one is the label declaration, which again, like extends it is optional. Because it is possible to have many concepts that will emulate the same kind of information with the same representation it is important to allow the freedom of the serialization, concrete case we can have XPerson and YPerson concepts which both will produce the same person XML document.

In the synopsis you will see eol, which means, as you probably already guessed, end of line. While the case of the keywords or the number of white spaces (space, tab) between keywords it is not important the end of lines matters. MN8 uses the end of lines to determine the grammar of the language. The number of end of lines it is not important, the only thing that counts is that when you see in the tutorial or keyword reference eol, you have to have at least one, other ways the interpretation of you script will fail because of syntactic errors.

top

3. Attributes Definition

Just like a concept emulates a XML document or a piece of it, the MN8 attributes emulate an XML attribute.

The synopsis of an attribute definition is:

        
(STATIC)? @ attribute_name (!|?)? (= expression)? (TYPEOF concept_type)? (LABEL "attribute_label")? eol 
    

Let's start with the beginning. The optional STATIC keyword means that the defined attribute will be static, it does not need a concept instance, and it's value and properties will be propagated among all the existing instances.

Let's see an example:

        #---- Person.mn8 ---
        define Person [
        	static @version typeof String 
        	@firstName
        	@lastName
        ]        
        

As you can see the person concept has three attributes: firstName, lastName and version which is static. Now let's use that concept.

        
        #---- PersonTest.mn8 ----
        Person@version = "0.1"
        $me typeof Person
        $me@firstName = "Remus"
        $me@lastName = "Pereni"
        $friend typeof Person
        $friend@firstName = "Sorin"
        $friend@lastName = "Iluti"
        print $me.toXML, $friend.toXML
        

The result is:

        
        <Person version="0.1" lastName="Pereni" firstName="Remus"></Person>
        <Person version="0.1" lastName="Iluti" firstName="Sorin"></Person>                   
        

Now we can change any of the instances version number and we will see the new number propagating at every instance.

    
        $friend@version = "0.2"
        print $me.toXML
        print $friend.toXML
        
        The result is:
        
        <Person version="0.2" lastName="Pereni" firstName="Remus"></Person>
        <Person version="0.2" lastName="Iluti" firstName="Sorin"></Person>        
        
The same is true for elements.

Getting back to our synopsis we'll see that after the static comes the @ attribute signaler followed by the attribute name. After the attribute name comes the rendering visibility modifiers consisting of the optional !, hidden sign and ? hidden if empty sign.

The hidden sign following an attribute or element means that the attribute or element will be visible in your scripts just like any other attribute or element, but when serialized (it's content it's outputted to XML) it will be hidden. The hidden if empty sign (?) will behave exactly like the hidden sign (!) but only when the attribute or element has no value.

Let's see a quick example.

        
        #--- Person.mn8 ---
        define Person [
            @version! 
            @firstName?
            @lastName?
        ]
        
        #---- PersonTest.mn8 ----
        $me typeof Person
        $me@version = "1.0"
        $me@firstName = "Remus"
        print $me.toXML
        
The result is:
        
        <Person firstName="Remus"></Person>
        

As you can see because the version and lastName attributes remained empty, are not shown in the resulting XML.

After the visibility modifiers comes an initialization expression and a type declaration, both optional.

Initially all attributes contain a Nil value. This value can be modified either by specifying another type using the TYPEOF keyword or by assigning at creation a default value using the initialization expression.

Every concept type knows hot it should be serialized to XML and when a MN8 script based custom written concept it serialized to XML its result will be automatically composed from it's attribute and elements XML serialization. That means that if you define an attribute as a custom type and that type has an XML serialization as an XML element your end result will be compromised. The way a concept is serialized to XML can be controlled by overriding it's toXML method. Now let's see an example that will, hopefully, clarify all the issues discussed above.

        
        #---- CustomPersonalId.mn8 ----
            define CustomPersonalId [
        	@type typeof String
        		@nr typeof String
        
        		: create( $type typeof String, $id typeof String ) [
        			@type = $type
        			@nr = $id
        		]
        		: toXML [
        			return @type + @nr
        		] typeof String
        	]
        
        #---- Person.mn8 ----
        	define Person [
        		@firstName
        		@lastName
        		@personalId typeof CustomPersonalId
        		@timestamp = Date.getToday
        	]
        
        #--- PersonTest.mn8 ----
        	$me typeof Person
        	$me@firstName = "Remus"
        	$me@lastName = "Pereni"
        	$me@personalId = CustomPersonalId.create("SPYNR", "007")
        	print $me.toXML
        

By executing the PersonTest.mn8 script will see the next result (if everything goes all right :)

        
        <Person personalId="SPYNR007" lastName="Pereni" timestamp="Sun Oct 20 03:02:46 EEST 2002" firstName="Remus"></Person>
        

In the above example scripts you could see how the TYPEOF keyword was used to make the value of the attribute personalId of the CustomPersonalId type, also how you could assign default values to an attribute in the case of the timestamp attribute.

The first concept however looks a bit more interesting and that's because we made a constructor (all constructors are methods with the create name) and override the default toXML method to get the wanted XML serialization for the CustomPersonalId concept, will see about methods and costructors more in depth a bit latter.

If we would have not altered the default serialization of the concept by not implementing the toXML method the result wold have been:

        
        <person personalId="&lt;CustomPersonalId type=&quot;SPYNR&quot; nr=&quot;007&quot;&gt;&lt;/CustomPersonalId&gt;" lastName="Pereni" timestamp="Sun Oct 20 03:13:22 EEST 2002" firstName="Remus"></Person>         
        

As you could see for yourself if you remove the toXML method, and that is because the default XML serialization for the CustomPersonalId is:

        
        <CustomPersonalId type="SPYNR" nr="007"></CustomPersonalId>        
        
Which is off course escaped when used as an attribute value.

top

4. Elements Definition

An MN8 element emulates the XML element, every thing we said about attributes are true for elements. So, let's start with an element definition synopsis.

First form of element definition (simple element definition):

        
(STATIC)? ElementName (*)? (! | ?)? (= expression)? (TYPEOF conceptType)? (LABEL "element label")? eol
        
The second form of element definition (complex element definition):
    
        
(STATIC)? ElementName (*)? (! | ?)? (LABEL "element label")?  [ eol
	        (attribute definition)*
	        (simple or complex element definition)*
        ] eol
        

Why do we have two forms, because in the real life the elements are nested, and we need the flexibility to define simple and nested elements as easy as possible.

Let's start with a clear example of element definitions.

        
        #--- Person.mn8 ---
        define Person [
        	@firstName label "First.Name"
        	@lastName label "Last.Name"
        	fullAddress label "Full.Address"
        	
        	contact [
        		emails [
        			email* [
        				@type typeof String 
        				address typeof String
        			]
        		] 
        		homepage label "Home.Page"
        	]
        
        	static : main ( $args typeof Series ) [
        		$me typeof Person
        		$me@firstName = "Remus"
        		$me@lastName = "Pereni"
        		$me/fullAddress/ = "Some address, but why mine?"
        		$me/contact/homepage/ = "http://neuro.nolimits.ro"
        	
        		$me/contact/emails/email.createNewEntry
        		$me/contact/emails/email/1@type = "work"
        		$me/contact/emails/email/1//address/ = "remus@nolimits.ro"
        	
        		$me/contact/emails/email.createNewEntry
        		$me/contact/emails/email.lastEntry@type = "yahoo"
        		$me/contact/emails/email.lastEntry/address/ = "rpereni@yahoo.com"
        	
        		print $me.toXML
        	]
        ]
        
Executing this concept will result in:
        
        <Person Last.Name="Pereni" First.Name="Remus">
          <Full.Address>Some address, but why mine?</Full.Address>
          <contact>
            <emails>
              <email type="work">remus@nolimits.ro</email>
              <email type="yahoo">rpereni@yahoo.com</email>
            </emails>
            <Home.Page>http://neuro.nolimits.ro</Home.Page>
          </contact>
        </Person>        
        

As you could see most of the things we discussed at attributes are true for the elements too, let's discuss about the things which the elements has in plus. Getting back to the element synopsis at the simple form will notice only one thing that the attributes don't have, the optional star * after the element name.

When used immediately after the element name it signifies a multi element. A multi element is an element, which can have multiple consecutive copies of him with the same structure (attributes, sub-elements) but with possible different values. Just like in the above example the email element as one person, usually (in our field ;), have multiple email addresses.

Just like at attributes the TYPEOF keyword denotes the type of the value of the element, and the type determines how the XML serialization will finally look. This can be seen well also in the above example.

When we define a sub-element, like emails in contact, the value of the contact element will automatically become element and from here the <emails XML element, but when we define the address sub-element of email as String we will have the simple element value like XML serialization.

One difference between simple elements and multi elements (the ones with * after the element name) is that at concept instantiation (that's when the concept is first created by the MN8 interpreter, in the above example when the $me typeof Person was executed) while the simple or complex elements are automatically created with all it's simple sub-elements, the multi elements are not. This behavior can be seen if we print an XML representation of the above Person concept immediately after it's creation, just like in the example bellow:

        
        #---- Person.mn8 ----
        define Person [
            @firstName label "First.Name"
        	@lastName label "Last.Name"
        	fullAddress label "Full.Address"
        	
        	contact [
        		emails [
        			email* [
        				@type typeof String 
        				address typeof String
        			]
        		] 
        		homepage label "Home.Page"
        	]
        
        	static : main ( $args typeof Series ) [
        		$me typeof Person			
        		print $me.toXML
        	]
        ]
        
With the result:
        
        <Person Last.Name="" First.Name="">
          <Full.Address></Full.Address>
          <contact>
            <emails></emails>
            <Home.Page></Home.Page>
          </contact>
        </Person>
        
As you can see there is no instance from the multi elements, that's email in our case.

top


© 2001