active-fedora 1.0.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.
@@ -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,109 @@
1
+ require 'fedora/datastream'
2
+ module ActiveFedora
3
+
4
+ #This class represents a Fedora datastream
5
+ class Datastream < Fedora::Datastream
6
+
7
+ attr_accessor :dirty, :last_modified, :fields
8
+
9
+ def initialize(attrs = nil)
10
+ @fields={}
11
+ @dirty = false
12
+ super
13
+ end
14
+
15
+ #Return the xml content representing this Datastream from Fedora
16
+ def content
17
+ result = Fedora::Repository.instance.fetch_custom(self.attributes[:pid], "datastreams/#{self.dsid}")
18
+ return result
19
+ end
20
+
21
+ #set this Datastream's content
22
+ def content=(content)
23
+ self.blob = content
24
+ end
25
+
26
+ #get this datastreams identifier
27
+ def pid
28
+ self.attributes[:pid]
29
+ end
30
+
31
+ #set this datastreams parent identifier
32
+ def pid=(pid)
33
+ self.attributes[:pid] = pid
34
+ end
35
+
36
+ #set this datastreams identifier (note: sets both dsID and dsid)
37
+ def dsid=(dsid)
38
+ self.attributes[:dsID] = dsid
39
+ self.attributes[:dsid] = dsid
40
+ end
41
+
42
+ #compatibility method for rails' url generators. This method will
43
+ #urlescape escape dots, which are apparently
44
+ #invalid characters in a dsid.
45
+ def to_param
46
+ dsid.gsub(/\./, '%2e')
47
+ end
48
+
49
+ #has this datastream been modified since it was last saved?
50
+ def dirty?
51
+ @dirty
52
+ end
53
+
54
+ #saves this datastream into fedora.
55
+ def save
56
+ before_save
57
+ result = Fedora::Repository.instance.save(self)
58
+ after_save
59
+ result
60
+ end
61
+
62
+ def before_save # :nodoc:
63
+ #check_concurrency
64
+ end
65
+ def self.from_xml(tmpl, el)
66
+ el.elements.each("foxml:xmlContent/fields") do |f|
67
+ tmpl.send("#{f.name}_append", f.text)
68
+ end
69
+ tmpl.instance_variable_set(:@dirty, false)
70
+ tmpl
71
+ end
72
+
73
+ def after_save
74
+ self.dirty = false
75
+ end
76
+
77
+ # returns a datetime in the standard W3C DateTime Format.
78
+ # ie 2008-10-17T00:17:18.194Z
79
+ def last_modified_in_repository
80
+ # A hack to get around the fact that you can't call getDatastreamHistory
81
+ # or API-M getDatasreams on Fedora 3.0 REST API
82
+ # grabs the CREATED attribute off of the last foxml:datastreamVersion
83
+ # within the appropriate datastream node in the objectXML
84
+ if self.pid != nil
85
+ object_xml = Fedora::FedoraObject.object_xml(self.pid).gsub("\n ","")
86
+ datastream_xml = REXML::Document.new(object_xml).root.elements["foxml:datastream[@ID='#{self.dsid}']"]
87
+
88
+ puts datastream_xml.length
89
+ if datastream_xml.length > 3
90
+ datastream_xml.elements.each do |el|
91
+ puts el.inspect
92
+ end
93
+ end
94
+
95
+ datastream_xml.elements[datastream_xml.length - 2].attributes["CREATED"]
96
+ else
97
+ return nil
98
+ end
99
+ end
100
+
101
+ def check_concurrency # :nodoc:
102
+ return true
103
+ end
104
+
105
+ end
106
+
107
+ class DatastreamConcurrencyException < Exception # :nodoc:
108
+ end
109
+ end
@@ -0,0 +1,78 @@
1
+ module ActiveFedora
2
+
3
+ #
4
+ # This is a module replacing the ActiveFedora::Base class.
5
+ #
6
+ module FedoraObject
7
+ def initialize
8
+ @inner_object = Fedora::FedoraObject.new
9
+ Fedora::Repository.instance.save @inner_object
10
+ end
11
+
12
+ def save
13
+ Fedora::Repository.instance.save(@inner_object)
14
+ end
15
+
16
+ def delete
17
+ Fedora::Repository.instance.delete(@inner_object)
18
+ end
19
+
20
+ def datastreams
21
+ datastreams = {}
22
+ self.datastreams_xml['datastream'].each do |ds|
23
+ ds.merge!({:pid => self.pid, :dsID => ds["dsid"]})
24
+ datastreams.merge!({ds["dsid"] => ActiveFedora::Datastream.new(ds)})
25
+ end
26
+ return datastreams
27
+ end
28
+
29
+ def datastreams_xml
30
+ datastreams_xml = XmlSimple.xml_in(Fedora::Repository.instance.fetch_custom(self.pid, :datastreams))
31
+ end
32
+
33
+ # Adds datastream to the object. Saves the datastream to fedora upon adding.
34
+ def add_datastream(datastream)
35
+ datastream.pid = self.pid
36
+ datastream.save
37
+ end
38
+
39
+ # DC Datastream
40
+ def dc
41
+ #dc = REXML::Document.new(datastreams["DC"].content)
42
+ return datastreams["DC"]
43
+ end
44
+
45
+ # RELS-EXT Datastream
46
+ def rels_ext
47
+ if !datastreams.has_key?("RELS-EXT")
48
+ add(ActiveFedora::RelsExtDatastream.new)
49
+ end
50
+
51
+ return datastreams["RELS-EXT"]
52
+ end
53
+
54
+ def inner_object
55
+ @inner_object
56
+ end
57
+
58
+ def pid
59
+ @inner_object.pid
60
+ end
61
+
62
+ def state
63
+ @inner_object.state
64
+ end
65
+
66
+ def owner_id
67
+ @inner_object.owner_id
68
+ end
69
+
70
+ def errors
71
+ @inner_object.errors
72
+ end
73
+
74
+ end
75
+
76
+
77
+
78
+ end
@@ -0,0 +1,120 @@
1
+ module ActiveFedora
2
+ #this class represents a MetadataDatastream, a special case of ActiveFedora::Datastream
3
+ class MetadataDatastream < Datastream
4
+ attr_accessor :fields
5
+
6
+ #constructor, calls up to ActiveFedora::Datastream's constructor
7
+ def initialize(attrs=nil)
8
+ super
9
+ @fields={}
10
+ end
11
+
12
+ # sets the blob, which in this case is the xml version of self, then calls ActiveFedora::Datastream.save
13
+ def save
14
+ self.set_blob_for_save
15
+ super
16
+ end
17
+
18
+ def set_blob_for_save # :nodoc:
19
+ self.blob = self.to_xml
20
+ end
21
+
22
+ def to_solr(solr_doc = Solr::Document.new) # :nodoc:
23
+ fields.each do |field_key, field_info|
24
+ if field_info.has_key?(:values) && !field_info[:values].nil?
25
+ field_symbol = generate_solr_symbol(field_key, field_info[:type])
26
+ field_info[:values].each do |val|
27
+ solr_doc << Solr::Field.new(field_symbol => val)
28
+ end
29
+ end
30
+ end
31
+
32
+ return solr_doc
33
+ end
34
+
35
+ def to_xml(xml = REXML::Document.new("<fields />")) #:nodoc:
36
+ fields.each_pair do |field,field_info|
37
+ el = REXML::Element.new("#{field.to_s}")
38
+ if field_info[:element_attrs]
39
+ field_info[:element_attrs].each{|k,v| el.add_attribute(k.to_s, v.to_s)}
40
+ end
41
+ field_info[:values].each do |val|
42
+ el = el.clone
43
+ el.text = val.to_s
44
+ if xml.class == REXML::Document
45
+ xml.root.elements.add(el)
46
+ else
47
+ xml.add(el)
48
+ end
49
+ end
50
+ end
51
+ return xml.to_s
52
+ end
53
+ def self.from_xml(tmpl, el) # :nodoc:
54
+ el.elements.each("./foxml:datastreamVersion[last()]/foxml:xmlContent/fields/node()")do |f|
55
+ tmpl.send("#{f.name}_append", f.text)
56
+ end
57
+ tmpl.send(:dirty=, false)
58
+ tmpl
59
+ end
60
+
61
+ # This method generates the various accessor and mutator methods on self for the datastream metadata attributes.
62
+ # each field will have the 3 magic methods:
63
+ # name_values=(arg)
64
+ # name_values
65
+ # name_append(arg)
66
+ #
67
+ #
68
+ # Calling any of the generated methods marks self as dirty.
69
+ #
70
+ # 'tupe' is a datatype, currently :string, :text and :date are supported.
71
+ #
72
+ # opts is an options hash, which will affect the generation of the xml representation of this datastream.
73
+ #
74
+ # Currently supported modifiers:
75
+ # For +QualifiedDublinCorDatastreams+:
76
+ # :element_attrs =>{:foo=>:bar} - hash of xml element attributes
77
+ # :xml_node => :nodename - The xml node to be used to represent this object (in dcterms namespace)
78
+ # :encoding=>foo, or encodings_scheme - causes an xsi:type attribute to be set to 'foo'
79
+ # :multiple=>true - mark this field as a multivalue field (on by default)
80
+ #
81
+ #At some point, these modifiers will be ported up to work for any +ActiveFedora::MetadataDatastream+.
82
+ #
83
+ #There is quite a good example of this class in use in spec/examples/oral_history.rb
84
+ def field(name, tupe, opts={})
85
+ @fields[name.to_s.to_sym]={:type=>tupe, :values=>[]}.merge(opts)
86
+ eval <<-EOS
87
+ def #{name}_values=(arg)
88
+ @fields["#{name.to_s}".to_sym][:values]=[arg].flatten
89
+ self.dirty=true
90
+ end
91
+ def #{name}_values
92
+ @fields["#{name}".to_sym][:values]
93
+ end
94
+ def #{name}_append(arg)
95
+ @fields["#{name}".to_sym][:values] << arg
96
+ self.dirty =true
97
+ end
98
+ EOS
99
+ end
100
+
101
+ #get the field list
102
+ def self.fields
103
+ @@classFields
104
+ end
105
+
106
+ protected
107
+
108
+ def generate_solr_symbol(field_name, field_type) # :nodoc:
109
+ if field_name.to_s[-field_type.to_s.length - 1 .. -1] == "_#{field_type.to_s}"
110
+ return field_name.to_sym
111
+ elsif field_type == :string
112
+ return "#{field_name.to_s}_field".to_sym
113
+ else
114
+ return "#{field_name.to_s}_#{field_type.to_s}".to_sym
115
+ end
116
+ end
117
+
118
+ end
119
+
120
+ end
@@ -0,0 +1,125 @@
1
+ require 'active_fedora/fedora_object'
2
+ module ActiveFedora
3
+ # = ActiveFedora
4
+ # This module mixes various methods into the including class,
5
+ # much in the way ActiveRecord does.
6
+ module Model
7
+ extend ActiveFedora::FedoraObject
8
+
9
+ attr_accessor :properties
10
+
11
+ def self.included(klass) # :nodoc:
12
+ klass.extend(ClassMethods)
13
+ end
14
+
15
+ def add_metadata
16
+ end
17
+
18
+ def datastream
19
+ end
20
+
21
+
22
+ #
23
+ # =Class Methods
24
+ # These methods are mixed into the inheriting class.
25
+ #
26
+ # Accessor and mutator methods are dynamically generated based
27
+ # on the contents of the @@field_spec hash, which stores the
28
+ # field specifications recorded during invocation of has_metadata.
29
+ #
30
+ # Each metadata field will generate 3 methods:
31
+ #
32
+ # fieldname_values
33
+ # *returns the current values array for this field
34
+ # fieldname_values=(val)
35
+ # *store val as the values array. val
36
+ # may be a single string, or an array of strings
37
+ # (single items become single element arrays).
38
+ # fieldname_append(val)
39
+ # *appends val to the values array.
40
+ module ClassMethods
41
+
42
+ # Load an instance with the following pid. Note that you can actually
43
+ # pass an pid into this method, regardless of Fedora model type, and
44
+ # ActiveFedora will try to parse the results into the current type
45
+ # of self, which may or may not be what you want.
46
+ def load_instance(pid)
47
+ Fedora::Repository.instance.find_model(pid, self)
48
+ end
49
+
50
+ # Takes :all or a pid as arguments
51
+ # Returns an Array of objects of the Class that +find+ is being
52
+ # called on
53
+ def find(args)
54
+ if args == :all
55
+ escaped_class_name = self.name.gsub(/(:)/, '\\:')
56
+ q = "active_fedora_model_field:#{escaped_class_name}"
57
+ elsif args.class == String
58
+ escaped_id = args.gsub(/(:)/, '\\:')
59
+ q = "id:#{escaped_id}"
60
+ end
61
+ hits = SolrService.instance.conn.query(q).hits
62
+ results = hits.map do |hit|
63
+ obj = Fedora::Repository.instance.find_model(hit["id"], self)
64
+ end
65
+ results.first
66
+ end
67
+
68
+ #Sends a query directly to SolrService
69
+ def solr_search(query, args={})
70
+ SolrService.instance.conn.query(query, args)
71
+ end
72
+
73
+
74
+ # If query is :all, this method will query Solr for all instances
75
+ # of self.type (based on active_fedora_model_field as indexed
76
+ # by Solr). If the query is any other string, this method simply does
77
+ # a pid based search (id:query).
78
+ #
79
+ # Note that this method does _not_ return ActiveFedora::Model
80
+ # objects, but rather an array of SolrResults.
81
+ #
82
+ # Args is an options hash, which is passed into the SolrService
83
+ # connection instance.
84
+ def find_by_solr(query, args={})
85
+ if query == :all
86
+ escaped_class_name = self.name.gsub(/(:)/, '\\:')
87
+ SolrService.instance.conn.query("active_fedora_model_field:#{escaped_class_name}", args)
88
+ elsif query.class == String
89
+ escaped_id = query.gsub(/(:)/, '\\:')
90
+ SolrService.instance.conn.query("id:#{escaped_id}", args)
91
+ end
92
+ end
93
+
94
+
95
+ #wrapper around instance_variable_set, sets @name to value
96
+ def attribute_set(name, value)
97
+ instance_variable_set("@#{name}", value)
98
+ end
99
+
100
+ #wrapper around instance_variable_get, returns current value of @name
101
+ def attribute_get(name)
102
+ #instance_variable_get(properties[":#{name}"].instance_variable_name)
103
+ instance_variable_get("@#{name}")
104
+ end
105
+
106
+ end
107
+ def create_property_getter(property) # :nodoc:
108
+
109
+ class_eval <<-END
110
+ def #{property.name}
111
+ attribute_get("#{property.name}")
112
+ end
113
+ END
114
+ end
115
+
116
+ def create_property_setter(property)# :nodoc:
117
+ class_eval <<-END
118
+ def #{property.name}=(value)
119
+ attribute_set("#{property.name}", value)
120
+ end
121
+ END
122
+ end
123
+
124
+ end
125
+ end