rpi_marca 0.0.1

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.
@@ -0,0 +1,26 @@
1
+ module RpiMarca
2
+ class Ncl
3
+ attr_reader :number, :edition, :goods_services
4
+
5
+ def initialize(number:, edition:, goods_services:)
6
+ fail ParseError, "NCL class #{number} out of range (1-45)" unless
7
+ (1..45).include?(number.to_i)
8
+
9
+ @number = number
10
+ @edition = edition if edition > 0
11
+ @goods_services = goods_services
12
+ end
13
+
14
+ def self.parse(el)
15
+ return unless el
16
+
17
+ new(
18
+ number: Helpers.get_attribute_value(el, 'codigo'),
19
+ edition: Helpers.get_attribute_value(el, 'edicao').to_i,
20
+ goods_services: Helpers.get_element_value(
21
+ el.at_xpath('.//especificacao')
22
+ )
23
+ )
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,21 @@
1
+ module RpiMarca
2
+ class Owner
3
+ attr_reader :name, :country, :state
4
+
5
+ def initialize(name:, country:, state:)
6
+ @name = name
7
+ @country = country
8
+ @state = state
9
+ end
10
+
11
+ def self.parse(el)
12
+ return unless el
13
+
14
+ new(
15
+ name: Helpers.get_attribute_value(el, 'nome-razao-social'),
16
+ country: Helpers.get_attribute_value(el, 'pais'),
17
+ state: Helpers.get_attribute_value(el, 'uf')
18
+ )
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ module RpiMarca
2
+ class PreviousApplication
3
+ attr_reader :application, :trademark
4
+
5
+ def initialize(application:, trademark:)
6
+ @application = application
7
+ @trademark = trademark
8
+ end
9
+
10
+ def self.parse(el)
11
+ return unless el
12
+
13
+ new(
14
+ application: Helpers.get_attribute_value(el, 'processo'),
15
+ trademark: Helpers.get_attribute_value(el, 'marca')
16
+ )
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,24 @@
1
+ module RpiMarca
2
+ class Priority
3
+ attr_reader :number, :date, :country
4
+
5
+ def initialize(number:, date:, country:)
6
+ fail ParseError,
7
+ 'Priority must have priority date' unless date
8
+
9
+ @number = number
10
+ @date = date
11
+ @country = country
12
+ end
13
+
14
+ def self.parse(el)
15
+ return unless el
16
+
17
+ new(
18
+ number: Helpers.get_attribute_value(el, 'numero'),
19
+ date: Helpers.parse_date(Helpers.get_attribute_value(el, 'data')),
20
+ country: Helpers.get_attribute_value(el, 'pais')
21
+ )
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,136 @@
1
+ require 'rpi_marca/helpers'
2
+ require 'rpi_marca/owner'
3
+ require 'rpi_marca/receipt'
4
+ require 'rpi_marca/rule'
5
+ require 'rpi_marca/ncl'
6
+ require 'rpi_marca/national_class'
7
+ require 'rpi_marca/vienna_class'
8
+ require 'rpi_marca/priority'
9
+ require 'rpi_marca/previous_application'
10
+ require 'nokogiri'
11
+
12
+ module RpiMarca
13
+ class Publication
14
+ attr_reader :application
15
+ attr_reader :rules
16
+ attr_reader :filed_on
17
+ attr_reader :granted_on
18
+ attr_reader :expires_on
19
+ attr_reader :ncl
20
+ attr_reader :national_class
21
+ attr_reader :vienna_class
22
+ attr_reader :owners
23
+ attr_reader :trademark
24
+ attr_reader :kind
25
+ attr_reader :nature
26
+ attr_reader :agent
27
+ attr_reader :disclaimer
28
+ attr_reader :previous_applications
29
+ attr_reader :priorities
30
+
31
+ NATURE_NORMALIZATION = {
32
+ 'Certific.' => 'Certificação'
33
+ }
34
+
35
+ def initialize(publication)
36
+ @rules = []
37
+ @owners = []
38
+ @previous_applications = []
39
+ @priorities = []
40
+
41
+ element = validate_and_parse_publication(publication)
42
+ parse_element_children(element)
43
+ end
44
+
45
+ protected
46
+
47
+ def validate_and_parse_publication(element)
48
+ element =
49
+ if element.is_a? Nokogiri::XML::Element
50
+ element
51
+ elsif element.is_a? String
52
+ Nokogiri::XML(element).at_xpath('//processo')
53
+ else
54
+ fail ParseError, "Input couldn't be recognized as a publication"
55
+ end
56
+
57
+ fail ParseError if element.name != 'processo'
58
+
59
+ element
60
+ end
61
+
62
+ def parse_element_children(publication)
63
+ parse_element_processo(publication)
64
+
65
+ publication.elements.each do |el|
66
+ normalized_element_name = el.name.gsub('-', '_')
67
+ parse_method = "parse_element_#{normalized_element_name}".to_sym
68
+
69
+ fail ParseError unless respond_to?(parse_method, true)
70
+
71
+ __send__(parse_method, el)
72
+ end
73
+ end
74
+
75
+ def parse_element_processo(el)
76
+ @application =
77
+ Helpers.get_attribute_value(el, 'numero') or fail ParseError
78
+ @filed_on =
79
+ Helpers.parse_date(Helpers.get_attribute_value(el, 'data-deposito'))
80
+ @granted_on =
81
+ Helpers.parse_date(Helpers.get_attribute_value(el, 'data-concessao'))
82
+ @expires_on =
83
+ Helpers.parse_date(Helpers.get_attribute_value(el, 'data-vigencia'))
84
+
85
+ fail ParseError if @granted_on && @expires_on.nil?
86
+ fail ParseError if @expires_on && @granted_on.nil?
87
+ end
88
+
89
+ def parse_element_despachos(el)
90
+ el = el.elements
91
+ fail ParseError if el.empty?
92
+
93
+ @rules = el.map { |rule| Rule.parse(rule) }
94
+ end
95
+
96
+ def parse_element_procurador(el)
97
+ @agent = Helpers.get_element_value(el)
98
+ end
99
+
100
+ def parse_element_titulares(el)
101
+ @owners = el.elements.map { |owner| Owner.parse(owner) }
102
+ end
103
+
104
+ def parse_element_sobrestadores(el)
105
+ @previous_applications =
106
+ el.elements.map { |application| PreviousApplication.parse(application) }
107
+ end
108
+
109
+ def parse_element_marca(el)
110
+ @trademark = Helpers.get_element_value(el.at_xpath('.//nome'))
111
+ @kind = Helpers.get_attribute_value(el, 'apresentacao')
112
+ nature = Helpers.get_attribute_value(el, 'natureza')
113
+ @nature = NATURE_NORMALIZATION.fetch(nature, nature)
114
+ end
115
+
116
+ def parse_element_classe_nice(el)
117
+ @ncl = Ncl.parse(el)
118
+ end
119
+
120
+ def parse_element_classe_nacional(el)
121
+ @national_class = NationalClass.parse(el)
122
+ end
123
+
124
+ def parse_element_classes_vienna(el)
125
+ @vienna_class = ViennaClass.parse(el)
126
+ end
127
+
128
+ def parse_element_prioridade_unionista(el)
129
+ @priorities = el.elements.map { |prio| Priority.parse(prio) }
130
+ end
131
+
132
+ def parse_element_apostila(el)
133
+ @disclaimer = Helpers.get_element_value(el)
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,56 @@
1
+ module RpiMarca
2
+ class Receipt
3
+ attr_reader :number, :date, :service_code, :agent,
4
+ :applicant, :assignor, :assignee
5
+
6
+ IPAS_RECEIPT_NOT_REQUIRED = %w(
7
+ IPAS005 IPAS009 IPAS024 IPAS033 IPAS029 IPAS047 IPAS091 IPAS106 IPAS112
8
+ IPAS135 IPAS136 IPAS139 IPAS142 IPAS157 IPAS158 IPAS161 IPAS289 IPAS291
9
+ IPAS304 IPAS395 IPAS402 IPAS404 IPAS409 IPAS421 IPAS423
10
+ )
11
+
12
+ def initialize(number:, date:, service_code: nil, agent: nil,
13
+ applicant: nil, assignor: nil, assignee: nil)
14
+ @number = number
15
+ @date = date
16
+ @service_code = format_service_code(service_code)
17
+ @agent = agent
18
+ @applicant = applicant
19
+ @assignor = assignor
20
+ @assignee = assignee
21
+ end
22
+
23
+ def self.parse(el, rule_code)
24
+ return if el.nil? && IPAS_RECEIPT_NOT_REQUIRED.include?(rule_code)
25
+
26
+ number = Helpers.get_attribute_value(el, 'numero') or
27
+ fail ParseError, 'Receipt number is required'
28
+ date = Helpers.get_attribute_value(el, 'data') or
29
+ fail ParseError, 'Receipt date is required'
30
+
31
+ new(
32
+ number: number,
33
+ date: Helpers.parse_date(date),
34
+ **optional_params(el)
35
+ )
36
+ end
37
+
38
+ def self.optional_params(el)
39
+ {
40
+ service_code: Helpers.get_attribute_value(el, 'codigoServico'),
41
+ agent: Helpers.get_element_value(el.at_xpath('procurador')),
42
+ applicant: Owner.parse(el.at_xpath('requerente')),
43
+ assignor: Owner.parse(el.at_xpath('cedente')),
44
+ assignee: Owner.parse(el.at_xpath('cessionario'))
45
+ }
46
+ end
47
+
48
+ private_class_method :optional_params
49
+
50
+ private
51
+
52
+ def format_service_code(code)
53
+ "#{code[0...3]}.#{code[3..-1]}".chomp('.') if code
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,50 @@
1
+ module RpiMarca
2
+ class Rule
3
+ attr_reader :ipas, :description, :receipt, :complement,
4
+ :complementary_receipts
5
+
6
+ # 850130127025 de 02/07/2013, 850130131596 de 08/07/2013
7
+ COMPLEMENTARY_RECEIPTS = %r{
8
+ (?<receipt>[0-9]{12,}) # 850130127025
9
+ \s # space
10
+ de
11
+ \s
12
+ (?<data>[0-9]{2}/[0-9]{2}/[0-9]{4}) # 02/07/2013
13
+ }x
14
+
15
+ def initialize(ipas:, description:, complement:, receipt:)
16
+ @ipas = ipas or fail ParseError
17
+ @description = description or fail ParseError
18
+ @complement = complement
19
+ @receipt = receipt
20
+ @complementary_receipts = []
21
+
22
+ parse_complementary_text if @complement
23
+ end
24
+
25
+ def self.parse(el)
26
+ ipas = Helpers.get_attribute_value(el, 'codigo')
27
+
28
+ new(
29
+ ipas: ipas,
30
+ description: Helpers.get_attribute_value(el, 'nome'),
31
+ receipt: Receipt.parse(el.at_xpath('protocolo'), ipas),
32
+ complement: Helpers.get_element_value(
33
+ el.at_xpath('texto-complementar')
34
+ )
35
+ )
36
+ end
37
+
38
+ private
39
+
40
+ def parse_complementary_text
41
+ @complementary_receipts =
42
+ @complement.scan(COMPLEMENTARY_RECEIPTS).map do |number, date|
43
+ Receipt.new(
44
+ number: number,
45
+ date: Helpers.parse_date(date)
46
+ )
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,3 @@
1
+ module RpiMarca
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,43 @@
1
+ module RpiMarca
2
+ class ViennaClass
3
+ attr_reader :edition, :subclass1, :subclass2, :subclass3, :subclass4,
4
+ :subclass5
5
+
6
+ def initialize(edition:, subclass1:, subclass2: nil, subclass3: nil,
7
+ subclass4: nil, subclass5: nil)
8
+ @edition = edition
9
+ @subclass1 = subclass1
10
+ @subclass2 = subclass2
11
+ @subclass3 = subclass3
12
+ @subclass4 = subclass4
13
+ @subclass5 = subclass5
14
+ end
15
+
16
+ def self.parse(el)
17
+ return unless el
18
+
19
+ subclasses = parse_subclasses(el)
20
+
21
+ new(
22
+ edition: Helpers.get_attribute_value(el, 'edicao').to_i,
23
+ **subclasses
24
+ )
25
+ end
26
+
27
+ def self.parse_subclasses(el)
28
+ subclasses = el.xpath('.//classe-vienna').map { |s| s['codigo'] }
29
+ fail ParseError, "Vienna class can't have more than 5 subclasses" if
30
+ subclasses.length > 5
31
+
32
+ {
33
+ subclass1: subclasses[0],
34
+ subclass2: subclasses[1],
35
+ subclass3: subclasses[2],
36
+ subclass4: subclasses[3],
37
+ subclass5: subclasses[4]
38
+ }
39
+ end
40
+
41
+ private_class_method :parse_subclasses
42
+ end
43
+ end
data/lib/rpi_marca.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'rpi_marca/version'
2
+
3
+ module RpiMarca
4
+ # Your code goes here...
5
+ end
data/rpi_marca.gemspec ADDED
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'rpi_marca/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'rpi_marca'
8
+ spec.version = RpiMarca::VERSION
9
+ spec.authors = ['Luiz Damim']
10
+ spec.email = ['luizdamim@outlook.com']
11
+ spec.summary = 'Leitura da RPI de Marcas do INPI em formato XML.'
12
+ spec.description = <<-EOF
13
+ Faz a leitura da RPI de Marcas do INPI em formato XML, transformando em um
14
+ objeto Ruby para processamento.
15
+ EOF
16
+ spec.homepage = 'https://github.com/automatto/rpi_marca'
17
+ spec.license = 'MIT'
18
+
19
+ spec.files = `git ls-files -z`.split("\x0")
20
+ spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
21
+ spec.test_files = spec.files.grep(/^(test|spec|features)\//)
22
+ spec.require_paths = ['lib']
23
+
24
+ spec.add_development_dependency 'bundler', '~> 1.7'
25
+ spec.add_development_dependency 'rake', '~> 10.0'
26
+ spec.add_development_dependency 'rspec', '~> 3.1'
27
+ spec.add_development_dependency 'guard-rspec'
28
+ spec.add_development_dependency 'simplecov'
29
+
30
+ spec.add_dependency 'nokogiri', '~> 1.6'
31
+ end
@@ -0,0 +1,11 @@
1
+ {
2
+ "folders":
3
+ [
4
+ {
5
+ "follow_symlinks": true,
6
+ "path": ".",
7
+ "folder_exclude_patterns": [],
8
+ "file_exclude_patterns": ["*.sublime-project", "*.sublime-workspace"]
9
+ }
10
+ ]
11
+ }
@@ -0,0 +1,122 @@
1
+ require 'rpi_marca/magazine'
2
+
3
+ describe RpiMarca::Magazine do
4
+ # rubocop:disable Metrics/LineLength
5
+ RPI_2240 = <<-REVISTA
6
+ <?xml version="1.0" encoding="UTF-8" ?>
7
+ <revista numero="2240" data="10/12/2013">
8
+ <processo numero="905687116" data-deposito="18/12/2012">
9
+ <despachos>
10
+ <despacho codigo="IPAS009" nome="Publicação de pedido de registro para oposição"/>
11
+ </despachos>
12
+ <titulares>
13
+ <titular nome-razao-social="CINTIA DEL REY" pais="BR" uf="SP"/>
14
+ </titulares>
15
+ <marca apresentacao="Mista" natureza="De Produto">
16
+ <nome>Cupcakes for fun</nome>
17
+ </marca>
18
+ <classes-vienna edicao="4">
19
+ <classe-vienna codigo="8.1.17"/>
20
+ </classes-vienna>
21
+ <classe-nice codigo="30">
22
+ <especificacao>Confeitos; Bolo, preparado para consumo final, confeitado ou não;</especificacao>
23
+ </classe-nice>
24
+ </processo>
25
+ <processo numero="840233841" data-deposito="15/08/2012">
26
+ <despachos>
27
+ <despacho codigo="IPAS009" nome="Publicação de pedido de registro para oposição">
28
+ <texto-complementar>Imagem da Marca alterada.</texto-complementar>
29
+ </despacho>
30
+ </despachos>
31
+ <titulares>
32
+ <titular nome-razao-social="GRAVIA ESQUALITY INDÚSTRIA METALÚRICA LTDA" pais="BR" uf="GO"/>
33
+ </titulares>
34
+ <marca apresentacao="Mista" natureza="De Serviço">
35
+ <nome>ELITE</nome>
36
+ </marca>
37
+ <classes-vienna edicao="4">
38
+ <classe-vienna codigo="26.4.7"/>
39
+ <classe-vienna codigo="27.5.1"/>
40
+ </classes-vienna>
41
+ <classe-nice codigo="35">
42
+ <especificacao>COMÉRCIO, IMPORTAÇÃO E EXPORTAÇÃO DE PRODUTOS METALÚRGICOS; COMÉRCIO (ATRAVÉS DE QUALQUER MEIO) DE PORTAS E JANELAS DE AÇO, ALUMÍNIO.; </especificacao>
43
+ </classe-nice>
44
+ <procurador>VILAGE MARCAS &amp; PATENTES S/S LTDA</procurador>
45
+ </processo>
46
+ <processo numero="905688198" data-deposito="18/12/2012">
47
+ <despachos>
48
+ <despacho codigo="IPAS009" nome="Publicação de pedido de registro para oposição"/>
49
+ </despachos>
50
+ <titulares>
51
+ <titular nome-razao-social="CDTA - CENTRO DE DESENVOLVIMENTO DE TECNOLOGIAS AMBIENTAIS LTDA" pais="BR" uf="PR"/>
52
+ </titulares>
53
+ <marca apresentacao="Mista" natureza="De Serviço">
54
+ <nome>CDTA - TECNOLOGIA AMBIENTAL</nome>
55
+ </marca>
56
+ <classes-vienna edicao="4">
57
+ <classe-vienna codigo="5.3.14"/>
58
+ <classe-vienna codigo="15.9.18"/>
59
+ <classe-vienna codigo="27.5.1"/>
60
+ <classe-vienna codigo="27.5.8"/>
61
+ </classes-vienna>
62
+ <classe-nice codigo="42">
63
+ <especificacao>Proteção ambiental (Pesquisa no campo de - ) - [Consultoria em]; Proteção ambiental (Pesquisa no campo de - ) - [Assessoria em]; Proteção ambiental (Pesquisa no campo de - ); Assessoria, consultoria e informações sobre engenharia - [Consultoria em]; Assessoria, consultoria e informações sobre engenharia - [Assessoria em]; Projeto de engenharia de qualquer natureza - [Consultoria em]; Projeto de engenharia de qualquer natureza - [Assessoria em]; Projeto de engenharia de qualquer natureza;</especificacao>
64
+ </classe-nice>
65
+ <procurador>HÉLIO ROBERTO LINHARES DE OLIVEIRA</procurador>
66
+ </processo>
67
+ </revista>
68
+ REVISTA
69
+
70
+ RPI_INVALIDA = <<-REVISTA
71
+ <?xml version="1.0" encoding="UTF-8" ?>
72
+ <revista numero="2240" data="10/12/2013">
73
+ <processo numero="905687116" data-deposito="18/12/2012">
74
+ <despachos>
75
+ <despacho codigo="IPAS009" nome="Publicação de pedido de registro para oposição"/>
76
+ </despachos>
77
+ </processo>
78
+ <foo/>
79
+ </revista>
80
+ REVISTA
81
+ # rubocop:enable Metrics/LineLength
82
+
83
+ it 'tem numero e data de publicação' do
84
+ magazine = RpiMarca::Magazine.new(RPI_2240)
85
+
86
+ expect(magazine.number).to eq 2240
87
+ expect(magazine.date).to eq Date.new(2013, 12, 10)
88
+ end
89
+
90
+ it 'possui várias publicações' do
91
+ magazine = RpiMarca::Magazine.new(RPI_2240)
92
+
93
+ expect(magazine.count).to eq 3
94
+ end
95
+
96
+ it 'retorna objeto contendo dados da publicação' do
97
+ magazine = RpiMarca::Magazine.new(RPI_2240)
98
+ publication = magazine.first
99
+
100
+ expect(publication).to be_a RpiMarca::Publication
101
+ end
102
+
103
+ it 'retorna um Enumerator' do
104
+ magazine = RpiMarca::Magazine.new(RPI_2240)
105
+
106
+ expect(magazine.each).to be_a Enumerator
107
+ end
108
+
109
+ describe '#valid?' do
110
+ it 'XML é válido' do
111
+ magazine = RpiMarca::Magazine.new(RPI_2240)
112
+
113
+ expect(magazine).to be_valid
114
+ end
115
+
116
+ it 'erro quando XML é inválido' do
117
+ magazine = RpiMarca::Magazine.new(RPI_INVALIDA)
118
+
119
+ expect(magazine).not_to be_valid
120
+ end
121
+ end
122
+ end