Module: TaliaCore::ActiveSourceParts::ClassMethods

Included in:
TaliaCore::ActiveSource
Defined in:
lib/talia_core/active_source_parts/class_methods.rb

Instance Method Summary collapse

Instance Method Details

#additional_rdf_typesObject

Accessor for addtional rdf types that will automatically be added to each object of that Source class



7
8
9
# File 'lib/talia_core/active_source_parts/class_methods.rb', line 7

def additional_rdf_types 
  @additional_rdf_types ||= []
end

#create_from_xml(xml, options = {}) ⇒ Object

Create sources from XML. The result is either a single source or an Array of sources, depending on wether the XML contains multiple sources.

The imported sources will be saved during import, to ensure that relations between them are resolved correctly. If one of the imported elements does already exist, the existing source will be rewritten using ActiveSource#rewrite_attributes

The options may contain:

reader

The reader class that the import should use

progressor

The progress reporting object, which must respond to run_with_progress(message, size, &block)

errors

If given, all erors will be looged to this array instead of raising an exception. See the create_multi_from method for more.

duplicates

How to treat alredy existing sources. See ImportJobHelper for more documentation

base_file_uri

The base uri to import file from



70
71
72
73
74
75
76
77
78
# File 'lib/talia_core/active_source_parts/class_methods.rb', line 70

def create_from_xml(xml, options = {})
  options.to_options!
  options.assert_valid_keys(:reader, :progressor, :errors, :duplicates, :base_file_uri)
  reader = options[:reader] ? options.delete(:reader).to_s.classify.constantize : TaliaCore::ActiveSourceParts::Xml::SourceReader
  source_properties = reader.sources_from(xml, options[:progressor], options.delete(:base_file_uri))
  self.progressor = options.delete(:progressor)
  sources = create_multi_from(source_properties, options)
  (sources.size > 1) ? sources : sources.first
end

#create_multi_from(sources, options = {}) ⇒ Object

Creates multiple sources from the given array of attribute hashes. The sources are saved during import, ensuring that the relations are resolved correctly.

Options:

errors

If given, all erors will be logged to this array instead of raising an exception. Each “entry” in the error array will be an Error object containing the origianl stack trace of the error

duplicates

Indicates how to deal with sources that already exist in the datastore. See the ImportJobHelper class for a documentation of this option. Default is :skip



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
# File 'lib/talia_core/active_source_parts/class_methods.rb', line 91

def create_multi_from(sources, options = {})
  options.to_options!
  options.assert_valid_keys(:errors, :duplicates)
  source_objects = []
  run_with_progress('Writing imported', sources.size) do |progress|
    source_objects = sources.collect do |props|
      props.to_options!
      src = nil
      begin
        props[:uri] = uri_string_for(props[:uri])
        assit(props[:uri], "Must have a valid uri at this step")
        if(src = ActiveSource.find(:first, :conditions => { :uri => props[:uri] }))
          src.update_source(props, options[:duplicates])
        else
          src = ActiveSource.create_source(props)
        end
        src.save!
      rescue Exception => e
        if(options[:errors]) 
          err = ImportError.new("ERROR during import of #{props[:uri]}: #{e.message}")
          err.set_backtrace(e.backtrace)
          options[:errors] <<  err
          TaliaCore.logger.warn("Problems importing #{props[:uri]} (logged): #{e.message}")
        else
          raise
        end
      end
      progress.inc
      src
    end
  end
  source_objects
end

#create_source(args) ⇒ Object

Retrieves a new source with the given type. This gets a propety hash like #new, but it will correctly initialize a source of the type given in the hash. If no type is given, this will create a plain ActiveSource.



47
48
49
50
51
52
# File 'lib/talia_core/active_source_parts/class_methods.rb', line 47

def create_source(args)
  args.to_options!
  type = args.delete(:type) || 'TaliaCore::ActiveSource'
  klass = type.constantize
  klass.new(args)
end

#db_attr?(attribute) ⇒ Boolean

Returns true if the given attribute is one that is stored in the database

Returns:

  • (Boolean)


166
167
168
# File 'lib/talia_core/active_source_parts/class_methods.rb', line 166

def db_attr?(attribute)
  db_attributes.include?(attribute.to_s)
end

#exists?(value) ⇒ Boolean

This method is slightly expanded to allow passing uris and uri objects as an “id”

Returns:

  • (Boolean)


127
128
129
130
131
132
133
# File 'lib/talia_core/active_source_parts/class_methods.rb', line 127

def exists?(value)
  if(uri_s = uri_string_for(value))
    super(:uri => uri_s)
  else
    super
  end
end

#expand_uri(uri) ⇒ Object

Tries to expand a generic URI value that is either given as a full URL or a namespace:name value.

This will assume a full URL if it finds a “:/” string inside the URI. Otherwise it will construct a namespace - name URI



175
176
177
178
179
180
181
182
183
184
185
# File 'lib/talia_core/active_source_parts/class_methods.rb', line 175

def expand_uri(uri) # TODO: Merge with uri_for ?
  assit_block do |errors| 
    unless(uri.respond_to?(:uri) || uri.kind_of?(String)) || uri.kind_of?(Symbol)
      errors << "Found strange object of type #{uri.class}"
    end
    true
  end
  uri = uri.respond_to?(:uri) ? uri.uri.to_s : uri.to_s
  return uri if(uri.include?(':/'))
  N::URI.make_uri(uri).to_s
end

#new(*args) ⇒ Object

New method for ActiveSources. If a URL of an existing Source is given as the only parameter, that source will be returned. This makes the class work smoothly with our ActiveRDF version query interface.

Note that any semantic properties that were passed in to the constructor will be assigned after the ActiveRecord “create” callbacks have been called.

The option hash may contain a “files” option, which can be used to add data files directly on creation. This will call the attach_files method on the object.



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/talia_core/active_source_parts/class_methods.rb', line 20

def new(*args)
  the_source = if((args.size == 1) && (args.first.is_a?(Hash)))
    options = args.first
    options.to_options!

    # We have an option hash to init the source
    files = options.delete(:files)
    options[:uri] = uri_string_for(options[:uri])
    attributes = split_attribute_hash(options)
    the_source = super(attributes[:db_attributes])
    the_source.add_semantic_attributes(false, attributes[:semantic_attributes])
    the_source.attach_files(files) if(files)
    the_source
  elsif(args.size == 1 && ( uri_s = uri_string_for(args[0]))) # One string argument should be the uri
    # Either the current object from the db, or a new one if it doesn't exist in the db
    find(:first, :conditions => { :uri => uri_s } ) || super(:uri => uri_s)
  else
    # In this case, it's a generic "new" call
    super
  end
  the_source.add_additional_rdf_types if(the_source.new_record?)
  the_source
end

#paginate(*args) ⇒ Object

The pagination will also use the prepare_options! to have access to the advanced finder options



154
155
156
157
# File 'lib/talia_core/active_source_parts/class_methods.rb', line 154

def paginate(*args)
  prepare_options!(args.last) if(args.last.is_a?(Hash))
  super
end

#rewrite(id, attributes) ⇒ Object

Like update, only that it will overwrite the given attributes instead of adding to them

Raises:

  • (ActiveRecord::RecordNotFound)


146
147
148
149
150
# File 'lib/talia_core/active_source_parts/class_methods.rb', line 146

def rewrite(id, attributes)
  record = find(id)
  raise(ActiveRecord::RecordNotFound) unless(record)
  record.rewrite_attributes(attributes)
end

#split_attribute_hash(attributes) ⇒ Object

Splits the attribute hash that is given for new, update and the like. This will return another hash, where result will contain the hash of the database attributes while result will contain the other attributes.

The semantic attributes will be expanded to full URIs whereever possible.

This method will not check for attributes that correspond to singular property names.



196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/talia_core/active_source_parts/class_methods.rb', line 196

def split_attribute_hash(attributes)
  assit_kind_of(Hash, attributes)
  db_attributes = {}
  semantic_attributes = {}
  attributes.each do |field, value|
    if(db_attr?(field))
      db_attributes[field] = value
    else
      semantic_attributes[expand_uri(field)] = value
    end
  end
  { :semantic_attributes => semantic_attributes, :db_attributes => db_attributes }
end

#update(id, attributes) ⇒ Object

Semantic version of ActiveRecord::Base#update - the id may be a record id or an URL, and the attributes may contain semantic attributes. See the update_attributes method for details on how the semantic attributes behave.

Raises:

  • (ActiveRecord::RecordNotFound)


138
139
140
141
142
# File 'lib/talia_core/active_source_parts/class_methods.rb', line 138

def update(id, attributes)
  record = find(id)
  raise(ActiveRecord::RecordNotFound) unless(record)
  record.update_attributes(attributes)
end

#value_for(thing) ⇒ Object

If will return itself unless the value is a SemanticProperty, in which case it will return the property’s value.



161
162
163
# File 'lib/talia_core/active_source_parts/class_methods.rb', line 161

def value_for(thing)
  thing.is_a?(SemanticProperty) ? thing.value : thing
end