About triples
Sebastian Wiemer <[email protected]> Fri, 26 Dec 2003 22:11:20 +0100
| Newsgroups | gmane.comp.web.zope.plone.collective.ticle |
|---|---|
| Message-ID | <[email protected]> |
--Boundary-00=_4PK7/TPkfldS9nV Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline Hi ticlers, [N.B.: If attached a - hopefully - recent version of this as open office document.] About triples How it all started Project requirements When using plone we figured out a lack of features we badly needed in one of our projects. The project required a large number of documents to be linked together. The links had to have a type and required referential integrity, neither being feasible using standard plone features. So we decided to program a link manager to fullfill our needs. The link manager would care to prevent us from deleting objects which are still linked (that is ensuring referential integrity) and would provide links which could freely be typed and configured by a "constraint manager". The constraint manager simply checked the type of the objects that were to be linked and provided a simple interface for configuring new constraints. If a constraint is violated the constraint manager will not allow the creation (or deletion) of a link. So the constraint manager had only two basic methods: canAdd(link) and canDelete(link) both returning a boolean indicating wether a link can be added or deleted. Here is a sample for a link constraint: (person_type, isAuthorOf, content_type) This example shows how the link type "isAuthorOf" can be configured by the constraint manager. We define the link type "isAuthorOf" as a type that links to objects who have to have the type person_type for the first object and content_type for the second object. As a consequence the constraint manager will not allow an "isAuthorOf" link to be used with an Object that of content_type as first and an other Object of person_type unless you provide a second specification which does: (content_type, isAuthorOf, person_type) This constraint shows the following important things: 1.The constraint manager can put more than one constraint on one link type. 2.The constraint manager will not prevent you from designing semantically malicious constrains. In other words: the constraint manager does not check semantics but syntax. The constraint above is fullfilled if : The type is "isAuthorOf" The type of the first object is "content_type" The type of the second object is "person_type" With this combination of link and constraint manager we were able to meet the project requirements. The implementation was done with the project and specific performance considerations in mind so that the resulting "product" is full of customer specific code leading to a lot of limitations of the idea of using triples. In this paper I like to give an idea what else might be achieved using triples. We renamed the project to "ticle" (though I hope we might find a new name since ticle pronounces like "Tcl" of "Tcl/Tk"). TICLE and triples To give back something to the community we decided to make the link and constraint manager open source - but this time with all it's powerful features unleashed - and a new name: ticle. Since ticle is not yet ready to be described, because it is doomed to undergo many changes, I like to tell something about the underlying concepts ticle relys on: triples. A triple (that is a tuple of exactly three items) is capable of modelling a lot of things; I will try to show what and how virtually everything can be expressed using triples. (HINT: You might have wondered where the links have gone. We still talk about links here. A triple can (and will) be intepreted as a link. Thus a link is a triple. link = (source_of_link, type_of_link, target_of_link) And a triple is a link and a relation between objects - all the same - just in case you might have wondered.) Obviously it is possible to model a typed relation between to two objects with a triple. (A, relatesTo, B) So we have A relating to B in a "relatesTo" fashion. As we already have learned this relation is directed. If A relates to B that will not ensue B relating to A. Expressing other kind of relations between A and B will result in using a different type: (A, relatesInSomeOtherFashionTo, B) So far we have not said anything about the nature of the items in the triple. Please consider the items in the triple as something we can refer to by a unique name. We do not need to go into any further detail to understand the concept of using triples. If we supply every triple with a unique name (or ID if you like), then links migth also be objects in a triple. Thus unleashing the full potential of ticle: label_1: (A, relatesTo, B) label_2: (B, relatesTo, A) label_3: (label_1, isReversed, label_2) In a nested notation we would write: ((A,relatesTo,B), isReversed,(B, relatesTo, A)) The nested notation and the notation using IDs are equal in meaning. Though "relatesTo", "isReversed" or "isAuthorOf" are human understandable link types or in other words: they carry natural language semantics, they are pure syntax to ticle. Ticle will not care about linking anything stupid unless constraints are defined which prevent us from doing so. We will see later how such constraints can be modeled. First I like to show some sample applications which could be done with ticle. Case study - Linking A very simple and yet powerful application of ticle is linking objects together. Consider the following setup: you have 1500 people all working on (potentially) many different documents. All in all let's assume we have got 12.000 documents. The people relate in different manners to the documents. A person might be the author of one document and the translator of another document - or both of the same document. Persons and documents must be objects to ticle in other words: they must in some way be referable to - like by a unique ID (=uid). Given this prerequisits we can start using ticle to link documents and persons. some_id : (dave, authorOf, document1234) other_id: (naomi, translatorOf, document1234) In this application we usually will not be refering to triples (i.e. "some_id" and "other_id"), that is why I used meaningless names. "dave" is a uid, "authorOf" is a uid and "document1234" is a uid, too. In a real world application "dave" will point to a user-object (containing metadata about dave), "authorOf" is just a name to distinguish the different types of relations in which people can be to documents and "document1234" would be the id of a document. When we used "what is now called ticle", we used a tab on plone document object showing all linked people listed by linktypes. Thus giving an overview about the people involved in the creation process. Case study - Workflow Let us consider a simple editorial workflow: There is an author actually producing content, a designer making the content visually attractive and an editor deciding if the content and design is matching the desired quality and keeping an eye on deadlines. This workflow might be analysed in many other ways and I am well aware of it. Please regard the analysis as arbitrary but given - for the sake of explanation. The workflow covers the following aspects: persons performing actions with documents, pictures being inserted into documents and deadlines controlling the progress of production. Ticle has no implicit or inherent semantics. Not even for types, classes, objects, properties or whatever. To model such things as types and properties we have to make them ourselves. This is fairly easy. We add an object named "Type" and an object name "hasProperty". We use these objects so that anything that refers to "Type" by "hasProperty" i.e. all triples: (...,hasProperty,Type) is considered a type. Please do not forget that the name "Type" and "hasProperty" are arbitrary. They do not carry any meaning. The meaning emerges solemnly from how we use these objects. To tell link types (or predicates) and objects from another we use camelcaps with a lowercase starting letter for predicates and uppercase camelcaps names for objects. Since we have identified the things we want to model in the workflow (see above words in bold) as types of things we want to model, we can now tell them to be types of objects. [N.B.: We do not need to type objects. I just wanted to show you can, with the side effect of clarity.] id_0 = link(Type, hasProperty, Type) id_1 = link(Author, hasProperty, Type) id_13 = link(Designer,hasProperty, Type) id_12 = link(Editor, hasProperty, Type) id_2 = link(Document,hasProperty, Type) id_3 = link(Deadline,hasProperty, Type) id_4 = link(Picture, hasProperty, Type) id_5 = link(Action, hasProperty, Type) But of course not everything in our workflow model will be of type Type. To indicate something being an instance of a type we create the predicate: isInstanceOf. id_6 = link(Report, isInstanceOf, Document) id_7 = link(2003_10_10,isInstanceOf, Deadline) id_20 = link(2003_10_12,isInstanceOf, Deadline) id_21 = link(2003_10_15,isInstanceOf, Deadline) id_8 = link(Castle, isInstanceOf, Picture) id_9 = link(writes, isInstanceOf, Action) id_10 = link(publishes,isInstanceOf, Action) id_11 = link(addsPicture,isInstanceOf,Action) In our workflow we have some persons performing different jobs. So we tell them to have some "job": id_15 = link(Icheb, isInstanceOf, Designer) id_16 = link(Harry, isInstanceOf, Author) id_14 = link(Naomi, isInstanceOf, Editor) At this points it starts getting interesting again! Now we can model a the time constraint: "until" and the "into" relation (which we do not make a type here), which both use links instead of objects. id_18 = link(until, hasProperty, TimeConstraint) id_17 = link(Harry, writes, Report) id_24 = link(Castle, into, Report) id_22 = link(Naomi, addsPicture, id_24) id_23 = link(Icheb, publishes, Report) id_19 = link(id_17, until, 2003_10_10) id_25 = link(id_22, until, 2003_10_12) id_26 = link(id_23, until, 2003_10_15) So what does this thing mean? Harry has to write (= finish) his report until the deadline 2003_10_10, Naomi has to add a specific picture to the report until 2003_10_12 and Icheb has to publish the report until 2003_10_15. But why all these types in the beginning? An application does not necessarily understand words like "writes" and it would not be very configurable to program every possible action directly into the workflow engine. By adding the types the workflow engine can query for all possible actions, authors, deadlines and so on. If a new workflow is build up for a document then the engine could 1.show all possible actions 2.show all available authors, editors, ... 3.show all available deadlines By adding constraints the available items can be reduced to a minimum. Constraints Why constraints? In the case studies we have seen many different "linktypes" (= predicated,=the second item in a triple). Obviously it is not possible to pick predicates out of the blue. Predicates have a meaning evolving from their interpretation and usually apply only to a restricted number of subject and objects. The "authorOf" predicate for example will possibly want to link people to documents and not birds to cars. So if we want to create a predicate, that makes only sense with a particular set of objects and subject, we need two constrain these sets. The currently persued method is to create a "constraint", which is simply a set of three filters - one for each triple item. The constraint may also be attached to a Filters The concept of filters is crucial for constraints. Constraints check if a triple appears in a list of triples returned by a filter. (Or - which is likely to be more performant: return true when the first matching triple is found.) So a filter is "positive" it does not specify what to reject, but what to accept. A filter itself is a triple used to compare with the triple(s) in question. In other words: everything that is equal to the filter triple passes - the rest is rejected. [N.B.: In the previous version, the LinkManager, triples were unique. Are they still? If yes, we get only one answer, if not, we might get more than one...!] Obviously we do need something like a wildcard here, since otherwise we would need exactly as many filters as we have triples to match. So the filter triples may contain the item "any" which matches any triple item: all_triples: (any, any, any) dave_triples: (dave, any, any) writing_triples:(any, write, any) single_filter: (id123, id432, id234) The all_triples filter will match all triples. Whereas the "dave" filter will match all triples containing the uid "dave" as subject. Note that the uid must be the same, not the referenced value. The "writing_triples" will match all Besides the "any" filter, that matches anything, we will also need an atom functioning as placeholder. That placeholder could be used like a parameter. some_uid: (hans, writes, document) person_filter: (placeholder, isA, Person) So the person_filter applied on "hans" will return true if there is a triple "(hans, isA, Person)" Well, I know this has to be worked out a lot. I really do appreciate any help and any comment on this is welcome. Sebastian --Boundary-00=_4PK7/TPkfldS9nV Content-Type: application/x-zip; name="essay.sxw" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="essay.sxw" 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 LSM04bjQJfas+4FEW2s/jqiCDDZJEliBPdOWOCiQkHBIdMtnWcQDB5jWWJNUfVmdRpOZmbwVrOp2 fDqbPBtZljVMoKgxOKGoRHUgGYfOjsidw2+gi+sNm2N16jxSp0MvjebxvamzJruAlE2zGnWytV+9 aoDApTVn2IgmUXzeOrHvnMECw8o1XmHiKHZgUAYRcEJQ+nclpImwibsZ57AvbRjaG0j9YP9DpP/5 7g8IZmQFdzflU/0Iu6vrDIY7WdJm2G5K1QID7CVaPagsjT7YdlwFbSp2ErtnPXT/7cflP1BLBwgP zgNspwYAAKAiAABQSwMEFAAAAAAAKFSaL2OENjxuBAAAbgQAAAgAAABtZXRhLnhtbDw/eG1sIHZl cnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04Ij8+CjwhRE9DVFlQRSBvZmZpY2U6ZG9jdW1lbnQt bWV0YSBQVUJMSUMgIi0vL09wZW5PZmZpY2Uub3JnLy9EVEQgT2ZmaWNlRG9jdW1lbnQgMS4wLy9F TiIgIm9mZmljZS5kdGQiPjxvZmZpY2U6ZG9jdW1lbnQtbWV0YSB4bWxuczpvZmZpY2U9Imh0dHA6 Ly9vcGVub2ZmaWNlLm9yZy8yMDAwL29mZmljZSIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMu b3JnLzE5OTkveGxpbmsiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4x LyIgeG1sbnM6bWV0YT0iaHR0cDovL29wZW5vZmZpY2Uub3JnLzIwMDAvbWV0YSIgb2ZmaWNlOnZl cnNpb249IjEuMCI+PG9mZmljZTptZXRhPjxtZXRhOmdlbmVyYXRvcj5PcGVuT2ZmaWNlLm9yZyAx LjEuMCAoTGludXgpPC9tZXRhOmdlbmVyYXRvcj48IS0tNjQ1KEJ1aWxkOjg2ODcpLS0+PG1ldGE6 aW5pdGlhbC1jcmVhdG9yPlNlYmFzdGlhbiBXaWVtZXI8L21ldGE6aW5pdGlhbC1jcmVhdG9yPjxt ZXRhOmNyZWF0aW9uLWRhdGU+MjAwMy0xMC0xNlQxMDo1ODozNTwvbWV0YTpjcmVhdGlvbi1kYXRl PjxkYzpkYXRlPjIwMDMtMTItMjZUMTE6MzM6MTc8L2RjOmRhdGU+PGRjOmxhbmd1YWdlPmVuLUdC PC9kYzpsYW5ndWFnZT48bWV0YTplZGl0aW5nLWN5Y2xlcz4zODwvbWV0YTplZGl0aW5nLWN5Y2xl cz48bWV0YTplZGl0aW5nLWR1cmF0aW9uPlAyRFQxMkgwTTI3UzwvbWV0YTplZGl0aW5nLWR1cmF0 aW9uPjxtZXRhOnVzZXItZGVmaW5lZCBtZXRhOm5hbWU9IkluZm8gMSIvPjxtZXRhOnVzZXItZGVm aW5lZCBtZXRhOm5hbWU9IkluZm8gMiIvPjxtZXRhOnVzZXItZGVmaW5lZCBtZXRhOm5hbWU9Iklu Zm8gMyIvPjxtZXRhOnVzZXItZGVmaW5lZCBtZXRhOm5hbWU9IkluZm8gNCIvPjxtZXRhOmRvY3Vt ZW50LXN0YXRpc3RpYyBtZXRhOnRhYmxlLWNvdW50PSIwIiBtZXRhOmltYWdlLWNvdW50PSIwIiBt ZXRhOm9iamVjdC1jb3VudD0iMCIgbWV0YTpwYWdlLWNvdW50PSI1IiBtZXRhOnBhcmFncmFwaC1j b3VudD0iODMiIG1ldGE6d29yZC1jb3VudD0iMjExNCIgbWV0YTpjaGFyYWN0ZXItY291bnQ9IjEy MzU4Ii8+PC9vZmZpY2U6bWV0YT48L29mZmljZTpkb2N1bWVudC1tZXRhPlBLAwQUAAgACAAoVJov AAAAAAAAAAAAAAAADAAAAHNldHRpbmdzLnhtbM1ZbXOiSBD+fr/C4+tVApKXjVuJWwMK4ibGdyLf Rpgg6zDDwSCSX38Nam430buchqqzShG75+menn7F22/rkNZWJE4Czu6k+rki1QhzuRcw/06ajI2z G+lb87fb31uP+njWb9f483Pgkq8ed9OQMHGWECGAN6n1J9q9pdekM1l+jAh7LPnOeezLcmvcqm3u W9tlNRAky+2eVJM2gOee8KTm7UF00JIlXzfkO2khRPRVljnI4X/LURVFkTf30nbBmgZs+cqfZdl5 dlHy1huNhlxSd6wuZ8+B/w/YdXnDIu1s8IvVXnXfqdy83bBvgc8CQcJiP7XtzwyHsJNVQLLXXUr7 1vzKPwV+FBM85pG0o4g8AkrAhNSsq19uri9u5fcwH4e+J89iH/blzWm4duCJxT5gVb26qp+G3SGB v9irdV29uDpS8dGCZ0PigZMQfYGZT5I3AuacU4KZ1BRxSo6X0SHYI7G9CCjRYp4l4AqHBD1jmpwg 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 BQYAAAAABwAHAJQBAADzLAAAAAA= --Boundary-00=_4PK7/TPkfldS9nV-- ------------------------------------------------------- This SF.net email is sponsored by: IBM Linux Tutorials. Become an expert in LINUX or just sharpen your skills. Sign up for IBM's Free Linux Tutorials. Learn everything from the bash shell to sys admin. Click now! http://ads.osdn.com/?ad_id=1278&alloc_id=3371&op=click