Avanti Library Systems NOVA Version 0.1 alpha 17 August 2011 I. Introduction Avanti Nova is a general-purpose semantic mapping system. Although first conceived for use as new kind of library catalog, it can be used in any situation to dynamically map the relationships in a set of objects. Some of its core ideas were first used in Avanti MicroLCS, and these were later generalised and extended in Nova. Nova is firstly a data structure wth a scripting language interface to it. Programs are written in Nova to create and manage semantic maps. It also runs as a client-server system, and can be used from other environments like Unix shell scripts. And since it is written in Java, it naturally provides a Java API. The core idea in Nova is to represent a semantic map as a very large array. This allows for great flexibility in manipulating relationships in semantic maps. Version 0.1 is a prototype that focuses on establishing the core Nova scripting language and provides an interactive command line environment for running programs and exploring what it can do. It is something new and is built from the ground up. Version 0.1 is just a starting point for an idea. Much work remains to be done. A good way to introduce something new is to start with a tutorial introducing the basic concepts of the system and the Nova language using examples. In this tutorial we will be designing a very simple OPAC. II. Getting Started. Nova needs only Java to run. Please refer to your system's guide for installing a Java run time environment. A little about the directory structure and what things are. Some of these are to be fleshed out later: bin/ This contains startup shell scripts for Nova. nova.sh starts the single user standalone system. server.sh starts up Nova as a server. client.sh starts Nova as a client. db/ This directory contains database files for Nova databases. Every Nova database consists of two files: the arms and the tags files. The Arms file stores the semantic mappings. The tags are the objects those mappings refer to. default Don't delete this file! etc/ For scripts, configuration files and other things. lib/ This is where nova.jar lives. Basically the Java executable. manual/ This directory will contain a manual more in depth than this README file for using Nova. More to come in later versions. README.txt You are reading this. scripts/ Contains demo Nova scripts. You can put your own in here. The scripts that are included in version 0.1 are just a couple of very simple examples to show how a Nova program is structured and works. src/ This contains the Nova source code. III. Hello, World In the grand tradition let's start with "Hello, world." It shows how to start up the Nova command line interface and use it to print the message: Hello, world To enter the Nova command line from the Unix shell, get into the top level nova directory and type: bin/nova.sh When you see the command prompt READY> Nova is ready and waiting to accept commands. Then type: println "Hello, world" You will see READY> println "Hello, world" Hello, world READY> You can do this as many times as you wish, or replace "Hello, world" with any other message you like. To exit the Nova interface, type quit This will return you to the Unix shell. You can also write programs for Nova that run in batch mode. To do this, start up a text editor such as vi and type a single line: println "Hello, world" Save it as the file hello.scp To run hello.scp type this command from the Unix shell: java -cp ./lib/nova.jar avanti.nova.Nova -f hello.scp "Hello, world" will print in the Unix shell. Again, you can use this to print any message. You can write a Nova program to print a series of messages. println "me: Hello, world." println "world: The world is pleased to meet you." The println command is only one of many in the Nova language. To see what they are, go back into the interactive mode and type help READY> help Avanti Nova v0.1 alpha 20110817 Commands: $object_name = $object1 = $object2 %record($object).field %record($object).field = data $source --> $target ... $source x-> $target ... $source <-> $target ... $source ?-> $target ... del $object list $object listl $object browse $object count $object arms env help noop find print <["string"] [$object] [%record]> ... println <["string"] [$object] [%record]> ... quit save load reset READY> More on what some of these commands do later. IV. The Relation Matrix Data Structure The core idea behind Nova is to think of semantic relationships as being on a square n by n grid or an array, with one axis representing objects and the other axis representing the relationships those objects have with eachother. This is called a Relation Matrix. A very small relation matrix may look something like this: 1 . . . . . . . . . . . . . 1 . . 1 1 . . . . . . . . . 1 . . . 1 1 . . . . . . . . 1 . . . . 1 1 1 1 1 . . . . 1 . . . . . . . . . . . . . 1 . . . . . . . . . . . . . 1 . . . . . . . . . . . . . 1 . . . . . . . . . . . . . 1 . . . . . . . . . . . . . 1 . . . . . . . . . . . . . 1 . . . . . . . . . . . . . 1 . . . . . . . . . . . . . 1 Each column represents an object and each row represents the potential relationship an object has with all the other objects in the system. If object i has a relationship with object j we mark a 1 at that point in the grid. A 0 otherwise. We use a . instead of a 0 for readability. Setting a relationship establishes a link from one object to another. To make a link from object i to object j we express this as i --> j To remove the link we write i x-> j (The 'x->' indicates breaking a link.) Relationships are fundamentally one way. That means x(i,j) = 1 if object i has a relationship with object j. A relationship is called mutual if it goes both ways, where x(i,j) = 1 and x(j,i) = 1. To create a mutual link we write: i <-> j Objects In the relation matrix, objects are strings that either are the objects themselves or reference other things in the outside world, such as files, URLs, web sites, computers, whatever. This indirection works if we think of these objects as "tags" to things in the outside world and develop some sort of standard protocol for referencing them. A simple example would be storing standard URLs in the object strings of the relation matrix. V. Building a small opac. To introduce how Nova works, we will use it to build a tiny opac with only 32 objects in it. To do it interactively, we first fire up Nova and create a small relation matrix with 32 objects. reset 32 This is really tiny. An relation matrix for a real application may have a size of tens of millions of objects. We then create our first object, and call it "root" To do this type: $root = demo If all goes well Nova will return with the READY> prompt. Objects in Nova are sort of like variables. They are denoted with a "$" prefix. What "$root = demo" does is to create an object and store the string "demo" in it. If you want to see the contents of $root type $root at the prompt and it will return demo Next, we need an object to define the library for this opac $library = "Small Library" Note that strings containing white spaces are enclosed with quotes. Let's create two distinct collections in this library: $ac = "Adult Collection" $cc = "Children's Collection" Now lets define what an item is: items = , ItemID Title Author Subject Description This is different. Here we are not creating a label. Nova has built-in capability to look at an object as a record with fields. In this case an item has ItemID, Title, Author, Subject and Description fields. The first character ',' is the delimiter. This acts as a template when working with items. More on this later. Now let's make a generic definition of a location. A location is any entity that can store items or represent where an item is. Such as the the library shelf, a patron that has checked out an item, a new book in cataloging, etc. $locations = Locations A patron is an instance of a location. We're going to define a patron as we did an item, which a patron ID and name as fields: $patrons = , PatronID Name Now it's time to create the relationships these things have with eachother $root --> $library $library --> $ac $cc $items $locations $patrons $locations --> $patrons Now we get to define actual items with their data $i001 = i001,"Pure Ketchup: A history of Amercia's national condiment","Andrew F. Smith","ketchup condiments","paperback" $i002 = "i002","The Art of Computer programming","Donald E. Knuth","Computers programming","hardcover" $i003 = "i003","Salt: A world history","Mark Kurlansky","salt condiments history","hardcover" $i004 = "i004","Design of Library Automation Systems","Michael D. Cooper","library automation programming computers","hardcover" $i005 = "i005","Library Operations Research","Robert J. Daiute and Kenneth A. Gorman","library science research theory automation ","hardcover" $i006 = "i006","Father of Radio","Lee deForest","radio electronics audion invention","hardover. Signed by author" $i007 = "i007","The C Programming Language","Brian W. Kernighan and Dennis M. Ritchie","C programming computer science","isoftcover, second edition" $i008 = "i008","Walden","Henry David Thoreau","philosophy simple-living","small hardcover" $i009 = "i009","The Pragmatic Programmer","Andrew Hunt and David Thomas","programming computers","softcover" $i010 = "i010","Frank Lloyd Wright: An Autobiography","Frank Lloyd Wright","","" $i011 = "i011","Java in a Nutshell","David Flanagan","Java programming language computers","" $i012 = "i012","Emotional Design","Donald A. Norman","","hardcover" Now let's define a few patrons $p001 = "p001","Peter Schlumpf" $p002 = "p002","John Patron" $p003 = "p003","Jane Patron" Now let's create the links betwen all these things $items --> $i001 $i002 $i003 $i004 $i005 $items --> $i006 $i007 $i008 $i009 $i010 $i011 $i012 $patrons --> $p001 $p002 $p003 Note the two $items lines. We can link objects individually or at any time using arbitrary lists. With that done, let's see what the relation matrix looks like. Type arms: READY> arms 1 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1 1 1 1 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 . . . . 1 1 . . . . 1 . . . . . . . . . . . . . . . . . . . . . 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 . . 1 1 1 1 1 1 1 1 1 1 1 1 . . . . . . . . . . . . . . . . . . 1 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 . . . . . . . . . . . . . 1 1 1 . . . . . . . . . . . . . . . . 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1 1 1 1 1 1 READY> Note the diagonal of 1's from left to right. In Nova an object exists if it references itself. The very last object (bottom row) is the "free list" of unused objects. Objects that are deleted are returned to this list and re-used. Here is the program in its entirety, plus a little action at the end. // *************************************************************** // // demo.scp -- Implements a very tiny library system in a way // that one can see how the Nova system works. // // *************************************************************** reset 32 $root = demo $library = "Small Library" $ac = "Adult Collection" $cc = "Children's Collection" $items = , ItemID Title Author Subject Description $locations = Locations $patrons = , PatronID Name // // Now create the relationships between these things. // $root --> $library $library --> $ac $cc $items $locations $patrons $locations --> $patrons // //Define items // $i001 = "i001","Pure Ketchup: A history of Amercia's national condiment","Andrew F. Smith","ketchup condiments","paperback" $i002 = "i002","The Art of Computer programming","Donald E. Knuth","Computers programming","hardcover" $i003 = "i003","Salt: A world history","Mark Kurlansky","salt condiments history","hardcover" $i004 = "i004","Design of Library Automation Systems","Michael D. Cooper","library automation programming computers","hardcover" $i005 = "i005","Library Operations Research","Robert J. Daiute and Kenneth A. Gorman","library science research theory automation ","hardcover" $i006 = "i006","Father of Radio","Lee deForest","radio electronics audion invention","hardover. Signed by author" $i007 = "i007","The C Programming Language","Brian W. Kernighan and Dennis M. Ritchie","C programming computer science","isoftcover, second edition" $i008 = "i008","Walden","Henry David Thoreau","philosophy simple-living","small hardcover" $i009 = "i009","The Pragmatic Programmer","Andrew Hunt and David Thomas","programming computers","softcover" $i010 = "i010","Frank Lloyd Wright: An Autobiography","Frank Lloyd Wright","","" $i011 = "i011","Java in a Nutshell","David Flanagan","Java programming language computers","" $i012 = "i012","Emotional Design","Donald A. Norman","","hardcover" $ixxx = "ixxx",",","," // // define patrons // $p001 = "p001","Peter Schlumpf" $p002 = "p002","John Patron" $p003 = "p003","Jane Patron" $pxxx = "," // // Now we link items and patrons // $items --> $i001 $i002 $i003 $i004 $i005 $items --> $i006 $i007 $i008 $i009 $i010 $i011 $i012 $patrons --> $p001 $p002 $p003 // // Link some items to collections // $ac --> $i001 $i002 $i007 // ******************************************************* // // Now let's do stuff // arms $i002 println "Author= " #items($i002).Author println "Title= " #items($i002).Title // // Lets reinterpret how an item is used // Same as above, and we're looking at the same data // but we've defined a short version of the field labels // println "" println "Now we're looking at an item using the item2 template." $items2 = , i t a s d println "Author= " #items2($i002).a println "Title= " #items2($i002).t // // Checkout / checkin example // print "before checkout: " list $p001 list $i002 $p001 <-> $i002 print "after checkout: " list $p001 list $i002 arms $i011 save db/demo This program is in the scripts/ directory. To run it type: java -cp ./lib/nova.jar avanti.nova.Nova -f scripts/demo.scp A note on comments: Comment lines are prefixed either with "//" or with "#". Querying the Matrix: Find and Browse. Nova version 0.1 offers two basic commands for querying the relational matrix. The find command does a basic keyword matching on all the objects that the target object has relations with and returns all those that match one or more of the keywords in the find. So using our example, if we type: find $items condiment We get $i001 i001,"Pure Ketchup: A history of Amercia's national condiment","Andrew F. Smith","ketchup condiments","paperback" $i003 "i003","Salt: A world history","Mark Kurlansky","salt condiments history","hardcover" READY> The browse command returns the relationship structure from the point of view of a given object to a certain level. This level is like a degree of seperation. So if we type browse $root 2 we get $library $ac $cc $items $locations $patrons Browsing to a deeper level returns more: READY> browse $root 3 $library $ac $i001 $i002 $i007 $cc $items $i001 $i002 $i003 $i004 $i005 $i006 $i007 $i008 $i009 $i010 $i011 $i012 $locations $patrons $patrons $p001 $p002 $p003 READY> Both find and browse are in an early stage of development. Later versions of Nova will have far more advanced search capabilities. This is an example of creating a very simple opac in Nova. It shows the very basics of the Nova language. To create useful applications is a matter of scale. Appendix Nova Commands $object_name = Defines an object in the Arms. $object1 = $object2 Copies object2 to object 1. If object1 does not exist, it is created. #record($object).field Display the field data in $object as defined by #record. #record($object).field = data Set the field data in $object as defined by #record. $source --> $target ... Create a link from the source object to the target object. $source x-> $target ... Remove a link from the source object to the target object, if one exists. $object1 <-> $object2 ... Creates a mutual link between object1 and object2. $object1 ?-> $object2 Queries whether a relation link exists from object1 to object2. Returns 1 if true, 0 if false. arms Display the relation matrix graphically. browse $object Browse the relational structure from $object as a reference point to the specified browse level. del $object Delete an object from the relation matrix. env Prints the environment parameters. find $target Returns a list of objects that $target links to that contain keyword matches in the search string. help Prints out a list of Nova commands. list $object List all objects that $object has a relationship with. listl $object List all objects that $object has a relationship with and prints out the contents of those objects. load Load Nova with the relation matrix data in the specified database. This must include the relative path name if necesary: load db/demo noop No Operation. Does nothing. print <["string"] [$object] [#record]> ... Outputs a string or an object println <["string"] [$object] [#record]> ... Do the same with a carriage return. reset Clear all data and reset the system to the specified number of objects. save Save the state of the relation matrix to a database. This must include the relative path name if necessary: save db/demo ver Prints version information. Peter Schlumpf pschlumpf@gmail.com http://www.avantilibrarysystems.com 17 August 2011