phenomenal 1.1.1 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +15 -3
- data/lib/phenomenal.rb +19 -19
- data/lib/phenomenal/{adaptation.rb → context/adaptation.rb} +45 -16
- data/lib/phenomenal/{context.rb → context/context.rb} +15 -106
- data/lib/phenomenal/context/context_creation.rb +68 -0
- data/lib/phenomenal/{feature.rb → context/feature.rb} +0 -0
- data/lib/phenomenal/dsl.rb +20 -16
- data/lib/phenomenal/error.rb +2 -0
- data/lib/phenomenal/manager/{adaptations_management.rb → adaptation_management.rb} +10 -10
- data/lib/phenomenal/manager/conflict_policies.rb +5 -4
- data/lib/phenomenal/manager/{contexts_management.rb → context_management.rb} +15 -14
- data/lib/phenomenal/manager/manager.rb +6 -6
- data/lib/phenomenal/{relationships → relationship}/context_relationships.rb +0 -0
- data/lib/phenomenal/{relationships → relationship}/dsl.rb +3 -3
- data/lib/phenomenal/{relationships → relationship}/feature_relationships.rb +1 -1
- data/lib/phenomenal/{relationships → relationship}/implication.rb +0 -0
- data/lib/phenomenal/{relationships → relationship}/relationship.rb +0 -0
- data/lib/phenomenal/{relationships/relationships_manager.rb → relationship/relationship_manager.rb} +3 -5
- data/lib/phenomenal/{relationships/relationships_store.rb → relationship/relationship_store.rb} +1 -1
- data/lib/phenomenal/{relationships → relationship}/requirement.rb +1 -1
- data/lib/phenomenal/{relationships → relationship}/suggestion.rb +0 -0
- data/lib/phenomenal/version.rb +1 -1
- data/lib/phenomenal/viewer/graphical.rb +7 -7
- data/lib/phenomenal/viewer/textual.rb +1 -1
- data/spec/context_spec.rb +8 -8
- data/spec/dsl_spec.rb +2 -2
- data/spec/integration/adaptation_spec.rb +4 -3
- data/spec/integration/conflict_policy_spec.rb +3 -3
- data/spec/integration/relationships_spec.rb +6 -6
- data/spec/manager_spec.rb +3 -3
- data/spec/relationships/relationships_manager_spec.rb +1 -1
- data/spec/relationships/relationships_store_spec.rb +5 -5
- metadata +18 -17
- data/lib/phenomenal/logger.rb +0 -34
data/README.md
CHANGED
@@ -4,6 +4,18 @@ Phenomenal Gem is a context-oriented framework implemented in Ruby that allows c
|
|
4
4
|
|
5
5
|
See www.phenomenal-gem.com for more details
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
## Contributions
|
8
|
+
If you want to contribute, please:
|
9
|
+
|
10
|
+
* Fork the project.
|
11
|
+
* Make your feature addition or bug fix.
|
12
|
+
* Add tests for it. This is *very* important.
|
13
|
+
* Send a pull request on Github with a clear description.
|
14
|
+
|
15
|
+
Tests are executed with
|
16
|
+
|
17
|
+
rake
|
18
|
+
|
19
|
+
## Copyright
|
20
|
+
|
21
|
+
Copyright (c) 2011-2012 Loïc Vigneron - Thibault Poncelet. See LICENSE for details.
|
data/lib/phenomenal.rb
CHANGED
@@ -2,26 +2,28 @@
|
|
2
2
|
module Phenomenal
|
3
3
|
module Viewer end
|
4
4
|
end
|
5
|
-
#
|
6
|
-
require_relative "./phenomenal/
|
7
|
-
require_relative "./phenomenal/relationships/feature_relationships.rb"
|
8
|
-
require_relative "./phenomenal/relationships/relationships_store.rb"
|
9
|
-
require_relative "./phenomenal/relationships/relationships_manager.rb"
|
10
|
-
require_relative "./phenomenal/relationships/relationship.rb"
|
11
|
-
require_relative "./phenomenal/relationships/requirement.rb"
|
12
|
-
require_relative "./phenomenal/relationships/implication.rb"
|
13
|
-
require_relative "./phenomenal/relationships/suggestion.rb"
|
5
|
+
#Error
|
6
|
+
require_relative "./phenomenal/error.rb"
|
14
7
|
|
15
|
-
#
|
16
|
-
require_relative "./phenomenal/
|
8
|
+
#Relationships
|
9
|
+
require_relative "./phenomenal/relationship/context_relationships.rb"
|
10
|
+
require_relative "./phenomenal/relationship/feature_relationships.rb"
|
11
|
+
require_relative "./phenomenal/relationship/relationship_store.rb"
|
12
|
+
require_relative "./phenomenal/relationship/relationship_manager.rb"
|
13
|
+
require_relative "./phenomenal/relationship/relationship.rb"
|
14
|
+
require_relative "./phenomenal/relationship/requirement.rb"
|
15
|
+
require_relative "./phenomenal/relationship/implication.rb"
|
16
|
+
require_relative "./phenomenal/relationship/suggestion.rb"
|
17
17
|
|
18
|
-
|
19
|
-
require_relative "./phenomenal/
|
20
|
-
require_relative "./phenomenal/
|
18
|
+
# Context
|
19
|
+
require_relative "./phenomenal/context/adaptation.rb"
|
20
|
+
require_relative "./phenomenal/context/context_creation.rb"
|
21
|
+
require_relative "./phenomenal/context/context.rb"
|
22
|
+
require_relative "./phenomenal/context/feature.rb"
|
21
23
|
|
22
24
|
#Manager
|
23
|
-
require_relative "./phenomenal/manager/
|
24
|
-
require_relative "./phenomenal/manager/
|
25
|
+
require_relative "./phenomenal/manager/adaptation_management.rb"
|
26
|
+
require_relative "./phenomenal/manager/context_management.rb"
|
25
27
|
require_relative "./phenomenal/manager/conflict_policies.rb"
|
26
28
|
require_relative "./phenomenal/manager/manager.rb"
|
27
29
|
|
@@ -30,8 +32,6 @@ require_relative "./phenomenal/viewer/graphical.rb"
|
|
30
32
|
require_relative "./phenomenal/viewer/textual.rb"
|
31
33
|
|
32
34
|
# DSL
|
33
|
-
require_relative "./phenomenal/
|
35
|
+
require_relative "./phenomenal/relationship/dsl.rb"
|
34
36
|
require_relative "./phenomenal/viewer/dsl.rb"
|
35
37
|
require_relative "./phenomenal/dsl.rb"
|
36
|
-
|
37
|
-
|
@@ -32,23 +32,15 @@ class Phenomenal::Adaptation
|
|
32
32
|
klass.define_singleton_method(method_name,implementation)
|
33
33
|
end
|
34
34
|
end
|
35
|
-
|
36
|
-
# IMPROVE try to find a better implementation
|
35
|
+
|
37
36
|
# Bind the implementation corresponding to this adaptation to 'instance' when
|
38
37
|
# instance_adaptation or to implementation class when class method
|
39
38
|
def bind(instance,*args,&block)
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
else
|
44
|
-
implementation.bind(instance).call(*args,&block)
|
45
|
-
end
|
39
|
+
target = instance_adaptation? ? instance : klass
|
40
|
+
if implementation.is_a?(Proc)
|
41
|
+
bind_proc(target,*args,&block)
|
46
42
|
else
|
47
|
-
|
48
|
-
klass.instance_exec(*args,block,&implementation)
|
49
|
-
else
|
50
|
-
implementation.call(*args,&block)
|
51
|
-
end
|
43
|
+
bind_method(target,*args,&block)
|
52
44
|
end
|
53
45
|
end
|
54
46
|
|
@@ -65,13 +57,50 @@ class Phenomenal::Adaptation
|
|
65
57
|
end
|
66
58
|
|
67
59
|
private
|
60
|
+
def bind_proc(target,*args,&block)
|
61
|
+
args.push(block)
|
62
|
+
target.instance_exec(*args,&implementation)
|
63
|
+
end
|
64
|
+
|
65
|
+
def bind_method(target,*args,&block)
|
66
|
+
if instance_adaptation?
|
67
|
+
implementation.bind(target).call(*args,&block)
|
68
|
+
else
|
69
|
+
implementation.call(*args,&block)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
68
73
|
def check_validity
|
69
|
-
|
70
|
-
|
71
|
-
Phenomenal::
|
74
|
+
method = get_original_method
|
75
|
+
if method.arity != implementation.arity
|
76
|
+
raise(Phenomenal::Error,
|
77
|
+
"Illegal adaptation for context #{context},the adaptation "+
|
78
|
+
"have to keep the original method arity for method: " +
|
79
|
+
"#{klass.name}.#{method_name}: (#{method.arity} instead of " +
|
80
|
+
"#{implementation.arity})."
|
81
|
+
)
|
82
|
+
elsif klass.instance_methods.include?(method_name) ^ instance_adaptation?
|
83
|
+
raise(Phenomenal::Error,
|
72
84
|
"Illegal adaptation for context: #{context}" +
|
73
85
|
" for #{klass.name}.#{method_name}, type mismatch"
|
74
86
|
)
|
75
87
|
end
|
76
88
|
end
|
89
|
+
|
90
|
+
def get_original_method
|
91
|
+
begin
|
92
|
+
if instance_adaptation?
|
93
|
+
method = klass.instance_method(method_name)
|
94
|
+
else
|
95
|
+
method = klass.method(method_name)
|
96
|
+
end
|
97
|
+
rescue NameError
|
98
|
+
raise(Phenomenal::Error,
|
99
|
+
"Illegal adaptation for context #{context},a method with "+
|
100
|
+
"name: #{method_name} should exist in class #{klass.name} to "+
|
101
|
+
"be adapted."
|
102
|
+
)
|
103
|
+
end
|
104
|
+
method
|
105
|
+
end
|
77
106
|
end
|
@@ -1,82 +1,13 @@
|
|
1
1
|
# Represents a first class context
|
2
2
|
class Phenomenal::Context
|
3
|
+
extend Phenomenal::ContextCreation
|
3
4
|
include Phenomenal::ContextRelationships
|
5
|
+
|
4
6
|
@@total_activations = 0
|
5
7
|
|
6
8
|
attr_accessor :activation_age, :activation_frequency, :adaptations,
|
7
9
|
:activation_count, :parent, :forgotten
|
8
|
-
attr_reader :manager,:name
|
9
|
-
|
10
|
-
# Class metods
|
11
|
-
class << self
|
12
|
-
def create(context,*contexts,nested,closest_feature,&block)
|
13
|
-
manager = Phenomenal::Manager.instance
|
14
|
-
contexts.insert(0,context)
|
15
|
-
if contexts.length==1
|
16
|
-
context = find_or_create_simple_context(manager,context)
|
17
|
-
else #Combined contexts
|
18
|
-
context = find_or_create_combined_context(manager,contexts,nested,closest_feature)
|
19
|
-
end
|
20
|
-
context.add_adaptations(&block)
|
21
|
-
context
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
def find_or_create_simple_context(manager,context)
|
26
|
-
if !manager.context_defined?(context)
|
27
|
-
self.new(context)
|
28
|
-
else
|
29
|
-
context = manager.find_context(context)
|
30
|
-
if !context.instance_of?(self)
|
31
|
-
Phenomenal::Logger.instance.error(
|
32
|
-
"Only #{self.name} can be used with this keyword."
|
33
|
-
)
|
34
|
-
end
|
35
|
-
context
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def find_or_create_combined_context(manager,contexts,nested,closest_feature)
|
40
|
-
if !manager.context_defined?(*contexts) # New combined context
|
41
|
-
context = create_combined_context(manager,contexts,nested,closest_feature)
|
42
|
-
else
|
43
|
-
context = manager.find_context(*contexts)
|
44
|
-
if !context.instance_of?(self)
|
45
|
-
Phenomenal::Logger.instance.error(
|
46
|
-
"Only #{self.name} can be used with this keyword."
|
47
|
-
)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
context
|
51
|
-
end
|
52
|
-
|
53
|
-
def create_combined_context(manager,contexts,nested,closest_feature)
|
54
|
-
context = self.new
|
55
|
-
context.parent=closest_feature # Set parent
|
56
|
-
instances = Array.new
|
57
|
-
first = contexts.first
|
58
|
-
contexts.each do |c|
|
59
|
-
# Use the object instance if already available
|
60
|
-
# otherwise create it
|
61
|
-
if manager.context_defined?(c)
|
62
|
-
c = manager.find_context(c)
|
63
|
-
if !nested && c!=first && !c.instance_of?(self)
|
64
|
-
Phenomenal::Logger.instance.error(
|
65
|
-
"Only #{self.name} can be used with this keyword."
|
66
|
-
)
|
67
|
-
end
|
68
|
-
else
|
69
|
-
c = self.new(c)
|
70
|
-
end
|
71
|
-
instances.push(c)
|
72
|
-
manager.shared_contexts[c]= Array.new if !manager.shared_contexts[c]
|
73
|
-
manager.shared_contexts[c].push(context)
|
74
|
-
end
|
75
|
-
manager.combined_contexts[context] = instances
|
76
|
-
context
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
10
|
+
attr_reader :manager,:name
|
80
11
|
# Instance methods
|
81
12
|
def initialize(name=nil, manager=nil)
|
82
13
|
@manager = manager || Phenomenal::Manager.instance
|
@@ -95,7 +26,7 @@ class Phenomenal::Context
|
|
95
26
|
# TODO handle relationships references
|
96
27
|
def forget
|
97
28
|
if active?
|
98
|
-
Phenomenal::
|
29
|
+
raise(Phenomenal::Error,
|
99
30
|
"Active context cannot be forgotten"
|
100
31
|
)
|
101
32
|
else
|
@@ -108,40 +39,18 @@ class Phenomenal::Context
|
|
108
39
|
# Return the adaptation just created
|
109
40
|
def add_adaptation(klass, method_name,instance,umeth=nil, &implementation)
|
110
41
|
if klass.nil? # Not defined class
|
111
|
-
Phenomenal::
|
42
|
+
raise(Phenomenal::Error,
|
112
43
|
"The class to be adapted wasn't specified. Don't forget to use 'adaptations_for(Klass)' before adapting a method"
|
113
44
|
)
|
114
45
|
end
|
115
|
-
if umeth
|
116
|
-
implementation = umeth
|
117
|
-
end
|
118
46
|
if adaptations.find{ |i| i.concern?(klass,method_name,instance) }
|
119
|
-
|
47
|
+
raise(Phenomenal::Error,
|
120
48
|
"Illegal duplicated adaptation in context: #{self} for " +
|
121
49
|
"#{klass.name}:#{method_name}."
|
122
50
|
)
|
123
51
|
else
|
124
|
-
if klass.instance_methods.include?(method_name) && instance
|
125
|
-
method = klass.instance_method(method_name)
|
126
|
-
elsif klass.methods.include?(method_name) && !instance
|
127
|
-
method = klass.method(method_name)
|
128
|
-
else
|
129
|
-
Phenomenal::Logger.instance.error(
|
130
|
-
"Illegal adaptation for context #{self},a method with "+
|
131
|
-
"name: #{method_name} should exist in class #{klass.name} to "+
|
132
|
-
"be adapted."
|
133
|
-
)
|
134
|
-
end
|
135
|
-
if method.arity != implementation.arity
|
136
|
-
Phenomenal::Logger.instance.error(
|
137
|
-
"Illegal adaptation for context #{self},the adaptation "+
|
138
|
-
"have to keep the original method arity for method: " +
|
139
|
-
"#{klass.name}.#{method_name}: (#{method.arity} instead of " +
|
140
|
-
"#{implementation.arity})."
|
141
|
-
)
|
142
|
-
end
|
143
52
|
adaptation = Phenomenal::Adaptation.new(
|
144
|
-
self, klass, method_name,instance, implementation
|
53
|
+
self, klass, method_name,instance, umeth||implementation
|
145
54
|
)
|
146
55
|
adaptations.push(adaptation)
|
147
56
|
manager.register_adaptation(adaptation)
|
@@ -152,14 +61,14 @@ class Phenomenal::Context
|
|
152
61
|
# Catch nested context calls and transform them in nested contexts creation
|
153
62
|
def context(context,*contexts,&block)
|
154
63
|
check_validity
|
155
|
-
Phenomenal::Context.create(self,context,*contexts
|
64
|
+
Phenomenal::Context.create(true,self,self,context,*contexts,&block)
|
156
65
|
end
|
157
66
|
alias_method :phen_context,:context
|
158
67
|
|
159
68
|
# Catch nested feature calls and transform them in nested contexts creation
|
160
69
|
def feature(feature,*features, &block)
|
161
70
|
check_validity
|
162
|
-
Phenomenal::Feature.create(self,feature,*features
|
71
|
+
Phenomenal::Feature.create(true,self,self,feature,*features,&block)
|
163
72
|
end
|
164
73
|
alias_method :phen_feature,:feature
|
165
74
|
|
@@ -189,7 +98,7 @@ class Phenomenal::Context
|
|
189
98
|
adaptation_index =
|
190
99
|
adaptations.find_index{ |i| i.concern?(klass, method_name,instance) }
|
191
100
|
if !adaptation_index
|
192
|
-
Phenomenal::
|
101
|
+
raise(Phenomenal::Error,
|
193
102
|
"Illegal deleting of an inexistent adaptation in context: " +
|
194
103
|
"#{self} for #{klass.name}.#{method_name})."
|
195
104
|
)
|
@@ -210,7 +119,7 @@ class Phenomenal::Context
|
|
210
119
|
end
|
211
120
|
|
212
121
|
# Deactivate the context
|
213
|
-
def deactivate
|
122
|
+
def deactivate
|
214
123
|
check_validity
|
215
124
|
was_active = active?
|
216
125
|
if self.activation_count>0
|
@@ -269,7 +178,7 @@ class Phenomenal::Context
|
|
269
178
|
p=p.parent
|
270
179
|
end
|
271
180
|
if p.nil?
|
272
|
-
manager.
|
181
|
+
manager.default_feature
|
273
182
|
else
|
274
183
|
p
|
275
184
|
end
|
@@ -279,8 +188,8 @@ class Phenomenal::Context
|
|
279
188
|
def to_s
|
280
189
|
if name
|
281
190
|
name.to_s
|
282
|
-
elsif self==manager.
|
283
|
-
"Default
|
191
|
+
elsif self==manager.default_feature
|
192
|
+
"Default feature"
|
284
193
|
elsif manager.combined_contexts[self]
|
285
194
|
"#{manager.combined_contexts[self].flatten}"
|
286
195
|
else
|
@@ -291,7 +200,7 @@ class Phenomenal::Context
|
|
291
200
|
private
|
292
201
|
def check_validity
|
293
202
|
if forgotten
|
294
|
-
Phenomenal::
|
203
|
+
raise(Phenomenal::Error,
|
295
204
|
"Action not allowed anymore when context has been forgotten."
|
296
205
|
)
|
297
206
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Phenomenal::ContextCreation
|
2
|
+
def create(nested,closest_feature,context,*contexts,&block)
|
3
|
+
manager = Phenomenal::Manager.instance
|
4
|
+
contexts.insert(0,context)
|
5
|
+
if contexts.length==1
|
6
|
+
context = find_or_create_simple_context(manager,context)
|
7
|
+
else #Combined contexts
|
8
|
+
context = find_or_create_combined_context(manager,contexts,nested,closest_feature)
|
9
|
+
end
|
10
|
+
context.add_adaptations(&block)
|
11
|
+
context
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
def find_or_create_simple_context(manager,context)
|
16
|
+
if !manager.context_defined?(context)
|
17
|
+
self.new(context)
|
18
|
+
else
|
19
|
+
context = manager.find_context(context)
|
20
|
+
if !context.instance_of?(self)
|
21
|
+
raise(Phenomenal::Error,
|
22
|
+
"Only #{self.name} can be used with this keyword."
|
23
|
+
)
|
24
|
+
end
|
25
|
+
context
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def find_or_create_combined_context(manager,contexts,nested,closest_feature)
|
30
|
+
if !manager.context_defined?(*contexts) # New combined context
|
31
|
+
context = create_combined_context(manager,contexts,nested,closest_feature)
|
32
|
+
else
|
33
|
+
context = manager.find_context(*contexts)
|
34
|
+
if !context.instance_of?(self)
|
35
|
+
raise(Phenomenal::Error,
|
36
|
+
"Only #{self.name} can be used with this keyword."
|
37
|
+
)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
context
|
41
|
+
end
|
42
|
+
|
43
|
+
def create_combined_context(manager,contexts,nested,closest_feature)
|
44
|
+
context = self.new
|
45
|
+
context.parent=closest_feature # Set parent
|
46
|
+
instances = Array.new
|
47
|
+
first = contexts.first
|
48
|
+
contexts.each do |c|
|
49
|
+
# Use the object instance if already available
|
50
|
+
# otherwise create it
|
51
|
+
if manager.context_defined?(c)
|
52
|
+
c = manager.find_context(c)
|
53
|
+
if !nested && c!=first && !c.instance_of?(self)
|
54
|
+
raise(Phenomenal::Error,
|
55
|
+
"Only #{self.name} can be used with this keyword."
|
56
|
+
)
|
57
|
+
end
|
58
|
+
else
|
59
|
+
c = self.new(c)
|
60
|
+
end
|
61
|
+
instances.push(c)
|
62
|
+
manager.shared_contexts[c]= Array.new if !manager.shared_contexts[c]
|
63
|
+
manager.shared_contexts[c].push(context)
|
64
|
+
end
|
65
|
+
manager.combined_contexts[context] = instances
|
66
|
+
context
|
67
|
+
end
|
68
|
+
end
|
File without changes
|
data/lib/phenomenal/dsl.rb
CHANGED
@@ -5,13 +5,13 @@ module Phenomenal::DSL
|
|
5
5
|
klass.class_eval do
|
6
6
|
# Define context with adaptations
|
7
7
|
def phen_context(context,*contexts,&block)
|
8
|
-
Phenomenal::Context.create(context,*contexts
|
8
|
+
Phenomenal::Context.create(false,nil,context,*contexts,&block)
|
9
9
|
end
|
10
10
|
Phenomenal::DSL.phen_alias(:context,klass)
|
11
11
|
|
12
12
|
# Define context with adaptations
|
13
13
|
def phen_feature(context,*contexts,&block)
|
14
|
-
Phenomenal::Feature.create(context,*contexts
|
14
|
+
Phenomenal::Feature.create(false,nil,context,*contexts,&block)
|
15
15
|
end
|
16
16
|
Phenomenal::DSL.phen_alias(:feature,klass)
|
17
17
|
|
@@ -48,21 +48,13 @@ module Phenomenal::DSL
|
|
48
48
|
|
49
49
|
# Activate Context
|
50
50
|
def phen_activate_context(context,*contexts)
|
51
|
-
contexts
|
52
|
-
contexts.push(context)
|
53
|
-
contexts.each do |c|
|
54
|
-
Phenomenal::Manager.instance.find_context(c).activate
|
55
|
-
end
|
51
|
+
Phenomenal::DSL.phen_switch_context_state(true,context,*contexts)
|
56
52
|
end
|
57
53
|
Phenomenal::DSL.phen_alias(:activate_context,klass)
|
58
54
|
|
59
55
|
# Deactivate Context
|
60
56
|
def phen_deactivate_context(context,*contexts)
|
61
|
-
contexts
|
62
|
-
contexts.push(context)
|
63
|
-
contexts.each do |c|
|
64
|
-
Phenomenal::Manager.instance.find_context(c).deactivate
|
65
|
-
end
|
57
|
+
Phenomenal::DSL.phen_switch_context_state(false,context,*contexts)
|
66
58
|
end
|
67
59
|
Phenomenal::DSL.phen_alias(:deactivate_context,klass)
|
68
60
|
|
@@ -76,9 +68,9 @@ module Phenomenal::DSL
|
|
76
68
|
Phenomenal::Manager.instance.find_context(context).information
|
77
69
|
end
|
78
70
|
|
79
|
-
# Default
|
80
|
-
def
|
81
|
-
Phenomenal::Manager.instance.
|
71
|
+
# Default Feature
|
72
|
+
def phen_default_feature
|
73
|
+
Phenomenal::Manager.instance.default_feature
|
82
74
|
end
|
83
75
|
|
84
76
|
# Defined context registered in the manager
|
@@ -104,9 +96,21 @@ module Phenomenal::DSL
|
|
104
96
|
end
|
105
97
|
|
106
98
|
private
|
99
|
+
def self.phen_switch_context_state(activate,context,*contexts)
|
100
|
+
contexts=[] if contexts.nil?
|
101
|
+
contexts.push(context)
|
102
|
+
contexts.each do |c|
|
103
|
+
if activate
|
104
|
+
Phenomenal::Manager.instance.find_context(c).activate
|
105
|
+
else
|
106
|
+
Phenomenal::Manager.instance.find_context(c).deactivate
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
107
111
|
def self.phen_alias(method,klass)
|
108
112
|
if Kernel.respond_to? method
|
109
|
-
Phenomenal::
|
113
|
+
raise(Phenomenal::Error,
|
110
114
|
"The Phenomenal DSL keyword #{method} wasn't defined, use"+
|
111
115
|
" phen_#{method} instead"
|
112
116
|
)
|
@@ -1,12 +1,12 @@
|
|
1
|
-
module Phenomenal::
|
1
|
+
module Phenomenal::AdaptationManagement
|
2
2
|
attr_accessor :active_adaptations, :deployed_adaptations
|
3
3
|
|
4
4
|
# Register a new adaptation for a registered context
|
5
5
|
def register_adaptation(adaptation)
|
6
|
-
default_adaptation =
|
6
|
+
default_adaptation = default_feature.adaptations.find do|i|
|
7
7
|
i.concern?(adaptation.klass,adaptation.method_name,adaptation.instance_adaptation?)
|
8
8
|
end
|
9
|
-
if adaptation.context!=
|
9
|
+
if adaptation.context!=default_feature && !default_adaptation
|
10
10
|
save_default_adaptation(adaptation.klass, adaptation.method_name,adaptation.instance_adaptation?)
|
11
11
|
end
|
12
12
|
activate_adaptation(adaptation) if adaptation.context.active?
|
@@ -22,8 +22,8 @@ module Phenomenal::AdaptationsManagement
|
|
22
22
|
calling_adaptation = find_adaptation(calling_stack)
|
23
23
|
# IMPROVE Problems will appears if proceed called in a file where
|
24
24
|
# adaptations are defined but not in one of them=> how to check?
|
25
|
-
# IMPROVE Problems will also appears if two adaptations are defined on the
|
26
|
-
# line using the ';' some check needed at add_adaptation ?
|
25
|
+
# IMPROVE Problems will also appears if two adaptations are defined on the
|
26
|
+
# same line using the ';' some check needed at add_adaptation ?
|
27
27
|
adaptations_stack = sorted_adaptations_for(calling_adaptation.klass,
|
28
28
|
calling_adaptation.method_name,calling_adaptation.instance_adaptation?)
|
29
29
|
calling_adaptation_index = adaptations_stack.find_index(calling_adaptation)
|
@@ -54,7 +54,7 @@ module Phenomenal::AdaptationsManagement
|
|
54
54
|
# conflict policy
|
55
55
|
def redeploy_adaptation(klass, method_name,instance)
|
56
56
|
to_deploy = resolve_conflict(klass,method_name,instance)
|
57
|
-
# Do nothing when to_deploy==nil to break at default
|
57
|
+
# Do nothing when to_deploy==nil to break at default feature deactivation
|
58
58
|
if !deployed_adaptations.include?(to_deploy) && to_deploy!=nil
|
59
59
|
deploy_adaptation(to_deploy)
|
60
60
|
end
|
@@ -79,7 +79,7 @@ module Phenomenal::AdaptationsManagement
|
|
79
79
|
else
|
80
80
|
method = klass.method(method_name)
|
81
81
|
end
|
82
|
-
adaptation =
|
82
|
+
adaptation = default_feature.add_adaptation(klass,method_name,instance,method)
|
83
83
|
end
|
84
84
|
|
85
85
|
# Return the adaptation that math the calling_stack, on the basis of the
|
@@ -96,7 +96,7 @@ module Phenomenal::AdaptationsManagement
|
|
96
96
|
end
|
97
97
|
|
98
98
|
if match==nil
|
99
|
-
Phenomenal::
|
99
|
+
raise(Phenomenal::Error,
|
100
100
|
"Inexistant adaptation for proceed call at #{call_file}:#{call_line}"
|
101
101
|
)
|
102
102
|
end
|
@@ -114,7 +114,7 @@ module Phenomenal::AdaptationsManagement
|
|
114
114
|
|
115
115
|
# Gets the relevants adaptations for a file in DESC order of line number
|
116
116
|
def relevant_adaptations(call_file)
|
117
|
-
relevants = active_adaptations.
|
117
|
+
relevants = active_adaptations.find_all{ |i| i.src_file == call_file }
|
118
118
|
# Sort by src_line DESC order
|
119
119
|
relevants.sort!{ |a,b| b.src_line <=> a.src_line }
|
120
120
|
end
|
@@ -128,7 +128,7 @@ module Phenomenal::AdaptationsManagement
|
|
128
128
|
# conflict policy
|
129
129
|
def sorted_adaptations_for(klass,method_name,instance)
|
130
130
|
relevants =
|
131
|
-
active_adaptations.find_all
|
131
|
+
active_adaptations.find_all{ |i| i.concern?(klass, method_name,instance) }
|
132
132
|
relevants.sort!{|a,b| conflict_policy(a.context,b.context)}
|
133
133
|
end
|
134
134
|
end
|
@@ -2,13 +2,14 @@
|
|
2
2
|
module Phenomenal::ConflictPolicies
|
3
3
|
# Prefer not default adaptation, error if two not default ones
|
4
4
|
def no_resolution_conflict_policy(context1,context2)
|
5
|
-
if context1==
|
5
|
+
if context1==default_feature()
|
6
6
|
1
|
7
|
-
elsif context2==
|
7
|
+
elsif context2==default_feature()
|
8
8
|
-1
|
9
9
|
else #Fail if two non default adaptations
|
10
|
-
Phenomenal::
|
11
|
-
|
10
|
+
raise(Phenomenal::Error,
|
11
|
+
"Illegal duplicate adapation between contexts #{context1}"+
|
12
|
+
"and #{context2} "
|
12
13
|
)
|
13
14
|
end
|
14
15
|
end
|
@@ -1,15 +1,15 @@
|
|
1
|
-
module Phenomenal::
|
2
|
-
attr_accessor :contexts, :
|
1
|
+
module Phenomenal::ContextManagement
|
2
|
+
attr_accessor :contexts, :default_feature, :combined_contexts,:shared_contexts
|
3
3
|
|
4
4
|
# Register a new context
|
5
5
|
def register_context(context)
|
6
6
|
if context_defined?(context)
|
7
|
-
Phenomenal::
|
7
|
+
raise(Phenomenal::Error,
|
8
8
|
"The context #{context} is already registered"
|
9
9
|
)
|
10
10
|
end
|
11
11
|
if context.name && context_defined?(context.name)
|
12
|
-
Phenomenal::
|
12
|
+
raise(Phenomenal::Error,
|
13
13
|
"There is already a context with name: #{context.name}." +
|
14
14
|
" If you want to have named context it has to be a globally unique name"
|
15
15
|
)
|
@@ -22,15 +22,15 @@ module Phenomenal::ContextsManagement
|
|
22
22
|
|
23
23
|
# Unregister a context (forget)
|
24
24
|
def unregister_context(context)
|
25
|
-
if context==
|
26
|
-
Phenomenal::
|
27
|
-
"Default
|
25
|
+
if context==default_feature && contexts.size>1
|
26
|
+
raise(Phenomenal::Error,
|
27
|
+
"Default feature can only be forgotten when alone"
|
28
28
|
)
|
29
29
|
else
|
30
30
|
contexts.delete(context)
|
31
31
|
unregister_combined_contexts(context)
|
32
|
-
# Restore default
|
33
|
-
init_default() if context==
|
32
|
+
# Restore default feature
|
33
|
+
init_default() if context==default_feature
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
@@ -75,8 +75,9 @@ module Phenomenal::ContextsManagement
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
-
# Check wether context 'context' (or combined context) exist in the context
|
79
|
-
# Context can be either the context name or the context instance
|
78
|
+
# Check wether context 'context' (or combined context) exist in the context
|
79
|
+
# manager. Context can be either the context name or the context instance
|
80
|
+
# itself.
|
80
81
|
# Return the context if found, or nil otherwise
|
81
82
|
def context_defined?(context, *contexts)
|
82
83
|
c=nil
|
@@ -134,7 +135,7 @@ module Phenomenal::ContextsManagement
|
|
134
135
|
if find
|
135
136
|
find
|
136
137
|
else
|
137
|
-
Phenomenal::
|
138
|
+
raise(Phenomenal::Error,
|
138
139
|
"Unknown context #{context}"
|
139
140
|
)
|
140
141
|
end
|
@@ -157,13 +158,13 @@ module Phenomenal::ContextsManagement
|
|
157
158
|
end
|
158
159
|
end
|
159
160
|
if list.length==0
|
160
|
-
Phenomenal::
|
161
|
+
raise(Phenomenal::Error,
|
161
162
|
"Unknown combined context #{contexts}"
|
162
163
|
)
|
163
164
|
elsif list.length==1
|
164
165
|
return list.first
|
165
166
|
else
|
166
|
-
Phenomenal::
|
167
|
+
raise(Phenomenal::Error,
|
167
168
|
"Multiple definition of combined context #{contexts}"
|
168
169
|
)
|
169
170
|
end
|
@@ -3,17 +3,17 @@ require 'singleton'
|
|
3
3
|
class Phenomenal::Manager
|
4
4
|
include Singleton
|
5
5
|
include Phenomenal::ConflictPolicies
|
6
|
-
include Phenomenal::
|
7
|
-
include Phenomenal::
|
6
|
+
include Phenomenal::AdaptationManagement
|
7
|
+
include Phenomenal::ContextManagement
|
8
8
|
|
9
9
|
attr_accessor :rmanager
|
10
10
|
|
11
11
|
# PRIVATE METHODS
|
12
12
|
private
|
13
|
-
# Set the default
|
13
|
+
# Set the default feature
|
14
14
|
def init_default
|
15
|
-
self.
|
16
|
-
self.
|
15
|
+
self.default_feature = Phenomenal::Feature.new(nil,self)
|
16
|
+
self.default_feature.activate
|
17
17
|
end
|
18
18
|
|
19
19
|
# Private constructor because this is a singleton object
|
@@ -23,7 +23,7 @@ class Phenomenal::Manager
|
|
23
23
|
@active_adaptations = Array.new
|
24
24
|
@combined_contexts = Hash.new
|
25
25
|
@shared_contexts = Hash.new
|
26
|
-
@rmanager = Phenomenal::
|
26
|
+
@rmanager = Phenomenal::RelationshipManager.instance
|
27
27
|
init_default()
|
28
28
|
end
|
29
29
|
end
|
File without changes
|
@@ -4,19 +4,19 @@ module Phenomenal::DSL
|
|
4
4
|
klass.class_eval do
|
5
5
|
# Requirements
|
6
6
|
def phen_requirements_for(source,targets)
|
7
|
-
Phenomenal::Manager.instance.
|
7
|
+
Phenomenal::Manager.instance.default_feature.requirements_for(source,targets)
|
8
8
|
end
|
9
9
|
Phenomenal::DSL.phen_alias(:requirements_for,klass)
|
10
10
|
|
11
11
|
# Implications
|
12
12
|
def phen_implications_for(source,targets)
|
13
|
-
Phenomenal::Manager.instance.
|
13
|
+
Phenomenal::Manager.instance.default_feature.implications_for(source,targets)
|
14
14
|
end
|
15
15
|
Phenomenal::DSL.phen_alias(:implications_for,klass)
|
16
16
|
|
17
17
|
# Suggestions
|
18
18
|
def phen_suggestions_for(source,targets)
|
19
|
-
Phenomenal::Manager.instance.
|
19
|
+
Phenomenal::Manager.instance.default_feature.suggestions_for(source,targets)
|
20
20
|
end
|
21
21
|
Phenomenal::DSL.phen_alias(:suggestions_for,klass)
|
22
22
|
|
@@ -27,7 +27,7 @@ module Phenomenal::FeatureRelationships
|
|
27
27
|
def add_relationship(source,targets,type)
|
28
28
|
targets[:on]=Array.new.push(targets[:on]) if !targets[:on].is_a?(Array)
|
29
29
|
if targets[:on].nil?
|
30
|
-
Phenomenal::
|
30
|
+
raise(Phenomenal::Error,
|
31
31
|
"Invalid relationship, missing target context"
|
32
32
|
)
|
33
33
|
end
|
File without changes
|
File without changes
|
data/lib/phenomenal/{relationships/relationships_manager.rb → relationship/relationship_manager.rb}
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'singleton'
|
2
2
|
# This class manage the different relatiohsips in the system between contexts
|
3
|
-
class Phenomenal::
|
3
|
+
class Phenomenal::RelationshipManager
|
4
4
|
include Singleton
|
5
5
|
|
6
6
|
attr_accessor :relationships
|
@@ -41,10 +41,8 @@ class Phenomenal::RelationshipsManager
|
|
41
41
|
relationships.add(relationship)
|
42
42
|
end
|
43
43
|
rescue Phenomenal::Error => m
|
44
|
+
# Unable to activate the feature #{feature} \n #{m}
|
44
45
|
feature.deactivate
|
45
|
-
Phenomenal::Logger.instance.debug(
|
46
|
-
"Unable to activate the feature #{feature} \n #{m}"
|
47
|
-
)
|
48
46
|
end
|
49
47
|
end
|
50
48
|
|
@@ -58,6 +56,6 @@ class Phenomenal::RelationshipsManager
|
|
58
56
|
end
|
59
57
|
|
60
58
|
def initialize
|
61
|
-
@relationships = Phenomenal::
|
59
|
+
@relationships = Phenomenal::RelationshipStore.new
|
62
60
|
end
|
63
61
|
end
|
@@ -23,7 +23,7 @@ class Phenomenal::Requirement < Phenomenal::Relationship
|
|
23
23
|
private
|
24
24
|
def check_requirement
|
25
25
|
if source.active? && !target.active?
|
26
|
-
Phenomenal::
|
26
|
+
raise(Phenomenal::Error,
|
27
27
|
"Requirement of #{target} for #{source} is not satisfied"
|
28
28
|
)
|
29
29
|
end
|
File without changes
|
data/lib/phenomenal/version.rb
CHANGED
@@ -13,14 +13,14 @@ class Phenomenal::Viewer::Graphical
|
|
13
13
|
|
14
14
|
def initialize(destination_file)
|
15
15
|
if !@@graphviz
|
16
|
-
Phenomenal::
|
16
|
+
raise(Phenomenal::Error,
|
17
17
|
"The 'ruby-graphviz' gem isn't available. Please install it to generate graphic visualisations\n"+
|
18
18
|
" Otherwise use the text version: phen_textual_view"
|
19
19
|
)
|
20
20
|
end
|
21
21
|
|
22
22
|
@manager=Phenomenal::Manager.instance
|
23
|
-
@rmanager=Phenomenal::
|
23
|
+
@rmanager=Phenomenal::RelationshipManager.instance
|
24
24
|
@destination_file=destination_file
|
25
25
|
@main_graph=nil
|
26
26
|
@feature_nodes={}
|
@@ -82,7 +82,7 @@ class Phenomenal::Viewer::Graphical
|
|
82
82
|
def graph_container(relationship)
|
83
83
|
s_parent_feature=relationship.source.parent_feature
|
84
84
|
t_parent_feature=relationship.target.parent_feature
|
85
|
-
if s_parent_feature==t_parent_feature && s_parent_feature!=manager.
|
85
|
+
if s_parent_feature==t_parent_feature && s_parent_feature!=manager.default_feature
|
86
86
|
feature_nodes[relationship.source.parent_feature]
|
87
87
|
else
|
88
88
|
main_graph
|
@@ -91,7 +91,7 @@ class Phenomenal::Viewer::Graphical
|
|
91
91
|
|
92
92
|
def set_edge(context,edge,relationship)
|
93
93
|
# Define edge label
|
94
|
-
if context!=manager.
|
94
|
+
if context!=manager.default_feature
|
95
95
|
edge[:label]=context.to_s
|
96
96
|
end
|
97
97
|
# Define edge color
|
@@ -106,15 +106,15 @@ class Phenomenal::Viewer::Graphical
|
|
106
106
|
elsif relationship.is_a?(Phenomenal::Requirement)
|
107
107
|
edge[:arrowhead]="inv"
|
108
108
|
else
|
109
|
-
Phenomenal::
|
109
|
+
raise(Phenomenal::Error,
|
110
110
|
"This relationship hasn't been defined yet in the graphical viewer"
|
111
111
|
)
|
112
112
|
end
|
113
113
|
end
|
114
114
|
|
115
115
|
def add_node_for(context)
|
116
|
-
# The default
|
117
|
-
if feature_nodes[context.parent_feature].nil? && context==manager.
|
116
|
+
# The default feature is the first to be added to the main graph
|
117
|
+
if feature_nodes[context.parent_feature].nil? && context==manager.default_feature
|
118
118
|
current_graph=main_graph
|
119
119
|
# Always add the parent_feature before the contexts inside
|
120
120
|
elsif feature_nodes[context.parent_feature].nil?
|
data/spec/context_spec.rb
CHANGED
@@ -40,8 +40,8 @@ describe Phenomenal::Context do
|
|
40
40
|
force_forget_context(context)
|
41
41
|
end
|
42
42
|
|
43
|
-
it "should be anonymous if it is the default
|
44
|
-
Phenomenal::Manager.instance.
|
43
|
+
it "should be anonymous if it is the default feature" do
|
44
|
+
Phenomenal::Manager.instance.default_feature.name.should be_nil
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
@@ -65,11 +65,11 @@ describe Phenomenal::Context do
|
|
65
65
|
end
|
66
66
|
|
67
67
|
describe "#add_adaptation" do
|
68
|
-
it "should save the default behavior in the default
|
68
|
+
it "should save the default behavior in the default feature" do
|
69
69
|
@context.add_adaptation(TestString, :size,true) do
|
70
70
|
42
|
71
71
|
end
|
72
|
-
a =
|
72
|
+
a = phen_default_feature.adaptations.find{|a| a.concern?(TestString,:size,true)}
|
73
73
|
a.bind(TestString.new("1234")).should==4
|
74
74
|
end
|
75
75
|
|
@@ -261,8 +261,8 @@ describe Phenomenal::Context do
|
|
261
261
|
@context.anonymous?.should be_false
|
262
262
|
end
|
263
263
|
|
264
|
-
it "should be true for the default
|
265
|
-
Phenomenal::Manager.instance.
|
264
|
+
it "should be true for the default feature" do
|
265
|
+
Phenomenal::Manager.instance.default_feature.anonymous?.should be_true
|
266
266
|
end
|
267
267
|
|
268
268
|
it "should be true when the context has no name" do
|
@@ -278,7 +278,7 @@ describe Phenomenal::Context do
|
|
278
278
|
end
|
279
279
|
it "should have a matching :name field" do
|
280
280
|
@context.information[:name].should==:test
|
281
|
-
default = Phenomenal::Manager.instance.
|
281
|
+
default = Phenomenal::Manager.instance.default_feature
|
282
282
|
default.information[:name].should be_nil
|
283
283
|
end
|
284
284
|
it "should have a matching :adaptation field" do
|
@@ -314,7 +314,7 @@ describe Phenomenal::Context do
|
|
314
314
|
describe "#parent_feature" do
|
315
315
|
it "should be the default feature parent for simple contexts" do
|
316
316
|
c = context :b
|
317
|
-
c.parent_feature.should be Phenomenal::Manager.instance.
|
317
|
+
c.parent_feature.should be Phenomenal::Manager.instance.default_feature
|
318
318
|
c.forget
|
319
319
|
end
|
320
320
|
|
data/spec/dsl_spec.rb
CHANGED
@@ -106,9 +106,9 @@ describe Phenomenal::DSL do
|
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
109
|
-
describe "#
|
109
|
+
describe "#phen_default_feature" do
|
110
110
|
it "should exist in Kernel" do
|
111
|
-
Kernel.should respond_to :
|
111
|
+
Kernel.should respond_to :phen_default_feature
|
112
112
|
end
|
113
113
|
end
|
114
114
|
|
@@ -40,7 +40,6 @@ describe "Simple adaptations" do
|
|
40
40
|
@klass_inst_var+1
|
41
41
|
end
|
42
42
|
end
|
43
|
-
|
44
43
|
end
|
45
44
|
|
46
45
|
after :each do
|
@@ -108,12 +107,14 @@ describe "Simple adaptations" do
|
|
108
107
|
|
109
108
|
it "sould be possible to access class variables" do
|
110
109
|
TestClass.klass_var_access.should==1
|
111
|
-
|
112
|
-
|
110
|
+
|
113
111
|
pending "Adaptations doesn't have access to class variables, seems to be a Ruby bug"
|
112
|
+
activate_context(:test_2)
|
113
|
+
t.instance_klass_var_access.should==2
|
114
114
|
TestClass.klass_var_access.should==2
|
115
115
|
|
116
116
|
deactivate_context(:test_2)
|
117
|
+
t.instance_klass_var_access.should==1
|
117
118
|
TestClass.klass_var_access.should==1
|
118
119
|
end
|
119
120
|
|
@@ -34,14 +34,14 @@ describe "Conflict policies" do
|
|
34
34
|
it "should set the age of the context such that the most recent one has the smaller age" do
|
35
35
|
phen_change_conflict_policy { |a,b| age_conflict_policy(a,b) }
|
36
36
|
|
37
|
-
phen_context_active?(
|
37
|
+
phen_context_active?(phen_default_feature).should be_true
|
38
38
|
phen_context_active?(:screening).should be_false
|
39
39
|
phen_context_active?(:quiet).should be_false
|
40
40
|
|
41
41
|
phen_activate_context(:screening)
|
42
42
|
|
43
43
|
(phen_context_information(:screening)[:age] <
|
44
|
-
phen_context_information(
|
44
|
+
phen_context_information(phen_default_feature)[:age]).should be_true,
|
45
45
|
"screening context has been activated more recently than default"
|
46
46
|
|
47
47
|
phen_activate_context(:quiet)
|
@@ -49,7 +49,7 @@ describe "Conflict policies" do
|
|
49
49
|
phen_context_information(:screening)[:age]).should be_true
|
50
50
|
"quiet context has been activated more recently than screening"
|
51
51
|
(phen_context_information(:screening)[:age] <
|
52
|
-
phen_context_information(
|
52
|
+
phen_context_information(phen_default_feature)[:age]).should be_true,
|
53
53
|
"quiet context has still been activated more recently than default"
|
54
54
|
phen_deactivate_context(:quiet)
|
55
55
|
phen_deactivate_context(:screening)
|
@@ -15,8 +15,8 @@ describe "Relationships" do
|
|
15
15
|
@context_names.each do |name|
|
16
16
|
force_forget_context(name)
|
17
17
|
end
|
18
|
-
@manager.
|
19
|
-
@manager.
|
18
|
+
@manager.default_feature.deactivate
|
19
|
+
@manager.default_feature.forget
|
20
20
|
end
|
21
21
|
|
22
22
|
describe Phenomenal::Feature do
|
@@ -75,10 +75,10 @@ describe "Relationships" do
|
|
75
75
|
phen_context_active?(:feature).should be_false
|
76
76
|
end
|
77
77
|
|
78
|
-
it "should be possible to add requirements to the default
|
78
|
+
it "should be possible to add requirements to the default feature" do
|
79
79
|
requirements_for :a, :on=>[:b,:c,:d]
|
80
80
|
requirements_for :a, :on=>:e
|
81
|
-
@manager.
|
81
|
+
@manager.default_feature.relationships.should have(4).items
|
82
82
|
end
|
83
83
|
|
84
84
|
it "should be possible to put requirements in the nested contexts" do
|
@@ -152,7 +152,7 @@ describe "Relationships" do
|
|
152
152
|
describe "Suggestions" do
|
153
153
|
it "should be working on the default feature" do
|
154
154
|
suggestions_for :a,:on=>:b
|
155
|
-
@manager.
|
155
|
+
@manager.default_feature.relationships.should have(1).items
|
156
156
|
context(:a).active?.should be_false
|
157
157
|
context(:b).active?.should be_false
|
158
158
|
expect {activate_context :a}.to_not raise_error
|
@@ -168,7 +168,7 @@ describe "Relationships" do
|
|
168
168
|
context(:b).active?.should be_false
|
169
169
|
expect {activate_context :a}.to_not raise_error
|
170
170
|
suggestions_for :a,:on=>:b
|
171
|
-
@manager.
|
171
|
+
@manager.default_feature.relationships.should have(1).items
|
172
172
|
context(:a).active?.should be_true
|
173
173
|
context(:b).active?.should be_true
|
174
174
|
expect {deactivate_context :a}.to_not raise_error
|
data/spec/manager_spec.rb
CHANGED
@@ -34,13 +34,13 @@ describe Phenomenal::Manager do
|
|
34
34
|
@manager.contexts[context].should be_nil
|
35
35
|
end
|
36
36
|
|
37
|
-
it "should allow to forget default
|
37
|
+
it "should allow to forget default feature only when it is the only defined context" do
|
38
38
|
@manager.contexts.size.should==4
|
39
|
-
expect{@manager.unregister_context(@manager.
|
39
|
+
expect{@manager.unregister_context(@manager.default_feature)}.to raise_error Phenomenal::Error
|
40
40
|
force_forget_context(@context)
|
41
41
|
force_forget_context(@context2)
|
42
42
|
@manager.contexts.size.should==1
|
43
|
-
expect{@manager.unregister_context(@manager.
|
43
|
+
expect{@manager.unregister_context(@manager.default_feature)}.to_not raise_error
|
44
44
|
@context = Phenomenal::Context.new(:test)
|
45
45
|
@context2 = Phenomenal::Context.new(:test2)
|
46
46
|
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
describe Phenomenal::
|
3
|
+
describe Phenomenal::RelationshipStore do
|
4
4
|
before :each do
|
5
5
|
@source = context :source
|
6
6
|
@target = context :target
|
7
|
-
@relationship = Phenomenal::Relationship.new(:source,:target,
|
8
|
-
@relationship2 = Phenomenal::Relationship.new(:source2,:target2,
|
9
|
-
@relationship12 = Phenomenal::Relationship.new(:source,:target2,
|
10
|
-
@store = Phenomenal::
|
7
|
+
@relationship = Phenomenal::Relationship.new(:source,:target,phen_default_feature)
|
8
|
+
@relationship2 = Phenomenal::Relationship.new(:source2,:target2,phen_default_feature)
|
9
|
+
@relationship12 = Phenomenal::Relationship.new(:source,:target2,phen_default_feature)
|
10
|
+
@store = Phenomenal::RelationshipStore.new
|
11
11
|
end
|
12
12
|
|
13
13
|
after :each do
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: phenomenal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 1.
|
5
|
+
version: 1.2.1
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Loic Vigneron - Thibault Poncelet
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2012-05-
|
13
|
+
date: 2012-05-31 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rspec
|
@@ -32,28 +32,29 @@ extensions: []
|
|
32
32
|
extra_rdoc_files: []
|
33
33
|
|
34
34
|
files:
|
35
|
-
- lib/phenomenal/
|
35
|
+
- lib/phenomenal/error.rb
|
36
36
|
- lib/phenomenal/viewer/graphical.rb
|
37
37
|
- lib/phenomenal/viewer/textual.rb
|
38
38
|
- lib/phenomenal/viewer/dsl.rb
|
39
39
|
- lib/phenomenal/dsl.rb
|
40
40
|
- lib/phenomenal/version.rb
|
41
|
-
- lib/phenomenal/
|
42
|
-
- lib/phenomenal/
|
43
|
-
- lib/phenomenal/
|
44
|
-
- lib/phenomenal/
|
45
|
-
- lib/phenomenal/
|
46
|
-
- lib/phenomenal/
|
47
|
-
- lib/phenomenal/
|
48
|
-
- lib/phenomenal/
|
49
|
-
- lib/phenomenal/
|
50
|
-
- lib/phenomenal/context.rb
|
41
|
+
- lib/phenomenal/relationship/implication.rb
|
42
|
+
- lib/phenomenal/relationship/relationship.rb
|
43
|
+
- lib/phenomenal/relationship/relationship_store.rb
|
44
|
+
- lib/phenomenal/relationship/requirement.rb
|
45
|
+
- lib/phenomenal/relationship/dsl.rb
|
46
|
+
- lib/phenomenal/relationship/relationship_manager.rb
|
47
|
+
- lib/phenomenal/relationship/context_relationships.rb
|
48
|
+
- lib/phenomenal/relationship/suggestion.rb
|
49
|
+
- lib/phenomenal/relationship/feature_relationships.rb
|
51
50
|
- lib/phenomenal/manager/manager.rb
|
51
|
+
- lib/phenomenal/manager/adaptation_management.rb
|
52
52
|
- lib/phenomenal/manager/conflict_policies.rb
|
53
|
-
- lib/phenomenal/manager/
|
54
|
-
- lib/phenomenal/
|
55
|
-
- lib/phenomenal/
|
56
|
-
- lib/phenomenal/
|
53
|
+
- lib/phenomenal/manager/context_management.rb
|
54
|
+
- lib/phenomenal/context/feature.rb
|
55
|
+
- lib/phenomenal/context/context.rb
|
56
|
+
- lib/phenomenal/context/context_creation.rb
|
57
|
+
- lib/phenomenal/context/adaptation.rb
|
57
58
|
- lib/phenomenal.rb
|
58
59
|
- LICENSE
|
59
60
|
- Rakefile
|
data/lib/phenomenal/logger.rb
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
require 'logger'
|
2
|
-
require 'singleton'
|
3
|
-
|
4
|
-
class Phenomenal::Error < StandardError; end
|
5
|
-
|
6
|
-
class Phenomenal::Logger
|
7
|
-
attr_accessor :logger
|
8
|
-
include Singleton
|
9
|
-
|
10
|
-
def info(msg)
|
11
|
-
logger.info(msg)
|
12
|
-
end
|
13
|
-
|
14
|
-
def debug(msg)
|
15
|
-
logger.debug(msg)
|
16
|
-
end
|
17
|
-
|
18
|
-
def warn(msg)
|
19
|
-
logger.warn(msg)
|
20
|
-
end
|
21
|
-
|
22
|
-
def error(msg)
|
23
|
-
raise(Phenomenal::Error, msg)
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
def initialize
|
28
|
-
self.logger = Logger.new(STDOUT)
|
29
|
-
self.logger.level = Logger::DEBUG
|
30
|
-
self.logger.datetime_format = "%Y-%m-%d - %H:%M:%S"
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
|