talia_core 0.4.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/README.rdoc +41 -0
- data/bin/talia +33 -0
- data/lib/JXslt/jxslt.rb +60 -0
- data/lib/acts_as_roled.rb +11 -0
- data/lib/core_ext/platform.rb +9 -0
- data/lib/core_ext/string.rb +6 -0
- data/lib/core_ext.rb +1 -0
- data/lib/custom_template.rb +4 -0
- data/lib/loader_helper.rb +62 -0
- data/lib/mysql.rb +1214 -0
- data/lib/progressbar.rb +236 -0
- data/lib/role.rb +12 -0
- data/lib/talia_cl/command_line.rb +39 -0
- data/lib/talia_cl/commands/standalone/cl_options.rb +9 -0
- data/lib/talia_cl/commands/standalone/standalone_generate.rb +75 -0
- data/lib/talia_cl/commands/standalone.rb +25 -0
- data/lib/talia_cl/commands/talia_console/cl_options.rb +55 -0
- data/lib/talia_cl/commands/talia_console/console_commands.rb +37 -0
- data/lib/talia_cl/commands/talia_console/talia_commands.rb +131 -0
- data/lib/talia_cl/commands/talia_console.rb +47 -0
- data/lib/talia_cl/core_commands.rb +11 -0
- data/lib/talia_cl.rb +47 -0
- data/lib/talia_core/active_source.rb +372 -0
- data/lib/talia_core/active_source_parts/class_methods.rb +378 -0
- data/lib/talia_core/active_source_parts/predicate_handler.rb +89 -0
- data/lib/talia_core/active_source_parts/rdf.rb +131 -0
- data/lib/talia_core/active_source_parts/sql_helper.rb +36 -0
- data/lib/talia_core/active_source_parts/xml/base_builder.rb +47 -0
- data/lib/talia_core/active_source_parts/xml/generic_reader.rb +363 -0
- data/lib/talia_core/active_source_parts/xml/rdf_builder.rb +88 -0
- data/lib/talia_core/active_source_parts/xml/source_builder.rb +73 -0
- data/lib/talia_core/active_source_parts/xml/source_reader.rb +20 -0
- data/lib/talia_core/agent.rb +14 -0
- data/lib/talia_core/background_jobs/job.rb +82 -0
- data/lib/talia_core/background_jobs/progress_job.rb +68 -0
- data/lib/talia_core/collection.rb +13 -0
- data/lib/talia_core/data_types/data_loader.rb +92 -0
- data/lib/talia_core/data_types/data_record.rb +105 -0
- data/lib/talia_core/data_types/delayed_copier.rb +76 -0
- data/lib/talia_core/data_types/file_record.rb +59 -0
- data/lib/talia_core/data_types/file_store.rb +306 -0
- data/lib/talia_core/data_types/iip_data.rb +153 -0
- data/lib/talia_core/data_types/iip_loader.rb +127 -0
- data/lib/talia_core/data_types/image_data.rb +32 -0
- data/lib/talia_core/data_types/media_link.rb +19 -0
- data/lib/talia_core/data_types/mime_mapping.rb +45 -0
- data/lib/talia_core/data_types/path_helpers.rb +77 -0
- data/lib/talia_core/data_types/pdf_data.rb +42 -0
- data/lib/talia_core/data_types/simple_text.rb +36 -0
- data/lib/talia_core/data_types/temp_file_handling.rb +85 -0
- data/lib/talia_core/data_types/xml_data.rb +169 -0
- data/lib/talia_core/dc_resource.rb +20 -0
- data/lib/talia_core/dummy_handler.rb +34 -0
- data/lib/talia_core/dummy_source.rb +20 -0
- data/lib/talia_core/errors.rb +25 -0
- data/lib/talia_core/initializer.rb +427 -0
- data/lib/talia_core/ordered_source.rb +228 -0
- data/lib/talia_core/rails_ext/actionpack/action_controller/record_identifier.rb +13 -0
- data/lib/talia_core/rails_ext/actionpack/action_controller.rb +1 -0
- data/lib/talia_core/rails_ext/actionpack.rb +1 -0
- data/lib/talia_core/rails_ext.rb +1 -0
- data/lib/talia_core/rdf_import.rb +90 -0
- data/lib/talia_core/rdf_resource.rb +159 -0
- data/lib/talia_core/semantic_collection_item.rb +93 -0
- data/lib/talia_core/semantic_collection_wrapper.rb +324 -0
- data/lib/talia_core/semantic_property.rb +7 -0
- data/lib/talia_core/semantic_relation.rb +67 -0
- data/lib/talia_core/source.rb +323 -0
- data/lib/talia_core/source_transfer_object.rb +38 -0
- data/lib/talia_core/workflow/base.rb +15 -0
- data/lib/talia_core/workflow/publication_workflow.rb +62 -0
- data/lib/talia_core/workflow.rb +300 -0
- data/lib/talia_core.rb +9 -0
- data/lib/talia_dependencies.rb +12 -0
- data/lib/talia_util/bar_progressor.rb +15 -0
- data/lib/talia_util/configuration/config_file.rb +48 -0
- data/lib/talia_util/configuration/database_config.rb +40 -0
- data/lib/talia_util/configuration/mysql_database_setup.rb +104 -0
- data/lib/talia_util/data_import.rb +91 -0
- data/lib/talia_util/image_conversions.rb +82 -0
- data/lib/talia_util/import_job_helper.rb +132 -0
- data/lib/talia_util/io_helper.rb +54 -0
- data/lib/talia_util/progressable.rb +38 -0
- data/lib/talia_util/progressbar.rb +236 -0
- data/lib/talia_util/rdf_update.rb +80 -0
- data/lib/talia_util/some_sigla.xml +1960 -0
- data/lib/talia_util/test_helpers.rb +151 -0
- data/lib/talia_util/util.rb +226 -0
- data/lib/talia_util/yaml_import.rb +80 -0
- data/lib/talia_util.rb +13 -0
- data/lib/user.rb +116 -0
- data/lib/version.rb +15 -0
- data/test/core_ext/string_test.rb +11 -0
- data/test/custom_template_test.rb +8 -0
- data/test/talia_core/active_source_predicate_test.rb +54 -0
- data/test/talia_core/active_source_rdf_test.rb +89 -0
- data/test/talia_core/active_source_test.rb +631 -0
- data/test/talia_core/data_types/data_loader_test.rb +123 -0
- data/test/talia_core/data_types/data_record_test.rb +40 -0
- data/test/talia_core/data_types/file_record_test.rb +171 -0
- data/test/talia_core/data_types/iip_data_test.rb +130 -0
- data/test/talia_core/data_types/image_data_test.rb +88 -0
- data/test/talia_core/data_types/pdf_data_test.rb +68 -0
- data/test/talia_core/data_types/xml_data_test.rb +134 -0
- data/test/talia_core/generic_xml_test.rb +83 -0
- data/test/talia_core/initializer_test.rb +36 -0
- data/test/talia_core/ordered_source_test.rb +398 -0
- data/test/talia_core/rdf_resource_test.rb +115 -0
- data/test/talia_core/semantic_collection_item_test.rb +129 -0
- data/test/talia_core/source_reader_test.rb +33 -0
- data/test/talia_core/source_test.rb +484 -0
- data/test/talia_core/source_transfer_object_test.rb +24 -0
- data/test/talia_core/workflow/publication_workflow_test.rb +242 -0
- data/test/talia_core/workflow/user_class_for_workflow.rb +35 -0
- data/test/talia_core/workflow/workflow_base_test.rb +21 -0
- data/test/talia_core/workflow_test.rb +19 -0
- data/test/talia_util/import_job_helper_test.rb +46 -0
- data/test/test_helper.rb +68 -0
- metadata +262 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
module TaliaCore
|
|
2
|
+
class SemanticRelation < ActiveRecord::Base
|
|
3
|
+
belongs_to :subject, :class_name => 'ActiveSource'
|
|
4
|
+
belongs_to :object, :polymorphic => true
|
|
5
|
+
before_destroy :discard_property
|
|
6
|
+
|
|
7
|
+
# Returns true if the Relation matches the given predicate URI (and value,
|
|
8
|
+
# if given)
|
|
9
|
+
def matches?(predicate, value = nil)
|
|
10
|
+
if(value)
|
|
11
|
+
if(value.is_a?(ActiveSource) || value.is_a?(SemanticProperty))
|
|
12
|
+
(predicate_uri == predicate.to_s) && (value == object)
|
|
13
|
+
else
|
|
14
|
+
return false unless(object.is_a?(SemanticProperty))
|
|
15
|
+
(predicate_uri == predicate.to_s) && (object.value == value)
|
|
16
|
+
end
|
|
17
|
+
else
|
|
18
|
+
predicate_uri == predicate.to_s
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class << self
|
|
23
|
+
|
|
24
|
+
# Retrieve "fat" relations for the given source and property
|
|
25
|
+
def find_fat_relations(source, predicate)
|
|
26
|
+
joins = ActiveSource.sources_join
|
|
27
|
+
joins << ActiveSource.props_join
|
|
28
|
+
relations = SemanticRelation.find(:all, :conditions => {
|
|
29
|
+
:subject_id => source.id,
|
|
30
|
+
:predicate_uri => predicate
|
|
31
|
+
},
|
|
32
|
+
:joins => joins,
|
|
33
|
+
:select => fat_record_select
|
|
34
|
+
)
|
|
35
|
+
relations
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# For selecting "fat" records on the semantic properties
|
|
39
|
+
def fat_record_select
|
|
40
|
+
@select ||= begin
|
|
41
|
+
select = 'semantic_relations.id AS id, semantic_relations.created_at AS created_at, '
|
|
42
|
+
select << 'semantic_relations.updated_at AS updated_at, '
|
|
43
|
+
select << 'semantic_relations.rel_order AS rel_order,'
|
|
44
|
+
select << 'object_id, object_type, subject_id, predicate_uri, '
|
|
45
|
+
select << 'obj_props.created_at AS property_created_at, '
|
|
46
|
+
select << 'obj_props.updated_at AS property_updated_at, '
|
|
47
|
+
select << 'obj_props.value AS property_value, '
|
|
48
|
+
select << 'obj_sources.created_at AS object_created_at, '
|
|
49
|
+
select << 'obj_sources.updated_at AS object_updated_at, obj_sources.type AS object_realtype, '
|
|
50
|
+
select << 'obj_sources.uri AS object_uri'
|
|
51
|
+
select
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
# Discards the "value" property that belongs to this source
|
|
60
|
+
def discard_property
|
|
61
|
+
if(object.is_a?(SemanticProperty))
|
|
62
|
+
SemanticProperty.delete(object.id)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
# require 'objectproperties' # Includes the class methods for the object_properties
|
|
2
|
+
require 'source_transfer_object'
|
|
3
|
+
require 'active_rdf'
|
|
4
|
+
require 'semantic_naming'
|
|
5
|
+
require 'dummy_handler'
|
|
6
|
+
require 'rdf_resource'
|
|
7
|
+
|
|
8
|
+
module TaliaCore
|
|
9
|
+
|
|
10
|
+
# This represents a Source in the Talia core system.
|
|
11
|
+
#
|
|
12
|
+
# Since data for the Source exists both in the database and in the RDF store, the
|
|
13
|
+
# handling/saving of data is a bit peculiar at the moment (subject to change in the future):
|
|
14
|
+
#
|
|
15
|
+
# * When a new Source is created, no data is saved
|
|
16
|
+
# * RDF properties *cannot* be written until the Source has been saved for the first time
|
|
17
|
+
# * Database properties are *only* written when the save method is called
|
|
18
|
+
# * RDF properties are written immediately when they are assigned
|
|
19
|
+
# * To ensure that the data is written, the save method should be called as
|
|
20
|
+
# necessary.
|
|
21
|
+
class Source < ActiveSource
|
|
22
|
+
|
|
23
|
+
has_one :workflow, :class_name => 'TaliaCore::Workflow::Base', :dependent => :destroy
|
|
24
|
+
|
|
25
|
+
# The uri will be wrapped into an object
|
|
26
|
+
def uri
|
|
27
|
+
N::URI.new(self[:uri])
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Indicates if this source belongs to the local store
|
|
31
|
+
def local
|
|
32
|
+
uri.local?
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
alias_method :ar_update_attributes, :update_attributes
|
|
36
|
+
# Wrapping for <tt>ActiveRecord</tt> <tt>update_attributes</tt>.
|
|
37
|
+
def update_attributes(attributes)
|
|
38
|
+
attributes, rdf_attributes = extract_attributes!(attributes)
|
|
39
|
+
rdf_attributes.each do |k,v|
|
|
40
|
+
send(k + "=", v)
|
|
41
|
+
send('save_' + k)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Shortcut for assigning the primary_source status
|
|
46
|
+
def primary_source=(value)
|
|
47
|
+
value = value ? 'true' : 'false'
|
|
48
|
+
predicate_set(:talia, :primary_source, value)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Indicates if the current source is considered "primary" in the local
|
|
52
|
+
# library
|
|
53
|
+
def primary_source
|
|
54
|
+
predicate(:talia, :primary_source) == true
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Searches for sources where <tt>property</tt> has one of the values given
|
|
58
|
+
# to this method. The result is a hash that contains one result list for
|
|
59
|
+
# each of the values, with the value as a key.
|
|
60
|
+
#
|
|
61
|
+
# This performs a find operation for each value, and the params passed
|
|
62
|
+
# to this method are added to the find parameters for each of those finds.
|
|
63
|
+
#
|
|
64
|
+
# *Example*
|
|
65
|
+
#
|
|
66
|
+
# # Returns all Sources that are of the RDFS type Class or Property. This
|
|
67
|
+
# # will return a hash with 2 lists (one for the Classes, and one for the
|
|
68
|
+
# # properties, and each list will be limited to 5 elements.
|
|
69
|
+
# Source.groups_by_property(N::RDF::type, [N::RDFS.Class, N::RDFS.Property], :limit => 5)
|
|
70
|
+
def self.groups_by_property(property, values, params = {})
|
|
71
|
+
# First create the joins
|
|
72
|
+
joins = 'LEFT JOIN semantic_relations ON semantic_relations.subject_id = active_sources.id '
|
|
73
|
+
joins << "LEFT JOIN active_sources AS t_sources ON semantic_relations.object_id = t_sources.id AND semantic_relations.object_type = 'TaliaCore::ActiveSource' "
|
|
74
|
+
joins << "LEFT JOIN semantic_properties ON semantic_relations.object_id = semantic_properties.id AND semantic_relations.object_type = 'TaliaCore::SemanticProperty' "
|
|
75
|
+
|
|
76
|
+
property = uri_string_for(property)
|
|
77
|
+
results = {}
|
|
78
|
+
for val in values
|
|
79
|
+
find(:all )
|
|
80
|
+
val_str = uri_string_for(val)
|
|
81
|
+
find_parms = params.merge(
|
|
82
|
+
:conditions => ['semantic_properties.value = ? OR t_sources.uri = ?', val_str, val_str],
|
|
83
|
+
:joins => joins
|
|
84
|
+
)
|
|
85
|
+
results[val] = find(:all, find_parms)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
results
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Try to find a source for the given uri, if not exists it instantiate
|
|
92
|
+
# a new one, combining the N::LOCAL namespace and the given local name
|
|
93
|
+
#
|
|
94
|
+
# Example:
|
|
95
|
+
# ActiveSource.find_or_instantiate_by_uri('http://talia.org/existent')
|
|
96
|
+
# # => #<TaliaCore::ActiveSource id: 1, uri: "http://talia.org/existent">
|
|
97
|
+
#
|
|
98
|
+
# ActiveSource.find_or_instantiate_by_uri('http://talia.org/unexistent', 'Foo Bar')
|
|
99
|
+
# # => #<TaliaCore::ActiveSource id: nil, uri: "http://talia.org/Foo_Bar">
|
|
100
|
+
def self.find_or_instantiate_by_uri(uri, local_name)
|
|
101
|
+
result = find_by_uri(uri)
|
|
102
|
+
result ||= self.new(N::LOCAL.to_s + local_name.to_permalink)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Find a list of sources which contains the given token inside the local name.
|
|
106
|
+
# This means that the namespace it will be excluded.
|
|
107
|
+
#
|
|
108
|
+
# Sources in system:
|
|
109
|
+
# * http://talia.org/one
|
|
110
|
+
# * http://talia.org/two
|
|
111
|
+
#
|
|
112
|
+
# Source.find_by_uri_token('a') # => [ ]
|
|
113
|
+
# Source.find_by_uri_token('o') # => [ 'http://talia.org/one', 'http://talia.org/two' ]
|
|
114
|
+
#
|
|
115
|
+
# NOTE: It internally use a MySQL function, as sql condition, to find the local name of the uri.
|
|
116
|
+
def self.find_by_uri_token(token, options = {})
|
|
117
|
+
find(:all, {
|
|
118
|
+
:conditions => [ "LOWER(SUBSTRING_INDEX(uri, '/', -1)) LIKE ?", '%' + token.downcase + '%' ],
|
|
119
|
+
:select => :uri,
|
|
120
|
+
:order => "uri ASC",
|
|
121
|
+
:limit => 10 }.merge!(options))
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Find the fist Source that matches the given URI.
|
|
125
|
+
# It's useful for admin pane, because users visit:
|
|
126
|
+
# /admin/sources/<source_id>/edit
|
|
127
|
+
# but that information is not enough, since we store
|
|
128
|
+
# into the database the whole reference as URI:
|
|
129
|
+
# http://localnode.org/av_media_sources/source_id
|
|
130
|
+
def self.find_by_partial_uri(id)
|
|
131
|
+
find(:first, :conditions => ["uri LIKE ?", '%' + id + '%'])
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Return an hash of direct predicates, grouped by namespace.
|
|
135
|
+
def grouped_direct_predicates
|
|
136
|
+
#TODO should it be memoized?
|
|
137
|
+
direct_predicates.inject({}) do |result, predicate|
|
|
138
|
+
predicates = self[predicate].collect { |p| SourceTransferObject.new(p.to_s) }
|
|
139
|
+
namespace = predicate.namespace.to_s
|
|
140
|
+
result[namespace] ||= {}
|
|
141
|
+
result[namespace][predicate.local_name] ||= []
|
|
142
|
+
result[namespace][predicate.local_name] << predicates
|
|
143
|
+
result
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def predicate_objects(namespace, name) #:nodoc:
|
|
148
|
+
predicate(namespace, name).values.flatten.map(&:to_s)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Check if the current source is related with the given rdf object (triple endpoint).
|
|
152
|
+
def associated?(namespace, name, stringified_predicate)
|
|
153
|
+
predicate_objects(namespace, name).include?(stringified_predicate)
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# Check if a predicate is changed.
|
|
157
|
+
def predicate_changed?(namespace, name, objects)
|
|
158
|
+
not predicate_objects(namespace, name).eql?(objects.map(&:to_s))
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
attr_reader :predicates_attributes
|
|
162
|
+
def predicates_attributes=(predicates_attributes)
|
|
163
|
+
@predicates_attributes = predicates_attributes.collect do |attributes_hash|
|
|
164
|
+
attributes_hash['object'] = instantiate_source_or_rdf_object(attributes_hash)
|
|
165
|
+
attributes_hash
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Return an hash of new predicated attributes, grouped by namespace.
|
|
170
|
+
def grouped_predicates_attributes
|
|
171
|
+
@grouped_predicates_attributes ||= predicates_attributes.inject({}) do |result, predicate|
|
|
172
|
+
namespace, name = predicate['namespace'], predicate['name']
|
|
173
|
+
predicate = SourceTransferObject.new(predicate['titleized'])
|
|
174
|
+
result[namespace] ||= {}
|
|
175
|
+
result[namespace][name] ||= []
|
|
176
|
+
result[namespace][name] << predicate
|
|
177
|
+
result
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# Save, associate/disassociate given predicates attributes.
|
|
182
|
+
def save_predicates_attributes
|
|
183
|
+
each_predicate do |namespace, name, objects|
|
|
184
|
+
objects.each { |object| object.save if object.is_a?(Source) && object.new_record? }
|
|
185
|
+
self.predicate_replace(namespace, name, objects.to_s) if predicate_changed?(namespace, name, objects)
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
# Returns an array of labels for this source. You may give the name of the
|
|
191
|
+
# property that is used as a label, by default it uses rdf:label(s). If
|
|
192
|
+
# the given property is not set, it will return the local part of this
|
|
193
|
+
# Source's URI.
|
|
194
|
+
#
|
|
195
|
+
# In any case, the result will always be an Array with at least one elment.
|
|
196
|
+
def labels(type = N::RDFS::label)
|
|
197
|
+
labels = get_attribute(type)
|
|
198
|
+
unless(labels && labels.size > 0)
|
|
199
|
+
labels = [uri.local_name]
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
labels
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# This returns a single label of the given type. (If multiple labels
|
|
206
|
+
# exist in the RDF, just the first is returned.)
|
|
207
|
+
def label(type = N::RDFS::label)
|
|
208
|
+
labels(type)[0]
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
# Return the titleized uri local name.
|
|
212
|
+
#
|
|
213
|
+
# http://localnode.org/source # => Source
|
|
214
|
+
def titleized
|
|
215
|
+
self.uri.local_name.titleize
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
# Equality test. Two sources are equal if they have the same URI
|
|
219
|
+
def ==(value)
|
|
220
|
+
value.is_a?(Source) && (value.uri == uri)
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def normalize_uri(uri, label = '')
|
|
224
|
+
self.class.normalize_uri(uri, label)
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
protected
|
|
228
|
+
|
|
229
|
+
# Separates given attributes distinguishing between ActiveSource and RDF.
|
|
230
|
+
def extract_attributes!(attributes)
|
|
231
|
+
active_source_attributes = attributes.inject({}) do |active_source_attributes, column_values|
|
|
232
|
+
active_source_attributes[column_values.first] = attributes.delete(column_values.first) if self.class.column_names.include? column_values.first
|
|
233
|
+
active_source_attributes
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
[ active_source_attributes, attributes ]
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
# Look at the given attributes and choose to instantiate
|
|
240
|
+
# a Source or a RDF object (triple endpoint).
|
|
241
|
+
#
|
|
242
|
+
# Cases:
|
|
243
|
+
# Homer Simpson
|
|
244
|
+
# # => Should instantiate a source with
|
|
245
|
+
# http://localnode.org/Homer_Simpson using N::LOCAL constant.
|
|
246
|
+
#
|
|
247
|
+
# "Homer Simpson"
|
|
248
|
+
# # => Should return the string itself, without the double quoting
|
|
249
|
+
# in order to add it directly to the RDF triple.
|
|
250
|
+
#
|
|
251
|
+
# http://springfield.org/Homer_Simpson
|
|
252
|
+
# # => Should instantiate a source with the given uri
|
|
253
|
+
def instantiate_source_or_rdf_object(attributes)
|
|
254
|
+
name_or_uri = attributes['titleized']
|
|
255
|
+
if /^\"[\w\s\d]+\"$/.match name_or_uri
|
|
256
|
+
name_or_uri[1..-2]
|
|
257
|
+
elsif attributes['uri'].blank? and attributes['source'].blank?
|
|
258
|
+
name_or_uri
|
|
259
|
+
elsif /^http:\/\//.match name_or_uri
|
|
260
|
+
Source.new(name_or_uri)
|
|
261
|
+
else
|
|
262
|
+
Source.find_or_instantiate_by_uri(normalize_uri(attributes['uri']), name_or_uri)
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
# Iterate through grouped_predicates_attributes, yielding the given code.
|
|
267
|
+
def each_predicate(&block)
|
|
268
|
+
grouped_predicates_attributes.each do |namespace, predicates|
|
|
269
|
+
predicates.each do |predicate, objects|
|
|
270
|
+
block.call(namespace, predicate, objects.flatten)
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
# Class methods
|
|
276
|
+
class << self
|
|
277
|
+
|
|
278
|
+
# Normalize the given uri.
|
|
279
|
+
#
|
|
280
|
+
# Example:
|
|
281
|
+
# normalize_uri('Lucca') # => http://www.talia.discovery-project.org/sources/Lucca
|
|
282
|
+
# normalize_uri('http://xmlns.com/foaf/0.1/Group') # => http://xmlns.com/foaf/0.1/Group
|
|
283
|
+
# normalize_uri('http://www.talia.discovery-project.org/sources/Lucca')
|
|
284
|
+
# # => http://www.talia.discovery-project.org/sources/Lucca
|
|
285
|
+
def normalize_uri(uri, label = '')
|
|
286
|
+
uri = N::LOCAL if uri.blank?
|
|
287
|
+
uri = N::LOCAL+label.gsub(' ', '_') if uri == N::LOCAL.to_s
|
|
288
|
+
uri.to_s
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
# End of class methods
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
# Missing methods: This just check if the given method corresponds to a
|
|
297
|
+
# registered namespace. If yes, this will return a "dummy" handler that
|
|
298
|
+
# allows access to properties.
|
|
299
|
+
#
|
|
300
|
+
# This will allow invocations as namespace::name
|
|
301
|
+
def method_missing(method_name, *args)
|
|
302
|
+
# TODO: Add permission checking for all updates to the model
|
|
303
|
+
# TODO: Add permission checking for read access?
|
|
304
|
+
|
|
305
|
+
update = method_name.to_s[-1..-1] == '='
|
|
306
|
+
|
|
307
|
+
shortcut = if update
|
|
308
|
+
method_name.to_s[0..-2]
|
|
309
|
+
else
|
|
310
|
+
method_name.to_s
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
# Otherwise, check for the RDF predicate
|
|
314
|
+
registered = N::URI[shortcut.to_s]
|
|
315
|
+
|
|
316
|
+
return super(method_name, *args) unless(registered) # normal handler if not a registered uri
|
|
317
|
+
raise(ArgumentError, "Must give a namspace as argument") unless(registered.is_a?(N::Namespace))
|
|
318
|
+
|
|
319
|
+
DummyHandler.new(registered, self)
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
end
|
|
323
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module TaliaCore #:nodoc:
|
|
2
|
+
# Transfer Object Pattern implementation.
|
|
3
|
+
# It's required by source administration panel, in order to normalize
|
|
4
|
+
# the values transportation between view and controller layers.
|
|
5
|
+
#
|
|
6
|
+
# RDF objects (triple endpoint), could be a Source or a String.
|
|
7
|
+
#
|
|
8
|
+
# http://java.sun.com/blueprints/corej2eepatterns/Patterns/TransferObject.html
|
|
9
|
+
# http://java.sun.com/blueprints/patterns/TransferObject.html
|
|
10
|
+
class SourceTransferObject
|
|
11
|
+
attr_reader :uri
|
|
12
|
+
|
|
13
|
+
def initialize(name_or_uri) #:nodoc:
|
|
14
|
+
@uri, @name = if /http:\/\//.match name_or_uri
|
|
15
|
+
uri = N::URI.new(name_or_uri)
|
|
16
|
+
[uri, uri.local_name]
|
|
17
|
+
else
|
|
18
|
+
[nil, name_or_uri]
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def id
|
|
23
|
+
@name
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def source?
|
|
27
|
+
!uri.blank?
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def titleized #:nodoc:
|
|
31
|
+
@name.titleize
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def to_s #:nodoc:
|
|
35
|
+
(uri || @name).to_s
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require File.join('talia_core', 'workflow')
|
|
2
|
+
|
|
3
|
+
module TaliaCore
|
|
4
|
+
module Workflow
|
|
5
|
+
# Workflow Record class.
|
|
6
|
+
class Base < ActiveRecord::Base
|
|
7
|
+
|
|
8
|
+
set_table_name 'workflows'
|
|
9
|
+
belongs_to :source
|
|
10
|
+
|
|
11
|
+
include TaliaCore::Workflow
|
|
12
|
+
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
module TaliaCore
|
|
2
|
+
|
|
3
|
+
module Workflow
|
|
4
|
+
|
|
5
|
+
class PublicationWorkflow < Base
|
|
6
|
+
|
|
7
|
+
workflow_machine :initial => :submitted, :initial_properties => {:vote => 0}, :column => 'state', :properties => 'arguments'
|
|
8
|
+
|
|
9
|
+
state :submitted
|
|
10
|
+
state :accepted
|
|
11
|
+
state :rejected
|
|
12
|
+
state :published
|
|
13
|
+
|
|
14
|
+
event :vote, :require_role => :reviewer do
|
|
15
|
+
transitions :from => :submitted, :to => :submitted,
|
|
16
|
+
:guard => :is_submittable?,
|
|
17
|
+
:on_transition => :vote
|
|
18
|
+
transitions :from => :submitted, :to => :accepted,
|
|
19
|
+
:guard => :is_acceptable?,
|
|
20
|
+
:on_transition => :vote
|
|
21
|
+
transitions :from => :submitted, :to => :rejected,
|
|
22
|
+
:guard => :is_rejectable?,
|
|
23
|
+
:on_transition => :vote
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
event :direct_publish, :require_role => :admin do
|
|
27
|
+
transitions :from => :submitted, :to => :published
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
event :publish, :require_role => :editor do
|
|
31
|
+
transitions :from => :accepted, :to => :published
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
# vote method is called by transition
|
|
37
|
+
#
|
|
38
|
+
# Syntax example:
|
|
39
|
+
# record.vote!(my_user, 10)
|
|
40
|
+
def vote(value)
|
|
41
|
+
args = self.state_properties
|
|
42
|
+
args[:vote] += value[0]
|
|
43
|
+
self.state_properties=args
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def is_submittable?(value)
|
|
47
|
+
vote = self.state_properties[:vote] + value[0]
|
|
48
|
+
(vote >= 0) && (vote <= 5)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def is_acceptable?(value)
|
|
52
|
+
(self.state_properties[:vote] + value[0]) > 5
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def is_rejectable?(value)
|
|
56
|
+
(self.state_properties[:vote] + value[0]) < 0
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
end
|
|
62
|
+
end
|