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