amanzi-sld 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,152 @@
1
+ #/usr/bin/env ruby
2
+
3
+ module Amanzi
4
+ module XML
5
+ class Element
6
+ attr_reader :name, :children, :depth
7
+ attr_accessor :attributes, :namespace
8
+ def initialize(name,depth=0)
9
+ @name = name
10
+ @depth = depth
11
+ @children = []
12
+ @attributes = {}
13
+ end
14
+ # Utility for setting the namepace in a method-chaining DSL
15
+ def ns(ns)
16
+ self.namespace = ns
17
+ self
18
+ end
19
+ def []= (key,value)
20
+ @attributes[key] = value
21
+ end
22
+ def insert index, child
23
+ @children.insert index, child
24
+ end
25
+ def << child
26
+ @children << child
27
+ end
28
+ def make_child(name,options={},&block)
29
+ child = Element.new(name,depth+1)
30
+ namespace && (child.namespace = namespace)
31
+ options.each{|k,v| child[k]=v}
32
+ block && block.call(child)
33
+ child
34
+ end
35
+ def insert_child(index,name,options={},&block)
36
+ insert index, child = make_child(name,options,&block)
37
+ child
38
+ end
39
+ def add_child(name,options={},&block)
40
+ self << child = make_child(name,options,&block)
41
+ child
42
+ end
43
+ def comment(text)
44
+ @children << Comment.new(text)
45
+ end
46
+ def self.camelize(symbol)
47
+ symbol.to_s.gsub(/__/,':_').gsub(/(^|_)(\w)/){"#{$2.upcase}"}.gsub(/^(\w+):/){"#{$1.downcase}:"}
48
+ end
49
+ def method_missing(symbol,*args,&block)
50
+ add_child(Element.camelize(symbol), *args, &block)
51
+ end
52
+ def indent(offset=0)
53
+ @indent ||= []
54
+ @indent[offset] ||= (0...(depth+offset)).inject(''){|a,v|a << (@xml_options[:tab] || "\t")}
55
+ end
56
+ def attribute_text
57
+ attributes.empty? ? "" : " #{attributes.to_a.map{|x|"#{x[0]}=\"#{x[1]}\""}.join(' ')}"
58
+ end
59
+ def contents
60
+ children.length==1 && !children[0].is_a?(Element) && children[0].to_s ||
61
+ "\n#{indent(1)}#{children.map{|x|x.to_xml(@xml_options)}.join("\n#{indent(1)}")}\n#{indent}"
62
+ end
63
+ def tag
64
+ namespace ? "#{namespace}:#{name}" : name
65
+ end
66
+ def to_xml(options={})
67
+ @xml_options = options
68
+ children.empty? ? "<#{tag}#{attribute_text}/>" : "<#{tag}#{attribute_text}>#{contents}</#{tag}>"
69
+ end
70
+ def to_s
71
+ tag
72
+ end
73
+ end
74
+ class Comment < Element
75
+ def to_xml(options={})
76
+ "<!-- #{[name,children].flatten.map{|c| c.to_s}.join(', ')} -->"
77
+ end
78
+ end
79
+
80
+ class Document < Element
81
+ def to_xml(options={})
82
+ "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" + super(options) + "\n"
83
+ end
84
+ def singleton_elements
85
+ @singleton_elements ||= []
86
+ end
87
+ def comment text
88
+ !@singleton_elements.empty? && @singleton_elements.flatten[-1].comment(text)
89
+ end
90
+ def add_singleton_elements(elements=[])
91
+ prev_e = nil
92
+ singleton_elements << elements.map do |e|
93
+ parent = prev_e || self
94
+ element = Element.new(Element.camelize(e), parent.depth + 1)
95
+ parent << element
96
+ prev_e = element
97
+ end
98
+ end
99
+ def singleton_method(symbol,*args,&block)
100
+ name = Element.camelize symbol
101
+ singleton_elements.flatten.each do |element|
102
+ if element.name === name
103
+ #puts "Found singleton: #{name}"
104
+ block && block.call(element)
105
+ return element
106
+ end
107
+ end
108
+ #puts "Found no singletons for #{name}"
109
+ nil
110
+ end
111
+ def method_missing(symbol,*args,&block)
112
+ #puts "Method missing in XML::Document: #{symbol}"
113
+ singleton_method(symbol,*args,&block) || super(symbol,*args,&block)
114
+ end
115
+ def to_s
116
+ to_xml
117
+ end
118
+ end
119
+ end
120
+
121
+ module HTML
122
+ class Document < XML::Document
123
+ def initialize(title)
124
+ super 'HTML'
125
+ add_singleton_elements ['head']
126
+ add_singleton_elements ['body']
127
+ head.title << title
128
+ end
129
+ # Pass any unknown methods down to body
130
+ def method_missing(symbol,*args,&block)
131
+ singleton_method(symbol,*args,&block) ||
132
+ singleton_method(:body).send(symbol, *args, &block)
133
+ end
134
+ def self.test
135
+ doc = XML::Document.new "HTML"
136
+ doc.head.title << "Test HTML Document"
137
+ doc.body.h1 << "Header One"
138
+
139
+ puts doc.to_s
140
+
141
+ doc = HTML::Document.new 'Another test HTML Document'
142
+ doc.body.h1 << 'Header Two'
143
+ doc.table do |t|
144
+ t.tr{|r| r.th << :one;r.th << :two}
145
+ t.tr{|r| r.td << 1;r.td << 2}
146
+ end
147
+
148
+ puts doc.to_s
149
+ end
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'amanzi-sld'
8
+
9
+ class Test::Unit::TestCase
10
+ end
@@ -0,0 +1,47 @@
1
+ require 'helper'
2
+ require 'differ'
3
+
4
+ class TestFile < Test::Unit::TestCase
5
+ # should "probably rename this file and start testing for real" do
6
+ # flunk "hey buddy, you should probably rename this file and start testing for real"
7
+ # end
8
+ def show_diff(results,expected)
9
+ puts "Results: #{results.class.to_s}"
10
+ puts "Expected: #{expected.class.to_s}"
11
+ puts "Results: #{results.inspect[0..100]}"
12
+ puts "Expected: #{expected.inspect[0..100]}"
13
+ diff = Differ.diff_by_line(results,expected)
14
+ puts diff.methods.join(', ')
15
+ # puts diff.inspect
16
+ puts diff.format_as :color
17
+ end
18
+ def test_file(file,expect)
19
+ @results = `ruby -I lib #{file}`
20
+
21
+ if File.exist? expect
22
+ expected = File.open(expect).read
23
+ if expected.length != @results.length
24
+ puts "Got different results: #{expected.length} != #{@results.length}"
25
+ show_diff(@results,expected)
26
+ false
27
+ else
28
+ true
29
+ end
30
+ else
31
+ File.open(@expect,'w') do |file|
32
+ file.puts @results
33
+ end
34
+ puts "Wrote first time run results to #{@expect}"
35
+ end
36
+ end
37
+
38
+ context "Test file" do
39
+ setup do
40
+ @file = 'examples/test.rb'
41
+ @expect = 'examples/test.sld'
42
+ end
43
+ should "produce expected output" do
44
+ assert test_file @file, @expect
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,123 @@
1
+ require 'helper'
2
+
3
+ class TestXML < Test::Unit::TestCase
4
+ context "An SLD document" do
5
+ setup do
6
+ @doc = Amanzi::SLD::Document.new 'Test SLD Document'
7
+ end
8
+ should "contain an XML header" do
9
+ #puts "Have SLD document: #{@doc}"
10
+ assert @doc.to_s =~ /^\<\?xml/
11
+ end
12
+ should "have a StyledLayerDescriptor->NamedLayer->UserStyle->Name tree" do
13
+ assert_equal @doc.name, 'StyledLayerDescriptor'
14
+ assert_equal (layer = @doc.children[0]).name, 'NamedLayer'
15
+ assert_equal layer.children[0].name, 'Name'
16
+ assert_equal (style = layer.children[1]).name, 'UserStyle'
17
+ assert_equal style.children[0].name, 'Name'
18
+ assert_equal 2, layer.children.length
19
+ end
20
+
21
+ context "with some line styles" do
22
+ setup do
23
+ @doc.comment "Add a simple line style"
24
+ @doc.add_line_symbolizer :stroke_width => 5
25
+ @doc.comment "Add a more complex line style with filter"
26
+ @doc.add_line_symbolizer :stroke_width => 5, :stroke => '#2080a0' do |f|
27
+ f.geometry = 'LineString'
28
+ end
29
+ end
30
+ should "have two LineSymbolizers" do
31
+ #puts "Have SLD document: #{@doc}"
32
+ tags = @doc.to_s.split(/[\r\n]+/).grep(/\<LineSymbolizer/i)
33
+ assert_equal 2, tags.length
34
+ end
35
+ should "have a geometry type function call" do
36
+ tags = @doc.to_s.split(/[\r\n]+/).grep(/\<ogc\:Function/i)
37
+ assert_equal 1, tags.length
38
+ assert /geometryType/.match tags[0]
39
+ end
40
+ end
41
+
42
+ context "with polygon style and complex filter" do
43
+ setup do
44
+ @doc.comment "Polygon with complex Filter"
45
+ @doc.add_polygon_symbolizer(:stroke_width => 2, :stroke => '#dddddd', :fill => '#aaaaaa', :fill_opacity => 0.4) do |f|
46
+ f.op(:and) do |f|
47
+ f.geometry = 'Polygon'
48
+ f.op(:or) do |f|
49
+ f.property.not_exists? :highway
50
+ f.property.exists? :waterway
51
+ f.property[:natural] = 'water'
52
+ end
53
+ end
54
+ end
55
+ end
56
+ should "have one PolygonSymbolizers" do
57
+ #puts "Have SLD document: #{@doc}"
58
+ assert_equal 1, @doc.to_s.split(/[\r\n]+/).grep(/\<PolygonSymbolizer/i).length
59
+ assert_equal 1, @doc.to_s.split(/[\r\n]+/).grep(/\<\/PolygonSymbolizer/i).length
60
+ end
61
+ should "have a geometry type function call" do
62
+ tags = @doc.to_s.split(/[\r\n]+/).grep(/\<ogc\:Function/i)
63
+ assert_equal 1, tags.length
64
+ assert /geometryType/.match tags[0]
65
+ end
66
+ end
67
+
68
+ context "with multiple symbolizers using the same filter rules" do
69
+ setup do
70
+ @doc.comment "Multiple symbolizers and complex filter"
71
+ @doc.
72
+ add_line_symbolizer(:stroke_width => 7, :stroke => '#303030').
73
+ add_line_symbolizer(:stroke_width => 5, :stroke => '#e0e0ff') do |f|
74
+ f.op(:and) do |f|
75
+ f.geometry = 'LineString'
76
+ f.property.exists? :highway
77
+ f.op(:or) do |f|
78
+ f.property[:highway] = 'secondary'
79
+ f.property[:highway] = 'tertiary'
80
+ end
81
+ end
82
+ end
83
+ end
84
+ should "have two LineSymbolizers" do
85
+ #puts "Have SLD document: #{@doc}"
86
+ assert_equal 2, @doc.to_s.split(/[\r\n]+/).grep(/\<LineSymbolizer/i).length
87
+ assert_equal 2, @doc.to_s.split(/[\r\n]+/).grep(/\<\/LineSymbolizer/i).length
88
+ end
89
+ should "have a geometry type function call" do
90
+ tags = @doc.to_s.split(/[\r\n]+/).grep(/\<ogc\:Function/i)
91
+ assert_equal 1, tags.length
92
+ assert /geometryType/.match tags[0]
93
+ end
94
+ should "have four CssParameter tags" do
95
+ assert_equal 4, @doc.to_s.split(/[\r\n]+/).grep(/\<CssParameter/i).length
96
+ assert_equal 4, @doc.to_s.split(/[\r\n]+/).grep(/\<\/CssParameter/i).length
97
+ end
98
+ should "have an rule->filter->and tree with three children" do
99
+ assert_equal 'StyledLayerDescriptor', @doc.name
100
+ assert_equal 'NamedLayer', (layer = @doc.children[0]).name
101
+ assert_equal 'UserStyle', (style = layer.children[1]).name
102
+ assert_equal 3, style.children.length
103
+ assert_equal 'FeatureTypeStyle', (fstyle = style.children[2]).name
104
+ assert_equal 'Rule', (rule = fstyle.children[0]).name
105
+ assert_equal 3, rule.children.length
106
+ assert_equal 'Filter', (filter = rule.children[0]).name
107
+ assert_equal 1, filter.children.length
108
+ assert_equal 'And', (andtag = filter.children[0]).name
109
+ assert_equal 3, andtag.children.length
110
+ assert_equal 'PropertyIsEqualTo', (geom = andtag.children[0]).name
111
+ assert_equal 2, geom.children.length
112
+ assert_equal 'Literal', (gname = geom.children[1]).name
113
+ assert_equal 'LineString', gname.children[0]
114
+ assert_equal 'Or', (props = andtag.children[2]).name
115
+ assert_equal 2, props.children.length
116
+ assert_equal 'PropertyIsEqualTo', (propB = props.children[1]).name
117
+ assert_equal 'PropertyName', propB.children[0].name
118
+ assert_equal 'highway', propB.children[0].contents
119
+ assert_equal 'tertiary', propB.children[1].contents
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,70 @@
1
+ require 'helper'
2
+
3
+ class TestXML < Test::Unit::TestCase
4
+ context "An XML document" do
5
+ setup do
6
+ @doc = Amanzi::XML::Document.new 'Test'
7
+ end
8
+ should "contain an XML header" do
9
+ assert @doc.to_s =~ /^\<\?xml/
10
+ end
11
+ context "with some tags" do
12
+ setup do
13
+ @doc.data.body do |body|
14
+ body.head << "Header"
15
+ body.content << "Some text"
16
+ end
17
+ end
18
+ should "have only one body" do
19
+ #puts "Have XML document: #{@doc}"
20
+ body_tags = @doc.to_s.split(/[\r\n]+/).grep(/\<body/i)
21
+ assert_equal 1, body_tags.length
22
+ end
23
+ should "have an data->body with two child tags" do
24
+ assert_equal 'data', (data = @doc.children[0]).name.downcase
25
+ assert_equal 'body', (body = data.children[0]).name.downcase
26
+ assert_equal 2, body.children.length
27
+ end
28
+ end
29
+ end
30
+
31
+ context "An HTML document" do
32
+ setup do
33
+ @doc = Amanzi::HTML::Document.new 'Test HTML Document'
34
+ end
35
+ should "contain an XML header" do
36
+ assert @doc.to_s =~ /^\<\?xml/
37
+ end
38
+ context "with some tags" do
39
+ setup do
40
+ @doc.body.h1 << "Header"
41
+ @doc.body.p << "Some text"
42
+ @doc.body.p << "Some more text"
43
+ @doc.body.table do |t|
44
+ t.tr do |tr|
45
+ tr.td << 'a'
46
+ tr.td << 'b'
47
+ end
48
+ t.tr do |tr|
49
+ tr.td << '1'
50
+ tr.td << '2'
51
+ end
52
+ end
53
+ end
54
+ should "have only one body" do
55
+ #puts "Have HTML document: #{@doc}"
56
+ body_tags = @doc.to_s.split(/[\r\n]+/).grep(/\<body/i)
57
+ assert_equal 1, body_tags.length
58
+ end
59
+ should "have four table cell tags" do
60
+ assert_equal 4, @doc.to_s.split(/[\r\n]+/).grep(/\<td/i).length
61
+ assert_equal 4, @doc.to_s.split(/[\r\n]+/).grep(/\<\/td/i).length
62
+ end
63
+ should "have an html->body with four child tags" do
64
+ assert_equal 'head', (head = @doc.children[0]).name.downcase
65
+ assert_equal 'body', (body = @doc.children[1]).name.downcase
66
+ assert_equal 4, body.children.length
67
+ end
68
+ end
69
+ end
70
+ end
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: amanzi-sld
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Craig Taverner
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-11-02 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: thoughtbot-shoulda
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :development
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: differ
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 9
44
+ segments:
45
+ - 0
46
+ - 1
47
+ version: "0.1"
48
+ type: :development
49
+ version_requirements: *id002
50
+ description: Map styles are often defined using SLD, or Style Layer Descriptor documents. These XML documents are very long, verbose and complex to maintain. Amanzi:SLD is a simpler DSL designed to generate SLD documents, but using a very much simpler syntax. Many common cases might be a single line only, while the simplest SLD is usually a dozen lines or more.
51
+ email: craig@amanzi.com
52
+ executables: []
53
+
54
+ extensions: []
55
+
56
+ extra_rdoc_files:
57
+ - LICENSE
58
+ - README.rdoc
59
+ files:
60
+ - .document
61
+ - .gitignore
62
+ - LICENSE
63
+ - README.rdoc
64
+ - Rakefile
65
+ - VERSION
66
+ - amanzi-sld.gemspec
67
+ - examples/osm.rb
68
+ - examples/osm_highway_shp.rb
69
+ - examples/test.rb
70
+ - examples/test.sld
71
+ - lib/amanzi-sld.rb
72
+ - lib/amanzi/sld.rb
73
+ - lib/amanzi/xml.rb
74
+ - test/helper.rb
75
+ - test/test_file.rb
76
+ - test/test_sld.rb
77
+ - test/test_xml.rb
78
+ has_rdoc: true
79
+ homepage: http://github.com/craigtaverner/amanzi-sld
80
+ licenses: []
81
+
82
+ post_install_message:
83
+ rdoc_options:
84
+ - --charset=UTF-8
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ hash: 3
93
+ segments:
94
+ - 0
95
+ version: "0"
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ hash: 3
102
+ segments:
103
+ - 0
104
+ version: "0"
105
+ requirements: []
106
+
107
+ rubyforge_project:
108
+ rubygems_version: 1.3.7
109
+ signing_key:
110
+ specification_version: 3
111
+ summary: A Ruby DSL for simpler SLD creation for styling maps
112
+ test_files:
113
+ - test/test_file.rb
114
+ - test/test_xml.rb
115
+ - test/test_sld.rb
116
+ - test/helper.rb
117
+ - examples/osm.rb
118
+ - examples/test.rb
119
+ - examples/osm_highway_shp.rb