factoid 0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/COPYING +121 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +116 -0
- data/Rakefile +6 -0
- data/factoid.gemspec +31 -0
- data/lib/factoid.rb +4 -0
- data/lib/factoid/entitoid.rb +55 -0
- data/lib/factoid/entitoid_ref.rb +33 -0
- data/lib/factoid/factoid.rb +57 -0
- data/lib/factoid/source.rb +50 -0
- data/lib/factoid/value.rb +85 -0
- data/lib/factoid/version.rb +6 -0
- data/lib/factoid/xml.rb +91 -0
- data/spec/factoid/entitoid_spec.rb +56 -0
- data/spec/factoid/factoid_spec.rb +66 -0
- data/spec/fixtures/chopin.xml +49 -0
- data/spec/fixtures/zelazowa-wola +19 -0
- data/spec/fixtures/zelazowa-wola.xml +19 -0
- data/spec/spec_helpers.rb +3 -0
- metadata +142 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9e01d537e7fcee79c2f5f1d17096672fda9c17ff
|
4
|
+
data.tar.gz: ccbf896597df8d4ee9c2adf618fcefec774f970f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 97325418c38331595952ce5d20ba685951f97af709ed528ded4ceb7751e16d92bbff607d9905a316f990c17e6918058eafe8a6fac40265b5686aff2290528f67
|
7
|
+
data.tar.gz: c00e48f039b7d5e507f3335078d493206874f8a8bfc7d4500342fe10f9ad6ae4a0b94e930c3d166515602c2f7833b4d989b5cf2121f6efbbf1728608f3a2b383
|
data/.gitignore
ADDED
data/COPYING
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
Creative Commons Legal Code
|
2
|
+
|
3
|
+
CC0 1.0 Universal
|
4
|
+
|
5
|
+
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
6
|
+
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
7
|
+
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
8
|
+
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
9
|
+
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
10
|
+
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
11
|
+
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
12
|
+
HEREUNDER.
|
13
|
+
|
14
|
+
Statement of Purpose
|
15
|
+
|
16
|
+
The laws of most jurisdictions throughout the world automatically confer
|
17
|
+
exclusive Copyright and Related Rights (defined below) upon the creator
|
18
|
+
and subsequent owner(s) (each and all, an "owner") of an original work of
|
19
|
+
authorship and/or a database (each, a "Work").
|
20
|
+
|
21
|
+
Certain owners wish to permanently relinquish those rights to a Work for
|
22
|
+
the purpose of contributing to a commons of creative, cultural and
|
23
|
+
scientific works ("Commons") that the public can reliably and without fear
|
24
|
+
of later claims of infringement build upon, modify, incorporate in other
|
25
|
+
works, reuse and redistribute as freely as possible in any form whatsoever
|
26
|
+
and for any purposes, including without limitation commercial purposes.
|
27
|
+
These owners may contribute to the Commons to promote the ideal of a free
|
28
|
+
culture and the further production of creative, cultural and scientific
|
29
|
+
works, or to gain reputation or greater distribution for their Work in
|
30
|
+
part through the use and efforts of others.
|
31
|
+
|
32
|
+
For these and/or other purposes and motivations, and without any
|
33
|
+
expectation of additional consideration or compensation, the person
|
34
|
+
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
|
35
|
+
is an owner of Copyright and Related Rights in the Work, voluntarily
|
36
|
+
elects to apply CC0 to the Work and publicly distribute the Work under its
|
37
|
+
terms, with knowledge of his or her Copyright and Related Rights in the
|
38
|
+
Work and the meaning and intended legal effect of CC0 on those rights.
|
39
|
+
|
40
|
+
1. Copyright and Related Rights. A Work made available under CC0 may be
|
41
|
+
protected by copyright and related or neighboring rights ("Copyright and
|
42
|
+
Related Rights"). Copyright and Related Rights include, but are not
|
43
|
+
limited to, the following:
|
44
|
+
|
45
|
+
i. the right to reproduce, adapt, distribute, perform, display,
|
46
|
+
communicate, and translate a Work;
|
47
|
+
ii. moral rights retained by the original author(s) and/or performer(s);
|
48
|
+
iii. publicity and privacy rights pertaining to a person's image or
|
49
|
+
likeness depicted in a Work;
|
50
|
+
iv. rights protecting against unfair competition in regards to a Work,
|
51
|
+
subject to the limitations in paragraph 4(a), below;
|
52
|
+
v. rights protecting the extraction, dissemination, use and reuse of data
|
53
|
+
in a Work;
|
54
|
+
vi. database rights (such as those arising under Directive 96/9/EC of the
|
55
|
+
European Parliament and of the Council of 11 March 1996 on the legal
|
56
|
+
protection of databases, and under any national implementation
|
57
|
+
thereof, including any amended or successor version of such
|
58
|
+
directive); and
|
59
|
+
vii. other similar, equivalent or corresponding rights throughout the
|
60
|
+
world based on applicable law or treaty, and any national
|
61
|
+
implementations thereof.
|
62
|
+
|
63
|
+
2. Waiver. To the greatest extent permitted by, but not in contravention
|
64
|
+
of, applicable law, Affirmer hereby overtly, fully, permanently,
|
65
|
+
irrevocably and unconditionally waives, abandons, and surrenders all of
|
66
|
+
Affirmer's Copyright and Related Rights and associated claims and causes
|
67
|
+
of action, whether now known or unknown (including existing as well as
|
68
|
+
future claims and causes of action), in the Work (i) in all territories
|
69
|
+
worldwide, (ii) for the maximum duration provided by applicable law or
|
70
|
+
treaty (including future time extensions), (iii) in any current or future
|
71
|
+
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
72
|
+
including without limitation commercial, advertising or promotional
|
73
|
+
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
|
74
|
+
member of the public at large and to the detriment of Affirmer's heirs and
|
75
|
+
successors, fully intending that such Waiver shall not be subject to
|
76
|
+
revocation, rescission, cancellation, termination, or any other legal or
|
77
|
+
equitable action to disrupt the quiet enjoyment of the Work by the public
|
78
|
+
as contemplated by Affirmer's express Statement of Purpose.
|
79
|
+
|
80
|
+
3. Public License Fallback. Should any part of the Waiver for any reason
|
81
|
+
be judged legally invalid or ineffective under applicable law, then the
|
82
|
+
Waiver shall be preserved to the maximum extent permitted taking into
|
83
|
+
account Affirmer's express Statement of Purpose. In addition, to the
|
84
|
+
extent the Waiver is so judged Affirmer hereby grants to each affected
|
85
|
+
person a royalty-free, non transferable, non sublicensable, non exclusive,
|
86
|
+
irrevocable and unconditional license to exercise Affirmer's Copyright and
|
87
|
+
Related Rights in the Work (i) in all territories worldwide, (ii) for the
|
88
|
+
maximum duration provided by applicable law or treaty (including future
|
89
|
+
time extensions), (iii) in any current or future medium and for any number
|
90
|
+
of copies, and (iv) for any purpose whatsoever, including without
|
91
|
+
limitation commercial, advertising or promotional purposes (the
|
92
|
+
"License"). The License shall be deemed effective as of the date CC0 was
|
93
|
+
applied by Affirmer to the Work. Should any part of the License for any
|
94
|
+
reason be judged legally invalid or ineffective under applicable law, such
|
95
|
+
partial invalidity or ineffectiveness shall not invalidate the remainder
|
96
|
+
of the License, and in such case Affirmer hereby affirms that he or she
|
97
|
+
will not (i) exercise any of his or her remaining Copyright and Related
|
98
|
+
Rights in the Work or (ii) assert any associated claims and causes of
|
99
|
+
action with respect to the Work, in either case contrary to Affirmer's
|
100
|
+
express Statement of Purpose.
|
101
|
+
|
102
|
+
4. Limitations and Disclaimers.
|
103
|
+
|
104
|
+
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
105
|
+
surrendered, licensed or otherwise affected by this document.
|
106
|
+
b. Affirmer offers the Work as-is and makes no representations or
|
107
|
+
warranties of any kind concerning the Work, express, implied,
|
108
|
+
statutory or otherwise, including without limitation warranties of
|
109
|
+
title, merchantability, fitness for a particular purpose, non
|
110
|
+
infringement, or the absence of latent or other defects, accuracy, or
|
111
|
+
the present or absence of errors, whether or not discoverable, all to
|
112
|
+
the greatest extent permissible under applicable law.
|
113
|
+
c. Affirmer disclaims responsibility for clearing rights of other persons
|
114
|
+
that may apply to the Work or any use thereof, including without
|
115
|
+
limitation any person's Copyright and Related Rights in the Work.
|
116
|
+
Further, Affirmer disclaims responsibility for obtaining any necessary
|
117
|
+
consents, permissions or other rights required for any use of the
|
118
|
+
Work.
|
119
|
+
d. Affirmer understands and acknowledges that Creative Commons is not a
|
120
|
+
party to this document and has no duty or obligation with respect to
|
121
|
+
this CC0 or use of the Work.
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Gioele Barabucci
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
factoid: read, manipulate and save factoids
|
2
|
+
===========================================
|
3
|
+
|
4
|
+
`factoid` is a Ruby library to manipulate _factoids_ and _entitoids_
|
5
|
+
inside Ruby applications without touching the their XML representations.
|
6
|
+
|
7
|
+
|
8
|
+
What is a factoid?
|
9
|
+
------------------
|
10
|
+
|
11
|
+
Factoids and Entitoids are representations of pieces of information
|
12
|
+
about a certain entity. These representations not only store the
|
13
|
+
information itself, but also keep track of provenance (who stated
|
14
|
+
something, where, when) and context (under which assumption is a
|
15
|
+
certain piece of information valid?). Using factoids one can store
|
16
|
+
and manage different values for the same property of an entity.
|
17
|
+
|
18
|
+
For example, instead of just storing that
|
19
|
+
|
20
|
+
> composer with ID 14 has property 'name' = 'Frédéric Chopin'
|
21
|
+
|
22
|
+
using factoids one can say
|
23
|
+
|
24
|
+
> there is a composer with ID 14
|
25
|
+
|
26
|
+
> Wikipedia says that composer#14 has
|
27
|
+
> * a property 'name',
|
28
|
+
> * with context 'language' = 'fra',
|
29
|
+
> * and value 'Frédéric Chopin'.
|
30
|
+
|
31
|
+
> Book with ISBN 9780007351824 says that composer#14 has
|
32
|
+
> * a property 'name',
|
33
|
+
> * with context 'language' = 'pol',
|
34
|
+
> * and value 'Fryderyk Chopin'.
|
35
|
+
|
36
|
+
The name of composer 14 is then both _Frédéric Chopin_ and _Fryderyk
|
37
|
+
Chopin_ depending on the context.
|
38
|
+
|
39
|
+
Factoids and entitoids are described more in depth at
|
40
|
+
<http://svario.it/factoid>.
|
41
|
+
|
42
|
+
The `factoid` gem makes it possible to load and save factoids, to search
|
43
|
+
and select factoids that match certain patterns and to access complex
|
44
|
+
information in a simple way.
|
45
|
+
|
46
|
+
|
47
|
+
Examples
|
48
|
+
--------
|
49
|
+
|
50
|
+
c14 = Factoid::Entitoid.from_xml('composer14.xml')
|
51
|
+
|
52
|
+
puts "Known names:"
|
53
|
+
puts
|
54
|
+
c.factoids('name').each do |fact|
|
55
|
+
puts " #{fact.value} in #{fact.context['language']}"
|
56
|
+
puts " (from #{fact.sources})"
|
57
|
+
puts
|
58
|
+
end
|
59
|
+
|
60
|
+
# Known names:
|
61
|
+
#
|
62
|
+
# Frédéric Chopin in fra
|
63
|
+
# (from http://en.wikipedia.org/wiki/Frédéric_Chopin)
|
64
|
+
# Fryderyk Chopin in pol
|
65
|
+
# (from urn:isbn:9780007351824)
|
66
|
+
|
67
|
+
|
68
|
+
Requirements
|
69
|
+
------------
|
70
|
+
|
71
|
+
factoid is based on Nokogiri and uses Addressable to manage URIs.
|
72
|
+
|
73
|
+
|
74
|
+
Install
|
75
|
+
-------
|
76
|
+
|
77
|
+
Install the factoid gem using RubyGems
|
78
|
+
|
79
|
+
gem install factoid
|
80
|
+
|
81
|
+
or Bundler
|
82
|
+
|
83
|
+
# in Gemfile
|
84
|
+
gem 'factoid'
|
85
|
+
|
86
|
+
To use the factoid gem in your project, load it with
|
87
|
+
|
88
|
+
require 'factoid'
|
89
|
+
|
90
|
+
|
91
|
+
Author
|
92
|
+
------
|
93
|
+
|
94
|
+
* Gioele Barabucci <http://svario.it/gioele> (initial author)
|
95
|
+
|
96
|
+
|
97
|
+
Development
|
98
|
+
-----------
|
99
|
+
|
100
|
+
Code
|
101
|
+
: <http://svario.it/factoid/ruby> (redirects to GitHub)
|
102
|
+
|
103
|
+
Report issues
|
104
|
+
: <http://svario.it/factoid/ruby/issues>
|
105
|
+
|
106
|
+
Documentation
|
107
|
+
: <http://svario.it/factoid/ruby/docs>
|
108
|
+
|
109
|
+
|
110
|
+
License
|
111
|
+
-------
|
112
|
+
|
113
|
+
This is free software released into the public domain (CC0 license).
|
114
|
+
|
115
|
+
See the `COPYING` file or <http://creativecommons.org/publicdomain/zero/1.0/>
|
116
|
+
for more details.
|
data/Rakefile
ADDED
data/factoid.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# This is free software released into the public domain (CC0 license).
|
2
|
+
|
3
|
+
|
4
|
+
lib = File.expand_path('../lib', __FILE__)
|
5
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
6
|
+
|
7
|
+
require 'factoid/version'
|
8
|
+
|
9
|
+
Gem::Specification.new do |spec|
|
10
|
+
spec.name = "factoid"
|
11
|
+
spec.version = Factoid::VERSION
|
12
|
+
spec.authors = ["Gioele Barabucci"]
|
13
|
+
spec.email = ["gioele@svario.it"]
|
14
|
+
spec.summary = "factoid is a Ruby library to manipulate factoids " +
|
15
|
+
"entitoids inside Ruby applications without " +
|
16
|
+
"touching the their XML representations."
|
17
|
+
spec.homepage = 'http://svario.it/factoid/ruby'
|
18
|
+
spec.license = 'CC0'
|
19
|
+
|
20
|
+
spec.files = `git ls-files`.split($/)
|
21
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
22
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
23
|
+
spec.require_paths = ['lib']
|
24
|
+
|
25
|
+
spec.add_dependency 'nokogiri'
|
26
|
+
spec.add_dependency 'addressable'
|
27
|
+
|
28
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
29
|
+
spec.add_development_dependency 'rake'
|
30
|
+
spec.add_development_dependency 'rspec'
|
31
|
+
end
|
data/lib/factoid.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# This is free software released into the public domain (CC0 license).
|
2
|
+
|
3
|
+
|
4
|
+
module Factoid
|
5
|
+
class Entitoid
|
6
|
+
def initialize(uuid)
|
7
|
+
@uuid = uuid
|
8
|
+
@factoids = []
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :uuid
|
12
|
+
|
13
|
+
def add_factoid(factoid)
|
14
|
+
@factoids << factoid
|
15
|
+
end
|
16
|
+
|
17
|
+
def factoids(name, context = {})
|
18
|
+
if name == :all
|
19
|
+
return @factoids
|
20
|
+
end
|
21
|
+
|
22
|
+
matching = @factoids.select { |f| f.match?(name, context) }
|
23
|
+
return matching
|
24
|
+
end
|
25
|
+
|
26
|
+
def value(name, context = {})
|
27
|
+
f = factoids(name, context)
|
28
|
+
|
29
|
+
if f.empty?
|
30
|
+
raise "Cannot return value, no factoid matches name: '#{name}', context: #{context}"
|
31
|
+
end
|
32
|
+
|
33
|
+
if f.count > 1
|
34
|
+
raise "Cannot return value, too many factoids match name: '#{name}', context: #{context}"
|
35
|
+
end
|
36
|
+
|
37
|
+
return f.first.value
|
38
|
+
end
|
39
|
+
|
40
|
+
def eql?(other)
|
41
|
+
if other.equal?(self)
|
42
|
+
return true
|
43
|
+
end
|
44
|
+
|
45
|
+
if other.class != self.class
|
46
|
+
return false
|
47
|
+
end
|
48
|
+
|
49
|
+
f = factoids(:all)
|
50
|
+
other_f = other.factoids(:all)
|
51
|
+
|
52
|
+
return f.eql?(other_f)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# This is free software released into the public domain (CC0 license).
|
2
|
+
|
3
|
+
|
4
|
+
require 'addressable/uri'
|
5
|
+
|
6
|
+
require 'factoid/entitoid'
|
7
|
+
|
8
|
+
module Factoid
|
9
|
+
class EntitoidRef
|
10
|
+
def initialize(uri, base)
|
11
|
+
@uri = Addressable::URI.parse(uri)
|
12
|
+
@base = base
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :uri
|
16
|
+
|
17
|
+
def full_uri
|
18
|
+
return Addressable::URI.join(@base, @uri)
|
19
|
+
end
|
20
|
+
|
21
|
+
def deref
|
22
|
+
return Entitoid.from_xml(full_uri)
|
23
|
+
end
|
24
|
+
|
25
|
+
def eql?(other)
|
26
|
+
if other.class != self.class
|
27
|
+
return false
|
28
|
+
end
|
29
|
+
|
30
|
+
return other.full_uri == self.full_uri
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# This is free software released into the public domain (CC0 license).
|
2
|
+
|
3
|
+
|
4
|
+
module Factoid
|
5
|
+
class Factoid
|
6
|
+
def initialize(type, context, value_obj, sources, context_sources)
|
7
|
+
@type = type
|
8
|
+
@context = context
|
9
|
+
@value_obj = value_obj
|
10
|
+
|
11
|
+
@sources = sources
|
12
|
+
@context_sources = context_sources
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :type
|
16
|
+
attr_reader :value_obj
|
17
|
+
attr_reader :context
|
18
|
+
|
19
|
+
def sources
|
20
|
+
if !@sources.empty?
|
21
|
+
return @sources
|
22
|
+
end
|
23
|
+
|
24
|
+
uris = @context_sources.select { |s| s.default? }
|
25
|
+
|
26
|
+
return uris
|
27
|
+
end
|
28
|
+
|
29
|
+
def match?(type, context)
|
30
|
+
if @type != type # FIXME: check type hierarchy
|
31
|
+
return false
|
32
|
+
end
|
33
|
+
|
34
|
+
return context.to_a.all? { |k, v| @context[k.to_s] == v }
|
35
|
+
end
|
36
|
+
|
37
|
+
def value(interpret = true, follow = false)
|
38
|
+
return @value_obj.value(interpret, follow)
|
39
|
+
end
|
40
|
+
|
41
|
+
def eql?(other)
|
42
|
+
if other.equal?(self)
|
43
|
+
return true
|
44
|
+
end
|
45
|
+
|
46
|
+
if other.class != self.class
|
47
|
+
return false
|
48
|
+
end
|
49
|
+
|
50
|
+
same = other.type == self.type &&
|
51
|
+
other.value.eql?(self.value) &&
|
52
|
+
other.sources == self.sources
|
53
|
+
|
54
|
+
return same
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# This is free software released into the public domain (CC0 license).
|
2
|
+
|
3
|
+
|
4
|
+
require 'addressable/uri'
|
5
|
+
|
6
|
+
module Factoid
|
7
|
+
class Source
|
8
|
+
def initialize(uuid, uri, default, value)
|
9
|
+
@uuid = uuid
|
10
|
+
@uri = Addressable::URI.parse(uri)
|
11
|
+
@default = default
|
12
|
+
@value = value
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :uuid
|
16
|
+
attr_reader :uri
|
17
|
+
attr_reader :value
|
18
|
+
|
19
|
+
def default?
|
20
|
+
return @default
|
21
|
+
end
|
22
|
+
|
23
|
+
def ref?
|
24
|
+
# FIXME: separate SourceRef class
|
25
|
+
return !@uri.nil?
|
26
|
+
end
|
27
|
+
|
28
|
+
def ==(other)
|
29
|
+
if other.equal?(self)
|
30
|
+
return true
|
31
|
+
end
|
32
|
+
|
33
|
+
if other.is_a?(Source)
|
34
|
+
if other.ref?
|
35
|
+
return other.uri == self.uri
|
36
|
+
else
|
37
|
+
return other.value == self.value
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
if ref?
|
42
|
+
return Addressable::URI.parse(other) == @uri
|
43
|
+
else
|
44
|
+
return other == @value.to_s
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# FIXME: move part of == to eql?; add tests
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# This is free software released into the public domain (CC0 license).
|
2
|
+
|
3
|
+
|
4
|
+
module Factoid
|
5
|
+
class Value
|
6
|
+
def initialize(type, raw_value)
|
7
|
+
@type = type
|
8
|
+
@raw_value = raw_value
|
9
|
+
end
|
10
|
+
|
11
|
+
EMPTY = Value.new(nil, nil).freeze
|
12
|
+
|
13
|
+
def value(interpret, follow)
|
14
|
+
raw = nil
|
15
|
+
|
16
|
+
if @raw_value.elements.empty?
|
17
|
+
raw = @raw_value.text
|
18
|
+
else
|
19
|
+
raw = @raw_value
|
20
|
+
end
|
21
|
+
|
22
|
+
if !interpret
|
23
|
+
return raw
|
24
|
+
end
|
25
|
+
|
26
|
+
interpreter = Interpreters.find { |i| begin i.accept?(@type, raw); rescue; end; }
|
27
|
+
v = interpreter.interpret(@type, raw)
|
28
|
+
|
29
|
+
if !follow
|
30
|
+
return v
|
31
|
+
end
|
32
|
+
|
33
|
+
# FIXME: use Dereferenciators (like Interpreters)
|
34
|
+
if v.is_a? EntitoidRef
|
35
|
+
r = v.deref
|
36
|
+
else
|
37
|
+
r = v
|
38
|
+
end
|
39
|
+
|
40
|
+
return r
|
41
|
+
end
|
42
|
+
|
43
|
+
class XSDDateInterpreter
|
44
|
+
def self.accept?(type, value)
|
45
|
+
return type == 'xsd:date'
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.interpret(type, value)
|
49
|
+
require 'time'
|
50
|
+
return Time.parse(value)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class EntitoidInterpreter
|
55
|
+
def self.accept?(type, value)
|
56
|
+
return !value.xpath('./f:*', NS).empty?
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.interpret(type, value)
|
60
|
+
require 'factoid/xml'
|
61
|
+
|
62
|
+
# FIXME: allow also complete entitoids
|
63
|
+
|
64
|
+
elem = value.at('./f:*', NS)
|
65
|
+
return EntitoidRef.from_xml(elem)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class IndentityInterpreter
|
70
|
+
def self.accept?(type, value)
|
71
|
+
return true
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.interpret(type, value)
|
75
|
+
return value
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
Interpreters = [
|
80
|
+
XSDDateInterpreter,
|
81
|
+
EntitoidInterpreter,
|
82
|
+
IndentityInterpreter,
|
83
|
+
]
|
84
|
+
end
|
85
|
+
end
|
data/lib/factoid/xml.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
# This is free software released into the public domain (CC0 license).
|
2
|
+
|
3
|
+
|
4
|
+
require 'nokogiri'
|
5
|
+
|
6
|
+
require 'factoid/entitoid'
|
7
|
+
require 'factoid/entitoid_ref'
|
8
|
+
require 'factoid/factoid'
|
9
|
+
require 'factoid/source'
|
10
|
+
require 'factoid/value'
|
11
|
+
|
12
|
+
module Factoid
|
13
|
+
FACTOID_NS_URI = 'http://svario.it/factoid'
|
14
|
+
|
15
|
+
NS = {
|
16
|
+
'f' => FACTOID_NS_URI,
|
17
|
+
'xlink' => 'http://www.w3.org/1999/xlink',
|
18
|
+
'xsd' => 'http://www.w3.org/2001/XMLSchema-datatypes',
|
19
|
+
}
|
20
|
+
|
21
|
+
def Entitoid.from_xml(filename)
|
22
|
+
x = Nokogiri::XML(open(filename))
|
23
|
+
|
24
|
+
uuid = x.root.attr('xml:id')
|
25
|
+
e = self.new(uuid)
|
26
|
+
|
27
|
+
context_sources = []
|
28
|
+
x.xpath('/*/f:sources/f:source').each do |s|
|
29
|
+
context_sources << Source.from_xml(s)
|
30
|
+
end
|
31
|
+
|
32
|
+
x.xpath('/*/f:*', NS).each do |f|
|
33
|
+
if f.name == 'sources'
|
34
|
+
next
|
35
|
+
end
|
36
|
+
|
37
|
+
e.add_factoid(Factoid.from_xml(f, context_sources))
|
38
|
+
end
|
39
|
+
|
40
|
+
return e
|
41
|
+
end
|
42
|
+
|
43
|
+
def EntitoidRef.from_xml(elem)
|
44
|
+
href = elem.attr('xlink:href')
|
45
|
+
base = elem.document.url
|
46
|
+
|
47
|
+
return EntitoidRef.new(href, base)
|
48
|
+
end
|
49
|
+
|
50
|
+
def Factoid.from_xml(elem, context_sources)
|
51
|
+
type = elem.name unless elem.name == 'factoid'
|
52
|
+
type ||= elem.attr('type')
|
53
|
+
|
54
|
+
context = {}
|
55
|
+
elem.xpath('./*[name(.) != "value"]').each do |e|
|
56
|
+
context[e.name] = e.text
|
57
|
+
end
|
58
|
+
|
59
|
+
value = Value.from_xml(elem)
|
60
|
+
|
61
|
+
raw_sources = elem.xpath('f:source', NS)
|
62
|
+
sources = raw_sources.map do |e|
|
63
|
+
Source.from_xml(e)
|
64
|
+
end
|
65
|
+
|
66
|
+
return Factoid.new(type, context, value, sources, context_sources)
|
67
|
+
end
|
68
|
+
|
69
|
+
def Source.from_xml(elem)
|
70
|
+
uuid = elem.attr('xml:id')
|
71
|
+
|
72
|
+
uri = elem.attr('xlink:href')
|
73
|
+
|
74
|
+
default = (elem.attr('default') == 'true')
|
75
|
+
|
76
|
+
#value = Value.from_xml(elem)
|
77
|
+
value = Value::EMPTY
|
78
|
+
|
79
|
+
return Source.new(uuid, uri, default, value)
|
80
|
+
end
|
81
|
+
|
82
|
+
def Value.from_xml(container_elem)
|
83
|
+
elem = container_elem.at('./f:value', NS)
|
84
|
+
|
85
|
+
type = elem.attr('type')
|
86
|
+
# TODO: special case for entitoids
|
87
|
+
# TODO: use type = :entitoid_ref instead of nil
|
88
|
+
|
89
|
+
return Value.new(type, elem)
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# This is free software released into the public domain (CC0 license).
|
2
|
+
|
3
|
+
|
4
|
+
require 'spec_helpers'
|
5
|
+
|
6
|
+
require 'factoid/entitoid'
|
7
|
+
require 'factoid/xml'
|
8
|
+
|
9
|
+
describe Factoid::Entitoid do
|
10
|
+
before(:all) do
|
11
|
+
@e = Factoid::Entitoid.from_xml('spec/fixtures/chopin.xml')
|
12
|
+
end
|
13
|
+
|
14
|
+
it "can be loaded from XML" do
|
15
|
+
expect(@e).to be_a Factoid::Entitoid
|
16
|
+
expect(@e.uuid).to eql "chopin-23"
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#factoids" do
|
20
|
+
it "returns all the factoids" do
|
21
|
+
expect(@e.factoids(:all)).to have(8).items
|
22
|
+
end
|
23
|
+
|
24
|
+
it "returns all the factoids of type 'name'" do
|
25
|
+
expect(@e.factoids('name')).to have(4).items
|
26
|
+
end
|
27
|
+
|
28
|
+
it "returns all the factoids of type 'name' with a certain context" do
|
29
|
+
expect(@e.factoids('name', :language => 'fra')).to have(2).items
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#value" do
|
34
|
+
it "raises an exception if the request is ambiguous" do
|
35
|
+
expect { @e.value('birth-date') }.to raise_error
|
36
|
+
end
|
37
|
+
|
38
|
+
it "raises an exception if no factoid exists" do
|
39
|
+
expect { @e.value('unk-property') }.to raise_error
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "#source" do
|
44
|
+
it "returns the stated source" do
|
45
|
+
f = @e.factoids('birth-date').first
|
46
|
+
|
47
|
+
expect(f.sources).to eq ["#bcert"]
|
48
|
+
end
|
49
|
+
|
50
|
+
it "returns the default source" do
|
51
|
+
f = @e.factoids('birth-date').last
|
52
|
+
|
53
|
+
expect(f.sources).to eq ["http://en.wikipedia.org/wiki/Frédéric_Chopin"]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# This is free software released into the public domain (CC0 license).
|
2
|
+
|
3
|
+
|
4
|
+
require 'spec_helpers'
|
5
|
+
|
6
|
+
require 'nokogiri'
|
7
|
+
|
8
|
+
require 'factoid/entitoid'
|
9
|
+
require 'factoid/entitoid_ref'
|
10
|
+
require 'factoid/factoid'
|
11
|
+
require 'factoid/xml'
|
12
|
+
|
13
|
+
describe Factoid::Factoid do
|
14
|
+
before (:all) do
|
15
|
+
e = Factoid::Entitoid.from_xml('spec/fixtures/chopin.xml')
|
16
|
+
@name = e.factoids('name', 'language' => 'fra').first
|
17
|
+
@death_date = e.factoids('death-date').first
|
18
|
+
@birth_place = e.factoids('birth-place').first
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#value" do
|
22
|
+
context "with no arguments" do
|
23
|
+
it "returns a string" do
|
24
|
+
expect(@name.value).to eql "Frédéric Chopin"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "returns a date" do
|
28
|
+
expect(@death_date.value).to eql Time.mktime(1849, 10, 17)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "returns an entitoid ref" do
|
32
|
+
place_ref = Factoid::EntitoidRef.new('zelazowa-wola', 'spec/fixtures/chopin.xml')
|
33
|
+
expect(@birth_place.value).to eql place_ref
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "with no interpretation" do
|
38
|
+
it "returns a string" do
|
39
|
+
expect(@name.value(false)).to eql "Frédéric Chopin"
|
40
|
+
end
|
41
|
+
|
42
|
+
it "returns a string also for dates" do
|
43
|
+
expect(@death_date.value(false)).to eql "1849-10-17"
|
44
|
+
end
|
45
|
+
|
46
|
+
it "returns an XML element" do
|
47
|
+
expect(@birth_place.value(false)).to be_a Nokogiri::XML::Node
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context "with follows" do
|
52
|
+
it "returns a string" do
|
53
|
+
expect(@name.value(true, true)).to eql "Frédéric Chopin"
|
54
|
+
end
|
55
|
+
|
56
|
+
it "returns a string also for dates" do
|
57
|
+
expect(@death_date.value(true, true)).to eql Time.mktime(1849, 10, 17)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "returns an entitoid" do
|
61
|
+
zelazowa_wola = Factoid::Entitoid.from_xml('spec/fixtures/zelazowa-wola.xml')
|
62
|
+
expect(@birth_place.value(true, true)).to eql zelazowa_wola
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
<f:entity type="composer" xml:id="chopin-23" xmlns:f='http://svario.it/factoid'
|
2
|
+
xmlns:xlink="http://www.w3.org/1999/xlink"
|
3
|
+
xmlns:xsd="http://www.w3.org/2001/XMLSchema-datatypes">
|
4
|
+
<f:sources>
|
5
|
+
<f:source xml:id="wp" xlink:href="http://en.wikipedia.org/wiki/Fr%C3%A9d%C3%A9ric_Chopin" default="true"/>
|
6
|
+
<f:source xml:id="bcert" xlink:href="urn:isbn:9780007351824"/>
|
7
|
+
</f:sources>
|
8
|
+
|
9
|
+
<f:factoid type="name">
|
10
|
+
<language>pol</language>
|
11
|
+
<f:value>Fryderyk Franciszek Chopin</f:value>
|
12
|
+
</f:factoid>
|
13
|
+
|
14
|
+
<f:factoid type="name">
|
15
|
+
<language>pol</language>
|
16
|
+
<f:value>Fryderyk Chopin</f:value>
|
17
|
+
</f:factoid>
|
18
|
+
|
19
|
+
<f:name>
|
20
|
+
<language>fra</language>
|
21
|
+
<f:value>Frédéric Chopin</f:value>
|
22
|
+
</f:name>
|
23
|
+
|
24
|
+
<f:name>
|
25
|
+
<language>fra</language>
|
26
|
+
<alphabet>Hang</alphabet>
|
27
|
+
<f:value>프레데리크 쇼팽</f:value>
|
28
|
+
</f:name>
|
29
|
+
|
30
|
+
<f:factoid type="birth-date">
|
31
|
+
<f:value type="xsd:date">1810-08-22</f:value>
|
32
|
+
<f:source xlink:href="#bcert"/>
|
33
|
+
</f:factoid>
|
34
|
+
|
35
|
+
<f:birth-date>
|
36
|
+
<f:value type="xsd:date">1810-03-01</f:value>
|
37
|
+
</f:birth-date>
|
38
|
+
|
39
|
+
<f:birth-place>
|
40
|
+
<f:value>
|
41
|
+
<f:place xlink:href="zelazowa-wola"/>
|
42
|
+
</f:value>
|
43
|
+
</f:birth-place>
|
44
|
+
|
45
|
+
<f:death-date>
|
46
|
+
<f:value type="xsd:date">1849-10-17</f:value>
|
47
|
+
</f:death-date>
|
48
|
+
</f:entity>
|
49
|
+
<!-- This is free software released into the public domain (CC0 license). -->
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<f:entity type="place" xml:id="zelazowa-wola" xmlns:f='http://svario.it/factoid'
|
2
|
+
xmlns:xlink="http://www.w3.org/1999/xlink"
|
3
|
+
xmlns:xsd="http://www.w3.org/2001/XMLSchema-datatypes">
|
4
|
+
<f:sources>
|
5
|
+
<f:source xml:id="wp" xlink:href="http://en.wikipedia.org/wiki/Żelazowa_Wola" default="true"/>
|
6
|
+
</f:sources>
|
7
|
+
|
8
|
+
<f:name>
|
9
|
+
<language>pol</language>
|
10
|
+
<f:value>Żelazowa Wola</f:value>
|
11
|
+
</f:name>
|
12
|
+
|
13
|
+
<f:gmina>
|
14
|
+
<f:value>
|
15
|
+
<f:entity xlink:href="sochaczew"/>
|
16
|
+
</f:value>
|
17
|
+
</f:gmina>
|
18
|
+
</f:entity>
|
19
|
+
<!-- This is free software released into the public domain (CC0 license). -->
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<f:entity type="place" xml:id="zelazowa-wola" xmlns:f='http://svario.it/factoid'
|
2
|
+
xmlns:xlink="http://www.w3.org/1999/xlink"
|
3
|
+
xmlns:xsd="http://www.w3.org/2001/XMLSchema-datatypes">
|
4
|
+
<f:sources>
|
5
|
+
<f:source xml:id="wp" xlink:href="http://en.wikipedia.org/wiki/Żelazowa_Wola" default="true"/>
|
6
|
+
</f:sources>
|
7
|
+
|
8
|
+
<f:name>
|
9
|
+
<language>pol</language>
|
10
|
+
<f:value>Żelazowa Wola</f:value>
|
11
|
+
</f:name>
|
12
|
+
|
13
|
+
<f:gmina>
|
14
|
+
<f:value>
|
15
|
+
<f:entity xlink:href="sochaczew"/>
|
16
|
+
</f:value>
|
17
|
+
</f:gmina>
|
18
|
+
</f:entity>
|
19
|
+
<!-- This is free software released into the public domain (CC0 license). -->
|
metadata
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: factoid
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Gioele Barabucci
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-10-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: nokogiri
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: addressable
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.3'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.3'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description:
|
84
|
+
email:
|
85
|
+
- gioele@svario.it
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- .gitignore
|
91
|
+
- COPYING
|
92
|
+
- Gemfile
|
93
|
+
- LICENSE.txt
|
94
|
+
- README.md
|
95
|
+
- Rakefile
|
96
|
+
- factoid.gemspec
|
97
|
+
- lib/factoid.rb
|
98
|
+
- lib/factoid/entitoid.rb
|
99
|
+
- lib/factoid/entitoid_ref.rb
|
100
|
+
- lib/factoid/factoid.rb
|
101
|
+
- lib/factoid/source.rb
|
102
|
+
- lib/factoid/value.rb
|
103
|
+
- lib/factoid/version.rb
|
104
|
+
- lib/factoid/xml.rb
|
105
|
+
- spec/factoid/entitoid_spec.rb
|
106
|
+
- spec/factoid/factoid_spec.rb
|
107
|
+
- spec/fixtures/chopin.xml
|
108
|
+
- spec/fixtures/zelazowa-wola
|
109
|
+
- spec/fixtures/zelazowa-wola.xml
|
110
|
+
- spec/spec_helpers.rb
|
111
|
+
homepage: http://svario.it/factoid/ruby
|
112
|
+
licenses:
|
113
|
+
- CC0
|
114
|
+
metadata: {}
|
115
|
+
post_install_message:
|
116
|
+
rdoc_options: []
|
117
|
+
require_paths:
|
118
|
+
- lib
|
119
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - '>='
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - '>='
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
requirements: []
|
130
|
+
rubyforge_project:
|
131
|
+
rubygems_version: 2.0.4
|
132
|
+
signing_key:
|
133
|
+
specification_version: 4
|
134
|
+
summary: factoid is a Ruby library to manipulate factoids entitoids inside Ruby applications
|
135
|
+
without touching the their XML representations.
|
136
|
+
test_files:
|
137
|
+
- spec/factoid/entitoid_spec.rb
|
138
|
+
- spec/factoid/factoid_spec.rb
|
139
|
+
- spec/fixtures/chopin.xml
|
140
|
+
- spec/fixtures/zelazowa-wola
|
141
|
+
- spec/fixtures/zelazowa-wola.xml
|
142
|
+
- spec/spec_helpers.rb
|