/** * Copyright Intellectual Reserve, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.gedcomx; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.webcohesion.enunciate.metadata.Facet; import org.gedcomx.agent.Agent; import org.gedcomx.common.Attribution; import org.gedcomx.common.ResourceReference; import org.gedcomx.common.URI; import org.gedcomx.conclusion.*; import org.gedcomx.links.HypermediaEnabledData; import org.gedcomx.links.Link; import org.gedcomx.records.Collection; import org.gedcomx.records.Field; import org.gedcomx.records.RecordDescriptor; import org.gedcomx.rt.GedcomxConstants; import org.gedcomx.rt.GedcomxModelVisitor; import org.gedcomx.rt.MediaTypeDefinition; import org.gedcomx.rt.Model; import org.gedcomx.rt.json.JsonElementWrapper; import org.gedcomx.source.SourceCitation; import org.gedcomx.source.SourceDescription; import org.gedcomx.source.SourceReference; import org.gedcomx.types.RelationshipType; import org.gedcomx.types.ResourceType; import javax.xml.XMLConstants; import javax.xml.bind.annotation.*; import java.text.DateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; /** * <p>The GEDCOM X data formats define the serialization formats of the GEDCOM X conceptual model. The canonical documentation * is provided by the formal specification documents:</p> * * <ul> * <li><a href="https://github.com/FamilySearch/gedcomx/blob/master/specifications/conceptual-model-specification.md">The GEDCOM X Conceptual Model, Version 1.0</a></li> * <li><a href="https://github.com/FamilySearch/gedcomx/blob/master/specifications/json-format-specification.md">The GEDCOM X JSON Format, Version 1.0</a></li> * <li><a href="https://github.com/FamilySearch/gedcomx/blob/master/specifications/xml-format-specification.md">The GEDCOM X XML Format, Version 1.0</a></li> * </ul> * * <p>This documentation is provided as a non-normative reference guide.</p> * * @author Ryan Heaton */ @MediaTypeDefinition ( name = "GEDCOM X", description = "The GEDCOM X data formats define the serialization formats of the GEDCOM X conceptual model.", version = "1.0", xmlMediaType = GedcomxConstants.GEDCOMX_XML_MEDIA_TYPE, jsonMediaType = GedcomxConstants.GEDCOMX_JSON_MEDIA_TYPE, models = { @Model ( id = "gx", namespace = GedcomxConstants.GEDCOMX_NAMESPACE, label = "GEDCOM X Model", description = "The core model for all GEDCOM X data types and elements." ), @Model ( id = "types", namespace = GedcomxConstants.GEDCOMX_TYPES_NAMESPACE, label = "GEDCOM X Types", description = "The types model contains all of the types and constrained vocabulary for GEDCOM X data." ) } ) @XmlRootElement @JsonElementWrapper ( name = "gedcomx" ) @JsonInclude ( JsonInclude.Include.NON_NULL ) @XmlType ( name = "Gedcomx", propOrder = {"attribution", "persons", "relationships", "sourceDescriptions", "agents", "events", "places", "documents", "collections", "fields", "recordDescriptors"} ) public class Gedcomx extends HypermediaEnabledData { private String lang; private URI descriptionRef; private Attribution attribution; private List<Person> persons; private List<Relationship> relationships; private List<SourceDescription> sourceDescriptions; private List<Agent> agents; private List<Event> events; private List<PlaceDescription> places; private List<Document> documents; private List<Collection> collections; private List<Field> fields; private List<RecordDescriptor> recordDescriptors; /** * The language of this genealogical data set. See <a href="http://www.w3.org/International/articles/language-tags/">http://www.w3.org/International/articles/language-tags/</a>. * Note that some language-enabled elements MAY override the language. * * @return The language of the genealogical data. */ @XmlAttribute ( namespace = XMLConstants.XML_NS_URI ) public String getLang() { return lang; } /** * The language of this genealogical data set. See <a href="http://www.w3.org/International/articles/language-tags/">http://www.w3.org/International/articles/language-tags/</a>. * Note that some language-enabled elements MAY override the language. * * @param lang The language of this genealogical data. */ public void setLang(String lang) { this.lang = lang; } /** * Build out this envelope with a lang. * * @param lang The lang. * @return this. */ public Gedcomx lang(String lang) { setLang(lang); return this; } /** * A reference to a description of this data set. * * @return A reference to a description of this data set. */ @XmlAttribute ( name = "description" ) @JsonProperty ( "description" ) @org.codehaus.jackson.annotate.JsonProperty ( "description" ) @Facet ( GedcomxConstants.FACET_GEDCOMX_RECORD ) public URI getDescriptionRef() { return descriptionRef; } /** * A reference to a description of this data set. * * @param descriptionRef A reference to a description of this data set. */ @JsonProperty ( "description" ) @org.codehaus.jackson.annotate.JsonProperty ( "description" ) public void setDescriptionRef(URI descriptionRef) { this.descriptionRef = descriptionRef; } /** * Build out this with a description ref. * * @param descriptionRef The description ref. * @return this. */ public Gedcomx descriptionRef(URI descriptionRef) { setDescriptionRef(descriptionRef); return this; } /** * The attribution of this genealogical data. * * @return The attribution of this genealogical data. */ public Attribution getAttribution() { return attribution; } /** * The attribution of this genealogical data. * * @param attribution The attribution of this genealogical data. */ public void setAttribution(Attribution attribution) { this.attribution = attribution; } /** * Build this out with an attribution. * @param attribution The attribution. * @return this. */ public Gedcomx attribution(Attribution attribution) { setAttribution(attribution); return this; } /** * Get the first person in the document. * * @return The first person in the document. */ @XmlTransient @JsonIgnore @org.codehaus.jackson.annotate.JsonIgnore public Person getPerson() { return this.persons != null && this.persons.size() > 0 ? this.persons.get(0) : null; } /** * Find a person in the document by URI. * * @return The person, or null. */ public Person findPerson(URI uri) { return findSubject(this.persons, uri); } /** * The persons included in this genealogical data set. * * @return The persons included in this genealogical data set. */ @XmlElement ( name = "person" ) @JsonProperty ( "persons" ) @org.codehaus.jackson.annotate.JsonProperty ( "persons" ) public List<Person> getPersons() { return persons; } /** * The persons included in this genealogical data set. * * @param persons The persons included in this genealogical data set. */ @JsonProperty ( "persons" ) @org.codehaus.jackson.annotate.JsonProperty ( "persons" ) public void setPersons(List<Person> persons) { this.persons = persons; } /** * Build this out with a person. * @param person The person. * @return this. */ public Gedcomx person(Person person) { addPerson(person); return this; } /** * Add a person to the data set. * * @param person The person to be added. */ public void addPerson(Person person) { if (person != null) { if (persons == null) { persons = new LinkedList<Person>(); } persons.add(person); } } /** * Get the list of couple relationships in the document. * * @return The list of couple relationships in the document. */ @XmlTransient @JsonIgnore @org.codehaus.jackson.annotate.JsonIgnore public List<Relationship> getCoupleRelationships() { ArrayList<Relationship> filtered = null; if (this.relationships != null) { filtered = new ArrayList<Relationship>(); for (Relationship relationship : this.relationships) { if (relationship.getKnownType() == RelationshipType.Couple) { filtered.add(relationship); } } } return filtered; } /** * Get the list of parent-child relationships in the document. * * @return The list of parent-child relationships in the document. */ @XmlTransient @JsonIgnore @org.codehaus.jackson.annotate.JsonIgnore public List<Relationship> getParentChildRelationships() { ArrayList<Relationship> filtered = null; if (this.relationships != null) { filtered = new ArrayList<Relationship>(); for (Relationship relationship : this.relationships) { if (relationship.getKnownType() == RelationshipType.ParentChild) { filtered.add(relationship); } } } return filtered; } /** * Find the couple relationship (if any) that corresponds to the relationship between the parents in the given family. * @param family - Family to find the couple relationship for. * @return the couple relationship for the parents in the family, if any, or null if there isn't one (or if there are not two parents). */ public Relationship findCoupleRelationship(FamilyView family) { return family == null ? null : findCoupleRelationship(family.getParent1(), family.getParent2()); } /** * Find the couple relationship (if any) that corresponds to the relationship between the people with the given IDs. * @param person1 - person1 to find (i.e., husband) * @param person2 - person2 to find (i.e., wife) * @return the couple relationship for the parents in the family, if any, or null if there isn't one (or if there are not two parents). */ public Relationship findCoupleRelationship(ResourceReference person1, ResourceReference person2) { if (getRelationships() != null) { for (Relationship relationship : getRelationships()) { if (relationship.getKnownType() == RelationshipType.Couple && samePerson(person1, relationship.getPerson1()) && samePerson(person2, relationship.getPerson2())) { return relationship; } } } return null; } /** * Find the parent-child relationship between the given two persons. * @param parent - Reference to the parent to find. * @param child - Reference to the child to find. * @return parent-child relationship for the given parent and child, or null if not found in the document. */ public Relationship findParentChildRelationship(ResourceReference parent, ResourceReference child) { if (parent != null && child != null && getRelationships() != null && parent.getResource() != null && child.getResource() != null) { for (Relationship relationship : getRelationships()) { if (relationship.getKnownType().equals(RelationshipType.ParentChild) && samePerson(relationship.getPerson1(), parent) && samePerson(relationship.getPerson2(), child)) { return relationship; } } } return null; } /** * Tell whether the given resource reference is referencing the current person * @param ref1 - Local reference to a person URI. * @param ref2 - Local reference to a person URI. * @return true if the personReference is referencing this person (or both are null). False otherwise. */ protected static boolean samePerson(ResourceReference ref1, ResourceReference ref2) { return ref1 == ref2 || (ref1 != null && ref1.getResource() != null && ref2 != null && ref2.getResource() != null && ref1.getResource().equals(ref2.getResource())); } /** * Find a relationship in the document by URI. * * @return The relationship, or null. */ public Relationship findRelationship(URI uri) { return findSubject(this.relationships, uri); } /** * The relationships included in this genealogical data set. * * @return The relationships included in this genealogical data set. */ @XmlElement ( name = "relationship" ) @JsonProperty ( "relationships" ) @org.codehaus.jackson.annotate.JsonProperty ( "relationships" ) public List<Relationship> getRelationships() { return relationships; } /** * The relationships included in this genealogical data set. * * @param relationships The relationships included in this genealogical data set. */ @JsonProperty ( "relationships" ) @org.codehaus.jackson.annotate.JsonProperty ( "relationships" ) public void setRelationships(List<Relationship> relationships) { this.relationships = relationships; } /** * Build this out with a relationship. * @param relationship The relationship. * @return this. */ public Gedcomx relationship(Relationship relationship) { addRelationship(relationship); return this; } /** * Add a relationship to the data set. * * @param relationship The relationship to be added. */ public void addRelationship(Relationship relationship) { if (relationship != null) { if (relationships == null) { relationships = new LinkedList<Relationship>(); } relationships.add(relationship); } } /** * Get the first source description in the document. * * @return The first source description in the document. */ @XmlTransient @JsonIgnore @org.codehaus.jackson.annotate.JsonIgnore public SourceDescription getSourceDescription() { return this.sourceDescriptions != null && this.sourceDescriptions.size() > 0 ? this.sourceDescriptions.get(0) : null; } /** * Get the first source description in the document with the type that is specified. * * @param resourceType The URI resource type of the SourceDescription you are trying to find. * * @return The first source description in the document with the type that is specified.. */ public SourceDescription getSourceDescription(URI resourceType) { if (this.sourceDescriptions != null && this.sourceDescriptions.size() > 0) { for (SourceDescription sourceDescription : this.sourceDescriptions) { if (sourceDescription.getResourceType().equals(resourceType)) { return sourceDescription; } } } return null; } /** * Find a description in the document by URI. * * @return The description, or null. */ public SourceDescription findDescription(URI uri) { return findElement(this.sourceDescriptions, uri); } /** * The descriptions of sources included in this genealogical data set. * * @return The descriptions of sources included in this genealogical data set. */ @XmlElement ( name = "sourceDescription" ) @JsonProperty ( "sourceDescriptions" ) @org.codehaus.jackson.annotate.JsonProperty ( "sourceDescriptions" ) public List<SourceDescription> getSourceDescriptions() { return sourceDescriptions; } /** * The descriptions of sources included in this genealogical data set. * * @param sourceDescriptions The descriptions of sources included in this genealogical data set. */ @JsonProperty ( "sourceDescriptions" ) @org.codehaus.jackson.annotate.JsonProperty ( "sourceDescriptions" ) public void setSourceDescriptions(List<SourceDescription> sourceDescriptions) { this.sourceDescriptions = sourceDescriptions; } /** * Build this out with a source description. * @param sourceDescription The source description. * @return this. */ public Gedcomx sourceDescription(SourceDescription sourceDescription) { addSourceDescription(sourceDescription); return this; } /** * Add a source description to the data set. * * @param sourceDescription The source description to be added. */ public void addSourceDescription(SourceDescription sourceDescription) { if (sourceDescription != null) { if (sourceDescriptions == null) { sourceDescriptions = new LinkedList<SourceDescription>(); } sourceDescriptions.add(sourceDescription); } } /** * The agents included in this genealogical data set. * * @return The agents included in this genealogical data set. */ @XmlElement ( name = "agent" ) @JsonProperty ( "agents" ) @org.codehaus.jackson.annotate.JsonProperty ( "agents" ) public List<Agent> getAgents() { return agents; } /** * Find a agent in the document by URI. * * @return The agent, or null. */ public Agent findAgent(URI uri) { return findElement(this.agents, uri); } /** * The agents included in this genealogical data set. * * @param agents The agents included in this genealogical data set. */ @JsonProperty ( "agents" ) @org.codehaus.jackson.annotate.JsonProperty ( "agents" ) public void setAgents(List<Agent> agents) { this.agents = agents; } /** * Build this out with a agent. * @param agent The agent. * @return this. */ public Gedcomx agent(Agent agent) { addAgent(agent); return this; } /** * Add a agent to the data set. * * @param agent The agent to be added. */ public void addAgent(Agent agent) { if (agent != null) { if (agents == null) { agents = new LinkedList<Agent>(); } agents.add(agent); } } /** * The events included in this genealogical data set. * * @return The events included in this genealogical data set. */ @XmlElement ( name = "event" ) @JsonProperty ( "events" ) @org.codehaus.jackson.annotate.JsonProperty ( "events" ) public List<Event> getEvents() { return events; } /** * The events included in this genealogical data set. * * @param events The events included in this genealogical data set. */ @JsonProperty ( "events" ) @org.codehaus.jackson.annotate.JsonProperty ( "events" ) public void setEvents(List<Event> events) { this.events = events; } /** * Build this out with a event. * @param event The event. * @return this. */ public Gedcomx event(Event event) { addEvent(event); return this; } /** * Add a event to the data set. * * @param event The event to be added. */ public void addEvent(Event event) { if (event != null) { if (events == null) { events = new LinkedList<Event>(); } events.add(event); } } /** * The places included in this genealogical data set. * * @return The places included in this genealogical data set. */ @XmlElement ( name = "place" ) @JsonProperty ( "places" ) @org.codehaus.jackson.annotate.JsonProperty ( "places" ) public List<PlaceDescription> getPlaces() { return places; } /** * Find a place in the document by URI. * * @return The place, or null. */ public PlaceDescription findPlace(URI uri) { return findSubject(this.places, uri); } /** * The places included in this genealogical data set. * * @param places The places included in this genealogical data set. */ @JsonProperty ( "places" ) @org.codehaus.jackson.annotate.JsonProperty ( "places" ) public void setPlaces(List<PlaceDescription> places) { this.places = places; } /** * Build this out with a place. * @param place The place. * @return this. */ public Gedcomx place(PlaceDescription place) { addPlace(place); return this; } /** * Add a place to the data set. * * @param place The place to be added. */ public void addPlace(PlaceDescription place) { if (place != null) { if (places == null) { places = new LinkedList<PlaceDescription>(); } places.add(place); } } /** * The documents included in this genealogical data set. * * @return The documents included in this genealogical data set. */ @XmlElement ( name = "document" ) @JsonProperty ( "documents" ) @org.codehaus.jackson.annotate.JsonProperty ( "documents" ) public List<Document> getDocuments() { return documents; } /** * The documents included in this genealogical data set. * * @param documents The documents included in this genealogical data set. */ @JsonProperty ( "documents" ) @org.codehaus.jackson.annotate.JsonProperty ( "documents" ) public void setDocuments(List<Document> documents) { this.documents = documents; } /** * Build this out with a document. * @param document The document. * @return this. */ public Gedcomx document(Document document) { addDocument(document); return this; } /** * Add a document to the data set. * * @param document The document to be added. */ public void addDocument(Document document) { if (document != null) { if (documents == null) { documents = new LinkedList<Document>(); } documents.add(document); } } /** * The collections included in this genealogical data set. * * @return The collections included in this genealogical data set. */ @XmlElement ( name = "collection" ) @JsonProperty ( "collections" ) @org.codehaus.jackson.annotate.JsonProperty ( "collections" ) @Facet ( GedcomxConstants.FACET_GEDCOMX_RECORD ) public List<Collection> getCollections() { return collections; } /** * The collections included in this genealogical data set. * * @param collections The collections included in this genealogical data set. */ @JsonProperty ( "collections" ) @org.codehaus.jackson.annotate.JsonProperty ( "collections" ) public void setCollections(List<Collection> collections) { this.collections = collections; } /** * Build this out with a collection. * @param collection The collection. * @return this. */ public Gedcomx collection(Collection collection) { addCollection(collection); return this; } /** * Add a collection to the data set. * * @param collection The collection to be added. */ public void addCollection(Collection collection) { if (collection != null) { if (collections == null) { collections = new LinkedList<Collection>(); } collections.add(collection); } } /** * The extracted fields included in this genealogical data set. Fields that apply to a particular person, * relationship or value should be included within that person or value, respectively. * Remaining fields that did not have a place within the person or relationship structure can be included here. * Also, fields that were extracted but not yet fit into a structure can also be included here. * * @return The extracted fields included in this genealogical data set. */ @XmlElement ( name = "field" ) @JsonProperty ( "fields" ) @org.codehaus.jackson.annotate.JsonProperty ( "fields" ) @com.webcohesion.enunciate.metadata.Facet ( GedcomxConstants.FACET_GEDCOMX_RECORD ) public List<Field> getFields() { return fields; } /** * The extracted fields included in this genealogical data set. * * @param fields The extracted fields included in this genealogical data set. */ @JsonProperty ( "fields" ) @org.codehaus.jackson.annotate.JsonProperty ( "fields" ) public void setFields(List<Field> fields) { this.fields = fields; } /** * Build this out with a field. * @param field The field. * @return this. */ public Gedcomx field(Field field) { addField(field); return this; } /** * Add a field to the data set. * * @param field The field to be added. */ public void addField(Field field) { if (field != null) { if (fields == null) { fields = new LinkedList<Field>(); } fields.add(field); } } /** * The record descriptors included in this genealogical data set. * * @return The record descriptors included in this genealogical data set. */ @XmlElement ( name = "recordDescriptor" ) @JsonProperty ( "recordDescriptors" ) @org.codehaus.jackson.annotate.JsonProperty ( "recordDescriptors" ) @Facet ( GedcomxConstants.FACET_GEDCOMX_RECORD ) public List<RecordDescriptor> getRecordDescriptors() { return recordDescriptors; } /** * The record descriptors included in this genealogical data set. * * @param recordDescriptors The record descriptors included in this genealogical data set. */ @JsonProperty ( "recordDescriptors" ) @org.codehaus.jackson.annotate.JsonProperty ( "recordDescriptors" ) public void setRecordDescriptors(List<RecordDescriptor> recordDescriptors) { this.recordDescriptors = recordDescriptors; } /** * Build this out with a record descriptor. * * @param recordDescriptor The record descriptor. * @return this. */ public Gedcomx recordDescriptor(RecordDescriptor recordDescriptor) { addRecordDescriptor(recordDescriptor); return this; } /** * Add a recordDescriptor to the data set. * * @param recordDescriptor The recordDescriptor to be added. */ public void addRecordDescriptor(RecordDescriptor recordDescriptor) { if (recordDescriptor != null) { if (recordDescriptors == null) { recordDescriptors = new LinkedList<RecordDescriptor>(); } recordDescriptors.add(recordDescriptor); } } /** * Accept a visitor. * * @param visitor The visitor. */ public void accept(GedcomxModelVisitor visitor) { visitor.visitGedcomx(this); } public void embed(Gedcomx gedcomx) { List<Link> links = gedcomx.getLinks(); if (links != null) { for (Link link : links) { boolean found = false; if (link.getRel() != null) { if (getLinks() != null) { for (Link target : getLinks()) { if (link.getRel().equals(target.getRel())) { found = true; break; } } } } if (!found) { addLink(link); } } } List<Person> persons = gedcomx.getPersons(); if (persons != null) { for (Person person : persons) { boolean found = false; if (person.getId() != null) { if (getPersons() != null) { for (Person target : getPersons()) { if (person.getId().equals(target.getId())) { target.embed(person); found = true; break; } } } } if (!found) { addPerson(person); } } } List<Relationship> relationships = gedcomx.getRelationships(); if (relationships != null) { for (Relationship relationship : relationships) { boolean found = false; if (relationship.getId() != null) { if (getRelationships() != null) { for (Relationship target : getRelationships()) { if (relationship.getId().equals(target.getId())) { target.embed(relationship); found = true; break; } } } } if (!found) { addRelationship(relationship); } } } List<SourceDescription> sourceDescriptions = gedcomx.getSourceDescriptions(); if (sourceDescriptions != null) { for (SourceDescription sourceDescription : sourceDescriptions) { boolean found = false; if (sourceDescription.getId() != null) { if (getSourceDescriptions() != null) { for (SourceDescription target : getSourceDescriptions()) { if (sourceDescription.getId().equals(target.getId())) { target.embed(sourceDescription); found = true; break; } } } } if (!found) { addSourceDescription(sourceDescription); } } } List<Agent> agents = gedcomx.getAgents(); if (agents != null) { for (Agent agent : agents) { boolean found = false; if (agent.getId() != null) { if (getAgents() != null) { for (Agent target : getAgents()) { if (agent.getId().equals(target.getId())) { target.embed(agent); found = true; break; } } } } if (!found) { addAgent(agent); } } } List<Event> events = gedcomx.getEvents(); if (events != null) { for (Event event : events) { boolean found = false; if (event.getId() != null) { if (getEvents() != null) { for (Event target : getEvents()) { if (event.getId().equals(target.getId())) { target.embed(event); found = true; break; } } } } if (!found) { addEvent(event); } } } List<PlaceDescription> placeDescriptions = gedcomx.getPlaces(); if (placeDescriptions != null) { for (PlaceDescription placeDescription : placeDescriptions) { boolean found = false; if (placeDescription.getId() != null) { if (getPlaces() != null) { for (PlaceDescription target : getPlaces()) { if (placeDescription.getId().equals(target.getId())) { target.embed(placeDescription); found = true; break; } } } } if (!found) { addPlace(placeDescription); } } } List<Document> documents = gedcomx.getDocuments(); if (documents != null) { for (Document document : documents) { boolean found = false; if (document.getId() != null) { if (getDocuments() != null) { for (Document target : getDocuments()) { if (document.getId().equals(target.getId())) { target.embed(document); found = true; break; } } } } if (!found) { addDocument(document); } } } List<Collection> collections = gedcomx.getCollections(); if (collections != null) { for (Collection collection : collections) { boolean found = false; if (collection.getId() != null) { if (getCollections() != null) { for (Collection target : getCollections()) { if (collection.getId().equals(target.getId())) { target.embed(collection); found = true; break; } } } } if (!found) { addCollection(collection); } } } List<Field> fields = gedcomx.getFields(); if (fields != null) { for (Field field : fields) { boolean found = false; if (field.getId() != null) { if (getFields() != null) { for (Field target : getFields()) { if (field.getId().equals(target.getId())) { found = true; break; } } } } if (!found) { addField(field); } } } List<RecordDescriptor> recordDescriptors = gedcomx.getRecordDescriptors(); if (recordDescriptors != null) { for (RecordDescriptor recordDescriptor : recordDescriptors) { boolean found = false; if (recordDescriptor.getId() != null) { if (getRecordDescriptors() != null) { for (RecordDescriptor target : getRecordDescriptors()) { if (recordDescriptor.getId().equals(target.getId())) { target.embed(recordDescriptor); found = true; break; } } } } if (!found) { addRecordDescriptor(recordDescriptor); } } } } /** * Add a description for the main person in this document. * * @return this. */ public Gedcomx addMainPersonDescription() { Person person = getPerson(); if (person != null) { addPersonDescription(person, null, null, null, null); } return this; } /** * Add a description for the person in this document. * * @param person The person * @param lastModified When the person was last modified. * @param dateFormat The format for the date. * @param version The version of the person. * @param collectionUri The URI to the collection in which the person is found. * @return this. */ public Gedcomx addPersonDescription(Person person, java.util.Date lastModified, DateFormat dateFormat, String version, URI collectionUri) { String id = person.getId(); if (id != null) { String name = null; if (person.getNames() != null && person.getNames().size() > 0 && person.getNames().get(0).getNameForms() != null && person.getNames().get(0).getNameForms().size() > 0) { name = person.getNames().get(0).getNameForms().get(0).getFullText(); } if (name == null) { name = "Unknown Person"; } String sdid = "SD-" + id; SourceDescription personDescription = new SourceDescription() .id(sdid) .about(URI.create("#" + id)) .resourceType(ResourceType.Person) .title(name) .version(version); if (collectionUri != null) { personDescription = personDescription.componentOf(new SourceReference().descriptionRef(collectionUri)); } StringBuilder citation = new StringBuilder("\"Family Tree,\" database, <i>FamilySearch</i> (http://familysearch.org"); if (lastModified != null) { personDescription = personDescription.modified(lastModified); if (dateFormat != null) { citation.append(" : modified ").append(dateFormat.format(lastModified)); } } citation.append("), entry for ").append(name); URI persistentId = person.getPersistentId(); if (persistentId != null) { personDescription.setPersistentId(persistentId); citation.append("(PID ").append(persistentId).append(")"); } citation.append("; contributed by various users."); personDescription.addCitation(new SourceCitation().lang("en").value(citation.toString())); if (getSourceDescriptions() == null) { setSourceDescriptions(new ArrayList<>()); } getSourceDescriptions().add(0, personDescription); setDescriptionRef(URI.create("#" + sdid)); } return this; } /** * Fixes all references to entities that are in the document to be local references. * * @return this */ public Gedcomx fixLocalReferences() { List<Person> locals = getPersons() == null ? Collections.emptyList() : getPersons(); List<Relationship> relationships = getRelationships() == null ? Collections.emptyList() : getRelationships(); List<SourceDescription> sds = getSourceDescriptions() == null ? Collections.emptyList() : getSourceDescriptions(); List<PlaceDescription> placeDescriptions = getPlaces() == null ? Collections.emptyList() : getPlaces(); //make the references to other persons in the relationship local if they're in the same document. //also make the references to the sources in each source reference local if they're in the same document. for (Person local : locals) { String localId = local.getId(); if (localId != null) { for (Relationship relationship : relationships) { fixId(relationship.getPerson1(), localId); fixId(relationship.getPerson2(), localId); fixupSourceReferences(sds, relationship); } } fixupSourceReferences(sds, local); } for (PlaceDescription placeDescription : placeDescriptions) { if (placeDescription.getPlace() != null) { String resourceId = placeDescription.getPlace().getResourceId(); if (resourceId != null) { for (PlaceDescription checkDescription : placeDescriptions) { if (placeDescription != checkDescription) { if (checkDescription.getPlace() != null && resourceId.equals(checkDescription.getPlace().getResourceId())) { org.gedcomx.common.URI uri = new org.gedcomx.common.URI("#" + placeDescription.getPlace().getResourceId()); placeDescription.setPlace(new ResourceReference(uri, placeDescription.getPlace().getResourceId())); break; } } } } } } return this; } protected static void fixupSourceReferences(List<SourceDescription> sds, Subject local) { if (local.getSources() != null) { for (SourceReference sourceReference : local.getSources()) { String sdid = sourceReference.getDescriptionId(); if (sdid != null) { for (SourceDescription sourceDescription : sds) { if (sdid.equals(sourceDescription.getId())) { sourceReference.setDescriptionRef(org.gedcomx.common.URI.create("#" + sdid)); } } } } } } protected static void fixId(ResourceReference ref, String localId) { if (ref != null && localId.equals(ref.getResourceId())) { ref.setResource(org.gedcomx.common.URI.create("#" + localId)); } } public static <S extends Subject> S findSubject(List<S> items, URI ref) { if (items == null || ref == null) { return null; } String value = ref.toString(); String id = value.startsWith("#") ? value.substring(1) : null; for (S subject : items) { if (id != null && id.equals(subject.getId())) { return subject; } if (subject.getIdentifiers() != null) { for (Identifier identifier : subject.getIdentifiers()) { if (ref.equals(identifier.getValue())) { return subject; } } } } return null; } public static <E extends HypermediaEnabledData> E findElement(List<E> items, URI ref) { if (items == null || ref == null) { return null; } String value = ref.toString(); String id = value.startsWith("#") ? value.substring(1) : null; for (E element : items) { if (id != null && id.equals(element.getId())) { return element; } } return null; } }