reality-facets 1.0.0

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.
@@ -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