root/activerdf-1.6.10/lib/active_rdf/objectmanager/object_manager.rb @ 25

Revision 25, 4.5 KB (checked in by samuraraujo, 5 years ago)

Initial import.

Line 
1require 'active_rdf'
2
3# Constructs Ruby classes for RDFS classes (in the right namespace)
4
5class ObjectManager
6        # Constructs empty Ruby classes for all RDF types found in the data. Allows
7        # users to invoke methods on classes (e.g. FOAF::Person) without
8        # getting symbol undefined errors (because e.g. foaf:person wasnt encountered
9  # before so no class was created for it)
10  def self.construct_classes
11    # find all rdf:types and construct class for each of them
12    #q = Query.new.select(:t).where(:s,Namespace.lookup(:rdf,:type),:t)
13               
14                # find everything defined as rdfs:class or owl:class
15                type = Namespace.lookup(:rdf,:type)
16                rdfsklass = Namespace.lookup(:rdfs,:Class)
17
18                # TODO: we should not do this, we should not support OWL
19                # instead, owl:Class is defined as subclass-of rdfs:Class, so if the
20                # reasoner has access to owl definition it should work out fine.
21                owlklass = Namespace.lookup(:owl,:Class)
22
23                klasses = []
24    klasses << Query.new.distinct(:s).where(:s,type,rdfsklass).execute
25    klasses << Query.new.distinct(:s).where(:s,type,owlklass).execute
26
27                # flattening to get rid of nested arrays
28                # compacting array to get rid of nil (if one of these queries returned nil)
29                klasses = klasses.flatten.compact
30                $activerdflog.debug "ObjectManager: construct_classes: classes found: #{klasses}"
31               
32                # then we construct a Ruby class for each found rdfs:class
33                # and return the set of all constructed classes
34    klasses.collect { |t| construct_class(t) }
35  end
36
37  # constructs Ruby class for the given resource (and puts it into the module as
38  # defined by the registered namespace abbreviations)
39  def self.construct_class(resource)
40    # get prefix abbreviation and localname from type
41    # e.g. :foaf and Person
42    localname = Namespace.localname(resource)
43    prefix = Namespace.prefix(resource)
44
45    # find (ruby-acceptable) names for the module and class
46    # e.g. FOAF and Person
47    if prefix.nil?
48                        # if the prefix is unknown, we create our own from the full URI
49      modulename = create_module_name(resource)
50      $activerdflog.debug "ObjectManager: construct_class: constructing modulename #{modulename} from URI #{resource}"
51                else
52                        # otherwise we convert the registered prefix into a module name
53                        modulename = prefix_to_module(prefix)
54                        $activerdflog.debug "ObjectManager: construct_class: constructing modulename #{modulename} from registered prefix #{prefix}"
55    end
56    klassname = localname_to_class(localname)
57
58    # look whether module defined
59    # else: create it
60    _module = if Object.const_defined?(modulename.to_sym)
61        $activerdflog.debug "ObjectManager: construct_class: module name #{modulename} previously defined"
62                                Object.const_get(modulename.to_sym)
63                        else
64        $activerdflog.debug "ObjectManager: construct_class: defining module name #{modulename} now"
65                                Object.const_set(modulename, Module.new)
66                        end
67
68                # look whether class defined in that module
69                if _module.const_defined?(klassname.to_sym)
70      $activerdflog.debug "ObjectManager: construct_class: given class #{klassname} defined in the module"
71                        # if so, return the existing class
72                        _module.const_get(klassname.to_sym)
73                else
74      $activerdflog.debug "ObjectManager: construct_class: creating given class #{klassname}"
75                        # otherwise: create it, inside that module, as subclass of RDFS::Resource
76                        # (using toplevel Class.new to prevent RDFS::Class.new from being called)
77                        klass = _module.module_eval("#{klassname} = Object::Class.new(RDFS::Resource)")
78                        klass.class_uri = resource
79                        klass
80                end
81        end
82
83        def self.prefix_to_module(prefix)
84                # TODO: remove illegal characters
85                prefix.to_s.upcase
86        end
87
88        def self.localname_to_class(localname)
89                # replace illegal characters inside the uri
90                # and capitalize the classname
91                replace_illegal_chars(localname).capitalize
92        end
93
94        def self.create_module_name(resource)
95                # TODO: write unit test to verify replacement of all illegal characters
96               
97                # extract non-local part (including delimiter)
98                uri = resource.uri
99                delimiter = uri.rindex(/#|\//)
100                nonlocal = uri[0..delimiter]
101
102                # remove illegal characters appearing at the end of the uri (e.g. trailing
103                # slash)
104                cleaned_non_local = nonlocal.gsub(/[^a-zA-Z0-9]+$/, '')
105
106                # replace illegal chars within the uri
107                replace_illegal_chars(cleaned_non_local).upcase
108        end
109
110        def self.replace_illegal_chars(name)
111                name.gsub(/[^a-zA-Z0-9]+/, '_')
112        end
113
114  #declare the class level methods as private with these directives
115  private_class_method :prefix_to_module
116  private_class_method :localname_to_class
117  private_class_method :create_module_name
118  private_class_method :replace_illegal_chars
119end
Note: See TracBrowser for help on using the browser.