phenomenal 0.9.0 → 0.11.11.24.3
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/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/lib/phenomenal/feature.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
module Phenomenal::ContextRelationships
|
2
|
-
def requires(context,*contexts)
|
3
|
-
contexts = contexts.push(context)
|
4
|
-
contexts.each do |target|
|
5
|
-
self.parent_feature.requirements_for(self,{:on=>target})
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
def implies(context,*contexts)
|
10
|
-
contexts = contexts.push(context)
|
11
|
-
contexts.each do |target|
|
12
|
-
self.parent_feature.implications_for(self,{:on=>target})
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def suggests(context,*contexts)
|
17
|
-
contexts = contexts.push(context)
|
18
|
-
contexts.each do |target|
|
19
|
-
self.parent_feature.suggestions_for(self,{:on=>target})
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
module Phenomenal::DSL
|
2
|
-
def self.define_relationships(klass)
|
3
|
-
klass.class_eval do
|
4
|
-
# Requirements
|
5
|
-
def requirements_for(source,targets)
|
6
|
-
Phenomenal::Manager.instance.default_context.requirements_for(source,targets)
|
7
|
-
end
|
8
|
-
# Implications
|
9
|
-
def implications_for(source,targets)
|
10
|
-
Phenomenal::Manager.instance.default_context.implications_for(source,targets)
|
11
|
-
end
|
12
|
-
# Suggestions
|
13
|
-
def suggestions_for(source,targets)
|
14
|
-
Phenomenal::Manager.instance.default_context.suggestions_for(source,targets)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
module Phenomenal::FeatureRelationships
|
2
|
-
attr_accessor :relationships
|
3
|
-
|
4
|
-
def initialize_relationships
|
5
|
-
@relationships = Array.new
|
6
|
-
end
|
7
|
-
|
8
|
-
def requirements_for(source,targets)
|
9
|
-
add_relationship(source,targets,Phenomenal::Requirement)
|
10
|
-
end
|
11
|
-
|
12
|
-
def implications_for(source,targets)
|
13
|
-
add_relationship(source,targets,Phenomenal::Implication)
|
14
|
-
end
|
15
|
-
|
16
|
-
def suggestions_for(source,targets)
|
17
|
-
add_relationship(source,targets,Phenomenal::Suggestion)
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
def add_relationship(source,targets,type)
|
22
|
-
targets[:on]=Array.new.push(targets[:on]) if !targets[:on].is_a?(Array)
|
23
|
-
|
24
|
-
if targets[:on].nil?
|
25
|
-
Phenomenal::Logger.instance.error(
|
26
|
-
"Invalid relationship, missing target context"
|
27
|
-
)
|
28
|
-
end
|
29
|
-
targets[:on].each do |target|
|
30
|
-
r = type.new(source,target,self)
|
31
|
-
if relationships.find{|o| o==r}.nil?
|
32
|
-
relationships.push(r)
|
33
|
-
if self.active?
|
34
|
-
r.refresh
|
35
|
-
manager.rmanager.relationships.add(r)
|
36
|
-
r.activate_feature
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
end
|
42
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
class Phenomenal::Implication < Phenomenal::Relationship
|
2
|
-
attr_accessor :activation_counter
|
3
|
-
def initialize(source,target,feature)
|
4
|
-
super(source,target,feature)
|
5
|
-
@activation_counter=0
|
6
|
-
end
|
7
|
-
|
8
|
-
def activate_feature
|
9
|
-
if source.active?
|
10
|
-
target.activate
|
11
|
-
activation_counter+=1
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def deactivate_feature
|
16
|
-
if activation_counter>0
|
17
|
-
target.deactivate
|
18
|
-
activation_coutner-=1
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def activate_context(context)
|
23
|
-
if source==context
|
24
|
-
target.activate
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def deactivate_context(context)
|
29
|
-
if source==context
|
30
|
-
target.deactivate
|
31
|
-
else
|
32
|
-
source.deactivate
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
class Phenomenal::Relationship
|
2
|
-
attr_accessor :source,:target,:manager,:feature
|
3
|
-
|
4
|
-
def initialize(source,target,feature)
|
5
|
-
@source=source
|
6
|
-
@target=target
|
7
|
-
@manager=Phenomenal::Manager.instance
|
8
|
-
@feature=feature
|
9
|
-
refresh
|
10
|
-
end
|
11
|
-
|
12
|
-
def ==(other)
|
13
|
-
self.class==other.class &&
|
14
|
-
self.source==other.source &&
|
15
|
-
self.target==other.target &&
|
16
|
-
self.feature==other.feature
|
17
|
-
end
|
18
|
-
|
19
|
-
def refresh
|
20
|
-
s = manager.context_defined?(source)
|
21
|
-
self.source=s if !s.nil?
|
22
|
-
|
23
|
-
t = manager.context_defined?(target)
|
24
|
-
self.target=t if !t.nil?
|
25
|
-
end
|
26
|
-
|
27
|
-
def activate_context(context)
|
28
|
-
end
|
29
|
-
|
30
|
-
def deactivate_context(context)
|
31
|
-
end
|
32
|
-
|
33
|
-
def activate_feature
|
34
|
-
end
|
35
|
-
|
36
|
-
def deactivate_feature
|
37
|
-
end
|
38
|
-
|
39
|
-
def to_s
|
40
|
-
"#{self.class.name} between #{source.class.name}:#{source} and #{target.class.name}:#{target}"
|
41
|
-
end
|
42
|
-
end
|
@@ -1,63 +0,0 @@
|
|
1
|
-
require 'singleton'
|
2
|
-
|
3
|
-
class Phenomenal::RelationshipsManager
|
4
|
-
include Singleton
|
5
|
-
|
6
|
-
attr_accessor :relationships
|
7
|
-
|
8
|
-
def activate_relationships(context)
|
9
|
-
# Step 1: Import the new relationships for a feature
|
10
|
-
if context.is_a?(Phenomenal::Feature)
|
11
|
-
import_relationships(context)
|
12
|
-
end
|
13
|
-
# Step 2: Apply relationships
|
14
|
-
relationships.get_for(context).each do |relationship|
|
15
|
-
relationship.activate_context(context)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def deactivate_relationships(context)
|
20
|
-
# Step 1: Unapply relationships
|
21
|
-
relationships.get_for(context).each do |relationship|
|
22
|
-
relationship.deactivate_context(context)
|
23
|
-
end
|
24
|
-
# Step 2: Remove relationships
|
25
|
-
if context.is_a?(Phenomenal::Feature)
|
26
|
-
remove_relationships(context)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
# Called when a context is defined in the manager
|
31
|
-
def update_relationships_references(context)
|
32
|
-
relationships.update_references(context)
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
def import_relationships(feature)
|
37
|
-
begin
|
38
|
-
feature.relationships.each do |relationship|
|
39
|
-
relationship.refresh # Update references
|
40
|
-
relationship.activate_feature # Activate relationship
|
41
|
-
relationships.add(relationship)
|
42
|
-
end
|
43
|
-
rescue Phenomenal::Error => m
|
44
|
-
feature.deactivate
|
45
|
-
Phenomenal::Logger.instance.debug(
|
46
|
-
"Unable to activate the feature #{feature} \n #{m}"
|
47
|
-
)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def remove_relationships(feature)
|
52
|
-
feature.relationships.each do |relationship|
|
53
|
-
if relationships.include?(relationship)
|
54
|
-
relationship.deactivate_feature
|
55
|
-
relationships.remove(relationship)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def initialize
|
61
|
-
@relationships = Phenomenal::RelationshipsStore.new
|
62
|
-
end
|
63
|
-
end
|
@@ -1,73 +0,0 @@
|
|
1
|
-
class Phenomenal::RelationshipsStore
|
2
|
-
attr_accessor :sources, :targets
|
3
|
-
|
4
|
-
def initialize
|
5
|
-
@sources = {}
|
6
|
-
@targets = {}
|
7
|
-
end
|
8
|
-
|
9
|
-
def add(relationship)
|
10
|
-
if @sources[relationship.source].nil?
|
11
|
-
@sources[relationship.source] = Array.new
|
12
|
-
end
|
13
|
-
@sources[relationship.source].push(relationship)
|
14
|
-
|
15
|
-
if @targets[relationship.target].nil?
|
16
|
-
@targets[relationship.target] = Array.new
|
17
|
-
end
|
18
|
-
@targets[relationship.target].push(relationship)
|
19
|
-
end
|
20
|
-
|
21
|
-
def remove(relationship)
|
22
|
-
@sources[relationship.source].delete(relationship) if @sources[relationship.source] # In case of rollback
|
23
|
-
@targets[relationship.target].delete(relationship) if @targets[relationship.target]
|
24
|
-
end
|
25
|
-
|
26
|
-
def include?(relationship)
|
27
|
-
if @sources[relationship.source]
|
28
|
-
@sources[relationship.source].include?(relationship)
|
29
|
-
else
|
30
|
-
false
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def update_references(context)
|
35
|
-
# Do nothing when anonymous, references are already valid
|
36
|
-
return if context.anonymous?
|
37
|
-
# Update sources
|
38
|
-
@sources[context.name].each do |relationship|
|
39
|
-
relationship.source=context
|
40
|
-
end
|
41
|
-
@sources[context]=@source.delete(context.name)
|
42
|
-
# Update targets
|
43
|
-
@targets[context.name].each do |relationship|
|
44
|
-
relationship.target=context
|
45
|
-
end
|
46
|
-
@targets[context]=@targets.delete(context.name)
|
47
|
-
end
|
48
|
-
|
49
|
-
def get_for(context)
|
50
|
-
get_for_source(context).concat(get_for_target(context))
|
51
|
-
end
|
52
|
-
|
53
|
-
private
|
54
|
-
# Return an array of relationships
|
55
|
-
def get_for_source(source)
|
56
|
-
rel = @sources[source]
|
57
|
-
if rel.nil?
|
58
|
-
Array.new
|
59
|
-
else
|
60
|
-
rel
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
# Return an array of relationships
|
65
|
-
def get_for_target(target)
|
66
|
-
rel = @targets[target]
|
67
|
-
if rel.nil?
|
68
|
-
Array.new
|
69
|
-
else
|
70
|
-
rel
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
class Phenomenal::Requirement < Phenomenal::Relationship
|
2
|
-
def activate_feature
|
3
|
-
check_requirement
|
4
|
-
end
|
5
|
-
|
6
|
-
def activate_context(context)
|
7
|
-
if(source==context)
|
8
|
-
check_requirement
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def deactivate_context(context)
|
13
|
-
if(target==context)
|
14
|
-
source.deactivate
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
19
|
-
def check_requirement
|
20
|
-
if source.active? && !target.active?
|
21
|
-
Phenomenal::Logger.instance.error(
|
22
|
-
"Requirement of #{target} for #{source} is not satisfied"
|
23
|
-
)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
class Phenomenal::Suggestion < Phenomenal::Relationship
|
2
|
-
attr_accessor :activation_counter
|
3
|
-
|
4
|
-
def initialize(source,target,feature)
|
5
|
-
super(source,target,feature)
|
6
|
-
@activation_counter=0
|
7
|
-
end
|
8
|
-
|
9
|
-
def activate_feature
|
10
|
-
begin
|
11
|
-
if source.active?
|
12
|
-
target.activate
|
13
|
-
self.activation_counter+=1
|
14
|
-
end
|
15
|
-
rescue
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def deactivate_feature
|
20
|
-
begin
|
21
|
-
if activation_counter>0
|
22
|
-
target.deactivate
|
23
|
-
self.activation_coutner-=1
|
24
|
-
end
|
25
|
-
rescue
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
|
30
|
-
def activate_context(context)
|
31
|
-
if source==context
|
32
|
-
target.activate
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def deactivate_context(context)
|
37
|
-
if source==context
|
38
|
-
target.deactivate
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
data/lib/phenomenal/version.rb
DELETED
data/spec/adaptation_spec.rb
DELETED
@@ -1,64 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
describe Phenomenal::Adaptation do
|
3
|
-
before :each do
|
4
|
-
define_test_classes
|
5
|
-
end
|
6
|
-
|
7
|
-
describe "#deploy" do
|
8
|
-
it "should be able to deploy itself in instances to override default implementation" do
|
9
|
-
adaptation = Phenomenal::Adaptation.new(nil,TestString,:length,true,Proc.new{-1})
|
10
|
-
t = TestString.new("1234")
|
11
|
-
t.length.should == 4
|
12
|
-
expect {adaptation.deploy}.to_not raise_error
|
13
|
-
t.length.should == -1
|
14
|
-
end
|
15
|
-
|
16
|
-
it "should be able to deploy itself in classes to override default implementation" do
|
17
|
-
TestString.name.should == "TestString"
|
18
|
-
adaptation = Phenomenal::Adaptation.new(nil,TestString,:name,false,Proc.new{"TEST"})
|
19
|
-
expect {adaptation.deploy}.to_not raise_error
|
20
|
-
TestString.name.should == "TEST"
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
describe "#bind" do
|
25
|
-
it "should be possible to temporary bind adapation as instance methods" do
|
26
|
-
adaptation = Phenomenal::Adaptation.new(nil,TestString,:length,true,Proc.new{-10})
|
27
|
-
t = TestString.new("1234")
|
28
|
-
t.length.should == -1
|
29
|
-
adaptation.bind(t).should == -10
|
30
|
-
t.length.should == -1
|
31
|
-
end
|
32
|
-
|
33
|
-
it "should be possible to temporary bind adapatation as class methods" do
|
34
|
-
TestString.name.should == "TEST"
|
35
|
-
adaptation = Phenomenal::Adaptation.new(nil,TestString,:name,false,Proc.new{"TEST2"})
|
36
|
-
adaptation.bind(TestString).should == "TEST2"
|
37
|
-
TestString.name.should == "TEST"
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
describe "#instance_adaptation?" do
|
42
|
-
it "should return true if the method is a instance method" do
|
43
|
-
adaptation = Phenomenal::Adaptation.new(nil,TestString,:length,true,Proc.new{-10})
|
44
|
-
adaptation.instance_adaptation?.should be_true
|
45
|
-
end
|
46
|
-
|
47
|
-
it "should return false if the method is a class method" do
|
48
|
-
adaptation = Phenomenal::Adaptation.new(nil,TestString,:name,false,Proc.new{"TEST2"})
|
49
|
-
adaptation.instance_adaptation?.should be_false
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
describe "#concern" do
|
54
|
-
it "should return true if the adaptation concern the class n_klass and method n_method and is instance method if instance=true" do
|
55
|
-
adaptation = Phenomenal::Adaptation.new(nil,TestString,:length,true,Proc.new{-10})
|
56
|
-
adaptation.concern?(TestString,:length,true).should be_true
|
57
|
-
end
|
58
|
-
|
59
|
-
it "should return false if the adaptation doesn't concern the class n_klass and method n_method and is instance method if instance=true" do
|
60
|
-
adaptation = Phenomenal::Adaptation.new(nil,TestString,:size,true,Proc.new{-10})
|
61
|
-
adaptation.concern?(TestString,:length,true).should be_false
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|