active-fedora 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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