phenomenal 1.1.1 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
|