proteus 0.9.0
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/COPYING +674 -0
- data/README +88 -0
- data/Rakefile +33 -0
- data/bin/pro +189 -0
- data/lib/ClassParser.rb +84 -0
- data/lib/ComponentClass.rb +51 -0
- data/lib/ComponentInstance.rb +76 -0
- data/lib/DefinitionHelper.rb +157 -0
- data/lib/DefinitionParser.rb +107 -0
- data/lib/Facade.rb +116 -0
- data/lib/FileHelper.rb +80 -0
- data/lib/InputParser.rb +241 -0
- data/lib/InstanceParser.rb +65 -0
- data/lib/InstanceProxy.rb +100 -0
- data/lib/PropertyHash.rb +64 -0
- data/lib/TemplateRenderer.rb +128 -0
- data/lib/exceptions.rb +50 -0
- data/test/spec/ClassParser_spec.rb +314 -0
- data/test/spec/ComponentClass_spec.rb +44 -0
- data/test/spec/ComponentInstance_spec.rb +50 -0
- data/test/spec/DefinitionHelper_spec.rb +134 -0
- data/test/spec/DefinitionParser_spec.rb +236 -0
- data/test/spec/Facade_spec.rb +44 -0
- data/test/spec/FileHelper_spec.rb +113 -0
- data/test/spec/InputParser_spec.rb +424 -0
- data/test/spec/InstanceParser_spec.rb +125 -0
- data/test/spec/TemplateRenderer_spec.rb +54 -0
- data/test/spec/lib/NS1/TestComponent10.def +4 -0
- data/test/spec/lib/NS1/TestComponent11.def +4 -0
- data/test/spec/lib/NS1/TestComponent4.def +4 -0
- data/test/spec/lib/NS1/TestComponent5.def +4 -0
- data/test/spec/lib/NS1/TestComponent8.def +4 -0
- data/test/spec/lib/NS1/TestComponent9.def +4 -0
- data/test/spec/lib/NS2/TestComponent6.def +4 -0
- data/test/spec/lib/TestComponent1.def +4 -0
- data/test/spec/lib/TestComponent3.def +4 -0
- data/test/spec/test_lib_dir1/File1.def +0 -0
- data/test/spec/test_lib_dir1/File3.def +0 -0
- data/test/spec/test_lib_dir1/NS1/File4.def +0 -0
- data/test/spec/test_lib_dir1/NS1/NS2/File5.def +0 -0
- data/test/spec/test_lib_dir2/File1.def +0 -0
- data/test/spec/test_lib_dir2/File2.def +0 -0
- metadata +113 -0
@@ -0,0 +1,76 @@
|
|
1
|
+
################################################################################
|
2
|
+
# ComponentInstance.rb
|
3
|
+
#
|
4
|
+
# Represents an instance of a component.
|
5
|
+
# -----------------------------------------------------------------------------
|
6
|
+
# (C) Copyright 2009 William Madden
|
7
|
+
#
|
8
|
+
# This file is part of Proteus.
|
9
|
+
#
|
10
|
+
# Proteus is free software: you can redistribute it and/or modify it under the
|
11
|
+
# terms of the GNU General Public License as published by the Free Software
|
12
|
+
# Foundation, either version 3 of the License, or (at your option) any later
|
13
|
+
# version.
|
14
|
+
#
|
15
|
+
# Proteus is distributed in the hope that it will be useful, but WITHOUT ANY
|
16
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
17
|
+
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
18
|
+
#
|
19
|
+
# You should have received a copy of the GNU General Public License along with
|
20
|
+
# Proteus. If not, see <http://www.gnu.org/licenses/>.
|
21
|
+
################################################################################
|
22
|
+
|
23
|
+
require File.expand_path( File.join(File.dirname(__FILE__), 'ComponentClass.rb') )
|
24
|
+
|
25
|
+
|
26
|
+
module Proteus
|
27
|
+
|
28
|
+
class ComponentInstance
|
29
|
+
|
30
|
+
#---------------------------------------------------------------------------
|
31
|
+
#
|
32
|
+
# Constructor
|
33
|
+
#
|
34
|
+
#---------------------------------------------------------------------------
|
35
|
+
|
36
|
+
def initialize( kind = ComponentClass::DEFAULT_CLASS,
|
37
|
+
properties = {}, children = [] )
|
38
|
+
|
39
|
+
@kind = kind
|
40
|
+
@properties = properties
|
41
|
+
@children = children
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
#---------------------------------------------------------------------------
|
46
|
+
#
|
47
|
+
# Properties
|
48
|
+
#
|
49
|
+
#---------------------------------------------------------------------------
|
50
|
+
|
51
|
+
attr_accessor :kind, :children, :properties
|
52
|
+
|
53
|
+
#---------------------------------------------------------------------------
|
54
|
+
#
|
55
|
+
# Methods
|
56
|
+
#
|
57
|
+
#---------------------------------------------------------------------------
|
58
|
+
|
59
|
+
#
|
60
|
+
# Merges the component's properties with the class's and returns the result.
|
61
|
+
#
|
62
|
+
def final_properties
|
63
|
+
return kind.properties.merge( @properties )
|
64
|
+
end
|
65
|
+
|
66
|
+
#
|
67
|
+
# Merges the component's children with the class's and returns the result.
|
68
|
+
#
|
69
|
+
def final_children
|
70
|
+
return kind.children.merge( @children )
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
@@ -0,0 +1,157 @@
|
|
1
|
+
################################################################################
|
2
|
+
# DefinitionHelper.rb
|
3
|
+
#
|
4
|
+
# Responsible for loading definitions and maintaining the set of loaded classes.
|
5
|
+
# -----------------------------------------------------------------------------
|
6
|
+
# (C) Copyright 2009 William Madden
|
7
|
+
#
|
8
|
+
# This file is part of Proteus.
|
9
|
+
#
|
10
|
+
# Proteus is free software: you can redistribute it and/or modify it under the
|
11
|
+
# terms of the GNU General Public License as published by the Free Software
|
12
|
+
# Foundation, either version 3 of the License, or (at your option) any later
|
13
|
+
# version.
|
14
|
+
#
|
15
|
+
# Proteus is distributed in the hope that it will be useful, but WITHOUT ANY
|
16
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
17
|
+
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
18
|
+
#
|
19
|
+
# You should have received a copy of the GNU General Public License along with
|
20
|
+
# Proteus. If not, see <http://www.gnu.org/licenses/>.
|
21
|
+
################################################################################
|
22
|
+
|
23
|
+
require 'yaml'
|
24
|
+
|
25
|
+
require File.expand_path( File.join(File.dirname(__FILE__), 'DefinitionParser.rb') )
|
26
|
+
require File.expand_path( File.join(File.dirname(__FILE__), 'FileHelper.rb') )
|
27
|
+
require File.expand_path( File.join(File.dirname(__FILE__), 'exceptions.rb') )
|
28
|
+
|
29
|
+
|
30
|
+
module Proteus
|
31
|
+
|
32
|
+
class DefinitionHelper
|
33
|
+
|
34
|
+
#---------------------------------------------------------------------------
|
35
|
+
#
|
36
|
+
# Constructor
|
37
|
+
#
|
38
|
+
#---------------------------------------------------------------------------
|
39
|
+
|
40
|
+
def initialize( definition_parser = nil, path = nil )
|
41
|
+
@path = path
|
42
|
+
@definition_parser = definition_parser
|
43
|
+
|
44
|
+
@loaded_classes = {}
|
45
|
+
@loading = []
|
46
|
+
end
|
47
|
+
|
48
|
+
#---------------------------------------------------------------------------
|
49
|
+
#
|
50
|
+
# Properties
|
51
|
+
#
|
52
|
+
#---------------------------------------------------------------------------
|
53
|
+
|
54
|
+
public
|
55
|
+
|
56
|
+
attr_accessor :path, :definition_parser
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
attr_accessor :loaded_classes
|
61
|
+
|
62
|
+
#---------------------------------------------------------------------------
|
63
|
+
#
|
64
|
+
# Methods
|
65
|
+
#
|
66
|
+
#---------------------------------------------------------------------------
|
67
|
+
|
68
|
+
public
|
69
|
+
|
70
|
+
#
|
71
|
+
# Returns the given class.
|
72
|
+
#
|
73
|
+
# class_path: an array containing the namespaces and class id of the class
|
74
|
+
# current_ns: the current namespace, an array of namespace identifiers
|
75
|
+
#
|
76
|
+
def get_class( class_path, current_ns )
|
77
|
+
|
78
|
+
current_ns = current_ns || []
|
79
|
+
|
80
|
+
# 1. Search the current namespace
|
81
|
+
# 2. Search the default namespace
|
82
|
+
begin
|
83
|
+
result = find_class( current_ns.concat(class_path) )
|
84
|
+
rescue Exceptions::DefinitionUnavailable
|
85
|
+
result = find_class( class_path )
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
#
|
94
|
+
# Searches for the given class and loads it if not found.
|
95
|
+
#
|
96
|
+
# class_path: the fully qualified class path, including ALL namespaces.
|
97
|
+
#
|
98
|
+
def find_class( class_path )
|
99
|
+
|
100
|
+
# If it's already loaded, return it.
|
101
|
+
if @loaded_classes.has_key?( class_path )
|
102
|
+
return @loaded_classes[ class_path ]
|
103
|
+
end
|
104
|
+
|
105
|
+
# Otherwise create it,
|
106
|
+
new_class = ComponentClass.new
|
107
|
+
|
108
|
+
# add it to the dictionary,
|
109
|
+
@loaded_classes[ class_path ] = new_class
|
110
|
+
|
111
|
+
# load its definition,
|
112
|
+
begin
|
113
|
+
new_class = load_class( class_path, new_class )
|
114
|
+
rescue Exception => exception
|
115
|
+
# Load failed so delete it from the dictionary
|
116
|
+
# TODO: consider dropping entire dictionary, since linked classes might
|
117
|
+
# also be affected
|
118
|
+
@loaded_classes.delete( class_path )
|
119
|
+
|
120
|
+
raise exception
|
121
|
+
end
|
122
|
+
|
123
|
+
# and return it.
|
124
|
+
return new_class
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
#
|
129
|
+
# Loads the given class.
|
130
|
+
#
|
131
|
+
# class_path: the full path of the class, including all namespaces
|
132
|
+
#
|
133
|
+
def load_class( class_path, new_class )
|
134
|
+
|
135
|
+
file = FileHelper.find_definition( class_path, @path )
|
136
|
+
|
137
|
+
if file.nil?
|
138
|
+
raise Exceptions::DefinitionUnavailable,
|
139
|
+
"File not found for class path: '" + class_path.inspect + "'"
|
140
|
+
end
|
141
|
+
|
142
|
+
yaml = YAML.load_file( file )
|
143
|
+
|
144
|
+
@definition_parser.parse_yaml( yaml, new_class, class_path.slice(0..-2) )
|
145
|
+
|
146
|
+
if new_class.name != class_path[ class_path.length - 1 ]
|
147
|
+
raise Exceptions::DefinitionMalformed,
|
148
|
+
"Definition class name ('" + new_class.name +
|
149
|
+
"') does not match file name ('" +
|
150
|
+
class_path[ class_path.length - 1 ] + "')."
|
151
|
+
end
|
152
|
+
|
153
|
+
return new_class
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
################################################################################
|
2
|
+
# DefinitionParser.rb
|
3
|
+
#
|
4
|
+
# Responsible for interpreting YAML for definition files.
|
5
|
+
# -----------------------------------------------------------------------------
|
6
|
+
# (C) Copyright 2009 William Madden
|
7
|
+
#
|
8
|
+
# This file is part of Proteus.
|
9
|
+
#
|
10
|
+
# Proteus is free software: you can redistribute it and/or modify it under the
|
11
|
+
# terms of the GNU General Public License as published by the Free Software
|
12
|
+
# Foundation, either version 3 of the License, or (at your option) any later
|
13
|
+
# version.
|
14
|
+
#
|
15
|
+
# Proteus is distributed in the hope that it will be useful, but WITHOUT ANY
|
16
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
17
|
+
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
18
|
+
#
|
19
|
+
# You should have received a copy of the GNU General Public License along with
|
20
|
+
# Proteus. If not, see <http://www.gnu.org/licenses/>.
|
21
|
+
################################################################################
|
22
|
+
|
23
|
+
require File.expand_path( File.join(File.dirname(__FILE__), 'ComponentClass.rb') )
|
24
|
+
|
25
|
+
|
26
|
+
module Proteus
|
27
|
+
|
28
|
+
class DefinitionParser
|
29
|
+
|
30
|
+
#---------------------------------------------------------------------------
|
31
|
+
#
|
32
|
+
# Constructor
|
33
|
+
#
|
34
|
+
#---------------------------------------------------------------------------
|
35
|
+
|
36
|
+
def initialize( definition_helper = nil, class_parser = nil,
|
37
|
+
input_parser = nil )
|
38
|
+
|
39
|
+
@definition_helper = definition_helper
|
40
|
+
@class_parser = class_parser
|
41
|
+
@input_parser = input_parser
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
#---------------------------------------------------------------------------
|
46
|
+
#
|
47
|
+
# Properties
|
48
|
+
#
|
49
|
+
#---------------------------------------------------------------------------
|
50
|
+
|
51
|
+
public
|
52
|
+
|
53
|
+
attr_accessor :definition_helper, :class_parser, :input_parser
|
54
|
+
|
55
|
+
#---------------------------------------------------------------------------
|
56
|
+
#
|
57
|
+
# Methods
|
58
|
+
#
|
59
|
+
#---------------------------------------------------------------------------
|
60
|
+
|
61
|
+
public
|
62
|
+
|
63
|
+
#------------------------------
|
64
|
+
# parse_yaml
|
65
|
+
#------------------------------
|
66
|
+
|
67
|
+
#
|
68
|
+
# Takes the YAML input read directly from the definition file and parses it,
|
69
|
+
# returning the loaded ComponentClass.
|
70
|
+
#
|
71
|
+
# yaml: The input YAML to be parsed.
|
72
|
+
# component_class: The component class to load.
|
73
|
+
#
|
74
|
+
def parse_yaml( yaml, component_class, current_ns = nil )
|
75
|
+
|
76
|
+
result = component_class || ComponentClass.new
|
77
|
+
|
78
|
+
# Let the class parser handle interpreting the YAML, then load the parent
|
79
|
+
# class and parse all the values in the children and properties of the new
|
80
|
+
# component class.
|
81
|
+
|
82
|
+
@class_parser.parse_yaml( yaml, result )
|
83
|
+
|
84
|
+
# Get the parent class
|
85
|
+
if result.parent != nil
|
86
|
+
result.parent = @definition_helper.get_class( result.parent.split(':'),
|
87
|
+
current_ns )
|
88
|
+
end
|
89
|
+
|
90
|
+
# Parse properties
|
91
|
+
for property in result.properties
|
92
|
+
result.properties[ property[0] ] =
|
93
|
+
@input_parser.parse_yaml( property[1], current_ns )
|
94
|
+
end
|
95
|
+
|
96
|
+
# Parse children
|
97
|
+
result.children.length.times do |i|
|
98
|
+
result.children[i] = @input_parser.parse_yaml( result.children[i],
|
99
|
+
current_ns )
|
100
|
+
end
|
101
|
+
|
102
|
+
return result
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
data/lib/Facade.rb
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
################################################################################
|
2
|
+
# Facade.rb
|
3
|
+
#
|
4
|
+
# An implementation of the Facade pattern. Provides an easy way to handle the
|
5
|
+
# parser and helper classes.
|
6
|
+
# -----------------------------------------------------------------------------
|
7
|
+
# (C) Copyright 2009 William Madden
|
8
|
+
#
|
9
|
+
# This file is part of Proteus.
|
10
|
+
#
|
11
|
+
# Proteus is free software: you can redistribute it and/or modify it under the
|
12
|
+
# terms of the GNU General Public License as published by the Free Software
|
13
|
+
# Foundation, either version 3 of the License, or (at your option) any later
|
14
|
+
# version.
|
15
|
+
#
|
16
|
+
# Proteus is distributed in the hope that it will be useful, but WITHOUT ANY
|
17
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
18
|
+
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
19
|
+
#
|
20
|
+
# You should have received a copy of the GNU General Public License along with
|
21
|
+
# Proteus. If not, see <http://www.gnu.org/licenses/>.
|
22
|
+
################################################################################
|
23
|
+
|
24
|
+
require File.expand_path( File.join(File.dirname(__FILE__), 'DefinitionHelper.rb') )
|
25
|
+
|
26
|
+
require File.expand_path( File.join(File.dirname(__FILE__), 'InstanceParser.rb') )
|
27
|
+
require File.expand_path( File.join(File.dirname(__FILE__), 'ClassParser.rb') )
|
28
|
+
require File.expand_path( File.join(File.dirname(__FILE__), 'InputParser.rb') )
|
29
|
+
require File.expand_path( File.join(File.dirname(__FILE__), 'DefinitionParser.rb') )
|
30
|
+
|
31
|
+
module Proteus
|
32
|
+
|
33
|
+
class Facade
|
34
|
+
|
35
|
+
#---------------------------------------------------------------------------
|
36
|
+
#
|
37
|
+
# Constructor
|
38
|
+
#
|
39
|
+
#---------------------------------------------------------------------------
|
40
|
+
|
41
|
+
def initialize( )
|
42
|
+
|
43
|
+
# Instance parser
|
44
|
+
@instance_parser = InstanceParser.new
|
45
|
+
|
46
|
+
# Class parser
|
47
|
+
@class_parser = ClassParser.new
|
48
|
+
|
49
|
+
# Definition parser
|
50
|
+
@definition_parser = DefinitionParser.new
|
51
|
+
@definition_parser.class_parser = @class_parser
|
52
|
+
|
53
|
+
# Definition helper
|
54
|
+
@definition_helper = DefinitionHelper.new
|
55
|
+
@definition_helper.definition_parser = @definition_parser
|
56
|
+
|
57
|
+
@definition_parser.definition_helper = @definition_helper
|
58
|
+
|
59
|
+
# Input parser
|
60
|
+
@input_parser = InputParser.new
|
61
|
+
@input_parser.instance_parser = @instance_parser
|
62
|
+
@input_parser.definition_helper = @definition_helper
|
63
|
+
|
64
|
+
@definition_parser.input_parser = @input_parser
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
#---------------------------------------------------------------------------
|
69
|
+
#
|
70
|
+
# Properties
|
71
|
+
#
|
72
|
+
#---------------------------------------------------------------------------
|
73
|
+
|
74
|
+
public
|
75
|
+
|
76
|
+
# Parsers
|
77
|
+
attr_accessor :class_parser, :instance_parser, :definition_parser,
|
78
|
+
:input_parser
|
79
|
+
|
80
|
+
# Helpers
|
81
|
+
attr_accessor :definition_helper
|
82
|
+
|
83
|
+
# Properties
|
84
|
+
attr_reader :path
|
85
|
+
|
86
|
+
def path=( value )
|
87
|
+
@path = value
|
88
|
+
@definition_helper.path = value
|
89
|
+
end
|
90
|
+
|
91
|
+
#---------------------------------------------------------------------------
|
92
|
+
#
|
93
|
+
# Methods
|
94
|
+
#
|
95
|
+
#---------------------------------------------------------------------------
|
96
|
+
|
97
|
+
public
|
98
|
+
|
99
|
+
#
|
100
|
+
# Parses the given input YAML.
|
101
|
+
#
|
102
|
+
def parse_input( yaml, current_ns = [] )
|
103
|
+
return @input_parser.parse_yaml( yaml )
|
104
|
+
end
|
105
|
+
|
106
|
+
#
|
107
|
+
# Parses the given input file.
|
108
|
+
#
|
109
|
+
def parse_file( file, current_ns = [] )
|
110
|
+
return @input_parser.parse_yaml( YAML.load_file(file) )
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|