Class: RDF::SAK::Transform::Application
- Defined in:
- lib/rdf/sak/transform.rb
Overview
“Application” as in to “apply” a function, not an “app”.
A record of a transformation function application.
Instance Attribute Summary collapse
-
#completes ⇒ Object
readonly
Returns the value of attribute completes.
-
#input ⇒ Object
readonly
Returns the value of attribute input.
-
#output ⇒ Object
readonly
Returns the value of attribute output.
Attributes inherited from Partial
Class Method Summary collapse
-
.resolve(harness, subject: nil, transform: nil, params: {}, partial: nil, input: nil, output: nil) ⇒ RDF::SAK::Transform::Application
Resolve a particular function Application from the repository.
Instance Method Summary collapse
- #===(other) ⇒ Object
- #[](key) ⇒ Object
- #completes?(partial) ⇒ Boolean
-
#initialize(subject, transform, input, output, params = {}, start: nil, stop: nil) ⇒ Application
constructor
Create a new function application from whole cloth.
- #keys ⇒ Object
- #matches?(params) ⇒ Boolean
- #params ⇒ Object
-
#to_triples ⇒ Object
Returns the function application as an array of triples.
- #transform ⇒ Object
Methods inherited from Partial
Constructor Details
#initialize(subject, transform, input, output, params = {}, start: nil, stop: nil) ⇒ Application
Create a new function application from whole cloth.
901 902 903 904 905 906 907 908 909 910 911 |
# File 'lib/rdf/sak/transform.rb', line 901 def initialize subject, transform, input, output, params = {}, start: nil, stop: nil # params may be a partial super subject, transform, params @input = input @output = output @completes = params if params.is_a? RDF::SAK::Transform::Partial @start = start @stop = stop end |
Instance Attribute Details
#completes ⇒ Object (readonly)
Returns the value of attribute completes.
891 892 893 |
# File 'lib/rdf/sak/transform.rb', line 891 def completes @completes end |
#input ⇒ Object (readonly)
Returns the value of attribute input.
891 892 893 |
# File 'lib/rdf/sak/transform.rb', line 891 def input @input end |
#output ⇒ Object (readonly)
Returns the value of attribute output.
891 892 893 |
# File 'lib/rdf/sak/transform.rb', line 891 def output @output end |
Class Method Details
.resolve(harness, subject: nil, transform: nil, params: {}, partial: nil, input: nil, output: nil) ⇒ RDF::SAK::Transform::Application
Resolve a particular function Application from the repository. Either resolve by subject, or resolve by a transform + parameter + input set. Applications that complete Partials will be automatically resolved.
766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 |
# File 'lib/rdf/sak/transform.rb', line 766 def self.resolve harness, subject: nil, transform: nil, params: {}, partial: nil, input: nil, output: nil # either a subject or transform + input + output? + params? repo = harness.repo partials = harness.partials if subject # noop return subject if subject.is_a? self # okay partial partial = RDF::SAK::Util.objects_for( subject, RDF::SAK::TFO.completes, only: :resource).sort.first if partial tmp = partials.resolve(subject: partial) or raise "Could not find partial #{partial}" partial = tmp transform = partial.transform else transform = RDF::SAK::Util.objects_for( subject, RDF::SAK::TFO.transform, only: :resource).sort.first or raise "Could not find a transform for #{subject}" tmp = harness.resolve(transform) or raise "Could not find transform #{transform}" transform = tmp params = transform.validate # get params params = {} transform.keys.each do |p| o = repo.query([subject, p, nil]).objects.uniq.sort params[p] = o unless o.empty? end end # get inputs and outputs input = RDF::SAK::Util.objects_for( subject, RDF::SAK::TFO.input, only: :resource).sort.first output = RDF::SAK::Util.objects_for( subject, RDF::SAK::TFO.output, only: :resource).sort.first raise 'Data must have both input and output' unless input and output elsif input and ((transform and params) or partial) # XXX dispatch on partial only? smart? dumb? if partial transform = partial.transform params = partial.params else # do transform t = harness.resolve(transform) or raise "Could not resolve transform #{transform}" transform = t # coerce/validate params params = transform.validate params, defaults: false # do partial partial = partials.resolve transform: transform, params: params end # collect function application receipts candidates = RDF::Query.new do # note that there is no cost-based optimization so we write # these in the order of least to most cardinality pattern [:t, RDF::SAK::TFO.output, output] if output pattern [:t, RDF::SAK::TFO.input, input] end.execute(repo).map { |sol| sol[:t] }.compact.uniq.select do |s| # this should say, try matching the partial if there is one # to match, otherwise attempt to directly match the transform if partial and repo.has_statement?( RDF::Statement(s, RDF::SAK::TFO.completes, partial.subject)) true elsif repo.has_statement?( RDF::Statement(s, RDF::SAK::TFO.transform, transform.subject)) testp = transform.keys.map do |p| o = repo.query([s, p, nil]).objects.uniq.sort o.empty? ? nil : [p, o] end.compact.to_h testp = transform.validate testp, defaults: false, silent: true testp == params end end.compact.uniq.sort return if candidates.empty? if candidates.size == 1 subject = candidates.first else # now we have the unlikely case that there are two identical # records so we just sort em first by end date, then by # start date, then lexically subject = candidates.map do |s| st, et = %i[startedAtTime endedAtTime].map do |p| repo.query([s, RDF::Vocab::PROV[p], nil]).map do |stmt| dt = stmt.object.object dt if dt.is_a? DateTime end.compact.sort.last end [s, st, et] end.sort do |a, b| # first check latest end-time, then check latest start-time c = a[2] && b[2] ? b[2] <=> a[2] : 0 # if those two yield nothing, then sort lexically i guess (c == 0 && a[1] && b[1]) ? b[1] <=> a[1] : a[0] <=> b[0] end.first.first end else raise ArgumentError, 'must have either a subject or transform + params + input' end # don't forget the output output ||= repo.query( [subject, RDF::SAK::TFO.output, nil] ).objects.select(&:uri?).sort.first new subject, transform, input, output, partial || params end |
Instance Method Details
#===(other) ⇒ Object
968 969 970 971 972 973 974 975 976 977 |
# File 'lib/rdf/sak/transform.rb', line 968 def ===(other) return false unless other.is_a? Application return false unless @input == other.input and @output == other.output # now the comparand is either the partial or us cmp = @completes || self # and this should do it other.transform == cmp.transform and other.matches? cmp.params end |
#[](key) ⇒ Object
942 943 944 945 |
# File 'lib/rdf/sak/transform.rb', line 942 def [](key) # note complete is (@completes || @params)[key] end |
#completes?(partial) ⇒ Boolean
959 960 961 |
# File 'lib/rdf/sak/transform.rb', line 959 def completes? partial @completes and partial and @completes == partial end |
#keys ⇒ Object
947 948 949 |
# File 'lib/rdf/sak/transform.rb', line 947 def keys (@completes || @params).keys end |
#matches?(params) ⇒ Boolean
963 964 965 966 |
# File 'lib/rdf/sak/transform.rb', line 963 def matches? params return @completes.matches? params if @completes super params end |
#params ⇒ Object
951 952 953 |
# File 'lib/rdf/sak/transform.rb', line 951 def params @completes ? @completes.params : @params.dup end |
#to_triples ⇒ Object
Returns the function application as an array of triples.
914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 |
# File 'lib/rdf/sak/transform.rb', line 914 def to_triples out = [] # .extend RDF::Enumerable s = @subject out << [s, RDF.type, RDF::SAK::TFO.Application] if @start start = @start.is_a?(RDF::Literal) ? @start : RDF::Literal(@start) out << [s, RDF::Vocab::PROV.startedAtTime, start] end if @stop stop = @stop.is_a?(RDF::Literal) ? @stop : RDF::Literal(@stop) out << [s, RDF::Vocab::PROV.endedAtTime, stop] end if @completes out << [s, RDF::SAK::TFO.completes, @completes.subject] else out << [s, RDF::SAK::TFO.transform, transform.subject] pdup = transform.validate params, defaults: false, silent: true pdup.each do |k, vals| vals.each { |v| out << [s, k, v] } end end out.map { |triples| RDF::Statement(*triples) } end |
#transform ⇒ Object
955 956 957 |
# File 'lib/rdf/sak/transform.rb', line 955 def transform @completes ? @completes.transform : @transform end |