boundy 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +7 -0
  2. data/lib/boundy.rb +19 -0
  3. data/lib/boundy/bound.rb +65 -0
  4. data/lib/boundy/bound/comparator.rb +67 -0
  5. data/lib/boundy/bound/constrainer.rb +29 -0
  6. data/lib/boundy/bound/infinite.rb +46 -0
  7. data/lib/boundy/bound/infinite/above.rb +12 -0
  8. data/lib/boundy/bound/infinite/below.rb +13 -0
  9. data/lib/boundy/comparator.rb +19 -0
  10. data/lib/boundy/comparators.rb +28 -0
  11. data/lib/boundy/domain.rb +115 -0
  12. data/lib/boundy/domain/anterior.rb +45 -0
  13. data/lib/boundy/domain/builder.rb +31 -0
  14. data/lib/boundy/domain/comparator.rb +26 -0
  15. data/lib/boundy/domain/constrainer.rb +21 -0
  16. data/lib/boundy/domain/finite.rb +64 -0
  17. data/lib/boundy/domain/posterior.rb +43 -0
  18. data/lib/boundy/formatter.rb +9 -0
  19. data/lib/boundy/formatter/sql.rb +26 -0
  20. data/lib/boundy/formatter/sql/domain.rb +20 -0
  21. data/lib/boundy/formatter/sql/domain/plugin.rb +22 -0
  22. data/lib/boundy/formatter/sql/factory.rb +14 -0
  23. data/lib/boundy/formatter/sql/plugin.rb +38 -0
  24. data/lib/boundy/formatters/bound.rb +16 -0
  25. data/lib/boundy/formatters/domain.rb +12 -0
  26. data/lib/boundy/formatters/fixnum.rb +20 -0
  27. data/lib/boundy/formatters/sql/bound.rb +22 -0
  28. data/lib/boundy/formatters/sql/domain.rb +28 -0
  29. data/lib/boundy/formatters/sql/domain/anterior.rb +23 -0
  30. data/lib/boundy/formatters/sql/domain/finite.rb +24 -0
  31. data/lib/boundy/formatters/sql/domain/posterior.rb +23 -0
  32. data/lib/boundy/formatters/time.rb +42 -0
  33. data/lib/boundy/range/comparator.rb +38 -0
  34. data/lib/boundy/range/constrainer.rb +17 -0
  35. data/lib/boundy/time/comparator.rb +37 -0
  36. data/test/integration/boundy_test.rb +37 -0
  37. data/test/integration/domain_test.rb +18 -0
  38. data/test/integration/formatter/sql_test.rb +21 -0
  39. data/test/integration/test_helper.rb +14 -0
  40. data/test/unit/boundy/bound/comparator_test.rb +37 -0
  41. data/test/unit/boundy/bound/constrainer_test.rb +123 -0
  42. data/test/unit/boundy/bound/infinite/above_test.rb +36 -0
  43. data/test/unit/boundy/bound/infinite/below_test.rb +36 -0
  44. data/test/unit/boundy/bound/infinite_test.rb +0 -0
  45. data/test/unit/boundy/bound_test.rb +86 -0
  46. data/test/unit/boundy/comparator_test.rb +0 -0
  47. data/test/unit/boundy/domain/anterior_test.rb +103 -0
  48. data/test/unit/boundy/domain/comparator_test.rb +75 -0
  49. data/test/unit/boundy/domain/constrainer_test.rb +11 -0
  50. data/test/unit/boundy/domain/posterior_test.rb +75 -0
  51. data/test/unit/boundy/domain_test.rb +50 -0
  52. data/test/unit/boundy/formatter/sql/domain/plugin_test.rb +16 -0
  53. data/test/unit/boundy/formatter/sql/plugin_test.rb +50 -0
  54. data/test/unit/boundy/formatter/sql_test.rb +26 -0
  55. data/test/unit/boundy/formatters/bound_test.rb +43 -0
  56. data/test/unit/boundy/formatters/domain_test.rb +12 -0
  57. data/test/unit/boundy/formatters/sql/domain/anterior_test.rb +29 -0
  58. data/test/unit/boundy/formatters/sql/domain/finite_test.rb +35 -0
  59. data/test/unit/boundy/formatters/sql/domain/posterior_test.rb +30 -0
  60. data/test/unit/boundy/formatters/time_test.rb +27 -0
  61. data/test/unit/boundy/range/comparator_test.rb +44 -0
  62. data/test/unit/boundy/range/constrainer_test.rb +11 -0
  63. data/test/unit/boundy/time/comparator_test.rb +40 -0
  64. data/test/unit/test_helper.rb +14 -0
  65. metadata +154 -0
@@ -0,0 +1,31 @@
1
+ module Boundy
2
+ module Domain
3
+ module Builder
4
+ def self.builders
5
+ [
6
+ {
7
+ bounds: {
8
+ from: Boundy::Bound::Infinite::Below,
9
+ to: Boundy::Bound
10
+ },
11
+ builder: Proc.new {|b,e| Boundy::Domain::Anterior.new(e) }
12
+ },
13
+ {
14
+ bounds: {
15
+ from: Boundy::Bound,
16
+ to: Boundy::Bound
17
+ },
18
+ builder: Proc.new {|b,e| Boundy::Domain::Finite.new(b,e) }
19
+ },
20
+ {
21
+ bounds: {
22
+ from: Boundy::Bound,
23
+ to: Boundy::Bound::Infinite::Above
24
+ },
25
+ builder: Proc.new {|b,e| Boundy::Domain::Posterior.new(b) }
26
+ }
27
+ ]
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,26 @@
1
+ require 'boundy/comparator'
2
+
3
+ module Boundy
4
+ module Domain
5
+ class Comparator
6
+ include Boundy::Comparator
7
+
8
+ def initialize(datum, subject)
9
+ @datum = datum
10
+ @subject = subject
11
+ end
12
+
13
+ def after?
14
+ @subject.from > @datum && @subject.to >= @datum
15
+ end
16
+
17
+ def before?
18
+ @subject.from <= @datum && @subject.to < @datum
19
+ end
20
+
21
+ def within?
22
+ @subject.from <= @datum && @subject.to >= @datum
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,21 @@
1
+ require 'boundy/bound/constrainer'
2
+ require 'boundy/domain'
3
+
4
+ module Boundy
5
+ module Domain
6
+ class Constrainer
7
+ def initialize(me, other)
8
+ @me = me
9
+ @other = other
10
+ end
11
+
12
+
13
+ def constrain
14
+ from = Boundy::Bound::Constrainer.new(@me.from, @other.from)
15
+ to = Boundy::Bound::Constrainer.new(@me.to, @other.to)
16
+
17
+ Boundy::Domain.new(from.max, to.min)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,64 @@
1
+ require 'boundy/domain'
2
+
3
+ module Boundy
4
+ module Domain
5
+ class Finite
6
+ def self.builder
7
+ {
8
+ bounds: {
9
+ from: Boundy::Bound,
10
+ to: Boundy::Bound
11
+ },
12
+ builder: Proc.new {|b,e| self.new(b,e) }
13
+ }
14
+ end
15
+
16
+ include Domain::Plugin
17
+
18
+ def initialize(b,e)
19
+ case b
20
+ when Boundy::Bound
21
+ @from = b
22
+ @to = e
23
+ else
24
+ raise "I can't convert #{b.class.name} into a Boundy::Domain::Finite"
25
+ end
26
+ unless valid?
27
+ raise "Backlooking ranges aren't allowed.\n\nFROM: #{@from.inspect}\nTO: #{@to.inspect}"
28
+ end
29
+ end
30
+
31
+ def valid?
32
+ raise if from.nil?
33
+ raise if to.nil?
34
+ raise if from.class < Boundy::Bound::Infinite
35
+ raise if to.class < Boundy::Bound::Infinite
36
+
37
+ from <= to
38
+ end
39
+
40
+
41
+ def strictly_earlier?(subject)
42
+ @from.before?(subject)
43
+ end
44
+
45
+ def strictly_after?(subject)
46
+ @to.after?(subject)
47
+ end
48
+
49
+ def partially_after?(subject)
50
+ @from.after?(subject) && @to.within?(subject)
51
+ end
52
+
53
+ def partially_before?(subject)
54
+ @from.within?(subject) && @to.before?(subject)
55
+ end
56
+
57
+ def partially_within?(subject)
58
+ [:within?, :partially_before?, :partially_after?].any? do |m|
59
+ send(m, subject)
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,43 @@
1
+ require 'boundy/domain'
2
+ require 'boundy/bound'
3
+ require 'boundy/bound/infinite/below'
4
+
5
+ module Boundy
6
+ module Domain
7
+ class Posterior
8
+ def self.builder
9
+ {
10
+ bounds: {
11
+ from: Boundy::Bound::Infinite::Below,
12
+ to: Boundy::Bound
13
+ },
14
+ builder: Proc.new {|b,e| self.new(e)}
15
+ }
16
+ end
17
+
18
+ include Domain::Plugin
19
+
20
+ def initialize(datum)
21
+ if datum.nil?
22
+ raise
23
+ end
24
+
25
+ @from = Boundy::Bound::Infinite::Below.new
26
+ @to = case datum
27
+ when Boundy::Bound
28
+ datum
29
+ else
30
+ Boundy::Bound.new(datum)
31
+ end
32
+ end
33
+
34
+ def cute
35
+ "[-infinity, #{@to.datum}]"
36
+ end
37
+
38
+ def inspect
39
+ "#<#{self.class.name} bounded above by #{@to.inspect}>"
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,9 @@
1
+ module Boundy
2
+ module Formatter
3
+ def sql
4
+ Boundy::Formatter::Sql
5
+ end
6
+ end
7
+ end
8
+
9
+
@@ -0,0 +1,26 @@
1
+ require 'boundy'
2
+ require 'boundy/formatter/sql/plugin'
3
+
4
+ require 'punchout'
5
+
6
+ require 'boundy/formatter/sql/factory'
7
+
8
+ module Boundy
9
+ module Formatter
10
+ class Sql
11
+ def initialize(obj, name)
12
+ formatter_factory = Plugin.for(obj)
13
+ if formatter_factory.nil?
14
+ raise "No formatter registered for #{obj.class}: #{obj.inspect}"
15
+ end
16
+ @formatter = formatter_factory.build(obj, name)
17
+ end
18
+
19
+ def to_s
20
+ @formatter.to_s
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ require 'boundy/formatters/sql/domain'
@@ -0,0 +1,20 @@
1
+ require 'boundy/formatter/sql/domain/plugin'
2
+
3
+ module Boundy
4
+ module Formatter
5
+ class Sql
6
+ class Domain
7
+ def initialize(obj, name)
8
+ @formatter = Plugin.for(obj).new(obj,name)
9
+ if @formatter.nil?
10
+ raise "No formatter registered for #{obj.inspect}"
11
+ end
12
+ end
13
+
14
+ def to_s
15
+ @formatter.to_s
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,22 @@
1
+ module Boundy
2
+ module Formatter
3
+ class Sql
4
+ class Domain
5
+ module Plugin
6
+ extend Punchout::Punchable
7
+ class << self
8
+ def included(base)
9
+ Boundy.logger.info "REGISTERING #{base} AS DOMAIN FORMATTER FOR #{base.type}"
10
+ matchable = Punchout::Matcher::Ancestry.new(base.type).punches(base)
11
+ puncher.add(matchable)
12
+ end
13
+
14
+ def for(obj)
15
+ punch(obj)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,14 @@
1
+ module Boundy
2
+ module Formatter
3
+ class Sql
4
+ class Factory
5
+ def initialize(klass)
6
+ @klass = klass
7
+ end
8
+ def build(obj, name)
9
+ @klass.new(obj, name)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,38 @@
1
+ require 'boundy'
2
+
3
+ require 'punchout'
4
+ require 'boundy/formatter/sql/factory'
5
+
6
+ module Boundy
7
+ module Formatter
8
+ class Sql
9
+ module Plugin
10
+ extend Punchout::Punchable
11
+ class << self
12
+
13
+ module FactoryMethods
14
+ def factory
15
+ @factory ||= Factory.new(self)
16
+ end
17
+ end
18
+
19
+ def included(base)
20
+ # XXX: This should really become an explicit include.
21
+ unless base.respond_to?(:factory)
22
+ base.instance_exec do
23
+ extend FactoryMethods
24
+ end
25
+ end
26
+ Boundy.logger.info "REGISTERING #{base} AS FORMATTER FOR #{base.type}"
27
+ matchable = Punchout::Matcher::Ancestry.new(base.type).punches(base.factory)
28
+ puncher.add(matchable)
29
+ end
30
+
31
+ def for(obj)
32
+ punch(obj)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,16 @@
1
+ require 'punchout'
2
+ require 'punchout/matcher/ancestry'
3
+
4
+ module Boundy
5
+ module Formatters
6
+ module Bound
7
+ def initialize(bound)
8
+ @bound = bound
9
+ end
10
+
11
+ def to_s
12
+ @formatter.to_s
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,12 @@
1
+ require 'boundy/formatters/bound'
2
+
3
+ module Boundy
4
+ module Formatters
5
+ module Domain
6
+ def initialize(domain)
7
+ @from = domain.from
8
+ @to = domain.to
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,20 @@
1
+ module Boundy
2
+ module Formatters
3
+ class Fixnum
4
+ def initialize(num, name)
5
+ @num = num
6
+ end
7
+
8
+ def self.type
9
+ ::Fixnum
10
+ end
11
+
12
+ include Boundy::Formatters::Bound
13
+ include Boundy::Formatter::Sql::Plugin
14
+
15
+ def to_s
16
+ @num
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,22 @@
1
+ require 'boundy/bound'
2
+
3
+ require 'boundy/formatter/sql/plugin'
4
+
5
+ require 'boundy/formatters/bound'
6
+
7
+ module Boundy::Formatters::Sql
8
+ class Bound
9
+ def self.type
10
+ Boundy::Bound
11
+ end
12
+
13
+ include Boundy::Formatters::Bound
14
+ include Boundy::Formatter::Sql::Plugin
15
+
16
+ def initialize(bound, name)
17
+ @formatter = Boundy::Formatter::Sql.new(bound.datum, name)
18
+ super(bound)
19
+ end
20
+ end
21
+ end
22
+
@@ -0,0 +1,28 @@
1
+ require 'boundy/formatter/sql/domain/plugin'
2
+
3
+ require 'boundy/formatters/domain'
4
+
5
+ module Boundy::Formatters::Sql
6
+ class Domain
7
+ def self.type
8
+ Boundy::Domain::Plugin
9
+ end
10
+
11
+ def initialize(domain, name)
12
+ @formatter = Boundy::Formatter::Sql::Domain::Plugin.for(domain).new(domain,name)
13
+ if @formatter.nil?
14
+ raise "No formatter registered for #{obj.inspect}"
15
+ end
16
+ end
17
+
18
+ include Boundy::Formatter::Sql::Plugin
19
+
20
+ def to_s
21
+ @formatter.to_s
22
+ end
23
+ end
24
+ end
25
+
26
+ require 'boundy/formatters/sql/domain/anterior'
27
+ require 'boundy/formatters/sql/domain/finite'
28
+ require 'boundy/formatters/sql/domain/posterior'
@@ -0,0 +1,23 @@
1
+ require 'boundy/formatter/sql/domain/plugin'
2
+ require 'boundy/domain/anterior'
3
+
4
+ module Boundy::Formatters::Sql
5
+ class Domain
6
+ class Anterior
7
+ def self.type
8
+ Boundy::Domain::Anterior
9
+ end
10
+
11
+ include Boundy::Formatter::Sql::Domain::Plugin
12
+
13
+ def initialize(domain, name)
14
+ @name = name
15
+ @formatter = Boundy::Formatter::Sql.new(domain.from, name)
16
+ end
17
+
18
+ def to_s
19
+ "#{@name} >= '#{@formatter.to_s}'"
20
+ end
21
+ end
22
+ end
23
+ end