lib/ruby-fs-stack/familytree.rb in ruby-fs-stack-0.4.12 vs lib/ruby-fs-stack/familytree.rb in ruby-fs-stack-0.5.0
- old
+ new
@@ -1,1445 +1,23 @@
require 'rubygems'
-require 'ruby-fs-stack/fs_communicator'
-require 'ruby-fs-stack/fs_utils'
+require 'ruby-fs-stack/familytree/communicator'
# Including more than one enunciate library raises a warning of
# already initialized constant.
require 'ruby-fs-stack/warning_suppressor'
with_warnings_suppressed do
require 'ruby-fs-stack/enunciate/familytree'
end
+require 'ruby-fs-stack/familytree/gender'
+require 'ruby-fs-stack/familytree/name'
+require 'ruby-fs-stack/familytree/event'
+require 'ruby-fs-stack/familytree/ordinance'
+require 'ruby-fs-stack/familytree/characteristic'
+require 'ruby-fs-stack/familytree/exist'
+require 'ruby-fs-stack/familytree/relationship'
+require 'ruby-fs-stack/familytree/person'
+require 'ruby-fs-stack/familytree/search'
+require 'ruby-fs-stack/familytree/match'
+require 'ruby-fs-stack/familytree/pedigree'
+require 'ruby-fs-stack/familytree/note'
-module FamilytreeV2
-
- # This method gets mixed into the FsCommunicator so that
- # you can make calls on the familytree_v2 module
- def familytree_v2
- @familytree_v2_com ||= Communicator.new self # self at this point refers to the FsCommunicator instance
- end
-
- class Communicator
- Base = '/familytree/v2/'
-
- # ===params
- # fs_communicator: FsCommunicator instance
- def initialize(fs_communicator)
- @fs_communicator = fs_communicator
- end
-
- # ===params
- # <tt>id_or_ids</tt> should be a string of the persons identifier. For the 'me' person, use :me or 'me'. Can also accept an array of ID strings.
- # <tt>options</tt> accepts a hash of parameters as documented by the API.
- # For full parameter documentation, see DevNet[https://devnet.familysearch.org/docs/api-manual-reference-system/familytree-v2/r_api_family_tree_person_read_v2.html]
- #
- # ===Example
- # # communicator is an authenticated FsCommunicator object
- # # Request a person with no assertions, only the version.
- # p = communicator.familytree_v2.person :me, :names => 'none', :genders => 'none', :events => 'none'
- #
- # p.version # => '90194378772'
- # p.id # => 'KW3B-NNM'
- def person(id_or_ids, options = {})
- if id_or_ids.kind_of? Array
- multiple_ids = true
- url = Base + 'person/' + id_or_ids.join(',')
- props = properties()
- if id_or_ids.size > props['person.max.ids']
- persons = []
- id_or_ids.each_slice(props['person.max.ids']) do |ids_slice|
- persons = persons + person(ids_slice,options)
- end
- return persons
- end
- else
- multiple_ids = false
- id = id_or_ids.to_s
- if id == 'me'
- url = Base + 'person'
- else
- url = Base + 'person/' + id
- end
- end
- url += add_querystring(options)
- response = @fs_communicator.get(url)
- familytree = Org::Familysearch::Ws::Familytree::V2::Schema::FamilyTree.from_json JSON.parse(response.body)
- if multiple_ids
- return familytree.persons
- else
- person = familytree.persons.find{|p| p.requestedId == id }
- person ||= familytree.persons.first if id == 'me'
- return person
- end
- end
-
- def save_person(person)
- if person.id.nil?
- url = Base + 'person'
- else
- url = Base + 'person/' + person.id
- end
- familytree = Org::Familysearch::Ws::Familytree::V2::Schema::FamilyTree.new
- familytree.persons = [person]
- response = @fs_communicator.post(url,familytree.to_json)
- res_familytree = Org::Familysearch::Ws::Familytree::V2::Schema::FamilyTree.from_json JSON.parse(response.body)
- person = res_familytree.persons.first
- return person
- end
-
- # ====Params
- # <tt>search_params</tt> - A hash of search parameters matching API doc
- def search(search_params)
- url = Base + 'search'
- url += add_querystring(search_params)
- response = @fs_communicator.get(url)
- familytree = Org::Familysearch::Ws::Familytree::V2::Schema::FamilyTree.from_json JSON.parse(response.body)
- # require 'pp'
- # pp familytree
- familytree.searches[0]
- end
-
- # ====Params
- # <tt>id_or_hash</tt> - Either an ID or a hash of match parameters matching API doc
- # <tt>hash</tt> - if the first parameter is an ID, then this will contain the hash
- # of match parameters.
- def match(id_or_hash, hash={})
- url = Base + 'match'
- if id_or_hash.kind_of? String
- id = id_or_hash
- url += "/#{id}"
- params_hash = hash
- elsif id_or_hash.kind_of? Hash
- id = nil
- params_hash = id_or_hash
- else
- raise ArgumentError, "first parameter must be a kind of String or Hash"
- end
- url += add_querystring(params_hash) #"?" + FsUtils.querystring_from_hash(params_hash) unless params_hash.empty?
- response = @fs_communicator.get(url)
- familytree = Org::Familysearch::Ws::Familytree::V2::Schema::FamilyTree.from_json JSON.parse(response.body)
- # require 'pp'
- # pp familytree
- familytree.matches[0]
- end
-
- # ====Params
- # * <tt>base_id</tt> - The root person for creating the relationship
- # * <tt>options</tt> - Should include either :parent, :spouse, or :child. :lineage and :event is optional
- #
- # :lineage can be set to the following values:
- # * 'Biological'
- # * 'Adoptive'
- # * 'Foster'
- # * 'Guardianship'
- # * 'Step'
- # * 'Other'
- #
- # :event should be a hash with the following values
- # ** :type - "Marriage", etc. (REQUIRED)
- # ** :place - "Utah, United States" (optional)
- # ** :date - "Nov 2009"
- #
- # :ordinance should be a hash with the following values
- # ** :type - "Sealing_to_Spouse", etc. (REQUIRED)
- # ** :place - "Utah, United States" (optional)
- # ** :date - "Nov 2009"
- # ** :temple - 'SLAKE'
- #
- # If the :lineage is set, the parent-child relationships will be written via a characteristic.
- # Otherwise, an exists assertion will be created to just establish the relationship.
- # ====Example
- #
- # communicator.familytree_v2.write_relationship 'KWQS-BBQ', :parent => 'KWQS-BBT', :lineage => 'Biological'
- # communicator.familytree_v2.write_relationship 'KWQS-BBQ', :parent => 'KWQS-BBT', :lineage => 'Adoptive'
- # communicator.familytree_v2.write_relationship 'KWQS-BBQ', :spouse => 'KWRT-BBZ', :event => {:type => 'Marriage', :date => '15 Aug 1987', :place => 'Utah, United States'}
- def write_relationship(base_id,options)
-
- relationship_type = get_relationship_type(options)
- with_id = options[relationship_type.to_sym]
-
- # Get the existing person/relationship or create a new person
- unless person = relationship(base_id,options.merge({:events => 'none'}))
- person = Org::Familysearch::Ws::Familytree::V2::Schema::Person.new
- person.id = base_id
- end
-
- # Add the relationship to the person with all of the correct options
- r_options = {:type => relationship_type, :with => with_id}
- r_options[:event] = options[:event] if options[:event]
- r_options[:ordinance] = options[:ordinance] if options[:ordinance]
- r_options[:lineage] = options[:lineage] if options[:lineage]
- person.create_relationship r_options
-
- # Create the payload
- familytree = Org::Familysearch::Ws::Familytree::V2::Schema::FamilyTree.new
- familytree.persons = [person]
-
- # Get the most current related ID for the URI
- rels = person.relationships.get_relationships_of_type(r_options[:type])
- rel = rels.find{|r|r.id == r_options[:with] || r.requestedId == r_options[:with]}
- related_id = rel.id
- url = "#{Base}person/#{base_id}/#{relationship_type}/#{related_id}"
-
- # Post the response and return the resulting person/relationship record from response
- response = @fs_communicator.post(url,familytree.to_json)
- res_familytree = Org::Familysearch::Ws::Familytree::V2::Schema::FamilyTree.from_json JSON.parse(response.body)
- person = res_familytree.persons.first
- return person
- end
-
- # ====Params
- # * <tt>base_id</tt> - The root person for creating the relationship
- # * <tt>options</tt> - Should include either :parent, :spouse, or :child. :lineage and :event is optional.
- # Other Relationship Read parameters may be included in options such as :events => 'all',
- # :characteristics => 'all', etc.
- #
- # If the :lineage is set, the parent-child relationships will be written via a characteristic.
- # Otherwise, an exists assertion will be created to just establish the relationship.
- # ====Example
- #
- # communicator.familytree_v2.relationship 'KWQS-BBQ', :parent => 'KWQS-BBT'
- # communicator.familytree_v2.relationship 'KWQS-BBQ', :parent => 'KWQS-BBT'
- def relationship(base_id,options)
- begin
- r_type = get_relationship_type(options)
- with_id = options[r_type.to_sym]
- url = "#{Base}person/#{base_id}/#{r_type}/#{with_id}"
- options.reject!{|k,v| k.to_s == 'spouse'}
- url += add_querystring(options)
- res = @fs_communicator.get(url)
- familytree = Org::Familysearch::Ws::Familytree::V2::Schema::FamilyTree.from_json JSON.parse(res.body)
- person = familytree.persons.find{|p|p.requestedId == base_id}
- return person
- rescue RubyFsStack::NotFound
- return nil
- end
- end
-
- # Writes a note attached to the value ID of the specific person or relationship.
- #
- # ====Params
- # * <tt>options</tt> - Options for the note including the following:
- # * <tt>:personId</tt> - the person ID if attaching to a person assertion.
- # * <tt>:spouseIds</tt> - an Array of spouse IDs if creating a note attached to a spouse
- # relationship assertion.
- # * <tt>:parentIds</tt> - an Array of parent IDs if creating a note attached to a parent
- # relationship assertion. If creating a note for a child-parent or parent-child
- # relationship, you will need only one parent ID in the array along with a :childId option.
- # * <tt>:childId</tt> - a child ID.
- # * <tt>:text</tt> - the text of the note (required).
- # * <tt>:assertionId</tt> - the valueId of the assertion you are attaching this note to.
- #
- def write_note(options)
- url = "#{Base}note"
- note = Org::Familysearch::Ws::Familytree::V2::Schema::Note.new
- note.build(options)
- familytree = Org::Familysearch::Ws::Familytree::V2::Schema::FamilyTree.new
- familytree.notes = [note]
- res = @fs_communicator.post(url,familytree.to_json)
- familytree = Org::Familysearch::Ws::Familytree::V2::Schema::FamilyTree.from_json JSON.parse(res.body)
- return familytree.notes.first
- end
-
- # Combines person into a new person
- #
- # ====Params
- # * <tt>person_array</tt> - an array of person IDs.
- def combine(person_array)
- url = Base + 'person'
- version_persons = self.person person_array, :genders => 'none', :events => 'none', :names => 'none'
- combine_person = Org::Familysearch::Ws::Familytree::V2::Schema::Person.new
- combine_person.create_combine(version_persons)
- familytree = Org::Familysearch::Ws::Familytree::V2::Schema::FamilyTree.new
- familytree.persons = [combine_person]
- res = @fs_communicator.post(url,familytree.to_json)
- familytree = Org::Familysearch::Ws::Familytree::V2::Schema::FamilyTree.from_json JSON.parse(res.body)
- return familytree.persons[0]
- end
-
- def pedigree(id_or_ids)
- if id_or_ids.kind_of? Array
- multiple_ids = true
- url = Base + 'pedigree/' + id_or_ids.join(',')
- else
- multiple_ids = false
- id = id_or_ids.to_s
- if id == 'me'
- url = Base + 'pedigree'
- else
- url = Base + 'pedigree/' + id
- end
- end
- # url += add_querystring(options)
- response = @fs_communicator.get(url)
- familytree = parse_response(response)
- if multiple_ids
- return familytree.pedigrees
- else
- pedigree = familytree.pedigrees.find{|p| p.requestedId == id }
- pedigree ||= familytree.pedigrees.first if id == 'me'
- return pedigree
- end
- end
-
- # ===params
- # <tt>id_or_ids</tt> should be a string of the persons identifier. For the 'me' person, use :me or 'me'. Can also accept an array of ID strings.
- # <tt>options</tt> accepts a hash of parameters as documented by the API.
- # For full parameter documentation, see DevNet[https://devnet.familysearch.org/docs/api-manual-reference-system/familytree-v2/r_api_family_tree_person_read_v2.html]
- #
- # ===Example
- # # communicator is an authenticated FsCommunicator object
- # # Request a person with no assertions, only the version.
- # p = communicator.familytree_v2.person :me, :names => 'none', :genders => 'none', :events => 'none'
- #
- # p.version # => '90194378772'
- # p.id # => 'KW3B-NNM'
- def contributor(id_or_ids)
- if id_or_ids.kind_of? Array
- multiple_ids = true
- url = Base + 'contributor/' + id_or_ids.join(',')
- props = properties()
- if id_or_ids.size > props['contributor.max.ids']
- contributors = []
- id_or_ids.each_slice(props['contributor.max.ids']) do |ids_slice|
- contributors = contributors + contributor(ids_slice)
- end
- return contributors
- end
- else
- multiple_ids = false
- id = id_or_ids.to_s
- if id == 'me'
- url = Base + 'contributor'
- else
- url = Base + 'contributor/' + id
- end
- end
- response = @fs_communicator.get(url)
- familytree = parse_response(response)
- if multiple_ids
- return familytree.contributors
- else
- return familytree.contributors.first
- end
- end
-
- def properties
- if @properties_hash
- return @properties_hash
- else
- url = Base + 'properties'
- response = @fs_communicator.get(url)
- familytree = parse_response(response)
- @properties_hash = {}
- familytree.properties.each do |prop|
- @properties_hash[prop.name] = prop.value.to_i
- end
- return @properties_hash
- end
- end
-
- private
-
- def parse_response(response)
- Org::Familysearch::Ws::Familytree::V2::Schema::FamilyTree.from_json JSON.parse(response.body)
- end
- #options will either have a :parent, :child, or :spouse key. We need to find which one
- def get_relationship_type(options)
- keys = options.keys.collect{|k|k.to_s}
- key = keys.find{|k| ['parent','child','spouse'].include? k}
- key
- end
-
- def add_querystring(options)
- params = options.reject{|k,v| ['parent','child','lineage','event'].include? k.to_s }
- (params.empty?) ? '' : "?" + FsUtils.querystring_from_hash(params)
- end
- end
-
-end
-
-# Mix in the module so that the fs_familytree_v1 can be called
-class FsCommunicator
- include FamilytreeV2
-end
-
-
-
-module Org::Familysearch::Ws::Familytree::V2::Schema
-
- class GenderAssertion
- def add_value(value)
- self.value = GenderValue.new
- self.value.type = value
- end
- end
-
- class NameForm
- def set_name(name)
- split_pieces = name.match(/(.*)\/(.*)\//)
- # if there is a name like John Jacob /Felch/, split to name pieces, otherwise use fullText
- if split_pieces
- given_pieces = split_pieces[1]
- family_pieces = split_pieces[2]
- self.pieces = given_pieces.split(" ").collect do |piece|
- p = NamePiece.new
- p.type = "Given"
- p.postdelimiters = " "
- p.value = piece
- p
- end
- self.pieces = self.pieces + family_pieces.split(" ").collect do |piece|
- p = NamePiece.new
- p.type = "Family"
- p.predelimiters = ""
- p.value = piece
- p
- end
- else
- self.fullText = name
- end
- end
-
- def surname
- if self.pieces.nil?
- (self.fullText.nil?) ? nil : self.fullText.split(' ').last
- else
- piece = self.pieces.find{|piece|piece.type == 'Family'}
- (piece.nil?) ? nil : piece.value
- end
- end
-
- def buildFullText
- if self.pieces.nil?
- return ''
- else
- self.pieces.collect{|piece| "#{piece.predelimiters}#{piece.value}#{piece.postdelimiters}"}.join('')
- end
- end
- end
-
- class NameValue
- def add_form(value)
- self.forms = []
- f = NameForm.new
- f.set_name(value)
- self.forms << f
- end
-
- end
-
- class NameAssertion
- def add_value(value)
- self.value = NameValue.new
- self.value.add_form(value)
- end
-
- def select(value_id)
- self.action = 'Select'
- self.value = AssertionValue.new
- self.value.id = value_id
- end
- end
-
- class EventValue
- def add_date(value)
- self.date = GenDate.new
- self.date.original = value
- end
-
- def add_place(value)
- self.place = Place.new
- self.place.original = value
- end
- end
-
- class EventAssertion
- # ====Params
- # * <tt>options</tt> - requires a :type option and accepts an (optional) :date and :place option
- #
- # ====Example
- #
- # person.add_birth :date => '12 Aug 1902', :place => 'United States'
- def add_value(options)
- raise ArgumentError, "missing option[:type]" if options[:type].nil?
- self.value = EventValue.new
- self.value.type = options[:type]
- self.value.add_date(options[:date]) if options[:date]
- self.value.add_place(options[:place]) if options[:place]
- end
-
- def select(type,value_id)
- self.value = EventValue.new
- self.value.id = value_id
- self.value.type = type
- self.action = 'Select'
- end
-
- # To make porting code from v1 to v2 easier, date will reference
- # value.date
- def date
- value.date
- end
-
- # To make porting code from v1 to v2 easier, date will reference
- # value.date
- def place
- value.place
- end
- end
-
- class OrdinanceType
-
- # Born in Covenant -> Possibly needs to be changed to no underscores
- # Born_in_Covenant = "Born_in_Covenant"
-
- # Override the incorrect constants in the enunciate library
- with_warnings_suppressed do
- # Sealing to parents.
- Sealing_to_Parents = "Sealing to Parents"
-
- # Sealing to spouse.
- Sealing_to_Spouse = "Sealing to Spouse"
- end
- end
-
-
- class OrdinanceValue
-
- def add_date(value)
- self.date = GenDate.new
- self.date.original = value
- end
-
- def add_place(value)
- self.place = Place.new
- self.place.original = value
- end
-
- def add_mother(mother_id)
- add_parent('Female',mother_id)
- end
-
- def add_father(father_id)
- add_parent('Male',father_id)
- end
-
- def add_parent(gender, id)
- add_parents!
- parent = PersonReference.new
- parent.id = id
- parent.gender = gender
- self.parents << parent
- end
-
- private
- def add_parents!
- self.parents ||= []
- end
-
- end
-
- class OrdinanceAssertion
-
- def add_value(options)
- raise ArgumentError, "missing option[:type]" if options[:type].nil?
- raise ArgumentError, "missing option[:place]" if options[:place].nil?
- self.value = OrdinanceValue.new
- self.value.type = options[:type]
- self.value.add_date(options[:date]) if options[:date]
- self.value.add_place(options[:place]) if options[:place]
- self.value.temple = options[:temple] if options[:temple]
- if options[:type] == OrdinanceType::Sealing_to_Parents
- self.value.add_mother(options[:mother])
- self.value.add_father(options[:father])
- end
- end
- end
-
- class PersonAssertions
- def add_gender(value)
- self.genders ||= []
- g = GenderAssertion.new
- g.add_value(value)
- self.genders << g
- end
-
- def add_name(value)
- self.names ||= []
- n = NameAssertion.new
- n.add_value(value)
- self.names << n
- end
-
- def select_name(value_id)
- self.names ||= []
- n = NameAssertion.new
- n.select(value_id)
- self.names << n
- end
-
- def add_event(options)
- self.events ||= []
- e = EventAssertion.new
- e.add_value(options)
- self.events << e
- end
-
- def select_event_summary(type,value_id)
- self.events ||= []
- e = EventAssertion.new
- e.select(type,value_id)
- self.events << e
- end
-
- def add_ordinance(options)
- self.ordinances ||= []
- o = OrdinanceAssertion.new
- o.add_value(options)
- self.ordinances << o
- end
-
- end
-
- class CharacteristicAssertion
- # ====Params
- # * <tt>options</tt> - same as RelationshipAssertions#add_characteristic
- def add_value(options)
- self.value = CharacteristicValue.new
- self.value.type = options[:type]
- self.value.lineage = options[:lineage] if options[:lineage]
- end
- end
-
- class ExistsAssertion
- def add_value
- self.value = ExistsValue.new
- end
- end
-
- class RelationshipAssertions
- # ====Params
- # * <tt>options</tt> - :type ('Lineage' or valid CharacteristicType), :lineage => 'Biological', etc.
- def add_characteristic(options)
- self.characteristics ||= []
- characteristic = CharacteristicAssertion.new
- characteristic.add_value(options)
- self.characteristics << characteristic
- end
-
- # ====Params
- # * <tt>options</tt> - Accepts the following options
- # ** :type - 'Marriage', etc. REQUIRED
- # ** :date - 'Utah, United States' (optional)
- # ** :place - '16 Nov 1987' (optional)
- def add_event(options)
- self.events ||= []
- event = EventAssertion.new
- event.add_value(options)
- self.events << event
- end
-
- # ====Params
- # * <tt>options</tt> - Accepts the following options
- # ** :type - 'Sealing_to_Spouse', etc. REQUIRED
- # ** :date - 'Utah, United States' (optional)
- # ** :place - '16 Nov 1987' (optional)
- # ** :temple - 'SLAKE'
- def add_ordinance(options)
- self.ordinances ||= []
- ordinance = OrdinanceAssertion.new
- ordinance.add_value(options)
- self.ordinances << ordinance
- end
-
- def add_exists
- self.exists ||= []
- exist = ExistsAssertion.new
- exist.add_value
- self.exists << exist
- end
- end
-
- class Relationship
- def add_lineage_characteristic(lineage)
- add_assertions!
- self.assertions.add_characteristic(:type => 'Lineage', :lineage => lineage)
- end
-
- def add_exists
- add_assertions!
- self.assertions.add_exists
- end
-
- # ====Params
- # * <tt>event_hash</tt> - Accepts the following options
- # ** :type - 'Marriage', etc. REQUIRED
- # ** :date - 'Utah, United States' (optional)
- # ** :place - '16 Nov 1987' (optional)
- def add_event(event_hash)
- add_assertions!
- self.assertions.add_event(event_hash)
- end
-
- # ====Params
- # * <tt>ordinance_hash</tt> - Accepts the following options
- # ** :type - 'Sealing_to_Spouse', etc. REQUIRED
- # ** :date - 'Utah, United States' (optional)
- # ** :place - '16 Nov 1987' (optional)
- # ** :temple - 'SLAKE'
- def add_ordinance(ordinance_hash)
- add_assertions!
- self.assertions.add_ordinance(ordinance_hash)
- end
-
- private
- def add_assertions!
- self.assertions ||= RelationshipAssertions.new
- end
- end
-
- class FamilyReference
- def select_spouse(spouse_id)
- add_parents!
- self.action = 'Select'
- parent = PersonReference.new
- parent.id = spouse_id
- self.parents << parent
- end
-
- private
- def add_parents!
- self.parents ||= []
- end
- end
-
- class ParentsReference
- def select_parent(parent_id, gender)
- add_parents!
- self.action = 'Select'
- parent = PersonReference.new
- parent.gender = gender
- parent.id = parent_id
- self.parents << parent
- end
-
- private
- def add_parents!
- self.parents ||= []
- end
- end
-
- class PersonRelationships
- def initialize
- @parents = []
- @spouses = []
- @children = []
- end
-
- # ====Params
- # * <tt>options</tt> - requires the following:
- # ** :type - 'parent', 'child', 'spouse'
- # ** :with - ID of the person with whom you are making the relationship
- # ** :lineage (optional) - 'Biological', 'Adoptive', etc.
- # ** :event - a hash with values {:type => 'Marriage', :date => '15 Nov 2007', :place => 'Utah, United States'}
- # ** :ordinance - a hash with values {:date => '15 Nov 2007', :temple => 'SLAKE', :place => 'Utah, United States', :type => "Sealing_to_Spouse"}
- def add_relationship(options)
- relationship = self.get_relationships_of_type(options[:type]).find{|r|r.id == options[:with] || r.requestedId == options[:with]}
- if relationship.nil?
- relationship = Relationship.new
- relationship.id = options[:with]
- end
- if options[:lineage]
- relationship.add_lineage_characteristic(options[:lineage]) if options[:lineage]
- else
- relationship.add_exists
- end
- if options[:event]
- relationship.add_event(options[:event])
- end
- if options[:ordinance]
- relationship.add_ordinance(options[:ordinance])
- end
- s_command = set_command(options[:type])
- self.send(s_command.to_sym,[relationship])
- end
-
- # ====Params
- # * type - should be 'child', 'spouse', or 'parent'
- def get_relationships_of_type(type)
- g_command = get_command(type)
- relationships = self.send(g_command.to_sym)
- end
-
- # Overriding the Enunciate code because of a bug (parents, spouses, and children were not pluralized)
- # the json hash for this PersonRelationships
- def to_jaxb_json_hash
- _h = {}
- if !parents.nil?
- _ha = Array.new
- parents.each { | _item | _ha.push _item.to_jaxb_json_hash }
- _h['parents'] = _ha
- end
- if !spouses.nil?
- _ha = Array.new
- spouses.each { | _item | _ha.push _item.to_jaxb_json_hash }
- _h['spouses'] = _ha
- end
- if !children.nil?
- _ha = Array.new
- children.each { | _item | _ha.push _item.to_jaxb_json_hash }
- _h['children'] = _ha
- end
- return _h
- end
-
- # Overriding the Enunciate code because of a bug
- #initializes this PersonRelationships with a json hash
- def init_jaxb_json_hash(_o)
- if !_o['parents'].nil?
- @parents = Array.new
- _oa = _o['parents']
- _oa.each { | _item | @parents.push Org::Familysearch::Ws::Familytree::V2::Schema::Relationship.from_json(_item) }
- end
- if !_o['spouses'].nil?
- @spouses = Array.new
- _oa = _o['spouses']
- _oa.each { | _item | @spouses.push Org::Familysearch::Ws::Familytree::V2::Schema::Relationship.from_json(_item) }
- end
- if !_o['children'].nil?
- @children = Array.new
- _oa = _o['children']
- _oa.each { | _item | @children.push Org::Familysearch::Ws::Familytree::V2::Schema::Relationship.from_json(_item) }
- end
- end
-
- private
- def get_command(type)
- (type.to_s == 'child') ? 'children' : "#{type}s"
- end
-
- def set_command(type)
- get_command(type)+"="
- end
- end
-
- class Person
-
- def full_names
- if assertions && assertions.names
- return assertions.names.collect do |name|
- (name.value.forms[0].fullText.nil?) ? name.value.forms[0].buildFullText : name.value.forms[0].fullText
- end
- else
- []
- end
- end
-
- def full_name
- self.full_names.first
- end
-
- def surnames
- if assertions && assertions.names
- names = assertions.names.collect do |name|
- name.value.forms[0].surname
- end
- return names.reject{|n|n.nil?}
- else
- []
- end
- end
-
- def surname
- surnames.first
- end
-
- def gender
- if assertions && assertions.genders && assertions.genders[0] && assertions.genders[0].value
- assertions.genders[0].value.type
- else
- nil
- end
- end
-
- # Convenience method for adding the gender.
- #
- # ====Params
- # <tt>value</tt> - 'Male' or 'Female'
- def add_gender(value)
- add_assertions!
- assertions.add_gender(value)
- end
-
- # Convenience method for adding a name. It fills in the necessary
- # structure underneath to create the name.
- #
- # ====Params
- # <tt>value</tt> - the name to be added
- #
- # ====Example
- #
- # person.add_name 'Parker Felch' # Sets the fullText to "Parker Felch"
- # person.add_name 'Parker Jones /Felch/' # Does not set the fullText, but sets the name pieces.
- def add_name(value)
- add_assertions!
- assertions.add_name(value)
- end
-
- # Select the name for the summary view. This should be called on a Person record that
- # contains a person id and version.
- #
- # ====Params
- # <tt>value_id</tt> - the value id of a name assertion that you would like to set as the summary
- #
- # ===Example
- # person = com.familytree_v2.person 'KWQS-BBR', :names => 'none', :genders => 'none', :events => 'none'
- # person.select_name_summary('1000134')
- # com.familytree_v2.save_person person
- #
- # This is the recommended approach, to start with a "Version" person (no names, genders, or events)
- def select_name_summary(value_id)
- add_assertions!
- assertions.select_name(value_id)
- end
-
- def births
- select_events('Birth')
- end
-
- # It should return the selected birth assertion unless it is
- # not set in which case it will return the first
- def birth
- birth = births.find{|b|!b.selected.nil?}
- birth ||= births[0]
- birth
- end
-
- def deaths
- select_events('Death')
- end
-
- # It should return the selected death assertion unless it is
- # not set in which case it will return the first
- def death
- death = deaths.find{|b|!b.selected.nil?}
- death ||= deaths[0]
- death
- end
-
- # This should only be called on a person containing relationships
- def marriages(for_person)
- select_spouse_events('Marriage',for_person)
- end
-
- # This should only be called on a person containing relationships
- def divorces(for_person)
- select_spouse_events('Divorce',for_person)
- end
-
- # Add an event with type of Birth
- #
- # ====Params
- # * <tt>options</tt> - accepts a :date and :place option
- #
- # ====Example
- #
- # person.add_birth :date => '12 Aug 1902', :place => 'United States'
- def add_birth(options)
- add_assertions!
- options[:type] = 'Birth'
- assertions.add_event(options)
- end
-
- # Select the birth for the summary view. This should be called on a Person record that
- # contains a person id and version.
- #
- # ====Params
- # <tt>value_id</tt> - the value id of a birth assertion that you would like to set as the summary
- #
- # ===Example
- # person = com.familytree_v2.person 'KWQS-BBR', :names => 'none', :genders => 'none', :events => 'none'
- # person.select_birth_summary('1000134')
- # com.familytree_v2.save_person person
- #
- # This is the recommended approach, to start with a "Version" person (no names, genders, or events)
- def select_birth_summary(value_id)
- add_assertions!
- assertions.select_event_summary('Birth',value_id)
- end
-
- # Add an event with type of Birth
- #
- # ====Params
- # * <tt>options</tt> - accepts a :date and :place option
- #
- # ====Example
- #
- # person.add_birth :date => '12 Aug 1902', :place => 'United States'
- def add_death(options)
- add_assertions!
- options[:type] = 'Death'
- assertions.add_event(options)
- end
-
- # Select the death for the summary view. This should be called on a Person record that
- # contains a person id and version.
- #
- # ====Params
- # <tt>value_id</tt> - the value id of a death assertion that you would like to set as the summary
- #
- # ===Example
- # person = com.familytree_v2.person 'KWQS-BBR', :names => 'none', :genders => 'none', :events => 'none'
- # person.select_death_summary('1000134')
- # com.familytree_v2.save_person person
- #
- # This is the recommended approach, to start with a "Version" person (no names, genders, or events)
- def select_death_summary(value_id)
- add_assertions!
- assertions.select_event_summary('Death',value_id)
- end
-
- # Select the mother for the summary view. This should be called on a Person record that
- # contains a person id and version.
- #
- # Make sure you set both the mother and father before saving the person. Otherwise you will
- # set a single parent as the summary.
- #
- # ====Params
- # <tt>person_id</tt> - the person id of the mother that you would like to set as the summary
- #
- # ===Example
- # person = com.familytree_v2.person 'KWQS-BBR', :names => 'none', :genders => 'none', :events => 'none'
- # person.select_mother_summary('KWQS-BBQ')
- # person.select_father_summary('KWQS-BBT')
- # com.familytree_v2.save_person person
- #
- # This is the recommended approach, to start with a "Version" person (no names, genders, or events)
- def select_mother_summary(person_id)
- add_parents!
- couple = parents[0] || ParentsReference.new
- couple.select_parent(person_id,'Female')
- parents[0] = couple
- end
-
- # Select the father for the summary view. This should be called on a Person record that
- # contains a person id and version.
- #
- # Make sure you set both the mother and father before saving the person. Otherwise you will
- # set a single parent as the summary.
- #
- # ====Params
- # <tt>person_id</tt> - the person id of the father that you would like to set as the summary
- #
- # ===Example
- # person = com.familytree_v2.person 'KWQS-BBR', :names => 'none', :genders => 'none', :events => 'none'
- # person.select_father_summary('KWQS-BBQ')
- # person.select_mother_summary('KWQS-BBT')
- # com.familytree_v2.save_person person
- #
- # This is the recommended approach, to start with a "Version" person (no names, genders, or events)
- def select_father_summary(person_id)
- add_parents!
- couple = parents[0] || ParentsReference.new
- couple.select_parent(person_id,'Male')
- parents[0] = couple
- end
-
- # Select the spouse for the summary view. This should be called on a Person record that
- # contains a person id and version.
- #
- # ====Params
- # <tt>person_id</tt> - the person id of the spouse that you would like to set as the summary
- #
- # ===Example
- # person = com.familytree_v2.person 'KWQS-BBR', :names => 'none', :genders => 'none', :events => 'none'
- # person.select_spouse_summary('KWQS-BBQ')
- # com.familytree_v2.save_person person
- #
- # This is the recommended approach, to start with a "Version" person (no names, genders, or events)
- def select_spouse_summary(person_id)
- add_families!
- family = FamilyReference.new
- family.select_spouse(person_id)
- families << family
- end
-
- def baptisms
- select_ordinances('Baptism')
- end
-
- def confirmations
- select_ordinances('Confirmation')
- end
-
- def initiatories
- select_ordinances('Initiatory')
- end
-
- def endowments
- select_ordinances('Endowment')
- end
-
- def sealing_to_parents
- select_ordinances(OrdinanceType::Sealing_to_Parents)
- end
-
- def sealing_to_spouses(id)
- select_relationship_ordinances(:relationship_type => 'spouse', :id => id, :type => OrdinanceType::Sealing_to_Spouse)
- end
-
- # Add a baptism ordinance
- #
- # ====Params
- # * <tt>options</tt> - accepts a :date, :place, and :temple option
- #
- # ====Example
- #
- # person.add_baptism :date => '14 Aug 2009', :temple => 'SGEOR', :place => 'Salt Lake City, Utah'
- def add_baptism(options)
- add_assertions!
- options[:type] = 'Baptism'
- assertions.add_ordinance(options)
- end
-
- # Add a confirmation ordinance
- #
- # ====Params
- # * <tt>options</tt> - accepts a :date, :place, and :temple option
- #
- # ====Example
- #
- # person.add_confirmation :date => '14 Aug 2009', :temple => 'SGEOR', :place => 'Salt Lake City, Utah'
- def add_confirmation(options)
- add_assertions!
- options[:type] = 'Confirmation'
- assertions.add_ordinance(options)
- end
-
- # Add a initiatory ordinance
- #
- # ====Params
- # * <tt>options</tt> - accepts a :date, :place, and :temple option
- #
- # ====Example
- #
- # person.add_initiatory :date => '14 Aug 2009', :temple => 'SGEOR', :place => 'Salt Lake City, Utah'
- def add_initiatory(options)
- add_assertions!
- options[:type] = 'Initiatory'
- assertions.add_ordinance(options)
- end
-
- # Add a endowment ordinance
- #
- # ====Params
- # * <tt>options</tt> - accepts a :date, :place, and :temple option
- #
- # ====Example
- #
- # person.add_endowment :date => '14 Aug 2009', :temple => 'SGEOR', :place => 'Salt Lake City, Utah'
- def add_endowment(options)
- add_assertions!
- options[:type] = 'Endowment'
- assertions.add_ordinance(options)
- end
-
- # Add a sealing to parents ordinance
- #
- # ====Params
- # * <tt>options</tt> - accepts a :date, :place, :temple, :mother, and :father option
- #
- # ====Example
- #
- # person.add_sealing_to_parents :date => '14 Aug 2009', :temple => 'SGEOR', :place => 'Salt Lake City, Utah'
- def add_sealing_to_parents(options)
- raise ArgumentError, ":mother option is required" if options[:mother].nil?
- raise ArgumentError, ":father option is required" if options[:father].nil?
- add_assertions!
- options[:type] = OrdinanceType::Sealing_to_Parents
- assertions.add_ordinance(options)
- end
-
- # This method should really only be called from FamilytreeV2::Communicator#write_relationships
- #
- # ====Params
- # * <tt>options</tt> - requires the following:
- # * :type - 'parent', 'child', 'spouse'
- # * :with - ID of the person with whom you are making the relationship
- # * :lineage (optional) - 'Biological', 'Adoptive', etc.
- # * :event - a hash with values {:type => 'Marriage', :date => '15 Nov 2007', :place => 'Utah, United States'}
- def create_relationship(options)
- raise ArgumentError, ":type option is required" if options[:type].nil?
- raise ArgumentError, ":with option is required" if options[:with].nil?
- add_relationships!
- self.relationships.add_relationship(options)
- end
-
- # This method should only be called from FamilytreeV2::Communicator#combine
- #
- # ====Params
- # * <tt>persons</tt> - an array of person objects. All persons must have an id and version
- def create_combine(persons)
- self.personas = Org::Familysearch::Ws::Familytree::V2::Schema::PersonPersonas.new
- self.personas.personas = persons.map do |person|
- persona = Org::Familysearch::Ws::Familytree::V2::Schema::PersonPersona.new
- persona.id = person.id
- persona.version = person.version
- persona
- end
- end
-
- def father_id
- parent_id('Male')
- end
-
- def mother_id
- parent_id('Female')
- end
-
- def spouse_id
- if families && families[0] && families[0].parents
- spouse_ref = families[0].parents.find{|p|p.id != self.id}
- spouse_ref.id if spouse_ref
- end
- end
-
- private
-
- def parent_id(gender)
- if parents && parents[0]
- parent_ref = parents[0].parents.find{|p|p.gender == gender}
- parent_ref.id if parent_ref
- end
- end
-
- def add_parents!
- self.parents ||= []
- end
-
- def add_families!
- self.families ||= []
- end
-
- def add_relationships!
- self.relationships ||= PersonRelationships.new
- end
-
- def add_assertions!
- if assertions.nil?
- self.assertions = PersonAssertions.new
- end
- end
-
- def select_events(type)
- if assertions && assertions.events
- assertions.events.select{|e| e.value.type == type}
- else
- []
- end
- end
-
- def select_spouse_events(type,for_person)
- spouse = relationships.spouses.find{|s|s.requestedId=for_person}
- if spouse.assertions && spouse.assertions.events
- spouse.assertions.events.select{|e| e.value.type == type}
- else
- []
- end
- end
-
- def select_ordinances(type)
- if assertions && assertions.ordinances
- assertions.ordinances.select{|e| e.value.type == type}
- else
- []
- end
- end
-
- # only ordinance type is Sealing_to_Spouse
- def select_relationship_ordinances(options)
- raise ArgumentError, ":id required" if options[:id].nil?
- if self.relationships
- spouse_relationship = self.relationships.spouses.find{|s|s.id == options[:id]}
- if spouse_relationship && spouse_relationship.assertions && spouse_relationship.assertions.ordinances
- spouse_relationship.assertions.ordinances
- else
- []
- end
- end
- end
-
- end
-
- class SearchPerson
- alias :name :full_name
- alias :ref :id
- def events
- (assertions && assertions.events) ? assertions.events : []
- end
-
- # Always will return nil. Method is here for v1 backwards compatibility
- def marriage
- nil
- end
- end
-
- class SearchResult
- alias :ref :id
-
- def father
- parents.find{|p|p.gender == 'Male'}
- end
-
- def mother
- parents.find{|p|p.gender == 'Female'}
- end
- end
-
- class PedigreePerson < Person
- attr_accessor :pedigree
-
- def initialize(pedigree = nil, person = nil)
- if person
- @id = person.id
- # @version = person.version if person.version
- @assertions = person.assertions if person.assertions
- @families = person.families if person.families
- @parents = person.parents if person.parents
- @properties = person.properties if person.properties
- end
- if pedigree
- @pedigree = pedigree
- end
- end
-
- def father
- pedigree.get_person(father_id)
- end
-
- def mother
- pedigree.get_person(mother_id)
- end
-
- end
-
- class Pedigree
- attr_accessor :person_hash
-
- def initialize
- @person_hash = {}
- @persons = []
- end
-
- def injest(pedigree)
- @person_hash.merge!(pedigree.person_hash)
- graft_persons_to_self(pedigree.persons)
- @persons = @persons + pedigree.persons
- end
-
- def <<(person)
- p = PedigreePerson.new(self, person)
- @persons << p
- @person_hash[p.id] = p
- end
-
- def continue_nodes
- @persons.select do |person|
- (!person.mother_id.nil? && person.mother.nil?) || (!person.father_id.nil? && person.father.nil?)
- end
- end
-
- def continue_node_ids
- continue_nodes.collect{|n|n.id}
- end
-
- def continue_ids
- cns = continue_nodes
- father_ids = cns.select{|n|!n.father_id.nil?}.collect{|n|n.father_id}
- mother_ids = cns.select{|n|!n.mother_id.nil?}.collect{|n|n.mother_id}
- father_ids + mother_ids
- end
-
- def get_person(id)
- @person_hash[id]
- end
-
- def person_ids
- @persons.collect{|p|p.id}
- end
-
- def init_jaxb_json_hash(_o)
- @id = String.from_json(_o['id']) unless _o['id'].nil?
- @requestedId = String.from_json(_o['requestedId']) unless _o['requestedId'].nil?
- if !_o['persons'].nil?
- @persons = Array.new
- _oa = _o['persons']
- _oa.each do | _item |
- pedigree_person = Org::Familysearch::Ws::Familytree::V2::Schema::PedigreePerson.from_json(_item)
- pedigree_person.pedigree = self
- @persons.push pedigree_person
- @person_hash[pedigree_person.id] = pedigree_person
- end
- end
- end
-
- def root
- persons.first
- end
-
- private
- def graft_persons_to_self(persons_to_graft)
- persons_to_graft.each do |person|
- person.pedigree = self
- end
- end
-
- end
-
- class Note
-
- #Builds out the elements needed for the note.
- # ====Params
- # * <tt>options</tt> - Options for the note including the following:
- # * <tt>:personId</tt> - the person ID if attaching to a person assertion.
- # * <tt>:spouseIds</tt> - an Array of spouse IDs if creating a note attached to a spouse
- # relationship assertion.
- # * <tt>:parentIds</tt> - an Array of parent IDs if creating a note attached to a parent
- # relationship assertion. If creating a note for a child-parent or parent-child
- # relationship, you will need only one parent ID in the array along with a :childId option.
- # * <tt>:childId</tt> - a child ID.
- # * <tt>:text</tt> - the text of the note (required).
- # * <tt>:assertionId</tt> - the valueId of the assertion you are attaching this note to.
- def build(options)
- if spouseIds = options[:spouseIds]
- self.spouses = spouseIds.collect do |id|
- s = Org::Familysearch::Ws::Familytree::V2::Schema::EntityReference.new
- s.id = id
- s
- end
- end
- if parentIds = options[:parentIds]
- self.parents = parentIds.collect do |id|
- p = Org::Familysearch::Ws::Familytree::V2::Schema::EntityReference.new
- p.id = id
- p
- end
- end
- if personId = options[:personId]
- self.person = Org::Familysearch::Ws::Familytree::V2::Schema::EntityReference.new
- self.person.id = personId
- end
- if childId = options[:childId]
- self.child = Org::Familysearch::Ws::Familytree::V2::Schema::EntityReference.new
- self.child.id = childId
- end
- if assertionId = options[:assertionId]
- self.assertion = Org::Familysearch::Ws::Familytree::V2::Schema::EntityReference.new
- self.assertion.id = assertionId
- end
- if text = options[:text]
- self.text = text
- end
- end
- end
-end
\ No newline at end of file