diff --git a/Mavenfile b/Mavenfile
index 6318f16..801d471 100644
--- a/Mavenfile
+++ b/Mavenfile
@@ -24,18 +24,6 @@ packaging 'java-gem'
build.final_name '${project.artifactId}_ext'
-profile(:transient) do |t|
- t.plugin(:rspec).configuration[:specSourceDirectory] = 'spec/transient'
-end
-
-profile(:adapter) do |t|
- t.plugin(:rspec).configuration[:specSourceDirectory] = 'spec/abstract_adapter'
-end
-
-profile(:dm) do |t|
- t.plugin(:rspec).configuration[:specSourceDirectory] = 'spec/dm_core'
-end
-
# copy the pom to pom.xml so java IDEs can use it
execute_in_phase(:initialize) do
require 'fileutils'
diff --git a/lib/dm-hibernate-adapter.rb b/lib/dm-hibernate-adapter.rb
index d284216..b363bc0 100644
--- a/lib/dm-hibernate-adapter.rb
+++ b/lib/dm-hibernate-adapter.rb
@@ -47,6 +47,7 @@
require 'dm-hibernate-adapter/hibernate/property_shim'
require 'dm-hibernate-adapter/hibernate/dialects'
require 'dm-hibernate-adapter/hibernate/transaction'
+require 'dm-hibernate-adapter/hibernate/dynamic_java'
require 'dm-hibernate-adapter/hibernate/model'
require 'dm-hibernate-adapter/data_mapper/adapters/hibernate_adapter'
require 'dm-hibernate-adapter/data_mapper/dm-core'
diff --git a/lib/dm-hibernate-adapter/data_mapper/dm-core.rb b/lib/dm-hibernate-adapter/data_mapper/dm-core.rb
index 427fb97..c63f455 100644
--- a/lib/dm-hibernate-adapter/data_mapper/dm-core.rb
+++ b/lib/dm-hibernate-adapter/data_mapper/dm-core.rb
@@ -1,3 +1,18 @@
+# -*- coding: utf-8 -*-
+# Copyright 2011 Douglas Ferreira, Kristian Meier, Piotr Gęga
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
module DataMapper
def self.finalize
Model.descendants.each do |model|
diff --git a/lib/dm-hibernate-adapter/hibernate/dynamic_java.rb b/lib/dm-hibernate-adapter/hibernate/dynamic_java.rb
new file mode 100644
index 0000000..e30dfbe
--- /dev/null
+++ b/lib/dm-hibernate-adapter/hibernate/dynamic_java.rb
@@ -0,0 +1,59 @@
+# -*- coding: utf-8 -*-
+# Copyright 2011 Douglas Ferreira, Kristian Meier, Piotr Gęga
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+module Hibernate::DynamicJava
+
+ def make_java_class(annotations = {})
+ add_class_annotation annotations if !annotations.empty?
+
+ reload = Hibernate.allow_reload
+ become_java!(reload)
+
+ if reload
+ unless java.lang.Thread.currentThread.context_class_loader.is_a? JRubyClassLoader
+ cl = java.lang.Thread.currentThread.context_class_loader
+ if cl.is_a? org.jruby.util.JRubyClassLoader
+ java.lang.Thread.currentThread.context_class_loader = JRubyClassLoader.new(cl)
+ else
+ java.lang.Thread.currentThread.context_class_loader = 'TODO'
+ end
+ end
+
+ java.lang.Thread.currentThread.context_class_loader.register(self.java_class)
+ end
+ self
+ end
+
+ def add_get_accessor(name, target_type, annotations = {}, &blk)
+ get_name = "get#{name.to_s.capitalize}"
+ define_method(get_name.to_sym, &blk)
+ mapped_type = to_java_type(target_type).java_class
+ add_method_signature get_name, [mapped_type]
+ add_method_annotation get_name, annotations if !annotations.empty?
+ end
+
+ def add_set_accessor(name, target_type, annotations = {}, &blk)
+ set_name = "set#{name.to_s.capitalize}"
+ define_method(set_name.to_sym, &blk)
+ mapped_type = to_java_type(target_type).java_class
+ add_method_signature set_name, [JVoid, mapped_type]
+ add_method_annotation set_name, annotations if !annotations.empty?
+ end
+
+ def to_java_type(target_type)
+ target_type = target_type.primitive if target_type.respond_to?(:primitive)
+ TYPES[target_type] || target_type
+ end
+end
diff --git a/lib/dm-hibernate-adapter/hibernate/model.rb b/lib/dm-hibernate-adapter/hibernate/model.rb
index d255a40..83051e1 100644
--- a/lib/dm-hibernate-adapter/hibernate/model.rb
+++ b/lib/dm-hibernate-adapter/hibernate/model.rb
@@ -14,20 +14,10 @@
# limitations under the License.
module Hibernate::Model
-
- TYPES = {
- ::String => java.lang.String,
- ::Integer => java.lang.Integer,
- ::Float => java.lang.Double,
- ::BigDecimal => java.math.BigDecimal,
- ::Date => java.util.Date,
- ::DateTime => java.util.Date,
- ::Time => java.util.Date,
- ::TrueClass => java.lang.Boolean,
- }
-
def self.included(model)
model.extend(ClassMethods)
+ model.extend(Hibernate::DynamicJava)
+ model.extend(PropertyTransformer)
end
module ClassMethods
@@ -47,11 +37,6 @@ def auto_migrate!(repo = nil)
def auto_upgrade!(repo = nil)
end
- def to_java_type(type)
- TYPES[type] || self.to_java_type(type.primitive)
- end
-
-
def to_java_class_name
# http://jira.codehaus.org/browse/JRUBY-4601
"rubyobj."+self.to_s.gsub("::",".")
@@ -66,10 +51,13 @@ def hibernate!
relationship.target_key
end
- properties.each do |prop|
+ filtered_properties = multi_keys? ? properties.reject {|prop| prop.key?} : properties
+ filtered_properties.each do |prop|
discriminator = add_java_property(prop) || discriminator
end
+ add_composite_key_property if multi_keys?
+
# "stolen" from http://github.com/superchris/hibernate
annotation = {
javax.persistence.Entity => { },
@@ -81,140 +69,159 @@ def hibernate!
annotation[javax.persistence.DiscriminatorColumn] = { "name" => discriminator }
end
- add_class_annotation annotation
+ Hibernate.add_model(make_java_class(annotation), self)
- reload = Hibernate.allow_reload
- Hibernate.add_model(become_java!(reload), self)
-
- if reload
-
- unless java.lang.Thread.currentThread.context_class_loader.is_a? JRubyClassLoader
- cl = java.lang.Thread.currentThread.context_class_loader
- if cl.is_a? org.jruby.util.JRubyClassLoader
- java.lang.Thread.currentThread.context_class_loader = JRubyClassLoader.new(cl)
- else
- java.lang.Thread.currentThread.context_class_loader = 'TODO'
- end
- end
-
- java.lang.Thread.currentThread.context_class_loader.register(java_class)
- end
@@logger.debug "become_java! #{java_class}"
else
@@logger.debug "become_java! fired already #{java_class}"
end
end
- private
+ def multi_keys?
+ key.size > 1
+ end
- # "stolen" from http://github.com/superchris/hibernate
- def add_java_property(prop)
- @@logger.info("#{prop.model.name} gets property added #{prop.name}")
- name = prop.name
- type = prop.class
- return name if (type == DataMapper::Property::Discriminator)
+ def add_composite_key_property
+ add_get_accessor(:composite_key, composite_class, javax.persistence.EmbeddedId => {}) do
+ # if !instance_variable_defined?(:@composite_key) || @composite_key.nil?
+ # any_instance_key_defined = !key.map {|prop| attribute_get(prop.name) }.reject {|elem| elem.nil? }.empty
+ # @composite_key = any_instance_key_defined ? composite_class.new : nil
+ # end
+ # @composite_key
+ @composite_key = @@composite_class.new
+ @composite_key.owner = self
+
+ @composite_key
+ end
+
+ add_set_accessor(:composite_key, composite_class) do |value|
+ @composite_key = value
+ @composite_key.owner = self
+ end
+ end
+
+ def composite_class
+ @@composite_class ||= make_composite_class
+ end
+
+ def make_composite_class
+ model = self
+ Class.new do
+ include java.io.Serializable
+ extend Hibernate::DynamicJava
+ extend PropertyTransformer
+
+ attr_accessor :owner
+
+ model.key.each do |prop_key|
+ self.add_java_property(prop_key, :simple_key? => false)
+ end
+ self.make_java_class(javax.persistence.Embeddable => {})
+ end
+ end
+ end
+ module PropertyTransformer
+ @@logger = Slf4r::LoggerFacade.new(Hibernate::Model)
- column_name = prop.field
- annotation = {}
+ def add_java_property(prop, options = {:simple_key? => true})
+ @@logger.info("#{prop.model.name} gets property added #{prop.name}")
+ name = prop.name
+ property_type = prop.class
+ return name if (property_type == DataMapper::Property::Discriminator)
+ make_accessors(name, property_type, build_annotation(prop, options))
+ nil
+ end
+
+ def build_annotation(prop, options)
+ annotation = {}
+
+ if options[:simple_key?]
if prop.serial?
annotation[javax.persistence.Id] = {}
annotation[javax.persistence.GeneratedValue] = {}
- elsif prop.key?
+ elsif prop.key?
annotation[javax.persistence.Id] = {}
end
-
- annotation[javax.persistence.Column] = {
- "unique" => prop.unique?,
- "name" => prop.field
- }
-
- unless prop.index.nil?
- if (prop.index == true)
- annotation[org.hibernate.annotations.Index]
- elsif (prop.index.class == Symbol)
- annotation[org.hibernate.annotations.Index] = {"name" => prop.index.to_s}
- else
- # TODO arrays !!
- #annotation[org.hibernate.annotations.Index] = {"name" => []}
- #prop.index.each do|index|
- # annotation[org.hibernate.annotations.Index]["name"] << index.to_s
- #end
- end
- end
- if prop.required?
- annotation[javax.persistence.Column]["nullable"] = !prop.required?
- end
- if (prop.respond_to?(:length) && !prop.length.nil?)
- annotation[javax.persistence.Column]["length"] = java.lang.Integer.new(prop.length)
- end
- if (prop.respond_to?(:scale) && !prop.scale.nil?)
- annotation[javax.persistence.Column]["scale"] = java.lang.Integer.new(prop.scale)
- end
- if (prop.respond_to?(:precision) && !prop.precision.nil?)
- annotation[javax.persistence.Column]["precision"] = java.lang.Integer.new(prop.precision)
- end
-
- get_name = "get#{name.to_s.capitalize}"
- set_name = "set#{name.to_s.capitalize}"
-
- # TODO Time, Discriminator, EmbededValue
- # to consider: in my opinion those methods should set from/get to java objects...
- if (type == DataMapper::Property::Date)
- class_eval <<-EOT
- def #{set_name.intern}(d)
- attribute_set(:#{name} , d.nil? ? nil : Date.civil(d.year + 1900, d.month + 1, d.date))
- end
- EOT
- class_eval <<-EOT
- def #{get_name.intern}
- d = attribute_get(:#{name} )
- org.joda.time.DateTime.new(d.year, d.month, d.day, 0, 0, 0, 0).to_date if d
- end
- EOT
- elsif (type == DataMapper::Property::DateTime)
- class_eval <<-EOT
- def #{set_name.intern}(d)
- attribute_set(:#{name} , d.nil? ? nil : DateTime.civil(d.year + 1900, d.month + 1, d.date, d.hours, d.minutes, d.seconds))
- end
- EOT
- class_eval <<-EOT
- def #{get_name.intern}
- d = attribute_get(:#{name})
- org.joda.time.DateTime.new(d.year, d.month, d.day, d.hour, d.min, d.sec, 0).to_date if d
- end
- EOT
- elsif (type.to_s == BigDecimal || type == DataMapper::Property::Decimal)
- class_eval <<-EOT
- def #{set_name.intern}(d)
- attribute_set(:#{name} , d.nil? ? nil :#{type}.new(d.to_s))
- end
- EOT
- class_eval <<-EOT
- def #{get_name.intern}
- d = attribute_get(:#{name})
- java.math.BigDecimal.new(d.to_i) if d
- end
- EOT
+ end
+
+ annotation[javax.persistence.Column] = {
+ "unique" => prop.unique?,
+ "name" => prop.field
+ }
+
+ unless prop.index.nil?
+ if (prop.index == true)
+ annotation[org.hibernate.annotations.Index]
+ elsif (prop.index.class == Symbol)
+ annotation[org.hibernate.annotations.Index] = {"name" => prop.index.to_s}
else
- class_eval <<-EOT
- def #{set_name.intern}(d)
- attribute_set(:#{name} , d)
- end
- EOT
- class_eval <<-EOT
- def #{get_name.intern}
- d = attribute_get(:#{name})
- d
- end
- EOT
+ # TODO arrays !!
+ #annotation[org.hibernate.annotations.Index] = {"name" => []}
+ #prop.index.each do|index|
+ # annotation[org.hibernate.annotations.Index]["name"] << index.to_s
+ #end
end
-
- mapped_type = to_java_type(type).java_class
- add_method_signature get_name, [mapped_type]
- add_method_annotation get_name, annotation
- add_method_signature set_name, [JVoid, mapped_type]
- nil
end
+ if prop.required?
+ annotation[javax.persistence.Column]["nullable"] = !prop.required?
+ end
+ if (prop.respond_to?(:length) && !prop.length.nil?)
+ annotation[javax.persistence.Column]["length"] = java.lang.Integer.new(prop.length)
+ end
+ if (prop.respond_to?(:scale) && !prop.scale.nil?)
+ annotation[javax.persistence.Column]["scale"] = java.lang.Integer.new(prop.scale)
+ end
+ if (prop.respond_to?(:precision) && !prop.precision.nil?)
+ annotation[javax.persistence.Column]["precision"] = java.lang.Integer.new(prop.precision)
+ end
+ annotation
+ end
+
+ def make_accessors(name, property_type, accessor_annotations = {})
+ get_accessor_block = AccessorStrategy.get_accessor_block(name, property_type)
+ add_get_accessor(name, property_type, accessor_annotations, &get_accessor_block)
+
+ set_accessor_block = AccessorStrategy.set_accessor_block(name, property_type)
+ add_set_accessor(name, property_type, accessor_annotations, &set_accessor_block)
+ end
end
+
+ module AccessorStrategy
+
+ STRATEGY = {
+ ::Date => {
+ :set => Proc.new {|d| Date.civil(d.year + 1900, d.month + 1, d.date) },
+ :get => Proc.new {|d| org.joda.time.DateTime.new(d.year, d.month, d.day, 0, 0, 0, 0).to_date }
+ },
+ ::DateTime => {
+ :set => Proc.new {|d| DateTime.civil(d.year + 1900, d.month + 1, d.date, d.hours, d.minutes, d.seconds) },
+ :get => Proc.new {|d| org.joda.time.DateTime.new(d.year, d.month, d.day, d.hour, d.min, d.sec, 0).to_date }
+ },
+
+ ::BigDecimal => {
+ :set => Proc.new {|d| BigDecimal.new(d.to_s) },
+ :get => Proc.new {|d| java.math.BigDecimal.new(d.to_s) }
+ },
+ }
+
+ def self.get_accessor_block(property_name, property_type)
+ Proc.new do
+ owner_instance = self.respond_to?(:owner) ? self.owner : self
+ AccessorStrategy.strategy_of(:get, property_name, property_type, owner_instance.attribute_get(property_name.to_sym))
+ end
+ end
+
+ def self.set_accessor_block(property_name, property_type)
+ Proc.new do |value|
+ owner_instance = self.respond_to?(:owner) ? self.owner : self
+ owner_instance.attribute_set(property_name.to_sym, AccessorStrategy.strategy_of(:set, property_name, property_type, value))
+ end
+ end
+
+ def self.strategy_of(strategy_type, property_name, property_type, value)
+ value = STRATEGY[property_type][strategy_type].call(value) if !STRATEGY[property_type].nil? && !value.nil?
+ value
+ end
+ end
end
diff --git a/lib/dm-hibernate-adapter/utils/constants.rb b/lib/dm-hibernate-adapter/utils/constants.rb
index 71359a0..d6dcdf0 100644
--- a/lib/dm-hibernate-adapter/utils/constants.rb
+++ b/lib/dm-hibernate-adapter/utils/constants.rb
@@ -16,3 +16,15 @@
JClass = java.lang.Class
JVoid = java.lang.Void::TYPE
+TYPES = {
+ ::String => java.lang.String,
+ ::Integer => java.lang.Integer,
+ ::Float => java.lang.Double,
+ ::BigDecimal => java.math.BigDecimal,
+ ::Date => java.util.Date,
+ ::DateTime => java.util.Date,
+ ::Time => java.util.Date,
+ ::TrueClass => java.lang.Boolean,
+ ::FalseClass => java.lang.Boolean,
+}
+
diff --git a/pom.xml b/pom.xml
index c10cfaf..a16f6ec 100644
--- a/pom.xml
+++ b/pom.xml
@@ -187,17 +187,29 @@
${project.artifactId}_ext
+
+ de.saumya.mojo
+ rspec-maven-plugin
+ ${jruby.plugins.version}
+
+
+
+ test
+
+
+
+
de.saumya.mojo
gem-maven-plugin
${jruby.plugins.version}
true
- lib/dm-hibernate-adapter_ext.jar,lib/dm-hibernate-adapter.rb,lib/dm-hibernate-adapter,lib/dm-hibernate-adapter/data_mapper,lib/dm-hibernate-adapter/data_mapper/adapters,lib/dm-hibernate-adapter/data_mapper/adapters/hibernate_adapter.rb,lib/dm-hibernate-adapter/hibernate,lib/dm-hibernate-adapter/hibernate/dialects.rb,lib/dm-hibernate-adapter/hibernate/hibernate.rb,lib/dm-hibernate-adapter/hibernate/model.rb,lib/dm-hibernate-adapter/hibernate/property_shim.rb,lib/dm-hibernate-adapter/hibernate/transaction.rb,lib/dm-hibernate-adapter/utils,lib/dm-hibernate-adapter/utils/constants.rb,lib/dm-hibernate-adapter/utils/logger.rb,spec/adapter_spec.rb,spec/rcov.opts,spec/spec.opts,spec/spec_helper.rb
+ lib/dm-hibernate-adapter_ext.jar,lib/dm-hibernate-adapter.rb,lib/dm-hibernate-adapter,lib/dm-hibernate-adapter/hibernate,lib/dm-hibernate-adapter/hibernate/property_shim.rb,lib/dm-hibernate-adapter/hibernate/hibernate.rb,lib/dm-hibernate-adapter/hibernate/model.rb,lib/dm-hibernate-adapter/hibernate/dynamic_java.rb,lib/dm-hibernate-adapter/hibernate/model.rb.~8afce901e5b51d010121b5545cffcd4a1e913bdb~,lib/dm-hibernate-adapter/hibernate/dialects.rb,lib/dm-hibernate-adapter/hibernate/transaction.rb,lib/dm-hibernate-adapter/spec,lib/dm-hibernate-adapter/spec/setup.rb,lib/dm-hibernate-adapter/data_mapper,lib/dm-hibernate-adapter/data_mapper/adapters,lib/dm-hibernate-adapter/data_mapper/adapters/hibernate_adapter.rb,lib/dm-hibernate-adapter/data_mapper/dm-core.rb,lib/dm-hibernate-adapter/utils,lib/dm-hibernate-adapter/utils/constants.rb,lib/dm-hibernate-adapter/utils/logger.rb,spec/spec_helper.rb,spec/rcov.opts,spec/cpk_spec.rb,spec/target,spec/target/rubygems-rake-maven-plugin,spec/spec.opts,spec/adapter_spec.rb
dm-hibernate-adapter.gemspec
java
1.3.1]]>
- spec/adapter_spec.rb
+ spec/cpk_spec.rb,spec/adapter_spec.rb
@@ -213,62 +225,6 @@
-
- de.saumya.mojo
- rspec-maven-plugin
- ${jruby.plugins.version}
-
-
-
- test
-
-
-
-
-
-
- transient
-
-
-
- de.saumya.mojo
- rspec-maven-plugin
-
- spec/transient
-
-
-
-
-
-
- adapter
-
-
-
- de.saumya.mojo
- rspec-maven-plugin
-
- spec/abstract_adapter
-
-
-
-
-
-
- dm
-
-
-
- de.saumya.mojo
- rspec-maven-plugin
-
- spec/dm_core
-
-
-
-
-
-
diff --git a/spec/adapter_spec.rb b/spec/adapter_spec.rb
index 3277274..b39984c 100644
--- a/spec/adapter_spec.rb
+++ b/spec/adapter_spec.rb
@@ -19,6 +19,6 @@
require 'dm-core/spec/shared/adapter_spec'
describe DataMapper::Adapters::HibernateAdapter do
- it_should_behave_like 'An Adapter'
+ it_should_behave_like 'An Adapter'
end
diff --git a/spec/cpk_spec.rb b/spec/cpk_spec.rb
new file mode 100644
index 0000000..54f4cad
--- /dev/null
+++ b/spec/cpk_spec.rb
@@ -0,0 +1,8 @@
+require 'spec_helper'
+
+dm_core_spec_path = $:.select {|path| path =~ /dm-core/ }.first.gsub(/lib$/, 'spec')
+
+# load from dm-core specs still not working
+# spec_helper not work with multiples specs
+# cpk implementation are broken in 'should be able to access the child'
+# require "#{dm_core_spec_path}/public/associations/many_to_one_with_boolean_cpk_spec"
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index c90bebe..537c323 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -18,7 +18,13 @@
require 'dm-core/spec/lib/pending_helpers'
require 'dm-core/spec/lib/adapter_helpers'
-require 'dm-core/spec/lib/collection_helpers'
+require 'dm-core/spec/lib/spec_helper'
+
+require 'dm-core/spec/setup'
+
+ENV['ADAPTER'] ||= 'hibernate'
+ENV['ADAPTER_SUPPORTS'] = 'all'
+ENV['RELOAD'] = 'true'
DB_CONFIGS = {
:H2_EMB => { :adapter => "hibernate", :dialect => "H2", :username => "sa", :url => "jdbc:h2:target/jibernate" },
@@ -32,12 +38,20 @@
Spec::Runner.configure do |config|
config.include DataMapper::Spec::PendingHelpers
- # config.include DataMapper::Spec::AdaptersHelpers
- # config.include DataMapper::Spec::CollectionHelpers
+ config.extend( DataMapper::Spec::Adapters::Helpers)
+ config.include(DataMapper::Spec::Helpers)
config.before :all do
- @adapter = DataMapper.setup(:default, DB_CONFIGS[(ENV['DIALECT'] || :H2_EMB).to_sym])
- DataMapper.auto_migrate!
+ #TODO: loading multiples specs not work
+ # we need to avoid setup adapter here
+ @adapter = DataMapper.setup(:default, DB_CONFIGS[(ENV['DIALECT'] || :H2_EMB).to_sym].merge(:reload => 'true'))
+ DataMapper.auto_migrate!
+ end
+
+ config.after :all do
+ #DataMapper::Spec.cleanup_models
+ # DataMapper::Spec.remove_ivars(self, instance_variables.reject { |ivar| ivar[0, 2] == '@_' })
+ # DataMapper::Spec.remove_ivars(Spec::Matchers.last_matcher, %w[ @expected ])
end
end