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.
- data/COPYING.LESSER.txt +165 -0
- data/COPYING.txt +674 -0
- data/Manifest.txt +19 -20
- data/README.txt +6 -1
- data/Rakefile +4 -0
- data/config/hoe.rb +2 -2
- data/config/requirements.rb +9 -2
- data/lib/active_fedora.rb +41 -0
- data/lib/active_fedora/base.rb +278 -8
- data/lib/active_fedora/content_model.rb +22 -0
- data/lib/active_fedora/datastream.rb +95 -0
- data/lib/active_fedora/fedora_object.rb +84 -0
- data/lib/active_fedora/metadata_datastream.rb +97 -0
- data/lib/active_fedora/model.rb +94 -0
- data/lib/active_fedora/property.rb +15 -0
- data/lib/active_fedora/qualified_dublin_core_datastream.rb +72 -0
- data/lib/active_fedora/relationship.rb +43 -0
- data/lib/active_fedora/rels_ext_datastream.rb +43 -0
- data/lib/active_fedora/semantic_node.rb +221 -0
- data/lib/active_fedora/solr_service.rb +20 -0
- data/lib/fedora/base.rb +2 -1
- data/lib/fedora/connection.rb +104 -134
- data/lib/fedora/datastream.rb +10 -1
- data/lib/fedora/fedora_object.rb +28 -24
- data/lib/fedora/generic_search.rb +71 -0
- data/lib/fedora/repository.rb +47 -3
- data/lib/ruby-fedora.rb +9 -8
- data/lib/util/class_level_inheritable_attributes.rb +23 -0
- data/solr/config/schema.xml +229 -0
- metadata +37 -24
- data/lib/active-fedora.rb +0 -1
- data/lib/ambition/adapters/active_fedora.rb +0 -10
- data/lib/ambition/adapters/active_fedora/base.rb +0 -14
- data/lib/ambition/adapters/active_fedora/query.rb +0 -48
- data/lib/ambition/adapters/active_fedora/select.rb +0 -104
- data/lib/ambition/adapters/active_fedora/slice.rb +0 -19
- data/lib/ambition/adapters/active_fedora/sort.rb +0 -43
- data/script/destroy +0 -14
- data/script/generate +0 -14
- data/script/txt2html +0 -74
- data/tasks/deployment.rake +0 -34
- data/tasks/environment.rake +0 -7
- data/tasks/website.rake +0 -17
- data/website/index.html +0 -93
- data/website/index.txt +0 -39
- data/website/javascripts/rounded_corners_lite.inc.js +0 -285
- data/website/stylesheets/screen.css +0 -138
- 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,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
|