Class: ActiveSesame::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/active_sesame/base.rb

Direct Known Subclasses

Study

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attributes_table = {}) ⇒ Base

Instance Methods ##########



195
196
197
198
# File 'lib/active_sesame/base.rb', line 195

def initialize(attributes_table={})
  @attribute_table = attributes_table
  @attribute_table.each {|key,value| self.send(key.to_s + "=", ActiveSesame::Support.uncode_whitespace(value)) }
end

Class Method Details

.inherited(subClass) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/active_sesame/base.rb', line 5

def Base.inherited(subClass)
  ############################################
  #######  Generic Attribute Handling ########
  ############################################

  #Create class variables that are independant of the super class
  class << self
    attr_accessor :rdf_class, :triple_store_id, :base_uri, :unique_property, :unique_property_type, :attributes, :attribute_method_names
    attr_accessor :connection
    attr_accessor :simple_attributes, :simple_method_names
    attr_accessor :complex_attributes, :complex_method_names
  end

  #Set the Default values for the inheritable class accessors
  subClass.rdf_class = subClass.name.split("::").last.to_s
  subClass.triple_store_id = "study-stash"
  subClass.set_base_uri "http://study-stash.radiology.umm.edu/ontologies/study-stash.owl#"
  subClass.unique_property = subClass.name
  subClass.unique_property_type = RDFConstants.class_to_match_hash[String]
  subClass.attributes = {}
  subClass.attribute_method_names = []
  subClass.simple_attributes = {}
  subClass.simple_method_names = []
  subClass.complex_attributes = {}
  subClass.complex_method_names = []
  subClass.connection = Repository.new

  #Create the attribute accessors for instances
  attr_accessor :attribute_table, :instance, :transaction_triples

  def subClass.base_uri_location
    uri_with_quacks = self.base_uri.split(" ").last
    uri_with_quacks.slice(1,uri_with_quacks.length-2)
  end

  def subClass.set_rdf_class(new_class_name)
    self.rdf_class = new_class_name.to_s
    self.set_attributes
  end

  def subClass.set_triple_store_id(new_id)
    self.triple_store_id = new_id.to_s
    self.set_attributes
  end

  def subClass.set_unique_property(new_property_name, type)
    self.unique_property = new_property_name.to_s
    self.unique_property_type = RDFConstants.class_to_match_hash[type]
  end

  def subClass.set_attributes
    #puts "SELECT ?property_name ?property_type WHERE { ?property_name rdfs:domain <#{rdf_class}>; rdfs:range ?property_type }"
    self.attributes = ResultParser.hash_values(self.connection.find_by_sparql("SELECT ?property_name ?property_type WHERE { ?property_name rdfs:domain <#{rdf_class}>; rdfs:range ?property_type }"))
    self.attributes.each do |uri,type|
      if RDFConstants.literals.include?(type) 
        self.simple_attributes[uri] = type
        self.simple_method_names << Support.uri_to_sym(uri)
      else
        self.complex_attributes[uri] = type
        self.complex_method_names << Support.uri_to_sym(uri).to_s.pluralize
      end
    end
    self.generate_methods
    self.attributes
  end
    
  def subClass.set_attribute_method_names
    self.attribute_method_names = self.attributes.keys.collect {|key| Support.uri_to_sym(key) }
  end

  ####################################
  ######## Validation Tools  #########
  ####################################

  def subClass.validate(instance)
    self.find(instance.instance) ? false : true
  end

  ###########################################
  ######## Dynamic Method Generation ########
  ###########################################

  #creates accessor methods and initiates other method Generators
  def subClass.generate_methods
    attr_accessor *(self.simple_method_names) unless self.simple_method_names.empty?
    self.generate_find_methods
    self.generate_complex_methods
  end

  #Generates methods for selecting all the uri (complex) properties associated with a specific instance
  def subClass.generate_complex_methods
    self.complex_attributes.each do |uri,type|
      method = Support.uri_to_sym(uri)
      define_method(method.to_s.pluralize) do
        if Kernel.const_get(Support.uri_to_sym(type))
          ResultParser.singular_values(self.class.find_by_sparql("SELECT ?object WHERE { <#{self.instance}> <#{uri}> ?object }")).collect {|foreign_uri| Kernel.const_get(Support.uri_to_sym(type)).find(foreign_uri) }
        else
          "No Class Defined for: #{Support.uri_to_sym(type)}"
        end
      end
      define_method("add_" + method.to_s.pluralize) do |instance_or_object|
        instance_or_object.class == String ? instance = instance_or_object : instance = instance_or_object.instance
        if Kernel.const_get(Support.uri_to_sym(type))
          self.class.group_save(ActiveSesame::TransactionBuilder.build_triple(self.instance, uri, instance))
        end
      end
      attr_accessor (method.to_s.pluralize + "_for_" + self.name.downcase).to_sym
    end
  end

  #Generates all the find_by_property methods for the inherited class
  def subClass.generate_find_methods
    self.simple_method_names.each do |m|
      self.class_eval(
        "def self.find_by_#{m} (value)
        #puts \"SELECT \#{self.attributes_to_sparql_vars} WHERE { ?instance <#{m}> '\#{value}'^^\#{ActiveSesame::RDFConstants.class_to_match_hash[value.class]} . \#{self.attributes_to_sparql_patterns}}\"
             self.new(ResultParser.tableize(self.connection.find_by_sparql(\"SELECT \#{self.attributes_to_sparql_vars} WHERE { ?instance <#{m}> '\#{value}' . \#{self.attributes_to_sparql_patterns}}\")).first)
             #puts self.connection.find_by_sparql(\"SELECT \#{self.attributes_to_sparql_vars} WHERE { ?instance <#{m}> '\#{value}'^^\#{ActiveSesame::RDFConstants.class_to_match_hash[value.class]} . \#{self.attributes_to_sparql_patterns}}\")
    end") #When you fix the datatype attributes in allegro graph you need to change this function or you'll get nils
    end
  end


  ######################################
  ######## SPARQL Query Helpers ########
  ######################################

  #Converts the simple method names list into a series of sparql patterns for the WHERE clause
  def subClass.attributes_to_sparql_patterns
    self.simple_method_names.inject("") {|outstring,item| outstring += "?instance <#{item}> ?#{item}. "}
  end

  #Converts the simple method names list into a string of SPARQL variables
  def subClass.attributes_to_sparql_vars
    "?instance ?" + self.simple_method_names.join(" ?")
  end


  ######################################
  ######### SPARQL Find Methods ########
  ######################################

  #Does a SPARQL select based on simple options and instantiates the Class Instances From the Returning XML
  def subClass.find(unique_uri_or_length, args={})
    if unique_uri_or_length.class != Symbol
      begin
        puts "SELECT #{self.attributes_to_sparql_vars.gsub("?instance","")} WHERE { #{self.attributes_to_sparql_patterns.gsub("?instance",'<' + unique_uri_or_length + '>')}}"
        graph_object = self.new(ResultParser.tableize(self.connection.find_by_sparql("SELECT #{self.attributes_to_sparql_vars.gsub("?instance","")} WHERE { #{self.attributes_to_sparql_patterns.gsub("?instance",'<' + unique_uri_or_length + '>')}}")).first)
        graph_object.instance = unique_uri_or_length
        return graph_object
      rescue
        return nil
      end
    elsif args.has_key?(:sparql) #Submit Pure Sparql without Object Creation (Returns Hash)
      (ResultParser.tableize(self.connection.find_by_sparql(:sparql)))
    elsif args.has_key?(:simple_conditional) #Returns objects that match the simple_condition, if specified, and apply the length operator via the send method
      (ResultParser.tableize(self.connection.find_by_sparql("SELECT #{self.attributes_to_sparql_vars} WHERE {?instance rdf:type <#{self.rdf_class}> . #{args[:simple_conditional]} OPTIONAL {#{self.attributes_to_sparql_patterns}} . }")).collect {|table| self.new(table)}).send(unique_uri_or_length)
    else
      (ResultParser.tableize(self.connection.find_by_sparql("SELECT #{self.attributes_to_sparql_vars} WHERE {?instance rdf:type <#{self.rdf_class}> . OPTIONAL {#{self.attributes_to_sparql_patterns}} . }")).collect {|table| self.new(table)}).send(unique_uri_or_length)
    end
  end

  def subClass.uniques(args={})
    uniques = []
    generals = self.find(:all, args)
    generals.each {|g| uniques << g unless uniques.find {|u| u.instance == g.instance}}
    uniques
  end

  #########################################
  ########## Class Admin Methods ##########
  #########################################


  #########################################
  ######## Class Initializer Calls ########
  #########################################
  subClass.set_attributes
  subClass.set_attribute_method_names
end

Instance Method Details

#add_transaction_triple(s, p, o) ⇒ Object



200
201
202
# File 'lib/active_sesame/base.rb', line 200

def add_transaction_triple(s,p,o)
  self.transaction_triples = self.transaction_triples + ActiveSesame::TransactionBuilder.build_triple(s,p,o)
end

#after_saveObject



224
225
226
227
228
229
230
231
232
# File 'lib/active_sesame/base.rb', line 224

def after_save
  self.class.complex_method_names.each do |method|
    values = self.send(method.to_s.pluralize + "_for_" + self.class.rdf_class.downcase)
    values.to_a
    if self.send(method.to_s.pluralize + "_for_" + self.class.rdf_class.downcase)
      values.each {|value| self.send("add_" + method.to_s.pluralize, value)}
    end
  end
end

#before_saveObject



221
222
# File 'lib/active_sesame/base.rb', line 221

def before_save
end

#build_triplesObject



217
218
219
# File 'lib/active_sesame/base.rb', line 217

def build_triples
  self.transaction_triples = ActiveSesame::TransactionBuilder.object_to_triples(self)
end

#saveObject



204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/active_sesame/base.rb', line 204

def save
  if self.class.validate(self)
    self.build_triples
    self.before_save
    self.class.group_save(self.transaction_triples)
    self.after_save
    return true
  else
    self.after_save
    return false
  end
end