tinkit 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/LICENSE +176 -0
  2. data/README +11 -0
  3. data/Rakefile +75 -0
  4. data/lib/glue_envs/couchrest/couchrest_attachment_handler.rb +260 -0
  5. data/lib/glue_envs/couchrest/couchrest_files_mgr.rb +198 -0
  6. data/lib/glue_envs/couchrest_glue_env.rb +536 -0
  7. data/lib/glue_envs/files_mgr_base.rb +51 -0
  8. data/lib/glue_envs/filesystem/filesystem_files_mgr.rb +187 -0
  9. data/lib/glue_envs/filesystem_glue_env.rb +395 -0
  10. data/lib/glue_envs/mysql/mysql_files_mgr.rb +175 -0
  11. data/lib/glue_envs/mysql_glue_env.rb +428 -0
  12. data/lib/glue_envs/sdb_s3/sdb_s3_files_mgr.rb +314 -0
  13. data/lib/glue_envs/sdb_s3_glue_env.rb +248 -0
  14. data/lib/helpers/camel.rb +21 -0
  15. data/lib/helpers/filesystem_helpers.rb +27 -0
  16. data/lib/helpers/hash_helpers.rb +74 -0
  17. data/lib/helpers/log_helper.rb +34 -0
  18. data/lib/helpers/mime_types_new.rb +126 -0
  19. data/lib/helpers/old_more_open_struct.rb +28 -0
  20. data/lib/helpers/require_helper.rb +45 -0
  21. data/lib/helpers/tk_escape.rb +17 -0
  22. data/lib/midas/bufs_data_structure.rb +84 -0
  23. data/lib/midas/node_element_operations.rb +264 -0
  24. data/lib/tinkit.rb +38 -0
  25. data/lib/tinkit_base_node.rb +733 -0
  26. data/lib/tinkit_node_factory.rb +47 -0
  27. data/spec/couchrest_files_mgr_spec.rb +551 -0
  28. data/spec/couchrest_glue_spec.rb +246 -0
  29. data/spec/filesystem_files_mgr_spec.rb +236 -0
  30. data/spec/filesystem_glue_spec.rb +243 -0
  31. data/spec/filesystem_helpers_spec.rb +42 -0
  32. data/spec/helpers/bufs_node_builder.rb +17 -0
  33. data/spec/helpers/bufs_sample_dataset.rb +160 -0
  34. data/spec/helpers/bufs_test_environments.rb +81 -0
  35. data/spec/helpers/tmp_view_cleaner.rb +15 -0
  36. data/spec/lib_helpers/tk_escape_spec.rb +45 -0
  37. data/spec/mysql_files_mgr_spec.rb +250 -0
  38. data/spec/mysql_glue_spec.rb +214 -0
  39. data/spec/node_element_operations_spec.rb +392 -0
  40. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec1.rb +82 -0
  41. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec2.rb +68 -0
  42. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec3.rb +80 -0
  43. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec4.rb +110 -0
  44. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec5.rb +84 -0
  45. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec6.rb +83 -0
  46. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec7.rb +101 -0
  47. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec8.rb +92 -0
  48. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec_all.rb +266 -0
  49. data/spec/sdb_s3_glue_spec.rb +230 -0
  50. data/spec/tinkit_node_factory_spec.rb +1108 -0
  51. metadata +114 -0
@@ -0,0 +1,21 @@
1
+ #copy of Rails camelize and underscore (almost)
2
+
3
+ module Camel
4
+ def self.ize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
5
+ if first_letter_in_uppercase
6
+ lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
7
+ else
8
+ lower_case_and_underscored_word.first + camelize(lower_case_and_underscored_word)[1..-1]
9
+ end
10
+ end
11
+
12
+ def self.score(camel_cased_word)
13
+ word = camel_cased_word.to_s.dup
14
+ word.gsub!(/::/, '_') #except I changed '/' to '_'
15
+ word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
16
+ word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
17
+ word.tr!("-", "_")
18
+ word.downcase!
19
+ word
20
+ end
21
+ end
@@ -0,0 +1,27 @@
1
+
2
+ class DirFilter
3
+ def initialize(ignore_list)
4
+ @ignore_list = [ignore_list].flatten
5
+ @ignore_list << /^\./ #ignore dot files
6
+ end
7
+
8
+
9
+ def filter_entries(path)
10
+ wkg_entries = Dir.entries(path)
11
+ #remove dot files
12
+ wkg_entires = wkg_entries.delete_if{|entry| in_ignore_list?(entry) }
13
+ end
14
+
15
+ private
16
+ def in_ignore_list?(entry)
17
+ in_ignore = @ignore_list.map{|list| true if entry =~ list}
18
+ in_ignore.compact.first #nil if nothing in ignore
19
+ end
20
+ end
21
+
22
+ class FileNames
23
+ def flatten_problem_chars(filenames)
24
+ #via http://stackoverflow.com/questions/2270635/invalid-chars-filter-for-file-folder-name-ruby
25
+ file_names.map! { |f| f.gsub(/[\x00\/\\:\*\?\"<>\|]/, '_') }
26
+ end
27
+ end
@@ -0,0 +1,74 @@
1
+ require 'ostruct'
2
+
3
+ #from Facets via Hashery
4
+ class Hash
5
+
6
+
7
+
8
+ def rekey!(*args, &block)
9
+ # for backward comptability (TODO: DEPRECATE).
10
+ block = args.pop.to_sym.to_proc if args.size == 1
11
+ if args.empty?
12
+ block = lambda{|k| k.to_sym} unless block
13
+ keys.each do |k|
14
+ nk = block[k]
15
+ self[nk]=delete(k) if nk
16
+ end
17
+ else
18
+ raise ArgumentError, "3 for 2" if block
19
+ to, from = *args
20
+ self[to] = self.delete(from) if self.has_key?(from)
21
+ end
22
+ self
23
+ end
24
+
25
+ def rekey(*args, &block)
26
+ dup.rekey!(*args, &block)
27
+ end
28
+
29
+ public :rekey, :rekey!
30
+ end
31
+
32
+ module HashKeys
33
+ def self.str_to_sym(a_hash)
34
+ raise "#{a_hash.class.name} must respond to inject" unless a_hash.respond_to? :inject
35
+ a_hash.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
36
+ end
37
+
38
+ def self.sym_to_str(a_hash) #inverse of above
39
+ raise "#{a_hash.class.name} must respond to inject" unless a_hash.respond_to? :inject
40
+ a_hash.inject({}){|memo,(k,v)| memo["#{k}"] = v; memo}
41
+ end
42
+ end
43
+
44
+ module HashOps
45
+ def self.remove_hash(other_hash)
46
+ delete_if { |k,v| other_hash[k] == v }
47
+ end
48
+ end
49
+
50
+ class MoreOpenStruct < OpenStruct
51
+ def _to_hash
52
+ h = @table
53
+ #handles nested structures
54
+ h.each do |k,v|
55
+ if v.class == MoreOpenStruct
56
+ h[k] = v._to_hash
57
+ end
58
+ end
59
+ return h
60
+ end
61
+
62
+ def _table
63
+ @table #table is the hash structure used in OpenStruct
64
+ end
65
+
66
+ def _manual_set(hash)
67
+ if hash && (hash.class == Hash)
68
+ for k,v in hash
69
+ @table[k.to_sym] = v
70
+ new_ostruct_member(k)
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,34 @@
1
+ require 'log4r'
2
+
3
+ #Set Logger
4
+ #TODO: Create spec
5
+ module TinkitLog
6
+ include Log4r
7
+
8
+ class << self; attr_accessor :default_level, :fatal_log, :log_output end
9
+ TinkitLog.default_level = :info
10
+ TinkitLog.log_output = 'stdout'
11
+ TinkitLog.fatal_log = Logger.new('fatal_log')
12
+ TinkitLog.fatal_log.level = FATAL
13
+ TinkitLog.fatal_log.outputters = Outputter[TinkitLog.log_output]
14
+
15
+ @@log_levels = { :debug => DEBUG,
16
+ :info => INFO,
17
+ :warn => WARN,
18
+ :error => ERROR,
19
+ :fatal => FATAL
20
+ }
21
+
22
+ def self.set(name, level=TinkitLog.default_level, out=Outputter.stdout)
23
+ log = Logger[name] || Logger.new(name)
24
+ log.outputters = out
25
+ log.level = @@log_levels[level]
26
+ log.trace = true if log.level <= DEBUG
27
+ log
28
+ end
29
+
30
+ def self.log_raise(error_msg, exc_type= RuntimeError)
31
+ self.fatal_log.fatal("#{__LINE__} #{error_msg}")
32
+ raise exc_type, error_msg
33
+ end
34
+ end
@@ -0,0 +1,126 @@
1
+ #Copyright (C) 2010 David Martin
2
+ #
3
+ #David Martin mailto:dmarti21@gmail.com
4
+
5
+
6
+ require 'mime/types'
7
+
8
+ #This class will include the Office 2007 extension types when looking up MIME types.
9
+ class MimeNew
10
+
11
+ DefaultUnknownContentType = "application/octet-stream"
12
+ #Returns the mime type of a file
13
+ # MimeNew.for_ofc_x('a_new_word_doc.docx')
14
+ # #=> "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
15
+ def self.for_ofc_x(fname)
16
+ cont_type = nil
17
+ old_ext = File.extname(fname)
18
+ cont_type =case old_ext
19
+ #New Office Formats
20
+ when '.docx'
21
+ ["application/vnd.openxmlformats-officedocument.wordprocessingml.document"]
22
+ when '.dotx'
23
+ ["application/vnd.openxmlformats-officedocument.wordprocessingml.template"]
24
+ when '.pptx'
25
+ ["application/vnd.openxmlformats-officedocument.presentationml.presentation"]
26
+ when '.ppsx'
27
+ ["application/vnd.openxmlformats-officedocument.presentationml.slideshow"]
28
+ when '.potx'
29
+ ["application/vnd.openxmlformats-officedocument.presentationml.template"]
30
+ when '.xlsx'
31
+ ["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"]
32
+ when '.xltx'
33
+ ["application/vnd.openxmlformats-officedocument.spreadsheetml.template"]
34
+ else
35
+ self.other_content_types(fname)
36
+ end#case
37
+ cont_type = [cont_type].flatten.first
38
+ #puts "Content Type returned: #{cont_type.inspect}"
39
+ return cont_type
40
+ end# def
41
+
42
+ def self.just_ofc_x(ext)
43
+ cont_type = case File.extname(fname)
44
+ #New Office Formats
45
+ when '.docx'
46
+ ["application/vnd.openxmlformats-officedocument.wordprocessingml.document"]
47
+ when '.dotx'
48
+ ["application/vnd.openxmlformats-officedocument.wordprocessingml.template"]
49
+ when '.pptx'
50
+ ["application/vnd.openxmlformats-officedocument.presentationml.presentation"]
51
+ when '.ppsx'
52
+ ["application/vnd.openxmlformats-officedocument.presentationml.slideshow"]
53
+ when '.potx'
54
+ ["application/vnd.openxmlformats-officedocument.presentationml.template"]
55
+ when '.xlsx'
56
+ ["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"]
57
+ when '.xltx'
58
+ ["application/vnd.openxmlformats-officedocument.spreadsheetml.template"]
59
+ end
60
+ end
61
+
62
+ def self.other_content_types(fname)
63
+ std_type = MIME::Types.type_for(fname).first
64
+ rtn = if std_type
65
+ std_type.content_type
66
+ else
67
+ DefaultUnknownContentType
68
+ end
69
+ return rtn
70
+ end#def
71
+ end
72
+
73
+
74
+ #duck punching RestClient's duck punch for bufs because libraries are using MIME::Types directly
75
+ =begin
76
+ module MIME
77
+ class Types
78
+
79
+ # Return the first found content-type for a value considered as an extension or the value itself
80
+ def type_for_extension ext
81
+ puts "Duck Punch ext: #{ext.inspect}"
82
+ candidates = @extension_index[ext]
83
+ puts "Duck Punch candidates: #{candidates.inspect}"
84
+ candidates.empty? ? ext : candidates[0].content_type
85
+ end
86
+ end
87
+ end
88
+ =end
89
+ =begin
90
+ class MIME::Types
91
+ def type_for(filename, platform = false)
92
+ puts "Duck Punched MIME::Types"
93
+ puts "--filename: #{filename.inspect}"
94
+
95
+ ext = filename.chomp.downcase.gsub(/.*\./o, '')
96
+ list = @extension_index[ext]
97
+ list.delete_if { |e| not e.platform? } if platform
98
+ list
99
+
100
+ new_ext = File.extname(filename)
101
+ cont_type =case new_ext
102
+ #New Office Formats
103
+ when '.docx'
104
+ ["application/vnd.openxmlformats-officedocument.wordprocessingml.document"]
105
+ when '.dotx'
106
+ ["application/vnd.openxmlformats-officedocument.wordprocessingml.template"]
107
+ when '.pptx'
108
+ ["application/vnd.openxmlformats-officedocument.presentationml.presentation"]
109
+ when '.ppsx'
110
+ ["application/vnd.openxmlformats-officedocument.presentationml.slideshow"]
111
+ when '.potx'
112
+ ["application/vnd.openxmlformats-officedocument.presentationml.template"]
113
+ when '.xlsx'
114
+ ["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"]
115
+ when '.xltx'
116
+ ["application/vnd.openxmlformats-officedocument.spreadsheetml.template"]
117
+ end
118
+
119
+ puts "Duck New Cont Type: #{cont_type.inspect}"
120
+ (list + cont_type).compact! if cont_type
121
+ puts "Duck Mime Extension: #{ext.inspect}"
122
+ puts "Duck Content Types: #{ list.map{|m| m.content_type} }"
123
+ list
124
+ end
125
+ end
126
+ =end
@@ -0,0 +1,28 @@
1
+ require 'ostruct'
2
+
3
+ class MoreOpenStruct < OpenStruct
4
+ def _to_hash
5
+ h = @table
6
+ #handles nested structures
7
+ h.each do |k,v|
8
+ if v.class == MoreOpenStruct
9
+ h[k] = v._to_hash
10
+ end
11
+ end
12
+ return h
13
+ end
14
+
15
+ def _table
16
+ @table #table is the hash structure used in OpenStruct
17
+ end
18
+
19
+ def _manual_set(hash)
20
+ if hash && (hash.class == Hash)
21
+ for k,v in hash
22
+ @table[k.to_sym] = v
23
+ new_ostruct_member(k)
24
+ end
25
+ end
26
+ end
27
+ end
28
+
@@ -0,0 +1,45 @@
1
+ #Tinkit Library Locations
2
+ module Tinkit
3
+ @@top = File.join(File.dirname(__FILE__), '../..') #main bufs directory
4
+ @@lib = File.join(@@top, 'lib/')
5
+ @@helpers = File.join(@@top, 'lib/helpers/')
6
+ @@moabs = File.join(@@lib, 'moabs')
7
+ @@midas = File.join(@@lib, 'midas')
8
+ @@glue = File.join(@@lib, 'glue_envs')
9
+ @@specs = File.join(@@top, 'spec')
10
+ @@spec_helpers = File.join(@@specs, 'helpers')
11
+ @@fixtures = File.join(@@top, 'bufs_fixtures')
12
+
13
+ def self.lib(req_file)
14
+ File.expand_path(File.join(@@lib, req_file))
15
+ end
16
+
17
+ def self.helpers(req_file)
18
+ File.expand_path(File.join(@@helpers, req_file))
19
+ end
20
+
21
+ def self.spec(req_file)
22
+ File.expand_path(File.join(@@specs, req_file))
23
+ end
24
+
25
+ def self.spec_helpers(req_file)
26
+ File.expand_path(File.join(@@spec_helpers, req_file))
27
+ end
28
+
29
+ def self.fixtures(req_file)
30
+ File.expand_path(File.join(@@fixtures, req_file))
31
+ end
32
+
33
+ def self.moabs(req_file)
34
+ File.expand_path(File.join(@@moabs, req_file))
35
+ end
36
+
37
+ def self.midas(req_file)
38
+ File.expand_path(File.join(@@midas, req_file))
39
+ end
40
+
41
+ def self.glue(req_file)
42
+ File.expand_path(File.join(@@glue, req_file))
43
+ end
44
+ end
45
+
@@ -0,0 +1,17 @@
1
+ require 'cgi' #Can replace with url_escape if performance is an issue
2
+
3
+ class TkEscape
4
+ def self.escape(str)
5
+ esc_str = str.gsub(/([^a-zA-Z0-9_.-]+)/n, '_')
6
+ #str.gsub!('+', ' ')
7
+ #str = CGI.escape(str)
8
+ #str.gsub!('%2B', '+')
9
+ return esc_str
10
+ end
11
+
12
+ #TODO: Continue using cgi or create unescape specific to Tinkit?
13
+ def self.unescape(str)
14
+ return CGI.unescape(str)
15
+ end
16
+ end
17
+
@@ -0,0 +1,84 @@
1
+ module DataStructureModels
2
+ module Tinkit
3
+ #Required Keys on instantiation
4
+ RequiredInstanceKeys = [:my_category]
5
+ RequiredSaveKeys = [:my_category] #duplicative?
6
+ NodeKey = :my_category #TODO look at supporting multiple node keys
7
+ end
8
+ end
9
+
10
+ =begin
11
+ module NodeElementOperations
12
+ #TODO the hash inside the proc is confusing (the curly braces) update to better readability
13
+ MyCategoryAddOp = lambda {|this,other| Hash[:update_this => this] } #my cat is not allowed to change
14
+ MyCategorySubtractOp = lambda{ |this, other| Hash[:update_this => this] } #TODO use this to delete a node?
15
+ MyCategoryOps = {:add => MyCategoryAddOp, :subtract => MyCategorySubtractOp}
16
+ ParentCategoryAddOp = lambda {|this,other|
17
+ this = this || []
18
+ other = other || []
19
+ this = this + [other].flatten
20
+ this.uniq!; this.compact!
21
+ Hash[:update_this => this]
22
+ }
23
+ ParentCategorySubtractOp = lambda {|this,other|
24
+ this = [this] || []
25
+ other = [other] || []
26
+ this.flatten!
27
+ other.flatten!
28
+ this -= other
29
+ this.uniq!
30
+ this.compact!
31
+ Hash[:update_this => this]
32
+ }
33
+ ParentCategoryOps = {:add => ParentCategoryAddOp, :subtract => ParentCategorySubtractOp}
34
+ LinkAddOp = lambda {|this, other|
35
+ this = this || {} #investigate why its passed as nil (probably hasn't been built yet
36
+ other = other || {}
37
+ srcs = other.keys
38
+ srcs.each {|s| if this[s]
39
+ #this[s] = [ other[s] ].flatten
40
+ this[s] = other[s]
41
+ else
42
+ #this[s] = [ other[s] ].flatten
43
+ this[s] = other[s]
44
+ end }
45
+ #this[s].uniq!
46
+ #this[s].compact! }
47
+ Hash[:update_this => this] }
48
+ #if link_name is used besides other, then all link_names would need to be unique, so we use other
49
+ LinkSubtractOp = lambda {|this, other| this = this || {}
50
+ #Hacked together needs thought out (and TESTED!!)
51
+ other = other || {}
52
+ puts "This / Other: #{this.inspect} / #{other.inspect}"
53
+ #srcs = [other].flatten
54
+ other.keys.each { |s|
55
+ #other[s].each {|olnk| this[s].delete(olnk) if this[s]}
56
+ puts "delete #{other[s].inspect} from #{this[s].inspect}"
57
+ #this[s].delete(other[s]) if this[s]
58
+ this.delete(s)
59
+ #this.delete(s) if (this[s].nil? || this[s].empty?)
60
+ }
61
+ Hash[:update_this => this]
62
+ }
63
+ #think if this is what you want, returning a single uri if only one exists, while an array if more than one?
64
+ #I think so since it's *almost* an error case if more than one url exists for a name, but I'm not sure this is the best approach
65
+ LinkGetOp = lambda {|this, link_name|
66
+ this_ary = this.to_a
67
+ rtn_val = nil
68
+ rtn_val = if this_ary.flatten.include? link_name
69
+ srcs = []
70
+ this_ary.each { |s, ls| srcs << s if ls.include? link_name }
71
+ rtn_val = {:return_value => srcs, :update_this => this } if srcs.size > 1
72
+ rtn_val = {:return_value => srcs.first, :update_this => this } if srcs.size == 1
73
+ rtn_val
74
+ else
75
+ rtn_val = {:return_value => nil, :update_this => this}
76
+ end
77
+ rtn_val
78
+ }
79
+
80
+ LinkOps = {:add => LinkAddOp, :subtract => LinkSubtractOp, :get => LinkGetOp}
81
+
82
+ Ops = {:my_category => MyCategoryOps, :parent_categories => ParentCategoryOps, :links => LinkOps}
83
+ end
84
+ =end