bio-nexml 0.0.1
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/Gemfile +15 -0
- data/Gemfile.lock +24 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +47 -0
- data/Rakefile +55 -0
- data/TODO.txt +6 -0
- data/VERSION +1 -0
- data/bio-nexml.gemspec +126 -0
- data/extconf.rb +2 -0
- data/lib/bio-nexml.rb +0 -0
- data/lib/bio.rb +321 -0
- data/lib/bio/db/nexml.rb +109 -0
- data/lib/bio/db/nexml/mapper.rb +113 -0
- data/lib/bio/db/nexml/mapper/framework.rb +157 -0
- data/lib/bio/db/nexml/mapper/inflection.rb +99 -0
- data/lib/bio/db/nexml/mapper/repository.rb +59 -0
- data/lib/bio/db/nexml/matrix.rb +1046 -0
- data/lib/bio/db/nexml/parser.rb +622 -0
- data/lib/bio/db/nexml/schema/README.txt +21 -0
- data/lib/bio/db/nexml/schema/abstract.xsd +159 -0
- data/lib/bio/db/nexml/schema/characters/README.txt +1 -0
- data/lib/bio/db/nexml/schema/characters/abstractcharacters.xsd +361 -0
- data/lib/bio/db/nexml/schema/characters/characters.xsd +22 -0
- data/lib/bio/db/nexml/schema/characters/continuous.xsd +190 -0
- data/lib/bio/db/nexml/schema/characters/dna.xsd +282 -0
- data/lib/bio/db/nexml/schema/characters/protein.xsd +280 -0
- data/lib/bio/db/nexml/schema/characters/restriction.xsd +239 -0
- data/lib/bio/db/nexml/schema/characters/rna.xsd +283 -0
- data/lib/bio/db/nexml/schema/characters/standard.xsd +261 -0
- data/lib/bio/db/nexml/schema/external/sawsdl.xsd +21 -0
- data/lib/bio/db/nexml/schema/external/xhtml-datatypes-1.xsd +177 -0
- data/lib/bio/db/nexml/schema/external/xlink.xsd +75 -0
- data/lib/bio/db/nexml/schema/external/xml.xsd +145 -0
- data/lib/bio/db/nexml/schema/meta/README.txt +2 -0
- data/lib/bio/db/nexml/schema/meta/annotations.xsd +100 -0
- data/lib/bio/db/nexml/schema/meta/meta.xsd +294 -0
- data/lib/bio/db/nexml/schema/nexml.xsd +104 -0
- data/lib/bio/db/nexml/schema/taxa/README.txt +2 -0
- data/lib/bio/db/nexml/schema/taxa/taxa.xsd +39 -0
- data/lib/bio/db/nexml/schema/trees/README.txt +2 -0
- data/lib/bio/db/nexml/schema/trees/abstracttrees.xsd +135 -0
- data/lib/bio/db/nexml/schema/trees/network.xsd +113 -0
- data/lib/bio/db/nexml/schema/trees/tree.xsd +149 -0
- data/lib/bio/db/nexml/schema/trees/trees.xsd +36 -0
- data/lib/bio/db/nexml/taxa.rb +147 -0
- data/lib/bio/db/nexml/trees.rb +663 -0
- data/lib/bio/db/nexml/writer.rb +265 -0
- data/test/data/nexml/test.xml +69 -0
- data/test/test_bio-nexml.rb +17 -0
- data/test/unit/bio/db/nexml/tc_factory.rb +119 -0
- data/test/unit/bio/db/nexml/tc_mapper.rb +78 -0
- data/test/unit/bio/db/nexml/tc_matrix.rb +551 -0
- data/test/unit/bio/db/nexml/tc_parser.rb +21 -0
- data/test/unit/bio/db/nexml/tc_taxa.rb +118 -0
- data/test/unit/bio/db/nexml/tc_trees.rb +370 -0
- data/test/unit/bio/db/nexml/tc_writer.rb +633 -0
- metadata +253 -0
data/lib/bio/db/nexml.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
#load XML library for parser and serializer
|
2
|
+
require 'xml'
|
3
|
+
|
4
|
+
#load required class and module definitions
|
5
|
+
require "bio/db/nexml/mapper"
|
6
|
+
|
7
|
+
#Autoload definition
|
8
|
+
module Bio
|
9
|
+
module NeXML
|
10
|
+
|
11
|
+
@@id_counter = 0;
|
12
|
+
def self.generate_id( klass )
|
13
|
+
myname = klass.name
|
14
|
+
local = myname.gsub(/.*:/,"")
|
15
|
+
@@id_counter += 1
|
16
|
+
newid = @@id_counter
|
17
|
+
"#{local}#{newid}"
|
18
|
+
end
|
19
|
+
|
20
|
+
module Base
|
21
|
+
attr_accessor :xml_base
|
22
|
+
attr_accessor :xml_id
|
23
|
+
attr_accessor :xml_lang
|
24
|
+
attr_accessor :xml_space
|
25
|
+
end #end module Base
|
26
|
+
|
27
|
+
# Autoload multiple modules that reside in the same file.
|
28
|
+
def self.mautoload( modules, file )
|
29
|
+
modules.each do |m|
|
30
|
+
autoload m, file
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
mautoload %w|Otu Otus|, 'bio/db/nexml/taxa.rb'
|
35
|
+
mautoload %w|Node Edge Tree Network Trees|, 'bio/db/nexml/trees.rb'
|
36
|
+
mautoload %w|State Char States Cell Sequence Format Characters|, 'bio/db/nexml/matrix.rb'
|
37
|
+
|
38
|
+
autoload :Parser, 'bio/db/nexml/parser'
|
39
|
+
autoload :Writer, 'bio/db/nexml/writer'
|
40
|
+
|
41
|
+
class Nexml
|
42
|
+
@@writer = Bio::NeXML::Writer.new
|
43
|
+
include Mapper
|
44
|
+
include Enumerable
|
45
|
+
attr_accessor :version
|
46
|
+
attr_accessor :generator
|
47
|
+
|
48
|
+
has_n :otus, :singularize => false
|
49
|
+
has_n :trees, :singularize => false
|
50
|
+
has_n :characters, :singularize => false
|
51
|
+
|
52
|
+
def initialize( version = '0.9', generator = 'bioruby' )
|
53
|
+
@version = version
|
54
|
+
@generator = generator
|
55
|
+
end
|
56
|
+
|
57
|
+
# Append a Otus, Trees, or Characters object to any
|
58
|
+
# Nexml object.
|
59
|
+
def <<( element )
|
60
|
+
case element
|
61
|
+
when Otus
|
62
|
+
add_otus element
|
63
|
+
when Trees
|
64
|
+
add_trees element
|
65
|
+
when Characters
|
66
|
+
add_characters element
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def create_otus( options = {} )
|
71
|
+
otus = Otus.new( Bio::NeXML.generate_id( Otus ), options )
|
72
|
+
self << otus
|
73
|
+
otus
|
74
|
+
end
|
75
|
+
|
76
|
+
def create_trees( options )
|
77
|
+
trees = Trees.new( Bio::NeXML.generate_id( Trees ), options )
|
78
|
+
self << trees
|
79
|
+
trees
|
80
|
+
end
|
81
|
+
|
82
|
+
def create_characters( type = "Dna", verbose = false, options = {} )
|
83
|
+
subtype = verbose ? "Cells" : "Seqs"
|
84
|
+
klass_name = "#{type.to_s.capitalize}#{subtype}"
|
85
|
+
klass = NeXML.const_get( klass_name )
|
86
|
+
characters = klass.new( Bio::NeXML.generate_id( klass ), options )
|
87
|
+
self << characters
|
88
|
+
characters
|
89
|
+
end
|
90
|
+
|
91
|
+
def to_xml
|
92
|
+
node = @@writer.create_node( "nex:nexml", :"xsi:schemaLocation" => "http://www.nexml.org/2009 http://www.nexml.org/2009/xsd/nexml.xsd", :generator => generator, :version => version )
|
93
|
+
node.namespaces = { nil => "http://www.nexml.org/2009", :xsi => "http://www.w3.org/2001/XMLSchema-instance", :xlink => "http://www.w3.org/1999/xlink", :nex => "http://www.nexml.org/2009" }
|
94
|
+
self.each_otus do |otus|
|
95
|
+
node << otus.to_xml
|
96
|
+
end
|
97
|
+
self.each_characters do |characters|
|
98
|
+
node << characters.to_xml
|
99
|
+
end
|
100
|
+
self.each_trees do |trees|
|
101
|
+
node << trees.to_xml
|
102
|
+
end
|
103
|
+
node
|
104
|
+
end
|
105
|
+
|
106
|
+
end #end class Nexml
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'bio/db/nexml/mapper/inflection'
|
2
|
+
require 'bio/db/nexml/mapper/repository'
|
3
|
+
require 'bio/db/nexml/mapper/framework'
|
4
|
+
|
5
|
+
module Bio
|
6
|
+
module NeXML
|
7
|
+
|
8
|
+
# Mapper provides a very small DSL for defining NeXML classes, specifically one-to-many relation
|
9
|
+
# between classes as they are found a lot in NeXML. Though the style has been borrowed from
|
10
|
+
# ActiveRecord, it should not be mistaken for an ORM. It just factors out repetitive chunk of
|
11
|
+
# code that would otherwise be present.
|
12
|
+
#
|
13
|
+
# Including Mapper in a class, creates <tt>has_n</tt>, and <tt>belongs_to</tt> class methods
|
14
|
+
# by extending Framework module. These methods are used to define a one-to-many relation
|
15
|
+
# between two classes. Two types of one-to-many relation occurs in NeXML.
|
16
|
+
# * parent-child - an element <em>contains</em> other elements. In raw NeXML it would mean
|
17
|
+
# nested elements.
|
18
|
+
# * association - an element <em>refers</em> to other elements. In raw NeXML it would mean
|
19
|
+
# a source element, referred to by several targets.
|
20
|
+
#
|
21
|
+
# Their implementation however is same. Defining a relation automatically creates methods to
|
22
|
+
# add, delete and query objects.
|
23
|
+
#
|
24
|
+
# class Otu
|
25
|
+
# property :id
|
26
|
+
# belongs_to :otus
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# class Otus
|
30
|
+
# property :id
|
31
|
+
# has_n :otus
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# t1 = Otu.new
|
35
|
+
# t1.id = 't1'
|
36
|
+
# t2 = Otu.new
|
37
|
+
# t2.id = 't2'
|
38
|
+
# o1 = Otus.new
|
39
|
+
# o1.id = 'o1'
|
40
|
+
#
|
41
|
+
# # add to source
|
42
|
+
# o1.add_otu( t1 )
|
43
|
+
# o1.otus
|
44
|
+
# => [ t1 ]
|
45
|
+
# t1.otus
|
46
|
+
# => o1
|
47
|
+
#
|
48
|
+
# # add to target
|
49
|
+
# t2.otus = o1
|
50
|
+
# o1.otus
|
51
|
+
# => [ t1, t2 ]
|
52
|
+
# t2.otus
|
53
|
+
# => o1
|
54
|
+
#
|
55
|
+
# # query from source
|
56
|
+
# o1.has_otu?( t1 )
|
57
|
+
# => true
|
58
|
+
# o1.get_otu_by_id( 't1' )
|
59
|
+
# => t1
|
60
|
+
#
|
61
|
+
# # delete from source
|
62
|
+
# o1.delete_otu( t1 )
|
63
|
+
# o1.otus
|
64
|
+
# => [ t2 ]
|
65
|
+
# t1.otus
|
66
|
+
# => nil
|
67
|
+
module Mapper # :nodoc: all
|
68
|
+
|
69
|
+
# Gets or sets properties of the receiver.
|
70
|
+
def properties( args = {} )
|
71
|
+
@properties ||= {}
|
72
|
+
|
73
|
+
# set properties if defined
|
74
|
+
args.each do |property, value|
|
75
|
+
raise "#{property} not defined" unless respond_to?( setter = "#{property}=" )
|
76
|
+
send( setter, value )
|
77
|
+
end unless args.empty?
|
78
|
+
|
79
|
+
# return a copy of @properties so that it is not modified inadvertently by the user
|
80
|
+
@properties.dup
|
81
|
+
end
|
82
|
+
alias properties= properties
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
# Fetches an instance variable corresponding to name. If the instance variable
|
87
|
+
# is nil, set it to defaul value and return it.
|
88
|
+
def repository( name, type = HashRepository )
|
89
|
+
ivget( name ) || ivset( name, type.new )
|
90
|
+
end
|
91
|
+
|
92
|
+
# Return an instance variable corresponding to the given name.
|
93
|
+
# '@' is automatically prepended to the name.
|
94
|
+
# object.ivget( 'name' ) #=> returns value of @name
|
95
|
+
# object.ivget( :name ) #=> returns value of @name
|
96
|
+
def ivget( name )
|
97
|
+
instance_variable_get( "@#{name}" )
|
98
|
+
end
|
99
|
+
|
100
|
+
# Set an instance variable corresponding to the given name.
|
101
|
+
# '@' is automatically prepended to the name.
|
102
|
+
# object.ivset( 'name', value ) #=> sets @name to value
|
103
|
+
# object.ivget( :name, value ) #=> sets @name to value
|
104
|
+
def ivset( name, value = nil )
|
105
|
+
instance_variable_set( "@#{name}", value )
|
106
|
+
end
|
107
|
+
|
108
|
+
def self.included( klass )
|
109
|
+
klass.extend Framework
|
110
|
+
end
|
111
|
+
end #end module Mapper
|
112
|
+
end #end module NeXML
|
113
|
+
end #end module Bio
|
@@ -0,0 +1,157 @@
|
|
1
|
+
module Bio
|
2
|
+
module NeXML
|
3
|
+
module Mapper
|
4
|
+
|
5
|
+
# Framework is the real workhorse of Mapper.
|
6
|
+
module Framework
|
7
|
+
|
8
|
+
# Define a source for the target.
|
9
|
+
# belongs_to :source
|
10
|
+
def belongs_to( name, options = {} )
|
11
|
+
update = ( options[ :update ] || self.name.key ).to_sym
|
12
|
+
|
13
|
+
# create attribute reader for source
|
14
|
+
attr_reader name
|
15
|
+
|
16
|
+
# Add this target to a source.
|
17
|
+
# def add_to_source( source )
|
18
|
+
# return if @source == source or source.nil?
|
19
|
+
# @source = source
|
20
|
+
# source.add_target( self )
|
21
|
+
# end
|
22
|
+
define_method( "add_to_#{name}" ) do |source,|
|
23
|
+
# return if the target already belongs to
|
24
|
+
# the given source or if the source is nil.
|
25
|
+
return if ivget( name ) == source or source.nil?
|
26
|
+
|
27
|
+
# add source and send a message to source
|
28
|
+
# to add self as target.
|
29
|
+
ivset( name, source )
|
30
|
+
source.send( "add_#{update}", self )
|
31
|
+
end
|
32
|
+
|
33
|
+
# Set or remove source.
|
34
|
+
# def source=( source )
|
35
|
+
# return remove_from_source if source.nil?
|
36
|
+
# return add_to_source( self )
|
37
|
+
# end
|
38
|
+
define_method( "#{name}=" ) do |source,|
|
39
|
+
return send( "remove_from_#{name}" ) if source.nil?
|
40
|
+
return send( "add_to_#{name}", source )
|
41
|
+
end
|
42
|
+
|
43
|
+
# Remove this target from an existing source.
|
44
|
+
# def remove_from_source
|
45
|
+
# return unless source = @source
|
46
|
+
# @source = nil
|
47
|
+
# source.delete_target( self )
|
48
|
+
# end
|
49
|
+
define_method( "remove_from_#{name}" ) do
|
50
|
+
# return if a sourc is not set.
|
51
|
+
return unless source = ivget( name )
|
52
|
+
|
53
|
+
# remove source and send a message to source
|
54
|
+
# to remove itself as target.
|
55
|
+
ivset( name, nil )
|
56
|
+
source.send( "delete_#{update}", self )
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Define target set for the source.
|
61
|
+
# has_n :otu
|
62
|
+
def has_n( target, options = {} )
|
63
|
+
name = ( options[ :singularize ] == false ) ? target.to_s : target.to_s.singular
|
64
|
+
type = ( options[ :index ] == false ) ? ArrayRepository : HashRepository
|
65
|
+
update = ( options[ :update ] || self.name.key ).to_sym
|
66
|
+
|
67
|
+
# Return an Array of targets.
|
68
|
+
# def targets
|
69
|
+
# @targets.objects
|
70
|
+
# end
|
71
|
+
define_method( target ) do
|
72
|
+
repository( target, type ).objects
|
73
|
+
end
|
74
|
+
|
75
|
+
# Set an Array as a target.
|
76
|
+
# def targets=( targets )
|
77
|
+
# @targets.clear
|
78
|
+
# targets.each do |t|
|
79
|
+
# add_target( t )
|
80
|
+
# end
|
81
|
+
# end
|
82
|
+
define_method( "#{target}=" ) do |objects,|
|
83
|
+
repository( target, type ).clear
|
84
|
+
objects.each do |o|
|
85
|
+
send( "add_#{name}", o )
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Add a target.
|
90
|
+
# def add_target( target )
|
91
|
+
# return if @targets.include?( target )
|
92
|
+
# @targets.append( target )
|
93
|
+
# target.source = self
|
94
|
+
# end
|
95
|
+
define_method( "add_#{name}" ) do |object,|
|
96
|
+
repository = repository( target, type )
|
97
|
+
return if repository.include?( object )
|
98
|
+
repository.append( object )
|
99
|
+
object.send( "#{update}=", self )
|
100
|
+
self
|
101
|
+
end
|
102
|
+
|
103
|
+
# Delete a target.
|
104
|
+
# def delete_target( target )
|
105
|
+
# return unless @targets.include?( target )
|
106
|
+
# return unless deleted = @targets.delete( target )
|
107
|
+
# target.source = nil
|
108
|
+
# end
|
109
|
+
define_method( "delete_#{name}" ) do |object,|
|
110
|
+
repository = repository( target, type )
|
111
|
+
return unless deleted = repository.delete( object )
|
112
|
+
object.send( "#{update}=", nil )
|
113
|
+
deleted
|
114
|
+
end
|
115
|
+
|
116
|
+
# Return the number of targets a source has.
|
117
|
+
# def number_of_targets
|
118
|
+
# @targets.length
|
119
|
+
# end
|
120
|
+
define_method( "number_of_#{target}" ) do
|
121
|
+
repository( target, type ).length
|
122
|
+
end
|
123
|
+
|
124
|
+
# Return true if the source has the given target.
|
125
|
+
# def has_target?( target )
|
126
|
+
# @targets.include?( target )
|
127
|
+
# end
|
128
|
+
define_method( "has_#{name}?" ) do |object,|
|
129
|
+
repository( target, type ).include?( object )
|
130
|
+
end
|
131
|
+
|
132
|
+
# Iterate over each target.
|
133
|
+
# def each( &block )
|
134
|
+
# @targets.each( &block )
|
135
|
+
# end
|
136
|
+
class_eval <<_END_OF_EVAL_
|
137
|
+
def each_#{name}( &block )
|
138
|
+
repository( "#{target}", #{type} ).each( &block )
|
139
|
+
end
|
140
|
+
_END_OF_EVAL_
|
141
|
+
|
142
|
+
if type == HashRepository
|
143
|
+
define_method( "get_#{name}_by_id" ) do |id,|
|
144
|
+
repository( target, type )[ id ]
|
145
|
+
end
|
146
|
+
class_eval <<_END_OF_EVAL_
|
147
|
+
def each_#{name}_with_id( &block )
|
148
|
+
repository( #{target }, #{type } ).each_with_id( &block )
|
149
|
+
end
|
150
|
+
_END_OF_EVAL_
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
end #end module Framework
|
155
|
+
end #end module Mapper
|
156
|
+
end #end module NeXML
|
157
|
+
end #end module Mapper
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module Bio
|
2
|
+
module NeXML
|
3
|
+
module Mapper # :nodoc:
|
4
|
+
|
5
|
+
# String inflections. This module is mixed with the String class.
|
6
|
+
#
|
7
|
+
# "targets".singular #=> "target"
|
8
|
+
# "target".plural #=> "targets"
|
9
|
+
# "Bio::NeXML::Otu".key #=> "otu"
|
10
|
+
module Inflections
|
11
|
+
PLURALS =
|
12
|
+
[
|
13
|
+
[ /$/, 's' ],
|
14
|
+
[ /s$/i, 's' ],
|
15
|
+
[ /(ax|test)is$/i, '\1es' ],
|
16
|
+
[ /(octop|vir)us$/i, '\1i' ],
|
17
|
+
[ /(alias|status)$/i, '\1es' ],
|
18
|
+
[ /(bu)s$/i, '\1ses' ],
|
19
|
+
[ /(buffal|tomat)o$/i, '\1oes' ],
|
20
|
+
[ /([ti])um$/i, '\1a' ],
|
21
|
+
[ /sis$/i, 'ses' ],
|
22
|
+
[ /(?:([^f])fe|([lr])f)$/i, '\1\2ves' ],
|
23
|
+
[ /(hive)$/i, '\1s' ],
|
24
|
+
[ /([^aeiouy]|qu)y$/i, '\1ies' ],
|
25
|
+
[ /(x|ch|ss|sh)$/i, '\1es' ],
|
26
|
+
[ /(matr|vert|ind)(?:ix|ex)$/i, '\1ices' ],
|
27
|
+
[ /([m|l])ouse$/i, '\1ice' ],
|
28
|
+
[ /^(ox)$/i, '\1en' ],
|
29
|
+
[ /(quiz)$/i, '\1zes' ]
|
30
|
+
]
|
31
|
+
|
32
|
+
SINGULARS =
|
33
|
+
[
|
34
|
+
[ /s$/i, '' ],
|
35
|
+
[ /(n)ews$/i, '\1ews' ],
|
36
|
+
[ /([ti])a$/i, '\1um' ],
|
37
|
+
[ /((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i, '\1\2sis' ],
|
38
|
+
[ /(^analy)ses$/i, '\1sis' ],
|
39
|
+
[ /([^f])ves$/i, '\1fe' ],
|
40
|
+
[ /(hive)s$/i, '\1' ],
|
41
|
+
[ /(tive)s$/i, '\1' ],
|
42
|
+
[ /([lr])ves$/i, '\1f' ],
|
43
|
+
[ /([^aeiouy]|qu)ies$/i, '\1y' ],
|
44
|
+
[ /(s)eries$/i, '\1eries' ],
|
45
|
+
[ /(m)ovies$/i, '\1ovie' ],
|
46
|
+
[ /(x|ch|ss|sh)es$/i, '\1' ],
|
47
|
+
[ /([m|l])ice$/i, '\1ouse' ],
|
48
|
+
[ /(bus)es$/i, '\1' ],
|
49
|
+
[ /(o)es$/i, '\1' ],
|
50
|
+
[ /(shoe)s$/i, '\1' ],
|
51
|
+
[ /(cris|ax|test)es$/i, '\1is' ],
|
52
|
+
[ /(octop|vir)i$/i, '\1us' ],
|
53
|
+
[ /(alias|status)es$/i, '\1' ],
|
54
|
+
[ /^(ox)en/i, '\1' ],
|
55
|
+
[ /(vert|ind)ices$/i, '\1ex' ],
|
56
|
+
[ /(matr)ices$/i, '\1ix' ],
|
57
|
+
[ /(quiz)zes$/i, '\1' ],
|
58
|
+
[ /(database)s$/i, '\1' ]
|
59
|
+
]
|
60
|
+
|
61
|
+
# Return the singular form of string.
|
62
|
+
def singular
|
63
|
+
result = self.dup
|
64
|
+
SINGULARS.each do |match, replace|
|
65
|
+
rule = Regexp.compile( match )
|
66
|
+
unless match( rule ).nil?
|
67
|
+
result = gsub( rule, replace)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
return result
|
71
|
+
end
|
72
|
+
|
73
|
+
# Return the plural form of a string.
|
74
|
+
def plural
|
75
|
+
result = self.dup
|
76
|
+
PLURALS.each do |match_exp, replacement_exp|
|
77
|
+
unless match(Regexp.compile(match_exp)).nil?
|
78
|
+
result = gsub(Regexp.compile(match_exp), replacement_exp)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
return result
|
82
|
+
end
|
83
|
+
|
84
|
+
# For a module name as "Bio::NeXML" return "nexml".
|
85
|
+
def key
|
86
|
+
result = self.dup
|
87
|
+
if i = rindex( ':' )
|
88
|
+
result = self[ i + 1 .. -1 ]
|
89
|
+
end
|
90
|
+
result.downcase
|
91
|
+
end
|
92
|
+
end # end module Inflections
|
93
|
+
|
94
|
+
String.class_eval do
|
95
|
+
include Inflections
|
96
|
+
end
|
97
|
+
end #end module Mapper
|
98
|
+
end #end module NeXML
|
99
|
+
end #end module Bio
|