pdf_ravager 0.0.1-java

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,4 @@
1
+ Gemfile.lock
2
+ pkg/
3
+ *.gem
4
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source :rubygems
2
+
3
+ group :development, :test do
4
+ gem "minitest", "~> 4.1.0"
5
+ gem "rspec", "~> 2.11.0"
6
+ gem "turn", "~> 0.9.6", :require => false
7
+ gem "bundler", "~> 1.2.1"
8
+ end
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2012 Abe Voelker
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.
@@ -0,0 +1,50 @@
1
+ # PDF Ravager
2
+
3
+ Provides a simple DSL for easily filling out AcroForms PDF or XFA documents.
4
+
5
+ ## Description
6
+
7
+ This library uses a combination of a simple DSL and a minimal veneer over the
8
+ last free version of the iText library to aid in filling out AcroForms PDF or
9
+ XFA documents.
10
+
11
+ ## Synopsis
12
+
13
+ ```ruby
14
+ require 'pdf_ravager'
15
+
16
+ data = {:name => 'Bob', :gender => 'm', :relation => 'Uncle' }
17
+
18
+ info = pdf do
19
+ text 'name', data[:name]
20
+ radio_group 'sex' do
21
+ fill 'male', :if => data[:gender] == 'm'
22
+ fill 'female', :if => data[:gender] == 'f'
23
+ end
24
+ checkbox_group 'relation' do
25
+ check 'parent', :if => ['Mom', 'Dad'].include?(data[:relation])
26
+ check 'sibling', :if => ['Brother', 'Sister'].include?(data[:relation])
27
+ check 'other', :unless => ['Brother', 'Sister', 'Mom', 'Dad'].include?(data[:relation])
28
+ # OR
29
+ case data[:relation]
30
+ when 'Mom', 'Dad'
31
+ check 'parent'
32
+ when 'Brother', 'Sister'
33
+ check 'sibling'
34
+ else
35
+ check 'other'
36
+ end
37
+ end
38
+ end
39
+
40
+ info.ravage '/tmp/info.pdf', :out_file => '/tmp/info_filled.pdf'
41
+ ```
42
+
43
+ ## Usage
44
+
45
+ To find the names of the fields, use a tool such as Adobe LiveCycle.
46
+
47
+ ## Copyright
48
+
49
+ Copyright (c) 2012 Abe Voelker. Released under the terms of the
50
+ MIT license. See LICENSE for details.
@@ -0,0 +1,10 @@
1
+ require 'rspec'
2
+ require 'rake/testtask'
3
+ require 'bundler'
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.libs << ["lib", "spec"]
7
+ t.pattern = "spec/*_spec.rb"
8
+ end
9
+
10
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,3 @@
1
+ require 'pdf_ravager/version'
2
+ require 'pdf_ravager/pdf'
3
+ require 'pdf_ravager/ravager' if RUBY_PLATFORM =~ /java/
@@ -0,0 +1,97 @@
1
+ require 'json'
2
+ require 'pdf_ravager/ravager' if RUBY_PLATFORM =~ /java/
3
+
4
+ module PDFRavager
5
+ class PDF
6
+ attr_reader :name, :fields
7
+
8
+ def initialize(name=nil, opts={})
9
+ @name = name if name
10
+ @fields = opts[:fields] || []
11
+ end
12
+
13
+ def text(name, value, opts={})
14
+ return if opts.has_key?(:when) && !opts[:when]
15
+ return if opts.has_key?(:if) && !opts[:if]
16
+ return if opts.has_key?(:unless) && opts[:unless]
17
+ @fields << {:name => name, :value => value, :type => :text}
18
+ end
19
+
20
+ def radio_group(name, &blk)
21
+ fields = []
22
+ # TODO: replace w/ singleton method?
23
+ PDF.instance_eval do
24
+ send(:define_method, :fill) do |value, opts={}|
25
+ return if opts.has_key?(:when) && !opts[:when]
26
+ return if opts.has_key?(:if) && !opts[:if]
27
+ return if opts.has_key?(:unless) && opts[:unless]
28
+ fields << {:name => name, :value => value, :type => :radio}
29
+ end
30
+ blk.call
31
+ send(:undef_method, :fill)
32
+ end
33
+
34
+ @fields += fields
35
+ end
36
+
37
+ def checkbox_group(name, &blk)
38
+ fields = []
39
+ # TODO: replace w/ singleton method?
40
+ PDF.instance_eval do
41
+ send(:define_method, :check) do |value, opts={}|
42
+ return if opts.has_key?(:when) && !opts[:when]
43
+ return if opts.has_key?(:if) && !opts[:if]
44
+ return if opts.has_key?(:unless) && opts[:unless]
45
+ fields << {:name => name, :value => value, :type => :checkbox}
46
+ end
47
+ blk.call
48
+ send(:undef_method, :check)
49
+ end
50
+
51
+ @fields += fields
52
+ end
53
+
54
+ if RUBY_PLATFORM =~ /java/
55
+ def ravage(file, opts={})
56
+ PDFRavager::Ravager.open(opts.merge(:in_file => file)) do |pdf|
57
+ @fields.each do |f|
58
+ pdf.set_field_value(f[:name], f[:value])
59
+ end
60
+ end
61
+ end
62
+ else
63
+ def ravage(file, opts={})
64
+ raise "You can only ravage .pdfs using JRuby, not #{RUBY_PLATFORM}!"
65
+ end
66
+ end
67
+
68
+ def ==(other)
69
+ self.name == other.name && self.fields == other.fields
70
+ end
71
+
72
+ def to_json(*args)
73
+ {
74
+ "json_class" => self.class.name,
75
+ "data" => {"name" => @name, "fields" => @fields }
76
+ }.to_json(*args)
77
+ end
78
+
79
+ def self.json_create(obj)
80
+ fields = obj["data"]["fields"].map do |f|
81
+ # symbolize the keys
82
+ f = f.inject({}){|h,(k,v)| h[k.to_sym] = v; h}
83
+ f[:type] = f[:type].to_sym if f[:type]
84
+ f
85
+ end
86
+ o = new(obj["data"]["name"], :fields => fields)
87
+ end
88
+ end
89
+ end
90
+
91
+ module Kernel
92
+ def pdf(name=nil, opts={}, &blk)
93
+ r = PDFRavager::PDF.new(name, opts)
94
+ r.instance_eval(&blk)
95
+ r
96
+ end
97
+ end
@@ -0,0 +1,90 @@
1
+ require 'java'
2
+ require File.dirname(__FILE__) + '/../../vendor/iText-4.2.0'
3
+
4
+ include_class "com.lowagie.text.pdf.AcroFields"
5
+ include_class "com.lowagie.text.pdf.PdfArray"
6
+ include_class "com.lowagie.text.pdf.PdfDictionary"
7
+ include_class "com.lowagie.text.pdf.PdfName"
8
+ include_class "com.lowagie.text.pdf.PdfObject"
9
+ include_class "com.lowagie.text.pdf.PdfReader"
10
+ include_class "com.lowagie.text.pdf.PdfStamper"
11
+ include_class "com.lowagie.text.pdf.PdfStream"
12
+ include_class "com.lowagie.text.pdf.PdfWriter"
13
+ include_class "com.lowagie.text.pdf.XfaForm"
14
+ include_class "com.lowagie.text.pdf.XfdfReader"
15
+
16
+ module PDFRavager
17
+ class Ravager
18
+ private_class_method :new
19
+
20
+ def self.open(opts={}, &block)
21
+ opts = {:in_file => opts} if opts.is_a? String
22
+ out = if opts[:out_file]
23
+ java.io.FileOutputStream.new(opts[:out_file])
24
+ else
25
+ java.io.ByteArrayOutputStream.new
26
+ end
27
+ raise "You must pass a block" unless block_given?
28
+ ravager = new(opts[:in_file], out)
29
+ yield ravager
30
+ ravager.destroy
31
+ out
32
+ end
33
+
34
+ def set_field_value(name, value)
35
+ # Transform boolean checkbox value to 1 or 0 char
36
+ if get_field_type(name) == AcroFields::FIELD_TYPE_CHECKBOX && !!value
37
+ value = value == true ? '1' : '0'
38
+ end
39
+ # First use AcroForms method
40
+ begin
41
+ @afields.setField(XfaForm::Xml2Som::getShortName(SOM.escape(name)), value)
42
+ rescue java.lang.NullPointerException
43
+ # If the AcroForms method doesn't work, we'll set the XDP
44
+ doc = Nokogiri::XML::Document.wrap(@xfa.getDomDocument)
45
+ doc.xpath("//*[local-name()='field'][@name='#{name}']").each do |node|
46
+ # Create an XML node in the XDP basically like this: "<value><text>#{value}</text></value>"
47
+ Nokogiri::XML::Builder.with(node) do |xml|
48
+ xml.value_ do |v|
49
+ v.text_ value
50
+ end
51
+ end
52
+ end
53
+ @xfa.setDomDocument(doc.to_java)
54
+ @xfa.setChanged(true)
55
+ end
56
+ end
57
+
58
+ def get_field_type(name)
59
+ short_name = XfaForm::Xml2Som::getShortName(SOM.escape(name))
60
+ begin
61
+ @afields.getFieldType(short_name)
62
+ rescue java.lang.NullPointerException
63
+ nil
64
+ end
65
+ end
66
+
67
+ def destroy
68
+ @stamper.close
69
+ end
70
+
71
+ private
72
+
73
+ def initialize(in_file, out)
74
+ @reader = PdfReader.new(in_file)
75
+ @out = out
76
+ @stamper = PdfStamper.new(@reader, @out)
77
+ @afields = @stamper.getAcroFields
78
+ @xfa = @afields.getXfa
79
+ @som = @xfa.getDatasetsSom
80
+ @som_template = @xfa.getTemplateSom
81
+ end
82
+
83
+ end
84
+
85
+ class SOM
86
+ def self.escape(str)
87
+ XfaForm::Xml2Som.escapeSom(str) # just does: str.gsub(/\./) { '\\.' }
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,3 @@
1
+ module PDFRavager
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path("../lib/pdf_ravager/version", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "pdf_ravager"
6
+ s.version = PDFRavager::VERSION
7
+ s.platform = 'java'
8
+ s.authors = ['Abe Voelker']
9
+ s.email = 'abe@abevoelker.com'
10
+ s.date = '2012-10-17'
11
+ s.homepage = 'https://github.com/abevoelker/pdf_ravager'
12
+ s.summary = %q{DSL to aid filling out AcroForms PDF and XFA documents}
13
+ s.description = %q{DSL to aid filling out AcroForms PDF and XFA documents}
14
+
15
+ s.add_runtime_dependency "json"
16
+ s.add_development_dependency "bundler", ">= 1.0.0"
17
+
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+ s.require_paths = ["lib"]
22
+ end
@@ -0,0 +1,140 @@
1
+ require 'spec_helper'
2
+ require 'pdf_ravager/pdf'
3
+
4
+ class TestPDF < MiniTest::Unit::TestCase
5
+ def setup
6
+ @pdf = pdf 'foo.pdf' do
7
+ text 'text_always', 'foo'
8
+ text 'text_when_true', 'foo', :when => true
9
+ text 'text_when_false', 'foo', :when => false
10
+ text 'text_if_true', 'foo', :if => true
11
+ text 'text_if_false', 'foo', :if => false
12
+ text 'text_unless_true', 'foo', :unless => true
13
+ text 'text_unless_false', 'foo', :unless => false
14
+ radio_group 'radio_group_always_filled' do
15
+ fill 'foo'
16
+ end
17
+ radio_group 'radio_group_if' do
18
+ fill 'true', :if => true
19
+ fill 'false', :if => false
20
+ end
21
+ radio_group 'radio_group_when' do
22
+ fill 'true', :when => true
23
+ fill 'false', :when => false
24
+ end
25
+ radio_group 'radio_group_unless' do
26
+ fill 'true', :unless => true
27
+ fill 'false', :unless => false
28
+ end
29
+ checkbox_group 'checkbox_group_always_checked' do
30
+ check 'foo'
31
+ end
32
+ checkbox_group 'checkbox_group_if' do
33
+ check 'true', :if => true
34
+ check 'false', :if => false
35
+ end
36
+ checkbox_group 'checkbox_group_when' do
37
+ check 'true', :when => true
38
+ check 'false', :when => false
39
+ end
40
+ checkbox_group 'checkbox_group_unless' do
41
+ check 'true', :unless => true
42
+ check 'false', :unless => false
43
+ end
44
+ end
45
+
46
+ @pdf_from_json = JSON.parse(@pdf.to_json)
47
+ end
48
+
49
+ def test_that_name_is_set
50
+ assert_equal @pdf.name, 'foo.pdf'
51
+ end
52
+
53
+ def test_that_text_is_set
54
+ assert_includes @pdf.fields, {:name => 'text_always', :value => 'foo', :type => :text}
55
+ end
56
+
57
+ def test_that_text_when_true_is_set
58
+ assert_includes @pdf.fields, {:name => 'text_when_true', :value => 'foo', :type => :text}
59
+ end
60
+
61
+ def test_that_text_when_false_is_not_set
62
+ refute_includes @pdf.fields, {:name => 'text_when_false', :value => 'foo', :type => :text}
63
+ end
64
+
65
+ def test_that_text_if_true_is_set
66
+ assert_includes @pdf.fields, {:name => 'text_if_true', :value => 'foo', :type => :text}
67
+ end
68
+
69
+ def test_that_text_if_false_is_not_set
70
+ refute_includes @pdf.fields, {:name => 'text_if_false', :value => 'foo', :type => :text}
71
+ end
72
+
73
+ def test_that_text_unless_true_is_not_set
74
+ refute_includes @pdf.fields, {:name => 'text_unless_true', :value => 'foo', :type => :text}
75
+ end
76
+
77
+ def test_that_text_unless_false_is_set
78
+ assert_includes @pdf.fields, {:name => 'text_unless_false', :value => 'foo', :type => :text}
79
+ end
80
+
81
+ def test_that_radio_group_always_filled_is_filled
82
+ assert_includes @pdf.fields, {:name => 'radio_group_always_filled', :value => 'foo', :type => :radio}
83
+ end
84
+
85
+ def test_that_radio_group_when_true_is_set
86
+ assert_includes @pdf.fields, {:name => 'radio_group_when', :value => 'true', :type => :radio}
87
+ end
88
+
89
+ def test_that_radio_group_when_false_is_not_set
90
+ refute_includes @pdf.fields, {:name => 'radio_group_when', :value => 'false', :type => :radio}
91
+ end
92
+
93
+ def test_that_radio_group_if_true_is_set
94
+ assert_includes @pdf.fields, {:name => 'radio_group_if', :value => 'true', :type => :radio}
95
+ end
96
+
97
+ def test_that_radio_group_if_false_is_not_set
98
+ refute_includes @pdf.fields, {:name => 'radio_group_if', :value => 'false', :type => :radio}
99
+ end
100
+
101
+ def test_that_radio_group_unless_true_is_not_set
102
+ refute_includes @pdf.fields, {:name => 'radio_group_unless', :value => 'true', :type => :radio}
103
+ end
104
+
105
+ def test_that_radio_group_unless_false_is_set
106
+ assert_includes @pdf.fields, {:name => 'radio_group_unless', :value => 'false', :type => :radio}
107
+ end
108
+
109
+ def test_that_checkbox_group_always_checked_is_checked
110
+ assert_includes @pdf.fields, {:name => 'checkbox_group_always_checked', :value => 'foo', :type => :checkbox}
111
+ end
112
+
113
+ def test_that_checkbox_group_when_true_is_set
114
+ assert_includes @pdf.fields, {:name => 'checkbox_group_when', :value => 'true', :type => :checkbox}
115
+ end
116
+
117
+ def test_that_checkbox_group_when_false_is_not_set
118
+ refute_includes @pdf.fields, {:name => 'checkbox_group_when', :value => 'false', :type => :checkbox}
119
+ end
120
+
121
+ def test_that_checkbox_group_if_true_is_set
122
+ assert_includes @pdf.fields, {:name => 'checkbox_group_if', :value => 'true', :type => :checkbox}
123
+ end
124
+
125
+ def test_that_checkbox_group_if_false_is_not_set
126
+ refute_includes @pdf.fields, {:name => 'checkbox_group_if', :value => 'false', :type => :checkbox}
127
+ end
128
+
129
+ def test_that_checkbox_group_unless_true_is_not_set
130
+ refute_includes @pdf.fields, {:name => 'checkbox_group_unless', :value => 'true', :type => :checkbox}
131
+ end
132
+
133
+ def test_that_checkbox_group_unless_false_is_set
134
+ assert_includes @pdf.fields, {:name => 'checkbox_group_unless', :value => 'false', :type => :checkbox}
135
+ end
136
+
137
+ def test_json_serialization
138
+ assert_equal @pdf, @pdf_from_json
139
+ end
140
+ end
@@ -0,0 +1 @@
1
+ require 'turn/autorun'
Binary file
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pdf_ravager
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: java
7
+ authors:
8
+ - Abe Voelker
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-10-17 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: json
16
+ version_requirements: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ! '>='
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ none: false
22
+ requirement: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ none: false
28
+ prerelease: false
29
+ type: :runtime
30
+ - !ruby/object:Gem::Dependency
31
+ name: bundler
32
+ version_requirements: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - ! '>='
35
+ - !ruby/object:Gem::Version
36
+ version: 1.0.0
37
+ none: false
38
+ requirement: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ! '>='
41
+ - !ruby/object:Gem::Version
42
+ version: 1.0.0
43
+ none: false
44
+ prerelease: false
45
+ type: :development
46
+ description: DSL to aid filling out AcroForms PDF and XFA documents
47
+ email: abe@abevoelker.com
48
+ executables: []
49
+ extensions: []
50
+ extra_rdoc_files: []
51
+ files:
52
+ - .gitignore
53
+ - Gemfile
54
+ - LICENSE
55
+ - README.md
56
+ - Rakefile
57
+ - lib/pdf_ravager.rb
58
+ - lib/pdf_ravager/pdf.rb
59
+ - lib/pdf_ravager/ravager.rb
60
+ - lib/pdf_ravager/version.rb
61
+ - pdf_ravager.gemspec
62
+ - spec/pdf_spec.rb
63
+ - spec/spec_helper.rb
64
+ - vendor/iText-4.2.0.jar
65
+ homepage: https://github.com/abevoelker/pdf_ravager
66
+ licenses: []
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ none: false
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ! '>='
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ none: false
83
+ requirements: []
84
+ rubyforge_project:
85
+ rubygems_version: 1.8.24
86
+ signing_key:
87
+ specification_version: 3
88
+ summary: DSL to aid filling out AcroForms PDF and XFA documents
89
+ test_files: []
90
+ ...