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

Revision 151, 4.6 KB (checked in by samuraraujo, 5 years ago)
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    begin 
70                if _module.const_defined?(klassname.to_sym)
71      $activerdflog.debug "ObjectManager: construct_class: given class #{klassname} defined in the module"
72                        # if so, return the existing class
73                        _module.const_get(klassname.to_sym)
74                else
75      $activerdflog.debug "ObjectManager: construct_class: creating given class #{klassname}"
76                        # otherwise: create it, inside that module, as subclass of RDFS::Resource
77                        # (using toplevel Class.new to prevent RDFS::Class.new from being called)
78                        klass = _module.module_eval("#{klassname} = Object::Class.new(RDFS::Resource)")
79                        klass.class_uri = resource
80                        klass
81        end
82  rescue
83    puts "ActiveRDF could not create class with this name: #{klassname}"
84    end 
85        end
86
87        def self.prefix_to_module(prefix)
88                # TODO: remove illegal characters
89                prefix.to_s.upcase
90        end
91
92        def self.localname_to_class(localname)
93                # replace illegal characters inside the uri
94                # and capitalize the classname
95                replace_illegal_chars(localname).capitalize
96        end
97
98        def self.create_module_name(resource)
99                # TODO: write unit test to verify replacement of all illegal characters
100               
101                # extract non-local part (including delimiter)
102                uri = resource.uri
103                delimiter = uri.rindex(/#|\//)
104                nonlocal = uri[0..delimiter]
105
106                # remove illegal characters appearing at the end of the uri (e.g. trailing
107                # slash)
108                cleaned_non_local = nonlocal.gsub(/[^a-zA-Z0-9]+$/, '')
109
110                # replace illegal chars within the uri
111                replace_illegal_chars(cleaned_non_local).upcase
112        end
113
114        def self.replace_illegal_chars(name)
115                name.gsub(/[^a-zA-Z0-9]+/, '_')
116        end
117
118  #declare the class level methods as private with these directives
119  private_class_method :prefix_to_module
120  private_class_method :localname_to_class
121  private_class_method :create_module_name
122  private_class_method :replace_illegal_chars
123end
Note: See TracBrowser for help on using the browser.