Hoy en dÃa la norma para desarrollar la capa de persistencia de una aplicación web consiste en desarrollar un esquema para algún sistema de base de datos relacional en el que almacenar los datos.
Esto supone básicamente darle golpes a tus objetos hasta convertirlos en conjuntos de enteros, cadenas, etc que después se vuelven a encajar en tablas, indicando relaciones entre esas tablas duplicando valores en columnas especiales de esas tablas. Estamos tan acostumbrados a hacerlo de esta manera que ni nos damos cuenta de la gran distancia que media entre nuestro modelo objetual, con el que trabajamos en nuestro código, y el nivel de abstracción mucho más bajo con el que almacenamos una representación persistente de esos datos.
Sin embargo, esto no tendrÃa porque ser asÃ. Cuando creamos y modelamos nuestro dominio de datos para la aplicación, no hacemos más que crear una ontologÃa, una descripción de los recursos del dominio y sus relaciones, y en los últimos años se ha estandarizado un lenguaje para la descripción de ontologÃas por parte de la W3C: OWL.
OWL nace del mundo de la lógica descriptiva y permite describir las dos partes que componen una ontologÃa:
- Una TBox: o terminological box, donde describimos una terminologÃa, los tipos de recursos y relaciones, por ejemplo, existen cosas llamadas personas, existe una relación entre una cosa y un número llamada tener edad, etc...
- Una ABox: o assertional box, donde hacemos aserciones usando los términos de la TBox, por ejemplo: Juan es una persona, Juan tiene una edad de 15, etc...
A continuación mostraré una biblioteca para describir una TBox en Clojure lisp.
Nuestra primera tarea es tener un sitio donde almacenar la TBox, para ello debemos tener una conexión con un repositorio. Con el siguiente código creamos un repositorio en memoria y lo registramos con un nombre para usarlo posteriormente:
(register-repository! :test (init-memory-repository!))
A continuación podemos pasar a describir nuestra TBox para la ontologÃa que vamos a describir, la famosa aplicación para escribir blogs, para ello usamos las funciones (describe-owl-*):
(write-graph-in-repository (describe-tbox ;; algunas propiedades de datos (describe-owl-datatype-property :superblog "title" (xsd-string)) (describe-owl-datatype-property :superblog "content" (xsd-string)) (describe-owl-datatype-property :superblog "name" (xsd-string)) ;; algunas clases (describe-owl-class :superblog "Blog") (describe-owl-class :superblog "Post") (describe-owl-class :superblog "Author") ;; asignamos propiedades a clases (describe-owl-class-has-property :superblog "Blog" :superblog "title") (describe-owl-class-has-property :superblog "Post" :superblog "title") (describe-owl-class-has-property :superblog "Post" :superblog "content") (describe-owl-class-has-property :superblog "Author" :superblog "name") ;; algunas propiedades de objetos (describe-owl-object-property :superblog "contains") (describe-owl-object-property :superblog "writes") ;; relaciones entre clases (describe-owl-class-has-property :superblog "Blog" :superblog "contains") (describe-owl-property-range :superblog "contains" :superblog "Post") (describe-owl-class-has-property :superblog "Author" :superblog "writes") (describe-owl-property-range :superblog "writes" :superblog "Post")) ;; seleccionamos la conexion con el repositorio anteriormente registrado (connection! :test))
El código anterior es equivalente a escribir una migración en Ruby on Rails, pero el hecho de usar OWL en vez de directamente una base de datos relacional, nos aporta una serie de beneficios, por ejemplo, la reutilización del esfuerzo empleado en modelar el dominio. En el ejemplo anterior podemos darnos cuenta de que las relaciones como tÃtulo, ser autor de, etc, ya han sido modelados y estandarizados dentro del Dublin Core Metadata Initiative (http://en.wikipedia.org/wiki/Dublin_Core), ¿por qué no utilizar el soporte para el Dublin Core que incluye la biblioteca? La reutilización se basa en el concepto de kits de vocabularios, que incluyen clases y propiedades y funciones que trabajan sobre estas partÃculas OWL:
(use 'com.agh.webserver.framework.persistence.rdf.vocabularies.dc) ;; cargamos la descripción del Dublin Core en el repositorio de test (import-vocabulary-kit :dc (connection! :test)) ;; buscamos sinonimos entre nuestro dominio y el DC (write-graph-in-repository (describe-tbox (describe-owl-equivalent-properties :superblog "title" (dc-title)) (describe-owl-equivalent-properties :superblog "writes" (dc-creator))) (connection! :test))
La descripción de la TBox de la ontologÃa está en este momento almacenada en el repositorio, para poder usar la TBox de forma eficiente debemos iniciar la TBox al empezar a usar nuestra aplicación declarando que recursos de la ontologÃa almacenada en el repositorio queremos utilizar:
;; iniciamos la TBox (tbox-register-name! :owl-thing (owl-Thing) :test) (tbox-register-name! :superblog-Post "http://superblog.com/Post" :test) (tbox-register-name! :superblog-Blog "http://superblog.com/Blog" :test) (tbox-register-name! :superblog-Author "http://superblog.com/Author" :test) (tbox-register-name! :superblog-content "http://superblog.com/content" :test) (tbox-register-name! :superblog-title "http://superblog.com/title" :test) (tbox-register-name! :superblog-name "http://superblog.com/name" :test) (tbox-register-name! :superblog-post "http://superblog.com/contains" :test) (tbox-register-name! :superblog-post "http://superblog.com/writes" :test) ;; iniciamos el kit de Dublin Core con los nombre por defecto que asigna la :: biblioteca (tbox-register-vocabulary-dc :test) ;; el codigo de la aplicacion empezaria aqui
Ahora ya podrÃamos acceder a los recursos mediante su URI o mediante el nombre con el que se ha registrado. Un test que muestra la interacción entre las diferentes partes, además de la inferencia entre propiedades y subclases, podrÃa ser:
(deftest test-class-subclassing
(let [orig-tbox @*tbox*
orig-conn @*connections*
orig-repos @*repositories-registry*
repo (init-memory-repository!)
graph (describe-tbox
(describe-owl-datatype-property "http://test.com/prop_a" (xsd-float))
(describe-owl-datatype-property "http://test.com/prop_b" (xsd-float))
(describe-owl-class "http://test.com/class_a")
(describe-owl-class "http://test.com/class_b")
(describe-owl-class "http://test.com/class_c")
(describe-owl-subclass "http://test.com/class_a" "http://test.com/class_b")
(describe-owl-subclass "http://test.com/class_a" "http://test.com/class_c")
(describe-owl-class-has-property "http://test.com/class_a" "http://test.com/prop_a")
(describe-owl-class-has-property "http://test.com/class_b" "http://test.com/prop_b"))]
(do (tbox-clear!)
(register-repository! :test repo)
(write-graph-in-repository graph (connection! :test))
(tbox-register-name! :owl-thing (owl-Thing) :test)
(tbox-register-name! :class_a "http://test.com/class_a" :test)
(tbox-register-name! :class_b "http://test.com/class_b" :test)
(tbox-register-name! :class_c "http://test.com/class_c" :test)
(tbox-register-name! :prop_a "http://test.com/prop_a" :test)
(tbox-register-name! :prop_b "http://test.com/prop_b" :test)
(let [class-recovered (tbox-find-class-by-uri! "http://test.com/class_a")]
(do
(is (= class-recovered
{:name :class_a
:uri "http://test.com/class_a"
:subclass-of [{:name :class_a
:uri {:prefix "", :value "http://www.w3.org/2002/07/owl#Thing"}
:subclass-of []
:datatype-properties #{}
:object-properties #{}
:repository-name :test}
{:name :class_b
:uri {:prefix "", :value "http://test.com/class_b"}
:subclass-of [{:name :owl-Thing
:uri {:prefix "", :value "http://www.w3.org/2002/07/owl#Thing"}
:subclass-of []
:datatype-properties #{}
:object-properties #{}
:repository-name :test}]
:datatype-properties #{{:name nil
:uri
{:prefix "", :value "http://test.com/prop_b"}
:range {:prefix "", :value "http://www.w3.org/2001/XMLSchema#float"}
:equivalent-properties #{}
:repository-name :test}}
:object-properties #{}
:repository-name :test}
{:name :class_c
:uri {:prefix "", :value "http://test.com/class_c"}
:subclass-of [{:name :owl-Thing
:uri {:prefix "", :value "http://www.w3.org/2002/07/owl#Thing"}
:subclass-of []
:datatype-properties #{}
:object-properties #{}
:repository-name :test}]
:datatype-properties #{}
:object-properties #{}
:repository-name :test}]
:datatype-properties #{{:name :prop_b
:uri {:prefix "", :value "http://test.com/prop_b"}
:range {:prefix "", :value "http://www.w3.org/2001/XMLSchema#float"}
:equivalent-properties #{}
:repository-name :test}
{:name :prop_a
:uri
{:prefix "", :value "http://test.com/prop_a"}
:range {:prefix "", :value "http://www.w3.org/2001/XMLSchema#float"}
:equivalent-properties #{}
:repository-name :test}}
:object-properties #{}
:repository-name :test}
(tbox-restore! orig-tbox)
(repositories-register-restore! orig-repos)
(connections-restore! orig-conn))))))
Al igual que OWL se situa sobre una pila de protocolos de la W3C para la web semántica, en concreto, una ontologÃa OWL se codifica como un grafo RDF que a su vez se puede describir como un documento XML, la biblioteca OWL usa la bibliteca RDF que comenté anteriormente para describir los recursos en términos de constructores de un grafo RDF y recupera su información transformando ese grafo en consultas SPARQL.
En siguientes posts, veremos como usar esta TBox para hacer aserciones sobre objetos concretos dentro de la ABox.
Aunque todavÃa se encuentra muy lejos de ser usable para nada, si queréis hacer pruebas y juguetear con él, el código se encuentra disponible en mi repositorio de Github.

through shanghai escortfax or email.A student of music needs as shanghai escort long and as arduous a escort shanghai training to become a performer as a medical student needs to become a doctor.
come !come my dear friends .come here buy fake rolex .cheap fake rolex at here .heave the replica rolex
Wearing Vibram Five Fingers shoes at walking in the rain, experience a unique experience. If you like it, we have barefoot running shoes and Five Fingers Shoes for you to choose.