phenomenal 0.9.0 → 0.11.11.24.3
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +1 -1
- data/README +4 -3
- data/Rakefile +0 -3
- data/demo.rb +24 -0
- data/demo_age.rb +89 -0
- data/demo_dsl.rb +28 -0
- data/lib/phenomenal.rb +2 -15
- data/lib/phenomenal/adaptation.rb +12 -22
- data/lib/phenomenal/context.rb +134 -127
- data/lib/phenomenal/dsl.rb +14 -41
- data/lib/phenomenal/logger.rb +1 -0
- data/lib/phenomenal/manager.rb +35 -117
- data/phenomenal.gemspec +15 -0
- data/{spec → test}/test_classes.rb +0 -3
- data/test/test_cop_adaptation.rb +168 -0
- data/test/test_cop_composition.rb +84 -0
- data/test/test_cop_conflictpolicy.rb +177 -0
- data/test/test_cop_infrastructure.rb +129 -0
- data/test_declaration.rb +18 -0
- metadata +29 -70
- data/lib/phenomenal/feature.rb +0 -8
- data/lib/phenomenal/relationships/context_relationships.rb +0 -22
- data/lib/phenomenal/relationships/dsl.rb +0 -18
- data/lib/phenomenal/relationships/feature_relationships.rb +0 -42
- data/lib/phenomenal/relationships/implication.rb +0 -35
- data/lib/phenomenal/relationships/relationship.rb +0 -42
- data/lib/phenomenal/relationships/relationships_manager.rb +0 -63
- data/lib/phenomenal/relationships/relationships_store.rb +0 -73
- data/lib/phenomenal/relationships/requirement.rb +0 -26
- data/lib/phenomenal/relationships/suggestion.rb +0 -41
- data/lib/phenomenal/version.rb +0 -3
- data/spec/adaptation_spec.rb +0 -64
- data/spec/behavior/adaptation_spec.rb +0 -5
- data/spec/behavior/combined_contexts_spec.rb +0 -5
- data/spec/behavior/composition_spec.rb +0 -5
- data/spec/behavior/conflict_policy_spec.rb +0 -5
- data/spec/behavior/open_context.rb +0 -5
- data/spec/behavior/relationships_spec.rb +0 -249
- data/spec/context_spec.rb +0 -268
- data/spec/dsl_spec.rb +0 -181
- data/spec/feature_spec.rb +0 -5
- data/spec/manager_spec.rb +0 -84
- data/spec/proc_spec.rb +0 -20
- data/spec/relationships/context_relationships_spec.rb +0 -13
- data/spec/relationships/dsl_spec.rb +0 -13
- data/spec/relationships/feature_relationships_spec.rb +0 -13
- data/spec/relationships/relationship_spec.rb +0 -31
- data/spec/relationships/relationships_manager_spec.rb +0 -15
- data/spec/relationships/relationships_store_spec.rb +0 -19
- data/spec/spec_helper.rb +0 -18
data/LICENSE
CHANGED
data/README
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
Build gem command:
|
2
|
+
gem build phenomenal.gemspec
|
3
|
+
Test gem command:
|
4
|
+
rake test
|
data/Rakefile
CHANGED
data/demo.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require_relative 'lib/phenomenal.rb'
|
2
|
+
class Foo
|
3
|
+
def initialize
|
4
|
+
@inst_var = "bar"
|
5
|
+
end
|
6
|
+
def print
|
7
|
+
"Base: " +@inst_var
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
pnml_define_context(:demo)
|
12
|
+
pnml_add_adaptation(:demo, Foo, :print) do
|
13
|
+
pnml_proceed + " adaptation: "+ @inst_var
|
14
|
+
end
|
15
|
+
|
16
|
+
f = Foo.new
|
17
|
+
puts f.print
|
18
|
+
|
19
|
+
pnml_activate_context(:demo)
|
20
|
+
puts f.print
|
21
|
+
|
22
|
+
pnml_deactivate_context(:demo)
|
23
|
+
puts f.print
|
24
|
+
|
data/demo_age.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
require_relative "./lib/phenomenal.rb"
|
2
|
+
|
3
|
+
pnml_change_conflict_policy { |a,b| age_conflict_policy(a,b) }
|
4
|
+
|
5
|
+
class Plop
|
6
|
+
@@klass_var = "PPPP"
|
7
|
+
@klass_inst_var = "xD"
|
8
|
+
attr_accessor :test
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@test = ">BOR<"
|
12
|
+
end
|
13
|
+
|
14
|
+
def print(arg)
|
15
|
+
"0 -> Test: #{self.test} default Plop.print(arg): ARG: #{arg.to_s}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.plop(arg)
|
19
|
+
"SELF 0 #{arg} KlassVar: #{@@klass_var} INSTKLS #{@klass_inst_var}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
pnml_define_context(:level1)
|
24
|
+
|
25
|
+
pnml_add_adaptation(:level1,Plop,:print) do |arg|
|
26
|
+
pnml_proceed(arg) + "\n" + "1 -> level1 ARG1: #{arg.to_s}"
|
27
|
+
end
|
28
|
+
|
29
|
+
pnml_add_adaptation(:level1,Plop,:plop) do |arg|
|
30
|
+
pnml_proceed(arg) + "\n" + "1 -> SELF level1 ARG1: #{arg.to_s} INSTKLS #{@kls_var}"
|
31
|
+
end
|
32
|
+
|
33
|
+
pnml_define_context(:level2)
|
34
|
+
|
35
|
+
pnml_add_adaptation(:level2,Plop,:print) do |arg|
|
36
|
+
pnml_proceed(arg) + "\n" + "2 -> level2 ARG2: #{arg.to_s}"
|
37
|
+
end
|
38
|
+
|
39
|
+
pnml_add_adaptation(:level2,Plop,:plop) do |arg|
|
40
|
+
pnml_proceed(arg) + "\n" + "2 -> SELF level2 ARG2: #{arg.to_s} INSTKLS #{@kls_inst_var}"
|
41
|
+
end
|
42
|
+
|
43
|
+
pnml_define_context(:level3)
|
44
|
+
|
45
|
+
pnml_add_adaptation(:level3,Plop,:print) do |arg|
|
46
|
+
pnml_proceed(arg) + "\n" + "3 -> level3 ARG3: #{arg.to_s}"
|
47
|
+
end
|
48
|
+
|
49
|
+
pnml_define_context(:level4)
|
50
|
+
|
51
|
+
pnml_add_adaptation(:level4,Plop,:print) do |arg|
|
52
|
+
pnml_proceed(arg) + "\n" + "4 -> TEST4: #{@test} level4 ARG4: #{arg.to_s}"
|
53
|
+
end
|
54
|
+
|
55
|
+
p = Plop.new
|
56
|
+
|
57
|
+
puts "=============> LEVEL 0 <===============\n"+
|
58
|
+
p.print("foo")+
|
59
|
+
"\n======================================="
|
60
|
+
|
61
|
+
pnml_activate_context(:level1)
|
62
|
+
puts "=============> LEVEL 1 <===============\n"+
|
63
|
+
p.print("foo1")+
|
64
|
+
"\n======================================="
|
65
|
+
|
66
|
+
pnml_activate_context(:level2)
|
67
|
+
puts "=============> LEVEL 2 <===============\n"+
|
68
|
+
p.print("foo2")+
|
69
|
+
"\n======================================="
|
70
|
+
|
71
|
+
pnml_activate_context(:level3)
|
72
|
+
puts "=============> LEVEL 3 <===============\n"+
|
73
|
+
p.print("foo3")+
|
74
|
+
"\n======================================="
|
75
|
+
p.test=">BAR<"
|
76
|
+
pnml_activate_context(:level4)
|
77
|
+
puts "=============> LEVEL 4 <===============\n"+
|
78
|
+
p.print("foo4")+
|
79
|
+
"\n======================================="
|
80
|
+
|
81
|
+
pnml_deactivate_context(:level3)
|
82
|
+
puts "=============> LEVEL 4 -3 <===============\n"+
|
83
|
+
p.print("foo4-2")+
|
84
|
+
"\n======================================="
|
85
|
+
|
86
|
+
puts "\n\n========> LEVEL 4 -3 KLASS METH<===========\n"+
|
87
|
+
Plop.plop(">KLASS_METH_ARG<") +
|
88
|
+
"\n======================================="
|
89
|
+
|
data/demo_dsl.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require_relative 'lib/phenomenal.rb'
|
2
|
+
class Foo
|
3
|
+
def initialize
|
4
|
+
@inst_var = "bar"
|
5
|
+
end
|
6
|
+
def print
|
7
|
+
"Base: " +@inst_var
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
context :Test do
|
12
|
+
implies :plop
|
13
|
+
|
14
|
+
adaptations_for Foo
|
15
|
+
adapt :print do
|
16
|
+
pnml_proceed + "ADAPT"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
f = Foo.new
|
21
|
+
puts f.print
|
22
|
+
|
23
|
+
pnml_activate_context(:Test)
|
24
|
+
puts f.print
|
25
|
+
|
26
|
+
pnml_deactivate_context(:Test)
|
27
|
+
puts f.print
|
28
|
+
|
data/lib/phenomenal.rb
CHANGED
@@ -1,24 +1,11 @@
|
|
1
1
|
# Load the gem files in the system
|
2
2
|
module Phenomenal end
|
3
|
-
#Relationships
|
4
|
-
require_relative "./phenomenal/relationships/context_relationships.rb"
|
5
|
-
require_relative "./phenomenal/relationships/feature_relationships.rb"
|
6
|
-
require_relative "./phenomenal/relationships/relationships_store.rb"
|
7
|
-
require_relative "./phenomenal/relationships/relationships_manager.rb"
|
8
|
-
require_relative "./phenomenal/relationships/relationship.rb"
|
9
|
-
require_relative "./phenomenal/relationships/requirement.rb"
|
10
|
-
require_relative "./phenomenal/relationships/implication.rb"
|
11
|
-
require_relative "./phenomenal/relationships/suggestion.rb"
|
12
|
-
|
13
|
-
# Core
|
14
3
|
require_relative "./phenomenal/adaptation.rb"
|
15
4
|
require_relative "./phenomenal/conflict_policies.rb"
|
16
5
|
require_relative "./phenomenal/context.rb"
|
17
|
-
require_relative "./phenomenal/feature.rb"
|
18
6
|
require_relative "./phenomenal/logger.rb"
|
19
7
|
require_relative "./phenomenal/manager.rb"
|
20
8
|
require_relative "./phenomenal/proc.rb"
|
21
|
-
|
22
|
-
# DSL
|
23
|
-
require_relative "./phenomenal/relationships/dsl.rb"
|
24
9
|
require_relative "./phenomenal/dsl.rb"
|
10
|
+
|
11
|
+
|
@@ -1,16 +1,14 @@
|
|
1
1
|
# Represent a method adaptation for a particular context
|
2
2
|
class Phenomenal::Adaptation
|
3
3
|
attr_accessor :context, :klass, :method_name, :implementation, :src_file,
|
4
|
-
:src_line
|
4
|
+
:src_line
|
5
5
|
|
6
|
-
def initialize(context,klass, method_name,
|
6
|
+
def initialize(context,klass, method_name, implementation)
|
7
7
|
@context = context
|
8
8
|
@klass = klass
|
9
9
|
@method_name = method_name
|
10
10
|
@implementation = implementation
|
11
|
-
@instance_adaptation=instance_adapatation
|
12
11
|
|
13
|
-
check_validity
|
14
12
|
# Save the source location if any, this is used to find again the adaptation
|
15
13
|
# in a ctxt_proceed call. It always exists except for method directly
|
16
14
|
# implemented in C -> Not a problem because these one never use ctxt_proceed
|
@@ -33,7 +31,9 @@ class Phenomenal::Adaptation
|
|
33
31
|
end
|
34
32
|
end
|
35
33
|
|
36
|
-
#
|
34
|
+
#TODO check for better implem
|
35
|
+
#TODO we are forced to keep unBoundMethod bind code,
|
36
|
+
# so allow user to use unbound meth?
|
37
37
|
# Bind the implementation corresponding to this adaptation to 'instance' when
|
38
38
|
# instance_method or to implementation klass when class method
|
39
39
|
def bind(instance,*args,&block)
|
@@ -52,28 +52,18 @@ class Phenomenal::Adaptation
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
+
# True if the adapted method is an instance method
|
56
|
+
def instance_adaptation?
|
57
|
+
klass.instance_methods.include?(method_name)
|
58
|
+
end
|
59
|
+
|
55
60
|
#True if the adaptation concern the class n_klass and method n_method
|
56
|
-
def concern?(klass,method_name
|
57
|
-
self.klass==klass &&
|
58
|
-
self.method_name==method_name &&
|
59
|
-
self.instance_adaptation==instance_adaptation
|
61
|
+
def concern?(klass,method_name)
|
62
|
+
self.klass==klass && self.method_name==method_name
|
60
63
|
end
|
61
64
|
|
62
|
-
alias_method :instance_adaptation?, :instance_adaptation
|
63
|
-
|
64
65
|
# String representation
|
65
66
|
def to_s
|
66
67
|
":#{context.name} => #{klass.name}.#{method_name} :: #{src_file}:#{src_line}"
|
67
68
|
end
|
68
|
-
|
69
|
-
private
|
70
|
-
def check_validity
|
71
|
-
if klass.instance_methods.include?(method_name) && !instance_adaptation? ||
|
72
|
-
!klass.instance_methods.include?(method_name) && instance_adaptation?
|
73
|
-
Phenomenal::Logger.instance.error(
|
74
|
-
"Illegal adaptation for context: #{context}" +
|
75
|
-
" for #{klass.name}.#{method_name}, type mismatch"
|
76
|
-
)
|
77
|
-
end
|
78
|
-
end
|
79
69
|
end
|
data/lib/phenomenal/context.rb
CHANGED
@@ -1,72 +1,47 @@
|
|
1
1
|
# Represent a first class context
|
2
2
|
class Phenomenal::Context
|
3
|
-
include Phenomenal::ContextRelationships
|
4
3
|
@@total_activations = 0
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
context = self.new(context)
|
11
|
-
else
|
12
|
-
context = manager.find_context(context)
|
13
|
-
if !context.instance_of?(self)
|
14
|
-
Phenomenal::Logger.instance.error(
|
15
|
-
"Only #{self.name} can be used with this keyword"
|
16
|
-
)
|
17
|
-
end
|
4
|
+
|
5
|
+
def self.create(*args,&block)
|
6
|
+
if args.length==1
|
7
|
+
if !Phenomenal::Manager.instance.context_defined?(args[0])
|
8
|
+
context = Phenomenal::Context.new(args[0])
|
18
9
|
end
|
10
|
+
context.add_adaptations(&block)
|
19
11
|
else #Combined contexts
|
20
|
-
|
21
|
-
context = self.new
|
22
|
-
context.parent=closest_feature # Set parent
|
23
|
-
instances = Array.new
|
24
|
-
first = contexts.first
|
25
|
-
contexts.each do |c|
|
26
|
-
# Use the object instance if already available
|
27
|
-
# otherwise create it
|
28
|
-
if manager.context_defined?(c)
|
29
|
-
c = manager.find_context(c)
|
30
|
-
if !nested && c!=first && !c.instance_of?(self)
|
31
|
-
Phenomenal::Logger.instance.error(
|
32
|
-
"Only #{self.name} can be used with this keyword"
|
33
|
-
)
|
34
|
-
end
|
35
|
-
else
|
36
|
-
c = self.new(c)
|
37
|
-
end
|
38
|
-
instances.push(c)
|
39
|
-
manager.shared_contexts[c]= Array.new if !manager.shared_contexts[c]
|
40
|
-
manager.shared_contexts[c].push(context)
|
41
|
-
end
|
42
|
-
manager.combined_contexts[context] = instances
|
43
|
-
else
|
44
|
-
context = manager.find_context(*contexts)
|
45
|
-
end
|
12
|
+
#TODO
|
46
13
|
end
|
47
|
-
context.add_adaptations(&block)
|
48
|
-
context
|
49
14
|
end
|
50
15
|
|
51
|
-
|
52
|
-
|
16
|
+
def self.create_feature(*args,&block)
|
17
|
+
context = self.create(*args,&block)
|
18
|
+
context.persistent=true
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_accessor :activation_age, :activation_frequency, :priority, :adaptations,
|
22
|
+
:activation_count, :persistent, :required, :implied, :guessed, :is_implied, :is_required
|
53
23
|
attr_reader :manager,:name
|
54
24
|
|
55
|
-
def initialize(name=nil, manager=nil)
|
25
|
+
def initialize(name=nil, priority=nil,persistent=false,manager=nil)
|
26
|
+
@persistent = persistent
|
56
27
|
@manager = manager || Phenomenal::Manager.instance
|
57
28
|
@name = name
|
29
|
+
@priority = priority
|
58
30
|
@activation_age = 0
|
59
31
|
@activation_count = 0
|
60
32
|
@adaptations = Array.new
|
61
33
|
@manager.register_context(self)
|
62
|
-
@
|
63
|
-
@
|
34
|
+
@implied = Array.new
|
35
|
+
@is_implied = {}
|
36
|
+
@required = Array.new
|
37
|
+
@is_required = {}
|
38
|
+
@guessed = Array.new
|
64
39
|
end
|
65
40
|
|
66
41
|
# Unregister the context from the context manager,
|
67
42
|
# This context shoudn't be used after.
|
68
43
|
# The context has to be inactive before being forgetted
|
69
|
-
# TODO
|
44
|
+
# TODO Find a way to avoid the use of forgeted context (use forgeted flag?)
|
70
45
|
def forget
|
71
46
|
if active?
|
72
47
|
Phenomenal::Logger.instance.error(
|
@@ -74,26 +49,24 @@ class Phenomenal::Context
|
|
74
49
|
)
|
75
50
|
else
|
76
51
|
manager.unregister_context(self)
|
77
|
-
forgotten=true
|
78
52
|
end
|
79
53
|
end
|
80
54
|
|
81
55
|
# Add a new method adaptation to the context
|
82
56
|
# Return the adaptation just created
|
83
|
-
def add_adaptation(klass, method_name,
|
57
|
+
def add_adaptation(klass, method_name,umeth=nil, &implementation)
|
84
58
|
if umeth
|
85
59
|
implementation = umeth
|
86
|
-
instance = klass.instance_methods.include?(method_name)
|
87
60
|
end
|
88
|
-
if adaptations.find{ |i| i.concern?(klass,method_name
|
61
|
+
if adaptations.find{ |i| i.concern?(klass,method_name) }
|
89
62
|
Phenomenal::Logger.instance.error(
|
90
63
|
"Error: Illegal duplicated adaptation in context: #{self} for " +
|
91
64
|
"#{klass.name}:#{method_name}"
|
92
65
|
)
|
93
66
|
else
|
94
|
-
if klass.instance_methods.include?(method_name)
|
67
|
+
if klass.instance_methods.include?(method_name)
|
95
68
|
method = klass.instance_method(method_name)
|
96
|
-
elsif klass.methods.include?(method_name)
|
69
|
+
elsif klass.methods.include?(method_name)
|
97
70
|
method = klass.method(method_name)
|
98
71
|
else
|
99
72
|
Phenomenal::Logger.instance.error(
|
@@ -112,31 +85,17 @@ class Phenomenal::Context
|
|
112
85
|
end
|
113
86
|
|
114
87
|
adaptation = Phenomenal::Adaptation.new(
|
115
|
-
self, klass, method_name,
|
88
|
+
self, klass, method_name, implementation
|
116
89
|
)
|
117
90
|
adaptations.push(adaptation)
|
118
91
|
manager.register_adaptation(adaptation)
|
119
92
|
adaptation
|
120
93
|
end
|
121
94
|
end
|
122
|
-
|
123
|
-
# Catch nested context calls and transform them in nested contexts creation
|
124
|
-
def context(context,*contexts,&block)
|
125
|
-
check_validity
|
126
|
-
Phenomenal::Context.create(self,context,*contexts,true,self,&block)
|
127
|
-
end
|
128
|
-
alias_method :phen_context,:context
|
129
|
-
|
130
|
-
# Catch nested feature calls and transform them in nested contexts creation
|
131
|
-
def feature(feature,*features, &block)
|
132
|
-
check_validity
|
133
|
-
Phenomenal::Feature.create(self,feature,*features,true,self,&block)
|
134
|
-
end
|
135
|
-
alias_method :phen_feature,:feature
|
136
95
|
|
137
96
|
# Add multiple adaptations at definition time
|
138
97
|
def add_adaptations(&block)
|
139
|
-
instance_eval(&block)
|
98
|
+
instance_eval(&block)
|
140
99
|
end
|
141
100
|
|
142
101
|
# Set the current adapted class for the next adapt calls
|
@@ -146,18 +105,41 @@ class Phenomenal::Context
|
|
146
105
|
|
147
106
|
# Adapt a method for @current_adapted_class
|
148
107
|
def adapt(method,&block)
|
149
|
-
add_adaptation(@current_adapted_class,method
|
108
|
+
add_adaptation(@current_adapted_class,method,&block)
|
150
109
|
end
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
110
|
+
|
111
|
+
|
112
|
+
# Requires
|
113
|
+
def requires(*args)
|
114
|
+
args.each do |context|
|
115
|
+
if !required.include?(context)
|
116
|
+
required.push(context)
|
117
|
+
end
|
118
|
+
end
|
155
119
|
end
|
156
120
|
|
121
|
+
# Implies
|
122
|
+
def implies(*args)
|
123
|
+
args.each do |context|
|
124
|
+
if !implies.include?(context)
|
125
|
+
implied.push(context)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# Guess
|
131
|
+
def guess(*args)
|
132
|
+
args.each do |context|
|
133
|
+
if !guessed.include?(context)
|
134
|
+
guessed.push(context)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
157
139
|
# Remove a method adaptation from the context
|
158
|
-
def remove_adaptation(klass,method_name
|
140
|
+
def remove_adaptation(klass,method_name)
|
159
141
|
adaptation_index =
|
160
|
-
adaptations.find_index{ |i| i.concern?(klass, method_name
|
142
|
+
adaptations.find_index{ |i| i.concern?(klass, method_name) }
|
161
143
|
if !adaptation_index
|
162
144
|
Phenomenal::Logger.instance.error(
|
163
145
|
"Error: Illegal deleting of an inexistent adaptation in context: " +
|
@@ -171,20 +153,75 @@ class Phenomenal::Context
|
|
171
153
|
|
172
154
|
# Activate the context
|
173
155
|
def activate
|
174
|
-
|
175
|
-
|
176
|
-
|
156
|
+
#TODO
|
157
|
+
# check_required
|
158
|
+
# activate_implicated
|
159
|
+
# activate_guessed
|
160
|
+
@@total_activations = @@total_activations+1
|
161
|
+
self.activation_age = @@total_activations
|
177
162
|
self.activation_count = self.activation_count+1
|
178
163
|
manager.activate_context(self)
|
179
164
|
self
|
180
|
-
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def check_required
|
168
|
+
required.each do |context_name|
|
169
|
+
context = manager.find_context(context_name)
|
170
|
+
if !context.active?
|
171
|
+
context.is_required[self.__id__] = self
|
172
|
+
Phenomenal::Logger.instance.error(
|
173
|
+
"Error: Required context #{context_name} not active."
|
174
|
+
)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def activate_implicated
|
180
|
+
activated = Array.new
|
181
|
+
begin
|
182
|
+
implicated.each do |context_name|
|
183
|
+
context = manager.find_context(context_name)
|
184
|
+
if !context.active?
|
185
|
+
context.activate
|
186
|
+
context.is_implied[self.__id__] = self
|
187
|
+
activated.push
|
188
|
+
end
|
189
|
+
end
|
190
|
+
rescue PhenomenalError => error
|
191
|
+
activated.reverse.each do |context|
|
192
|
+
context.deactivate
|
193
|
+
end
|
194
|
+
Phenomenal::Logger.instance.error(
|
195
|
+
"Error: Implication not satisfied for context #{name} : \n"+error
|
196
|
+
)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def activate_guessed
|
201
|
+
begin
|
202
|
+
implicated.each do |context_name|
|
203
|
+
context = manager.find_context(context_name)
|
204
|
+
if !context.active?
|
205
|
+
context.activate
|
206
|
+
end
|
207
|
+
end
|
208
|
+
rescue PhenomenalError # Don't care of error in case of guess
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
|
213
|
+
|
214
|
+
def can_activate
|
215
|
+
#TODO for exclude relations
|
216
|
+
true
|
217
|
+
end
|
218
|
+
|
219
|
+
|
181
220
|
|
182
221
|
# Deactivate the context
|
183
|
-
def deactivate
|
184
|
-
check_validity
|
222
|
+
def deactivate
|
185
223
|
was_active = active?
|
186
224
|
if self.activation_count>0
|
187
|
-
#Deactivation
|
188
225
|
self.activation_count = self.activation_count-1
|
189
226
|
end
|
190
227
|
if was_active && !active?
|
@@ -193,26 +230,25 @@ class Phenomenal::Context
|
|
193
230
|
self
|
194
231
|
end
|
195
232
|
|
233
|
+
def can_deactivate
|
234
|
+
#TODO for other relations
|
235
|
+
true
|
236
|
+
end
|
237
|
+
|
196
238
|
# True if the context is active
|
197
239
|
def active?
|
198
240
|
activation_count>0
|
199
241
|
end
|
200
242
|
|
201
|
-
# True if the context has just became active
|
202
|
-
def just_activated?
|
203
|
-
activation_count==1
|
204
|
-
end
|
205
|
-
|
206
|
-
# True if the context is anonymous
|
207
|
-
def anonymous?
|
208
|
-
name.nil?
|
209
|
-
end
|
210
|
-
|
211
243
|
# Return the activation age of the context:
|
212
244
|
# The age counter minus the age counter when the context was activated
|
213
245
|
# for the last time
|
214
246
|
def age
|
215
|
-
|
247
|
+
if activation_age == 0
|
248
|
+
@@total_activations
|
249
|
+
else
|
250
|
+
@@total_activations-activation_age
|
251
|
+
end
|
216
252
|
end
|
217
253
|
|
218
254
|
# Return context informations:
|
@@ -220,50 +256,21 @@ class Phenomenal::Context
|
|
220
256
|
# - List of the adaptations
|
221
257
|
# - Active state
|
222
258
|
# - Activation age
|
223
|
-
|
224
|
-
def information
|
259
|
+
def informations
|
225
260
|
{
|
226
261
|
:name=>name,
|
227
262
|
:adaptations=>adaptations,
|
228
263
|
:active=>active?,
|
229
|
-
:
|
230
|
-
:activation_count=>activation_count,
|
231
|
-
:type=>self.class.name
|
264
|
+
:activation_age=>age
|
232
265
|
}
|
233
266
|
end
|
234
267
|
|
235
|
-
# Return the closest parent feature of the context
|
236
|
-
def parent_feature
|
237
|
-
p = parent
|
238
|
-
while p!=nil && !p.is_a?(Phenomenal::Feature) do
|
239
|
-
p=p.parent
|
240
|
-
end
|
241
|
-
if p.nil?
|
242
|
-
manager.default_context
|
243
|
-
else
|
244
|
-
p
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
268
|
# String representation of the context
|
249
269
|
def to_s
|
250
270
|
if name
|
251
271
|
name.to_s
|
252
|
-
elsif self==manager.default_context
|
253
|
-
"'Default context'"
|
254
|
-
elsif manager.combined_contexts[self]
|
255
|
-
"'Combined context : #{manager.combined_contexts[self].flatten}'"
|
256
272
|
else
|
257
|
-
"
|
258
|
-
end
|
259
|
-
end
|
260
|
-
|
261
|
-
private
|
262
|
-
def check_validity
|
263
|
-
if forgotten
|
264
|
-
Phenomenal::Logger.instance.error(
|
265
|
-
"Action not allowed anymore when context has been forgotten"
|
266
|
-
)
|
273
|
+
"Anonymous context"
|
267
274
|
end
|
268
275
|
end
|
269
276
|
end
|