From: Neil Smith Date: Fri, 3 Feb 2012 17:12:32 +0000 (+0000) Subject: Added label objects X-Git-Url: https://git.njae.me.uk/?a=commitdiff_plain;h=042a27abb3ac3bf9faf36406204fe1d1901123d3;p=erd-marker.git Added label objects --- diff --git a/Gemfile b/Gemfile index 116c2fc..f73bc3e 100644 --- a/Gemfile +++ b/Gemfile @@ -6,9 +6,10 @@ source "http://rubygems.org" # Add dependencies to develop your gem here. # Include everything needed to run rake, tests, features, etc. group :development do - gem "rspec", "~> 2.6.0" - gem "bundler", "~> 1.0.0" + gem "rspec" + gem "bundler" gem "rdoc" gem "rake" - gem "graph.njae", "0.2.3" + gem "graph.njae" + gem "porter2stemmer" end diff --git a/Gemfile.lock b/Gemfile.lock index 9962be5..d440e9c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,25 +1,29 @@ GEM remote: http://rubygems.org/ specs: - diff-lcs (1.1.2) + diff-lcs (1.1.3) graph.njae (0.2.3) - rake (0.9.2) - rdoc (3.7) - rspec (2.6.0) - rspec-core (~> 2.6.0) - rspec-expectations (~> 2.6.0) - rspec-mocks (~> 2.6.0) - rspec-core (2.6.4) - rspec-expectations (2.6.0) + json (1.6.5) + porter2stemmer (1.0.0) + rake (0.9.2.2) + rdoc (3.12) + json (~> 1.4) + rspec (2.8.0) + rspec-core (~> 2.8.0) + rspec-expectations (~> 2.8.0) + rspec-mocks (~> 2.8.0) + rspec-core (2.8.0) + rspec-expectations (2.8.0) diff-lcs (~> 1.1.2) - rspec-mocks (2.6.0) + rspec-mocks (2.8.0) PLATFORMS ruby DEPENDENCIES - bundler (~> 1.0.0) - graph.njae (= 0.2.3) + bundler + graph.njae + porter2stemmer rake rdoc - rspec (~> 2.6.0) + rspec diff --git a/lib/erd_handler.rb b/lib/erd_handler.rb index 6524d31..241db56 100644 --- a/lib/erd_handler.rb +++ b/lib/erd_handler.rb @@ -1,11 +1,14 @@ require 'bundler/setup' -require "rexml/document" +require 'rexml/document' include REXML -require "graph.njae" +require 'graph.njae' include GraphNjae +require 'porter2stemmer' + +require 'erd_handler/label' require 'erd_handler/erd' require 'erd_handler/box' require 'erd_handler/link' diff --git a/lib/erd_handler/box.rb b/lib/erd_handler/box.rb index 7389955..75543eb 100644 --- a/lib/erd_handler/box.rb +++ b/lib/erd_handler/box.rb @@ -8,7 +8,7 @@ module ErdHandler def read(box_element) self.id = box_element.attributes["id"].to_i - self.name = box_element.attributes["name"] + self.name = Label.new box_element.attributes["name"] self.mark = box_element.attributes["mark"].to_f self.x = box_element.elements["location"].attributes["x"].to_f @@ -19,5 +19,14 @@ module ErdHandler self end + def contains?(other) + self.x < other.x and self.x + self.width > other.x + other.width and + self.y < other.y and self.y + self.height > other.y + other.height + end + + def within?(other) + other.contains?(self) + end + end end diff --git a/lib/erd_handler/erd.rb b/lib/erd_handler/erd.rb index 142f575..bf74007 100644 --- a/lib/erd_handler/erd.rb +++ b/lib/erd_handler/erd.rb @@ -10,7 +10,7 @@ module ErdHandler doc = Document.new(source) raise InvalidErdFile unless doc.elements.to_a.length == 1 and doc.elements[1].name.downcase == 'drawing' self.mark = doc.elements['Drawing'].attributes["mark"].to_f - self.name = doc.elements['Drawing'].attributes["name"] + self.name = Label.new doc.elements['Drawing'].attributes["name"] doc.elements.each('Drawing/box') do |box_element| self << Box.new(box_element) end diff --git a/lib/erd_handler/label.rb b/lib/erd_handler/label.rb new file mode 100644 index 0000000..ad81618 --- /dev/null +++ b/lib/erd_handler/label.rb @@ -0,0 +1,47 @@ +class Label + + attr_reader :original, :processed + + def initialize(original) + @original = original + @processed = [original] + end + + def split(opts = {}) + if opts.class == Regexp + regexp = opts + split_camel_case = true + else + regexp = opts[:regexp] || /[ _,.-]+/ + if opts.has_key? :camel_case + split_camel_case = opts[:camel_case] + else + split_camel_case = true + end + end + @processed = @processed.map do |segment| + segment.split(regexp) + end.flatten + + if split_camel_case + @processed = @processed.map do |segment| + segment.split(/(?=[A-Z])/) + end.flatten + end + self + end + + def downcase + @processed = @processed.map do |segment| segment.downcase end + self + end + + def stem(gb_english = false) + @processed = @processed.map do |segment| segment.stem(gb_english) end + self + end + + def tidy + self.split.downcase.stem + end +end \ No newline at end of file diff --git a/lib/erd_handler/link.rb b/lib/erd_handler/link.rb index 4a7b181..63bfd06 100644 --- a/lib/erd_handler/link.rb +++ b/lib/erd_handler/link.rb @@ -9,7 +9,7 @@ module ErdHandler def read(link_element, vertices) self.id = link_element.attributes["id"].to_i self.mark = link_element.attributes["mark"].to_f - self.name = link_element.elements['moveableName'].attributes['name'] + self.name = Label.new link_element.elements['moveableName'].attributes['name'] box1 = vertices.select {|v| v.id == link_element.elements['box1'].attributes['id'].to_i}[0] box2 = vertices.select {|v| v.id == link_element.elements['box2'].attributes['id'].to_i}[0] self << box1 << box2 @@ -27,5 +27,6 @@ module ErdHandler c2.blob = link_element.elements['box2EndAdornments'].attributes['blob'].downcase.intern c2.crowsfoot = link_element.elements['box2EndAdornments'].attributes['crowsfoot'].downcase.intern end + end end diff --git a/spec/erd_handler/box_spec.rb b/spec/erd_handler/box_spec.rb new file mode 100644 index 0000000..82005d6 --- /dev/null +++ b/spec/erd_handler/box_spec.rb @@ -0,0 +1,42 @@ +require 'spec_helper' + +module ErdHandler + describe Box do + # Needed as RSpec includes the Psych YAML reader, which defines :y as + # a method for generating YAML of an object. + class Box + undef_method :y + end + + describe "#contains?" do + it "reports when a box contains another" do + b1 = Box.new + b1.x = 10 ; b1.y = 10 ; b1.width = 20 ; b1.height = 20 + b2 = Box.new ; b2.x = 5 ; b2.y = 5 ; b2.width = 30 ; b2.height = 30 + b3 = Box.new ; b3.x = 15 ; b3.y = 15 ; b3.width = 20 ; b3.height = 20 + + b1.should_not be_contains(b2) + b2.should be_contains(b1) + b1.should_not be_contains(b3) + b3.should_not be_contains(b1) + end + end # contains? + + describe "#within?" do + it "reports when a box is within another" do + b1 = Box.new + b1.x = 10 ; b1.y = 10 ; b1.width = 20 ; b1.height = 20 + b2 = Box.new ; b2.x = 5 ; b2.y = 5 ; b2.width = 30 ; b2.height = 30 + b3 = Box.new ; b3.x = 15 ; b3.y = 15 ; b3.width = 20 ; b3.height = 20 + + # Can't use the standard RSpec predicate notation as it clashes with + # floating-point expectations + b1.within?(b2).should == true + b2.within?(b1).should == false + b1.within?(b3).should == false + b3.within?(b1).should == false + end + end # contains? + + end +end diff --git a/spec/erd_handler/erd_spec.rb b/spec/erd_handler/erd_spec.rb index 0c32a81..d6d5561 100644 --- a/spec/erd_handler/erd_spec.rb +++ b/spec/erd_handler/erd_spec.rb @@ -79,56 +79,62 @@ module ErdHandler erd.should have(6).edges b0 = erd.vertices.find {|b| b.id == 0} - b0.name.should == "Unit" + b0.name.original.should == "Unit" b0.should have(2).neighbours b1 = erd.vertices.find {|b| b.id == 1} - b1.name.should == "Employee" + b1.name.original.should == "Employee" b1.should have(2).neighbours b2 = erd.vertices.find {|b| b.id == 2} - b2.name.should == "Course" + b2.name.original.should == "Course" b2.should have(3).neighbours b3 = erd.vertices.find {|b| b.id == 3} - b3.name.should == "Presentation" + b3.name.original.should == "Presentation" b3.should have(3).neighbours b4 = erd.vertices.find {|b| b.id == 4} - b4.name.should == "Client" + b4.name.original.should == "Client" b4.should have(1).neighbours l0 = erd.edges.find {|e| e.id == 0} + l0.name.original.should == "ConsistsOf" l0.connections.find {|c| c.end == b0}.blob.should be :closed l0.connections.find {|c| c.end == b0}.crowsfoot.should be :yes l0.connections.find {|c| c.end == b2}.blob.should be :closed l0.connections.find {|c| c.end == b2}.crowsfoot.should be :no l1 = erd.edges.find {|e| e.id == 1} + l1.name.original.should == "Prepares" l1.connections.find {|c| c.end == b0}.blob.should be :open l1.connections.find {|c| c.end == b0}.crowsfoot.should be :yes l1.connections.find {|c| c.end == b1}.blob.should be :closed l1.connections.find {|c| c.end == b1}.crowsfoot.should be :no l2 = erd.edges.find {|e| e.id == 2} + l2.name.original.should == "Presents" l2.connections.find {|c| c.end == b1}.blob.should be :closed l2.connections.find {|c| c.end == b1}.crowsfoot.should be :no l2.connections.find {|c| c.end == b3}.blob.should be :closed l2.connections.find {|c| c.end == b3}.crowsfoot.should be :yes l3 = erd.edges.find {|e| e.id == 3} + l3.name.original.should == "Presented" l3.connections.find {|c| c.end == b2}.blob.should be :open l3.connections.find {|c| c.end == b2}.crowsfoot.should be :no l3.connections.find {|c| c.end == b3}.blob.should be :closed l3.connections.find {|c| c.end == b3}.crowsfoot.should be :yes l4 = erd.edges.find {|e| e.id == 4} + l4.name.original.should == "Recieves" l4.connections.find {|c| c.end == b3}.blob.should be :closed l4.connections.find {|c| c.end == b3}.crowsfoot.should be :yes l4.connections.find {|c| c.end == b4}.blob.should be :closed l4.connections.find {|c| c.end == b4}.crowsfoot.should be :no l5 = erd.edges.find {|e| e.id == 5} + l5.name.original.should == "IsPrerequisiteOf" l5.connections.find {|c| c.crowsfoot == :yes}.blob.should be :open l5.connections.find {|c| c.crowsfoot == :no}.blob.should be :open l5.connections.find {|c| c.crowsfoot == :yes}.end.should be b2 diff --git a/spec/erd_handler/label_spec.rb b/spec/erd_handler/label_spec.rb new file mode 100644 index 0000000..d2fb0c8 --- /dev/null +++ b/spec/erd_handler/label_spec.rb @@ -0,0 +1,119 @@ +require 'spec_helper' + +module ErdHandler + describe Label do + describe '#original' do + it "reports the string it was initialised with" do + test_label = "Test label" + l1 = Label.new test_label + l1.original.should == test_label + end + end # original + + describe '#processed' do + it "reports the original if no processing has been done" do + test_label = "Test label" + l1 = Label.new test_label + l1.processed.should == [test_label] + l1.original.should == test_label + end + end # processed + + describe '#split' do + it "splits the original on the specified regexp" do + l1 = Label.new "Test label" + l1.split(/ /) + l1.processed.should == ["Test", "label"] + l1.original.should == "Test label" + + l1 = Label.new "Test_label" + l1.split(/_/) + l1.processed.should == ["Test", "label"] + + l1 = Label.new "Test label_string" + l1.split(/[ _]/) + l1.processed.should == ["Test", "label", "string"] + end + + it "splits the original on camel case" do + l1 = Label.new "TestLabel" + l1.split :camel_case => true + l1.processed.should == ["Test", "Label"] + l1.original.should == "TestLabel" + + l2 = Label.new "testLabel" + l2.split :camel_case => true + l2.processed.should == ["test", "Label"] + l2.original.should == "testLabel" + end + + it "doesn't split the original on camel case if asked not to" do + l1 = Label.new "TestLabel" + l1.split :camel_case => false + l1.processed.should == ["TestLabel"] + l1.original.should == "TestLabel" + + l2 = Label.new "TestLabel" + l2.split :camel_case => nil + l2.processed.should == ["TestLabel"] + l2.original.should == "TestLabel" + end + + it "splits the original using a default regexp" do + l1 = Label.new "Test label_string" + l1.split + l1.processed.should == ["Test", "label", "string"] + end + + it "splits the original on camel case by default" do + l1 = Label.new "TestLabel" + l1.split + l1.processed.should == ["Test", "Label"] + l1.original.should == "TestLabel" + end + + it "splits the original on punctuation and camel case by default" do + l1 = Label.new "TestLabel is_split, he,said" + l1.split + l1.processed.should == ["Test", "Label", "is", "split", "he", "said"] + l1.original.should == "TestLabel is_split, he,said" + end + + it "is idempotent" do + l1 = Label.new "TestLabel is_split, he,said" + res1 = l1.split.dup + res2 = l1.split + res1.processed.should == res2.processed + l1.original.should == "TestLabel is_split, he,said" + end + end # split + + describe "#downcase" do + it "downcases all parts of the processed label" do + l1 = Label.new "Test label_string" + l1.split.downcase + l1.processed.should == ["test", "label", "string"] + end + end # downcase + + describe "#stem" do + it "stems all parts of the processed label" do + l1 = Label.new "testing labeller string pontificated" + l1.split.stem + l1.processed.should == ["test", "label", "string", "pontif"] + end + end # stem + + describe "#tidy" do + it "tidies a label" do + l1 = Label.new "testingLabeller string, he_pontificated" + l2 = Label.new l1.original + l1.tidy + l2.split.downcase.stem + l1.processed.should == l2.processed + + end + end # tidy + + end +end diff --git a/spec/fixtures/complex_erd.xml b/spec/fixtures/complex_erd.xml new file mode 100644 index 0000000..26d808b --- /dev/null +++ b/spec/fixtures/complex_erd.xml @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spec/fixtures/single_box_self_loop_erd.xml b/spec/fixtures/single_box_self_loop_erd.xml new file mode 100644 index 0000000..d44a486 --- /dev/null +++ b/spec/fixtures/single_box_self_loop_erd.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file