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