class InterMine::Metadata::Path
A representation of a path through the data model, starting at a table/class, and descending ultimately to an attribute. A path represents a valid sequence of joins and column accesses according to the webservice's database schema.
In string format, a path can be represented using dotted notation:
Gene.proteins.proteinDomains.name
Which is a valid path through the data-model, starting in the gene table, following a reference to the protein table (via x-to-many relationship) and then to the protein-domain table and then finally to the name column in the protein domain table. Joins are implicitly implied.
- author
-
Alex Kalderimis dev@intermine.org
- homepage
- Licence
-
Copyright (C) 2002-2011 FlyMine
This code may be freely distributed and modified under the terms of the GNU Lesser General Public Licence. This should be distributed with the code. See the LICENSE file for more information or www.gnu.org/copyleft/lesser.html.
Attributes
The objects represented by each section of the path. The first is always a ClassDescriptor
.
The data model that this path describes.
The root class of this path. This is the same as the first element.
The subclass information used to create this path.
Public Class Methods
Construct a Path
The standard mechanism is to parse a string representing a path with information about the model and the subclasses that are in force. However, it is also possible to clone a path by passing a Path
through as the first element, and also to construct a path from a ClassDescriptor
. In both cases the new Path
will inherit the model of the object used to construct it, this avoid the need for a model in these cases.
# File lib/intermine/model.rb 726 def initialize(pathstring, model=nil, subclasses={}) 727 @model = model 728 @subclasses = subclasses 729 @elements = [] 730 @rootClass = nil 731 parse(pathstring) 732 end
Public Instance Methods
Two paths can be said to be equal when they stringify to the same representation.
# File lib/intermine/model.rb 781 def ==(other) 782 return self.to_s == other.to_s 783 end
Return the last ClassDescriptor
mentioned in this path. eg:
Gene
-
Gene
Gene.symbol
-
Gene
Gene.proteins
-
Protein
Gene.proteins.name
-
Protein
# File lib/intermine/model.rb 764 def end_cd 765 last = @elements.last 766 if last.is_a?(ClassDescriptor) 767 return last 768 elsif last.respond_to?(:referencedType) 769 return last.referencedType 770 else 771 penult = @elements[-2] 772 if penult.is_a?(ClassDescriptor) 773 return penult 774 else 775 return penult.referencedType 776 end 777 end 778 end
Return the string that describes the kind of thing this path represents. eg:
Gene
-
“Gene”
Gene.symbol
-
“java.lang.String”
Gene.proteins
-
“Protein”
# File lib/intermine/model.rb 743 def end_type 744 last = @elements.last 745 if last.is_a?(ClassDescriptor) 746 return last.name 747 elsif last.respond_to?(:referencedType) 748 return last.referencedType.name 749 else 750 return last.dataType 751 end 752 end
Return true if the Path
ends in an attribute
# File lib/intermine/model.rb 801 def is_attribute? 802 return @elements.last.is_a?(AttributeDescriptor) 803 end
Return true if the last element is a class (ie. a path of length 1)
# File lib/intermine/model.rb 806 def is_class? 807 return @elements.last.is_a?(ClassDescriptor) 808 end
Return true if the last element is a collection
# File lib/intermine/model.rb 816 def is_collection? 817 return @elements.last.is_a?(CollectionDescriptor) 818 end
Return true if the last element is a reference.
# File lib/intermine/model.rb 811 def is_reference? 812 return @elements.last.is_a?(ReferenceDescriptor) 813 end
Get the number of elements in the path
# File lib/intermine/model.rb 786 def length 787 return @elements.length 788 end
Returns a string as to_s
without the first element. eg: “proteins.name”
# File lib/intermine/model.rb 796 def to_headless_s 797 return @elements[1, @elements.size - 1].map {|x| x.name}.join(".") 798 end
Return the string representation of this path, eg: “Gene.proteins.name”
# File lib/intermine/model.rb 791 def to_s 792 return @elements.map {|x| x.name}.join(".") 793 end
Private Instance Methods
Perform the parsing of the input into a sequence of elements.
# File lib/intermine/model.rb 823 def parse(pathstring) 824 if pathstring.is_a?(ClassDescriptor) 825 @rootClass = pathstring 826 @elements << pathstring 827 @model = pathstring.model 828 return 829 elsif pathstring.is_a?(Path) 830 @rootClass = pathstring.rootClass 831 @elements = pathstring.elements 832 @model = pathstring.model 833 @subclasses = pathstring.subclasses 834 return 835 end 836 837 bits = pathstring.split(".") 838 rootName = bits.shift 839 @rootClass = @model.get_cd(rootName) 840 if @rootClass.nil? 841 raise PathException.new(pathstring, subclasses, "Invalid root class '#{rootName}'") 842 end 843 844 @elements << @rootClass 845 processed = [rootName] 846 847 current_cd = @rootClass 848 849 while (bits.length > 0) 850 this_bit = bits.shift 851 fd = current_cd.get_field(this_bit) 852 if fd.nil? 853 subclassKey = processed.join(".") 854 if @subclasses.has_key?(subclassKey) 855 subclass = model.get_cd(@subclasses[subclassKey]) 856 if subclass.nil? 857 raise PathException.new(pathstring, subclasses, 858 "'#{subclassKey}' constrained to be a '#{@subclasses[subclassKey]}', but that is not a valid class in the model") 859 end 860 current_cd = subclass 861 fd = current_cd.get_field(this_bit) 862 end 863 if fd.nil? 864 raise PathException.new(pathstring, subclasses, 865 "giving up at '#{subclassKey}.#{this_bit}'. Could not find '#{this_bit}' in '#{current_cd}'") 866 end 867 end 868 @elements << fd 869 if fd.respond_to?(:referencedType) 870 current_cd = fd.referencedType 871 elsif bits.length > 0 872 raise PathException.new(pathstring, subclasses, 873 "Attributes must be at the end of the path. Giving up at '#{this_bit}'") 874 else 875 current_cd = nil 876 end 877 processed << this_bit 878 end 879 end