reality-facets 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,98 @@
1
+ #
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+ #
14
+
15
+ module Reality #nodoc
16
+ module Facets #nodoc
17
+
18
+ # Module that should be mixed into all model objects that have facets.
19
+ # Implementation should define a method `facet_container` that retrieves
20
+ # the associated manager.
21
+ module Faceted
22
+
23
+ def facet_enabled?(facet_key)
24
+ method_name = :"#{facet_key}?"
25
+ self.respond_to?(method_name) ? self.send(method_name) : false
26
+ end
27
+
28
+ def facet(facet_key)
29
+ self.send(facet_key)
30
+ end
31
+
32
+ def enabled_facets
33
+ (@enabled_facets ||= []).dup
34
+ end
35
+
36
+ def enable_facet(key)
37
+ Facets.error("Facet #{key} already enabled.") if self.facet_enabled?(key)
38
+ self.activate_facet(key)
39
+ end
40
+
41
+ def enable_facets!(*keys)
42
+ keys = keys[0] if keys.size == 1 && keys[0].is_a?(Array)
43
+ keys.flatten.each do |key|
44
+ enable_facet(key)
45
+ end
46
+ end
47
+
48
+ def enable_facets(*keys)
49
+ keys = keys[0] if keys.size == 1 && keys[0].is_a?(Array)
50
+ keys.flatten.each do |key|
51
+ self.activate_facet(key) unless self.facet_enabled?(key)
52
+ end
53
+ end
54
+
55
+ def disable_facet(key)
56
+ Facets.error("Facet #{key} not enabled.") unless self.facet_enabled?(key)
57
+ self.deactivate_facet(key)
58
+ end
59
+
60
+ def disable_facets!(*keys)
61
+ keys = keys[0] if keys.size == 1 && keys[0].is_a?(Array)
62
+ keys.flatten.each do |key|
63
+ disable_facet(key)
64
+ end
65
+ end
66
+
67
+ def disable_facets(*keys)
68
+ keys = keys[0] if keys.size == 1 && keys[0].is_a?(Array)
69
+ keys.flatten.each do |key|
70
+ disable_facet(key) if self.facet_enabled?(key)
71
+ end
72
+ end
73
+
74
+ def disable_facets_not_in(keys)
75
+ keys = keys[0] if keys.size == 1 && keys[0].is_a?(Array)
76
+ (self.enabled_facets - keys).each do |facet_key|
77
+ self.disable_facet(facet_key) if self.facet_enabled?(facet_key)
78
+ end
79
+ end
80
+
81
+ protected
82
+
83
+ def extension_point(action)
84
+ Facets.debug "Facet '#{self}' extension point #{action} started"
85
+ facet_container.extension_point(self, action)
86
+ Facets.debug "Facet '#{self}' extension point #{action} completed"
87
+ end
88
+
89
+ def activate_facet(facet_key)
90
+ facet_container.activate_facet(self, facet_key)
91
+ end
92
+
93
+ def deactivate_facet(facet_key)
94
+ facet_container.deactivate_facet(self, facet_key)
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,143 @@
1
+ #
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+ #
14
+
15
+ module Reality #nodoc
16
+ module Facets #nodoc
17
+
18
+ # A descriptor describing a base type in the system model.
19
+ class Target
20
+ def initialize(target_manager, model_class, key, container_key, options)
21
+ @target_manager = target_manager
22
+ @model_class = model_class
23
+ @key = key.to_sym
24
+ @access_method = (options[:access_method] || Reality::Naming.pluralize(@key)).to_sym
25
+ @inverse_access_method = (options[:inverse_access_method] || @key).to_sym
26
+ @container_key = container_key.nil? ? nil : container_key.to_sym
27
+ @extension_module = nil
28
+
29
+ if @container_key && !target_manager.target_by_key?(@container_key)
30
+ raise "Target '#{key}' defines container as '#{@container_key}' but no such target exists."
31
+ end
32
+
33
+ @target_manager.send(:register_target, self)
34
+ end
35
+
36
+ attr_reader :target_manager
37
+ attr_reader :model_class
38
+ attr_reader :key
39
+ attr_reader :container_key
40
+ attr_reader :access_method
41
+ attr_reader :inverse_access_method
42
+
43
+ def extension_module
44
+ unless @extension_module
45
+ outer_module = target_manager.container.facet_definitions
46
+ module_name = "#{::Reality::Naming.pascal_case(key)}Extension"
47
+ outer_module.class_eval "module #{module_name}\n end"
48
+ @extension_module = outer_module.const_get(module_name)
49
+ @extension_module.send(:include, Faceted)
50
+ @extension_module.class_eval("def parent; #{self.container_key}; end") if self.container_key
51
+ @extension_module.class_eval 'def facet_container; @facet_container; end'
52
+ end
53
+ @extension_module
54
+ end
55
+
56
+ def apply_extension_to(object)
57
+ raise "Can not apply extension to model object of type #{object.class} as it is not of expected model type #{model_class.name} for target #{key}" unless object.is_a?(model_class)
58
+ raise "Attempted to apply extension multiple time to model object of type #{model_class.name} for target #{key}" if object.instance_variable_defined?('@facet_extension_active')
59
+ object.class.send(:include, extension_module)
60
+ object.instance_variable_set('@facet_container', target_manager.container)
61
+ object.instance_variable_set('@facet_extension_active', true)
62
+
63
+ if self.container_key
64
+ container = object.send(self.container_key)
65
+ container.enabled_facets.each do |facet_key|
66
+ object.send(:"_enable_facet_#{facet_key}!")
67
+ end
68
+ end
69
+ object
70
+ end
71
+ end
72
+
73
+ class TargetManager
74
+ attr_reader :container
75
+
76
+ def initialize(container)
77
+ @container = container
78
+ end
79
+
80
+ def is_target_valid?(key)
81
+ target_map.keys.include?(key)
82
+ end
83
+
84
+ def target_keys
85
+ target_map.keys
86
+ end
87
+
88
+ def targets
89
+ target_map.values
90
+ end
91
+
92
+ def target_by_key?(key)
93
+ !!target_map[key]
94
+ end
95
+
96
+ def target_by_key(key)
97
+ target = target_map[key.to_sym]
98
+ raise "Can not find target with key '#{key}'" unless target
99
+ target
100
+ end
101
+
102
+ def target_by_model_class(model_class)
103
+ target_map.each do |key, target|
104
+ return target if target.model_class == model_class
105
+ end
106
+ raise "Can not find target with model class '#{model_class.name}'"
107
+ end
108
+
109
+ def apply_extension(model)
110
+ self.target_by_model_class(model.class).apply_extension_to(model)
111
+ end
112
+
113
+ def target(model_class, key, container_key = nil, options = {})
114
+ Target.new(self, model_class, key, container_key, options)
115
+ end
116
+
117
+ def targets_by_container(container_key)
118
+ target_map.values.select { |target| target.container_key == container_key }
119
+ end
120
+
121
+ def lock_targets
122
+ @targets_locked = true
123
+ end
124
+
125
+ def reset_targets
126
+ target_map.clear
127
+ @targets_locked = false
128
+ end
129
+
130
+ private
131
+
132
+ def register_target(target)
133
+ raise "Attempting to define target #{target.key} when targets have been locked." if (@targets_locked ||= false)
134
+ raise "Attempting to redefine target #{target.key}" if target_map[target.key]
135
+ target_map[target.key] = target
136
+ end
137
+
138
+ def target_map
139
+ @target_map ||= Reality::OrderedHash.new
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{reality-facets}
5
+ s.version = '1.0.0'
6
+ s.platform = Gem::Platform::RUBY
7
+
8
+ s.authors = ['Peter Donald']
9
+ s.email = %q{peter@realityforge.org}
10
+
11
+ s.homepage = %q{https://github.com/realityforge/reality-facets}
12
+ s.summary = %q{A basic toolkit for binding facets or extensions to model objects.}
13
+ s.description = %q{A basic toolkit for binding facets or extensions to model objects.}
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {spec}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
18
+ s.default_executable = []
19
+ s.require_paths = %w(lib)
20
+
21
+ s.has_rdoc = false
22
+ s.rdoc_options = %w(--line-numbers --inline-source --title reality-facets)
23
+
24
+ s.add_dependency 'reality-core', '= 1.4.0'
25
+ s.add_dependency 'reality-naming', '= 1.4.0'
26
+ s.add_dependency 'reality-orderedhash', '= 1.0.0'
27
+
28
+ s.add_development_dependency(%q<minitest>, ['= 5.9.1'])
29
+ s.add_development_dependency(%q<test-unit>, ['= 3.1.5'])
30
+ end
@@ -0,0 +1,80 @@
1
+ require File.expand_path('../../helper', __FILE__)
2
+
3
+ class Reality::Facets::TestFacet < Reality::TestCase
4
+ class Component < Reality.base_element(:name => true, :container_key => :project, :pre_config_code => 'Reality::TestCase::TestFacetContainer.target_manager.apply_extension(self)')
5
+ end
6
+
7
+ class Project < Reality.base_element(:name => true, :pre_config_code => 'Reality::TestCase::TestFacetContainer.target_manager.apply_extension(self)')
8
+ def component(name, options = {}, &block)
9
+ component_map[name.to_s] = Component.new(self, name, options, &block)
10
+ end
11
+
12
+ def comps
13
+ component_map.values
14
+ end
15
+
16
+ def component_map
17
+ @component_map ||= {}
18
+ end
19
+ end
20
+
21
+ def test_basic_operation
22
+
23
+ assert_equal false, TestFacetContainer.facet_by_name?(:gwt)
24
+ assert_equal false, TestFacetContainer.facet_by_name?(:gwt_rpc)
25
+ assert_equal false, TestFacetContainer.facet_by_name?(:imit)
26
+
27
+ TestFacetContainer.target_manager.target(Project, :project)
28
+ TestFacetContainer.target_manager.target(Component,
29
+ :component,
30
+ :project,
31
+ :access_method => :comps,
32
+ :inverse_access_method => :comp)
33
+
34
+ Reality::Facets::Facet.new(TestFacetContainer, :gwt)
35
+ Reality::Facets::Facet.new(TestFacetContainer, :gwt_rpc, :required_facets => [:gwt])
36
+
37
+ Reality::Facets::Facet.new(TestFacetContainer, :imit, :suggested_facets => [:gwt_rpc]) do |f|
38
+ f.enhance(Project) do
39
+ def name
40
+ "Gwt#{project.name}"
41
+ end
42
+ end
43
+ f.enhance(Component)
44
+ end
45
+
46
+ assert_equal true, TestFacetContainer.facet_by_name?(:gwt)
47
+ assert_equal true, TestFacetContainer.facet_by_name?(:gwt_rpc)
48
+ assert_equal true, TestFacetContainer.facet_by_name?(:imit)
49
+
50
+ project = Project.new(:MyProject) do |p|
51
+ p.enable_facets(:imit)
52
+ p.component(:MyComponent)
53
+ end
54
+ component = project.comps[0]
55
+
56
+ assert_equal true, project.gwt?
57
+ assert_equal false, project.respond_to?(:gwt)
58
+ assert_equal false, project.respond_to?(:facet_gwt)
59
+ assert_equal true, project.gwt_rpc?
60
+ assert_equal false, project.respond_to?(:gwt_rpc)
61
+ assert_equal false, project.respond_to?(:facet_gwt_rpc)
62
+ assert_equal true, project.imit?
63
+ assert_equal true, project.respond_to?(:imit)
64
+ assert_equal true, project.respond_to?(:facet_imit)
65
+ assert_equal 'GwtMyProject', project.imit.name
66
+
67
+ # These methods all test that FacetModule has been mixed in.
68
+ assert_equal 'GwtMyProject', project.facet(:imit).name
69
+ assert_equal true, project.facet_enabled?(:imit)
70
+
71
+ assert_equal [:gwt, :gwt_rpc, :imit], project.enabled_facets
72
+ assert_equal [:gwt, :gwt_rpc, :imit], component.enabled_facets
73
+
74
+ # Ensure there is a link back to the container using inverse_access_method
75
+ assert_equal project, project.imit.project
76
+ assert_equal project, project.imit.parent
77
+ assert_equal component, component.imit.comp
78
+ assert_equal component, component.imit.parent
79
+ end
80
+ end
@@ -0,0 +1,64 @@
1
+ require File.expand_path('../../helper', __FILE__)
2
+
3
+ class Reality::Facets::TestFacetContainer < Reality::TestCase
4
+ class Component < Reality.base_element(:name => true)
5
+ end
6
+
7
+ class Component2 < Reality.base_element(:name => true)
8
+ end
9
+
10
+ def test_basic_operation
11
+
12
+ assert_equal false, TestFacetContainer.facet_by_name?(:gwt)
13
+ assert_equal false, TestFacetContainer.facet?(:gwt)
14
+ assert_equal false, TestFacetContainer.facet_by_name?(:gwt_rpc)
15
+ assert_equal false, TestFacetContainer.facet?(:gwt_rpc)
16
+ assert_equal [], TestFacetContainer.facet_keys
17
+ assert_equal 0, TestFacetContainer.facets.size
18
+
19
+ assert_raise_message("Unknown facet 'gwt'") { TestFacetContainer.facet_by_name(:gwt) }
20
+ assert_raise_message("Unknown facet 'gwt_rpc'") { TestFacetContainer.facet_by_name(:gwt_rpc) }
21
+
22
+ # Make sure we can add targets
23
+ TestFacetContainer.target_manager.target(Component, :component)
24
+
25
+ TestFacetContainer.facet(:gwt)
26
+
27
+ # targets should be locked after first facet defined
28
+ assert_raise_message('Attempting to define target component when targets have been locked.') do
29
+ TestFacetContainer.target_manager.target(Component, :component)
30
+ end
31
+
32
+ assert_equal true, TestFacetContainer.facet_by_name?(:gwt)
33
+ assert_equal true, TestFacetContainer.facet?(:gwt)
34
+ assert_equal false, TestFacetContainer.facet_by_name?(:gwt_rpc)
35
+ assert_equal false, TestFacetContainer.facet?(:gwt_rpc)
36
+ assert_equal %w(gwt), TestFacetContainer.facet_keys
37
+ assert_equal 1, TestFacetContainer.facets.size
38
+
39
+ assert_raise_message("Unknown facet 'gwt_rpc'") { TestFacetContainer.facet_by_name(:gwt_rpc) }
40
+
41
+ assert_equal TestFacetContainer, TestFacetContainer.facet_by_name(:gwt).facet_container
42
+ assert_equal :gwt, TestFacetContainer.facet_by_name(:gwt).key
43
+ assert_equal [], TestFacetContainer.facet_by_name(:gwt).required_facets
44
+ assert_equal [], TestFacetContainer.facet_by_name(:gwt).suggested_facets
45
+
46
+ TestFacetContainer.facet(:gwt_rpc => [:gwt])
47
+
48
+ assert_equal true, TestFacetContainer.facet_by_name?(:gwt)
49
+ assert_equal true, TestFacetContainer.facet?(:gwt)
50
+ assert_equal true, TestFacetContainer.facet_by_name?(:gwt_rpc)
51
+ assert_equal true, TestFacetContainer.facet?(:gwt_rpc)
52
+ assert_equal %w(gwt gwt_rpc), TestFacetContainer.facet_keys
53
+ assert_equal 2, TestFacetContainer.facets.size
54
+
55
+ assert_equal TestFacetContainer, TestFacetContainer.facet_by_name(:gwt_rpc).facet_container
56
+ assert_equal :gwt_rpc, TestFacetContainer.facet_by_name(:gwt_rpc).key
57
+ assert_equal [:gwt], TestFacetContainer.facet_by_name(:gwt_rpc).required_facets
58
+ assert_equal [], TestFacetContainer.facet_by_name(:gwt_rpc).suggested_facets
59
+
60
+ assert_raise_message('Attempting to redefine facet gwt') { TestFacetContainer.facet(:gwt) }
61
+
62
+ assert_raise_message("Unknown definition form '{:x=>:y, :z=>1}'") { TestFacetContainer.facet(:x => :y, :z => 1) }
63
+ end
64
+ end
@@ -0,0 +1,267 @@
1
+ require File.expand_path('../../helper', __FILE__)
2
+
3
+ class Reality::Facets::TestFacetedModel < Reality::TestCase
4
+ class Attribute < Reality.base_element(:name => true, :container_key => :entity)
5
+ def qualified_name
6
+ "#{entity.qualified_name}.#{name}"
7
+ end
8
+ end
9
+
10
+ class Entity < Reality.base_element(:name => true, :container_key => :repository)
11
+ def qualified_name
12
+ "#{repository.name}.#{name}"
13
+ end
14
+
15
+ def attribute(name, options = {}, &block)
16
+ attribute_map[name.to_s] = Attribute.new(self, name, options, &block)
17
+ end
18
+
19
+ def attributes
20
+ attribute_map.values
21
+ end
22
+
23
+ def attribute_map
24
+ @attribute_map ||= {}
25
+ end
26
+ end
27
+
28
+ class Repository < Reality.base_element(:name => true)
29
+ def entity(name, options = {}, &block)
30
+ entity_map[name.to_s] = Entity.new(self, name, options, &block)
31
+ end
32
+
33
+ def entities
34
+ entity_map.values
35
+ end
36
+
37
+ def entity_map
38
+ @entity_map ||= {}
39
+ end
40
+ end
41
+
42
+ def test_activation
43
+ TestFacetContainer.target_manager.target(Repository, :repository)
44
+ TestFacetContainer.target_manager.target(Entity, :entity, :repository)
45
+ TestFacetContainer.target_manager.target(Attribute, :attribute, :entity)
46
+
47
+ TestFacetContainer.facet(:json)
48
+ TestFacetContainer.facet(:jpa)
49
+ TestFacetContainer.facet(:gwt)
50
+ TestFacetContainer.facet(:gwt_rpc => [:gwt])
51
+ TestFacetContainer.facet(:imit => [:gwt_rpc]) do |f|
52
+ f.suggested_facets << :jpa
53
+ end
54
+
55
+ assert_equal 5, TestFacetContainer.facets.size
56
+
57
+ repository = Repository.new(:MyRepo) do |r|
58
+ TestFacetContainer.target_manager.apply_extension(r)
59
+
60
+ r.enable_facet(:json)
61
+
62
+ r.entity(:MyEntityA) do |e|
63
+ TestFacetContainer.target_manager.apply_extension(e)
64
+ e.attribute(:MyAttr1) do |a|
65
+ TestFacetContainer.target_manager.apply_extension(a)
66
+ end
67
+ e.disable_facet(:json)
68
+ e.attribute(:MyAttr2) do |a|
69
+ TestFacetContainer.target_manager.apply_extension(a)
70
+ end
71
+ end
72
+
73
+ r.entity(:MyEntityB) do |e|
74
+ TestFacetContainer.target_manager.apply_extension(e)
75
+ end
76
+ end
77
+
78
+ entity1 = repository.entities[0]
79
+ attribute1 = entity1.attributes[0]
80
+ attribute2 = entity1.attributes[1]
81
+ entity2 = repository.entities[1]
82
+
83
+ assert_equal [:json], repository.enabled_facets
84
+ assert_equal [], entity1.enabled_facets
85
+ assert_equal [:json], entity2.enabled_facets
86
+ assert_equal [], attribute1.enabled_facets
87
+ assert_equal [], attribute2.enabled_facets
88
+
89
+ repository.enable_facet(:imit)
90
+ assert_raise_message('Facet imit already enabled.') { repository.enable_facet(:imit) }
91
+
92
+ assert_equal [:json, :gwt, :gwt_rpc, :jpa, :imit], repository.enabled_facets
93
+ assert_equal [:gwt, :gwt_rpc, :jpa, :imit], entity1.enabled_facets
94
+ assert_equal [:json, :gwt, :gwt_rpc, :jpa, :imit], entity2.enabled_facets
95
+ assert_equal [:gwt, :gwt_rpc, :jpa, :imit], attribute1.enabled_facets
96
+ assert_equal [:gwt, :gwt_rpc, :jpa, :imit], attribute2.enabled_facets
97
+
98
+ entity1.disable_facet(:gwt)
99
+
100
+ assert_equal [:json, :gwt, :gwt_rpc, :jpa, :imit], repository.enabled_facets
101
+ assert_equal [:jpa], entity1.enabled_facets
102
+ assert_equal [:json, :gwt, :gwt_rpc, :jpa, :imit], entity2.enabled_facets
103
+ assert_equal [:jpa], attribute1.enabled_facets
104
+ assert_equal [:jpa], attribute2.enabled_facets
105
+
106
+ entity1.enable_facet(:json)
107
+
108
+ assert_equal [:json, :gwt, :gwt_rpc, :jpa, :imit], repository.enabled_facets
109
+ assert_equal [:jpa, :json], entity1.enabled_facets
110
+ assert_equal [:json, :gwt, :gwt_rpc, :jpa, :imit], entity2.enabled_facets
111
+ assert_equal [:jpa, :json], attribute1.enabled_facets
112
+ assert_equal [:jpa, :json], attribute2.enabled_facets
113
+
114
+ repository.disable_facet(:json)
115
+
116
+ assert_equal [:gwt, :gwt_rpc, :jpa, :imit], repository.enabled_facets
117
+ assert_equal [:jpa], entity1.enabled_facets
118
+ assert_equal [:gwt, :gwt_rpc, :jpa, :imit], entity2.enabled_facets
119
+ assert_equal [:jpa], attribute1.enabled_facets
120
+ assert_equal [:jpa], attribute2.enabled_facets
121
+
122
+ repository.enable_facets([:json])
123
+
124
+ assert_equal [:gwt, :gwt_rpc, :jpa, :imit, :json], repository.enabled_facets
125
+ assert_equal [:jpa, :json], entity1.enabled_facets
126
+ assert_equal [:gwt, :gwt_rpc, :jpa, :imit, :json], entity2.enabled_facets
127
+ assert_equal [:jpa, :json], attribute1.enabled_facets
128
+ assert_equal [:jpa, :json], attribute2.enabled_facets
129
+
130
+ # No-op as all enabled
131
+ repository.enable_facets([:json])
132
+
133
+ assert_equal [:gwt, :gwt_rpc, :jpa, :imit, :json], repository.enabled_facets
134
+ assert_equal [:jpa, :json], entity1.enabled_facets
135
+ assert_equal [:gwt, :gwt_rpc, :jpa, :imit, :json], entity2.enabled_facets
136
+ assert_equal [:jpa, :json], attribute1.enabled_facets
137
+ assert_equal [:jpa, :json], attribute2.enabled_facets
138
+
139
+ assert_raise_message('Facet json already enabled.') { repository.enable_facets!([:json]) }
140
+
141
+ # Try using brackets
142
+ repository.disable_facets([:json, :imit])
143
+ repository.enable_facets([:imit, :json])
144
+
145
+ assert_equal [:gwt, :gwt_rpc, :jpa, :imit, :json], repository.enabled_facets
146
+ assert_equal [:jpa, :gwt, :gwt_rpc, :imit, :json], entity1.enabled_facets
147
+ assert_equal [:gwt, :gwt_rpc, :jpa, :imit, :json], entity2.enabled_facets
148
+ assert_equal [:jpa, :gwt, :gwt_rpc, :imit, :json], attribute1.enabled_facets
149
+ assert_equal [:jpa, :gwt, :gwt_rpc, :imit, :json], attribute2.enabled_facets
150
+
151
+ # Try using raw facet list
152
+ repository.disable_facets(:json, :imit)
153
+ repository.enable_facets(:imit, :json)
154
+
155
+ assert_equal [:gwt, :gwt_rpc, :jpa, :imit, :json], repository.enabled_facets
156
+ assert_equal [:jpa, :gwt, :gwt_rpc, :imit, :json], entity1.enabled_facets
157
+ assert_equal [:gwt, :gwt_rpc, :jpa, :imit, :json], entity2.enabled_facets
158
+ assert_equal [:jpa, :gwt, :gwt_rpc, :imit, :json], attribute1.enabled_facets
159
+ assert_equal [:jpa, :gwt, :gwt_rpc, :imit, :json], attribute2.enabled_facets
160
+
161
+ # Try forcing
162
+ repository.disable_facets(:json, :imit)
163
+ repository.enable_facets!(:imit, :json)
164
+
165
+ assert_equal [:gwt, :gwt_rpc, :jpa, :imit, :json], repository.enabled_facets
166
+ assert_equal [:jpa, :gwt, :gwt_rpc, :imit, :json], entity1.enabled_facets
167
+ assert_equal [:gwt, :gwt_rpc, :jpa, :imit, :json], entity2.enabled_facets
168
+ assert_equal [:jpa, :gwt, :gwt_rpc, :imit, :json], attribute1.enabled_facets
169
+ assert_equal [:jpa, :gwt, :gwt_rpc, :imit, :json], attribute2.enabled_facets
170
+ end
171
+
172
+ def test_extension_point
173
+ TestFacetContainer.target_manager.target(Repository, :repository)
174
+ TestFacetContainer.target_manager.target(Entity, :entity, :repository)
175
+ TestFacetContainer.target_manager.target(Attribute, :attribute, :entity)
176
+
177
+ TestFacetContainer.facet(:json) do |f|
178
+ f.enhance(Entity) do
179
+ def hook2?
180
+ @hook2 ||= false
181
+ end
182
+
183
+ def hook2
184
+ @hook2 = true
185
+ end
186
+ end
187
+ end
188
+
189
+ TestFacetContainer.facet(:jpa) do |f|
190
+ f.enhance(Repository) do
191
+ def hook1?
192
+ @hook1 ||= false
193
+ end
194
+
195
+ def hook1
196
+ @hook1 = true
197
+ end
198
+
199
+ def hook2?
200
+ @hook2 ||= false
201
+ end
202
+
203
+ def hook2
204
+ @hook2 = true
205
+ end
206
+ end
207
+
208
+ f.enhance(Attribute) do
209
+ def hook2?
210
+ @hook2 ||= false
211
+ end
212
+
213
+ def hook2
214
+ @hook2 = true
215
+ end
216
+ end
217
+ end
218
+
219
+ repository = Repository.new(:MyRepo) do |r|
220
+ TestFacetContainer.target_manager.apply_extension(r)
221
+
222
+ r.enable_facets(:json, :jpa)
223
+
224
+ r.entity(:MyEntityA) do |e|
225
+ TestFacetContainer.target_manager.apply_extension(e)
226
+ e.disable_facet(:json)
227
+ e.attribute(:MyAttr1) do |a|
228
+ TestFacetContainer.target_manager.apply_extension(a)
229
+ end
230
+ e.attribute(:MyAttr2) do |a|
231
+ TestFacetContainer.target_manager.apply_extension(a)
232
+ end
233
+ end
234
+
235
+ r.entity(:MyEntityB) do |e|
236
+ TestFacetContainer.target_manager.apply_extension(e)
237
+ end
238
+ end
239
+
240
+ entity1 = repository.entities[0]
241
+ entity2 = repository.entities[1]
242
+ attribute1 = entity1.attributes[0]
243
+ attribute2 = entity1.attributes[1]
244
+
245
+ assert_equal false, repository.jpa.hook1?
246
+ assert_equal false, repository.jpa.hook2?
247
+ assert_equal false, entity2.json.hook2?
248
+ assert_equal false, attribute1.jpa.hook2?
249
+ assert_equal false, attribute2.jpa.hook2?
250
+
251
+ repository.send(:extension_point, :hook1)
252
+
253
+ assert_equal true, repository.jpa.hook1?
254
+ assert_equal false, repository.jpa.hook2?
255
+ assert_equal false, entity2.json.hook2?
256
+ assert_equal false, attribute1.jpa.hook2?
257
+ assert_equal false, attribute2.jpa.hook2?
258
+
259
+ repository.send(:extension_point, :hook2)
260
+
261
+ assert_equal true, repository.jpa.hook1?
262
+ assert_equal true, repository.jpa.hook2?
263
+ assert_equal true, entity2.json.hook2?
264
+ assert_equal true, attribute1.jpa.hook2?
265
+ assert_equal true, attribute2.jpa.hook2?
266
+ end
267
+ end