ruby-fedora 0.1.2 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. data/COPYING.LESSER.txt +165 -0
  2. data/COPYING.txt +674 -0
  3. data/Manifest.txt +19 -20
  4. data/README.txt +6 -1
  5. data/Rakefile +4 -0
  6. data/config/hoe.rb +2 -2
  7. data/config/requirements.rb +9 -2
  8. data/lib/active_fedora.rb +41 -0
  9. data/lib/active_fedora/base.rb +278 -8
  10. data/lib/active_fedora/content_model.rb +22 -0
  11. data/lib/active_fedora/datastream.rb +95 -0
  12. data/lib/active_fedora/fedora_object.rb +84 -0
  13. data/lib/active_fedora/metadata_datastream.rb +97 -0
  14. data/lib/active_fedora/model.rb +94 -0
  15. data/lib/active_fedora/property.rb +15 -0
  16. data/lib/active_fedora/qualified_dublin_core_datastream.rb +72 -0
  17. data/lib/active_fedora/relationship.rb +43 -0
  18. data/lib/active_fedora/rels_ext_datastream.rb +43 -0
  19. data/lib/active_fedora/semantic_node.rb +221 -0
  20. data/lib/active_fedora/solr_service.rb +20 -0
  21. data/lib/fedora/base.rb +2 -1
  22. data/lib/fedora/connection.rb +104 -134
  23. data/lib/fedora/datastream.rb +10 -1
  24. data/lib/fedora/fedora_object.rb +28 -24
  25. data/lib/fedora/generic_search.rb +71 -0
  26. data/lib/fedora/repository.rb +47 -3
  27. data/lib/ruby-fedora.rb +9 -8
  28. data/lib/util/class_level_inheritable_attributes.rb +23 -0
  29. data/solr/config/schema.xml +229 -0
  30. metadata +37 -24
  31. data/lib/active-fedora.rb +0 -1
  32. data/lib/ambition/adapters/active_fedora.rb +0 -10
  33. data/lib/ambition/adapters/active_fedora/base.rb +0 -14
  34. data/lib/ambition/adapters/active_fedora/query.rb +0 -48
  35. data/lib/ambition/adapters/active_fedora/select.rb +0 -104
  36. data/lib/ambition/adapters/active_fedora/slice.rb +0 -19
  37. data/lib/ambition/adapters/active_fedora/sort.rb +0 -43
  38. data/script/destroy +0 -14
  39. data/script/generate +0 -14
  40. data/script/txt2html +0 -74
  41. data/tasks/deployment.rake +0 -34
  42. data/tasks/environment.rake +0 -7
  43. data/tasks/website.rake +0 -17
  44. data/website/index.html +0 -93
  45. data/website/index.txt +0 -39
  46. data/website/javascripts/rounded_corners_lite.inc.js +0 -285
  47. data/website/stylesheets/screen.css +0 -138
  48. data/website/template.rhtml +0 -48
@@ -0,0 +1,22 @@
1
+ module ActiveFedora
2
+ class ContentModel < Base
3
+ CMODEL_NAMESPACE = "afmodel"
4
+ CMODEL_PID_SUFFIX = ""
5
+
6
+ attr_accessor :pid_suffix, :namespace
7
+
8
+ def initialize(attrs={})
9
+ @pid_suffix = attrs.has_key?(:pid_suffix) ? attrs[:pid_suffix] : CMODEL_PID_SUFFIX
10
+ @namespace = attrs.has_key?(:namespace) ? attrs[:namespace] : CMODEL_NAMESPACE
11
+ super
12
+ end
13
+
14
+ def self.pid_from_ruby_class(klass,attrs={})
15
+ sanitized_class_name = klass.name.gsub(/(::)/, '_')
16
+ pid_suffix = attrs.has_key?(:pid_suffix) ? attrs[:pid_suffix] : CMODEL_PID_SUFFIX
17
+ namespace = attrs.has_key?(:namespace) ? attrs[:namespace] : CMODEL_NAMESPACE
18
+ return "#{namespace}:#{sanitized_class_name}#{pid_suffix}"
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,95 @@
1
+ module ActiveFedora
2
+ class Datastream < Fedora::Datastream
3
+
4
+ attr_accessor :dirty, :last_modified, :fields
5
+
6
+ def initialize(attrs = nil)
7
+ @fields={}
8
+ @dirty = false
9
+ super
10
+ end
11
+
12
+ def content
13
+ result = Fedora::Repository.instance.fetch_custom(self.attributes[:pid], "datastreams/#{self.dsid}")
14
+ #self.last_modified = last_modified_in_repository
15
+ return result
16
+ end
17
+
18
+ def content=(content)
19
+ self.blob = content
20
+ end
21
+
22
+ def pid
23
+ self.attributes[:pid]
24
+ end
25
+
26
+ def pid=(pid)
27
+ self.attributes[:pid] = pid
28
+ end
29
+
30
+ def dsid=(dsid)
31
+ self.attributes[:dsID] = dsid
32
+ self.attributes[:dsid] = dsid
33
+ end
34
+ def to_param
35
+ dsid.gsub(/\./, '%2e')
36
+ end
37
+
38
+ def dirty?
39
+ @dirty
40
+ end
41
+
42
+ def save
43
+ before_save
44
+ result = Fedora::Repository.instance.save(self)
45
+ after_save
46
+ result
47
+ end
48
+
49
+ def before_save
50
+ #check_concurrency
51
+ end
52
+ def self.from_xml(tmpl, el)
53
+ el.elements.each("foxml:xmlContent/fields") do |f|
54
+ tmpl.send("#{f.name}_append", f.text)
55
+ end
56
+ tmpl.instance_variable_set(:@dirty, false)
57
+ tmpl
58
+ end
59
+
60
+ def after_save
61
+ self.dirty = false
62
+ end
63
+
64
+ # returns a datetime in the standard W3C DateTime Format. ie 2008-10-17T00:17:18.194Z
65
+ def last_modified_in_repository
66
+ # A hack to get around the fact that you can't call getDatastreamHistory or API-M getDatasreams on Fedora 3.0 REST API
67
+ # grabs the CREATED attribute off of the last foxml:datastreamVersion within the appropriate datastream node in the objectXML
68
+ puts "PID: #{self.pid} , DSID: #{self.dsid}"
69
+ if self.pid != nil
70
+ object_xml = Fedora::FedoraObject.object_xml(self.pid).gsub("\n ","")
71
+ datastream_xml = REXML::Document.new(object_xml).root.elements["foxml:datastream[@ID='#{self.dsid}']"]
72
+
73
+ puts datastream_xml.length
74
+ if datastream_xml.length > 3
75
+ datastream_xml.elements.each do |el|
76
+ puts el.inspect
77
+ end
78
+ end
79
+
80
+ datastream_xml.elements[datastream_xml.length - 2].attributes["CREATED"]
81
+ else
82
+ return nil
83
+ end
84
+ end
85
+
86
+ def check_concurrency
87
+ return true
88
+ #@last_modified == self.last_modified_in_repository ? true : raise(ActiveFedora::DatastreamConcurrencyException.new, "Someone else has changed this datastream in Fedora while you were working on it.")
89
+ end
90
+
91
+ end
92
+
93
+ class DatastreamConcurrencyException < Exception
94
+ end
95
+ end
@@ -0,0 +1,84 @@
1
+ require 'ruby-fedora'
2
+ require "rexml/document"
3
+
4
+ require 'active_fedora/datastream'
5
+ require 'active_fedora/relationship'
6
+
7
+ module ActiveFedora
8
+
9
+ #
10
+ # This is a module replacing the ActiveFedora::Base class.
11
+ #
12
+ module FedoraObject
13
+ def initialize
14
+ @inner_object = Fedora::FedoraObject.new
15
+ Fedora::Repository.instance.save @inner_object
16
+ end
17
+
18
+ def save
19
+ Fedora::Repository.instance.save(@inner_object)
20
+ end
21
+
22
+ def delete
23
+ Fedora::Repository.instance.delete(@inner_object)
24
+ end
25
+
26
+ def datastreams
27
+ datastreams = {}
28
+ self.datastreams_xml['datastream'].each do |ds|
29
+ ds.merge!({:pid => self.pid, :dsID => ds["dsid"]})
30
+ datastreams.merge!({ds["dsid"] => ActiveFedora::Datastream.new(ds)})
31
+ end
32
+ return datastreams
33
+ end
34
+
35
+ def datastreams_xml
36
+ datastreams_xml = XmlSimple.xml_in(Fedora::Repository.instance.fetch_custom(self.pid, :datastreams))
37
+ end
38
+
39
+ # Adds datastream to the object. Saves the datastream to fedora upon adding.
40
+ def add_datastream(datastream)
41
+ datastream.pid = self.pid
42
+ datastream.save
43
+ end
44
+
45
+ # DC Datastream
46
+ def dc
47
+ #dc = REXML::Document.new(datastreams["DC"].content)
48
+ return datastreams["DC"]
49
+ end
50
+
51
+ # RELS-EXT Datastream
52
+ def rels_ext
53
+ if !datastreams.has_key?("RELS-EXT")
54
+ add(ActiveFedora::RelsExtDatastream.new)
55
+ end
56
+
57
+ return datastreams["RELS-EXT"]
58
+ end
59
+
60
+ def inner_object
61
+ @inner_object
62
+ end
63
+
64
+ def pid
65
+ @inner_object.pid
66
+ end
67
+
68
+ def state
69
+ @inner_object.state
70
+ end
71
+
72
+ def owner_id
73
+ @inner_object.owner_id
74
+ end
75
+
76
+ def errors
77
+ @inner_object.errors
78
+ end
79
+
80
+ end
81
+
82
+
83
+
84
+ end
@@ -0,0 +1,97 @@
1
+ require "rexml/document"
2
+ require "rexml/element"
3
+ require "solr"
4
+
5
+ module ActiveFedora
6
+ class MetadataDatastream < Datastream
7
+ attr_accessor :fields
8
+
9
+ def initialize(attrs=nil)
10
+ super
11
+ @fields={}
12
+ end
13
+
14
+ def save
15
+ self.set_blob_for_save
16
+ super
17
+ end
18
+
19
+ def set_blob_for_save
20
+ self.blob = self.to_xml
21
+ end
22
+
23
+ def to_solr(solr_doc = Solr::Document.new)
24
+ fields.each do |field_key, field_info|
25
+ if field_info.has_key?(:values) && !field_info[:values].nil?
26
+ field_symbol = generate_solr_symbol(field_key, field_info[:type])
27
+ field_info[:values].each do |val|
28
+ solr_doc << Solr::Field.new(field_symbol => val)
29
+ end
30
+ end
31
+ end
32
+
33
+ return solr_doc
34
+ end
35
+
36
+ def to_xml(xml = REXML::Document.new("<fields />"))
37
+ fields.each_pair do |field,field_info|
38
+ el = REXML::Element.new("#{field.to_s}")
39
+ if field_info[:element_attrs]
40
+ field_info[:element_attrs].each{|k,v| el.add_attribute(k.to_s, v.to_s)}
41
+ end
42
+ field_info[:values].each do |val|
43
+ el = el.clone
44
+ el.text = val.to_s
45
+ if xml.class == REXML::Document
46
+ xml.root.elements.add(el)
47
+ else
48
+ xml.add(el)
49
+ end
50
+ end
51
+ end
52
+ return xml.to_s
53
+ end
54
+ def self.from_xml(tmpl, el)
55
+ el.elements.each("./foxml:datastreamVersion[last()]/foxml:xmlContent/fields/node()")do |f|
56
+ tmpl.send("#{f.name}_append", f.text)
57
+ end
58
+ tmpl.send(:dirty=, false)
59
+ tmpl
60
+ end
61
+
62
+ def field(name, tupe, opts={})
63
+ @fields[name.to_s.to_sym]={:type=>tupe, :values=>[]}.merge(opts)
64
+ eval <<-EOS
65
+ def #{name}_values=(arg)
66
+ @fields["#{name.to_s}".to_sym][:values]=[arg].flatten
67
+ self.dirty=true
68
+ end
69
+ def #{name}_values
70
+ @fields["#{name}".to_sym][:values]
71
+ end
72
+ def #{name}_append(arg)
73
+ @fields["#{name}".to_sym][:values] << arg
74
+ self.dirty =true
75
+ end
76
+ EOS
77
+ end
78
+
79
+ def self.fields
80
+ @@classFields
81
+ end
82
+
83
+ protected
84
+
85
+ def generate_solr_symbol(field_name, field_type)
86
+ if field_name.to_s[-field_type.to_s.length - 1 .. -1] == "_#{field_type.to_s}"
87
+ return field_name.to_sym
88
+ elsif field_type == :string
89
+ return "#{field_name.to_s}_field".to_sym
90
+ else
91
+ return "#{field_name.to_s}_#{field_type.to_s}".to_sym
92
+ end
93
+ end
94
+
95
+ end
96
+
97
+ end
@@ -0,0 +1,94 @@
1
+ require 'active_fedora/semantic_node'
2
+ require 'active_fedora/fedora_object'
3
+
4
+ module ActiveFedora
5
+ module Model
6
+ extend ActiveFedora::FedoraObject
7
+
8
+ attr_accessor :properties
9
+
10
+ def self.included(klass)
11
+ klass.extend(ClassMethods)
12
+ end
13
+
14
+ def add_metadata
15
+ end
16
+
17
+ def datastream
18
+ end
19
+
20
+
21
+ #
22
+ # Class Methods
23
+ #
24
+
25
+ module ClassMethods
26
+
27
+ def load_instance(pid)
28
+ Fedora::Repository.instance.find_model(pid, self)
29
+ end
30
+
31
+ # Takes :all or a pid as arguments
32
+ # @returns an Array of objects of the Class that .find is being called on
33
+ def find(args)
34
+ if args == :all
35
+ escaped_class_name = self.name.gsub(/(:)/, '\\:')
36
+ q = "active_fedora_model_field:#{escaped_class_name}"
37
+ elsif args.class == String
38
+ escaped_id = args.gsub(/(:)/, '\\:')
39
+ q = "id:#{escaped_id}"
40
+ end
41
+ hits = SolrService.instance.conn.query(q).hits
42
+ results = hits.map do |hit|
43
+ obj = Fedora::Repository.instance.find_model(hit["id"], self)
44
+ end
45
+ results.first
46
+ end
47
+
48
+ #this just takes raw solr queries
49
+ def solr_search(query, args={})
50
+ SolrService.instance.conn.query(query, args)
51
+ end
52
+
53
+
54
+ # this is supposed to behave more like a finder.
55
+ def find_by_solr(query, args={})
56
+ if query == :all
57
+ escaped_class_name = self.name.gsub(/(:)/, '\\:')
58
+ SolrService.instance.conn.query("active_fedora_model_field:#{escaped_class_name}", args)
59
+ elsif query.class == String
60
+ escaped_id = query.gsub(/(:)/, '\\:')
61
+ SolrService.instance.conn.query("id:#{escaped_id}", args)
62
+ end
63
+ end
64
+
65
+ def create_property_getter(property)
66
+ class_eval <<-END
67
+ def #{property.name}
68
+ attribute_get("#{property.name}")
69
+ end
70
+ END
71
+ end
72
+
73
+ def create_property_setter(property)
74
+ class_eval <<-END
75
+ def #{property.name}=(value)
76
+ attribute_set("#{property.name}", value)
77
+ end
78
+ END
79
+ end
80
+
81
+ def attribute_set(name, value)
82
+ #instance_variable_set(properties[":#{name}"].instance_variable_name)
83
+ instance_variable_set("@#{name}", value)
84
+ end
85
+
86
+ def attribute_get(name)
87
+ #instance_variable_get(properties[":#{name}"].instance_variable_name)
88
+ instance_variable_get("@#{name}")
89
+ end
90
+
91
+ end
92
+
93
+ end
94
+ end
@@ -0,0 +1,15 @@
1
+ module ActiveFedora
2
+ class Property
3
+
4
+ attr_accessor :name, :instance_variable_name
5
+
6
+ def initialize(model, name, type, options = {})
7
+ @name = name
8
+ @instance_variable_name = "@#{@name}"
9
+ end
10
+
11
+ def field
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,72 @@
1
+ require "rexml/document"
2
+ require "rexml/element"
3
+
4
+
5
+ module ActiveFedora
6
+ class QualifiedDublinCoreDatastream < MetadataDatastream
7
+ DCTERMS = [
8
+ :contributor, :coverage, :creator, :description, :format, :identifier, :language, :publisher, :relation, :source, :title, :abstract, :accessRights, :accrualMethod, :accrualPeriodicity, :accrualPolicy, :alternative, :audience, :available, :bibliographicCitation, :conformsTo, :contributor, :coverage, :created, :creator, :date, :dateAccepted, :dateCopyrighted, :dateSubmitted, :description, :educationLevel, :extent, :format, :hasFormat, :hasPart, :hasVersion, :identifier, :instructionalMethod, :isFormatOf, :isPartOf, :isReferencedBy, :isReplacedBy, :isRequiredBy, :issued, :isVersionOf, :language, :license, :mediator, :medium, :modified, :provenance, :publisher, :references, :relation, :replaces, :requires, :rights, :rightsHolder, :source, :spatial, :subject, :tableOfContents, :temporal, :type, :valid
9
+ ]
10
+ DCTERMS.freeze
11
+
12
+ def initialize(attrs=nil)
13
+ super
14
+ DCTERMS.each do |el|
15
+ field el, :string, :multiple=>true
16
+ end
17
+ self
18
+ end
19
+
20
+ def set_blob_for_save
21
+ self.blob = self.to_dc_xml
22
+ end
23
+ def self.from_xml(tmpl, el)
24
+ tmpl.fields.each do |z|
25
+ fname = z.first
26
+ fspec = z.last
27
+ node = "dcterms:#{fspec[:xml_node] ? fspec[:xml_node] : fname}"
28
+ attr_modifier= "[@xsi:type='#{fspec[:encoding]}']" if fspec[:encoding]
29
+ query = "./foxml:datastreamVersion[last()]/foxml:xmlContent/dc/#{node}#{attr_modifier}"
30
+ el.elements.each(query) do |f|
31
+ tmpl.send("#{fname}_append", f.text)
32
+ end
33
+
34
+ end
35
+ tmpl.instance_variable_set(:@dirty, false)
36
+ tmpl
37
+ end
38
+
39
+ def to_dc_xml
40
+ xml = REXML::Document.new("<dc xmlns:dcterms='http://purl.org/dc/terms/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'/>")
41
+ fields.each do |field_name,field_info|
42
+ el = REXML::Element.new("dcterms:#{field_name.to_s}")
43
+ if field_info.class == Hash
44
+ field_info.each do |k, v|
45
+ case k
46
+ when :element_attrs
47
+ v.each{|k,v| el.add_attribute(k.to_s, v.to_s)}
48
+ when :values, :type
49
+ # do nothing to the :values array
50
+ when :xml_node
51
+ el.name = "dcterms:#{v}"
52
+ when :encoding, :encoding_scheme
53
+ el.add_attribute("xsi:type", v)
54
+ when :multiple
55
+ next
56
+ else
57
+ el.add_attribute(k.to_s, v)
58
+ end
59
+ end
60
+ field_info = field_info[:values]
61
+ end
62
+ field_info.each do |val|
63
+ el = el.clone
64
+ el.text = val.to_s
65
+ xml.root.elements.add(el)
66
+ end
67
+ end
68
+ return xml.to_s
69
+ end
70
+
71
+ end
72
+ end