gf-tree_visitor 0.0.2

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 ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 gf
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,28 @@
1
+ = ralbum_commmon
2
+
3
+ * FIX (url)
4
+
5
+ == DESCRIPTION:
6
+
7
+ FIX (describe your package)
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * FIX (list of features or problems)
12
+
13
+ == SYNOPSIS:
14
+
15
+ FIX (code sample of usage)
16
+
17
+ == REQUIREMENTS:
18
+
19
+ * utilizza la libreria abstract di kwartz
20
+ * gui: dipende da fxruby e/o wxruby
21
+
22
+ == INSTALL:
23
+
24
+ * FIX (sudo gem install, anything else)
25
+
26
+ == Copyright
27
+
28
+ Copyright (c) 2009 gf. See LICENSE for details.
data/bin/dirtree.rb ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Piccolo wrapper per richiamare il programma
4
+ # clidirtree
5
+ #
6
+
7
+ $COMMON_HOME = File.expand_path( File.join( File.dirname( __FILE__), ".." ) )
8
+ $:.unshift( File.join($COMMON_HOME, "lib" ) )
9
+
10
+ require "tree_visitor/cli/cli_dir_tree"
11
+
12
+ CliDirTree.run
13
+ exit
@@ -0,0 +1,116 @@
1
+ # rubygems
2
+ require "rubygems"
3
+ require "abstract"
4
+
5
+ #
6
+ # Nodo Astratto
7
+ # Gerarchia delle classi
8
+ #
9
+ # AbsNode ha un nome, un parent
10
+ # | definisce un path
11
+ # |
12
+ # |- LeafNode
13
+ # |
14
+ # |- TreeNode
15
+ #
16
+ #
17
+ class AbsNode
18
+
19
+ attr_reader :parent
20
+ attr_reader :name
21
+
22
+ # solo TreeNode puo' scrivere vedi funzione add_leaf
23
+ attr_accessor :prev
24
+ attr_accessor :next
25
+
26
+
27
+ def initialize( name )
28
+ @parent = nil
29
+ @name = name
30
+ @prefix_path = nil
31
+ invalidate
32
+ end
33
+
34
+ #
35
+ # invalidate cached info
36
+ #
37
+ def invalidate
38
+ @path = nil
39
+ @path_from_root = nil
40
+ @depth = nil
41
+ end
42
+
43
+ def prefix_path
44
+ if not @parent.nil?
45
+ raise "Not root!!"
46
+ end
47
+ @prefix_path
48
+ end
49
+
50
+ def prefix_path=( prefix )
51
+ if not @parent.nil?
52
+ raise "Not root!!"
53
+ end
54
+ if prefix != @prefix_path
55
+ @prefix_path = prefix
56
+ invalidate
57
+ end
58
+ end
59
+
60
+ def root
61
+ if root?
62
+ self
63
+ else
64
+ parent.root
65
+ end
66
+ end
67
+
68
+ def path
69
+ return @path unless @path.nil?
70
+ if @parent.nil?
71
+ if @prefix_path
72
+ @path = @prefix_path + @name
73
+ else
74
+ @path = @name
75
+ end
76
+ else
77
+ @path = File.join( @parent.path, @name )
78
+ end
79
+ @path
80
+ end
81
+
82
+ def path_from_root
83
+ return @path_from_root unless @path_from_root.nil?
84
+ if @parent.nil?
85
+ if @prefix_path
86
+ @path_from_root = @prefix_path
87
+ else
88
+ @path_from_root = ""
89
+ end
90
+ else
91
+ @path_from_root = File.join( @parent.path_from_root, @name )
92
+ end
93
+ @path_from_root
94
+ end
95
+
96
+ def depth
97
+ return @depth unless @depth.nil?
98
+ if @parent.nil?
99
+ @depth = 1
100
+ else
101
+ @depth = @parent.depth + 1
102
+ end
103
+ @depth
104
+ end
105
+
106
+ def accept( visitor )
107
+ not_implemented
108
+ end
109
+
110
+ protected
111
+
112
+ def parent=( parent )
113
+ @parent = parent
114
+ end
115
+
116
+ end
@@ -0,0 +1,58 @@
1
+ # common
2
+ require 'tree_visitor/tree_node'
3
+ require 'tree_visitor/dir_tree_walker'
4
+ require 'tree_visitor/tree_node_visitor'
5
+
6
+ #
7
+ # costruisce una albero TreeNode a partire dalla struttura
8
+ # della directory, simile a clona
9
+ # Clona un TreeNode
10
+ #
11
+ class BuildDirTreeVisitor < TreeNodeVisitor
12
+
13
+ attr_reader :root
14
+
15
+ def initialize
16
+ super
17
+ @root = nil
18
+ @stack = []
19
+ end
20
+
21
+ def enter_treeNode( pathname )
22
+ if @stack.empty?
23
+ treeNode = TreeNode.new( File.basename( pathname ) )
24
+ @root = treeNode
25
+ else
26
+ treeNode = TreeNode.new( File.basename( pathname ), @stack.last )
27
+ end
28
+ @stack.push( treeNode )
29
+ end
30
+
31
+ def exit_treeNode( pathname )
32
+ @stack.pop
33
+ end
34
+
35
+ def visit_leafNode( pathname )
36
+ leafNode = LeafNode.new( File.basename(pathname), @stack.last )
37
+ end
38
+
39
+ end
40
+
41
+ #
42
+ # Utilizzo della classa astratta DirTreeProcessor
43
+ # per stampare i nodi di un TreeNode
44
+ #
45
+ class PrintDirTreeVisitor < TreeNodeVisitor
46
+
47
+ def enter_treeNode( pathname )
48
+ puts pathname
49
+ end
50
+
51
+ def exit_treeNode( treeNode )
52
+ end
53
+
54
+ def visit_leafNode( pathname )
55
+ puts pathname
56
+ end
57
+
58
+ end
@@ -0,0 +1,84 @@
1
+ # stdlib
2
+ require 'optparse'
3
+
4
+ # common
5
+ require 'tree_visitor/dir_tree_walker'
6
+ require 'tree_visitor/build_dir_tree_visitor'
7
+
8
+ #
9
+ #
10
+ #
11
+ class CliDirTree
12
+
13
+ def self.run
14
+ self.new.parse_args( ARGV )
15
+ end
16
+
17
+ def parse_args( argv )
18
+
19
+ options = { :verbose => true, :force => false, :algo => 'build' }
20
+
21
+ opts = OptionParser.new
22
+ opts.banner = "Usage: example.rb [options]"
23
+
24
+ opts.separator ""
25
+ opts.separator "programma per testare la classe DirProcessor"
26
+ opts.separator "Inserire il nome della directory da cui costuire il tree"
27
+
28
+ opts.separator ""
29
+ opts.separator "opzioni: "
30
+
31
+ opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
32
+ options[:verbose] = v
33
+ end
34
+
35
+ opts.on("-q", "--quiet", "quiet mode as --no-verbose") do |v|
36
+ options[:verbose] = false
37
+ end
38
+
39
+ opts.on("-h", "--help", "Show this message") do
40
+ puts opts
41
+ exit
42
+ end
43
+
44
+
45
+ algos = %w[build visit]
46
+ algo_aliases = { "b" => "build", "v" => "visit" }
47
+
48
+ algo_list = (algo_aliases.keys + algos).join(',')
49
+ opts.on("-a", "--algo ALGO", algos, algo_aliases, "Select algo"," (#{algo_list})") do |algo|
50
+ options[:algo] = algo
51
+ end
52
+
53
+ rest = opts.parse(argv)
54
+
55
+ # p options
56
+ # p ARGV
57
+
58
+ if rest.length < 1
59
+ puts opts
60
+ return 1
61
+ end
62
+
63
+ dirname = rest[0]
64
+ dirname = File.expand_path( dirname )
65
+
66
+ puts "reading : #{dirname}"
67
+
68
+ dtw = DirTreeWalker.new( dirname )
69
+ dtw.add_ignore_dir( ".svn" )
70
+ dtw.add_ignore_dir( "catalog_data" )
71
+
72
+ case options[:algo]
73
+ when 'build'
74
+ visitor = BuildDirTreeVisitor.new
75
+ dtw.run( visitor )
76
+ puts visitor.root.to_str
77
+ when 'visit'
78
+ visitor = PrintDirTreeVisitor.new
79
+ dtw.run( visitor )
80
+ end
81
+
82
+ end
83
+
84
+ end
@@ -0,0 +1,40 @@
1
+ require 'pathname'
2
+
3
+ class DirProcessor
4
+
5
+ def initialize( dirname, &action )
6
+ @dirname = dirname
7
+ @processors = {}
8
+ @default_processor = action
9
+ end
10
+
11
+ def add_processor( re, &action )
12
+ @processors[ re ] = action
13
+ end
14
+
15
+ def run()
16
+ old_dirname = Dir.pwd
17
+ Dir.chdir( @dirname )
18
+ Dir["**/*"].each { |f|
19
+ pn = Pathname.new( f ).expand_path
20
+ # puts "#{self.class.name}#loadfromdir #{f}"
21
+ next if pn.directory?
22
+ process_file( pn )
23
+ }
24
+ Dir.chdir( old_dirname )
25
+ self
26
+ end
27
+
28
+ private
29
+
30
+ def process_file( pn )
31
+ # puts "file: #{f}"
32
+ pair = @processors.find { |re,action| re =~ pn.to_s }
33
+ unless pair.nil?
34
+ pair[1].call( pn )
35
+ else
36
+ @default_processor.call( pn ) if @default_processor
37
+ end
38
+ end
39
+
40
+ end
@@ -0,0 +1,99 @@
1
+ class DirTreeWalker
2
+
3
+ def initialize( dirname )
4
+ @dirname = dirname
5
+ unless File.directory?( dirname )
6
+ raise "#{dirname} is not a directory!"
7
+ end
8
+
9
+ @visitor = nil
10
+ @ignore_dir_patterns = []
11
+ @inspect_file_patterns = []
12
+ @ignore_file_patterns = []
13
+ end
14
+
15
+ def add_ignore_dir( pattern )
16
+ @ignore_dir_patterns << pattern
17
+ end
18
+
19
+ def add_ignore_file( pattern )
20
+ @ignore_file_patterns << pattern
21
+ end
22
+
23
+ #
24
+ # quali file bisogna prendere in considerazione
25
+ # inspect opposto di ignore :-)
26
+ #
27
+ def add_inspect_file( pattern )
28
+ @inspect_file_patterns << pattern
29
+ end
30
+
31
+ def ignore_dir?( dirname )
32
+ basename = File.basename( dirname )
33
+ @ignore_dir_patterns.find{ |pattern|
34
+ basename == pattern
35
+ }
36
+ end
37
+
38
+ def ignore_file?( filename )
39
+ basename = File.basename( filename )
40
+ @ignore_file_patterns.find{ |pattern|
41
+ if pattern.kind_of? Regexp
42
+ pattern =~ basename
43
+ else
44
+ pattern == basename
45
+ end
46
+ }
47
+ end
48
+
49
+ def inspect_file?( filename )
50
+ return true if @inspect_file_patterns.empty?
51
+ basename = File.basename( filename )
52
+ @inspect_file_patterns.find{ |pattern|
53
+ if pattern.kind_of? Regexp
54
+ pattern =~ basename
55
+ else
56
+ pattern == basename
57
+ end
58
+ }
59
+ end
60
+
61
+ def run( treeNodeVisitor )
62
+ @visitor = treeNodeVisitor
63
+ process_directory( File.expand_path( @dirname ) )
64
+ end
65
+
66
+ private
67
+
68
+ #
69
+ # recurse on other directories
70
+ #
71
+ # def process_directory( parentNode, dirname )
72
+ def process_directory( dirname )
73
+ return if ignore_dir?( dirname )
74
+
75
+ @visitor.enter_treeNode( dirname )
76
+
77
+ Dir.entries( dirname ).each { |basename|
78
+ next if basename == "." or basename == ".."
79
+ pathname = File.join( dirname, basename )
80
+
81
+ if File.directory?( pathname )
82
+
83
+ # directory
84
+ if ! ignore_dir?( basename )
85
+ process_directory( pathname )
86
+ end
87
+
88
+ else
89
+
90
+ # file
91
+ if inspect_file?( basename ) && ! ignore_file?( basename )
92
+ @visitor.visit_leafNode( pathname )
93
+ end
94
+
95
+ end
96
+ }
97
+ @visitor.exit_treeNode( dirname )
98
+ end
99
+ end
@@ -0,0 +1,27 @@
1
+ # common
2
+ require "tree_visitor/abs_node"
3
+
4
+ #
5
+ # Deriva da AbsNode
6
+ #
7
+ # definisce un metodo to_str
8
+ #
9
+ #
10
+ class LeafNode < AbsNode
11
+
12
+ def initialize( name, parent = nil )
13
+ super( name )
14
+ if parent
15
+ parent.add_leaf( self )
16
+ end
17
+ end
18
+
19
+ def accept( visitor )
20
+ visitor.visit_leafNode( self )
21
+ end
22
+
23
+ def to_str
24
+ name.to_str
25
+ end
26
+
27
+ end
@@ -0,0 +1,134 @@
1
+ # common
2
+ require 'tree_visitor/leaf_node'
3
+
4
+ #
5
+ # Un treeNode e' come un AbsNode
6
+ # in piu' ha la possibilita' di contenere
7
+ # altri treeNode e LeafNode
8
+ #
9
+ # TreeNode @childs -1---n-> TreeNode
10
+ # @leaves -1---n-> LeafNode
11
+ #
12
+ class TreeNode < AbsNode
13
+
14
+ attr_reader :leaves
15
+ attr_reader :childs
16
+
17
+ def initialize( name, parent = nil )
18
+ @leaves = []
19
+ @childs = []
20
+ super( name )
21
+ if parent
22
+ parent.add_child( self )
23
+ end
24
+ end
25
+
26
+ def root?
27
+ @parent.nil?
28
+ end
29
+
30
+ #
31
+ # invalidate cached info
32
+ #
33
+ def invalidate
34
+ super
35
+ @childs.each{ |c| c.invalidate }
36
+ @leaves.each{ |l| l.invalidate }
37
+ end
38
+
39
+ def nr_nodes
40
+ nr = @leaves.length + @childs.length
41
+ @childs.inject( nr ) { |nr,c| nr + c.nr_nodes }
42
+ end
43
+
44
+ def nr_leaves
45
+ @leaves.length + @childs.inject(0) { |sum, child| sum + child.nr_leaves }
46
+ end
47
+
48
+ def nr_childs
49
+ @childs.length + @childs.inject(0) { |sum, child| sum + child.nr_childs }
50
+ end
51
+
52
+ def add_leaf( leaf )
53
+ return if leaf.parent == self
54
+ if not leaf.parent.nil?
55
+ leaf.remove_from_parent()
56
+ end
57
+ leaf.parent = self
58
+ if @leaves.length > 0
59
+ @leaves.last.next = leaf
60
+ leaf.prev = @leaves.last
61
+ leaf.next = nil
62
+ end
63
+ leaf.invalidate
64
+ @leaves << leaf
65
+ end
66
+
67
+ def add_child( treeNode )
68
+ return if treeNode.parent == self
69
+ if not treeNode.parent.nil?
70
+ treeNode.remove_from_parent()
71
+ end
72
+ treeNode.invalidate
73
+ treeNode.parent = self
74
+ @childs << treeNode
75
+ end
76
+
77
+ def find( name )
78
+ if self.name == name
79
+ return self
80
+ end
81
+
82
+ leaf = @leaves.find { |l| l.name == name }
83
+ if leaf
84
+ return leaf
85
+ end
86
+
87
+ @childs.each {|c|
88
+ node = c.find(name)
89
+ return node if node
90
+ }
91
+ nil
92
+ end
93
+
94
+ def accept( visitor )
95
+ visitor.enter_treeNode( self )
96
+ @leaves.each{ |l|
97
+ l.accept( visitor )
98
+ }
99
+ @childs.each { |tn|
100
+ tn.accept( visitor )
101
+ }
102
+ visitor.exit_treeNode( self )
103
+ end
104
+
105
+ def to_str( depth = 0 )
106
+ str = ""
107
+ (0...depth).step {
108
+ str << " |-"
109
+ }
110
+
111
+ str << @name
112
+ str << "\n"
113
+
114
+ if ! @leaves.empty?
115
+ @leaves.each{ |l|
116
+ (0...depth-1).step {
117
+ str << " |-"
118
+ }
119
+ if @childs.empty?
120
+ str << " | "
121
+ else
122
+ str << " | | "
123
+ end
124
+ str << l.to_str
125
+ str << "\n"
126
+ }
127
+ end
128
+
129
+ @childs.each { |tn|
130
+ str << tn.to_str( depth + 1 )
131
+ }
132
+ str
133
+ end
134
+ end
@@ -0,0 +1,251 @@
1
+ # rubygems
2
+ require 'rubygems'
3
+ require 'abstract'
4
+
5
+ #
6
+ # Classe astratta per visitare un TreeNode
7
+ #
8
+ class TreeNodeVisitor
9
+
10
+ def enter_treeNode( treeNode )
11
+ not_implemented
12
+ end
13
+
14
+ def exit_treeNode( treeNode )
15
+ not_implemented
16
+ end
17
+
18
+ def visit_leafNode( leafNode )
19
+ not_implemented
20
+ end
21
+
22
+ end
23
+
24
+ #
25
+ # Utilizzo della classa astratta DirTreeProcessor
26
+ # per chimare un blocco su tutti i TreeNode
27
+ #
28
+ class BlockTreeNodeVisitor
29
+
30
+ def initialize( &action )
31
+ @block = action
32
+ end
33
+
34
+ def enter_treeNode( treeNode )
35
+ @block.call( treeNode )
36
+ end
37
+
38
+ def exit_treeNode( treeNode )
39
+ end
40
+
41
+ def visit_leafNode( leafNode )
42
+ @block.call( leafNode )
43
+ end
44
+
45
+ end
46
+
47
+ #
48
+ # Utilizzo della classa astratta DirTreeProcessor
49
+ # per stampare i nodi di un TreeNode
50
+ #
51
+ class FlatPrintTreeNodeVisitor < TreeNodeVisitor
52
+
53
+ def enter_treeNode( treeNode )
54
+ puts treeNode.name
55
+ end
56
+
57
+ def exit_treeNode( treeNode )
58
+ end
59
+
60
+ def visit_leafNode( leafNode )
61
+ puts leafNode.name
62
+ end
63
+
64
+ end
65
+
66
+
67
+ class PrintTreeNodeVisitor < TreeNodeVisitor
68
+
69
+ def initialize( *args )
70
+ super( *args )
71
+ @depth = 0
72
+ end
73
+
74
+ def visit_leafNode( leafNode )
75
+ str = ""
76
+ (0...@depth-1).step {
77
+ str << " |-"
78
+ }
79
+ str << " | "
80
+ puts str + leafNode.name.to_s
81
+ end
82
+
83
+ def enter_treeNode( treeNode )
84
+
85
+ str = ""
86
+ (0...@depth).step {
87
+ str << " |-"
88
+ }
89
+
90
+ if @depth == 0
91
+ puts str + treeNode.name.to_s
92
+ else
93
+ puts str + treeNode.name.to_s
94
+ end
95
+ @depth += 1
96
+ end
97
+
98
+ def exit_treeNode( treeNode )
99
+ @depth -= 1
100
+ end
101
+ end
102
+
103
+
104
+ #
105
+ #
106
+ #
107
+ class DepthTreeNodeVisitor < TreeNodeVisitor
108
+
109
+ attr_reader :depth
110
+
111
+ def initialize
112
+ super
113
+ @depth = 0
114
+ end
115
+
116
+ def enter_treeNode( treeNode )
117
+ @depth += 1
118
+ end
119
+
120
+ def exit_treeNode( treeNode )
121
+ @depth -= 1
122
+ end
123
+
124
+ def visit_leafNode( leafNode )
125
+ end
126
+
127
+ end
128
+
129
+ #
130
+ # Esempio
131
+ # Clona un TreeNode
132
+ #
133
+ class CloneTreeNodeVisitor < TreeNodeVisitor
134
+
135
+ attr_reader :clonedRoot
136
+
137
+ def initialize
138
+ super
139
+ @clonedRoot = nil
140
+ @stack = []
141
+ end
142
+
143
+ def enter_treeNode( treeNode )
144
+ if @stack.empty?
145
+ clonedTreeNode = TreeNode.new( treeNode.name )
146
+ @clonedRoot = clonedTreeNode
147
+ else
148
+ clonedTreeNode = TreeNode.new( treeNode.name, @stack.last )
149
+ end
150
+ @stack.push( clonedTreeNode )
151
+ end
152
+
153
+ def exit_treeNode( treeNode )
154
+ @stack.pop
155
+ end
156
+
157
+ def visit_leafNode( leafNode )
158
+ clonedLeafNode = LeafNode.new( leafNode.name, @stack.last )
159
+ end
160
+
161
+ end
162
+
163
+ #
164
+ # CallbackTreeNodeVisitor
165
+ #
166
+ class CallbackTreeNodeVisitor < TreeNodeVisitor
167
+
168
+ def initialize( root = nil )
169
+ super()
170
+ @stack = []
171
+ @root = root
172
+ @stack.push( root ) if root
173
+ @action_enterTreeNode = nil
174
+ @action_visitLeafNode = nil
175
+ end
176
+
177
+ def onEnterTreeNode( &action )
178
+ @action_enterTreeNode = action
179
+ end
180
+
181
+ def onVisitLeafNode( &action )
182
+ @action_visitLeafNode = action
183
+ end
184
+
185
+ def enter_treeNode( treeNode )
186
+ parentNode = if @stack.empty?
187
+ nil
188
+ else
189
+ @stack.last
190
+ end
191
+ @root = treeNode if @stack.empty?
192
+ @stack.push( treeNode )
193
+ @action_enterTreeNode.call( treeNode ) if @action_enterTreeNode
194
+ end
195
+
196
+ def exit_treeNode( treeNode )
197
+ @stack.pop
198
+ end
199
+
200
+ def visit_leafNode( leafNode )
201
+ parentNode = @stack.last
202
+ @action_visitLeafNode.call( leafNode ) if @action_visitLeafNode
203
+ end
204
+
205
+ end
206
+
207
+
208
+ #
209
+ # CallbackTreeNodeVisitor
210
+ #
211
+ class CallbackTreeNodeVisitor2 < TreeNodeVisitor
212
+
213
+ attr_reader :root
214
+
215
+ def initialize( root = nil )
216
+ super()
217
+ @stack = []
218
+ @root = root
219
+ @stack.push( root ) if root
220
+ end
221
+
222
+ def onEnterTreeNode( &action )
223
+ @action_enterTreeNode = action
224
+ end
225
+
226
+ def onVisitLeafNode( &action )
227
+ @action_visitLeafNode = action
228
+ end
229
+
230
+ def enter_treeNode( treeNode )
231
+ newParentNode = if @stack.empty?
232
+ nil
233
+ else
234
+ @stack.last
235
+ end
236
+ newTreeNode = @action_enterTreeNode.call( treeNode, newParentNode )
237
+ @root = newTreeNode if @stack.empty?
238
+ @stack.push( newTreeNode )
239
+ end
240
+
241
+ def exit_treeNode( treeNode )
242
+ @stack.pop
243
+ end
244
+
245
+ def visit_leafNode( leafNode )
246
+ newParentNode = @stack.last
247
+ @action_visitLeafNode.call( leafNode, newParentNode )
248
+ end
249
+
250
+ end
251
+
@@ -0,0 +1,17 @@
1
+ # stdlib
2
+ require 'md5'
3
+
4
+ #
5
+ # calcola md5 di file grandi, copiata da usenet
6
+ #
7
+ class MD5
8
+ def self.file(file)
9
+ File.open(file, "rb") do |f|
10
+ res = self.new
11
+ while (data = f.read(4096))
12
+ res << data
13
+ end
14
+ res
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ class Numeric
2
+ #
3
+ # ritorna una stringa con le migliaia serparate da <separator>
4
+ # es.: 100000 -> 1.000.000
5
+ #
6
+ #
7
+ # copiata da http://wiki.rubygarden.org/Ruby/page/show/FixNumFormat
8
+ #
9
+ def with_separator( separator = ',', length = 3 )
10
+ splitter = Regexp.compile "(\\d{#{length}})"
11
+ before, after = self.to_s.split('.')
12
+ before = before.reverse.gsub splitter, '\1' + separator
13
+ str = "#{ before.chomp( separator ).reverse }"
14
+ str += ".#{ after }" if after
15
+ return str
16
+ end
17
+ end
@@ -0,0 +1,35 @@
1
+ class PrintTreeNodeVisitor2 < TreeNodeVisitor
2
+
3
+ def initialize( *args )
4
+ super( *args )
5
+ @depth = 0
6
+ end
7
+
8
+ def visit_leafNode( leafNode )
9
+ str = ""
10
+ (0...@depth-1).step {
11
+ str << " |-"
12
+ }
13
+ str << " | "
14
+ puts str + leafNode.to_s
15
+ end
16
+
17
+ def enter_treeNode( treeNode )
18
+
19
+ str = ""
20
+ (0...@depth).step {
21
+ str << " |-"
22
+ }
23
+
24
+ if @depth == 0
25
+ puts str + treeNode.to_s
26
+ else
27
+ puts str + treeNode.to_s
28
+ end
29
+ @depth += 1
30
+ end
31
+
32
+ def exit_treeNode( treeNode )
33
+ @depth -= 1
34
+ end
35
+ end
@@ -0,0 +1,3 @@
1
+ class TreeVisitor
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,16 @@
1
+ require 'test/unit'
2
+
3
+ $COMMON_HOME = File.expand_path( File.join( File.dirname( __FILE__), "..", ".." ) )
4
+ $:.unshift( File.join($COMMON_HOME, "lib" ) )
5
+ $:.unshift( File.join($COMMON_HOME, "test" ) )
6
+
7
+ $TEST_DATA = File.join( $COMMON_HOME, "test", "tree_visitor", "test_data" )
8
+
9
+ require 'tree_visitor/dir_processor'
10
+
11
+ class TCDirProcessor < Test::Unit::TestCase
12
+ def test_simple
13
+ dp = DirProcessor.new($TEST_DATA) { |f| puts f }
14
+ dp.run
15
+ end
16
+ end
@@ -0,0 +1,37 @@
1
+ # stdlib
2
+ require 'test/unit'
3
+
4
+ # common
5
+ $COMMON_HOME = File.expand_path( File.join( File.dirname( __FILE__), "..", ".." ) )
6
+ $:.unshift( File.join($COMMON_HOME, "lib" ) )
7
+ $:.unshift( File.join($COMMON_HOME, "test" ) )
8
+ $TEST_DATA = File.join( $COMMON_HOME, "test", "tree_visitor", "test_data" )
9
+
10
+ require 'tree_visitor/dir_tree_walker.rb'
11
+ require 'tree_visitor/tree_node_visitor.rb'
12
+
13
+ class TCDirTreeWalker < Test::Unit::TestCase
14
+
15
+ def test_simple
16
+ dir_tree_walker = DirTreeWalker.new( $TEST_DATA )
17
+ dir_tree_walker.add_ignore_dir( ".svn" )
18
+
19
+ accumulator = []
20
+ visitor = BlockTreeNodeVisitor.new { |pathname| accumulator << File.basename( pathname ) }
21
+ dir_tree_walker.run( visitor )
22
+ assert_equal( 7, accumulator.length )
23
+ assert_equal( %w{ test_data dir.1 dir.1.2 file.1.2.1 file.1.1 dir.2 file.2.1 }, accumulator )
24
+ end
25
+
26
+ def test_ignore_dir
27
+ dtp = DirTreeWalker.new( "." )
28
+
29
+ dtp.add_ignore_dir(".xvpics")
30
+ dtp.add_ignore_dir(".thumbnails")
31
+ dtp.add_ignore_dir("catalog_data")
32
+
33
+ assert( dtp.ignore_dir?( ".thumbnails" ) )
34
+ assert( ! dtp.ignore_dir?( "pippo" ) )
35
+ end
36
+
37
+ end
@@ -0,0 +1,135 @@
1
+ # stdlib
2
+ require 'test/unit'
3
+
4
+ # common
5
+ $COMMON_HOME = File.expand_path( File.join( File.dirname( __FILE__), "..", ".." ) )
6
+ $:.unshift( File.join($COMMON_HOME, "lib" ) )
7
+ $:.unshift( File.join($COMMON_HOME, "test" ) )
8
+
9
+ require 'tree_visitor/tree_node.rb'
10
+
11
+ class TCTreeNode < Test::Unit::TestCase
12
+
13
+ def test_simple_build
14
+ ta = TreeNode.new( "a" )
15
+ assert( ta.root? )
16
+ ln1 = LeafNode.new("1", ta)
17
+ assert_equal( ta, ln1.parent )
18
+ ln2 = LeafNode.new("2", ta)
19
+ tb = TreeNode.new( "b", ta )
20
+ ln3 = LeafNode.new( "3", tb )
21
+ assert_equal( tb, ln3.parent )
22
+
23
+ # test depth
24
+ assert_equal( 2, tb.depth )
25
+ assert_equal( 3, ln3.depth )
26
+
27
+ # test nr_nodes
28
+ assert_equal( 1, tb.nr_nodes )
29
+ assert_equal( 4, ta.nr_nodes )
30
+
31
+ # puts ta.to_str
32
+ end
33
+
34
+ def test_add_methods
35
+ ta = TreeNode.new( "a" )
36
+ assert( ta.root? )
37
+
38
+ ln1 = LeafNode.new("1")
39
+ ta.add_leaf( ln1 )
40
+ assert_equal( ta, ln1.parent )
41
+
42
+ ln2 = LeafNode.new("2", ta)
43
+ ta.add_leaf( ln2 )
44
+
45
+ tb = TreeNode.new( "b", ta )
46
+ ln3 = LeafNode.new( "3", tb )
47
+ tb.add_leaf( ln3 )
48
+ assert_equal( tb, ln3.parent )
49
+
50
+ ta.add_child( tb )
51
+ # puts ta.to_str
52
+ end
53
+
54
+ def test_next_prev
55
+ ta = TreeNode.new( "a" )
56
+
57
+ ln1 = LeafNode.new("1", ta)
58
+ assert_nil( ln1.next )
59
+ assert_nil( ln1.prev )
60
+
61
+ ln2 = LeafNode.new("2", ta)
62
+ assert_equal( ln1, ln2.prev )
63
+ assert_nil( ln2.next )
64
+
65
+ ln3 = LeafNode.new("3", ta)
66
+ assert_equal( ln3, ln2.next )
67
+ end
68
+
69
+ def test_nr_methods
70
+ ta = TreeNode.new( "a" )
71
+ ln1 = LeafNode.new("1", ta)
72
+ ln2 = LeafNode.new("2", ta)
73
+ tb = TreeNode.new( "b", ta )
74
+ ln3 = LeafNode.new( "3", tb )
75
+
76
+ assert_equal( 4, ta.nr_nodes )
77
+ assert_equal( 3, ta.nr_leaves )
78
+ assert_equal( 1, ta.nr_childs )
79
+
80
+ assert_equal( 1, tb.nr_nodes )
81
+ assert_equal( 1, tb.nr_leaves )
82
+ assert_equal( 0, tb.nr_childs )
83
+ end
84
+
85
+ def test_prefix_path
86
+ ta = TreeNode.new( "a" )
87
+ ln1 = LeafNode.new("1", ta)
88
+ ln2 = LeafNode.new("2", ta)
89
+ tb = TreeNode.new( "b", ta )
90
+ ln3 = LeafNode.new( "3", tb )
91
+
92
+ assert_equal( "a", ta.path )
93
+ assert_equal( "a/b", tb.path )
94
+
95
+ ta.prefix_path= "<root>/"
96
+
97
+ assert_equal( "<root>/a", ta.path )
98
+ assert_equal( "<root>/a/b", tb.path )
99
+ end
100
+
101
+ def test_invalidate
102
+ ta = TreeNode.new( "a" )
103
+ ln1 = LeafNode.new("1", ta)
104
+ ln2 = LeafNode.new("2", ta)
105
+ tb = TreeNode.new( "b", ta )
106
+ ln3 = LeafNode.new( "3", tb )
107
+
108
+ #@path = nil
109
+ #@path_from_root = nil
110
+ #@depth = nil
111
+
112
+
113
+ assert_equal( "a/b", tb.path )
114
+ assert_equal( "/b", tb.path_from_root )
115
+ assert_equal( 2, tb.depth )
116
+
117
+ r = TreeNode.new( "r" )
118
+ r.add_child( ta )
119
+ assert_equal( "r/a/b", tb.path )
120
+ assert_equal( "/a/b", tb.path_from_root )
121
+ assert_equal( 3, tb.depth )
122
+ end
123
+
124
+ def test_find
125
+ ta = TreeNode.new( "a" )
126
+ ln1 = LeafNode.new("1", ta)
127
+ ln2 = LeafNode.new("2", ta)
128
+ tb = TreeNode.new( "b", ta )
129
+ ln3 = LeafNode.new( "3", tb )
130
+
131
+ assert_equal(ln3, ta.find( "3"))
132
+ assert_equal(tb, ta.find( "b"))
133
+ assert_nil( ta.find("not existent"))
134
+ end
135
+ end
@@ -0,0 +1,70 @@
1
+ require 'test/unit'
2
+
3
+ $COMMON_HOME = File.expand_path( File.join( File.dirname( __FILE__), "..", ".." ) )
4
+ $:.unshift( File.join($COMMON_HOME, "lib" ) )
5
+ $:.unshift( File.join($COMMON_HOME, "test" ) )
6
+
7
+ require 'tree_visitor/tree_node.rb'
8
+ require 'tree_visitor/tree_node_visitor.rb'
9
+
10
+ class TCTreeNodeVisitor < Test::Unit::TestCase
11
+
12
+ def setup
13
+ ta = TreeNode.new( "a", nil )
14
+ LeafNode.new("1", ta )
15
+ LeafNode.new("2", ta )
16
+
17
+ tb = TreeNode.new( "b", ta )
18
+ LeafNode.new( "3", tb )
19
+
20
+ @tree = ta
21
+ end
22
+
23
+ def test_blocktreenodevisitor
24
+ accumulator = []
25
+ visitor = BlockTreeNodeVisitor.new { |node| accumulator << node.name}
26
+ @tree.accept( visitor )
27
+ assert_equal( 5, accumulator.length )
28
+ assert_equal( %w{ a 1 2 b 3 }, accumulator )
29
+ end
30
+
31
+ def test_depthtreenodevisitor
32
+ visitor = DepthTreeNodeVisitor.new
33
+ @tree.accept( visitor )
34
+ assert_equal( 0, visitor.depth )
35
+
36
+ visitor = CloneTreeNodeVisitor.new
37
+ @tree.accept( visitor )
38
+ assert_equal(@tree.nr_nodes, visitor.clonedRoot.nr_nodes )
39
+ end
40
+
41
+ def test_callback_tree_node_visitor
42
+ accumulator = []
43
+ visitor = CallbackTreeNodeVisitor.new
44
+ visitor.onEnterTreeNode{ |treeNode| accumulator << treeNode.name }
45
+ visitor.onVisitLeafNode{ |leafNode| accumulator << leafNode.name }
46
+ @tree.accept( visitor )
47
+ assert_equal( 5, accumulator.length )
48
+ assert_equal( %w{ a 1 2 b 3 }, accumulator )
49
+ end
50
+
51
+ def test_callback_tree_node_visitor2
52
+ visitor = CallbackTreeNodeVisitor2.new
53
+ visitor.onEnterTreeNode{ |treeNode, newParentNode|
54
+ TreeNode.new("n" + treeNode.name, newParentNode)
55
+ }
56
+ visitor.onVisitLeafNode{ |leafNode, newParentNode|
57
+ LeafNode.new( "n" + leafNode.name, newParentNode )
58
+ }
59
+ @tree.accept( visitor )
60
+ newRoot = visitor.root
61
+ assert_equal( "n" + @tree.name, newRoot.name)
62
+
63
+ accumulator = []
64
+ visitor = BlockTreeNodeVisitor.new { |node| accumulator << node.name}
65
+ newRoot.accept( visitor )
66
+ assert_equal( 5, accumulator.length )
67
+ assert_equal( %w{ na n1 n2 nb n3 }, accumulator )
68
+ end
69
+
70
+ end
@@ -0,0 +1,20 @@
1
+ # stdlib
2
+ require 'test/unit'
3
+
4
+ # common
5
+ $COMMON_HOME = File.expand_path( File.join( File.dirname( __FILE__), "..", "..", ".." ) )
6
+ $:.unshift( File.join($COMMON_HOME, "lib" ) )
7
+ $:.unshift( File.join($COMMON_HOME, "test" ) )
8
+ $TEST_FILE = File.join( $COMMON_HOME, "lib", "tree_visitor.rb" )
9
+
10
+
11
+ require 'tree_visitor/utility/md5.rb'
12
+
13
+ class TCMD5 < Test::Unit::TestCase
14
+
15
+ def test_simple_build
16
+ file_name = File.join( $TEST_FILE )
17
+ MD5.file( file_name )
18
+ end
19
+
20
+ end
@@ -0,0 +1,21 @@
1
+ # stdlib
2
+ require 'test/unit'
3
+
4
+ # common
5
+ $COMMON_HOME = File.expand_path( File.join( File.dirname( __FILE__), "..", "..", ".." ) )
6
+ $:.unshift( File.join($COMMON_HOME, "lib" ) )
7
+ $:.unshift( File.join($COMMON_HOME, "test" ) )
8
+ $TEST_FILE = File.join( $COMMON_HOME, "lib", "tree_visitor.rb" )
9
+
10
+
11
+ require 'tree_visitor/utility/numeric.rb'
12
+
13
+ class TCNumeric < Test::Unit::TestCase
14
+
15
+ def test_simple
16
+ assert_equal "10", 10.with_separator
17
+ assert_equal "10.0", 10.0.with_separator
18
+ assert_equal "1,000,000", 1000000.with_separator
19
+ end
20
+
21
+ end
@@ -0,0 +1,16 @@
1
+ # stdlib
2
+ require "test/unit"
3
+
4
+ # common
5
+ $COMMON_HOME = File.expand_path( File.join( File.dirname( __FILE__), "..") )
6
+ $:.unshift( File.join($COMMON_HOME, "lib" ) )
7
+ $:.unshift( File.join($COMMON_HOME, "test" ) )
8
+
9
+ require "tree_visitor"
10
+
11
+ require "tree_visitor/utility/tc_md5"
12
+
13
+ require "tree_visitor/tc_dir_processor"
14
+ require "tree_visitor/tc_dir_tree_walker"
15
+ require "tree_visitor/tc_tree_node"
16
+ require "tree_visitor/tc_tree_node_visitor"
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gf-tree_visitor
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - gf
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-05-22 00:00:00 -07:00
13
+ default_executable: dirtree.rb
14
+ dependencies: []
15
+
16
+ description:
17
+ email: giovanni.ferro@gmail.com
18
+ executables:
19
+ - dirtree.rb
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - LICENSE
24
+ - README.rdoc
25
+ files:
26
+ - lib/tree_visitor.rb
27
+ - lib/tree_visitor/abs_node.rb
28
+ - lib/tree_visitor/build_dir_tree_visitor.rb
29
+ - lib/tree_visitor/cli/cli_dir_tree.rb
30
+ - lib/tree_visitor/dir_processor.rb
31
+ - lib/tree_visitor/dir_tree_walker.rb
32
+ - lib/tree_visitor/leaf_node.rb
33
+ - lib/tree_visitor/tree_node.rb
34
+ - lib/tree_visitor/tree_node_visitor.rb
35
+ - lib/tree_visitor/utility/md5.rb
36
+ - lib/tree_visitor/utility/numeric.rb
37
+ - lib/tree_visitor/visitor/print_node_visitor2.rb
38
+ - LICENSE
39
+ - README.rdoc
40
+ has_rdoc: true
41
+ homepage: http://github.com/gf/tree_visitor
42
+ post_install_message:
43
+ rdoc_options:
44
+ - --charset=UTF-8
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ version:
59
+ requirements: []
60
+
61
+ rubyforge_project:
62
+ rubygems_version: 1.2.0
63
+ signing_key:
64
+ specification_version: 2
65
+ summary: TODO
66
+ test_files:
67
+ - test/ts_tree_visitor.rb
68
+ - test/tree_visitor/tc_dir_processor.rb
69
+ - test/tree_visitor/tc_dir_tree_walker.rb
70
+ - test/tree_visitor/tc_tree_node.rb
71
+ - test/tree_visitor/tc_tree_node_visitor.rb
72
+ - test/tree_visitor/utility/tc_md5.rb
73
+ - test/tree_visitor/utility/tc_numeric.rb