cwyckoff-babel_icious 0.0.1 → 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/README.rdoc CHANGED
@@ -17,7 +17,7 @@ Add a mapper for JSON.
17
17
 
18
18
  Mappings are set up by calling passing mapping 'coordinates' to a 'config' block on the Mapper class:
19
19
 
20
- Mapper.config(:foo) do |m|
20
+ Babelicious::Mapper.config(:foo) do |m|
21
21
 
22
22
  m.direction = {:from => :xml, :to => :hash}
23
23
 
@@ -49,7 +49,7 @@ with the value of "bar" from the hash above placed in the nested <foo> tags in t
49
49
 
50
50
  When you want to translate the mappings, simply call:
51
51
 
52
- Mapper.translate(:foo, source)
52
+ Babelicious::Mapper.translate(:foo, source)
53
53
 
54
54
  passing the tag for the mapping and the actual source you want to translate from.
55
55
 
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require File.join(File.dirname(__FILE__), "lib", "babel_icious")
@@ -0,0 +1,9 @@
1
+ # http://rpheath.com/posts/341-ruby-inject-with-index
2
+ unless Array.instance_methods.include?("inject_with_index")
3
+ module Enumerable
4
+ def inject_with_index(injected)
5
+ each_with_index{ |obj, index| injected = yield(injected, obj, index) }
6
+ injected
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,36 @@
1
+ module Babelicious
2
+
3
+ class HashMap
4
+
5
+ def initialize(path_translator)
6
+ @path_translator = path_translator
7
+ end
8
+
9
+ def map_from(hash_output, source_value)
10
+ catch :no_value do
11
+ @path_translator.inject_with_index(hash_output) do |hsh, element, index|
12
+ if(hsh[element])
13
+ hsh[element]
14
+ else
15
+ hsh[element] = (index == @path_translator.last_index ? source_value : {})
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ def value_from(source)
22
+ hash = {}
23
+ @path_translator.inject_with_index(hash) do |hsh, element, index|
24
+ return hsh[element.to_sym] if (index == @path_translator.last_index)
25
+ if hsh.empty?
26
+ source[element.to_sym]
27
+ else
28
+ hsh[element.to_sym]
29
+ end
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+
@@ -0,0 +1,19 @@
1
+ module Babelicious
2
+
3
+ class MapFactory
4
+
5
+ class << self
6
+
7
+ def source(direction, opts={})
8
+ eval("Babelicious::#{direction[:from].to_s.capitalize}Map").new(PathTranslator.new(opts[:from]))
9
+ end
10
+
11
+ def target(direction, opts={})
12
+ eval("Babelicious::#{direction[:to].to_s.capitalize}Map").new(PathTranslator.new(opts[:to]))
13
+ end
14
+
15
+ end
16
+
17
+ end
18
+ end
19
+
@@ -0,0 +1,52 @@
1
+ class MapperError < Exception; end
2
+
3
+ module Babelicious
4
+
5
+ class Mapper
6
+
7
+ class << self
8
+ attr_reader :direction, :current_target_map_key
9
+
10
+ def config(key)
11
+ raise MapperError, "A mapping for the key #{key} currently exists. Are you sure you want to merge the mapping you are about to do with the existing mapping?" if mapping_already_exists?(key)
12
+
13
+ @current_target_map_key = key
14
+ yield self
15
+ end
16
+
17
+ def direction=(dir={})
18
+ current_target_mapper.direction = dir
19
+ end
20
+
21
+ def map(opts={})
22
+ current_target_mapper.register_mapping(opts)
23
+ end
24
+
25
+ def mappings
26
+ @mapped_targets ||= {}
27
+ end
28
+
29
+ def reset
30
+ @mapped_targets, @direction = nil, nil
31
+ end
32
+
33
+ def translate(key=nil, source=nil)
34
+ raise MapperError, "No target mapper exists for key #{key}" unless mappings.has_key?(key)
35
+
36
+ mappings[key].map(source)
37
+ end
38
+
39
+ private
40
+
41
+ def current_target_mapper
42
+ mappings[@current_target_map_key] ||= (mappings[@current_target_map_key] = TargetMapper.new)
43
+ end
44
+
45
+ def mapping_already_exists?(key)
46
+ mappings.keys.include?(key)
47
+ end
48
+ end
49
+
50
+ end
51
+
52
+ end
@@ -0,0 +1,35 @@
1
+ module Babelicious
2
+
3
+ class PathTranslator
4
+ attr_reader :parsed_path, :full_path
5
+ include Enumerable
6
+
7
+ def initialize(untranslated_path)
8
+ @full_path = untranslated_path
9
+ @parsed_path = translate(untranslated_path)
10
+ end
11
+
12
+ def [](index)
13
+ @parsed_path[index]
14
+ end
15
+
16
+ def each(&block)
17
+ @parsed_path.each(&block)
18
+ end
19
+
20
+ def last_index
21
+ @parsed_path.size - 1
22
+ end
23
+
24
+ def size
25
+ @parsed_path.size
26
+ end
27
+
28
+ def translate(untranslated_path)
29
+ untranslated_path.gsub(/^\//, "").split("/")
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+
@@ -0,0 +1,54 @@
1
+ class TargetMapperError < Exception; end
2
+
3
+ module Babelicious
4
+
5
+ class TargetMapper
6
+ attr_reader :mappings, :direction
7
+
8
+ def initialize
9
+ @mappings = []
10
+ end
11
+
12
+ def direction=(dir)
13
+ raise TargetMapperError, "Direction must be a hash" unless dir.is_a?(Hash)
14
+ raise TargetMapperError, "Both :from and :to keys must be set (e.g., {:from => :xml, :to => :hash}" unless (dir[:from] && dir[:to])
15
+
16
+ @direction = dir
17
+ end
18
+
19
+ def map(source)
20
+ target = initial_target
21
+ @mappings.each do |source_element, target_element|
22
+ source_value = source_element.value_from(source)
23
+ target_element.map_from(target, source_value)
24
+ end
25
+ target
26
+ end
27
+
28
+ def register_mapping(opts={})
29
+ raise TargetMapperError, "Both :from and :to keys must be set (e.g., {:from => \"foo/bar\", :to => \"bar/foo\")" unless (opts[:from] && opts[:to])
30
+
31
+ @mappings << [MapFactory.source(@direction, opts), MapFactory.target(@direction, opts)]
32
+ end
33
+
34
+ def reset
35
+ @mappings, @direction = [], nil
36
+ end
37
+
38
+
39
+ private
40
+
41
+ def initial_target
42
+ raise TargetMapperError, "please set @direction (e.g., target_mapper.direction = {:from => :xml, :to => :hash}" unless @direction
43
+
44
+ case @direction[:to]
45
+ when :xml
46
+ XML::Document.new()
47
+ when :hash
48
+ {}
49
+ end
50
+ end
51
+
52
+ end
53
+ end
54
+
@@ -0,0 +1,63 @@
1
+ require 'xml'
2
+
3
+ module Babelicious
4
+
5
+ class XmlMap
6
+
7
+ def initialize(path_translator)
8
+ @path_translator = path_translator
9
+ end
10
+
11
+ def value_from(source)
12
+ source.find("/#{@path_translator.full_path}").each do |node|
13
+ return node.content
14
+ end
15
+ end
16
+
17
+ def map_from(xml_output, source_value)
18
+ @index = @path_translator.last_index
19
+
20
+ set_root(xml_output)
21
+
22
+ unless(update_node?(xml_output, source_value))
23
+ populate_nodes(xml_output)
24
+ map_from(xml_output, source_value)
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def populate_nodes(xml_output)
31
+ return if @index == 0
32
+
33
+ if(node = previous_node(xml_output))
34
+ new_node = XML::Node.new(@path_translator[@index+1])
35
+ node << new_node
36
+ else
37
+ populate_nodes(xml_output)
38
+ end
39
+ end
40
+
41
+ def previous_node(xml_output)
42
+ @index -= 1
43
+ node = xml_output.find("//#{@path_translator[0..@index].join("/")}")
44
+ node[0]
45
+ end
46
+
47
+ def set_root(xml_output)
48
+ if xml_output.root.nil?
49
+ xml_output.root = XML::Node.new(@path_translator[0])
50
+ end
51
+ end
52
+
53
+ def update_node?(xml_output, source_value)
54
+ node = xml_output.find("/#{@path_translator.full_path}")
55
+ unless(node.empty?)
56
+ node[0] << source_value.strip
57
+ return true
58
+ end
59
+ false
60
+ end
61
+ end
62
+
63
+ end
@@ -0,0 +1,12 @@
1
+ require 'rubygems'
2
+ require 'xml'
3
+
4
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) unless $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__)))
5
+
6
+ require "babel_icious/core_ext/enumerable"
7
+ require "babel_icious/target_mapper"
8
+ require "babel_icious/map_factory"
9
+ require "babel_icious/path_translator"
10
+ require "babel_icious/xml_map"
11
+ require "babel_icious/hash_map"
12
+ require "babel_icious/mapper"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cwyckoff-babel_icious
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Wyckoff
@@ -31,8 +31,18 @@ extensions: []
31
31
  extra_rdoc_files:
32
32
  - README.rdoc
33
33
  - MIT-LICENSE
34
- files: []
35
-
34
+ files:
35
+ - init.rb
36
+ - lib/babel_icious.rb
37
+ - lib/babel_icious/hash_map.rb
38
+ - lib/babel_icious/map_factory.rb
39
+ - lib/babel_icious/xml_map.rb
40
+ - lib/babel_icious/mapper.rb
41
+ - lib/babel_icious/path_translator.rb
42
+ - lib/babel_icious/target_mapper.rb
43
+ - lib/babel_icious/core_ext/enumerable.rb
44
+ - README.rdoc
45
+ - MIT-LICENSE
36
46
  has_rdoc: true
37
47
  homepage: http://github.com/cwyckoff/babel_icious
38
48
  post_install_message: