# 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
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
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'
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
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
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
--- /dev/null
+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
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
c2.blob = link_element.elements['box2EndAdornments'].attributes['blob'].downcase.intern
c2.crowsfoot = link_element.elements['box2EndAdornments'].attributes['crowsfoot'].downcase.intern
end
+
end
end
--- /dev/null
+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
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
--- /dev/null
+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
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?><Drawing
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ name="Untitled" mark="4.0">
+
+<box id="0" name="Unit" mark="0.0">
+ <location x="121.0" y="113.0"/>
+ <size width="80.0" height="40.0"/>
+ <comment></comment>
+</box>
+
+<box id="1" name="Employee" mark="0.0">
+ <location x="356.0" y="129.0"/>
+ <size width="80.0" height="40.0"/>
+ <comment></comment>
+</box>
+
+<box id="2" name="Course" mark="0.0">
+ <location x="132.0" y="265.0"/>
+ <size width="80.0" height="40.0"/>
+ <comment></comment>
+</box>
+
+<box id="3" name="Presentation" mark="0.0">
+ <location x="383.0" y="277.0"/>
+ <size width="80.0" height="40.0"/>
+ <comment></comment>
+</box>
+
+<box id="4" name="Client" mark="0.0">
+ <location x="389.0" y="421.0"/>
+ <size width="80.0" height="40.0"/>
+ <comment></comment>
+</box>
+
+<link id="0" mark="0.0">
+ <moveableName name="ConsistsOf">
+ <point x="156" y="214"/>
+ </moveableName>
+ <converseName name="converseName"/>
+ <box1 id="0"/>
+ <box2 id="2"/>
+ <bendPoints>
+ <point x="161.0" y="133.0"/>
+ <point x="162.44736842105263" y="153.0"/>
+ <point x="166.5" y="209.0"/>
+ <point x="170.55263157894737" y="265.0"/>
+ <point x="172.0" y="285.0"/>
+ </bendPoints>
+ <midMoved value="false"/>
+ <box1EndAdornments blob="Closed" crowsfoot="Yes"/>
+ <box2EndAdornments blob="Closed" crowsfoot="No"/>
+ <comment></comment>
+</link>
+
+<link id="1" mark="0.0">
+ <moveableName name="Prepares">
+ <point x="257" y="149"/>
+ </moveableName>
+ <converseName name="converseName"/>
+ <box1 id="0"/>
+ <box2 id="1"/>
+ <bendPoints>
+ <point x="161.0" y="133.0"/>
+ <point x="201.0" y="135.72340425531914"/>
+ <point x="278.5" y="141.0"/>
+ <point x="356.0" y="146.27659574468086"/>
+ <point x="396.0" y="149.0"/>
+ </bendPoints>
+ <midMoved value="false"/>
+ <box1EndAdornments blob="Open" crowsfoot="Yes"/>
+ <box2EndAdornments blob="Closed" crowsfoot="No"/>
+ <comment></comment>
+</link>
+
+<link id="2" mark="0.0">
+ <moveableName name="Presents">
+ <point x="417" y="203"/>
+ </moveableName>
+ <converseName name="converseName"/>
+ <box1 id="1"/>
+ <box2 id="3"/>
+ <bendPoints>
+ <point x="396.0" y="149.0"/>
+ <point x="399.64864864864865" y="169.0"/>
+ <point x="409.5" y="223.0"/>
+ <point x="419.35135135135135" y="277.0"/>
+ <point x="423.0" y="297.0"/>
+ </bendPoints>
+ <midMoved value="false"/>
+ <box1EndAdornments blob="Closed" crowsfoot="No"/>
+ <box2EndAdornments blob="Closed" crowsfoot="Yes"/>
+ <comment></comment>
+</link>
+
+<link id="3" mark="0.0">
+ <moveableName name="Presented">
+ <point x="288" y="296"/>
+ </moveableName>
+ <converseName name="converseName"/>
+ <box1 id="2"/>
+ <box2 id="3"/>
+ <bendPoints>
+ <point x="172.0" y="285.0"/>
+ <point x="212.0" y="286.9123505976096"/>
+ <point x="297.5" y="291.0"/>
+ <point x="383.0" y="295.0876494023904"/>
+ <point x="423.0" y="297.0"/>
+ </bendPoints>
+ <midMoved value="false"/>
+ <box1EndAdornments blob="Open" crowsfoot="No"/>
+ <box2EndAdornments blob="Closed" crowsfoot="Yes"/>
+ <comment></comment>
+</link>
+
+<link id="4" mark="0.0">
+ <moveableName name="Recieves">
+ <point x="439" y="361"/>
+ </moveableName>
+ <converseName name="converseName"/>
+ <box1 id="3"/>
+ <box2 id="4"/>
+ <bendPoints>
+ <point x="423.0" y="297.0"/>
+ <point x="423.8333333333333" y="317.0"/>
+ <point x="426.0" y="369.0"/>
+ <point x="428.1666666666667" y="421.0"/>
+ <point x="429.0" y="441.0"/>
+ </bendPoints>
+ <midMoved value="false"/>
+ <box1EndAdornments blob="Closed" crowsfoot="Yes"/>
+ <box2EndAdornments blob="Closed" crowsfoot="No"/>
+ <comment></comment>
+</link>
+
+<selfLink id="5" mark="0.0">
+ <moveableName name="IsPrerequisiteOf">
+ <point x="40.0" y="228.0"/>
+ </moveableName>
+ <converseName name="converseName"/>
+ <box1 id="2"/>
+ <box2 id="2"/>
+ <cornerNo value="1"/>
+ <bendPoints>
+ <point x="132.0" y="265.0"/>
+ <point x="112.0" y="250.0"/>
+ <point x="132.0" y="265.0"/>
+ </bendPoints>
+ <midMoved value="false"/>
+ <box1EndAdornments blob="Open" crowsfoot="Yes"/>
+ <box2EndAdornments blob="Open" crowsfoot="No"/>
+ <comment></comment>
+</selfLink>
+
+</Drawing>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?><Drawing
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ name="Untitled" mark="4.5">
+
+<box id="3" name="Course" mark="0.0">
+ <location x="91.0" y="235.0"/>
+ <size width="80.0" height="40.0"/>
+ <comment></comment>
+</box>
+
+<selfLink id="5" mark="0.0">
+ <moveableName name="AssociatedWith">
+ <point x="71.0" y="200.0"/>
+ </moveableName>
+ <converseName name="converseName"/>
+ <box1 id="3"/>
+ <box2 id="3"/>
+ <cornerNo value="1"/>
+ <bendPoints>
+ <point x="91.0" y="235.0"/>
+ <point x="71.0" y="220.0"/>
+ <point x="91.0" y="235.0"/>
+ </bendPoints>
+ <midMoved value="false"/>
+ <box1EndAdornments blob="Closed" crowsfoot="Yes"/>
+ <box2EndAdornments blob="Open" crowsfoot="No"/>
+ <comment></comment>
+</selfLink>
+
+</Drawing>
\ No newline at end of file