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/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
|