Class: Dbd::Fact
- Inherits:
-
Object
- Object
- Dbd::Fact
- Defined in:
- lib/dbd/fact.rb,
lib/dbd/fact/id.rb,
lib/dbd/fact/subject.rb,
lib/dbd/fact/collection.rb
Overview
Basic Fact of knowledge.
The database is built as an ordered sequence of facts, a "fact stream".
This is somewhat similar to a "triple" in the RDF (Resource Description Framework) concept, but with different and extended functionality.
Each basic fact has:
-
a unique and invariant id (a uuid)
To allow referencing back to it (e.g. to invalidate it later in a fact stream).
-
a time_stamp (time with nanosecond granularity)
To allow verifying that the order in a fact stream is correct.
A time_stamp does not need to represent the exact time of the creation of the fact, but it has to increase in strictly monotic order in a fact stream.
-
a provenance_subject (a uuid)
The subject of the ProvenanceResource (a set of ProvenanceFacts with the same subject) about this fact. Each Fact, points back to a ProvenanceResource (the ProvenanceResource must have been fully defined, earlier in a fact stream).
-
a subject (a uuid)
"About which Resource is this fact?".
Similar to the subject of an RDF triple, except that this subject is not a URI, but an abstract uuid (that is world-wide unique and invariant).
Links to "real-world" URI's and URL's can be added later as separate facts (this also allows linking multiple "real-world" URI's to a single Resource).
-
a predicate (a string)
"Which property of the resource are we describing?".
Currently this is a string, but I suggest modeling this similar to predicate in RDF. Probably more detailed modeling using RDF predicate will follow.
-
an object (a string)
"What is the value of the property of the resource we are describing?".
Currently this is a string, but I suggest modeling this similar to object in RDF. Probably more detailed modeling using RDF object will follow.
Direct Known Subclasses
Defined Under Namespace
Modules: Collection, ID, Subject
Class Method Summary collapse
-
.attributes ⇒ Array
The 6 attributes of a Fact.
- .fact_from_hash(hash) ⇒ Object
-
.from_string_values(string_values) ⇒ Fact, ProvenanceFact
Constructs a Fact or ProvenanceFact from a string values array (e.g. pulled from a CSV row).
-
.hash_from_values(values) ⇒ Object
FIXME This has to move to a Fact::Factory.
-
.new_id ⇒ String
A new id string.
-
.new_subject ⇒ String
A new subject string.
- .values_hash(string_hash) ⇒ Object
Instance Method Summary collapse
-
#equivalent?(other) ⇒ Boolean
Equivalent facts (have all same values, except time_stamp).
-
#errors ⇒ Array
Checks if a fact has errors for storing in the graph.
-
#initialize(options) ⇒ Fact
constructor
Builds a new Fact.
-
#provenance_fact? ⇒ Boolean
Confirms this is not a ProvenanceFact.
-
#provenance_subject=(provenance_subject) ⇒ Object
A set_once setter for provenance_subject.
-
#provenance_subject_error(provenance_subject) ⇒ Object
Validates the presence or absence of provenance_subject.
-
#short ⇒ String
A short string representation of a Fact.
-
#string_values ⇒ Array
This is similar to the 6 entries in the to_CSV mapping.
-
#subject=(subject) ⇒ Object
A set_once setter for subject.
-
#time_stamp=(time_stamp) ⇒ Object
A set_once setter for time_stamp.
-
#update_used_provenance_subjects(h) ⇒ Object
Executes the required update in used_provenance_subjects.
-
#values ⇒ Array
The 6 values of a Fact.
Constructor Details
#initialize(options) ⇒ Fact
Builds a new Fact.
130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/dbd/fact.rb', line 130 def initialize() @id = [:id] || self.class.new_id @time_stamp = [:time_stamp] validate_time_stamp_class(@time_stamp) @provenance_subject = [:provenance_subject] @subject = [:subject] @predicate = [:predicate] @object = [:object] raise PredicateError, "predicate cannot be nil" if predicate.nil? raise ObjectError, "object cannot be nil" if object.nil? end |
Class Method Details
.attributes ⇒ Array
Returns The 6 attributes of a Fact.
62 63 64 65 66 67 68 69 |
# File 'lib/dbd/fact.rb', line 62 def self.attributes [:id, :time_stamp, :provenance_subject, :subject, :predicate, :object] end |
.fact_from_hash(hash) ⇒ Object
262 263 264 265 266 267 268 |
# File 'lib/dbd/fact.rb', line 262 def self.fact_from_hash(hash) if hash[:provenance_subject] Fact.new(hash) else ProvenanceFact.new(hash) end end |
.from_string_values(string_values) ⇒ Fact, ProvenanceFact
Constructs a Fact or ProvenanceFact from a string values array (e.g. pulled from a CSV row).
161 162 163 164 |
# File 'lib/dbd/fact.rb', line 161 def self.from_string_values(string_values) string_hash = hash_from_values(string_values) fact_from_hash(values_hash(string_hash)) end |
.hash_from_values(values) ⇒ Object
FIXME This has to move to a Fact::Factory
250 251 252 253 254 |
# File 'lib/dbd/fact.rb', line 250 def self.hash_from_values(values) # Do not keep "empty" values (e.g. the provenance_subject for a ProvenanceFact). attributes_values_array = [attributes, values].transpose.delete_if{|a,v| v.nil? || v == ''} Hash[attributes_values_array] end |
.new_id ⇒ String
Returns A new id string.
116 117 118 |
# File 'lib/dbd/fact.rb', line 116 def self.new_id ID.new_id end |
.new_subject ⇒ String
Returns A new subject string.
110 111 112 |
# File 'lib/dbd/fact.rb', line 110 def self.new_subject Subject.new_subject end |
Instance Method Details
#equivalent?(other) ⇒ Boolean
Equivalent facts (have all same values, except time_stamp).
For "equality" only a test on the id is used. If the id (which is a uuid) is the same, we assume that is the "same" fact. This equivalent? method is used to test is equal methods are "really" equivalent.
The time_stamp may be slightly different (because shifts of a few nanoseconds will be required to resolve collisions on merge).
177 178 179 180 181 |
# File 'lib/dbd/fact.rb', line 177 def equivalent?(other) (self.class.attributes - [:time_stamp]). all?{ |attribute| self.send(attribute) == other.send(attribute) } && self.time_stamp.near?(other.time_stamp) end |
#errors ⇒ Array
Checks if a fact has errors for storing in the graph.
210 211 212 213 214 215 216 217 218 219 |
# File 'lib/dbd/fact.rb', line 210 def errors # * id not validated, is set automatically upon creation # * time_stamp not validated, is set automatically later # * predicate not validated, is validated in initialize # * object not validated, is validated in initialize [].tap do |a| a << provenance_subject_error(provenance_subject) a << "Subject is missing" unless subject end.compact end |
#provenance_fact? ⇒ Boolean
Confirms this is not a ProvenanceFact.
Needed for validations that depend on different behavior for a provenance_fact (mainly, no provenance_subject).
239 240 241 |
# File 'lib/dbd/fact.rb', line 239 def provenance_fact? false end |
#provenance_subject=(provenance_subject) ⇒ Object
A set_once setter for provenance_subject.
This implements a "form" of immutable behavior. The value can be set once (possibly after creation the object), but can never be changed after that.
94 95 96 |
# File 'lib/dbd/fact.rb', line 94 def provenance_subject=(provenance_subject) set_once(:provenance_subject, provenance_subject) end |
#provenance_subject_error(provenance_subject) ⇒ Object
Validates the presence or absence of provenance_subject.
Here, in (base) Fact, provenance_subject must be present In the derived ProvenanceFact it must not be present. This is how the difference is encoded between Fact and ProvenanceFact in the fact stream. Return [nil, String] nil or an error message
230 231 232 |
# File 'lib/dbd/fact.rb', line 230 def provenance_subject_error(provenance_subject) "Provenance subject is missing" unless provenance_subject end |
#short ⇒ String
Returns a short string representation of a Fact.
185 186 187 188 189 190 |
# File 'lib/dbd/fact.rb', line 185 def short "#{provenance_subject_short} : " \ "#{subject.to_s[0...8]} : " \ "#{predicate.to_s.ljust(24, ' ')[0...24]} : " \ "#{object.to_s[0..60].gsub(/\n/, '_')}" end |
#string_values ⇒ Array
This is similar to the 6 entries in the to_CSV mapping
151 152 153 |
# File 'lib/dbd/fact.rb', line 151 def string_values values.map(&:to_s) end |
#subject=(subject) ⇒ Object
A set_once setter for subject.
This implements a "form" of immutable behavior. The value can be set once (possibly after creation the object), but can never be changed after that.
104 105 106 |
# File 'lib/dbd/fact.rb', line 104 def subject=(subject) set_once(:subject, subject) end |
#time_stamp=(time_stamp) ⇒ Object
A set_once setter for time_stamp.
This implements a "form" of immutable behavior. The value can be set once (possibly after creation the object), but can never be changed after that.
The input class is validated (easy confusion with String or Time).
83 84 85 86 |
# File 'lib/dbd/fact.rb', line 83 def time_stamp=(time_stamp) validate_time_stamp_class(time_stamp) set_once(:time_stamp, time_stamp) end |
#update_used_provenance_subjects(h) ⇒ Object
Executes the required update in used_provenance_subjects.
For a Fact, pointing to a ProvenanceResource in it's provenance_subject, marks this provenance_subject in the "used_provenance_subjects" hash that is passed in as an argument (DCI). This will avoid further changes to the ProvenanceResource with this provenance_subject.
This is overridden in the ProvenanceFact, since only relevant for a Fact.
201 202 203 204 |
# File 'lib/dbd/fact.rb', line 201 def update_used_provenance_subjects(h) # using a provenance_subject sets the key h[provenance_subject] = true end |
#values ⇒ Array
Returns The 6 values of a Fact.
144 145 146 |
# File 'lib/dbd/fact.rb', line 144 def values self.class.attributes.map{ |attribute| self.send(attribute) } end |