adf_builder 0.3.0 → 1.0.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.
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AdfBuilder
2
4
  class Prospect
3
5
  STATUSES = {
4
6
  new: :new,
5
7
  resend: :resend
6
- }
8
+ }.freeze
7
9
 
8
10
  def initialize(doc)
9
11
  @doc = doc
@@ -11,7 +13,6 @@ module AdfBuilder
11
13
  @prospect = @doc.adf.prospect
12
14
  @prospect[:status] = STATUSES[:new]
13
15
 
14
-
15
16
  @request_date = RequestDate.new(@prospect)
16
17
  @vehicles = Vehicles.new(@prospect)
17
18
  @customer = Customer.new(@prospect)
@@ -19,33 +20,15 @@ module AdfBuilder
19
20
  @provider = Provider.new(@prospect)
20
21
  end
21
22
 
22
- def request_date
23
- @request_date
24
- end
25
-
26
- def vehicles
27
- @vehicles
28
- end
29
-
30
- def customer
31
- @customer
32
- end
33
-
34
- def vendor
35
- @vendor
36
- end
37
-
38
- def provider
39
- @provider
40
- end
23
+ attr_reader :request_date, :vehicles, :customer, :vendor, :provider
41
24
 
42
25
  # set status to renew
43
26
  def set_renew
44
27
  @prospect[:status] = STATUSES[:resend]
45
28
  end
46
29
 
47
- def add_id(value, source=nil, sequence=1)
30
+ def add_id(value, source = nil, sequence = 1)
48
31
  Id.new.add(@prospect, value, source, sequence)
49
32
  end
50
33
  end
51
- end
34
+ end
@@ -1,15 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AdfBuilder
2
4
  class RequestDate
3
- WITH_SYMBOLS = '%FT%T%:z'
4
- WITHOUT_SYMBOLS = '%Y%m%dT%H%M%S%z'
5
+ WITH_SYMBOLS = "%FT%T%:z"
6
+ WITHOUT_SYMBOLS = "%Y%m%dT%H%M%S%z"
5
7
 
6
8
  def initialize(prospect_node)
7
- @request_date_node = Ox::Element.new('requestdate')
8
- @request_date_node << DateTime.now.strftime('%FT%T%:z')
9
+ @request_date_node = Ox::Element.new("requestdate")
10
+ @request_date_node << DateTime.now.strftime("%FT%T%:z")
9
11
  prospect_node << @request_date_node
10
12
  end
11
13
 
12
- def update_val(datetime_value, format=1)
14
+ def update_val(datetime_value, format = 1)
13
15
  if format == 1
14
16
  @request_date_node.replace_text(datetime_value.strftime(WITH_SYMBOLS))
15
17
  elsif format == 2
@@ -17,4 +19,4 @@ module AdfBuilder
17
19
  end
18
20
  end
19
21
  end
20
- end
22
+ end
@@ -1,25 +1,22 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AdfBuilder
2
4
  class Customer
3
5
  def initialize(prospect)
4
- @customer = Ox::Element.new('customer')
6
+ @customer = Ox::Element.new("customer")
5
7
  @contact = nil
6
8
  @timeframe = nil
7
9
 
8
10
  prospect << @customer
9
11
  end
10
12
 
11
- def contact
12
- @contact
13
- end
13
+ attr_reader :contact, :timeframe
14
14
 
15
- def timeframe
16
- @timeframe
17
- end
18
- def add(name, opts={})
15
+ def add(name, opts = {})
19
16
  @contact = Contact.new(@customer, name, opts)
20
17
  end
21
18
 
22
- def add_id(index, value, source=nil, sequence=1)
19
+ def add_id(index, value, source = nil, sequence = 1)
23
20
  if @prospect.locate("customer").empty?
24
21
  false
25
22
  else
@@ -34,25 +31,20 @@ module AdfBuilder
34
31
  # @param latest_date [DateTime] - Latest date customer is interested in. If timeframe tag
35
32
  # is present, it is required to specify earliestdate and/or
36
33
  # latestdate
37
- def add_timeframe(description, earliest_date=nil, latest_date=nil)
38
- if earliest_date.nil? and latest_date.nil?
39
- return false
40
- end
34
+ def add_timeframe(description, earliest_date = nil, latest_date = nil)
35
+ return false if earliest_date.nil? && latest_date.nil?
41
36
 
42
- if earliest_date and earliest_date.class != DateTime
43
- return false
44
- end
37
+ return false if earliest_date && (earliest_date.class != DateTime)
45
38
 
46
- if latest_date and latest_date.class != DateTime
47
- return false
48
- end
39
+ return false if latest_date && (latest_date.class != DateTime)
49
40
 
50
41
  @timeframe = Timeframe.new(@customer, description, earliest_date, latest_date) if @timeframe.nil?
51
42
  end
52
43
 
53
44
  def update_comments(comments)
54
45
  return false if comments.class != String
46
+
55
47
  AdfBuilder::Builder.update_node(@customer, :comments, comments)
56
48
  end
57
49
  end
58
- end
50
+ end
@@ -1,20 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AdfBuilder
2
4
  class Timeframe
3
5
  def initialize(customer, description, earliest_date, latest_date)
4
-
5
6
  begin
6
- earliest_date = earliest_date.strftime('%FT%T%:z') if earliest_date
7
- latest_date = latest_date.strftime('%FT%T%:z') if latest_date
8
- rescue => e
7
+ earliest_date = earliest_date.strftime("%FT%T%:z") if earliest_date
8
+ latest_date = latest_date.strftime("%FT%T%:z") if latest_date
9
+ rescue StandardError
9
10
  return nil
10
11
  end
11
12
 
12
- @timeframe = Ox::Element.new('timeframe')
13
-
13
+ @timeframe = Ox::Element.new("timeframe")
14
14
 
15
- @timeframe << (Ox::Element.new('description') << description)
16
- @timeframe << (Ox::Element.new('earliestdate') << earliest_date) if earliest_date
17
- @timeframe << (Ox::Element.new('latestdate') << latest_date) if latest_date
15
+ @timeframe << (Ox::Element.new("description") << description)
16
+ @timeframe << (Ox::Element.new("earliestdate") << earliest_date) if earliest_date
17
+ @timeframe << (Ox::Element.new("latestdate") << latest_date) if latest_date
18
18
  customer << @timeframe
19
19
  end
20
20
 
@@ -24,8 +24,8 @@ module AdfBuilder
24
24
 
25
25
  def update_earliest_date(date)
26
26
  begin
27
- date = date.strftime('%FT%T%:z')
28
- rescue
27
+ date = date.strftime("%FT%T%:z")
28
+ rescue StandardError
29
29
  return false
30
30
  end
31
31
  AdfBuilder::Builder.update_node(@timeframe, :earliestdate, date)
@@ -33,12 +33,12 @@ module AdfBuilder
33
33
 
34
34
  def update_latest_date(date)
35
35
  begin
36
- date = date.strftime('%FT%T%:z')
37
- rescue
36
+ date = date.strftime("%FT%T%:z")
37
+ rescue StandardError
38
38
  return false
39
39
  end
40
40
 
41
41
  AdfBuilder::Builder.update_node(@timeframe, :latestdate, date)
42
42
  end
43
43
  end
44
- end
44
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AdfBuilder
4
+ class DSL
5
+ def self.build(&block)
6
+ root = Nodes::Root.new
7
+ root.instance_eval(&block) if block_given?
8
+ root.validate!
9
+ Serializer.to_xml(root)
10
+ end
11
+
12
+ def self.tree(&block)
13
+ root = Nodes::Root.new
14
+ root.instance_eval(&block) if block_given?
15
+ root
16
+ end
17
+ end
18
+
19
+ def self.build(&block)
20
+ DSL.build(&block)
21
+ end
22
+
23
+ def self.tree(&block)
24
+ DSL.tree(&block)
25
+ end
26
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AdfBuilder
4
+ module Nodes
5
+ class Customer < Node
6
+ def contact(&block)
7
+ contact = Contact.new
8
+ contact.instance_eval(&block) if block_given?
9
+ add_child(contact)
10
+ end
11
+ end
12
+
13
+ class Contact < Node
14
+ def name(value, part: nil, type: nil)
15
+ name_node = Name.new(value, part: part, type: type)
16
+ add_child(name_node)
17
+ end
18
+
19
+ def email(value)
20
+ add_child(SimpleElement.new(:email, value))
21
+ end
22
+
23
+ def phone(value, type: nil)
24
+ phone_node = Phone.new(value, type: type)
25
+ add_child(phone_node)
26
+ end
27
+ end
28
+
29
+ class Name < Node
30
+ def initialize(value, part: nil, type: nil)
31
+ super()
32
+ @value = value
33
+ @attributes[:part] = part if part
34
+ @attributes[:type] = type if type
35
+ end
36
+ attr_reader :value
37
+ end
38
+
39
+ class Phone < Node
40
+ def initialize(value, type: nil)
41
+ super()
42
+ @value = value
43
+ @attributes[:type] = type if type
44
+ end
45
+ attr_reader :value
46
+ end
47
+
48
+ # Simple Helper for tags like <email>foo</email>
49
+ class SimpleElement < Node
50
+ def initialize(tag_name, value)
51
+ super()
52
+ @tag_name = tag_name
53
+ @value = value
54
+ end
55
+ attr_reader :value, :tag_name
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AdfBuilder
4
+ module Nodes
5
+ class Node
6
+ include AdfBuilder::Validations
7
+
8
+ attr_reader :children, :attributes
9
+
10
+ def initialize
11
+ @children = []
12
+ @attributes = {}
13
+ end
14
+
15
+ def add_child(node)
16
+ @children << node
17
+ end
18
+
19
+ def to_xml
20
+ Serializer.to_xml(self)
21
+ end
22
+
23
+ def method_missing(method_name, *args, &block)
24
+ # Support for dynamic/custom tags
25
+ # usage: custom_tag "value", attr: "val"
26
+ # usage: custom_tag { ... }
27
+
28
+ tag_name = method_name
29
+ attributes = args.last.is_a?(Hash) ? args.last : {}
30
+ value = args.first unless args.first == attributes
31
+
32
+ # If it's a block, it's a structural node
33
+ if block_given?
34
+ node = GenericNode.new(tag_name, attributes)
35
+ node.instance_eval(&block)
36
+ add_child(node)
37
+ # If it has a value, it's a leaf node/element
38
+ elsif value
39
+ node = GenericNode.new(tag_name, attributes, value)
40
+ add_child(node)
41
+ else
42
+ # Just a tag with attributes? e.g. <flag active="true"/>
43
+ node = GenericNode.new(tag_name, attributes)
44
+ add_child(node)
45
+ end
46
+ end
47
+
48
+ def respond_to_missing?(method_name, include_private = false)
49
+ true
50
+ end
51
+ end
52
+
53
+ class GenericNode < Node
54
+ def initialize(tag_name, attributes = {}, value = nil)
55
+ super()
56
+ @tag_name = tag_name
57
+ @attributes = attributes
58
+ @value = value
59
+ end
60
+ attr_reader :tag_name, :value
61
+ end
62
+
63
+ class Root < Node
64
+ # The root context of the builder
65
+ def prospect(&block)
66
+ prospect = Prospect.new
67
+ prospect.instance_eval(&block) if block_given?
68
+ add_child(prospect)
69
+ end
70
+
71
+ def first_prospect
72
+ @children.find { |c| c.is_a?(Prospect) }
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AdfBuilder
4
+ module Nodes
5
+ class Prospect < Node
6
+ def request_date(date)
7
+ @attributes[:requestdate] = date
8
+ end
9
+
10
+ def vehicle(&block)
11
+ vehicle = Vehicle.new
12
+ vehicle.instance_eval(&block) if block_given?
13
+ add_child(vehicle)
14
+ end
15
+
16
+ def customer(&block)
17
+ customer = Customer.new
18
+ customer.instance_eval(&block) if block_given?
19
+ add_child(customer)
20
+ end
21
+
22
+ # Helpers for Editing
23
+ def vehicles
24
+ @children.select { |c| c.is_a?(Vehicle) }
25
+ end
26
+
27
+ def customers
28
+ @children.select { |c| c.is_a?(Customer) }
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AdfBuilder
4
+ module Nodes
5
+ class Vehicle < Node
6
+ validates_inclusion_of :status, in: %i[new used]
7
+
8
+ def year(value)
9
+ @attributes[:year] = value
10
+ end
11
+
12
+ def make(value)
13
+ @attributes[:make] = value
14
+ end
15
+
16
+ def model(value)
17
+ @attributes[:model] = value
18
+ end
19
+
20
+ def status(value)
21
+ @attributes[:status] = value
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,8 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AdfBuilder
2
4
  class Provider
3
-
4
-
5
- FREE_TEXT_OPTIONAL_TAGS = [:service, :url]
5
+ FREE_TEXT_OPTIONAL_TAGS = %i[service url].freeze
6
6
 
7
7
  def initialize(prospect)
8
8
  @prospect = prospect
@@ -10,41 +10,39 @@ module AdfBuilder
10
10
  @contact = nil
11
11
  end
12
12
 
13
- def contact
14
- @contact
15
- end
16
-
13
+ attr_reader :contact
17
14
 
18
- def add(name, params={})
19
- @provider = Ox::Element.new('provider')
20
- params.merge!({valid_values: AdfBuilder::Contact::VALID_VALUES, valid_parameters: AdfBuilder::Contact::VALID_PARAMETERS})
21
- AdfBuilder::Builder.update_node(@provider, :name, name, params)
15
+ def add(name, params = {})
16
+ @provider = Ox::Element.new("provider")
17
+ params.merge!({ valid_values: AdfBuilder::Contact::VALID_VALUES,
18
+ valid_parameters: AdfBuilder::Contact::VALID_PARAMETERS })
19
+ AdfBuilder::Builder.update_node(@provider, :name, name, params)
22
20
  @prospect << @provider
23
21
  end
24
22
 
25
- def add_contact(name, opts={})
23
+ def add_contact(name, opts = {})
26
24
  @contact = Contact.new(@provider, name, opts)
27
25
  end
28
26
 
29
- def add_phone(phone, params={})
30
- params.merge!({valid_values: AdfBuilder::Contact::VALID_VALUES, valid_parameters: AdfBuilder::Contact::VALID_PARAMETERS})
31
- AdfBuilder::Builder.update_node(@provider, :phone, phone, params)
27
+ def add_phone(phone, params = {})
28
+ params.merge!({ valid_values: AdfBuilder::Contact::VALID_VALUES,
29
+ valid_parameters: AdfBuilder::Contact::VALID_PARAMETERS })
30
+ AdfBuilder::Builder.update_node(@provider, :phone, phone, params)
32
31
  end
33
32
 
34
- def add_email(email, params={})
35
- params.merge!({valid_values: AdfBuilder::Contact::VALID_VALUES, valid_parameters: AdfBuilder::Contact::VALID_PARAMETERS})
36
- AdfBuilder::Builder.update_node(@provider, :email, email, params)
33
+ def add_email(email, params = {})
34
+ params.merge!({ valid_values: AdfBuilder::Contact::VALID_VALUES,
35
+ valid_parameters: AdfBuilder::Contact::VALID_PARAMETERS })
36
+ AdfBuilder::Builder.update_node(@provider, :email, email, params)
37
37
  end
38
38
 
39
39
  def update_tags_with_free_text(tags)
40
40
  tags.each do |key, value|
41
- if FREE_TEXT_OPTIONAL_TAGS.include? key.to_sym
42
- AdfBuilder::Builder.update_node(@provider, key, value)
43
- end
41
+ AdfBuilder::Builder.update_node(@provider, key, value) if FREE_TEXT_OPTIONAL_TAGS.include? key.to_sym
44
42
  end
45
43
  end
46
44
 
47
- def add_id(index, value, source=nil, sequence=1)
45
+ def add_id(index, value, source = nil, sequence = 1)
48
46
  if @prospect.locate("provider").empty?
49
47
  false
50
48
  else
@@ -52,4 +50,4 @@ module AdfBuilder
52
50
  end
53
51
  end
54
52
  end
55
- end
53
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ox"
4
+
5
+ module AdfBuilder
6
+ class Serializer
7
+ def self.to_xml(node)
8
+ new(node).to_xml
9
+ end
10
+
11
+ def initialize(root_node)
12
+ @root_node = root_node
13
+ end
14
+
15
+ def to_xml
16
+ doc = Ox::Document.new
17
+
18
+ # XML Instruction
19
+ instruct = Ox::Instruct.new(:xml)
20
+ instruct[:version] = "1.0"
21
+ doc << instruct
22
+
23
+ # ADF Instruction
24
+ adf_instruct = Ox::Instruct.new("ADF")
25
+ adf_instruct[:version] = "1.0"
26
+ doc << adf_instruct
27
+
28
+ # ADF Root Element
29
+ adf = Ox::Element.new("adf")
30
+ doc << adf
31
+
32
+ @root_node.children.each do |child|
33
+ serialize_node(child, adf)
34
+ end
35
+
36
+ Ox.dump(doc)
37
+ end
38
+
39
+ private
40
+
41
+ def serialize_node(node, parent_element)
42
+ # Determine element name using tag_name to avoid conflict with DSL methods like 'name'
43
+ # Safest check: Does it have the instance variable set?
44
+ element_name = if node.instance_variable_defined?(:@tag_name)
45
+ node.instance_variable_get(:@tag_name).to_s
46
+ else
47
+ node.class.name.split("::").last.downcase
48
+ end
49
+
50
+ # puts "DEBUG: Serializing #{node.class} as <#{element_name}>"
51
+
52
+ element = Ox::Element.new(element_name)
53
+
54
+ # Add attributes (XML attributes) or Simple Child Elements
55
+ node.attributes.each do |key, value|
56
+ if attribute?(key)
57
+ element[key] = value.to_s
58
+ else
59
+ # It's a simple child element
60
+ child_el = Ox::Element.new(key.to_s)
61
+ child_el << value.to_s
62
+ element << child_el
63
+ end
64
+ end
65
+
66
+ # Add Node-level Text Content (e.g. <name>John</name>)
67
+ element << node.value.to_s if node.respond_to?(:value) && node.value
68
+
69
+ # Recursively add children nodes
70
+ node.children.each do |child|
71
+ serialize_node(child, element)
72
+ end
73
+
74
+ parent_element << element
75
+ end
76
+
77
+ def attribute?(key)
78
+ %i[part type status sequence source id valid preferredcontact time].include?(key)
79
+ end
80
+ end
81
+ end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AdfBuilder
2
4
  class Contact
3
5
  VALID_PARAMETERS = {
4
- name: [:part, :type, :primarycontact],
6
+ name: %i[part type primarycontact],
5
7
  email: [:preferredcontact],
6
- phone: [:type, :time, :preferredcontact]
7
- }
8
+ phone: %i[type time preferredcontact]
9
+ }.freeze
8
10
 
9
11
  VALID_VALUES = {
10
12
  name: {
@@ -13,30 +15,30 @@ module AdfBuilder
13
15
  primarycontact: %w[0 1]
14
16
  },
15
17
  email: {
16
- preferredcontact: %w[0 1],
18
+ preferredcontact: %w[0 1]
17
19
  },
18
20
  phone: {
19
21
  preferredcontact: %w[0 1],
20
22
  type: %w[phone fax cellphone pager],
21
23
  time: %w[morning afternoon evening nopreference day]
22
24
  }
23
- }
25
+ }.freeze
24
26
 
25
- def initialize(parent_node, name, params={})
26
- @contact = Ox::Element.new('contact')
27
- params.merge!({valid_values: VALID_VALUES, valid_parameters: VALID_PARAMETERS})
28
- AdfBuilder::Builder.update_node(@contact, :name, name, params)
27
+ def initialize(parent_node, name, params = {})
28
+ @contact = Ox::Element.new("contact")
29
+ params.merge!({ valid_values: VALID_VALUES, valid_parameters: VALID_PARAMETERS })
30
+ AdfBuilder::Builder.update_node(@contact, :name, name, params)
29
31
  parent_node << @contact
30
32
  end
31
33
 
32
- def add_phone(phone, params={})
33
- params.merge!({valid_values: VALID_VALUES, valid_parameters: VALID_PARAMETERS})
34
- AdfBuilder::Builder.update_node(@contact, :phone, phone, params)
34
+ def add_phone(phone, params = {})
35
+ params.merge!({ valid_values: VALID_VALUES, valid_parameters: VALID_PARAMETERS })
36
+ AdfBuilder::Builder.update_node(@contact, :phone, phone, params)
35
37
  end
36
38
 
37
- def add_email(email, params={})
38
- params.merge!({valid_values: VALID_VALUES, valid_parameters: VALID_PARAMETERS})
39
- AdfBuilder::Builder.update_node(@contact, :email, email, params)
39
+ def add_email(email, params = {})
40
+ params.merge!({ valid_values: VALID_VALUES, valid_parameters: VALID_PARAMETERS })
41
+ AdfBuilder::Builder.update_node(@contact, :email, email, params)
40
42
  end
41
43
  end
42
- end
44
+ end
@@ -1,20 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AdfBuilder
2
4
  class Id
3
- def initialize
4
-
5
- end
5
+ def initialize; end
6
6
 
7
7
  # add id tag to the form
8
- def add(parent_node, value, source=nil, sequence=1)
9
- id_node = Ox::Element.new('id')
8
+ def add(parent_node, value, source = nil, sequence = 1)
9
+ id_node = Ox::Element.new("id")
10
10
  id_node << value
11
11
  id_node[:sequence] = sequence
12
12
 
13
- if source
14
- id_node[:source] = source
15
- end
13
+ id_node[:source] = source if source
16
14
 
17
15
  parent_node.prepend_child(id_node)
18
16
  end
19
17
  end
20
- end
18
+ end