caruby-core 1.4.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/History.txt +4 -0
- data/LEGAL +5 -0
- data/LICENSE +22 -0
- data/README.md +51 -0
- data/doc/website/css/site.css +1 -5
- data/doc/website/images/avatar.png +0 -0
- data/doc/website/images/favicon.ico +0 -0
- data/doc/website/images/logo.png +0 -0
- data/doc/website/index.html +82 -0
- data/doc/website/install.html +87 -0
- data/doc/website/quick_start.html +87 -0
- data/doc/website/tissue.html +85 -0
- data/doc/website/uom.html +10 -0
- data/lib/caruby.rb +3 -0
- data/lib/caruby/active_support/README.txt +2 -0
- data/lib/caruby/active_support/core_ext/string.rb +7 -0
- data/lib/caruby/active_support/core_ext/string/inflections.rb +167 -0
- data/lib/caruby/active_support/inflections.rb +55 -0
- data/lib/caruby/active_support/inflector.rb +398 -0
- data/lib/caruby/cli/application.rb +36 -0
- data/lib/caruby/cli/command.rb +169 -0
- data/lib/caruby/csv/csv_mapper.rb +157 -0
- data/lib/caruby/csv/csvio.rb +185 -0
- data/lib/caruby/database.rb +252 -0
- data/lib/caruby/database/fetched_matcher.rb +66 -0
- data/lib/caruby/database/persistable.rb +432 -0
- data/lib/caruby/database/persistence_service.rb +162 -0
- data/lib/caruby/database/reader.rb +599 -0
- data/lib/caruby/database/saved_merger.rb +131 -0
- data/lib/caruby/database/search_template_builder.rb +59 -0
- data/lib/caruby/database/sql_executor.rb +75 -0
- data/lib/caruby/database/store_template_builder.rb +200 -0
- data/lib/caruby/database/writer.rb +469 -0
- data/lib/caruby/domain/annotatable.rb +25 -0
- data/lib/caruby/domain/annotation.rb +23 -0
- data/lib/caruby/domain/attribute_metadata.rb +447 -0
- data/lib/caruby/domain/java_attribute_metadata.rb +160 -0
- data/lib/caruby/domain/merge.rb +91 -0
- data/lib/caruby/domain/properties.rb +95 -0
- data/lib/caruby/domain/reference_visitor.rb +289 -0
- data/lib/caruby/domain/resource_attributes.rb +528 -0
- data/lib/caruby/domain/resource_dependency.rb +205 -0
- data/lib/caruby/domain/resource_introspection.rb +159 -0
- data/lib/caruby/domain/resource_metadata.rb +117 -0
- data/lib/caruby/domain/resource_module.rb +285 -0
- data/lib/caruby/domain/uniquify.rb +38 -0
- data/lib/caruby/import/annotatable_class.rb +28 -0
- data/lib/caruby/import/annotation_class.rb +27 -0
- data/lib/caruby/import/annotation_module.rb +67 -0
- data/lib/caruby/import/java.rb +338 -0
- data/lib/caruby/migration/migratable.rb +167 -0
- data/lib/caruby/migration/migrator.rb +533 -0
- data/lib/caruby/migration/resource.rb +8 -0
- data/lib/caruby/migration/resource_module.rb +11 -0
- data/lib/caruby/migration/uniquify.rb +20 -0
- data/lib/caruby/resource.rb +969 -0
- data/lib/caruby/util/attribute_path.rb +46 -0
- data/lib/caruby/util/cache.rb +53 -0
- data/lib/caruby/util/class.rb +99 -0
- data/lib/caruby/util/collection.rb +1053 -0
- data/lib/caruby/util/controlled_value.rb +35 -0
- data/lib/caruby/util/coordinate.rb +75 -0
- data/lib/caruby/util/domain_extent.rb +49 -0
- data/lib/caruby/util/file_separator.rb +65 -0
- data/lib/caruby/util/inflector.rb +20 -0
- data/lib/caruby/util/log.rb +95 -0
- data/lib/caruby/util/math.rb +12 -0
- data/lib/caruby/util/merge.rb +59 -0
- data/lib/caruby/util/module.rb +34 -0
- data/lib/caruby/util/options.rb +92 -0
- data/lib/caruby/util/partial_order.rb +36 -0
- data/lib/caruby/util/person.rb +119 -0
- data/lib/caruby/util/pretty_print.rb +184 -0
- data/lib/caruby/util/properties.rb +112 -0
- data/lib/caruby/util/stopwatch.rb +66 -0
- data/lib/caruby/util/topological_sync_enumerator.rb +53 -0
- data/lib/caruby/util/transitive_closure.rb +45 -0
- data/lib/caruby/util/tree.rb +48 -0
- data/lib/caruby/util/trie.rb +37 -0
- data/lib/caruby/util/uniquifier.rb +30 -0
- data/lib/caruby/util/validation.rb +48 -0
- data/lib/caruby/util/version.rb +56 -0
- data/lib/caruby/util/visitor.rb +351 -0
- data/lib/caruby/util/weak_hash.rb +36 -0
- data/lib/caruby/version.rb +3 -0
- metadata +186 -0
@@ -0,0 +1,285 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'caruby/util/collection'
|
3
|
+
require 'caruby/util/log'
|
4
|
+
|
5
|
+
module CaRuby
|
6
|
+
class JavaIncludeError < StandardError; end;
|
7
|
+
|
8
|
+
# The application and database connection access command line options.
|
9
|
+
ACCESS_OPTS = [
|
10
|
+
[:user, "--user USER", "the application login user"],
|
11
|
+
[:password, "--password PSWD", "the application login password"],
|
12
|
+
[:host, "--host HOST", "the application host name"],
|
13
|
+
[:database_host, "--database_host HOST", "the database host name"],
|
14
|
+
[:database_type, "--database_type TYPE", "the database type (mysql or oracle)"],
|
15
|
+
[:database_driver, "--database_driver DRIVER", "the database driver"],
|
16
|
+
[:database_port, "--database_port PORT", Integer, "the database port number"],
|
17
|
+
[:database, "--database NAME", "the database name"],
|
18
|
+
[:database_user, "--database_user USER", "the database login user"],
|
19
|
+
[:database_password, "--database_password PSWD", "the database login password"]
|
20
|
+
]
|
21
|
+
|
22
|
+
# Importable extends a Module with Java class support.
|
23
|
+
# The calling module must implement the following instance variables:
|
24
|
+
# * +*java_package+ - the module Java package name
|
25
|
+
# * +@mixin+ - the module which scopes the domain objects
|
26
|
+
# See the ClinicalTrials module for an example.
|
27
|
+
#
|
28
|
+
# The application properties hash specifies the startup information,
|
29
|
+
# including the user, password and application Java jar library path.
|
30
|
+
# The properties are read from a property file. See CaRuby::Properties for
|
31
|
+
# more information.
|
32
|
+
#
|
33
|
+
# A Java class is imported into Ruby either by directly calling the
|
34
|
+
# extended module {#java_import} method or on demand.
|
35
|
+
# Import on demand is induced by a reference to the class, e.g.:
|
36
|
+
# module ClinicalTrials
|
37
|
+
# extend Importable
|
38
|
+
#
|
39
|
+
# def java_package
|
40
|
+
# 'org.nci.ctms'
|
41
|
+
# end
|
42
|
+
# ...
|
43
|
+
# enables references by name to a +ClinicalTrials+ Ruby class wrapper of a
|
44
|
+
# +org.nci.ctms+ Java class without an import statement, e.g.:
|
45
|
+
# ClinicalTrials::Participant.new
|
46
|
+
# without defining the +Participant+ Ruby class.
|
47
|
+
module ResourceModule
|
48
|
+
# Adds the given klass to this ResourceModule. The class is extended with ResourceMetadata methods.
|
49
|
+
def add_class(klass)
|
50
|
+
@resource_module__loaded ||= Set.new
|
51
|
+
# add superclass if necessary
|
52
|
+
unless @resource_module__loaded.include?(klass.superclass) or klass.superclass == Java::JavaLang::Object then
|
53
|
+
# the domain module includes the superclass on demand
|
54
|
+
const_get(klass.superclass.name[/\w+$/].to_sym)
|
55
|
+
end
|
56
|
+
ResourceMetadata.extend_class(klass, self)
|
57
|
+
@resource_module__loaded << klass
|
58
|
+
end
|
59
|
+
|
60
|
+
# Reinclude the mixin in all loaded classes.
|
61
|
+
def mixin_changed
|
62
|
+
@resource_module__loaded.each { |klass| klass.instance_eval { include CaRuby::Resource } }
|
63
|
+
end
|
64
|
+
|
65
|
+
def access_properties
|
66
|
+
@resource_module__props ||= load_access_properties
|
67
|
+
end
|
68
|
+
|
69
|
+
# Loads the application start-up properties in the given file path.
|
70
|
+
# The default file path is a period followed by the lower-case application name in the home directory,
|
71
|
+
# e.g. +~/.clincaltrials+.
|
72
|
+
#
|
73
|
+
# The property file format is a series of property definitions in the form _property_ +=+ _value_.
|
74
|
+
# The supported properties include the following:
|
75
|
+
# * +path+ - the application client Java jar file directories
|
76
|
+
# * +user+ - the application service login
|
77
|
+
# * +password+ - the application service password
|
78
|
+
# * +database+ - the application database name
|
79
|
+
# * +database_user+ - the application database connection userid
|
80
|
+
# * +database_password+ - the application database connection password
|
81
|
+
# * :database_host - the application database connection host (default +localhost+)
|
82
|
+
# * +database_type+ - the application database type, + mysql+ or +oracle+ (default +mysql+)
|
83
|
+
# * +database_driver+ - the application database connection driver (default is the database type default)
|
84
|
+
# * +database_port+ - the application database connection port
|
85
|
+
# # The +path+ value is one or more directories separated by a semi-colon(;) or colon (:)
|
86
|
+
# # The jar files in the +path+ directory are added to the caRuby execution Java classpath.
|
87
|
+
def load_access_properties(file=nil)
|
88
|
+
# If a file was specified, then it must exist.
|
89
|
+
if file and not File.exists?(file) then
|
90
|
+
raise ArgumentError.new("Application access properties file does not exist: #{file}")
|
91
|
+
end
|
92
|
+
# the access properties
|
93
|
+
@resource_module__props ||= {}
|
94
|
+
# If no file was specified, then try the default.
|
95
|
+
# If the default does not exist, then use the empty properties hash.
|
96
|
+
# It is not an error to omit access properties, since the application domain classes
|
97
|
+
# can still be used but not queried or saved.
|
98
|
+
file ||= default_properties_file || return
|
99
|
+
|
100
|
+
logger.info("Loading application properties from #{file}...")
|
101
|
+
File.open(file).map do |line|
|
102
|
+
# match the tolerant property definition
|
103
|
+
match = PROP_DEF_REGEX.match(line.chomp) || next
|
104
|
+
# the property [name, value] tokens
|
105
|
+
tokens = match.captures
|
106
|
+
name = tokens.first.to_sym
|
107
|
+
value = tokens.last
|
108
|
+
# capture the property
|
109
|
+
@resource_module__props[name] = value
|
110
|
+
end
|
111
|
+
|
112
|
+
# Look for environment overrides preceded by the uppercase module name, e.g. CATISSUE
|
113
|
+
# for the CaTissue module.
|
114
|
+
env_prefix = name[/\w+$/].upcase
|
115
|
+
ACCESS_OPTS.each do |spec|
|
116
|
+
# the access option symbol is the first specification item
|
117
|
+
opt = spec[0]
|
118
|
+
# the envvar, e.g. CATISSUE_USER
|
119
|
+
ev = "#{env_prefix}_#{opt.to_s.upcase}"
|
120
|
+
# the envvar value
|
121
|
+
value = ENV[ev] || next
|
122
|
+
# override the file property with the envar value
|
123
|
+
@resource_module__props[opt] = value
|
124
|
+
logger.info("Set application property #{opt} from environment variable #{ev}.")
|
125
|
+
end
|
126
|
+
|
127
|
+
# load the Java application jar path
|
128
|
+
path_ev = "#{env_prefix}_PATH"
|
129
|
+
path = ENV[path_ev] || @resource_module__props[:path]
|
130
|
+
Java.add_path(path) if path
|
131
|
+
|
132
|
+
@resource_module__props
|
133
|
+
end
|
134
|
+
|
135
|
+
# Loads the Ruby source files in the given directory.
|
136
|
+
def load_dir(dir)
|
137
|
+
# load the properties on demand
|
138
|
+
load_access_properties if @resource_module__props.nil?
|
139
|
+
# the domain class definitions
|
140
|
+
sources = Dir.glob(File.join(dir, "*.rb"))
|
141
|
+
|
142
|
+
# autoload the domain classes to ensure that definitions are picked up on demand in class hierarchy order
|
143
|
+
sym_file_hash = {}
|
144
|
+
sources.each do |file|
|
145
|
+
base_name = File.basename(file, ".rb")
|
146
|
+
sym = base_name.camelize.to_sym
|
147
|
+
sym_file_hash[sym] = file
|
148
|
+
autoload(sym, file)
|
149
|
+
end
|
150
|
+
|
151
|
+
# load the domain class definitions
|
152
|
+
sym_file_hash.each do |sym, file|
|
153
|
+
require file
|
154
|
+
end
|
155
|
+
|
156
|
+
# print the loaded classes to the log
|
157
|
+
sym_file_hash.each_key do |sym|
|
158
|
+
# it is not an error if the inferred class name is not loaded, since only the Java application classes
|
159
|
+
# are required to be the camel-case form of the file names.
|
160
|
+
klass = const_get(sym) rescue next
|
161
|
+
logger.info("#{klass.pp_s}")
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# Extends the mod module with Java class support. See the class documentation for details.
|
166
|
+
def const_missing(symbol)
|
167
|
+
autoload?(symbol) ? super : import_domain_class(symbol)
|
168
|
+
end
|
169
|
+
|
170
|
+
# Imports the domain Java class with specified class name_or_sym.
|
171
|
+
# This method enables the domain class extensions for storing and retrieving domain objects.
|
172
|
+
# The class is added to this module.
|
173
|
+
#
|
174
|
+
# The optional block overrides the native Java property access wrappers.
|
175
|
+
# For example:
|
176
|
+
# ClinicalTrials.java_import('edu.wustl.catissuecore.domain.Study') do
|
177
|
+
# def study_code=(value)
|
178
|
+
# value = value.to_s if Integer === value
|
179
|
+
# setStudyCode(value)
|
180
|
+
# end
|
181
|
+
# end
|
182
|
+
# imports the ClinicalTrials Study class as ClinicalTrials::Study and overrides the
|
183
|
+
# +study_code+ setter method.
|
184
|
+
#
|
185
|
+
# Convenience aliases are added to the imported class, e.g. attribute +studyParticipantCollection+
|
186
|
+
# is aliased as +study_participants+. Specifically, each attribute reader and writer is aliased with
|
187
|
+
# the lower-case, underscore equivalent and a name ending in 'Collection' is changed to plural.
|
188
|
+
# Pluralization is smart, e.g. +studyCollection+ is aliased to +studies+ rather than +studys+.
|
189
|
+
#
|
190
|
+
# The optional aliases argument consists of additional alias => standard attribute associations.
|
191
|
+
# The optional owner_attr argument is a non-Java annotation owner attribute.
|
192
|
+
def import_domain_class(name_or_sym)
|
193
|
+
name = name_or_sym.to_s
|
194
|
+
if name.include?('.') then
|
195
|
+
symbol = name[/[A-Z]\w*$/].to_sym
|
196
|
+
else
|
197
|
+
symbol = name_or_sym.to_sym
|
198
|
+
name = [@java_package, name].join('.')
|
199
|
+
end
|
200
|
+
# check if the class is already defined
|
201
|
+
if const_defined?(symbol) then
|
202
|
+
klass = const_get(symbol)
|
203
|
+
if domain?(klass) then
|
204
|
+
logger.warn("Attempt to import #{self.qp} class twice: #{symbol}.") and return klass
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
# import the Java class
|
209
|
+
logger.debug { "Importing #{qp} Java class #{symbol}..." }
|
210
|
+
begin
|
211
|
+
java_import(name)
|
212
|
+
rescue Exception => e
|
213
|
+
raise JavaIncludeError.new("#{symbol} is not a #{qp} Java class - #{e.message}")
|
214
|
+
end
|
215
|
+
|
216
|
+
# the imported Java class is registered as a constant in this module
|
217
|
+
klass = const_get(symbol)
|
218
|
+
# the Resource import stack
|
219
|
+
@import_stack ||= []
|
220
|
+
@import_stack.push klass
|
221
|
+
# include the Resource mixin into the imported class
|
222
|
+
mixin = @mixin
|
223
|
+
klass.instance_eval { include mixin }
|
224
|
+
logger.info("Imported #{qp} class #{klass.qp}")
|
225
|
+
# if we are back to top of the stack, then print the imported Resources
|
226
|
+
if klass == @import_stack.first then
|
227
|
+
# a referenced class could be imported on demand in the course of printing a referencing class;
|
228
|
+
# the referenced class is then pushed onto the stack. thus, the stack can grow during the
|
229
|
+
# course of printing, but each imported class is consumed and printed in the end.
|
230
|
+
until @import_stack.empty? do
|
231
|
+
ref = @import_stack.pop
|
232
|
+
logger.debug { ref.pp_s }
|
233
|
+
end
|
234
|
+
end
|
235
|
+
klass
|
236
|
+
end
|
237
|
+
|
238
|
+
# Returns the domain class for class_name, or nil if none in this module.
|
239
|
+
def domain_type_with_name(class_name)
|
240
|
+
pkg, base = split_class_name(class_name)
|
241
|
+
return unless pkg.nil? or pkg == @java_package
|
242
|
+
begin
|
243
|
+
type = const_get(base)
|
244
|
+
rescue JavaIncludeError
|
245
|
+
# no such domain type; not an error.
|
246
|
+
# other exceptions indicate that there was a domain type but could not be loaded; these exceptions propagate up the call stack
|
247
|
+
logger.debug("#{base} is not a #{qp} Java class.")
|
248
|
+
return
|
249
|
+
end
|
250
|
+
type if type < Resource
|
251
|
+
end
|
252
|
+
|
253
|
+
private
|
254
|
+
|
255
|
+
# The property/value matcher, e.g.:
|
256
|
+
# host: jacardi
|
257
|
+
# host = jacardi
|
258
|
+
# host=jacardi
|
259
|
+
# name: J. Edgar Hoover
|
260
|
+
# but not:
|
261
|
+
# # host: jacardi
|
262
|
+
# The captures are the trimmed property and value
|
263
|
+
PROP_DEF_REGEX = /^(\w+)(?:\s*[:=]\s*)([^#]+)/
|
264
|
+
|
265
|
+
def default_properties_file
|
266
|
+
home = ENV['HOME'] || '~'
|
267
|
+
file = File.expand_path("#{home}/.#{name[/\w+$/].downcase}")
|
268
|
+
if File.exists?(file) then
|
269
|
+
file
|
270
|
+
else
|
271
|
+
logger.warn { "Default application property file not found: #{file}." }
|
272
|
+
nil
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
# Returns the [package prefix, base class symbol] pair.
|
277
|
+
def split_class_name(class_name)
|
278
|
+
# the package prefix, including the period
|
279
|
+
package = Java.java_package_name(class_name)
|
280
|
+
# remove the package and base class name
|
281
|
+
base = package.nil? ? class_name : class_name[package.length + 1..-1]
|
282
|
+
[package, base.to_sym]
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'caruby/util/uniquifier'
|
3
|
+
require 'caruby/util/collection'
|
4
|
+
|
5
|
+
module CaRuby
|
6
|
+
module Resource
|
7
|
+
# The Unique mix-in makes values unique within the scope of a Resource class.
|
8
|
+
module Unique
|
9
|
+
# Makes the given String value unique in the context of this object's class.
|
10
|
+
# @return nil if value is nil
|
11
|
+
# Raises TypeError if value is neither nil nor a String.
|
12
|
+
def uniquify_value(value)
|
13
|
+
unless String === value or value.nil? then
|
14
|
+
raise TypeError.new("Cannot uniquify #{qp} non-String value #{value}")
|
15
|
+
end
|
16
|
+
ResourceUniquifier.instance.uniquify(self, value)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# The ResourceUniquifier singleton makes Resource instance attribute values unique.
|
22
|
+
class ResourceUniquifier
|
23
|
+
include Singleton
|
24
|
+
|
25
|
+
def initialize
|
26
|
+
@cache = LazyHash.new { Hash.new }
|
27
|
+
end
|
28
|
+
|
29
|
+
# Makes the obj attribute value unique, or returns nil if value is nil.
|
30
|
+
def uniquify(obj, value)
|
31
|
+
@cache[obj.class][value] ||= value.uniquify if value
|
32
|
+
end
|
33
|
+
|
34
|
+
def clear
|
35
|
+
@cache.clear
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'caruby/util/class'
|
2
|
+
require 'caruby/util/collection'
|
3
|
+
require 'caruby/import/annotation_module'
|
4
|
+
|
5
|
+
module JavaImport
|
6
|
+
# AnnotatableClass adds Annotation modules to an annotation anchor's domain module.
|
7
|
+
module AnnotatableClass
|
8
|
+
|
9
|
+
def self.extended(klass)
|
10
|
+
klass.class_eval { include CaRuby::Annotatable }
|
11
|
+
end
|
12
|
+
|
13
|
+
def annotation_modules
|
14
|
+
@annotation_modules ||= []
|
15
|
+
end
|
16
|
+
|
17
|
+
# Creates a new AnnotationModule anchored by this class for the given package and database service.
|
18
|
+
def create_annotation_module(package, service)
|
19
|
+
annotation_modules << AnnotationModule.create_annotation_module(self, package, service)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns the class with the given unqualified name in one of this AnnotationClass's JavaImport::AnnotationModule
|
23
|
+
# modules, or nil if no such class.
|
24
|
+
def annotation_class(name)
|
25
|
+
annotation_modules.detect_value { |mod| annotation_modules.const_get(name) rescue nil }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module JavaImport
|
2
|
+
# AnnotationClass extends a domain class for an annotation class scoped by an annotation module.
|
3
|
+
# The extended class must contain the +@anchor_class+ and +@annotation_module+ instance variables.
|
4
|
+
module AnnotationClass
|
5
|
+
|
6
|
+
# Dynamically creates a new reference attribute if the given attribute symbol is the underscore
|
7
|
+
# form of this Annotation's anchor class.
|
8
|
+
#
|
9
|
+
#@param [Symbol] attribute the missing attribute
|
10
|
+
def attribute_missing(attribute)
|
11
|
+
# delegate to super to print an error if no class
|
12
|
+
super unless attribute.to_s == anchor_class.qp.underscore
|
13
|
+
# add the annotation attribute to the anchor class and the anchor attribute to this class
|
14
|
+
anchor_class.add_annotation(self)
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [Class] the annotated class
|
18
|
+
def anchor_class
|
19
|
+
@anchor_class
|
20
|
+
end
|
21
|
+
|
22
|
+
# @return [Module] the module which scopes this AnnotationClass
|
23
|
+
def annotation_module
|
24
|
+
@annotation_module
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'caruby/util/class'
|
2
|
+
require 'caruby/util/collection'
|
3
|
+
require 'caruby/import/importable'
|
4
|
+
require 'caruby/import/annotation_class'
|
5
|
+
|
6
|
+
module JavaImport
|
7
|
+
# AnnotationModule creates annotation package modules within a domain module as a context for importing annotation classes.
|
8
|
+
module AnnotationModule
|
9
|
+
include Importable
|
10
|
+
|
11
|
+
# Creates a new AnnotationModule in the given domain_module from the given annotation package and service.
|
12
|
+
def self.create_annotation_module(anchor_class, package, service)
|
13
|
+
domain_module = anchor_class.domain_module
|
14
|
+
# make parent modules for each package component
|
15
|
+
mod = package.split('.').inject(anchor_class.domain_module) do |parent, name|
|
16
|
+
mod_id = name.camelize.to_sym
|
17
|
+
if parent.const_defined?(mod_id) then
|
18
|
+
parent.const_get(mod_id)
|
19
|
+
else
|
20
|
+
parent.const_set(mod_id, Module.new)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
# the terminal module is the AnnotationModule
|
24
|
+
mod.extend(self)
|
25
|
+
# initialize the java_package, service and empty access_properties
|
26
|
+
mod.module_eval do
|
27
|
+
@anchor_class = anchor_class
|
28
|
+
@java_package = package
|
29
|
+
@service = service
|
30
|
+
@resource_module__props = CaRuby::Domain::Properties.new
|
31
|
+
end
|
32
|
+
mod_name = mod.name[anchor_class.domain_module.name.length..-1]
|
33
|
+
logger.debug { "Created annotation module #{mod}." }
|
34
|
+
mod
|
35
|
+
end
|
36
|
+
|
37
|
+
def java_package
|
38
|
+
@java_package
|
39
|
+
end
|
40
|
+
|
41
|
+
def service
|
42
|
+
@service
|
43
|
+
end
|
44
|
+
|
45
|
+
def anchor_class
|
46
|
+
@anchor_class
|
47
|
+
end
|
48
|
+
|
49
|
+
def access_properties
|
50
|
+
@resource_module__props
|
51
|
+
end
|
52
|
+
|
53
|
+
# Imports the domain Java class with specified class_name by delegating to Importable and
|
54
|
+
# augmenting the importer to include CaRuby::Annotation in each imported class.
|
55
|
+
def import_domain_class(class_name)
|
56
|
+
anchor_class = @anchor_class
|
57
|
+
ann_mod = self
|
58
|
+
klass = super(class_name) do
|
59
|
+
include CaRuby::Annotation
|
60
|
+
@anchor_class = anchor_class
|
61
|
+
@annotation_module = ann_mod
|
62
|
+
yield if block_given?
|
63
|
+
end
|
64
|
+
klass.extend(AnnotationClass)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|