Class: TaliaCore::Collection

Inherits:
Source show all
Includes:
Enumerable
Defined in:
lib/talia_core/collection.rb

Overview

Represents a collection of sources. In addition to being a container for sources, the Collection class will also provide an ordering of the contained sources.

In a nutshell, this behaves like an array of sources that preserves the order when saved.

The ordering will always assign a ”unique” integer value to each contained source that defines its position in the order of elements. The collection will keep an internal array where each object’s index maps directly to its position in the collection; the array and ordering are saved to the data store when the collection itself is saved.

The collection class is relatively lightweight and will behave mostly like the underlying array - most operations are simply passed through to the array and nothing is saved before the collection itself is saved.

Operations that are passed to the underlying array are: +, <<, ==, []=, at, clear, collect, delete_at, delete, each, each_index, empty?, include?, index, join, last, length and size.

This also means that all checks on added objects will only be performed when the collection is saved, and not much checking is done when the array is modified.

Important: it is required that no object in the list be present more than once.

In the RDF, the collection is represented as a seqContainer, using a predicate of “www.w3.org/1999/02/22-rdf-syntax-ns#_[index of element x]” to connect an element x with the collection.

Note: This class replaces the previous OrderedSource class

Instance Attribute Summary

Attributes inherited from Source

#predicates_attributes

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Source

#==, #associated?, #collections, find_or_instantiate_by_uri, #grouped_direct_predicates, #grouped_predicates_attributes, groups_by_property, #label, #labels, #local, #normalize_uri, normalize_uri, #predicate_changed?, #predicate_objects, #primary_source, #primary_source=, #save_predicates_attributes, #titleized, #uri

Methods inherited from ActiveSource

#add_additional_rdf_types, #add_semantic_attributes, #attach_files, #data, #db_attr?, #defined_property?, #direct_predicates, #inverse, #inverse_predicates, #predicate, #predicate_replace, #predicate_set, #predicate_set_uniq, #property_options_for, #rdf_selftype, #rewrite_attributes, #rewrite_attributes!, #short_uri, #to_rdf, #to_s, #to_uri, #to_xml, #update_attributes, #update_attributes!, #update_attributes_orig, #update_attributes_orig!, #update_source, #value_for, #write_predicate_direct

Methods included from ActiveSourceParts::ClassMethods

#additional_rdf_types, #create_from_xml, #create_multi_from, #create_source, #db_attr?, #defined_property?, #exists?, #expand_uri, #new, #paginate, #property_options_for, #props_to_destroy, #rewrite, #split_attribute_hash, #update, #value_for

Methods included from ActiveSourceParts::Finders

#count, #find, #find_by_partial_local, #find_by_partial_uri, #find_by_uri_token

Methods included from ActiveSourceParts::SqlHelper

#default_inv_joins, #default_joins, #props_join, #sources_join

Methods included from ActiveSourceParts::PredicateHandler::ClassMethods

#prefetch_relations_for

Methods included from TaliaUtil::Progressable

#progressor, #progressor=, #run_with_progress

Methods included from ActiveSourceParts::RdfHandler

#autosave_rdf=, #autosave_rdf?, #create_rdf, #my_rdf, #to_rdf

Methods included from ActiveSourceParts::PredicateHandler

#each_cached_wrapper, #get_objects_on, #get_wrapper_on, #has_type?, #inject_predicate, #reset!, #save_wrappers, #types

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class TaliaCore::Source

Class Method Details

.index_to_predicate(index) ⇒ Object

Returns the predicate that will be used for the collection element with the given index. The result will be:

http://www.w3.org/1999/02/22-rdf-syntax-ns#_<index>


115
116
117
# File 'lib/talia_core/collection.rb', line 115

def self.index_to_predicate(index)
  'http://www.w3.org/1999/02/22-rdf-syntax-ns#_' << ("%06d" % index.to_i) 
end

.new(*params) ⇒ Object

Creates a new Collection. Takes the same parameters as ActiveSource.new



54
55
56
57
58
# File 'lib/talia_core/collection.rb', line 54

def self.new(*params)
  collection = super(*params)
  # collection.autosave_rdf = false # Will do this by ourselves
  collection
end

.predicate_to_index(predicate) ⇒ Object

Takes a predicate of the form produced by index_to_predicate and returns the numeric index of the element



121
122
123
# File 'lib/talia_core/collection.rb', line 121

def self.predicate_to_index(predicate)
  predicate.sub('http://www.w3.org/1999/02/22-rdf-syntax-ns#_', '').to_i
end

Instance Method Details

#[](index_or_predicate) ⇒ Object

This accessor can be used for both collection items and predicates. If a number is passed in, the object will behave like an Array and the source at the given index is returned. Otherwise the parameter is treated like a predicate and it behaves like ActiveSource#[].



74
75
76
77
78
79
80
# File 'lib/talia_core/collection.rb', line 74

def [](index_or_predicate)
  if(index_or_predicate.is_a?(Fixnum))
    ordered_objects[index_or_predicate]
  else
    super
  end
end

#[]=(index_or_predicate, value) ⇒ Object

Writer that behaves in the same way as []



83
84
85
86
87
88
89
# File 'lib/talia_core/collection.rb', line 83

def []=(index_or_predicate, value)
  if(index_or_predicate.is_a?(Fixnum))
    ordered_objects[index_or_predicate] = value
  else
    super
  end
end

#after_initializeObject



48
49
50
# File 'lib/talia_core/collection.rb', line 48

def after_initialize
  @autosave_rdf = false
end

#elementsObject

Returns all contained sources in an ordered array.

The contained sources will appear in the sequential order in which they are contained in the collection, but there is no direct relation between the index in the collection and the index returned through this method. Repeated elements in the collection will be ignored.



97
98
99
100
# File 'lib/talia_core/collection.rb', line 97

def elements
  # execute query
  ordered_objects.compact.uniq
end

#force_rdf_rewriteObject



185
186
187
# File 'lib/talia_core/collection.rb', line 185

def force_rdf_rewrite
  create_rdf(:force)
end

#index_to_predicate(index) ⇒ Object

See Collection.index_to_predicate



103
104
105
# File 'lib/talia_core/collection.rb', line 103

def index_to_predicate(index)
  self.class.index_to_predicate(index)
end

#next(object) ⇒ Object

Returns the element next to the one passed as parameter. Returns nil if there is no next object. Requires that no object in the collection is present more than once.



135
136
137
# File 'lib/talia_core/collection.rb', line 135

def next(object)
  elements[elements.index(object) + 1]
end

#ordered_objectsObject

Returns all the objects that are ordered in an array where the array index equals the position of the object in the ordered set. The array is zero-based, position that don’t have an object attached will be set to nil.



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/talia_core/collection.rb', line 151

def ordered_objects
  return @ordered_objects if(@ordered_objects)
  relations = query
  # Let's assume the follwing is a sane assumption ;-)
  # Even if a one-base collection comes in, we need to push just one element
  @ordered_objects = Array.new(relations.size)
  # Now add the elements so that the relation property is reflected
  # on the position in the array
  relations.each do |rel|
    index = rel.rel_order
    @ordered_objects[index] = rel.object
  end

  @ordered_objects
end

#predicate_to_index(predicate) ⇒ Object

See Collection.predicate_to_index



108
109
110
# File 'lib/talia_core/collection.rb', line 108

def predicate_to_index(predicate)
  self.class.predicate_to_index(predicate)
end

#prev(object) ⇒ Object

Returns the element previous to the one passed as parameter. Returns nil if there is no previous object. Requires that no object in the collection is present more than once.



142
143
144
145
# File 'lib/talia_core/collection.rb', line 142

def prev(object)
  return nil if elements.index(object) == 0
  elements[elements.index(object) - 1]
end

#query(scope = :all) ⇒ Object

execute query and return the result



190
191
192
193
# File 'lib/talia_core/collection.rb', line 190

def query(scope = :all)
  # execute query
  self.semantic_relations.find(scope, :conditions => 'rel_order IS NOT NULL', :order => :rel_order)
end

#reloadObject

Reloading from database by clearing the internal array



126
127
128
129
130
# File 'lib/talia_core/collection.rb', line 126

def reload # :nodoc:
  @ordered_objects = nil
  ordered_objects
  super
end

#rewrite_order_relationsObject

This will be called before saving and will completely rewrite the relations that make up the ordered store, based on the internal array



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/talia_core/collection.rb', line 169

def rewrite_order_relations
  return unless(@ordered_objects) # If this is nil, the relations weren't loaded in the first place
  objects = ordered_objects # Fetch them before deleting
  # Now destroy the existing elements
  SemanticRelation.destroy_all(['subject_id = ? AND rel_order IS NOT NULL', self.id])
  SemanticRelation.destroy_all(['subject_id = ? AND predicate_uri = ?', self.id, N::DCT.hasPart.to_s])
  # rewrite from the relations array
  objects.each_index do |index|
    if(obj = objects.at(index)) # Check if there's a value to handle
      # Create a new relation with an order
      self[index_to_predicate(index)].add_record(obj, index)
      self[N::DCT.hasPart] << obj
    end
  end
end