diff --git a/.gitignore b/.gitignore index a2f47adb..7a917b5e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ *.iws target .idea +*.zargo~ diff --git a/enunciate-gedcomx-support/pom.xml b/enunciate-gedcomx-support/pom.xml index 846ad5ab..408fabaf 100644 --- a/enunciate-gedcomx-support/pom.xml +++ b/enunciate-gedcomx-support/pom.xml @@ -7,7 +7,7 @@ org.gedcomx gedcomx-parent - 0.14.0-SNAPSHOT + 0.18.0-SNAPSHOT diff --git a/enunciate-gedcomx-support/skin/css/style.css b/enunciate-gedcomx-support/skin/css/style.css index fcd3ef43..bd3540f4 100644 --- a/enunciate-gedcomx-support/skin/css/style.css +++ b/enunciate-gedcomx-support/skin/css/style.css @@ -545,6 +545,10 @@ body.advisories #nav-advisories,body.community #nav-community,body.blog #nav-blo margin-bottom: 10px; } +#recipe { + max-height: 600px; +} + /* @end */ /* @group Footer */ diff --git a/enunciate-gedcomx-support/skin/js/libs/jquery-iframe-auto-height.min.js b/enunciate-gedcomx-support/skin/js/libs/jquery-iframe-auto-height.min.js new file mode 100644 index 00000000..99b68391 --- /dev/null +++ b/enunciate-gedcomx-support/skin/js/libs/jquery-iframe-auto-height.min.js @@ -0,0 +1,7 @@ +/* + Plugin: iframe autoheight jQuery Plugin + Version: 1.5.0 + Description: when the page loads set the height of an iframe based on the height of its contents + see README: http://github.com/house9/jquery-iframe-auto-height +*/ +(function(a){a.fn.iframeAutoHeight=function(b){function e(b,c){d("Diagnostics from '"+c+"'");try{d(" "+a(b,window.top.document).contents().find("body")[0].scrollHeight+" for ...find('body')[0].scrollHeight"),d(" "+a(b.contentWindow.document).height()+" for ...contentWindow.document).height()"),d(" "+a(b.contentWindow.document.body).height()+" for ...contentWindow.document.body).height()")}catch(e){d(" unable to check in this state")}d("End diagnostics -> results vary by browser and when diagnostics are requested")}function d(a){c.debug&&c.debug===!0&&window.console&&console.log(a)}var c=a.extend({heightOffset:0,minHeight:0,callback:function(a){},debug:!1,diagnostics:!1},b);d(c),a(this).each(function(){function f(b){c.diagnostics&&e(b,"resizeHeight");var f=a(b,window.top.document).contents().find("body"),g=f[0].scrollHeight+c.heightOffset;g + +loading... + + \ No newline at end of file diff --git a/enunciate-gedcomx-support/skin/template.html b/enunciate-gedcomx-support/skin/template.html index 98c77f4c..a3f8e260 100644 --- a/enunciate-gedcomx-support/skin/template.html +++ b/enunciate-gedcomx-support/skin/template.html @@ -38,6 +38,7 @@
+
[/#macro] [#macro writeEndBody] @@ -90,6 +91,43 @@ }); + + + + [@libBoilerplate.writeFooter/] [@libBoilerplate.writeEndBody/] diff --git a/gedcomx-common/pom.xml b/gedcomx-common/pom.xml index aebb8dcd..259fd20c 100644 --- a/gedcomx-common/pom.xml +++ b/gedcomx-common/pom.xml @@ -7,7 +7,7 @@ org.gedcomx gedcomx-parent - 0.14.0-SNAPSHOT + 0.18.0-SNAPSHOT @@ -42,7 +42,7 @@ org.gedcomx gedcomx-rt-support - 0.14.0-SNAPSHOT + ${project.version} diff --git a/gedcomx-common/src/main/java/org/gedcomx/common/Collection.java b/gedcomx-common/src/main/java/org/gedcomx/common/Collection.java index 20bf7e5c..d04594fa 100644 --- a/gedcomx-common/src/main/java/org/gedcomx/common/Collection.java +++ b/gedcomx-common/src/main/java/org/gedcomx/common/Collection.java @@ -17,9 +17,8 @@ import org.codehaus.enunciate.json.JsonName; import org.codehaus.jackson.annotate.JsonProperty; -import org.codehaus.jackson.annotate.JsonTypeInfo; -import org.codehaus.jackson.map.annotate.JsonTypeIdResolver; import org.gedcomx.rt.*; +import org.gedcomx.rt.json.JsonElementWrapper; import org.gedcomx.types.TypeReference; import javax.xml.XMLConstants; @@ -34,8 +33,6 @@ */ @XmlRootElement @JsonElementWrapper ( name = "collections" ) -@JsonTypeInfo ( use =JsonTypeInfo.Id.CUSTOM, property = XmlTypeIdResolver.TYPE_PROPERTY_NAME) -@JsonTypeIdResolver (XmlTypeIdResolver.class) @XmlType ( name = "Collection", propOrder = { "title", "description", "publisher", "bibliographicCitation", "types", "spatial", "temporal", "items" } ) @RDFSubClassOf ( CommonModels.DUBLIN_CORE_TYPE_NAMESPACE + "Collection" ) public class Collection extends GenealogicalResource { diff --git a/gedcomx-common/src/main/java/org/gedcomx/common/FormalValue.java b/gedcomx-common/src/main/java/org/gedcomx/common/FormalValue.java index ebe08908..3c36be32 100644 --- a/gedcomx-common/src/main/java/org/gedcomx/common/FormalValue.java +++ b/gedcomx-common/src/main/java/org/gedcomx/common/FormalValue.java @@ -17,10 +17,7 @@ import org.codehaus.enunciate.XmlQNameEnumUtil; import org.codehaus.jackson.annotate.JsonIgnore; -import org.codehaus.jackson.annotate.JsonTypeInfo; -import org.codehaus.jackson.map.annotate.JsonTypeIdResolver; import org.gedcomx.rt.CommonModels; -import org.gedcomx.rt.XmlTypeIdResolver; import javax.xml.XMLConstants; import javax.xml.bind.annotation.*; @@ -38,8 +35,6 @@ * * @author Ryan Heaton */ -@JsonTypeInfo ( use = JsonTypeInfo.Id.CUSTOM, property = XmlTypeIdResolver.TYPE_PROPERTY_NAME) -@JsonTypeIdResolver (XmlTypeIdResolver.class) @XmlType ( name = "FormalValue" ) @SuppressWarnings("gedcomx:no_id") public class FormalValue { @@ -99,7 +94,7 @@ public void setResource(URI resource) { * @return The value. */ public > E getKnownValue(Class clazz) { - return XmlQNameEnumUtil.fromURIValue(getResource().toString(), clazz); + return getResource() != null ? XmlQNameEnumUtil.fromURIValue(getResource().toString(), clazz) : null; } /** diff --git a/gedcomx-common/src/main/java/org/gedcomx/common/AlternateId.java b/gedcomx-common/src/main/java/org/gedcomx/common/Identifier.java similarity index 65% rename from gedcomx-common/src/main/java/org/gedcomx/common/AlternateId.java rename to gedcomx-common/src/main/java/org/gedcomx/common/Identifier.java index ee68ee36..54ab87e9 100644 --- a/gedcomx-common/src/main/java/org/gedcomx/common/AlternateId.java +++ b/gedcomx-common/src/main/java/org/gedcomx/common/Identifier.java @@ -18,7 +18,7 @@ import org.codehaus.jackson.annotate.JsonIgnore; import org.codehaus.jackson.annotate.JsonProperty; import org.gedcomx.rt.CommonModels; -import org.gedcomx.types.AlternateIdType; +import org.gedcomx.types.IdentifierType; import org.gedcomx.types.TypeReference; import javax.xml.bind.annotation.XmlElement; @@ -26,18 +26,17 @@ import javax.xml.bind.annotation.XmlType; /** - * An alternate id for an entity, such as the id in another system or - * an id prior to a merge operation. + * An identifier for a resource. * * @author Ryan Heaton */ -@XmlType ( name = "AlternateId", propOrder = {"type", "value"}) -public final class AlternateId { +@XmlType ( name = "Identifier", propOrder = {"type", "value"}) +public final class Identifier { private String value; @XmlElement (namespace = CommonModels.RDF_NAMESPACE) @JsonProperty - private TypeReference type; + private TypeReference type; /** * The id value. @@ -76,28 +75,28 @@ public URI getType() { */ @JsonIgnore public void setType(URI type) { - this.type = type == null ? null : new TypeReference(type); + this.type = type == null ? null : new TypeReference(type); } /** - * The enum referencing a known alternate id type. + * The enum referencing a known identifier type. * - * @return The enum referencing a known alternate id type, or {@link AlternateIdType#OTHER} if not known. + * @return The enum referencing a known identifier type, or {@link org.gedcomx.types.IdentifierType#OTHER} if not known. */ @XmlTransient @JsonIgnore - public AlternateIdType getKnownType() { - return this.type == null ? null : AlternateIdType.fromQNameURI(this.type.getType()); + public IdentifierType getKnownType() { + return this.type == null ? null : IdentifierType.fromQNameURI(this.type.getType()); } /** - * Set the value of the id type from a known alternate id type. + * Set the value of the id type from a known identifier type. * - * @param knownType The known alternate id type. + * @param knownType The known identifier type. */ @JsonIgnore - public void setKnownType(AlternateIdType knownType) { - this.type = knownType == null ? null : new TypeReference(knownType); + public void setKnownType(IdentifierType knownType) { + this.type = knownType == null ? null : new TypeReference(knownType); } /** diff --git a/gedcomx-common/src/main/java/org/gedcomx/common/Note.java b/gedcomx-common/src/main/java/org/gedcomx/common/Note.java index a2f5b447..2adcaafe 100644 --- a/gedcomx-common/src/main/java/org/gedcomx/common/Note.java +++ b/gedcomx-common/src/main/java/org/gedcomx/common/Note.java @@ -15,10 +15,7 @@ */ package org.gedcomx.common; -import org.codehaus.jackson.annotate.JsonTypeInfo; -import org.codehaus.jackson.map.annotate.JsonTypeIdResolver; -import org.gedcomx.rt.JsonElementWrapper; -import org.gedcomx.rt.XmlTypeIdResolver; +import org.gedcomx.rt.json.JsonElementWrapper; import javax.xml.XMLConstants; import javax.xml.bind.annotation.XmlAttribute; @@ -32,8 +29,6 @@ */ @XmlRootElement @JsonElementWrapper(name = "notes") -@JsonTypeInfo ( use = JsonTypeInfo.Id.CUSTOM, property = XmlTypeIdResolver.TYPE_PROPERTY_NAME) -@JsonTypeIdResolver (XmlTypeIdResolver.class) @XmlType ( name = "Note", propOrder = { "text" } ) public final class Note extends GenealogicalResource { diff --git a/gedcomx-common/src/main/java/org/gedcomx/common/ResourceReference.java b/gedcomx-common/src/main/java/org/gedcomx/common/ResourceReference.java index 3e66ed4b..089d01d2 100644 --- a/gedcomx-common/src/main/java/org/gedcomx/common/ResourceReference.java +++ b/gedcomx-common/src/main/java/org/gedcomx/common/ResourceReference.java @@ -1,264 +1,114 @@ -/** - * Copyright 2011-2012 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.common; - -import org.codehaus.enunciate.doc.DocumentationExample; -import org.codehaus.jackson.annotate.JsonIgnore; -import org.codehaus.jackson.annotate.JsonProperty; -import org.codehaus.jackson.annotate.JsonTypeInfo; -import org.codehaus.jackson.map.annotate.JsonTypeIdResolver; -import org.gedcomx.rt.CommonModels; -import org.gedcomx.rt.SupportsExtensionAttributes; -import org.gedcomx.rt.SupportsExtensionElements; -import org.gedcomx.rt.XmlTypeIdResolver; -import org.gedcomx.types.ResourceFragmentParameter; -import org.gedcomx.types.ResourceType; -import org.gedcomx.types.TypeReference; - -import javax.xml.XMLConstants; -import javax.xml.bind.annotation.*; -import javax.xml.namespace.QName; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * A generic RDF-based reference to a resource. - * - * @author Ryan Heaton - */ -@XmlType ( name = "ResourceReference", namespace = CommonModels.RDF_NAMESPACE ) -@JsonTypeInfo ( use = JsonTypeInfo.Id.CUSTOM, property = XmlTypeIdResolver.TYPE_PROPERTY_NAME) -@JsonTypeIdResolver ( XmlTypeIdResolver.class ) -@XmlSeeAlso(ResourceFragmentParameter.class) -public class ResourceReference implements SupportsExtensionAttributes, SupportsExtensionElements { - - private String id; - @XmlElement (namespace = CommonModels.RDF_NAMESPACE) - @JsonProperty - private TypeReference type; - private URI resource; - private Map extensionAttributes; - private List extensionElements; - - /** - * The id of this resource reference. Note the distinction between this id and the id of the - * resource being referenced. - * - * @return The id of this resource reference. Note the distinction between this id and the id of the - * resource being referenced. - */ - @XmlID - @XmlAttribute( name = "ID", namespace = CommonModels.RDF_NAMESPACE ) - @DocumentationExample(exclude = true) - public String getId() { - return id; - } - - /** - * The id of this resource reference. Note the distinction between this id and the id of the - * resource being referenced. - * - * @param id The id of this resource reference. Note the distinction between this id and the id of the - * resource being referenced. - */ - public void setId(String id) { - this.id = id; - } - - /** - * The type of the resource being referenced. - * - * @return The type of the resource being referenced. - */ - @XmlTransient - @JsonIgnore - public URI getType() { - return this.type == null ? null : this.type.getType(); - } - - /** - * The type of the resource being referenced. - * - * @param type The type of the resource being referenced. - */ - @JsonIgnore - public void setType(URI type) { - this.type = type == null ? null : new TypeReference(type); - } - - /** - * The enum referencing the known type of the resource being referenced, or {@link org.gedcomx.types.ResourceType#OTHER} if not known. - * - * @return The enum referencing the known type of the source reference, or {@link org.gedcomx.types.ResourceType#OTHER} if not known. - */ - @XmlTransient - @JsonIgnore - public ResourceType getKnownType() { - return this.type == null ? null : ResourceType.fromQNameURI(this.type.getType()); - } - - /** - * Set the type of this reference from an enumeration of known source reference types. - * - * @param knownType The reference type. - */ - @JsonIgnore - public void setKnownType(ResourceType knownType) { - this.type = knownType == null ? null : new TypeReference(knownType); - } - - /** - * The URI to the resource. For more information, see Architecture of the World - * Wide Web, Volume One, Section 2 - * - * @link http://www.w3.org/TR/webarch/#identification - * @return The URI to the resource. - */ - @XmlAttribute (namespace= CommonModels.RDF_NAMESPACE) - @XmlSchemaType (name = "anyURI", namespace = XMLConstants.W3C_XML_SCHEMA_NS_URI) - public URI getResource() { - return resource; - } - - /** - * The URI to the resource. For more information, see Architecture of the World - * Wide Web, Volume One, Section 2 - * - * @link http://www.w3.org/TR/webarch/#identification - * @param resource The URI to the resource. - */ - public void setResource(URI resource) { - this.resource = resource; - } - - /** - * Custom attributes applicable to this resource reference. - * - * @return Custom attributes applicable to this resource reference. - */ - @XmlAnyAttribute - @JsonIgnore - public Map getExtensionAttributes() { - return extensionAttributes; - } - - /** - * Custom attributes applicable to this resource reference. - * - * @param extensionAttributes Custom attributes applicable to this resource reference. - */ - @JsonIgnore - public void setExtensionAttributes(Map extensionAttributes) { - this.extensionAttributes = extensionAttributes; - } - - /** - * Add a custom extension attribute. - * - * @param qname The qname of the attribute. - * @param value The value of the attribute. - */ - public void addExtensionAttribute(QName qname, String value) { - if (this.extensionAttributes == null) { - this.extensionAttributes = new HashMap(); - } - - this.extensionAttributes.put(qname, value); - } - - /** - * Custom attributes applicable to this resource reference. - * - * @return Custom attributes applicable to this resource reference. - */ - @XmlAnyElement ( lax = true ) - @JsonIgnore - public List getExtensionElements() { - return extensionElements; - } - - /** - * Custom attributes applicable to this resource reference. - * - * @param extensionElements Custom attributes applicable to this resource reference. - */ - @JsonIgnore - public void setExtensionElements(List extensionElements) { - this.extensionElements = extensionElements; - } - - /** - * Add an extension element. - * - * @param element The extension element to add. - */ - public void addExtensionElement(Object element) { - if (this.extensionElements == null) { - this.extensionElements = new ArrayList(); - } - - this.extensionElements.add(element); - } - - /** - * Finds the first extension of a specified type. - * - * @param clazz The type. - * @return The extension, or null if none found. - */ - @SuppressWarnings ( {"unchecked"} ) - public E findExtensionOfType(Class clazz) { - if (this.extensionElements != null) { - for (Object extension : extensionElements) { - if (clazz.isInstance(extension)) { - return (E) extension; - } - } - } - - return null; - } - - /** - * Find the extensions of a specified type. - * - * @param clazz The type. - * @return The extensions, possibly empty but not null. - */ - @SuppressWarnings ( {"unchecked"} ) - public List findExtensionsOfType(Class clazz) { - List ext = new ArrayList(); - if (this.extensionElements != null) { - for (Object extension : extensionElements) { - if (clazz.isInstance(extension)) { - ext.add((E) extension); - } - } - } - - return ext; - } - - /** - * Provide a simple toString() method. - */ - @Override - public String toString() { - return (resource == null) ? "" : resource.toString(); - } -} +/** + * Copyright 2011-2012 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.common; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.annotate.JsonDeserialize; +import org.codehaus.jackson.map.annotate.JsonSerialize; +import org.gedcomx.rt.CommonModels; +import org.gedcomx.rt.json.JsonSimpleValue; +import org.gedcomx.types.ResourceFragmentParameter; + +import javax.xml.XMLConstants; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlSeeAlso; +import javax.xml.bind.annotation.XmlType; +import java.io.IOException; + +/** + * A generic RDF-based reference to a resource. + * + * @author Ryan Heaton + */ +@XmlType ( name = "ResourceReference", namespace = CommonModels.RDF_NAMESPACE ) +@XmlSeeAlso(ResourceFragmentParameter.class) +@JsonSerialize (using = ResourceReference.JsonSerializer.class) +@JsonDeserialize (using = ResourceReference.JsonDeserializer.class) +@JsonSimpleValue ( example = "http://path/to/resource" ) +public final class ResourceReference { + + private URI resource; + + public ResourceReference() { + } + + public ResourceReference(URI resource) { + this.resource = resource; + } + + /** + * The URI to the resource. For more information, see Architecture of the World + * Wide Web, Volume One, Section 2 + * + * @link http://www.w3.org/TR/webarch/#identification + * @return The URI to the resource. + */ + @XmlAttribute (namespace= CommonModels.RDF_NAMESPACE) + @XmlSchemaType (name = "anyURI", namespace = XMLConstants.W3C_XML_SCHEMA_NS_URI) + public URI getResource() { + return resource; + } + + /** + * The URI to the resource. For more information, see Architecture of the World + * Wide Web, Volume One, Section 2 + * + * @link http://www.w3.org/TR/webarch/#identification + * @param resource The URI to the resource. + */ + public void setResource(URI resource) { + this.resource = resource; + } + + /** + * Provide a simple toString() method. + */ + @Override + public String toString() { + return (resource == null) ? "" : resource.toString(); + } + + public static class JsonSerializer extends org.codehaus.jackson.map.JsonSerializer { + @Override + public void serialize(ResourceReference value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { + if (value == null || value.getResource() == null) { + jgen.writeNull(); + } + else { + jgen.writeString(value.getResource().toString()); + } + } + } + + public static class JsonDeserializer extends org.codehaus.jackson.map.JsonDeserializer { + + @Override + public ResourceReference deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { + String text = jp.getText(); + if (text == null) { + return null; + } + else { + return new ResourceReference(URI.create(text)); + } + } + } +} diff --git a/gedcomx-common/src/main/java/org/gedcomx/common/ResourceSet.java b/gedcomx-common/src/main/java/org/gedcomx/common/ResourceSet.java index 6af2b44d..20339685 100644 --- a/gedcomx-common/src/main/java/org/gedcomx/common/ResourceSet.java +++ b/gedcomx-common/src/main/java/org/gedcomx/common/ResourceSet.java @@ -16,12 +16,9 @@ package org.gedcomx.common; import org.codehaus.jackson.annotate.JsonIgnore; -import org.codehaus.jackson.annotate.JsonTypeInfo; -import org.codehaus.jackson.map.annotate.JsonTypeIdResolver; import org.gedcomx.rt.CommonModels; -import org.gedcomx.rt.JsonElementWrapper; +import org.gedcomx.rt.json.JsonElementWrapper; import org.gedcomx.rt.SupportsExtensionElements; -import org.gedcomx.rt.XmlTypeIdResolver; import javax.xml.bind.annotation.*; import java.util.ArrayList; @@ -35,8 +32,6 @@ */ @XmlRootElement ( name = "RDF", namespace = CommonModels.RDF_NAMESPACE ) @JsonElementWrapper (name = "resourceSets") -@JsonTypeInfo ( use = JsonTypeInfo.Id.CUSTOM, property = XmlTypeIdResolver.TYPE_PROPERTY_NAME ) -@JsonTypeIdResolver ( XmlTypeIdResolver.class ) @XmlType ( name = "RDF", namespace = CommonModels.RDF_NAMESPACE ) public class ResourceSet implements SupportsExtensionElements { diff --git a/gedcomx-common/src/main/java/org/gedcomx/common/URI.java b/gedcomx-common/src/main/java/org/gedcomx/common/URI.java index abe6bb2e..0e8d0885 100644 --- a/gedcomx-common/src/main/java/org/gedcomx/common/URI.java +++ b/gedcomx-common/src/main/java/org/gedcomx/common/URI.java @@ -30,6 +30,10 @@ public final class URI { private final String value; public URI(String value) { + if (value == null) { + throw new IllegalArgumentException("value cannot be null"); + } + this.value = value; } @@ -49,7 +53,7 @@ public String toString() { @Override public boolean equals(Object o) { - return this == o || !(o == null || getClass() != o.getClass()) && value.equals(((URI) o).value); + return this == o || !(o == null) && value.equals(((URI) o).value); } @Override diff --git a/gedcomx-common/src/main/java/org/gedcomx/types/AlternateIdType.java b/gedcomx-common/src/main/java/org/gedcomx/types/DateFormatType.java similarity index 77% rename from gedcomx-common/src/main/java/org/gedcomx/types/AlternateIdType.java rename to gedcomx-common/src/main/java/org/gedcomx/types/DateFormatType.java index d6538c8d..13efeca9 100644 --- a/gedcomx-common/src/main/java/org/gedcomx/types/AlternateIdType.java +++ b/gedcomx-common/src/main/java/org/gedcomx/types/DateFormatType.java @@ -16,20 +16,27 @@ package org.gedcomx.types; import org.codehaus.enunciate.qname.XmlQNameEnum; +import org.codehaus.enunciate.qname.XmlQNameEnumValue; import org.codehaus.enunciate.qname.XmlUnknownQNameEnumValue; import org.gedcomx.common.URI; /** - * Enumeration of standard alternate id types. + * Enumeration of standard age part types. * * @author Ryan Heaton */ @XmlQNameEnum ( base = XmlQNameEnum.BaseType.URI ) -public enum AlternateIdType { +public enum DateFormatType { - Forwarded, + GEDCOM_5_5, + + @XmlQNameEnumValue( + namespace = "iso:", + localPart = "8601" + ) + ISO8601, @XmlUnknownQNameEnumValue OTHER; @@ -49,8 +56,8 @@ public URI toQNameURI() { * @param qname The qname. * @return The enumeration. */ - public static AlternateIdType fromQNameURI(URI qname) { - return org.codehaus.enunciate.XmlQNameEnumUtil.fromURIValue(qname.toString(), AlternateIdType.class); + public static DateFormatType fromQNameURI(URI qname) { + return org.codehaus.enunciate.XmlQNameEnumUtil.fromURIValue(qname.toString(), DateFormatType.class); } } diff --git a/gedcomx-common/src/main/java/org/gedcomx/types/FactType.java b/gedcomx-common/src/main/java/org/gedcomx/types/FactType.java index e2b7a3de..c288bf06 100644 --- a/gedcomx-common/src/main/java/org/gedcomx/types/FactType.java +++ b/gedcomx-common/src/main/java/org/gedcomx/types/FactType.java @@ -37,7 +37,7 @@ public enum FactType { Adoption, AdultChristening, Affiliation, - Age, + Arrival, Baptism, BarMitzvah, BatMitzvah, @@ -55,8 +55,8 @@ public enum FactType { CountOfMarriages, Cremation, Death, + Departure, DiedBeforeEight, - Dwelling, Emigration, Ethnicity, Excommunication, @@ -203,7 +203,7 @@ private static FactType include(FactType type) { public static final FactType Adoption = include(FactType.Adoption); public static final FactType AdultChristening = include(FactType.AdultChristening); public static final FactType Affiliation = include(FactType.Affiliation); - public static final FactType Age = include(FactType.Age); + public static final FactType Arrival = include(FactType.Arrival); public static final FactType Baptism = include(FactType.Baptism); public static final FactType BarMitzvah = include(FactType.BarMitzvah); public static final FactType BatMitzvah = include(FactType.BatMitzvah); @@ -221,8 +221,8 @@ private static FactType include(FactType type) { public static final FactType CountOfMarriages = include(FactType.CountOfMarriages); public static final FactType Cremation = include(FactType.Cremation); public static final FactType Death = include(FactType.Death); + public static final FactType Departure = include(FactType.Departure); public static final FactType DiedBeforeEight = include(FactType.DiedBeforeEight); - public static final FactType Dwelling = include(FactType.Dwelling); public static final FactType Emigration = include(FactType.Emigration); public static final FactType Ethnicity = include(FactType.Ethnicity); public static final FactType Excommunication = include(FactType.Excommunication); @@ -260,7 +260,7 @@ private static FactType include(FactType type) { public static final FactType PhysicalDescription = include(FactType.PhysicalDescription); public static final FactType Probate = include(FactType.Probate); public static final FactType PortOfDeparture = include(FactType.PortOfDeparture); - public static final FactType Possessions = include(FactType.Property); + public static final FactType Property = include(FactType.Property); public static final FactType PreviousResidence = include(FactType.PreviousResidence); public static final FactType Race = include(FactType.Race); public static final FactType RelationshipToHead = include(FactType.RelationshipToHead); diff --git a/gedcomx-common/src/main/java/org/gedcomx/types/IdentifierType.java b/gedcomx-common/src/main/java/org/gedcomx/types/IdentifierType.java new file mode 100644 index 00000000..c1fe78bc --- /dev/null +++ b/gedcomx-common/src/main/java/org/gedcomx/types/IdentifierType.java @@ -0,0 +1,64 @@ +/** + * Copyright 2011-2012 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.types; + +import org.codehaus.enunciate.qname.XmlQNameEnum; +import org.codehaus.enunciate.qname.XmlUnknownQNameEnumValue; +import org.gedcomx.common.URI; + +/** + * Enumeration of standard identifier types. + * + * @author Ryan Heaton + */ +@XmlQNameEnum ( + base = XmlQNameEnum.BaseType.URI +) +public enum IdentifierType { + + /** + * The primary identifier for the resource. + */ + Primary, + + /** + * A forwarded identifier for the resource, such as from the result of a merge. + */ + Forwarded, + + @XmlUnknownQNameEnumValue + OTHER; + + /** + * Return the QName value for this enum. + * + * @return The QName value for this enum. + */ + public URI toQNameURI() { + return URI.create(org.codehaus.enunciate.XmlQNameEnumUtil.toURIValue(this)); + } + + /** + * Get the enumeration from the QName. + * + * @param qname The qname. + * @return The enumeration. + */ + public static IdentifierType fromQNameURI(URI qname) { + return org.codehaus.enunciate.XmlQNameEnumUtil.fromURIValue(qname.toString(), IdentifierType.class); + } + +} diff --git a/gedcomx-common/src/main/java/org/gedcomx/types/TypeReference.java b/gedcomx-common/src/main/java/org/gedcomx/types/TypeReference.java index b2a814ce..1572816f 100644 --- a/gedcomx-common/src/main/java/org/gedcomx/types/TypeReference.java +++ b/gedcomx-common/src/main/java/org/gedcomx/types/TypeReference.java @@ -25,6 +25,7 @@ import org.codehaus.jackson.map.annotate.JsonSerialize; import org.gedcomx.common.URI; import org.gedcomx.rt.CommonModels; +import org.gedcomx.rt.json.JsonSimpleValue; import javax.xml.XMLConstants; import javax.xml.bind.annotation.XmlAttribute; @@ -41,6 +42,7 @@ @XmlType ( namespace = CommonModels.RDF_NAMESPACE, name = "type" ) @JsonSerialize (using = TypeReference.JsonSerializer.class) @JsonDeserialize (using = TypeReference.JsonDeserializer.class) +@JsonSimpleValue public final class TypeReference { private URI type; diff --git a/gedcomx-common/src/test/java/org/gedcomx/common/AlternateIdTest.java b/gedcomx-common/src/test/java/org/gedcomx/common/AlternateIdTest.java deleted file mode 100644 index 643e38f1..00000000 --- a/gedcomx-common/src/test/java/org/gedcomx/common/AlternateIdTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.gedcomx.common; - -import org.gedcomx.types.AlternateIdType; -import org.testng.annotations.Test; - -import static org.gedcomx.rt.SerializationUtil.processThroughJson; -import static org.gedcomx.rt.SerializationUtil.processThroughXml; -import static org.testng.AssertJUnit.assertEquals; - -/** - * @author Ryan Heaton - */ -@Test -public class AlternateIdTest { - - /** - * tests alternate id xml - */ - public void testAlternateIdXml() throws Exception { - AlternateId id = new AlternateId(); - id.setKnownType(AlternateIdType.Forwarded); - id.setValue("value"); - id = processThroughXml(id); - assertEquals(AlternateIdType.Forwarded, id.getKnownType()); - assertEquals("value", id.getValue()); - } - - /** - * tests alternate id json - */ - public void testAlternateIdJson() throws Exception { - AlternateId id = new AlternateId(); - id.setKnownType(AlternateIdType.Forwarded); - id.setValue("value"); - id = processThroughJson(id); - assertEquals(AlternateIdType.Forwarded, id.getKnownType()); - assertEquals("value", id.getValue()); - } - -} diff --git a/gedcomx-common/src/test/java/org/gedcomx/common/CustomEntity.java b/gedcomx-common/src/test/java/org/gedcomx/common/CustomEntity.java index 013f6246..49346d87 100644 --- a/gedcomx-common/src/test/java/org/gedcomx/common/CustomEntity.java +++ b/gedcomx-common/src/test/java/org/gedcomx/common/CustomEntity.java @@ -1,26 +1,23 @@ package org.gedcomx.common; -import org.codehaus.jackson.annotate.JsonIgnore; -import org.codehaus.jackson.annotate.JsonTypeInfo; -import org.codehaus.jackson.map.annotate.JsonTypeIdResolver; -import org.gedcomx.rt.JsonElementWrapper; -import org.gedcomx.rt.XmlTypeIdResolver; +import org.gedcomx.rt.json.JsonElementWrapper; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlTransient; -import java.util.Arrays; +import java.util.List; /** * @author Ryan Heaton */ @XmlRootElement @JsonElementWrapper (name = "customEntities") -@JsonTypeInfo ( use =JsonTypeInfo.Id.CUSTOM, property = XmlTypeIdResolver.TYPE_PROPERTY_NAME) -@JsonTypeIdResolver (XmlTypeIdResolver.class) public class CustomEntity extends GenealogicalResource { private ResourceReference source; private URI refToSomething; + private List uniqueKeyedItems; + private List keyedItems; public CustomEntity() { } @@ -44,4 +41,22 @@ public URI getRefToSomething() { public void setRefToSomething(URI refToSomething) { this.refToSomething = refToSomething; } + + @XmlElement ( name = "item" ) + public List getKeyedItems() { + return keyedItems; + } + + public void setKeyedItems(List keyedItems) { + this.keyedItems = keyedItems; + } + + @XmlElement ( name = "uitem" ) + public List getUniqueKeyedItems() { + return uniqueKeyedItems; + } + + public void setUniqueKeyedItems(List uniqueKeyedItems) { + this.uniqueKeyedItems = uniqueKeyedItems; + } } diff --git a/gedcomx-common/src/test/java/org/gedcomx/common/CustomKeyedItem.java b/gedcomx-common/src/test/java/org/gedcomx/common/CustomKeyedItem.java new file mode 100644 index 00000000..68659a3b --- /dev/null +++ b/gedcomx-common/src/test/java/org/gedcomx/common/CustomKeyedItem.java @@ -0,0 +1,59 @@ +package org.gedcomx.common; + +import org.codehaus.jackson.annotate.JsonIgnore; +import org.gedcomx.rt.json.HasJsonKey; +import org.gedcomx.rt.json.JsonElementWrapper; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +/** + * @author Ryan Heaton + */ +@XmlRootElement +@JsonElementWrapper(name = "customkeys") +public class CustomKeyedItem implements HasJsonKey { + + private String key = String.valueOf(hashCode()); + private String val1; + private String val2; + + @JsonIgnore + @XmlTransient + @Override + public String getJsonKey() { + return getKey(); + } + + @JsonIgnore + @Override + public void setJsonKey(String jsonKey) { + setKey(jsonKey); + } + + @JsonIgnore + public String getKey() { + return key; + } + + @JsonIgnore + public void setKey(String key) { + this.key = key; + } + + public String getVal1() { + return val1; + } + + public void setVal1(String val1) { + this.val1 = val1; + } + + public String getVal2() { + return val2; + } + + public void setVal2(String val2) { + this.val2 = val2; + } +} diff --git a/gedcomx-common/src/test/java/org/gedcomx/common/FormalValueTest.java b/gedcomx-common/src/test/java/org/gedcomx/common/FormalValueTest.java new file mode 100644 index 00000000..4f35345c --- /dev/null +++ b/gedcomx-common/src/test/java/org/gedcomx/common/FormalValueTest.java @@ -0,0 +1,52 @@ +package org.gedcomx.common; + +import org.gedcomx.types.DatePartType; +import org.gedcomx.types.PlacePartType; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; + + +public class FormalValueTest { + @Test + public void testGetDatatype() throws Exception { + FormalValue formalValue = new FormalValue(); + + // test initial state + assertNull(formalValue.getDatatype()); + assertNull(formalValue.getResource()); + assertNull(formalValue.getText()); + + // set some values + formalValue.setDatatype(URI.create("#myDataType")); + formalValue.setKnownValue(DatePartType.Months); // sets the resource property + formalValue.setText("Mayo"); + + // validate values + assertEquals(formalValue.getDatatype().toString(), "#myDataType"); + assertEquals(formalValue.getResource().toString(), DatePartType.Months.toQNameURI().toString()); + assertEquals(formalValue.getKnownValue(DatePartType.class), DatePartType.Months); + assertEquals(formalValue.getKnownValue(PlacePartType.class), PlacePartType.OTHER); + assertEquals(formalValue.getText(), "Mayo"); + assertEquals(formalValue.toString(), "Mayo"); + + // set values to null again + formalValue.setDatatype(null); + formalValue.setResource(null); + formalValue.setText(null); + + // test null state + assertNull(formalValue.getDatatype()); + assertNull(formalValue.getResource()); + assertNull(formalValue.getKnownValue(DatePartType.class)); + assertNull(formalValue.getText()); + assertEquals(formalValue.toString(), ""); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testSetKnownValueAsNull() throws Exception { + FormalValue formalValue = new FormalValue(); + formalValue.setKnownValue(null); + } +} diff --git a/gedcomx-common/src/test/java/org/gedcomx/common/IdentifierTest.java b/gedcomx-common/src/test/java/org/gedcomx/common/IdentifierTest.java new file mode 100644 index 00000000..658c691c --- /dev/null +++ b/gedcomx-common/src/test/java/org/gedcomx/common/IdentifierTest.java @@ -0,0 +1,40 @@ +package org.gedcomx.common; + +import org.gedcomx.types.IdentifierType; +import org.testng.annotations.Test; + +import static org.gedcomx.rt.SerializationUtil.processThroughJson; +import static org.gedcomx.rt.SerializationUtil.processThroughXml; +import static org.testng.AssertJUnit.assertEquals; + +/** + * @author Ryan Heaton + */ +@Test +public class IdentifierTest { + + /** + * tests identifier xml + */ + public void testIdXml() throws Exception { + Identifier id = new Identifier(); + id.setKnownType(IdentifierType.Forwarded); + id.setValue("value"); + id = processThroughXml(id); + assertEquals(IdentifierType.Forwarded, id.getKnownType()); + assertEquals("value", id.getValue()); + } + + /** + * tests identifier json + */ + public void testIdJson() throws Exception { + Identifier id = new Identifier(); + id.setKnownType(IdentifierType.Forwarded); + id.setValue("value"); + id = processThroughJson(id); + assertEquals(IdentifierType.Forwarded, id.getKnownType()); + assertEquals("value", id.getValue()); + } + +} diff --git a/gedcomx-common/src/test/java/org/gedcomx/common/JsonCustomizationTest.java b/gedcomx-common/src/test/java/org/gedcomx/common/JsonCustomizationTest.java new file mode 100644 index 00000000..9aa2585f --- /dev/null +++ b/gedcomx-common/src/test/java/org/gedcomx/common/JsonCustomizationTest.java @@ -0,0 +1,237 @@ +package org.gedcomx.common; + +import org.gedcomx.rt.GedcomNamespaceManager; +import org.testng.annotations.Test; + +import javax.xml.bind.JAXBContext; +import java.util.ArrayList; +import java.util.List; + +import static org.gedcomx.rt.SerializationUtil.processThroughJson; +import static org.gedcomx.rt.SerializationUtil.processThroughXml; +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.fail; + +/** + * @author Ryan Heaton + */ +@Test +public class JsonCustomizationTest { + + /** + * tests source reference xml + */ + public void testKeyedItemsXml() throws Exception { + CustomEntity custom = new CustomEntity(); + custom.setRefToSomething(new org.gedcomx.common.URI("uri:hello")); + + custom.setUniqueKeyedItems(new ArrayList()); + UniqueCustomKeyedItem item1 = new UniqueCustomKeyedItem(); + item1.setVal1("1"); + item1.setVal2("2"); + String key1 = item1.getKey(); + custom.getUniqueKeyedItems().add(item1); + UniqueCustomKeyedItem item2 = new UniqueCustomKeyedItem(); + item2.setVal1("one"); + item2.setVal2("two"); + String key2 = item2.getKey(); + custom.getUniqueKeyedItems().add(item2); + + custom.setKeyedItems(new ArrayList()); + CustomKeyedItem item3 = new CustomKeyedItem(); + item3.setVal1("1"); + item3.setVal2("2"); + String key3 = item3.getKey(); + custom.getKeyedItems().add(item3); + CustomKeyedItem item4 = new CustomKeyedItem(); + item4.setVal1("one"); + item4.setVal2("two"); + item4.setKey(key3); + custom.getKeyedItems().add(item4); + + custom = processThroughXml(custom); + + assertEquals("uri:hello", custom.getRefToSomething().toString()); + assertEquals(2, custom.getUniqueKeyedItems().size()); + assertEquals("1", custom.getUniqueKeyedItems().get(0).getVal1()); + assertEquals("2", custom.getUniqueKeyedItems().get(0).getVal2()); + assertEquals(key1, custom.getUniqueKeyedItems().get(0).getKey()); + assertEquals("one", custom.getUniqueKeyedItems().get(1).getVal1()); + assertEquals("two", custom.getUniqueKeyedItems().get(1).getVal2()); + assertEquals(key2, custom.getUniqueKeyedItems().get(1).getKey()); + assertEquals(2, custom.getKeyedItems().size()); + assertEquals("1", custom.getKeyedItems().get(0).getVal1()); + assertEquals("2", custom.getKeyedItems().get(0).getVal2()); + assertEquals(key3, custom.getKeyedItems().get(0).getKey()); + assertEquals("one", custom.getKeyedItems().get(1).getVal1()); + assertEquals("two", custom.getKeyedItems().get(1).getVal2()); + assertEquals(key3, custom.getKeyedItems().get(1).getKey()); + } + + /** + * tests source reference json + */ + public void testKeyedItemsJson() throws Exception { + CustomEntity custom = new CustomEntity(); + custom.setRefToSomething(new org.gedcomx.common.URI("uri:hello")); + + custom.setUniqueKeyedItems(new ArrayList()); + UniqueCustomKeyedItem item1 = new UniqueCustomKeyedItem(); + item1.setVal1("1"); + item1.setVal2("2"); + String key1 = item1.getKey(); + custom.getUniqueKeyedItems().add(item1); + UniqueCustomKeyedItem item2 = new UniqueCustomKeyedItem(); + item2.setVal1("one"); + item2.setVal2("two"); + String key2 = item2.getKey(); + custom.getUniqueKeyedItems().add(item2); + + custom.setKeyedItems(new ArrayList()); + CustomKeyedItem item3 = new CustomKeyedItem(); + item3.setVal1("1"); + item3.setVal2("2"); + String key3 = item3.getKey(); + custom.getKeyedItems().add(item3); + CustomKeyedItem item4 = new CustomKeyedItem(); + item4.setVal1("one"); + item4.setVal2("two"); + item4.setKey(key3); + custom.getKeyedItems().add(item4); + + custom = processThroughJson(custom); + assertEquals("uri:hello", custom.getRefToSomething().toString()); + assertEquals(2, custom.getUniqueKeyedItems().size()); + for (UniqueCustomKeyedItem keyedItem : custom.getUniqueKeyedItems()) { + if ("1".equals(keyedItem.getVal1())) { + assertEquals("2", keyedItem.getVal2()); + assertEquals(key1, keyedItem.getKey()); + } + else if ("one".equals(keyedItem.getVal1())) { + assertEquals("two", keyedItem.getVal2()); + assertEquals(key2, keyedItem.getKey()); + } + else { + fail("Unknown keyed item."); + } + } + assertEquals(2, custom.getKeyedItems().size()); + for (CustomKeyedItem keyedItem : custom.getKeyedItems()) { + if ("1".equals(keyedItem.getVal1())) { + assertEquals("2", keyedItem.getVal2()); + assertEquals(key3, keyedItem.getKey()); + } + else if ("one".equals(keyedItem.getVal1())) { + assertEquals("two", keyedItem.getVal2()); + assertEquals(key3, keyedItem.getKey()); + } + else { + fail("Unknown keyed item."); + } + } + } + + public void testKeyedItemsAsExtensionsXml() throws Exception { + ResourceSet set = new ResourceSet(); + UniqueCustomKeyedItem item1 = new UniqueCustomKeyedItem(); + item1.setVal1("1"); + item1.setVal2("2"); + String key1 = item1.getKey(); + set.addExtensionElement(item1); + UniqueCustomKeyedItem item2 = new UniqueCustomKeyedItem(); + item2.setVal1("one"); + item2.setVal2("two"); + String key2 = item2.getKey(); + set.addExtensionElement(item2); + + CustomKeyedItem item3 = new CustomKeyedItem(); + item3.setVal1("1"); + item3.setVal2("2"); + String key3 = item3.getKey(); + set.addExtensionElement(item3); + + CustomKeyedItem item4 = new CustomKeyedItem(); + item4.setVal1("one"); + item4.setVal2("two"); + item4.setKey(key3); + set.addExtensionElement(item4); + + set = processThroughXml(set, ResourceSet.class, JAXBContext.newInstance(ResourceSet.class, UniqueCustomKeyedItem.class, CustomKeyedItem.class)); + List keyedItems = set.findExtensionsOfType(UniqueCustomKeyedItem.class); + assertEquals(2, keyedItems.size()); + assertEquals("1", keyedItems.get(0).getVal1()); + assertEquals("2", keyedItems.get(0).getVal2()); + assertEquals(key1, keyedItems.get(0).getKey()); + assertEquals("one", keyedItems.get(1).getVal1()); + assertEquals("two", keyedItems.get(1).getVal2()); + assertEquals(key2, keyedItems.get(1).getKey()); + List keyedItems2 = set.findExtensionsOfType(CustomKeyedItem.class); + assertEquals("1", keyedItems2.get(0).getVal1()); + assertEquals("2", keyedItems2.get(0).getVal2()); + assertEquals(key3, keyedItems2.get(0).getKey()); + assertEquals("one", keyedItems2.get(1).getVal1()); + assertEquals("two", keyedItems2.get(1).getVal2()); + assertEquals(key3, keyedItems2.get(1).getKey()); + } + + public void testKeyedItemsAsExtensionsJson() throws Exception { + ResourceSet set = new ResourceSet(); + UniqueCustomKeyedItem item1 = new UniqueCustomKeyedItem(); + item1.setVal1("1"); + item1.setVal2("2"); + String key1 = item1.getKey(); + set.addExtensionElement(item1); + UniqueCustomKeyedItem item2 = new UniqueCustomKeyedItem(); + item2.setVal1("one"); + item2.setVal2("two"); + String key2 = item2.getKey(); + set.addExtensionElement(item2); + + CustomKeyedItem item3 = new CustomKeyedItem(); + item3.setVal1("1"); + item3.setVal2("2"); + String key3 = item3.getKey(); + set.addExtensionElement(item3); + + CustomKeyedItem item4 = new CustomKeyedItem(); + item4.setVal1("one"); + item4.setVal2("two"); + item4.setKey(key3); + set.addExtensionElement(item4); + + GedcomNamespaceManager.registerKnownJsonType(CustomKeyedItem.class); + GedcomNamespaceManager.registerKnownJsonType(UniqueCustomKeyedItem.class); + set = processThroughJson(set); + List keyedItems = set.findExtensionsOfType(UniqueCustomKeyedItem.class); + assertEquals(2, keyedItems.size()); + for (UniqueCustomKeyedItem keyedItem : keyedItems) { + if ("1".equals(keyedItem.getVal1())) { + assertEquals("2", keyedItem.getVal2()); + assertEquals(key1, keyedItem.getKey()); + } + else if ("one".equals(keyedItem.getVal1())) { + assertEquals("two", keyedItem.getVal2()); + assertEquals(key2, keyedItem.getKey()); + } + else { + fail("Unknown keyed item."); + } + } + List keyedItems2 = set.findExtensionsOfType(CustomKeyedItem.class); + assertEquals(2, keyedItems2.size()); + for (CustomKeyedItem keyedItem : keyedItems2) { + if ("1".equals(keyedItem.getVal1())) { + assertEquals("2", keyedItem.getVal2()); + assertEquals(key3, keyedItem.getKey()); + } + else if ("one".equals(keyedItem.getVal1())) { + assertEquals("two", keyedItem.getVal2()); + assertEquals(key3, keyedItem.getKey()); + } + else { + fail("Unknown keyed item."); + } + } + } + +} diff --git a/gedcomx-common/src/test/java/org/gedcomx/common/ResourceSetTest.java b/gedcomx-common/src/test/java/org/gedcomx/common/ResourceSetTest.java index c546645b..06841b04 100644 --- a/gedcomx-common/src/test/java/org/gedcomx/common/ResourceSetTest.java +++ b/gedcomx-common/src/test/java/org/gedcomx/common/ResourceSetTest.java @@ -15,7 +15,7 @@ public class ResourceSetTest { /** - * tests alternate id xml + * tests id xml */ public void testRDFMetadataBundleXml() throws Exception { ResourceSet meta = new ResourceSet(); @@ -28,7 +28,7 @@ public void testRDFMetadataBundleXml() throws Exception { } /** - * tests alternate id json + * tests id json */ public void testRDFMetadataJson() throws Exception { ResourceSet meta = new ResourceSet(); diff --git a/gedcomx-common/src/test/java/org/gedcomx/common/URITest.java b/gedcomx-common/src/test/java/org/gedcomx/common/URITest.java deleted file mode 100644 index 4247d84a..00000000 --- a/gedcomx-common/src/test/java/org/gedcomx/common/URITest.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.gedcomx.common; - -import org.testng.annotations.Test; - -import static org.gedcomx.rt.SerializationUtil.processThroughJson; -import static org.gedcomx.rt.SerializationUtil.processThroughXml; -import static org.testng.AssertJUnit.assertEquals; - -/** - * @author Ryan Heaton - */ -@Test -public class URITest { - - /** - * tests source reference xml - */ - public void testSourceReferenceXml() throws Exception { - CustomEntity custom = new CustomEntity(); - custom.setRefToSomething(new org.gedcomx.common.URI("uri:hello")); - custom = processThroughXml(custom); - assertEquals("uri:hello", custom.getRefToSomething().toString()); - } - - /** - * tests source reference json - */ - public void testSourceReferenceJson() throws Exception { - CustomEntity custom = new CustomEntity(); - custom.setRefToSomething(new org.gedcomx.common.URI("uri:hello")); - custom = processThroughJson(custom); - assertEquals("uri:hello", custom.getRefToSomething().toString()); - } - -} diff --git a/gedcomx-common/src/test/java/org/gedcomx/common/UniqueCustomKeyedItem.java b/gedcomx-common/src/test/java/org/gedcomx/common/UniqueCustomKeyedItem.java new file mode 100644 index 00000000..21616d76 --- /dev/null +++ b/gedcomx-common/src/test/java/org/gedcomx/common/UniqueCustomKeyedItem.java @@ -0,0 +1,59 @@ +package org.gedcomx.common; + +import org.codehaus.jackson.annotate.JsonIgnore; +import org.gedcomx.rt.json.HasUniqueJsonKey; +import org.gedcomx.rt.json.JsonElementWrapper; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +/** + * @author Ryan Heaton + */ +@XmlRootElement +@JsonElementWrapper(name = "ucustomkeys") +public class UniqueCustomKeyedItem implements HasUniqueJsonKey { + + private String key = String.valueOf(hashCode()); + private String val1; + private String val2; + + @JsonIgnore + @XmlTransient + @Override + public String getJsonKey() { + return getKey(); + } + + @JsonIgnore + @Override + public void setJsonKey(String jsonKey) { + setKey(jsonKey); + } + + @JsonIgnore + public String getKey() { + return key; + } + + @JsonIgnore + public void setKey(String key) { + this.key = key; + } + + public String getVal1() { + return val1; + } + + public void setVal1(String val1) { + this.val1 = val1; + } + + public String getVal2() { + return val2; + } + + public void setVal2(String val2) { + this.val2 = val2; + } +} diff --git a/gedcomx-common/src/test/java/org/gedcomx/types/TypesTest.java b/gedcomx-common/src/test/java/org/gedcomx/types/TypesTest.java index 4adca739..77b362bd 100644 --- a/gedcomx-common/src/test/java/org/gedcomx/types/TypesTest.java +++ b/gedcomx-common/src/test/java/org/gedcomx/types/TypesTest.java @@ -1,30 +1,29 @@ -/** - * Copyright 2011-2012 Intellectual Reserve, Inc. All Rights reserved. - */ -package org.gedcomx.types; - -import org.testng.annotations.Test; - -/** - */ -public class TypesTest { - @Test - public void testToQNameURI() throws Exception { - // These enum classes don't need to be tested, so just call toQNameURI to get the code referenced in a test - AgePartType.Days.toQNameURI(); - DatePartType.Days.toQNameURI(); - FactType.Age.isBirthLike(); - FactType.Couple.Marriage.toQNameURI(); - FactType.ParentChild.Biological.toQNameURI(); - FactType.Person.Baptism.toQNameURI(); - FactType.Record.Household.toQNameURI(); - GenderType.Male.toQNameURI(); - MaritalStatusType.Married.toQNameURI(); - NamePartType.Given.toQNameURI(); - NameType.Formal.toQNameURI(); - PlacePartType.Address.toQNameURI(); - RecordType.Census.getBaseType(); - RelationshipRole.Ancestor.toQNameURI(); - RelationshipType.Couple.toQNameURI(); - } -} +/** + * Copyright 2011-2012 Intellectual Reserve, Inc. All Rights reserved. + */ +package org.gedcomx.types; + +import org.testng.annotations.Test; + +/** + */ +public class TypesTest { + @Test + public void testToQNameURI() throws Exception { + // These enum classes don't need to be tested, so just call toQNameURI to get the code referenced in a test + AgePartType.Days.toQNameURI(); + DatePartType.Days.toQNameURI(); + FactType.Couple.Marriage.toQNameURI(); + FactType.ParentChild.Biological.toQNameURI(); + FactType.Person.Baptism.toQNameURI(); + FactType.Record.Household.toQNameURI(); + GenderType.Male.toQNameURI(); + MaritalStatusType.Married.toQNameURI(); + NamePartType.Given.toQNameURI(); + NameType.Formal.toQNameURI(); + PlacePartType.Address.toQNameURI(); + RecordType.Census.getBaseType(); + RelationshipRole.Ancestor.toQNameURI(); + RelationshipType.Couple.toQNameURI(); + } +} diff --git a/gedcomx-conclusion/pom.xml b/gedcomx-conclusion/pom.xml index b182b177..4d49e9c2 100644 --- a/gedcomx-conclusion/pom.xml +++ b/gedcomx-conclusion/pom.xml @@ -7,7 +7,7 @@ org.gedcomx gedcomx-parent - 0.14.0-SNAPSHOT + 0.18.0-SNAPSHOT @@ -16,6 +16,7 @@ ${basedir}/.. + ${project.build.directory}/recipes @@ -35,6 +36,54 @@ + + org.apache.maven.plugins + maven-surefire-plugin + + + ${recipes.dir} + + + + + org.apache.maven.plugins + maven-resources-plugin + + + copy-resources + prepare-package + + copy-resources + + + ${project.build.outputDirectory} + + + ${recipes.dir} + true + + + + + + + + org.apache.maven.plugins + maven-antrun-plugin + + + process-test-classes + + + + + + + run + + + + @@ -42,19 +91,26 @@ org.gedcomx gedcomx-common - 0.14.0-SNAPSHOT + ${project.version} org.gedcomx gedcomx-rt-support - 0.14.0-SNAPSHOT + ${project.version} org.gedcomx gedcomx-test-support - 0.14.0-SNAPSHOT + ${project.version} + test + + + + org.gedcomx + gedcomx-metadata + ${project.version} test diff --git a/gedcomx-conclusion/src/main/java/org/gedcomx/conclusion/Conclusion.java b/gedcomx-conclusion/src/main/java/org/gedcomx/conclusion/Conclusion.java index ab57d416..bf946db1 100644 --- a/gedcomx-conclusion/src/main/java/org/gedcomx/conclusion/Conclusion.java +++ b/gedcomx-conclusion/src/main/java/org/gedcomx/conclusion/Conclusion.java @@ -17,12 +17,8 @@ import org.codehaus.enunciate.json.JsonName; import org.codehaus.jackson.annotate.JsonProperty; -import org.codehaus.jackson.annotate.JsonTypeInfo; -import org.codehaus.jackson.map.annotate.JsonTypeIdResolver; import org.gedcomx.common.GenealogicalResource; -import org.gedcomx.rt.XmlTypeIdResolver; -import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; import java.util.List; @@ -32,33 +28,11 @@ * * @author Ryan Heaton */ -@JsonTypeInfo ( use =JsonTypeInfo.Id.CUSTOM, property = XmlTypeIdResolver.TYPE_PROPERTY_NAME) -@JsonTypeIdResolver (XmlTypeIdResolver.class) @XmlType ( name = "Conclusion" ) public abstract class Conclusion extends GenealogicalResource implements ReferencesSources { - private Boolean preferred; private List sources; - /** - * Whether the conclusion is preferred above other conclusions of the same type. Useful, for example, for display purposes. - * - * @return Whether the conclusion is preferred above other conclusions of the same type. Useful, for example, for display purposes. - */ - @XmlAttribute - public Boolean getPreferred() { - return preferred; - } - - /** - * Whether the conclusion is preferred above other conclusions of the same type. Useful, for example, for display purposes. - * - * @param preferred Whether the conclusion is preferred above other conclusions of the same type. Useful, for example, for display purposes. - */ - public void setPreferred(Boolean preferred) { - this.preferred = preferred; - } - /** * The source references for a conclusion. * diff --git a/gedcomx-conclusion/src/main/java/org/gedcomx/conclusion/Fact.java b/gedcomx-conclusion/src/main/java/org/gedcomx/conclusion/Fact.java index ba28d520..a953ca69 100644 --- a/gedcomx-conclusion/src/main/java/org/gedcomx/conclusion/Fact.java +++ b/gedcomx-conclusion/src/main/java/org/gedcomx/conclusion/Fact.java @@ -1,205 +1,205 @@ -/** - * Copyright 2011-2012 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.conclusion; - -import org.codehaus.jackson.annotate.JsonIgnore; -import org.codehaus.jackson.annotate.JsonProperty; -import org.codehaus.jackson.annotate.JsonTypeInfo; -import org.codehaus.jackson.map.annotate.JsonTypeIdResolver; -import org.gedcomx.common.FormalValue; -import org.gedcomx.common.URI; -import org.gedcomx.rt.CommonModels; -import org.gedcomx.rt.JsonElementWrapper; -import org.gedcomx.rt.RDFSubClassOf; -import org.gedcomx.rt.XmlTypeIdResolver; -import org.gedcomx.types.FactType; -import org.gedcomx.types.TypeReference; - -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlTransient; -import javax.xml.bind.annotation.XmlType; - -/** - * A conclusion about a fact applicable to a person or relationship. - */ -@JsonTypeInfo ( use =JsonTypeInfo.Id.CUSTOM, property = XmlTypeIdResolver.TYPE_PROPERTY_NAME) -@JsonTypeIdResolver (XmlTypeIdResolver.class) -@XmlType ( name = "Fact", propOrder = {"type", "date", "place", "original", "formal" }) -@RDFSubClassOf ( CommonModels.DUBLIN_CORE_TYPE_NAMESPACE + "Event" ) -@XmlRootElement -@JsonElementWrapper ( name = "facts" ) -public class Fact extends Conclusion implements Formalizeable { - - @XmlElement (namespace = CommonModels.RDF_NAMESPACE) - @JsonProperty - private TypeReference type; - private Date date; - private Place place; - private String original; - private FormalValue formal; - - /** - * Create a fact. - */ - public Fact() { - } - - /** - * Create a fact with the passed in type and values. - * - * @param factType the fact type. - * @param original The original value as supplied by the user. - */ - public Fact(FactType factType, String original) { - setKnownType(factType); - setOriginal(original); - setFormal(formal); - } - - /** - * Create a date/place fact with the passed in type and values. - * - * @param factType the fact type. - * @param date The date of applicability of this fact. - * @param place The place of applicability of this fact. - * @param original The original value as supplied by the user. - */ - public Fact(FactType factType, Date date, Place place, String original) { - setKnownType(factType); - setDate(date); - setPlace(place); - setOriginal(original); - } - - /** - * The type of the fact. - * - * @return The type of the fact. - */ - @XmlTransient - @JsonIgnore - public URI getType() { - return this.type == null ? null : this.type.getType(); - } - - /** - * The type of the fact. - * - * @param type The type of the fact. - */ - @JsonIgnore - public void setType(URI type) { - this.type = type == null ? null : new TypeReference(type); - } - - /** - * The enum referencing the known type of the fact, or {@link org.gedcomx.types.FactType#OTHER} if not known. - * - * @return The enum referencing the known type of the fact, or {@link org.gedcomx.types.FactType#OTHER} if not known. - */ - @XmlTransient - @JsonIgnore - public org.gedcomx.types.FactType getKnownType() { - return this.type == null ? null : FactType.fromQNameURI(this.type.getType()); - } - - /** - * Set the type of this fact from a known enumeration of fact types. - * - * @param knownType the fact type. - */ - @JsonIgnore - public void setKnownType(org.gedcomx.types.FactType knownType) { - this.type = knownType == null ? null : new TypeReference(knownType); - } - - /** - * The date of applicability of this fact. - * - * @return The date of applicability of this fact. - */ - public Date getDate() { - return date; - } - - /** - * The date of applicability of this fact. - * - * @param date The date of applicability of this fact. - */ - public void setDate(Date date) { - this.date = date; - } - - /** - * The place of applicability of this fact. - * - * @return The place of applicability of this fact. - */ - public Place getPlace() { - return place; - } - - /** - * The place of applicability of this fact. - * - * @param place The place of applicability of this fact. - */ - public void setPlace(Place place) { - this.place = place; - } - - /** - * The original text as supplied by the user. - * - * @return The original text as supplied by the user. - */ - @Override - public String getOriginal() { - return original; - } - - /** - * The original value as supplied by the user. - * - * @param original The original value as supplied by the user. - */ - @Override - public void setOriginal(String original) { - this.original = original; - } - - /** - * The formal value. - * - * @return The formal value. - */ - @Override - public FormalValue getFormal() { - return formal; - } - - /** - * The formal value. - * - * @param formal The formal value. - */ - @Override - public void setFormal(FormalValue formal) { - this.formal = formal; - } -} +/** + * Copyright 2011-2012 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.conclusion; + +import org.codehaus.jackson.annotate.JsonIgnore; +import org.codehaus.jackson.annotate.JsonProperty; +import org.gedcomx.common.FormalValue; +import org.gedcomx.common.URI; +import org.gedcomx.rt.CommonModels; +import org.gedcomx.rt.json.JsonElementWrapper; +import org.gedcomx.rt.RDFSubClassOf; +import org.gedcomx.types.FactType; +import org.gedcomx.types.TypeReference; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; +import javax.xml.bind.annotation.XmlType; + +/** + * A conclusion about a fact applicable to a person or relationship. + */ +@XmlType ( name = "Fact", propOrder = {"type", "date", "place", "original", "formal" }) +@RDFSubClassOf ( CommonModels.DUBLIN_CORE_TYPE_NAMESPACE + "Event" ) +@XmlRootElement +@JsonElementWrapper ( name = "facts" ) +public class Fact extends Conclusion implements Formalizeable { + + @XmlElement (namespace = CommonModels.RDF_NAMESPACE) + @JsonProperty + private TypeReference type; + private Date date; + private Place place; + private String original; + private FormalValue formal; + + /** + * Create a fact. + */ + public Fact() { + } + + /** + * Create a fact with the passed in type and values. + * + * @param factType the fact type. + * @param original The original value as supplied by the user. + */ + public Fact(FactType factType, String original) { + setKnownType(factType); + setOriginal(original); + setFormal(formal); + } + + /** + * Create a date/place fact with the passed in type and values. + * + * @param factType the fact type. + * @param date The date of applicability of this fact. + * @param place The place of applicability of this fact. + * @param original The original value as supplied by the user. + */ + public Fact(FactType factType, Date date, Place place, String original) { + setKnownType(factType); + setDate(date); + setPlace(place); + setOriginal(original); + } + + /** + * The type of the fact. + * + * @return The type of the fact. + */ + @XmlTransient + @JsonIgnore + public URI getType() { + return this.type == null ? null : this.type.getType(); + } + + /** + * The type of the fact. + * + * @param type The type of the fact. + */ + @JsonIgnore + public void setType(URI type) { + this.type = type == null ? null : new TypeReference(type); + } + + /** + * The enum referencing the known type of the fact, or {@link org.gedcomx.types.FactType#OTHER} if not known. + * + * @return The enum referencing the known type of the fact, or {@link org.gedcomx.types.FactType#OTHER} if not known. + */ + @XmlTransient + @JsonIgnore + public org.gedcomx.types.FactType getKnownType() { + return this.type == null ? null : FactType.fromQNameURI(this.type.getType()); + } + + /** + * Set the type of this fact from a known enumeration of fact types. + * + * @param knownType the fact type. + */ + @JsonIgnore + public void setKnownType(org.gedcomx.types.FactType knownType) { + this.type = knownType == null ? null : new TypeReference(knownType); + } + + /** + * The date of applicability of this fact. + * + * @return The date of applicability of this fact. + */ + public Date getDate() { + return date; + } + + /** + * The date of applicability of this fact. + * + * @param date The date of applicability of this fact. + */ + public void setDate(Date date) { + this.date = date; + } + + /** + * The place of applicability of this fact. + * + * @return The place of applicability of this fact. + */ + public Place getPlace() { + return place; + } + + /** + * The place of applicability of this fact. + * + * @param place The place of applicability of this fact. + */ + public void setPlace(Place place) { + this.place = place; + } + + /** + * The original text as supplied by the user. + * + * @return The original text as supplied by the user. + */ + @Override + public String getOriginal() { + return original; + } + + /** + * The original value as supplied by the user. + * + * @param original The original value as supplied by the user. + */ + @Override + public void setOriginal(String original) { + this.original = original; + } + + /** + * The formal value. + * + * @return The formal value. + */ + @Override + public FormalValue getFormal() { + return formal; + } + + /** + * The formal value. + * + * @param formal The formal value. + */ + @Override + public void setFormal(FormalValue formal) { + this.formal = formal; + } + + @Override + public String toString() { + return "type=" + getKnownType() + ",orig=" + getOriginal() + ",date=" + getDate() + ",place=" + getPlace(); + } +} diff --git a/gedcomx-conclusion/src/main/java/org/gedcomx/conclusion/Gender.java b/gedcomx-conclusion/src/main/java/org/gedcomx/conclusion/Gender.java index af390a6c..94cb86d1 100644 --- a/gedcomx-conclusion/src/main/java/org/gedcomx/conclusion/Gender.java +++ b/gedcomx-conclusion/src/main/java/org/gedcomx/conclusion/Gender.java @@ -1,91 +1,106 @@ -/** - * Copyright 2011-2012 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.conclusion; - -import org.codehaus.jackson.annotate.JsonIgnore; -import org.codehaus.jackson.annotate.JsonProperty; -import org.codehaus.jackson.annotate.JsonTypeInfo; -import org.codehaus.jackson.map.annotate.JsonTypeIdResolver; -import org.gedcomx.common.URI; -import org.gedcomx.rt.CommonModels; -import org.gedcomx.rt.JsonElementWrapper; -import org.gedcomx.rt.XmlTypeIdResolver; -import org.gedcomx.types.GenderType; -import org.gedcomx.types.TypeReference; - -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlTransient; -import javax.xml.bind.annotation.XmlType; - -/** - * A gender conclusion. - * - * @author Ryan Heaton - */ -@JsonTypeInfo ( use =JsonTypeInfo.Id.CUSTOM, property = XmlTypeIdResolver.TYPE_PROPERTY_NAME) -@JsonTypeIdResolver (XmlTypeIdResolver.class) -@XmlType ( name = "Gender" ) -@XmlRootElement -@JsonElementWrapper ( name = "genders" ) -public class Gender extends Conclusion { - - @XmlElement (namespace = CommonModels.RDF_NAMESPACE) - @JsonProperty - private TypeReference type; - - /** - * The type of the gender. - * - * @return The type of the gender. - */ - @XmlTransient - @JsonIgnore - public URI getType() { - return this.type == null ? null : this.type.getType(); - } - - /** - * The type of the gender. - * - * @param type The type of the gender. - */ - @JsonIgnore - public void setType(URI type) { - this.type = type == null ? null : new TypeReference(type); - } - - /** - * The known type of the gender. - * - * @return The type of the gender. - */ - @XmlTransient - @JsonIgnore - public GenderType getKnownType() { - return this.type == null ? null : GenderType.fromQNameURI(this.type.getType()); - } - - /** - * The type of the gender. - * - * @param type The type of the gender. - */ - @JsonIgnore - public void setKnownType(GenderType type) { - this.type = type == null ? null : new TypeReference(type); - } -} +/** + * Copyright 2011-2012 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.conclusion; + +import org.codehaus.jackson.annotate.JsonIgnore; +import org.codehaus.jackson.annotate.JsonProperty; +import org.gedcomx.common.URI; +import org.gedcomx.rt.CommonModels; +import org.gedcomx.rt.json.JsonElementWrapper; +import org.gedcomx.types.GenderType; +import org.gedcomx.types.TypeReference; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; +import javax.xml.bind.annotation.XmlType; + +/** + * A gender conclusion. + * + * @author Ryan Heaton + */ +@XmlType ( name = "Gender" ) +@XmlRootElement +@JsonElementWrapper ( name = "genders" ) +public class Gender extends Conclusion { + + @XmlElement (namespace = CommonModels.RDF_NAMESPACE) + @JsonProperty + private TypeReference type; + + /** + * Default constructor. + */ + public Gender() { + } + + /** + * Constructs a new gender object with the passed in type. + * + * @param type The type of the gender. + */ + public Gender(GenderType type) { + setKnownType(type); + } + + /** + * The type of the gender. + * + * @return The type of the gender. + */ + @XmlTransient + @JsonIgnore + public URI getType() { + return this.type == null ? null : this.type.getType(); + } + + /** + * The type of the gender. + * + * @param type The type of the gender. + */ + @JsonIgnore + public void setType(URI type) { + this.type = type == null ? null : new TypeReference(type); + } + + /** + * The known type of the gender. + * + * @return The type of the gender. + */ + @XmlTransient + @JsonIgnore + public GenderType getKnownType() { + return this.type == null ? null : GenderType.fromQNameURI(this.type.getType()); + } + + /** + * The type of the gender. + * + * @param type The type of the gender. + */ + @JsonIgnore + public void setKnownType(GenderType type) { + this.type = type == null ? null : new TypeReference(type); + } + + @Override + public String toString() { + return "type=" + getKnownType(); + } +} diff --git a/gedcomx-conclusion/src/main/java/org/gedcomx/conclusion/Name.java b/gedcomx-conclusion/src/main/java/org/gedcomx/conclusion/Name.java index 4c9cf73d..9d5593f0 100644 --- a/gedcomx-conclusion/src/main/java/org/gedcomx/conclusion/Name.java +++ b/gedcomx-conclusion/src/main/java/org/gedcomx/conclusion/Name.java @@ -18,12 +18,9 @@ import org.codehaus.enunciate.json.JsonName; import org.codehaus.jackson.annotate.JsonIgnore; import org.codehaus.jackson.annotate.JsonProperty; -import org.codehaus.jackson.annotate.JsonTypeInfo; -import org.codehaus.jackson.map.annotate.JsonTypeIdResolver; import org.gedcomx.common.URI; import org.gedcomx.rt.CommonModels; -import org.gedcomx.rt.JsonElementWrapper; -import org.gedcomx.rt.XmlTypeIdResolver; +import org.gedcomx.rt.json.JsonElementWrapper; import org.gedcomx.types.NameType; import org.gedcomx.types.TypeReference; @@ -38,9 +35,7 @@ * * @author Ryan Heaton */ -@JsonTypeInfo ( use =JsonTypeInfo.Id.CUSTOM, property = XmlTypeIdResolver.TYPE_PROPERTY_NAME) -@JsonTypeIdResolver (XmlTypeIdResolver.class) -@XmlType ( name = "Name", propOrder = { "type", "primaryForm", "alternateForms" } ) +@XmlType ( name = "Name", propOrder = { "type", "preferred", "primaryForm", "alternateForms" } ) @XmlRootElement @JsonElementWrapper ( name = "names" ) public class Name extends Conclusion { @@ -50,6 +45,7 @@ public class Name extends Conclusion { private TypeReference type; private NameForm primaryForm; private List alternateForms; + private Boolean preferred; /** * The type of the name. @@ -132,4 +128,27 @@ public List getAlternateForms() { public void setAlternateForms(List alternateForms) { this.alternateForms = alternateForms; } + + /** + * Whether the conclusion is preferred above other conclusions of the same type. Useful, for example, for display purposes. + * + * @return Whether the conclusion is preferred above other conclusions of the same type. Useful, for example, for display purposes. + */ + public Boolean getPreferred() { + return preferred; + } + + /** + * Whether the conclusion is preferred above other conclusions of the same type. Useful, for example, for display purposes. + * + * @param preferred Whether the conclusion is preferred above other conclusions of the same type. Useful, for example, for display purposes. + */ + public void setPreferred(Boolean preferred) { + this.preferred = preferred; + } + + @Override + public String toString() { + return "type=" + getKnownType() + ",primaryform=" + (primaryForm == null?"null":primaryForm.getFullText()) + ",pref=" + getPreferred(); + } } diff --git a/gedcomx-conclusion/src/main/java/org/gedcomx/conclusion/Person.java b/gedcomx-conclusion/src/main/java/org/gedcomx/conclusion/Person.java index 854764ef..1d231c04 100644 --- a/gedcomx-conclusion/src/main/java/org/gedcomx/conclusion/Person.java +++ b/gedcomx-conclusion/src/main/java/org/gedcomx/conclusion/Person.java @@ -1,265 +1,353 @@ -/** - * Copyright 2011-2012 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.conclusion; - -import org.codehaus.enunciate.json.JsonName; -import org.codehaus.jackson.annotate.JsonIgnore; -import org.codehaus.jackson.annotate.JsonProperty; -import org.codehaus.jackson.annotate.JsonTypeInfo; -import org.codehaus.jackson.map.annotate.JsonTypeIdResolver; -import org.gedcomx.common.AlternateId; -import org.gedcomx.common.GenealogicalResource; -import org.gedcomx.common.Note; -import org.gedcomx.common.URI; -import org.gedcomx.rt.JsonElementWrapper; -import org.gedcomx.rt.XmlTypeIdResolver; -import org.gedcomx.types.FactType; - -import javax.xml.XMLConstants; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlSchemaType; -import javax.xml.bind.annotation.XmlType; -import java.util.ArrayList; -import java.util.List; - -/** - * A person. - * - * @author Ryan Heaton - */ -@XmlRootElement -@JsonElementWrapper (name = "persons") -@JsonTypeInfo ( use =JsonTypeInfo.Id.CUSTOM, property = XmlTypeIdResolver.TYPE_PROPERTY_NAME) -@JsonTypeIdResolver (XmlTypeIdResolver.class) -@XmlType ( name = "Person", propOrder = { "persistentId", "alternateIds", "living", "genders", "names", "facts", "sources", "notes" } ) -public class Person extends GenealogicalResource implements HasFacts, HasNotes, ReferencesSources { - - private URI persistentId; - private List alternateIds; - private Boolean living; - private List genders; - private List names; - private List facts; - private List sources; - private List notes; - - /** - * A long-term, persistent, globally unique identifier for this person. - * - * @return A long-term, persistent, globally unique identifier for this person. - */ - @XmlSchemaType (name = "anyURI", namespace = XMLConstants.W3C_XML_SCHEMA_NS_URI) - public URI getPersistentId() { - return persistentId; - } - - /** - * A long-term, persistent, globally unique identifier for this person. - * - * @param persistentId A long-term, persistent, globally unique identifier for this person. - */ - public void setPersistentId(URI persistentId) { - this.persistentId = persistentId; - } - - /** - * The list of alternate ids of the person. - * - * @return The list of alternate ids of the person. - */ - @XmlElement (name="alternateId") - @JsonProperty ("alternateIds") - @JsonName ("alternateIds") - public List getAlternateIds() { - return alternateIds; - } - - /** - * The list of alternate ids of the person. - * - * @param alternateIds The list of alternate ids of the person. - */ - @JsonProperty ("alternateIds") - public void setAlternateIds(List alternateIds) { - this.alternateIds = alternateIds; - } - - /** - * Living status of the person as treated by the system. The value of this property is intended - * to be based on a system-specific calculation and therefore has limited portability. Conclusions - * about the living status of a person can be modeled with a fact. - * - * @return Living status of the person as treated by the system. - */ - public Boolean getLiving() { - return living; - } - - /** - * Living status of the person as treated by the system. The value of this property is intended - * to be based on a system-specific calculation and therefore has limited portability. Conclusions - * about the living status of a person can be modeled with a fact. - * - * @param living Living status of the person as treated by the system. - */ - public void setLiving(Boolean living) { - this.living = living; - } - - /** - * The gender conclusions for the person. - * - * @return The gender conclusions for the person. - */ - @XmlElement(name="gender") - @JsonProperty("genders") - @JsonName("genders") - public List getGenders() { - return genders; - } - - /** - * The gender conclusions for the person. - * - * @param genders The gender conclusions for the person. - */ - @JsonProperty("genders") - public void setGenders(List genders) { - this.genders = genders; - } - - /** - * The name conclusions for the person. - * - * @return The name conclusions for the person. - */ - @XmlElement(name="name") - @JsonProperty("names") - @JsonName("names") - public List getNames() { - return names; - } - - /** - * The name conclusions for the person. - * - * @param names The name conclusions for the person. - */ - @JsonProperty("names") - public void setNames(List names) { - this.names = names; - } - - /** - * The fact conclusions for the person. - * - * @return The fact conclusions for the person. - */ - @XmlElement(name="fact") - @JsonProperty("facts") - @JsonName("facts") - public List getFacts() { - return facts; - } - - /** - * Helper method for obtaining specific fact conclusions. - * - * @param factType The type of facts to return. - * @return The fact conclusions that match the factType. An empty list will be returned if no facts are found. - */ - @JsonIgnore - public List getFacts(FactType factType) { - ArrayList factsToReturn = new ArrayList(); - if (facts != null && factType != null) { - for (Fact fact : facts) { - if (fact.getKnownType() != null && fact.getKnownType().equals(factType)) { - factsToReturn.add(fact); - } - } - } - return factsToReturn; - } - - /** - * The fact conclusions for the person. - * - * @param facts The fact conclusions for the person. - */ - @JsonProperty("facts") - public void setFacts(List facts) { - this.facts = facts; - } - - /** - * Add a fact conclusion to the person. - * - * @param fact The fact conclusion to be added. - */ - public void addFact(Fact fact) { - if (fact != null) { - if (facts == null) { - facts = new ArrayList(); - } - facts.add(fact); - } - } - - /** - * The source references for a resource. - * - * @return The source references for a resource. - */ - @XmlElement (name="source") - @JsonProperty ("sources") - @JsonName ("sources") - public List getSources() { - return sources; - } - - /** - * The source references for a person. - * - * @param sources The source references for a person. - */ - @JsonProperty("sources") - public void setSources(List sources) { - this.sources = sources; - } - - /** - * Notes about a person. - * - * @return Notes about a person. - */ - @XmlElement (name = "note") - @JsonProperty ("notes") - @JsonName ("notes") - public List getNotes() { - return notes; - } - - /** - * Notes about a person. - * - * @param notes Notes about a person. - */ - @JsonProperty ("notes") - public void setNotes(List notes) { - this.notes = notes; - } -} +/** + * Copyright 2011-2012 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.conclusion; + +import org.codehaus.enunciate.json.JsonName; +import org.codehaus.jackson.annotate.JsonIgnore; +import org.codehaus.jackson.annotate.JsonProperty; +import org.gedcomx.common.GenealogicalResource; +import org.gedcomx.common.Identifier; +import org.gedcomx.common.Note; +import org.gedcomx.common.URI; +import org.gedcomx.rt.json.JsonElementWrapper; +import org.gedcomx.types.FactType; +import org.gedcomx.types.IdentifierType; +import org.gedcomx.types.NameType; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; +import javax.xml.bind.annotation.XmlType; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * A person. + * + * @author Ryan Heaton + */ +@XmlRootElement +@JsonElementWrapper (name = "persons") +@XmlType ( name = "Person", propOrder = { "identifiers", "living", "gender", "names", "facts", "sources", "notes" } ) +public class Person extends GenealogicalResource implements HasFacts, HasNotes, ReferencesSources { + + private List identifiers; + private Boolean living; + private Gender gender; + private List names; + private List facts; + private List sources; + private List notes; + + /** + * Find the long-term, persistent identifier for this person from the list of identifiers. + * + * @return The long-term, persistent identifier for this person. + */ + @XmlTransient + @JsonIgnore + public URI getPersistentId() { + URI identifier = null; + if (this.identifiers != null) { + for (Identifier id : this.identifiers) { + if (IdentifierType.Primary.equals(id.getKnownType())) { + identifier = id.getValue() != null ? URI.create(id.getValue()) : null; + break; + } + } + } + return identifier; + } + + /** + * A long-term, persistent, globally unique identifier for this person. + * + * @param persistentId A long-term, persistent, globally unique identifier for this person. + */ + @JsonIgnore + public void setPersistentId(URI persistentId) { + if (this.identifiers == null) { + this.identifiers = new ArrayList(); + } + + //clear out any other primary ids. + Iterator it = this.identifiers.iterator(); + while (it.hasNext()) { + if (IdentifierType.Primary.equals(it.next().getKnownType())) { + it.remove(); + } + } + + Identifier identifier = new Identifier(); + identifier.setKnownType(IdentifierType.Primary); + identifier.setValue(persistentId.toString()); + this.identifiers.add(identifier); + } + + /** + * The list of identifiers for the person. + * + * @return The list of identifiers for the person. + */ + @XmlElement (name="identifier") + @JsonProperty ("identifiers") + @JsonName ("identifiers") + public List getIdentifiers() { + return identifiers; + } + + /** + * The list of identifiers of the person. + * + * @param identifiers The list of identifiers of the person. + */ + @JsonProperty ("identifiers") + public void setIdentifiers(List identifiers) { + this.identifiers = identifiers; + } + + /** + * Living status of the person as treated by the system. The value of this property is intended + * to be based on a system-specific calculation and therefore has limited portability. Conclusions + * about the living status of a person can be modeled with a fact. + * + * @return Living status of the person as treated by the system. + */ + public Boolean getLiving() { + return living; + } + + /** + * Living status of the person as treated by the system. The value of this property is intended + * to be based on a system-specific calculation and therefore has limited portability. Conclusions + * about the living status of a person can be modeled with a fact. + * + * @param living Living status of the person as treated by the system. + */ + public void setLiving(Boolean living) { + this.living = living; + } + + /** + * The gender conclusion for the person. + * + * @return The gender conclusion for the person. + */ + public Gender getGender() { + return gender; + } + + /** + * The gender conclusion for the person. + * + * @param gender The gender conclusion for the person. + */ + public void setGender(Gender gender) { + this.gender = gender; + } + + /** + * The name conclusions for the person. + * + * @return The name conclusions for the person. + */ + @XmlElement(name="name") + @JsonProperty("names") + @JsonName("names") + public List getNames() { + return names; + } + + /** + * Get the first name of the specified type. + * + * @param type The type. + * @return the first name in the name list of the specified type, or null if none. + */ + @JsonIgnore + public Name getFirstNameOfType(NameType type) { + if (this.names == null) { + return null; + } + + for (Name name : this.names) { + if (type.equals(name.getKnownType())) { + return name; + } + } + + return null; + } + + /** + * The name conclusions for the person. + * + * @param names The name conclusions for the person. + */ + @JsonProperty("names") + public void setNames(List names) { + this.names = names; + } + + /** + * The fact conclusions for the person. + * + * @return The fact conclusions for the person. + */ + @XmlElement(name="fact") + @JsonProperty("facts") + @JsonName("facts") + public List getFacts() { + return facts; + } + + /** + * Get the first fact of the specified type. + * + * @param type The type. + * @return the first fact in the fact list of the specified type, or null if none. + */ + @JsonIgnore + public Fact getFirstFactOfType(FactType type) { + if (this.facts == null) { + return null; + } + + for (Fact fact : this.facts) { + if (type.equals(fact.getKnownType())) { + return fact; + } + } + + return null; + } + + /** + * Helper method for obtaining specific fact conclusions. + * + * @param factType The type of facts to return. + * @return The fact conclusions that match the factType. An empty list will be returned if no facts are found. + */ + @JsonIgnore + public List getFacts(FactType factType) { + ArrayList factsToReturn = new ArrayList(); + if (facts != null && factType != null) { + for (Fact fact : facts) { + if (fact.getKnownType() != null && fact.getKnownType().equals(factType)) { + factsToReturn.add(fact); + } + } + } + return factsToReturn; + } + + /** + * The fact conclusions for the person. + * + * @param facts The fact conclusions for the person. + */ + @JsonProperty("facts") + public void setFacts(List facts) { + this.facts = facts; + } + + /** + * Add a fact conclusion to the person. + * + * @param fact The fact conclusion to be added. + */ + public void addFact(Fact fact) { + if (fact != null) { + if (facts == null) { + facts = new ArrayList(); + } + facts.add(fact); + } + } + + /** + * The source references for a resource. + * + * @return The source references for a resource. + */ + @XmlElement (name="source") + @JsonProperty ("sources") + @JsonName ("sources") + public List getSources() { + return sources; + } + + /** + * The source references for a person. + * + * @param sources The source references for a person. + */ + @JsonProperty("sources") + public void setSources(List sources) { + this.sources = sources; + } + + /** + * Add a sourceReference. + * + * @param sourceReference The sourceReference to be added. + */ + public void addSource(SourceReference sourceReference) { + if (sourceReference != null) { + if (sources == null) { + sources = new ArrayList(); + } + sources.add(sourceReference); + } + } + + /** + * Notes about a person. + * + * @return Notes about a person. + */ + @XmlElement (name = "note") + @JsonProperty ("notes") + @JsonName ("notes") + public List getNotes() { + return notes; + } + + /** + * Notes about a person. + * + * @param notes Notes about a person. + */ + @JsonProperty ("notes") + public void setNotes(List notes) { + this.notes = notes; + } + + /** + * Add a note. + * + * @param note The note to be added. + */ + public void addNote(Note note) { + if (note != null) { + if (notes == null) { + notes = new ArrayList(); + } + notes.add(note); + } + } +} diff --git a/gedcomx-conclusion/src/main/java/org/gedcomx/conclusion/Relationship.java b/gedcomx-conclusion/src/main/java/org/gedcomx/conclusion/Relationship.java index 240646ea..f7358373 100644 --- a/gedcomx-conclusion/src/main/java/org/gedcomx/conclusion/Relationship.java +++ b/gedcomx-conclusion/src/main/java/org/gedcomx/conclusion/Relationship.java @@ -1,221 +1,263 @@ -/** - * Copyright 2011-2012 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.conclusion; - -import org.codehaus.enunciate.json.JsonName; -import org.codehaus.jackson.annotate.JsonIgnore; -import org.codehaus.jackson.annotate.JsonProperty; -import org.codehaus.jackson.annotate.JsonTypeInfo; -import org.codehaus.jackson.map.annotate.JsonTypeIdResolver; -import org.gedcomx.common.GenealogicalResource; -import org.gedcomx.common.Note; -import org.gedcomx.common.ResourceReference; -import org.gedcomx.common.URI; -import org.gedcomx.rt.*; -import org.gedcomx.types.RelationshipType; -import org.gedcomx.types.TypeReference; - -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlTransient; -import javax.xml.bind.annotation.XmlType; -import java.util.List; - -/** - * A relationship between two or more persons. - * - * @author Ryan Heaton - */ -@XmlRootElement -@JsonElementWrapper ( name = "relationships" ) -@JsonTypeInfo ( use =JsonTypeInfo.Id.CUSTOM, property = XmlTypeIdResolver.TYPE_PROPERTY_NAME) -@JsonTypeIdResolver (XmlTypeIdResolver.class) -@XmlType ( name = "Relationship", propOrder = { "type", "person1", "person2", "facts", "sources", "notes" } ) -public class Relationship extends GenealogicalResource implements HasFacts, HasNotes, ReferencesSources { - - @XmlElement (namespace = CommonModels.RDF_NAMESPACE) - @JsonProperty - private TypeReference type; - private ResourceReference person1; - private ResourceReference person2; - private List facts; - private List sources; - private List notes; - - /** - * The type of this relationship. - * - * @return The type of this relationship. - */ - @XmlTransient - @JsonIgnore - public URI getType() { - return this.type == null ? null : this.type.getType(); - } - - /** - * The type of this relationship. - * - * @param type The type of this relationship. - */ - @JsonIgnore - public void setType(URI type) { - this.type = type == null ? null : new TypeReference(type); - } - - /** - * The enum referencing the known type of the relationship, or {@link org.gedcomx.types.RelationshipType#OTHER} if not known. - * - * @return The enum referencing the known type of the relationship, or {@link org.gedcomx.types.RelationshipType#OTHER} if not known. - */ - @XmlTransient - @JsonIgnore - public RelationshipType getKnownType() { - return this.type == null ? null : RelationshipType.fromQNameURI(this.type.getType()); - } - - /** - * Set the relationship type from a known enumeration of relationship types. - * - * @param type The relationship type. - */ - @JsonIgnore - public void setKnownType(RelationshipType type) { - this.type = type == null ? null : new TypeReference(type); - } - - /** - * A reference to a person in the relationship. The name "person1" is used only to distinguish it from - * the other person in this relationship and implies neither order nor role. When the relationship type - * implies direction, it goes from "person1" to "person2". - * - * @return A reference to a person in the relationship. The name "person1" is used only to distinguish it from - * the other person in this relationship and implies neither order nor role. When the relationship type - * implies direction, it goes from "person1" to "person2". - */ - @RDFRange (Person.class) - @RDFSubPropertyOf ( CommonModels.DUBLIN_CORE_NAMESPACE + "hasPart") - public ResourceReference getPerson1() { - return person1; - } - - /** - * A reference to a person in the relationship. The name "person1" is used only to distinguish it from - * the other person in this relationship and implies neither order nor role. When the relationship type - * implies direction, it goes from "person1" to "person2". - * - * @param person1 A reference to a person in the relationship. The name "person1" is used only to distinguish it from - * the other person in this relationship and implies neither order nor role. When the relationship type - * implies direction, it goes from "person1" to "person2". - */ - public void setPerson1(ResourceReference person1) { - this.person1 = person1; - } - - /** - * A reference to a person in the relationship. The name "person2" is used only to distinguish it from - * the other person in this relationship and implies neither order nor role. When the relationship type - * implies direction, it goes from "person1" to "person2". - * - * @return A reference to a person in the relationship. The name "person2" is used only to distinguish it from - * the other person in this relationship and implies neither order nor role. When the relationship type - * implies direction, it goes from "person1" to "person2". - */ - @RDFRange (Person.class) - @RDFSubPropertyOf ( CommonModels.DUBLIN_CORE_NAMESPACE + "hasPart") - public ResourceReference getPerson2() { - return person2; - } - - /** - * A reference to a person in the relationship. The name "person2" is used only to distinguish it from - * the other person in this relationship and implies neither order nor role. When the relationship type - * implies direction, it goes from "person1" to "person2". - * - * @param person2 A reference to a person in the relationship. The name "person2" is used only to distinguish it from - * the other person in this relationship and implies neither order nor role. When the relationship type - * implies direction, it goes from "person1" to "person2". - */ - public void setPerson2(ResourceReference person2) { - this.person2 = person2; - } - - /** - * The fact conclusions for the relationship. - * - * @return The fact conclusions for the relationship. - */ - @XmlElement(name="fact") - @JsonProperty("facts") - @JsonName("facts") - public List getFacts() { - return facts; - } - - /** - * The fact conclusions for the relationship. - * - * @param facts The fact conclusions for the relationship. - */ - @JsonProperty("facts") - public void setFacts(List facts) { - this.facts = facts; - } - - /** - * The source references for a resource. - * - * @return The source references for a resource. - */ - @XmlElement (name="source") - @JsonProperty ("sources") - @JsonName ("sources") - public List getSources() { - return sources; - } - - /** - * The source references for a resource. - * - * @param sources The source references for a resource. - */ - @JsonProperty("sources") - public void setSources(List sources) { - this.sources = sources; - } - - /** - * Notes about a resource. - * - * @return Notes about a resource. - */ - @XmlElement (name = "note") - @JsonProperty ("notes") - @JsonName ("notes") - public List getNotes() { - return notes; - } - - /** - * Notes about a resource. - * - * @param notes Notes about a resource. - */ - @JsonProperty ("notes") - public void setNotes(List notes) { - this.notes = notes; - } -} +/** + * Copyright 2011-2012 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.conclusion; + +import org.codehaus.enunciate.json.JsonName; +import org.codehaus.jackson.annotate.JsonIgnore; +import org.codehaus.jackson.annotate.JsonProperty; +import org.gedcomx.common.GenealogicalResource; +import org.gedcomx.common.Note; +import org.gedcomx.common.ResourceReference; +import org.gedcomx.common.URI; +import org.gedcomx.rt.CommonModels; +import org.gedcomx.rt.json.JsonElementWrapper; +import org.gedcomx.rt.RDFRange; +import org.gedcomx.rt.RDFSubPropertyOf; +import org.gedcomx.types.RelationshipType; +import org.gedcomx.types.TypeReference; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; +import javax.xml.bind.annotation.XmlType; +import java.util.ArrayList; +import java.util.List; + +/** + * A relationship between two or more persons. + * + * @author Ryan Heaton + */ +@XmlRootElement +@JsonElementWrapper ( name = "relationships" ) +@XmlType ( name = "Relationship", propOrder = { "type", "person1", "person2", "facts", "sources", "notes" } ) +public class Relationship extends GenealogicalResource implements HasFacts, HasNotes, ReferencesSources { + + @XmlElement (namespace = CommonModels.RDF_NAMESPACE) + @JsonProperty + private TypeReference type; + private ResourceReference person1; + private ResourceReference person2; + private List facts; + private List sources; + private List notes; + + /** + * The type of this relationship. + * + * @return The type of this relationship. + */ + @XmlTransient + @JsonIgnore + public URI getType() { + return this.type == null ? null : this.type.getType(); + } + + /** + * The type of this relationship. + * + * @param type The type of this relationship. + */ + @JsonIgnore + public void setType(URI type) { + this.type = type == null ? null : new TypeReference(type); + } + + /** + * The enum referencing the known type of the relationship, or {@link org.gedcomx.types.RelationshipType#OTHER} if not known. + * + * @return The enum referencing the known type of the relationship, or {@link org.gedcomx.types.RelationshipType#OTHER} if not known. + */ + @XmlTransient + @JsonIgnore + public RelationshipType getKnownType() { + return this.type == null ? null : RelationshipType.fromQNameURI(this.type.getType()); + } + + /** + * Set the relationship type from a known enumeration of relationship types. + * + * @param type The relationship type. + */ + @JsonIgnore + public void setKnownType(RelationshipType type) { + this.type = type == null ? null : new TypeReference(type); + } + + /** + * A reference to a person in the relationship. The name "person1" is used only to distinguish it from + * the other person in this relationship and implies neither order nor role. When the relationship type + * implies direction, it goes from "person1" to "person2". + * + * @return A reference to a person in the relationship. The name "person1" is used only to distinguish it from + * the other person in this relationship and implies neither order nor role. When the relationship type + * implies direction, it goes from "person1" to "person2". + */ + @RDFRange (Person.class) + @RDFSubPropertyOf ( CommonModels.DUBLIN_CORE_NAMESPACE + "hasPart") + public ResourceReference getPerson1() { + return person1; + } + + /** + * A reference to a person in the relationship. The name "person1" is used only to distinguish it from + * the other person in this relationship and implies neither order nor role. When the relationship type + * implies direction, it goes from "person1" to "person2". + * + * @param person1 A reference to a person in the relationship. The name "person1" is used only to distinguish it from + * the other person in this relationship and implies neither order nor role. When the relationship type + * implies direction, it goes from "person1" to "person2". + */ + public void setPerson1(ResourceReference person1) { + this.person1 = person1; + } + + /** + * A reference to a person in the relationship. The name "person2" is used only to distinguish it from + * the other person in this relationship and implies neither order nor role. When the relationship type + * implies direction, it goes from "person1" to "person2". + * + * @return A reference to a person in the relationship. The name "person2" is used only to distinguish it from + * the other person in this relationship and implies neither order nor role. When the relationship type + * implies direction, it goes from "person1" to "person2". + */ + @RDFRange (Person.class) + @RDFSubPropertyOf ( CommonModels.DUBLIN_CORE_NAMESPACE + "hasPart") + public ResourceReference getPerson2() { + return person2; + } + + /** + * A reference to a person in the relationship. The name "person2" is used only to distinguish it from + * the other person in this relationship and implies neither order nor role. When the relationship type + * implies direction, it goes from "person1" to "person2". + * + * @param person2 A reference to a person in the relationship. The name "person2" is used only to distinguish it from + * the other person in this relationship and implies neither order nor role. When the relationship type + * implies direction, it goes from "person1" to "person2". + */ + public void setPerson2(ResourceReference person2) { + this.person2 = person2; + } + + /** + * The fact conclusions for the relationship. + * + * @return The fact conclusions for the relationship. + */ + @XmlElement(name="fact") + @JsonProperty("facts") + @JsonName("facts") + public List getFacts() { + return facts; + } + + /** + * The fact conclusions for the relationship. + * + * @param facts The fact conclusions for the relationship. + */ + @JsonProperty("facts") + public void setFacts(List facts) { + this.facts = facts; + } + + /** + * Add a fact conclusion. + * + * @param fact The fact conclusion to be added. + */ + public void addFact(Fact fact) { + if (fact != null) { + if (facts == null) { + facts = new ArrayList(); + } + facts.add(fact); + } + } + + /** + * The source references for a resource. + * + * @return The source references for a resource. + */ + @XmlElement (name="source") + @JsonProperty ("sources") + @JsonName ("sources") + public List getSources() { + return sources; + } + + /** + * The source references for a resource. + * + * @param sources The source references for a resource. + */ + @JsonProperty("sources") + public void setSources(List sources) { + this.sources = sources; + } + + /** + * Add a sourceReference. + * + * @param sourceReference The sourceReference to be added. + */ + public void addSource(SourceReference sourceReference) { + if (sourceReference != null) { + if (sources == null) { + sources = new ArrayList(); + } + sources.add(sourceReference); + } + } + + /** + * Notes about a resource. + * + * @return Notes about a resource. + */ + @XmlElement (name = "note") + @JsonProperty ("notes") + @JsonName ("notes") + public List getNotes() { + return notes; + } + + /** + * Notes about a resource. + * + * @param notes Notes about a resource. + */ + @JsonProperty ("notes") + public void setNotes(List notes) { + this.notes = notes; + } + + /** + * Add a note. + * + * @param note The note to be added. + */ + public void addNote(Note note) { + if (note != null) { + if (notes == null) { + notes = new ArrayList(); + } + notes.add(note); + } + } +} diff --git a/gedcomx-conclusion/src/main/java/org/gedcomx/conclusion/SourceReference.java b/gedcomx-conclusion/src/main/java/org/gedcomx/conclusion/SourceReference.java index e4911a24..05018352 100644 --- a/gedcomx-conclusion/src/main/java/org/gedcomx/conclusion/SourceReference.java +++ b/gedcomx-conclusion/src/main/java/org/gedcomx/conclusion/SourceReference.java @@ -1,84 +1,297 @@ -/** - * Copyright 2011-2012 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.conclusion; - -import org.codehaus.jackson.annotate.JsonTypeInfo; -import org.codehaus.jackson.map.annotate.JsonTypeIdResolver; -import org.gedcomx.common.Attributable; -import org.gedcomx.common.Attribution; -import org.gedcomx.common.ResourceReference; -import org.gedcomx.rt.CommonModels; -import org.gedcomx.rt.JsonElementWrapper; -import org.gedcomx.rt.RDFRange; -import org.gedcomx.rt.XmlTypeIdResolver; - -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlType; - -/** - * An attributable reference to a source for genealogical conclusions. - * - * @author Ryan Heaton - */ -@XmlRootElement -@JsonElementWrapper ( name = "attribution" ) -@JsonTypeInfo ( use = JsonTypeInfo.Id.CUSTOM, property = XmlTypeIdResolver.TYPE_PROPERTY_NAME) -@JsonTypeIdResolver (XmlTypeIdResolver.class) -@XmlType ( name = "SourceReference" ) -public class SourceReference extends ResourceReference implements Attributable { - - private Attribution attribution; - private ResourceReference description; - - /** - * The attribution metadata for this source reference. - * - * @return The attribution metadata for this source reference. - */ - @XmlElement ( namespace = CommonModels.GEDCOMX_COMMON_NAMESPACE ) - public Attribution getAttribution() { - return attribution; - } - - /** - * The attribution metadata for this source reference. - * - * @param attribution The attribution metadata for this source reference. - */ - public void setAttribution(Attribution attribution) { - this.attribution = attribution; - } - - /** - * A reference to a description about the source being referenced. - * - * @return A reference to a description about the source being referenced. - */ - @RDFRange( external = "org.gedcomx.metadata.rdf.RDFDescription" ) - public ResourceReference getDescription() { - return description; - } - - /** - * A reference to a description about the source being referenced. - * - * @param description A reference to a description about the source being referenced. - */ - public void setDescription(ResourceReference description) { - this.description = description; - } -} +/** + * Copyright 2011-2012 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.conclusion; + +import org.codehaus.enunciate.doc.DocumentationExample; +import org.codehaus.jackson.annotate.JsonIgnore; +import org.codehaus.jackson.annotate.JsonProperty; +import org.gedcomx.common.Attributable; +import org.gedcomx.common.Attribution; +import org.gedcomx.common.ResourceReference; +import org.gedcomx.common.URI; +import org.gedcomx.rt.CommonModels; +import org.gedcomx.rt.SupportsExtensionAttributes; +import org.gedcomx.rt.SupportsExtensionElements; +import org.gedcomx.rt.json.JsonElementWrapper; +import org.gedcomx.rt.RDFRange; +import org.gedcomx.types.ResourceType; +import org.gedcomx.types.TypeReference; + +import javax.xml.XMLConstants; +import javax.xml.bind.annotation.*; +import javax.xml.namespace.QName; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * An attributable reference to a source for genealogical conclusions. + * + * @author Ryan Heaton + */ +@XmlRootElement ( name = "source" ) +@JsonElementWrapper ( name = "source-references" ) +@XmlType ( name = "SourceReference" ) +public class SourceReference implements Attributable, SupportsExtensionAttributes, SupportsExtensionElements { + + private String id; + @XmlElement (namespace = CommonModels.RDF_NAMESPACE) + @JsonProperty + private TypeReference type; + private URI resource; + private Attribution attribution; + private ResourceReference description; + private Map extensionAttributes; + private List extensionElements; + + /** + * The id of this resource reference. Note the distinction between this id and the id of the + * resource being referenced. + * + * @return The id of this resource reference. Note the distinction between this id and the id of the + * resource being referenced. + */ + @XmlID + @XmlAttribute ( name = "ID", namespace = CommonModels.RDF_NAMESPACE ) + @DocumentationExample (exclude = true) + public String getId() { + return id; + } + + /** + * The id of this resource reference. Note the distinction between this id and the id of the + * resource being referenced. + * + * @param id The id of this resource reference. Note the distinction between this id and the id of the + * resource being referenced. + */ + public void setId(String id) { + this.id = id; + } + + /** + * The type of the resource being referenced. + * + * @return The type of the resource being referenced. + */ + @XmlTransient + @JsonIgnore + public URI getType() { + return this.type == null ? null : this.type.getType(); + } + + /** + * The type of the resource being referenced. + * + * @param type The type of the resource being referenced. + */ + @JsonIgnore + public void setType(URI type) { + this.type = type == null ? null : new TypeReference(type); + } + + /** + * The enum referencing the known type of the resource being referenced, or {@link org.gedcomx.types.ResourceType#OTHER} if not known. + * + * @return The enum referencing the known type of the source reference, or {@link org.gedcomx.types.ResourceType#OTHER} if not known. + */ + @XmlTransient + @JsonIgnore + public ResourceType getKnownType() { + return this.type == null ? null : ResourceType.fromQNameURI(this.type.getType()); + } + + /** + * Set the type of this reference from an enumeration of known source reference types. + * + * @param knownType The reference type. + */ + @JsonIgnore + public void setKnownType(ResourceType knownType) { + this.type = knownType == null ? null : new TypeReference(knownType); + } + + /** + * The URI to the resource. For more information, see Architecture of the World + * Wide Web, Volume One, Section 2 + * + * @link http://www.w3.org/TR/webarch/#identification + * @return The URI to the resource. + */ + @XmlAttribute (namespace= CommonModels.RDF_NAMESPACE) + @XmlSchemaType (name = "anyURI", namespace = XMLConstants.W3C_XML_SCHEMA_NS_URI) + public URI getResource() { + return resource; + } + + /** + * The URI to the resource. For more information, see Architecture of the World + * Wide Web, Volume One, Section 2 + * + * @link http://www.w3.org/TR/webarch/#identification + * @param resource The URI to the resource. + */ + public void setResource(URI resource) { + this.resource = resource; + } + + /** + * The attribution metadata for this source reference. + * + * @return The attribution metadata for this source reference. + */ + @XmlElement ( namespace = CommonModels.GEDCOMX_COMMON_NAMESPACE ) + public Attribution getAttribution() { + return attribution; + } + + /** + * The attribution metadata for this source reference. + * + * @param attribution The attribution metadata for this source reference. + */ + public void setAttribution(Attribution attribution) { + this.attribution = attribution; + } + + /** + * A reference to a description about the source being referenced. + * + * @return A reference to a description about the source being referenced. + */ + @RDFRange( external = "org.gedcomx.metadata.rdf.RDFDescription" ) + public ResourceReference getDescription() { + return description; + } + + /** + * A reference to a description about the source being referenced. + * + * @param description A reference to a description about the source being referenced. + */ + public void setDescription(ResourceReference description) { + this.description = description; + } + + /** + * Custom attributes applicable to this resource reference. + * + * @return Custom attributes applicable to this resource reference. + */ + @XmlAnyAttribute + @JsonIgnore + public Map getExtensionAttributes() { + return extensionAttributes; + } + + /** + * Custom attributes applicable to this resource reference. + * + * @param extensionAttributes Custom attributes applicable to this resource reference. + */ + @JsonIgnore + public void setExtensionAttributes(Map extensionAttributes) { + this.extensionAttributes = extensionAttributes; + } + + /** + * Add a custom extension attribute. + * + * @param qname The qname of the attribute. + * @param value The value of the attribute. + */ + public void addExtensionAttribute(QName qname, String value) { + if (this.extensionAttributes == null) { + this.extensionAttributes = new HashMap(); + } + + this.extensionAttributes.put(qname, value); + } + + /** + * Custom attributes applicable to this resource reference. + * + * @return Custom attributes applicable to this resource reference. + */ + @XmlAnyElement ( lax = true ) + @JsonIgnore + public List getExtensionElements() { + return extensionElements; + } + + /** + * Custom attributes applicable to this resource reference. + * + * @param extensionElements Custom attributes applicable to this resource reference. + */ + @JsonIgnore + public void setExtensionElements(List extensionElements) { + this.extensionElements = extensionElements; + } + + /** + * Add an extension element. + * + * @param element The extension element to add. + */ + public void addExtensionElement(Object element) { + if (this.extensionElements == null) { + this.extensionElements = new ArrayList(); + } + + this.extensionElements.add(element); + } + + /** + * Finds the first extension of a specified type. + * + * @param clazz The type. + * @return The extension, or null if none found. + */ + @SuppressWarnings ( {"unchecked"} ) + public E findExtensionOfType(Class clazz) { + if (this.extensionElements != null) { + for (Object extension : extensionElements) { + if (clazz.isInstance(extension)) { + return (E) extension; + } + } + } + + return null; + } + + /** + * Find the extensions of a specified type. + * + * @param clazz The type. + * @return The extensions, possibly empty but not null. + */ + @SuppressWarnings ( {"unchecked"} ) + public List findExtensionsOfType(Class clazz) { + List ext = new ArrayList(); + if (this.extensionElements != null) { + for (Object extension : extensionElements) { + if (clazz.isInstance(extension)) { + ext.add((E) extension); + } + } + } + + return ext; + } +} diff --git a/gedcomx-conclusion/src/test/java/org/gedcomx/conclusion/CustomEntity.java b/gedcomx-conclusion/src/test/java/org/gedcomx/conclusion/CustomEntity.java new file mode 100644 index 00000000..e4739988 --- /dev/null +++ b/gedcomx-conclusion/src/test/java/org/gedcomx/conclusion/CustomEntity.java @@ -0,0 +1,41 @@ +package org.gedcomx.conclusion; + +import org.gedcomx.common.GenealogicalResource; +import org.gedcomx.common.URI; +import org.gedcomx.rt.json.JsonElementWrapper; + +import javax.xml.bind.annotation.XmlRootElement; + +/** + * @author Ryan Heaton + */ +@XmlRootElement +@JsonElementWrapper (name = "customEntities") +public class CustomEntity extends GenealogicalResource { + + private SourceReference source; + private URI refToSomething; + + public CustomEntity() { + } + + public CustomEntity(String id) { + setId(id); + } + + public SourceReference getSource() { + return this.source; + } + + public void setSource(SourceReference source) { + this.source = source; + } + + public URI getRefToSomething() { + return refToSomething; + } + + public void setRefToSomething(URI refToSomething) { + this.refToSomething = refToSomething; + } +} diff --git a/gedcomx-conclusion/src/test/java/org/gedcomx/conclusion/DateRecipesTest.java b/gedcomx-conclusion/src/test/java/org/gedcomx/conclusion/DateRecipesTest.java index 5a6af07b..8eaf5830 100644 --- a/gedcomx-conclusion/src/test/java/org/gedcomx/conclusion/DateRecipesTest.java +++ b/gedcomx-conclusion/src/test/java/org/gedcomx/conclusion/DateRecipesTest.java @@ -1,9 +1,9 @@ package org.gedcomx.conclusion; import org.gedcomx.common.FormalValue; -import org.gedcomx.common.URI; import org.gedcomx.test.RecipeTest; import org.gedcomx.test.Snippet; +import org.gedcomx.types.DateFormatType; import org.gedcomx.types.FactType; import org.testng.annotations.Test; @@ -18,9 +18,9 @@ @Test public class DateRecipesTest extends RecipeTest { - public void testDateFormalValue() throws Exception { - createRecipe("Simple Formal Date") - .withDescription("Simple recipe for how to use dates.") + public void testDateFormalValueIso8601() throws Exception { + createRecipe("Standardized Date Using ISO 8601") + .withDescription("Simple recipe for creating a standardized date using the ISO 8601 standard. The example shows a person born on July 1, 1980.") .applicableTo(Date.class); @@ -33,7 +33,7 @@ public void testDateFormalValue() throws Exception { Date date = new Date(); date.setOriginal("1 July 1980"); FormalValue formal = new FormalValue(); - formal.setDatatype(URI.create("iso:123456")); + formal.setKnownValue(DateFormatType.ISO8601); formal.setText("1980-07-01"); date.setFormal(formal); fact.setDate(date); @@ -47,4 +47,34 @@ public void testDateFormalValue() throws Exception { } + + public void testDateFormalValueGedcom55() throws Exception { + createRecipe("Standardized Date Using GEDCOM 5.5") + .withDescription("Simple recipe for creating a standardized date using the GEDCOM 5.5 standard. The example shows a person born about July 1, 1980.") + .applicableTo(Date.class); + + + Person person = new Person(); + person.setId("12345"); + person.setFacts(new ArrayList()); + Fact fact = new Fact(); + fact.setKnownType(FactType.Birth); + person.getFacts().add(fact); + Date date = new Date(); + date.setOriginal("About July 1, 1980"); + FormalValue formal = new FormalValue(); + formal.setKnownValue(DateFormatType.GEDCOM_5_5); + formal.setText("ABT 01 JUL 1980"); + date.setFormal(formal); + fact.setDate(date); + + Snippet snippet = new Snippet(); + person = processThroughXml(person, snippet); + //todo: verify person. + person = processThroughJson(person, snippet); + //todo: verify person. + addSnippet(snippet); + + } + } diff --git a/gedcomx-conclusion/src/test/java/org/gedcomx/conclusion/EvidenceRecipesTest.java b/gedcomx-conclusion/src/test/java/org/gedcomx/conclusion/EvidenceRecipesTest.java new file mode 100644 index 00000000..a92cac3b --- /dev/null +++ b/gedcomx-conclusion/src/test/java/org/gedcomx/conclusion/EvidenceRecipesTest.java @@ -0,0 +1,360 @@ +package org.gedcomx.conclusion; + +import org.gedcomx.common.Attribution; +import org.gedcomx.common.ResourceReference; +import org.gedcomx.common.URI; +import org.gedcomx.metadata.dc.DublinCoreDescriptionDecorator; +import org.gedcomx.metadata.rdf.Description; +import org.gedcomx.metadata.rdf.RDFLiteral; +import org.gedcomx.metadata.rdf.RDFValue; +import org.gedcomx.test.RecipeTest; +import org.gedcomx.test.Snippet; +import org.gedcomx.types.FactType; +import org.gedcomx.types.GenderType; +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.gedcomx.rt.SerializationUtil.processThroughJson; +import static org.gedcomx.rt.SerializationUtil.processThroughXml; + +/** + * Recipes for citing evidence in GEDCOM X. + * @author Ryan Heaton + */ +@Test +public class EvidenceRecipesTest extends RecipeTest { + + /** + * tests citing an online record. + */ + public void testCitingOnlineArtifact() throws Exception { + createRecipe("Citing an Online Artifact") + .withDescription("The following example illustrates how to cite an online record. Evidence for Israel Hoyt Heaton is found in the 1920 U.S. Census. The URI to the record is \"https://familysearch.org/pal:/MM9.1.1/M8PT-4GN\". The URI for a description of the record is \"https://familysearch.org/platform/sources/GGG-GGGG\".") + .applicableTo(Person.class); + + Person person = createPersonCitingOnlineArtifact(); + Snippet snippet = new Snippet("The person."); + processThroughXml(person, snippet); + processThroughJson(person, snippet); + addSnippet(snippet); + + snippet = new Snippet("The description of the source. The URI to the description is \"https://familysearch.org/platform/sources/GGG-GGGG\"."); + Description description = createDescriptionOfOnlineArtifact(); + processThroughXml(description, snippet); + processThroughJson(description, snippet); + addSnippet(snippet); + +// assertEquals(person); + } + + static Description createDescriptionOfOnlineArtifact() { + return DublinCoreDescriptionDecorator.newInstance() + .bibliographicCitation(new RDFLiteral("\"United States Census, 1920,\" index and images, FamilySearch (https://familysearch.org/pal:/MM9.1.1/M8PT-4GN : accessed 31 May 2012), Israel H Heaton, , Kane, Utah.")) + .title(new RDFLiteral("\"United States Census, 1920,\" Israel H Heaton, , Kane, Utah")) + .about(URI.create("https://familysearch.org/pal:/MM9.1.1/M8PT-4GN")) + .getDecoratedDescription(); + } + + static Person createPersonCitingOnlineArtifact() { + Person person = new Person(); + person.setGender(new Gender(GenderType.Male)); + + Fact fact = new Fact(); + fact.setId("123"); + fact.setKnownType(FactType.Birth); + + fact.setAttribution(new Attribution()); + fact.getAttribution().setContributor(new ResourceReference()); + fact.getAttribution().getContributor().setResource(URI.create("https://familysearch.org/platform/contributors/BCD-FGHJ")); + fact.setDate(new Date()); + fact.getDate().setOriginal("30 January 1880"); + + fact.setPlace(new Place()); + fact.getPlace().setOriginal("Orderville, Utah"); + + person.addFact(fact); + + fact = new Fact(); + fact.setId("456"); + fact.setKnownType(FactType.Death); + + fact.setAttribution(new Attribution()); + fact.getAttribution().setContributor(new ResourceReference()); + fact.getAttribution().getContributor().setResource(URI.create("https://familysearch.org/platform/contributors/KLM-NPQR")); + fact.setDate(new Date()); + fact.getDate().setOriginal("29 August 1936"); + + fact.setPlace(new Place()); + fact.getPlace().setOriginal("Kanab, Kane, UT"); + + person.addFact(fact); + + List names = new ArrayList(); + Name name = new Name(); + name.setPreferred(true); + NameForm nameForm = new NameForm(); + nameForm.setFullText("Israel Hoyt Heaton"); + name.setPrimaryForm(nameForm); + name.setAttribution(new Attribution()); + name.getAttribution().setContributor(new ResourceReference()); + name.getAttribution().getContributor().setResource(URI.create("https://familysearch.org/platform/contributors/STV-WXZY")); + name.setId("789"); + names.add(name); + person.setNames(names); + + ArrayList sources = new ArrayList(); + SourceReference attributedSourceReference = new SourceReference(); + Attribution attribution = new Attribution(); + attribution.setContributor(new ResourceReference()); + attribution.getContributor().setResource(URI.create("https://familysearch.org/platform/contributors/STV-WXZY")); + attributedSourceReference.setAttribution(attribution); + attributedSourceReference.setResource(URI.create("https://familysearch.org/pal:/MM9.1.1/M8PT-4GN")); + attributedSourceReference.setDescription(new ResourceReference()); + attributedSourceReference.getDescription().setResource(URI.create("https://familysearch.org/platform/sources/GGG-GGGG")); + sources.add(attributedSourceReference); + person.setSources(sources); + + person.setId("KWCD-QBC"); + + return person; + } + + /** + * tests citing an online record. + */ + public void testCitingPhysicalArtifact() throws Exception { + createRecipe("Citing a Physical Artifact") + .withDescription("The following example illustrates how to cite a physical artifact, such as a book. Evidence for Asa Phillips is found in a book authored by Helen Kelly Brink. The book doesn't have a URI, but the URI for a description of the book is \"https://familysearch.org/platform/sources/KKK-KKKK\".") + .applicableTo(Person.class); + + Person person = createPersonCitingPhysicalArtifact(); + Snippet snippet = new Snippet("The person."); + processThroughXml(person, snippet); + processThroughJson(person, snippet); + addSnippet(snippet); + + snippet = new Snippet("The description of the source. The URI to the description is \"https://familysearch.org/platform/sources/KKK-KKKK\"."); + Description description = createDescriptionOfPhysicalArtifact(); + processThroughXml(description, snippet); + processThroughJson(description, snippet); + addSnippet(snippet); + +// assertEquals(person); + } + + static Description createDescriptionOfPhysicalArtifact() { + return DublinCoreDescriptionDecorator.newInstance() + .bibliographicCitation(new RDFLiteral("Helen Kelly Brink, Some of the Descendants of Asa Phillips (1793-1844); Who were Born in Vermont and Who Settled in Steuben County, New York in 1802, (Marco Island, Florida, By the Author, 1992) p.34")) + .title(new RDFLiteral("Some of the Descendants of Asa Phillips (1793-1844); Who were Born in Vermont and Who Settled in Steuben County, New York in 1802")) + .creator(new RDFValue("Helen Kelly Brink")) + .publisher(new RDFValue("Helen Kelly Brink")) + .temporal(new RDFValue("1802")) + .spatial(new RDFValue("Steuben County, New York")) + .id("KKK-KKKK") + .getDecoratedDescription(); + } + + static Person createPersonCitingPhysicalArtifact() { + Person person = new Person(); + person.setGender(new Gender(GenderType.Male)); + + Fact fact = new Fact(); + fact.setId("123"); + fact.setKnownType(FactType.Birth); + + fact.setAttribution(new Attribution()); + fact.getAttribution().setContributor(new ResourceReference()); + fact.getAttribution().getContributor().setResource(URI.create("https://familysearch.org/platform/contributors/BCD-FGHJ")); + fact.setDate(new Date()); + fact.getDate().setOriginal("1793"); + + fact.setPlace(new Place()); + fact.getPlace().setOriginal("Vermont"); + + person.addFact(fact); + + fact = new Fact(); + fact.setId("456"); + fact.setKnownType(FactType.Death); + + fact.setAttribution(new Attribution()); + fact.getAttribution().setContributor(new ResourceReference()); + fact.getAttribution().getContributor().setResource(URI.create("https://familysearch.org/platform/contributors/KLM-NPQR")); + fact.setDate(new Date()); + fact.getDate().setOriginal("1844"); + + fact.setPlace(new Place()); + fact.getPlace().setOriginal("Steuben County, New York"); + + person.addFact(fact); + + List names = new ArrayList(); + Name name = new Name(); + name.setPreferred(true); + NameForm nameForm = new NameForm(); + nameForm.setFullText("Asa Phillips"); + name.setPrimaryForm(nameForm); + name.setAttribution(new Attribution()); + name.getAttribution().setContributor(new ResourceReference()); + name.getAttribution().getContributor().setResource(URI.create("https://familysearch.org/platform/contributors/STV-WXZY")); + name.setId("789"); + names.add(name); + person.setNames(names); + + ArrayList sources = new ArrayList(); + SourceReference attributedSourceReference = new SourceReference(); + Attribution attribution = new Attribution(); + attribution.setContributor(new ResourceReference()); + attribution.getContributor().setResource(URI.create("https://familysearch.org/platform/contributors/STV-WXZY")); + attributedSourceReference.setAttribution(attribution); + attributedSourceReference.setDescription(new ResourceReference()); + attributedSourceReference.getDescription().setResource(URI.create("https://familysearch.org/platform/sources/KKK-KKKK")); + sources.add(attributedSourceReference); + person.setSources(sources); + + person.setId("K2VD-4P2"); + + return person; + } + + + /** + * tests citing an online record. + */ + public void testConclusionsCitingOtherConclusions() throws Exception { + createRecipe("Citing Other Conclusions") + .withDescription("The following example illustrates how to cite another conclusion. Evidence for Israel Heaton is found in another conclusion person that (presumably) describes the same person. The URI to the person being cited is \"https://familysearch.org/platform/persons/NNN-NNNN\".") + .applicableTo(Person.class); + + Person person = createPersonCitingOtherConclusion(); + Snippet snippet = new Snippet("The person."); + processThroughXml(person, snippet); + processThroughJson(person, snippet); + addSnippet(snippet); + + snippet = new Snippet("The person being cited. The URI to this conclusion person is \"https://familysearch.org/platform/sources/NNN-NNNN\"."); + Person description = createPersonBeingCitedByAnotherPerson(); + processThroughXml(description, snippet); + processThroughJson(description, snippet); + addSnippet(snippet); + +// assertEquals(person); + } + + static Person createPersonCitingOtherConclusion() { + Person person = new Person(); + person.setGender(new Gender(GenderType.Male)); + + Fact fact = new Fact(); + fact.setId("123"); + fact.setKnownType(FactType.Birth); + + fact.setAttribution(new Attribution()); + fact.getAttribution().setContributor(new ResourceReference()); + fact.getAttribution().getContributor().setResource(URI.create("https://familysearch.org/platform/contributors/BCD-FGHJ")); + fact.setDate(new Date()); + fact.getDate().setOriginal("30 January 1880"); + + fact.setPlace(new Place()); + fact.getPlace().setOriginal("Orderville, Utah"); + + person.addFact(fact); + + fact = new Fact(); + fact.setId("456"); + fact.setKnownType(FactType.Death); + + fact.setAttribution(new Attribution()); + fact.getAttribution().setContributor(new ResourceReference()); + fact.getAttribution().getContributor().setResource(URI.create("https://familysearch.org/platform/contributors/KLM-NPQR")); + fact.setDate(new Date()); + fact.getDate().setOriginal("29 August 1936"); + + fact.setPlace(new Place()); + fact.getPlace().setOriginal("Kanab, Kane, UT"); + + person.addFact(fact); + + List names = new ArrayList(); + Name name = new Name(); + name.setPreferred(true); + NameForm nameForm = new NameForm(); + nameForm.setFullText("Israel Hoyt Heaton"); + name.setPrimaryForm(nameForm); + name.setAttribution(new Attribution()); + name.getAttribution().setContributor(new ResourceReference()); + name.getAttribution().getContributor().setResource(URI.create("https://familysearch.org/platform/contributors/STV-WXZY")); + name.setId("789"); + names.add(name); + person.setNames(names); + + ArrayList sources = new ArrayList(); + SourceReference attributedSourceReference = new SourceReference(); + Attribution attribution = new Attribution(); + attribution.setContributor(new ResourceReference()); + attribution.getContributor().setResource(URI.create("https://familysearch.org/platform/contributors/STV-WXZY")); + attributedSourceReference.setAttribution(attribution); + attributedSourceReference.setResource(URI.create("https://familysearch.org/platform/persons/NNN-NNNN")); + sources.add(attributedSourceReference); + person.setSources(sources); + + person.setId("KWCD-QBC"); + + return person; + } + + static Person createPersonBeingCitedByAnotherPerson() { + Person person = new Person(); + person.setGender(new Gender(GenderType.Male)); + + Fact fact = new Fact(); + fact.setId("123"); + fact.setKnownType(FactType.Birth); + + fact.setAttribution(new Attribution()); + fact.getAttribution().setContributor(new ResourceReference()); + fact.getAttribution().getContributor().setResource(URI.create("https://familysearch.org/platform/contributors/YYY-YYYY")); + fact.setDate(new Date()); + fact.getDate().setOriginal("1880"); + + fact.setPlace(new Place()); + fact.getPlace().setOriginal("Orderville, Utah"); + + person.addFact(fact); + + List names = new ArrayList(); + Name name = new Name(); + name.setPreferred(true); + NameForm nameForm = new NameForm(); + nameForm.setFullText("Israel H. Heaton"); + name.setPrimaryForm(nameForm); + name.setAttribution(new Attribution()); + name.getAttribution().setContributor(new ResourceReference()); + name.getAttribution().getContributor().setResource(URI.create("https://familysearch.org/platform/contributors/XXX-XXXX")); + name.setId("789"); + names.add(name); + person.setNames(names); + + ArrayList sources = new ArrayList(); + SourceReference attributedSourceReference = new SourceReference(); + Attribution attribution = new Attribution(); + attribution.setContributor(new ResourceReference()); + attribution.getContributor().setResource(URI.create("https://familysearch.org/platform/contributors/ZZZ-ZZZZ")); + attributedSourceReference.setAttribution(attribution); + attributedSourceReference.setDescription(new ResourceReference()); + attributedSourceReference.getDescription().setResource(URI.create("https://familysearch.org/platform/sources/JJJ-JJJJ")); + sources.add(attributedSourceReference); + person.setSources(sources); + + person.setId("KWCD-QBC"); + + return person; + } + + static void assertEquals(Person person) { + //todo: + } + +} diff --git a/gedcomx-conclusion/src/test/java/org/gedcomx/conclusion/PersonRecipesTest.java b/gedcomx-conclusion/src/test/java/org/gedcomx/conclusion/PersonRecipesTest.java new file mode 100644 index 00000000..ce7450ea --- /dev/null +++ b/gedcomx-conclusion/src/test/java/org/gedcomx/conclusion/PersonRecipesTest.java @@ -0,0 +1,157 @@ +package org.gedcomx.conclusion; + +import org.gedcomx.common.Attribution; +import org.gedcomx.common.FormalValue; +import org.gedcomx.common.ResourceReference; +import org.gedcomx.common.URI; +import org.gedcomx.test.RecipeTest; +import org.gedcomx.test.Snippet; +import org.gedcomx.types.FactType; +import org.gedcomx.types.GenderType; +import org.gedcomx.types.NamePartType; +import org.gedcomx.types.ResourceType; +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.gedcomx.rt.SerializationUtil.processThroughJson; +import static org.gedcomx.rt.SerializationUtil.processThroughXml; + +/** + * @author Ryan Heaton + */ +@Test +public class PersonRecipesTest extends RecipeTest { + + /** + * tests processing a WWW person through xml... + */ + public void testStandardPerson() throws Exception { + createRecipe("Simple Person") + .withDescription("Simple example for a person.") + .applicableTo(Person.class); + + Person person = create(); + Snippet snippet = new Snippet(); + person = processThroughXml(person, snippet); + person = processThroughJson(person, snippet); + addSnippet(snippet); +// assertEquals(person); + } + + public void testMarriageWithNoSpouse() throws Exception { + createRecipe("Marriage Fact With No Spouse Provided") + .withDescription("How to model a marriage (or divorce) event for which the spouse is not available or otherwise not provided.") + .applicableTo(Person.class); + + Person person = new Person(); + Fact fact = new Fact(); + fact.setKnownType(FactType.Marriage); + fact.setDate(new Date()); + fact.getDate().setOriginal("January 6, 1759"); + fact.setPlace(new Place()); + fact.getPlace().setOriginal("New Kent, Virginia"); + person.addFact(fact); + Snippet snippet = new Snippet("Note that the recommendation is to add a marriage fact directly to the person. It is not recommended to create a relationship with only one person."); + person = processThroughXml(person, snippet); + person = processThroughJson(person, snippet); + addSnippet(snippet); +// assertEquals(person); + } + + + static Person create() { + Person person = new Person(); + person.setGender(new Gender(GenderType.Male)); + + Fact fact = new Fact(); + fact.setId("123"); + fact.setKnownType(FactType.Birth); + + fact.setAttribution(new Attribution()); + fact.getAttribution().setContributor(new ResourceReference()); + fact.getAttribution().getContributor().setResource(URI.create("https://familysearch.org/platform/contributors/BCD-FGHJ")); + fact.setDate(new Date()); + fact.getDate().setOriginal("February 22, 1732"); + FormalValue normalized = new FormalValue(); + normalized.setText("1732-02-22"); + normalized.setDatatype(URI.create("http://www.w3.org/2001/XMLSchema#date")); + fact.getDate().setFormal(normalized); + + fact.setPlace(new Place()); + fact.getPlace().setOriginal("Pope's Creek, Westmoreland, Virginia"); + normalized = new FormalValue(); + normalized.setText("Pope's Creek, Westmoreland, Virginia"); + normalized.setResource(URI.create("https://familysearch.org/platform/places/12345")); + fact.getPlace().setFormal(normalized); + + person.addFact(fact); + + fact = new Fact(); + fact.setId("456"); + fact.setKnownType(FactType.Death); + + fact.setAttribution(new Attribution()); + fact.getAttribution().setContributor(new ResourceReference()); + fact.getAttribution().getContributor().setResource(URI.create("https://familysearch.org/platform/contributors/KLM-NPQR")); + fact.setDate(new Date()); + fact.getDate().setOriginal("December 14, 1799"); + normalized = new FormalValue(); + normalized.setText("1799-12-14T22:00:00"); + normalized.setDatatype(URI.create("http://www.w3.org/2001/XMLSchema#dateTime")); + fact.getDate().setFormal(normalized); + + fact.setPlace(new Place()); + fact.getPlace().setOriginal("Mount Vernon, Virginia"); + normalized = new FormalValue(); + normalized.setText("Mount Vernon, Fairfax County, Virginia"); + normalized.setResource(URI.create("https://familysearch.org/platform/places/67890")); + fact.getPlace().setFormal(normalized); + + person.addFact(fact); + + List names = new ArrayList(); + Name name = new Name(); + name.setPreferred(true); + NameForm nameForm = new NameForm(); + nameForm.setFullText("George Washington"); + ArrayList parts = new ArrayList(); + NamePart part = new NamePart(); + part.setKnownType(NamePartType.Given); + part.setText("George"); + parts.add(part); + part = new NamePart(); + part.setKnownType(NamePartType.Surname); + part.setText("Washington"); + parts.add(part); + nameForm.setParts(parts); + name.setPrimaryForm(nameForm); + name.setAttribution(new Attribution()); + name.getAttribution().setContributor(new ResourceReference()); + name.getAttribution().getContributor().setResource(URI.create("https://familysearch.org/platform/contributors/STV-WXZY")); + name.setId("789"); + names.add(name); + person.setNames(names); + + ArrayList sources = new ArrayList(); + SourceReference attributedSourceReference = new SourceReference(); + Attribution attribution = new Attribution(); + attribution.setContributor(new ResourceReference()); + attribution.getContributor().setResource(URI.create("https://familysearch.org/platform/contributors/STV-WXZY")); + attributedSourceReference.setAttribution(attribution); + attributedSourceReference.setResource(URI.create("http://en.wikipedia.org/wiki/George_washington")); + attributedSourceReference.setKnownType(ResourceType.Text); + sources.add(attributedSourceReference); + person.setSources(sources); + + person.setId("BBB-BBBB"); + + return person; + } + + static void assertEquals(Person person) { + //todo: + } + +} diff --git a/gedcomx-conclusion/src/test/java/org/gedcomx/conclusion/PersonTest.java b/gedcomx-conclusion/src/test/java/org/gedcomx/conclusion/PersonTest.java index 9535eac3..c2ea6cc8 100644 --- a/gedcomx-conclusion/src/test/java/org/gedcomx/conclusion/PersonTest.java +++ b/gedcomx-conclusion/src/test/java/org/gedcomx/conclusion/PersonTest.java @@ -1,233 +1,233 @@ -package org.gedcomx.conclusion; - -import org.gedcomx.common.*; -import org.gedcomx.types.*; -import org.testng.AssertJUnit; -import org.testng.annotations.Test; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import static org.gedcomx.rt.SerializationUtil.processThroughJson; -import static org.gedcomx.rt.SerializationUtil.processThroughXml; -import static org.testng.AssertJUnit.assertTrue; - -/** - * @author Ryan Heaton - */ -@Test -public class PersonTest { - - /** - * tests processing a WWW person through xml... - */ - static public void testPersonXml() throws Exception { - Person person = create(); - person = processThroughXml(person); - assertEquals(person); - } - - /** - * tests processing a WWW person through json... - */ - static public void testPersonJson() throws Exception { - Person person = create(); - person = processThroughJson(person); - assertEquals(person); - } - - static Person create() { - Person person = new Person(); - Gender gender = new Gender(); - gender.setKnownType(GenderType.Male); - person.setGenders(Arrays.asList(gender)); - - ArrayList alternateIds = new ArrayList(); - AlternateId alternateId = new AlternateId(); - alternateId.setKnownType(AlternateIdType.Forwarded); - alternateId.setValue("forward-value"); - alternateIds.add(alternateId); - person.setAlternateIds(alternateIds); - - List facts = new ArrayList(); - - Fact fact = new Fact(); - fact.setAttribution(new Attribution()); - fact.getAttribution().setContributor(new ResourceReference()); - fact.getAttribution().getContributor().setResource(URI.create("urn:fact-attribution")); - fact.setDate(new Date()); - fact.getDate().setOriginal("original date"); - FormalValue normalized = new FormalValue(); - normalized.setText("normalized date"); - normalized.setDatatype(URI.create("urn:date")); - normalized.setKnownValue(DatePartType.Years); - fact.getDate().setFormal(normalized); - fact.setId("fact-id"); - fact.setKnownType(FactType.Occupation); - fact.setPlace(new Place()); - fact.getPlace().setOriginal("original place"); - normalized = new FormalValue(); - normalized.setText("normalized place"); - normalized.setDatatype(URI.create("urn:place")); - normalized.setKnownValue(PlacePartType.Cemetery); - fact.getPlace().setFormal(normalized); - fact.setOriginal("fact-value"); - facts.add(fact); - - Fact event = new Fact(); - event.setAttribution(new Attribution()); - event.getAttribution().setContributor(new ResourceReference()); - event.getAttribution().getContributor().setResource(URI.create("urn:event-attribution")); - event.setDate(new Date()); - event.getDate().setOriginal("original date"); - normalized = new FormalValue(); - normalized.setText("normalized date"); - normalized.setDatatype(URI.create("urn:date")); - normalized.setKnownValue(DatePartType.Years); - event.getDate().setFormal(normalized); - event.setId("event-id"); - event.setKnownType(FactType.Adoption); - event.setPlace(new Place()); - event.getPlace().setOriginal("original place"); - normalized = new FormalValue(); - normalized.setText("normalized place"); - normalized.setDatatype(URI.create("urn:place")); - normalized.setKnownValue(PlacePartType.Cemetery); - event.getPlace().setFormal(normalized); - event.setSources(new ArrayList()); - SourceReference eventSource = new SourceReference(); - eventSource.setId("event-source"); - eventSource.setAttribution(new Attribution()); - event.getSources().add(eventSource); - facts.add(event); - - person.setFacts(facts); - - List names = new ArrayList(); - Name name = new Name(); - name.setPreferred(true); - ArrayList alternateForms = new ArrayList(); - NameForm nameForm = new NameForm(); - nameForm.setFullText("alternate name form"); - ArrayList parts = new ArrayList(); - NamePart part = new NamePart(); - part.setKnownType(NamePartType.Given); - part.setText("alternate name part"); - parts.add(part); - nameForm.setParts(parts); - alternateForms.add(nameForm); - name.setAlternateForms(alternateForms); - name.setAttribution(new Attribution()); - name.getAttribution().setContributor(new ResourceReference()); - name.getAttribution().getContributor().setResource(URI.create("urn:name-attribution")); - name.setId("name-id"); - name.setKnownType(NameType.Formal); - NameForm primaryForm = new NameForm(); - primaryForm.setFullText("primary form"); - primaryForm.setParts(new ArrayList()); - NamePart namePart = new NamePart(); - namePart.setKnownType(NamePartType.Surname); - namePart.setText("primary surname"); - primaryForm.getParts().add(namePart); - name.setPrimaryForm(primaryForm); - names.add(name); - person.setNames(names); - - person.setPersistentId(URI.create("pal")); - - ArrayList sources = new ArrayList(); - SourceReference attributedSourceReference = new SourceReference(); - Attribution attribution = new Attribution(); - attribution.setContributor(new ResourceReference()); - attribution.getContributor().setResource(URI.create("urn:source-reference-attribution")); - attributedSourceReference.setAttribution(attribution); - attributedSourceReference.setResource(URI.create("urn:source-uri")); - attributedSourceReference.setId("source-reference-id"); - attributedSourceReference.setKnownType(ResourceType.Collection); - attributedSourceReference.setDescription(new ResourceReference()); - attributedSourceReference.getDescription().setResource(URI.create("urn:source-description")); - sources.add(attributedSourceReference); - person.setSources(sources); - - person.setId("pid"); - person.setAttribution(new Attribution()); - person.getAttribution().setProofStatement("this person existed."); - - person.setLiving(true); - - return person; - } - - static void assertEquals(Person person) { - Fact fact; - Fact event; - Name name; - SourceReference attributedSourceReference; - AssertJUnit.assertEquals(GenderType.Male, person.getGenders().get(0).getKnownType()); - - AssertJUnit.assertEquals(1, person.getAlternateIds().size()); - AssertJUnit.assertEquals(AlternateIdType.Forwarded, person.getAlternateIds().get(0).getKnownType()); - AssertJUnit.assertEquals("forward-value", person.getAlternateIds().get(0).getValue()); - - AssertJUnit.assertEquals(2, person.getFacts().size()); - fact = person.getFacts().get(0); - AssertJUnit.assertEquals("urn:fact-attribution", fact.getAttribution().getContributor().getResource().toString()); - AssertJUnit.assertEquals("original date", fact.getDate().getOriginal()); - AssertJUnit.assertEquals("normalized date", fact.getDate().getFormal().getText()); - AssertJUnit.assertEquals(DatePartType.Years, fact.getDate().getFormal().getKnownValue(DatePartType.class)); - AssertJUnit.assertEquals("urn:date", fact.getDate().getFormal().getDatatype().toString()); - AssertJUnit.assertEquals("fact-id", fact.getId()); - AssertJUnit.assertEquals(FactType.Occupation, fact.getKnownType()); - AssertJUnit.assertEquals("original place", fact.getPlace().getOriginal()); - AssertJUnit.assertEquals("normalized place", fact.getPlace().getFormal().getText()); - AssertJUnit.assertEquals(PlacePartType.Cemetery, fact.getPlace().getFormal().getKnownValue(PlacePartType.class)); - AssertJUnit.assertEquals("urn:date", fact.getDate().getFormal().getDatatype().toString()); - AssertJUnit.assertEquals("fact-value", fact.getOriginal()); - - event = person.getFacts().get(1); - AssertJUnit.assertEquals("urn:event-attribution", event.getAttribution().getContributor().getResource().toString()); - AssertJUnit.assertEquals("original date", event.getDate().getOriginal()); - AssertJUnit.assertEquals("normalized date", event.getDate().getFormal().getText()); - AssertJUnit.assertEquals(DatePartType.Years, event.getDate().getFormal().getKnownValue(DatePartType.class)); - AssertJUnit.assertEquals("urn:date", event.getDate().getFormal().getDatatype().toString()); - AssertJUnit.assertEquals("event-id", event.getId()); - AssertJUnit.assertEquals(FactType.Adoption, event.getKnownType()); - AssertJUnit.assertEquals("original place", event.getPlace().getOriginal()); - AssertJUnit.assertEquals("normalized place", event.getPlace().getFormal().getText()); - AssertJUnit.assertEquals(PlacePartType.Cemetery, event.getPlace().getFormal().getKnownValue(PlacePartType.class)); - AssertJUnit.assertEquals("urn:date", event.getDate().getFormal().getDatatype().toString()); - - AssertJUnit.assertEquals(1, person.getNames().size()); - name = person.getNames().iterator().next(); - assertTrue(name.getPreferred()); - AssertJUnit.assertEquals(1, name.getAlternateForms().size()); - AssertJUnit.assertEquals("alternate name form", name.getAlternateForms().get(0).getFullText()); - AssertJUnit.assertEquals(1, name.getAlternateForms().get(0).getParts().size()); - AssertJUnit.assertEquals("alternate name part", name.getAlternateForms().get(0).getParts().get(0).getText()); - AssertJUnit.assertEquals(NamePartType.Given, name.getAlternateForms().get(0).getParts().get(0).getKnownType()); - AssertJUnit.assertEquals("urn:name-attribution", name.getAttribution().getContributor().getResource().toString()); - AssertJUnit.assertEquals("name-id", name.getId()); - AssertJUnit.assertEquals(NameType.Formal, name.getKnownType()); - AssertJUnit.assertEquals("primary form", name.getPrimaryForm().getFullText()); - AssertJUnit.assertEquals(1, name.getPrimaryForm().getParts().size()); - AssertJUnit.assertEquals("primary surname", name.getPrimaryForm().getParts().get(0).getText()); - AssertJUnit.assertEquals(NamePartType.Surname, name.getPrimaryForm().getParts().get(0).getKnownType()); - - AssertJUnit.assertEquals("pal", person.getPersistentId().toString()); - - AssertJUnit.assertEquals(1, person.getSources().size()); - attributedSourceReference = person.getSources().iterator().next(); - AssertJUnit.assertEquals("urn:source-reference-attribution", attributedSourceReference.getAttribution().getContributor().getResource().toString()); - AssertJUnit.assertEquals("urn:source-uri", attributedSourceReference.getResource().toString()); - AssertJUnit.assertEquals("source-reference-id", attributedSourceReference.getId()); - AssertJUnit.assertEquals(ResourceType.Collection, attributedSourceReference.getKnownType()); - AssertJUnit.assertEquals("urn:source-description", attributedSourceReference.getDescription().getResource().toString()); - - AssertJUnit.assertEquals("pid", person.getId()); - AssertJUnit.assertEquals("this person existed.", person.getAttribution().getProofStatement()); - - assertTrue(person.getLiving()); - } - -} +package org.gedcomx.conclusion; + +import org.gedcomx.common.*; +import org.gedcomx.types.*; +import org.testng.AssertJUnit; +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.gedcomx.rt.SerializationUtil.processThroughJson; +import static org.gedcomx.rt.SerializationUtil.processThroughXml; +import static org.testng.AssertJUnit.assertTrue; + +/** + * @author Ryan Heaton + */ +@Test +public class PersonTest { + + /** + * tests processing a WWW person through xml... + */ + static public void testPersonXml() throws Exception { + Person person = create(); + person = processThroughXml(person); + assertEquals(person); + } + + /** + * tests processing a WWW person through json... + */ + static public void testPersonJson() throws Exception { + Person person = create(); + person = processThroughJson(person); + assertEquals(person); + } + + static Person create() { + Person person = new Person(); + person.setGender(new Gender(GenderType.Male)); + + ArrayList identifiers = new ArrayList(); + Identifier identifier = new Identifier(); + identifier.setKnownType(IdentifierType.Forwarded); + identifier.setValue("forward-value"); + identifiers.add(identifier); + identifier = new Identifier(); + identifier.setKnownType(IdentifierType.Primary); + identifier.setValue("pal"); + identifiers.add(identifier); + person.setIdentifiers(identifiers); + + Fact fact = new Fact(); + fact.setAttribution(new Attribution()); + fact.getAttribution().setContributor(new ResourceReference()); + fact.getAttribution().getContributor().setResource(URI.create("urn:fact-attribution")); + fact.setDate(new Date()); + fact.getDate().setOriginal("original date"); + FormalValue normalized = new FormalValue(); + normalized.setText("normalized date"); + normalized.setDatatype(URI.create("urn:date")); + normalized.setKnownValue(DatePartType.Years); + fact.getDate().setFormal(normalized); + fact.setId("fact-id"); + fact.setKnownType(FactType.Occupation); + fact.setPlace(new Place()); + fact.getPlace().setOriginal("original place"); + normalized = new FormalValue(); + normalized.setText("normalized place"); + normalized.setDatatype(URI.create("urn:place")); + normalized.setKnownValue(PlacePartType.Cemetery); + fact.getPlace().setFormal(normalized); + fact.setOriginal("fact-value"); + person.addFact(fact); + + Fact event = new Fact(); + event.setAttribution(new Attribution()); + event.getAttribution().setContributor(new ResourceReference()); + event.getAttribution().getContributor().setResource(URI.create("urn:event-attribution")); + event.setDate(new Date()); + event.getDate().setOriginal("original date"); + normalized = new FormalValue(); + normalized.setText("normalized date"); + normalized.setDatatype(URI.create("urn:date")); + normalized.setKnownValue(DatePartType.Years); + event.getDate().setFormal(normalized); + event.setId("event-id"); + event.setKnownType(FactType.Adoption); + event.setPlace(new Place()); + event.getPlace().setOriginal("original place"); + normalized = new FormalValue(); + normalized.setText("normalized place"); + normalized.setDatatype(URI.create("urn:place")); + normalized.setKnownValue(PlacePartType.Cemetery); + event.getPlace().setFormal(normalized); + event.setSources(new ArrayList()); + SourceReference eventSource = new SourceReference(); + eventSource.setId("event-source"); + eventSource.setAttribution(new Attribution()); + event.getSources().add(eventSource); + + List facts = person.getFacts(); + facts.add(event); + person.setFacts(facts); + + List names = new ArrayList(); + Name name = new Name(); + name.setPreferred(true); + ArrayList alternateForms = new ArrayList(); + NameForm nameForm = new NameForm(); + nameForm.setFullText("alternate name form"); + ArrayList parts = new ArrayList(); + NamePart part = new NamePart(); + part.setKnownType(NamePartType.Given); + part.setText("alternate name part"); + parts.add(part); + nameForm.setParts(parts); + alternateForms.add(nameForm); + name.setAlternateForms(alternateForms); + name.setAttribution(new Attribution()); + name.getAttribution().setContributor(new ResourceReference()); + name.getAttribution().getContributor().setResource(URI.create("urn:name-attribution")); + name.setId("name-id"); + name.setKnownType(NameType.Formal); + NameForm primaryForm = new NameForm(); + primaryForm.setFullText("primary form"); + primaryForm.setParts(new ArrayList()); + NamePart namePart = new NamePart(); + namePart.setKnownType(NamePartType.Surname); + namePart.setText("primary surname"); + primaryForm.getParts().add(namePart); + name.setPrimaryForm(primaryForm); + names.add(name); + person.setNames(names); + + ArrayList sources = new ArrayList(); + SourceReference attributedSourceReference = new SourceReference(); + Attribution attribution = new Attribution(); + attribution.setContributor(new ResourceReference()); + attribution.getContributor().setResource(URI.create("urn:source-reference-attribution")); + attributedSourceReference.setAttribution(attribution); + attributedSourceReference.setResource(URI.create("urn:source-uri")); + attributedSourceReference.setId("source-reference-id"); + attributedSourceReference.setKnownType(ResourceType.Collection); + attributedSourceReference.setDescription(new ResourceReference()); + attributedSourceReference.getDescription().setResource(URI.create("urn:source-description")); + sources.add(attributedSourceReference); + person.setSources(sources); + + person.setId("pid"); + person.setAttribution(new Attribution()); + person.getAttribution().setProofStatement("this person existed."); + + person.setLiving(true); + + return person; + } + + static void assertEquals(Person person) { + Fact fact; + Fact event; + Name name; + SourceReference attributedSourceReference; + AssertJUnit.assertEquals(GenderType.Male, person.getGender().getKnownType()); + + AssertJUnit.assertEquals(2, person.getIdentifiers().size()); + AssertJUnit.assertEquals(IdentifierType.Forwarded, person.getIdentifiers().get(0).getKnownType()); + AssertJUnit.assertEquals("forward-value", person.getIdentifiers().get(0).getValue()); + AssertJUnit.assertEquals(IdentifierType.Primary, person.getIdentifiers().get(1).getKnownType()); + AssertJUnit.assertEquals("pal", person.getIdentifiers().get(1).getValue()); + + AssertJUnit.assertEquals(2, person.getFacts().size()); + fact = person.getFirstFactOfType(FactType.Occupation); + AssertJUnit.assertEquals("urn:fact-attribution", fact.getAttribution().getContributor().getResource().toString()); + AssertJUnit.assertEquals("original date", fact.getDate().getOriginal()); + AssertJUnit.assertEquals("normalized date", fact.getDate().getFormal().getText()); + AssertJUnit.assertEquals(DatePartType.Years, fact.getDate().getFormal().getKnownValue(DatePartType.class)); + AssertJUnit.assertEquals("urn:date", fact.getDate().getFormal().getDatatype().toString()); + AssertJUnit.assertEquals("fact-id", fact.getId()); + AssertJUnit.assertEquals(FactType.Occupation, fact.getKnownType()); + AssertJUnit.assertEquals("original place", fact.getPlace().getOriginal()); + AssertJUnit.assertEquals("normalized place", fact.getPlace().getFormal().getText()); + AssertJUnit.assertEquals(PlacePartType.Cemetery, fact.getPlace().getFormal().getKnownValue(PlacePartType.class)); + AssertJUnit.assertEquals("urn:date", fact.getDate().getFormal().getDatatype().toString()); + AssertJUnit.assertEquals("fact-value", fact.getOriginal()); + + event = person.getFirstFactOfType(FactType.Adoption); + AssertJUnit.assertEquals("urn:event-attribution", event.getAttribution().getContributor().getResource().toString()); + AssertJUnit.assertEquals("original date", event.getDate().getOriginal()); + AssertJUnit.assertEquals("normalized date", event.getDate().getFormal().getText()); + AssertJUnit.assertEquals(DatePartType.Years, event.getDate().getFormal().getKnownValue(DatePartType.class)); + AssertJUnit.assertEquals("urn:date", event.getDate().getFormal().getDatatype().toString()); + AssertJUnit.assertEquals("event-id", event.getId()); + AssertJUnit.assertEquals(FactType.Adoption, event.getKnownType()); + AssertJUnit.assertEquals("original place", event.getPlace().getOriginal()); + AssertJUnit.assertEquals("normalized place", event.getPlace().getFormal().getText()); + AssertJUnit.assertEquals(PlacePartType.Cemetery, event.getPlace().getFormal().getKnownValue(PlacePartType.class)); + AssertJUnit.assertEquals("urn:date", event.getDate().getFormal().getDatatype().toString()); + + AssertJUnit.assertEquals(1, person.getNames().size()); + name = person.getNames().iterator().next(); + assertTrue(name.getPreferred()); + AssertJUnit.assertEquals(1, name.getAlternateForms().size()); + AssertJUnit.assertEquals("alternate name form", name.getAlternateForms().get(0).getFullText()); + AssertJUnit.assertEquals(1, name.getAlternateForms().get(0).getParts().size()); + AssertJUnit.assertEquals("alternate name part", name.getAlternateForms().get(0).getParts().get(0).getText()); + AssertJUnit.assertEquals(NamePartType.Given, name.getAlternateForms().get(0).getParts().get(0).getKnownType()); + AssertJUnit.assertEquals("urn:name-attribution", name.getAttribution().getContributor().getResource().toString()); + AssertJUnit.assertEquals("name-id", name.getId()); + AssertJUnit.assertEquals(NameType.Formal, name.getKnownType()); + AssertJUnit.assertEquals("primary form", name.getPrimaryForm().getFullText()); + AssertJUnit.assertEquals(1, name.getPrimaryForm().getParts().size()); + AssertJUnit.assertEquals("primary surname", name.getPrimaryForm().getParts().get(0).getText()); + AssertJUnit.assertEquals(NamePartType.Surname, name.getPrimaryForm().getParts().get(0).getKnownType()); + + AssertJUnit.assertEquals("pal", person.getPersistentId().toString()); + + AssertJUnit.assertEquals(1, person.getSources().size()); + attributedSourceReference = person.getSources().iterator().next(); + AssertJUnit.assertEquals("urn:source-reference-attribution", attributedSourceReference.getAttribution().getContributor().getResource().toString()); + AssertJUnit.assertEquals("urn:source-uri", attributedSourceReference.getResource().toString()); + AssertJUnit.assertEquals("source-reference-id", attributedSourceReference.getId()); + AssertJUnit.assertEquals(ResourceType.Collection, attributedSourceReference.getKnownType()); + AssertJUnit.assertEquals("urn:source-description", attributedSourceReference.getDescription().getResource().toString()); + + AssertJUnit.assertEquals("pid", person.getId()); + AssertJUnit.assertEquals("this person existed.", person.getAttribution().getProofStatement()); + + assertTrue(person.getLiving()); + } + +} diff --git a/gedcomx-conclusion/src/test/java/org/gedcomx/conclusion/RelationshipRecipesTest.java b/gedcomx-conclusion/src/test/java/org/gedcomx/conclusion/RelationshipRecipesTest.java new file mode 100644 index 00000000..7089fca2 --- /dev/null +++ b/gedcomx-conclusion/src/test/java/org/gedcomx/conclusion/RelationshipRecipesTest.java @@ -0,0 +1,76 @@ +package org.gedcomx.conclusion; + +import org.gedcomx.common.*; +import org.gedcomx.test.RecipeTest; +import org.gedcomx.test.Snippet; +import org.gedcomx.types.FactType; +import org.gedcomx.types.RelationshipType; +import org.gedcomx.types.ResourceType; +import org.testng.annotations.Test; + +import java.util.List; + +import static org.gedcomx.rt.SerializationUtil.processThroughJson; +import static org.gedcomx.rt.SerializationUtil.processThroughXml; +import static org.testng.AssertJUnit.assertEquals; + +/** + * @author Ryan Heaton + */ +@Test +public class RelationshipRecipesTest extends RecipeTest { + + public void testRelationship() throws Exception { + createRecipe("Simple Relationship") + .withDescription("Simple example for a relationship.") + .applicableTo(Relationship.class); + + Relationship relationship = createTestRelationship(); + Snippet snippet = new Snippet(); + relationship = processThroughXml(relationship, snippet); + relationship = processThroughJson(relationship, snippet); + assertTestRelationship(relationship); + } + + private Relationship createTestRelationship() { + Relationship relationship = new Relationship(); + relationship.setId("CCC-CCCC"); + relationship.setKnownType(RelationshipType.Couple); + + relationship.setAttribution(new Attribution()); + relationship.getAttribution().setProofStatement("(proof statement here)"); + ResourceReference contributor = new ResourceReference(); + contributor.setResource(URI.create("https://familysearch.org/platform/contributors/BCD-FGHJ")); + relationship.getAttribution().setContributor(contributor); + Fact fact = new Fact(); + fact.setId("123"); + fact.setKnownType(FactType.Marriage); + + fact.setAttribution(new Attribution()); + fact.getAttribution().setContributor(new ResourceReference()); + fact.getAttribution().getContributor().setResource(URI.create("https://familysearch.org/platform/contributors/HHH-HHHH")); + fact.setDate(new Date()); + fact.getDate().setOriginal("January 6, 1759"); + FormalValue normalized = new FormalValue(); + normalized.setText("1759-01-06"); + normalized.setDatatype(URI.create("http://www.w3.org/2001/XMLSchema#date")); + fact.getDate().setFormal(normalized); + + relationship.addFact(fact); + relationship.setPerson1(new ResourceReference()); + relationship.getPerson1().setResource(URI.create("https://familysearch.org/platform/persons/DDD-DDDD")); + relationship.setPerson2(new ResourceReference()); + relationship.getPerson2().setResource(URI.create("https://familysearch.org/platform/persons/FFF-FFFF")); + SourceReference sourceReference = new SourceReference(); + sourceReference.setId("5678"); + sourceReference.setResource(URI.create("http://en.wikipedia.org/wiki/George_washington")); + sourceReference.setKnownType(ResourceType.Text); + relationship.addSource(sourceReference); + return relationship; + } + + private void assertTestRelationship(Relationship relationship) { + //todo + } + +} diff --git a/gedcomx-conclusion/src/test/java/org/gedcomx/conclusion/RelationshipTest.java b/gedcomx-conclusion/src/test/java/org/gedcomx/conclusion/RelationshipTest.java index 00c11a24..aaa1fa00 100644 --- a/gedcomx-conclusion/src/test/java/org/gedcomx/conclusion/RelationshipTest.java +++ b/gedcomx-conclusion/src/test/java/org/gedcomx/conclusion/RelationshipTest.java @@ -1,74 +1,77 @@ -package org.gedcomx.conclusion; - -import org.gedcomx.common.AlternateId; -import org.gedcomx.common.Attribution; -import org.gedcomx.common.ResourceReference; -import org.gedcomx.types.RelationshipType; -import org.testng.annotations.Test; - -import org.gedcomx.common.URI; -import java.util.Arrays; - -import static org.gedcomx.rt.SerializationUtil.processThroughJson; -import static org.gedcomx.rt.SerializationUtil.processThroughXml; -import static org.testng.AssertJUnit.assertEquals; - -/** - * @author Ryan Heaton - */ -@Test -public class RelationshipTest { - - /** - * tests processing a relationship through xml... - */ - public void testRelationshipXml() throws Exception { - Relationship relationship = createTestRelationship(); - relationship = processThroughXml(relationship); - assertTestRelationship(relationship); - } - - /** - * tests processing a relationship through json... - */ - public void testPersonJson() throws Exception { - Relationship relationship = createTestRelationship(); - relationship = processThroughJson(relationship); - assertTestRelationship(relationship); - } - - private Relationship createTestRelationship() { - Relationship relationship = new Relationship(); - relationship.setKnownType(RelationshipType.Couple); - AlternateId alternateId = new AlternateId(); - alternateId.setValue("alt-id"); - relationship.setAttribution(new Attribution()); - relationship.getAttribution().setProofStatement("explanation"); - Fact fact = new Fact(); - fact.setId("fact"); - Fact event = new Fact(); - event.setId("event"); - relationship.setFacts(Arrays.asList(event, fact)); - relationship.setId("relationship"); - relationship.setPerson1(new ResourceReference()); - relationship.getPerson1().setResource(URI.create("urn:person1")); - relationship.setPerson2(new ResourceReference()); - relationship.getPerson2().setResource(URI.create("urn:person2")); - SourceReference sourceReference = new SourceReference(); - sourceReference.setId("source-ref"); - relationship.setSources(Arrays.asList(sourceReference)); - return relationship; - } - - private void assertTestRelationship(Relationship relationship) { - assertEquals(RelationshipType.Couple, relationship.getKnownType()); - assertEquals("explanation", relationship.getAttribution().getProofStatement()); - assertEquals("fact", relationship.getFacts().get(1).getId()); - assertEquals("event", relationship.getFacts().get(0).getId()); - assertEquals("relationship", relationship.getId()); - assertEquals(URI.create("urn:person1"), relationship.getPerson1().getResource()); - assertEquals(URI.create("urn:person2"), relationship.getPerson2().getResource()); - assertEquals("source-ref", relationship.getSources().get(0).getId()); - } - -} +package org.gedcomx.conclusion; + +import org.gedcomx.common.Identifier; +import org.gedcomx.common.Attribution; +import org.gedcomx.common.ResourceReference; +import org.gedcomx.common.URI; +import org.gedcomx.types.RelationshipType; +import org.testng.annotations.Test; + +import java.util.List; + +import static org.gedcomx.rt.SerializationUtil.processThroughJson; +import static org.gedcomx.rt.SerializationUtil.processThroughXml; +import static org.testng.AssertJUnit.assertEquals; + +/** + * @author Ryan Heaton + */ +@Test +public class RelationshipTest { + + /** + * tests processing a relationship through xml... + */ + public void testRelationshipXml() throws Exception { + Relationship relationship = createTestRelationship(); + relationship = processThroughXml(relationship); + assertTestRelationship(relationship); + } + + /** + * tests processing a relationship through json... + */ + public void testPersonJson() throws Exception { + Relationship relationship = createTestRelationship(); + relationship = processThroughJson(relationship); + assertTestRelationship(relationship); + } + + private Relationship createTestRelationship() { + Relationship relationship = new Relationship(); + relationship.setKnownType(RelationshipType.Couple); + Identifier identifier = new Identifier(); + identifier.setValue("alt-id"); + relationship.setAttribution(new Attribution()); + relationship.getAttribution().setProofStatement("explanation"); + Fact fact = new Fact(); + fact.setId("fact"); + Fact event = new Fact(); + event.setId("event"); + relationship.addFact(event); + List facts = relationship.getFacts(); + facts.add(fact); + relationship.setFacts(facts); + relationship.setId("relationship"); + relationship.setPerson1(new ResourceReference()); + relationship.getPerson1().setResource(URI.create("urn:person1")); + relationship.setPerson2(new ResourceReference()); + relationship.getPerson2().setResource(URI.create("urn:person2")); + SourceReference sourceReference = new SourceReference(); + sourceReference.setId("source-ref"); + relationship.addSource(sourceReference); + return relationship; + } + + private void assertTestRelationship(Relationship relationship) { + assertEquals(RelationshipType.Couple, relationship.getKnownType()); + assertEquals("explanation", relationship.getAttribution().getProofStatement()); + assertEquals("fact", relationship.getFacts().get(1).getId()); + assertEquals("event", relationship.getFacts().get(0).getId()); + assertEquals("relationship", relationship.getId()); + assertEquals(URI.create("urn:person1"), relationship.getPerson1().getResource()); + assertEquals(URI.create("urn:person2"), relationship.getPerson2().getResource()); + assertEquals("source-ref", relationship.getSources().get(0).getId()); + } + +} diff --git a/gedcomx-common/src/test/java/org/gedcomx/common/SourceReferenceTest.java b/gedcomx-conclusion/src/test/java/org/gedcomx/conclusion/SourceReferenceTest.java similarity index 64% rename from gedcomx-common/src/test/java/org/gedcomx/common/SourceReferenceTest.java rename to gedcomx-conclusion/src/test/java/org/gedcomx/conclusion/SourceReferenceTest.java index 59d40956..27632ce5 100644 --- a/gedcomx-common/src/test/java/org/gedcomx/common/SourceReferenceTest.java +++ b/gedcomx-conclusion/src/test/java/org/gedcomx/conclusion/SourceReferenceTest.java @@ -1,56 +1,57 @@ -package org.gedcomx.common; - -import org.gedcomx.types.ResourceType; -import org.testng.annotations.Test; - -import java.util.ArrayList; - -import static org.gedcomx.rt.SerializationUtil.processThroughJson; -import static org.gedcomx.rt.SerializationUtil.processThroughXml; -import static org.testng.AssertJUnit.assertEquals; - -/** - * @author Ryan Heaton - */ -@Test -public class SourceReferenceTest { - - /** - * tests source reference xml - */ - public void testSourceReferenceXml() throws Exception { - ResourceReference reference = new ResourceReference(); - reference.setResource(URI.create("urn:someid")); - reference.setKnownType(ResourceType.Collection); - reference.setId("refid"); - reference.setExtensionElements(new ArrayList()); - reference.getExtensionElements().add(new CustomEntity("alt")); - CustomEntity custom = new CustomEntity(); - custom.setSource(reference); - custom = processThroughXml(custom); - assertEquals("urn:someid", custom.getSource().getResource().toString()); - assertEquals(ResourceType.Collection, custom.getSource().getKnownType()); - assertEquals("refid", custom.getSource().getId()); - assertEquals("alt", ((CustomEntity) custom.getSource().getExtensionElements().get(0)).getId()); - } - - /** - * tests source reference json - */ - public void testSourceReferenceJson() throws Exception { - ResourceReference reference = new ResourceReference(); - reference.setResource(URI.create("urn:someid")); - reference.setKnownType(ResourceType.Collection); - reference.setId("refid"); - reference.setExtensionElements(new ArrayList()); - reference.getExtensionElements().add(new CustomEntity("alt")); - CustomEntity custom = new CustomEntity(); - custom.setSource(reference); - custom = processThroughJson(custom); - assertEquals("urn:someid", custom.getSource().getResource().toString()); - assertEquals(ResourceType.Collection, custom.getSource().getKnownType()); - assertEquals("refid", custom.getSource().getId()); - assertEquals("alt", ((CustomEntity) custom.getSource().getExtensionElements().get(0)).getId()); - } - -} +package org.gedcomx.conclusion; + +import org.gedcomx.common.URI; +import org.gedcomx.rt.SerializationUtil; +import org.gedcomx.types.ResourceType; +import org.testng.AssertJUnit; +import org.testng.annotations.Test; + +import java.util.ArrayList; + +import static org.testng.AssertJUnit.assertEquals; + +/** + * @author Ryan Heaton + */ +@Test +public class SourceReferenceTest { + + /** + * tests source reference xml + */ + public void testSourceReferenceXml() throws Exception { + SourceReference reference = new SourceReference(); + reference.setResource(URI.create("urn:someid")); + reference.setKnownType(ResourceType.Collection); + reference.setId("refid"); + reference.setExtensionElements(new ArrayList()); + reference.getExtensionElements().add(new CustomEntity("alt")); + CustomEntity custom = new CustomEntity(); + custom.setSource(reference); + custom = SerializationUtil.processThroughXml(custom); + AssertJUnit.assertEquals("urn:someid", custom.getSource().getResource().toString()); + assertEquals(ResourceType.Collection, custom.getSource().getKnownType()); + assertEquals("refid", custom.getSource().getId()); + AssertJUnit.assertEquals("alt", ((CustomEntity) custom.getSource().getExtensionElements().get(0)).getId()); + } + + /** + * tests source reference json + */ + public void testSourceReferenceJson() throws Exception { + SourceReference reference = new SourceReference(); + reference.setResource(URI.create("urn:someid")); + reference.setKnownType(ResourceType.Collection); + reference.setId("refid"); + reference.setExtensionElements(new ArrayList()); + reference.getExtensionElements().add(new CustomEntity("alt")); + CustomEntity custom = new CustomEntity(); + custom.setSource(reference); + custom = SerializationUtil.processThroughJson(custom); + AssertJUnit.assertEquals("urn:someid", custom.getSource().getResource().toString()); + assertEquals(ResourceType.Collection, custom.getSource().getKnownType()); + assertEquals("refid", custom.getSource().getId()); + AssertJUnit.assertEquals("alt", ((CustomEntity) custom.getSource().getExtensionElements().get(0)).getId()); + } + +} diff --git a/gedcomx-metadata/pom.xml b/gedcomx-metadata/pom.xml index 7147ad15..7a5eed20 100644 --- a/gedcomx-metadata/pom.xml +++ b/gedcomx-metadata/pom.xml @@ -7,7 +7,7 @@ org.gedcomx gedcomx-parent - 0.14.0-SNAPSHOT + 0.18.0-SNAPSHOT @@ -16,6 +16,7 @@ ${basedir}/.. + ${project.build.directory}/recipes @@ -35,6 +36,54 @@ + + org.apache.maven.plugins + maven-surefire-plugin + + + ${recipes.dir} + + + + + org.apache.maven.plugins + maven-resources-plugin + + + copy-resources + prepare-package + + copy-resources + + + ${project.build.outputDirectory} + + + ${recipes.dir} + true + + + + + + + + org.apache.maven.plugins + maven-antrun-plugin + + + process-test-classes + + + + + + + run + + + + @@ -42,13 +91,20 @@ org.gedcomx gedcomx-common - 0.14.0-SNAPSHOT + ${project.version} org.gedcomx gedcomx-rt-support - 0.14.0-SNAPSHOT + ${project.version} + + + + org.gedcomx + gedcomx-test-support + ${project.version} + test diff --git a/gedcomx-metadata/src/main/java/org/gedcomx/metadata/dc/DublinCoreDescriptionDecorator.java b/gedcomx-metadata/src/main/java/org/gedcomx/metadata/dc/DublinCoreDescriptionDecorator.java index 4c41cbe7..245a962f 100644 --- a/gedcomx-metadata/src/main/java/org/gedcomx/metadata/dc/DublinCoreDescriptionDecorator.java +++ b/gedcomx-metadata/src/main/java/org/gedcomx/metadata/dc/DublinCoreDescriptionDecorator.java @@ -15,6 +15,7 @@ */ package org.gedcomx.metadata.dc; +import org.gedcomx.common.URI; import org.gedcomx.metadata.rdf.Description; import org.gedcomx.metadata.rdf.RDFLiteral; import org.gedcomx.metadata.rdf.RDFValue; @@ -74,6 +75,46 @@ public Description getDecoratedDescription() { return description; } + /** + * The URI of the resource being described. + * + * @param uri The URI of the resource being described. + * @return this builder. + */ + public DublinCoreDescriptionDecorator about(URI uri) { + this.description.setAbout(uri); + return this; + } + + /** + * The URI of the resource being described. + * + * @return The URI of the resource being described. + */ + public URI getAbout() { + return this.description.getAbout(); + } + + /** + * The id of the description. + * + * @param id The id of the description. + * @return this builder. + */ + public DublinCoreDescriptionDecorator id(String id) { + this.description.setId(id); + return this; + } + + /** + * The id of the description. + * + * @return The id of the description. + */ + public String getId() { + return this.description.getId(); + } + /** * A summary of the resource. * @@ -164,7 +205,7 @@ public DublinCoreDescriptionDecorator audience(RDFValue audience) { * Date that the resource became or will become available. * * @return Date that the resource became or will become available. - * + * * @link http://dublincore.org/documents/dcmi-terms/#terms-available */ public DublinCoreDescriptionDecorator available(Date available) { @@ -172,6 +213,18 @@ public DublinCoreDescriptionDecorator available(Date available) { return this; } + /** + * Date that the resource became or will become available. + * + * @return Date that the resource became or will become available. + * + * @link http://dublincore.org/documents/dcmi-terms/#terms-available + */ + public DublinCoreDescriptionDecorator available(String available) { + this.description.addExtensionElement(OBJECT_FACTORY.createAvailableElement(new RDFLiteral(available))); + return this; + } + /** * A bibliographic reference for the resource. Recommended practice is to include sufficient * bibliographic detail to identify the resource as unambiguously as possible. @@ -226,7 +279,7 @@ public DublinCoreDescriptionDecorator coverage(RDFValue coverage) { * Date of creation of the resource. * * @return Date of creation of the resource. - * + * * @link http://dublincore.org/documents/dcmi-terms/#terms-created */ public DublinCoreDescriptionDecorator created(Date created) { @@ -234,6 +287,18 @@ public DublinCoreDescriptionDecorator created(Date created) { return this; } + /** + * Date of creation of the resource. + * + * @return Date of creation of the resource. + * + * @link http://dublincore.org/documents/dcmi-terms/#terms-created + */ + public DublinCoreDescriptionDecorator created(String created) { + this.description.addExtensionElement(OBJECT_FACTORY.createCreatedElement(new RDFLiteral(created))); + return this; + } + /** * Entities primarily responsible for making the resource. * @@ -258,6 +323,18 @@ public DublinCoreDescriptionDecorator date(Date date) { return this; } + /** + * A point or period of time associated with an event in the lifecycle of the resource. + * + * @return A point or period of time associated with an event in the lifecycle of the resource. + * + * @link http://dublincore.org/documents/dcmi-terms/#terms-date + */ + public DublinCoreDescriptionDecorator date(String date) { + this.description.addExtensionElement(OBJECT_FACTORY.createDateElement(new RDFLiteral(date))); + return this; + } + /** * Date of acceptance of the resource. * @@ -270,6 +347,18 @@ public DublinCoreDescriptionDecorator dateAccepted(Date dateAccepted) { return this; } + /** + * Date of acceptance of the resource. + * + * @return Date of acceptance of the resource. + * + * @link http://dublincore.org/documents/dcmi-terms/#terms-dateAccepted + */ + public DublinCoreDescriptionDecorator dateAccepted(String dateAccepted) { + this.description.addExtensionElement(OBJECT_FACTORY.createDateAcceptedElement(new RDFLiteral(dateAccepted))); + return this; + } + /** * Date of copyright. * @@ -282,6 +371,18 @@ public DublinCoreDescriptionDecorator dateCopyrighted(Date dateCopyrighted) { return this; } + /** + * Date of copyright. + * + * @return Date of copyright. + * + * @link http://dublincore.org/documents/dcmi-terms/#terms-dateCopyrighted + */ + public DublinCoreDescriptionDecorator dateCopyrighted(String dateCopyrighted) { + this.description.addExtensionElement(OBJECT_FACTORY.createDateCopyrightedElement(new RDFLiteral(dateCopyrighted))); + return this; + } + /** * Date of submission of the resource. * @@ -294,6 +395,18 @@ public DublinCoreDescriptionDecorator dateSubmitted(Date dateSubmitted) { return this; } + /** + * Date of submission of the resource. + * + * @return Date of submission of the resource. + * + * @link http://dublincore.org/documents/dcmi-terms/#terms-dateSubmitted + */ + public DublinCoreDescriptionDecorator dateSubmitted(String dateSubmitted) { + this.description.addExtensionElement(OBJECT_FACTORY.createDateSubmittedElement(new RDFLiteral(dateSubmitted))); + return this; + } + /** * An account of the resource. * @@ -481,6 +594,18 @@ public DublinCoreDescriptionDecorator issued(Date issued) { return this; } + /** + * Date of formal issuance (e.g., publication) of the resource. + * + * @return Date of formal issuance (e.g., publication) of the resource. + * + * @link http://dublincore.org/documents/dcmi-terms/#terms-issued + */ + public DublinCoreDescriptionDecorator issued(String issued) { + this.description.addExtensionElement(OBJECT_FACTORY.createIssuedElement(new RDFLiteral(issued))); + return this; + } + /** * A related resource of which the described resource is a version, edition, or adaptation. Changes in version imply substantive changes * in content rather than differences in format. @@ -555,6 +680,18 @@ public DublinCoreDescriptionDecorator modified(Date modified) { return this; } + /** + * Date on which the resource was changed. + * + * @return Date on which the resource was changed. + * + * @link http://dublincore.org/documents/dcmi-terms/#terms-modified + */ + public DublinCoreDescriptionDecorator modified(String modified) { + this.description.addExtensionElement(OBJECT_FACTORY.createModifiedElement(new RDFLiteral(modified))); + return this; + } + /** * A statement of any changes in ownership and custody of the resource since its creation that are significant for its authenticity, integrity, and interpretation. * @@ -731,7 +868,7 @@ public DublinCoreDescriptionDecorator title(RDFLiteral title) { * Date of validity of a resource. * * @return Date of validity of a resource. - * + * * @link http://dublincore.org/documents/dcmi-terms/#terms-valid */ public DublinCoreDescriptionDecorator valid(Date valid) { @@ -739,6 +876,18 @@ public DublinCoreDescriptionDecorator valid(Date valid) { return this; } + /** + * Date of validity of a resource. + * + * @return Date of validity of a resource. + * + * @link http://dublincore.org/documents/dcmi-terms/#terms-valid + */ + public DublinCoreDescriptionDecorator valid(String valid) { + this.description.addExtensionElement(OBJECT_FACTORY.createValidElement(new RDFLiteral(valid))); + return this; + } + /** * A summary of the resource. * @@ -817,6 +966,17 @@ public List getAudience() { return findElements("audience", RDFValue.class); } + /** + * Date that the resource became or will become available. + * + * @return Date that the resource became or will become available. + * + * @link http://dublincore.org/documents/dcmi-terms/#terms-available + */ + public List getAvailable() { + return findElements("available", RDFLiteral.class); + } + /** * Date that the resource became or will become available. * @@ -824,7 +984,7 @@ public List getAudience() { * * @link http://dublincore.org/documents/dcmi-terms/#terms-available */ - public List getAvailable() { + public List getAvailableAsDate() { return findElements("available", Date.class); } @@ -881,7 +1041,18 @@ public List getCoverage() { * * @link http://dublincore.org/documents/dcmi-terms/#terms-created */ - public List getCreated() { + public List getCreated() { + return findElements("created", RDFLiteral.class); + } + + /** + * Date of creation of the resource. + * + * @return Date of creation of the resource. + * + * @link http://dublincore.org/documents/dcmi-terms/#terms-created + */ + public List getCreatedAsDate() { return findElements("created", Date.class); } @@ -903,7 +1074,18 @@ public List getCreator() { * * @link http://dublincore.org/documents/dcmi-terms/#terms-date */ - public List getDate() { + public List getDate() { + return findElements("date", RDFLiteral.class); + } + + /** + * A point or period of time associated with an event in the lifecycle of the resource. + * + * @return A point or period of time associated with an event in the lifecycle of the resource. + * + * @link http://dublincore.org/documents/dcmi-terms/#terms-date + */ + public List getDateAsDate() { return findElements("date", Date.class); } @@ -911,10 +1093,21 @@ public List getDate() { * Date of acceptance of the resource. * * @return Date of acceptance of the resource. - * + * * @link http://dublincore.org/documents/dcmi-terms/#terms-dateAccepted */ - public List getDateAccepted() { + public List getDateAccepted() { + return findElements("dateAccepted", RDFLiteral.class); + } + + /** + * Date of acceptance of the resource. + * + * @return Date of acceptance of the resource. + * + * @link http://dublincore.org/documents/dcmi-terms/#terms-dateAccepted + */ + public List getDateAcceptedAsDate() { return findElements("dateAccepted", Date.class); } @@ -922,10 +1115,21 @@ public List getDateAccepted() { * Date of copyright. * * @return Date of copyright. - * + * + * @link http://dublincore.org/documents/dcmi-terms/#terms-dateCopyrighted + */ + public List getDateCopyrighted() { + return findElements("dateCopyrighted", RDFLiteral.class); + } + + /** + * Date of copyright. + * + * @return Date of copyright. + * * @link http://dublincore.org/documents/dcmi-terms/#terms-dateCopyrighted */ - public List getDateCopyrighted() { + public List getDateCopyrightedAsDate() { return findElements("dateCopyrighted", Date.class); } @@ -933,10 +1137,21 @@ public List getDateCopyrighted() { * Date of submission of the resource. * * @return Date of submission of the resource. - * + * * @link http://dublincore.org/documents/dcmi-terms/#terms-dateSubmitted */ - public List getDateSubmitted() { + public List getDateSubmitted() { + return findElements("dateSubmitted", RDFLiteral.class); + } + + /** + * Date of submission of the resource. + * + * @return Date of submission of the resource. + * + * @link http://dublincore.org/documents/dcmi-terms/#terms-dateSubmitted + */ + public List getDateSubmittedAsDate() { return findElements("dateSubmitted", Date.class); } @@ -1105,10 +1320,21 @@ public List getIsRequiredBy() { * Date of formal issuance (e.g., publication) of the resource. * * @return Date of formal issuance (e.g., publication) of the resource. - * + * + * @link http://dublincore.org/documents/dcmi-terms/#terms-issued + */ + public List getIssued() { + return findElements("issued", RDFLiteral.class); + } + + /** + * Date of formal issuance (e.g., publication) of the resource. + * + * @return Date of formal issuance (e.g., publication) of the resource. + * * @link http://dublincore.org/documents/dcmi-terms/#terms-issued */ - public List getIssued() { + public List getIssuedAsDate() { return findElements("issued", Date.class); } @@ -1176,7 +1402,18 @@ public List getMedium() { * * @link http://dublincore.org/documents/dcmi-terms/#terms-modified */ - public List getModified() { + public List getModified() { + return findElements("modified", RDFLiteral.class); + } + + /** + * Date on which the resource was changed. + * + * @return Date on which the resource was changed. + * + * @link http://dublincore.org/documents/dcmi-terms/#terms-modified + */ + public List getModifiedAsDate() { return findElements("modified", Date.class); } @@ -1342,10 +1579,21 @@ public List getTitle() { * Date of validity of a resource. * * @return Date of validity of a resource. - * + * + * @link http://dublincore.org/documents/dcmi-terms/#terms-valid + */ + public List getValid() { + return findElements("valid", RDFLiteral.class); + } + + /** + * Date of validity of a resource. + * + * @return Date of validity of a resource. + * * @link http://dublincore.org/documents/dcmi-terms/#terms-valid */ - public List getValid() { + public List getValidAsDate() { return findElements("valid", Date.class); } diff --git a/gedcomx-metadata/src/main/java/org/gedcomx/metadata/dc/ObjectFactory.java b/gedcomx-metadata/src/main/java/org/gedcomx/metadata/dc/ObjectFactory.java index d470516e..b88646f0 100644 --- a/gedcomx-metadata/src/main/java/org/gedcomx/metadata/dc/ObjectFactory.java +++ b/gedcomx-metadata/src/main/java/org/gedcomx/metadata/dc/ObjectFactory.java @@ -18,7 +18,7 @@ import org.gedcomx.metadata.rdf.RDFLiteral; import org.gedcomx.metadata.rdf.RDFValue; import org.gedcomx.rt.CommonModels; -import org.gedcomx.rt.JsonElementWrapper; +import org.gedcomx.rt.json.JsonElementWrapper; import javax.xml.bind.JAXBElement; import javax.xml.bind.annotation.XmlElementDecl; @@ -277,7 +277,7 @@ public JAXBElement createDateSubmittedElement(RDFLiteral dateSubmitt * @link http://dublincore.org/documents/dcmi-terms/#terms-description */ @XmlElementDecl ( namespace = CommonModels.DUBLIN_CORE_NAMESPACE, name = "description" ) - @JsonElementWrapper ( name = "descriptions" ) + @JsonElementWrapper ( name = "dc-descriptions" ) public JAXBElement createDescriptionElement(RDFValue description) { return new JAXBElement(new QName(CommonModels.DUBLIN_CORE_NAMESPACE, "description"), RDFValue.class, description); } @@ -663,7 +663,7 @@ public JAXBElement createRightsHolderElement(RDFValue rightsHolder) { * @link http://dublincore.org/documents/dcmi-terms/#terms-source */ @XmlElementDecl ( namespace = CommonModels.DUBLIN_CORE_NAMESPACE, name = "source" ) - @JsonElementWrapper ( name = "sources" ) + @JsonElementWrapper ( name = "dc-sources" ) public JAXBElement createSourceElement(RDFValue source) { return new JAXBElement(new QName(CommonModels.DUBLIN_CORE_NAMESPACE, "source"), RDFValue.class, source); } diff --git a/gedcomx-metadata/src/main/java/org/gedcomx/metadata/foaf/Address.java b/gedcomx-metadata/src/main/java/org/gedcomx/metadata/foaf/Address.java index b693f486..8d3cdf4b 100644 --- a/gedcomx-metadata/src/main/java/org/gedcomx/metadata/foaf/Address.java +++ b/gedcomx-metadata/src/main/java/org/gedcomx/metadata/foaf/Address.java @@ -15,15 +15,14 @@ */ package org.gedcomx.metadata.foaf; -import org.codehaus.jackson.annotate.JsonTypeInfo; -import org.codehaus.jackson.map.annotate.JsonTypeIdResolver; import org.gedcomx.rt.CommonModels; -import org.gedcomx.rt.XmlTypeIdResolver; import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlID; import javax.xml.bind.annotation.XmlType; + /** * An address. * @@ -31,8 +30,6 @@ * @author Ryan Heaton */ @XmlType (name = "Address", namespace = CommonModels.CONTACT_NAMESPACE) -@JsonTypeInfo ( use =JsonTypeInfo.Id.CUSTOM, property = XmlTypeIdResolver.TYPE_PROPERTY_NAME) -@JsonTypeIdResolver (XmlTypeIdResolver.class) public class Address { private String id; @@ -43,6 +40,7 @@ public class Address { private String street; private String street2; private String street3; + private String value; /** * The id of this address. @@ -189,4 +187,23 @@ public String getStreet3() { public void setStreet3(String street3) { this.street3 = street3; } + + /** + * The value of the property, if it can be expressed as a string. If the value can't be expressed as a string, use {@link #getResource() the resource ref}. + * + * @return The value of the property. + */ + @XmlElement ( name = "value", namespace = CommonModels.RDF_NAMESPACE ) + public String getValue() { + return value; + } + + /** + * The value of the property, if it can be expressed as a string. If the value can't be expressed as a string, use {@link #getResource() the resource ref}. + * + * @param value The value of the property. + */ + public void setValue(String value) { + this.value = value; + } } diff --git a/gedcomx-metadata/src/main/java/org/gedcomx/metadata/foaf/OnlineAccount.java b/gedcomx-metadata/src/main/java/org/gedcomx/metadata/foaf/OnlineAccount.java index 57eb9940..e17bdd64 100644 --- a/gedcomx-metadata/src/main/java/org/gedcomx/metadata/foaf/OnlineAccount.java +++ b/gedcomx-metadata/src/main/java/org/gedcomx/metadata/foaf/OnlineAccount.java @@ -17,12 +17,9 @@ import org.codehaus.enunciate.json.JsonName; import org.codehaus.jackson.annotate.JsonProperty; -import org.codehaus.jackson.annotate.JsonTypeInfo; -import org.codehaus.jackson.map.annotate.JsonTypeIdResolver; import org.gedcomx.common.ResourceReference; import org.gedcomx.metadata.rdf.RDFLiteral; import org.gedcomx.rt.CommonModels; -import org.gedcomx.rt.XmlTypeIdResolver; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; @@ -36,8 +33,6 @@ * @author Ryan Heaton */ @XmlType( name = "OnlineAccount" ) -@JsonTypeInfo ( use =JsonTypeInfo.Id.CUSTOM, property = XmlTypeIdResolver.TYPE_PROPERTY_NAME) -@JsonTypeIdResolver (XmlTypeIdResolver.class) public class OnlineAccount { private String id; diff --git a/gedcomx-metadata/src/main/java/org/gedcomx/metadata/foaf/Organization.java b/gedcomx-metadata/src/main/java/org/gedcomx/metadata/foaf/Organization.java index 970951eb..1682ab12 100644 --- a/gedcomx-metadata/src/main/java/org/gedcomx/metadata/foaf/Organization.java +++ b/gedcomx-metadata/src/main/java/org/gedcomx/metadata/foaf/Organization.java @@ -15,10 +15,6 @@ */ package org.gedcomx.metadata.foaf; -import org.codehaus.jackson.annotate.JsonTypeInfo; -import org.codehaus.jackson.map.annotate.JsonTypeIdResolver; -import org.gedcomx.rt.XmlTypeIdResolver; - import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; @@ -30,7 +26,5 @@ */ @XmlType ( name = "Organization" ) @XmlRootElement ( name = "Organization" ) -@JsonTypeInfo ( use =JsonTypeInfo.Id.CUSTOM, property = XmlTypeIdResolver.TYPE_PROPERTY_NAME) -@JsonTypeIdResolver (XmlTypeIdResolver.class) public class Organization extends Agent { } diff --git a/gedcomx-metadata/src/main/java/org/gedcomx/metadata/foaf/Person.java b/gedcomx-metadata/src/main/java/org/gedcomx/metadata/foaf/Person.java index 6c880d70..0c83af80 100644 --- a/gedcomx-metadata/src/main/java/org/gedcomx/metadata/foaf/Person.java +++ b/gedcomx-metadata/src/main/java/org/gedcomx/metadata/foaf/Person.java @@ -15,11 +15,8 @@ */ package org.gedcomx.metadata.foaf; -import org.codehaus.jackson.annotate.JsonTypeInfo; -import org.codehaus.jackson.map.annotate.JsonTypeIdResolver; import org.gedcomx.metadata.rdf.RDFLiteral; import org.gedcomx.rt.CommonModels; -import org.gedcomx.rt.XmlTypeIdResolver; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @@ -33,8 +30,6 @@ */ @XmlType( name = "Person" ) @XmlRootElement ( name = "Person" ) -@JsonTypeInfo ( use =JsonTypeInfo.Id.CUSTOM, property = XmlTypeIdResolver.TYPE_PROPERTY_NAME) -@JsonTypeIdResolver (XmlTypeIdResolver.class) public class Person extends Agent { private RDFLiteral familyName; diff --git a/gedcomx-metadata/src/main/java/org/gedcomx/metadata/rdf/Description.java b/gedcomx-metadata/src/main/java/org/gedcomx/metadata/rdf/Description.java index eb07e467..e04519d4 100644 --- a/gedcomx-metadata/src/main/java/org/gedcomx/metadata/rdf/Description.java +++ b/gedcomx-metadata/src/main/java/org/gedcomx/metadata/rdf/Description.java @@ -16,13 +16,11 @@ package org.gedcomx.metadata.rdf; import org.codehaus.jackson.annotate.JsonIgnore; -import org.codehaus.jackson.annotate.JsonTypeInfo; -import org.codehaus.jackson.map.annotate.JsonTypeIdResolver; import org.gedcomx.common.URI; import org.gedcomx.rt.CommonModels; +import org.gedcomx.rt.json.JsonElementWrapper; import org.gedcomx.rt.SupportsExtensionAttributes; import org.gedcomx.rt.SupportsExtensionElements; -import org.gedcomx.rt.XmlTypeIdResolver; import org.gedcomx.types.ResourceType; import org.gedcomx.types.TypeReference; @@ -41,8 +39,7 @@ */ @XmlRootElement( name = "Description" ) @XmlType ( name = "Description" ) -@JsonTypeInfo ( use =JsonTypeInfo.Id.CUSTOM, property = XmlTypeIdResolver.TYPE_PROPERTY_NAME) -@JsonTypeIdResolver (XmlTypeIdResolver.class) +@JsonElementWrapper( name = "descriptions" ) @XmlSeeAlso({RDFValue.class, RDFLiteral.class}) public class Description implements SupportsExtensionAttributes, SupportsExtensionElements { diff --git a/gedcomx-metadata/src/main/java/org/gedcomx/metadata/rdf/RDFLiteral.java b/gedcomx-metadata/src/main/java/org/gedcomx/metadata/rdf/RDFLiteral.java index ed5ac520..ef87c982 100644 --- a/gedcomx-metadata/src/main/java/org/gedcomx/metadata/rdf/RDFLiteral.java +++ b/gedcomx-metadata/src/main/java/org/gedcomx/metadata/rdf/RDFLiteral.java @@ -16,12 +16,9 @@ package org.gedcomx.metadata.rdf; import org.codehaus.jackson.annotate.JsonIgnore; -import org.codehaus.jackson.annotate.JsonTypeInfo; -import org.codehaus.jackson.map.annotate.JsonTypeIdResolver; import org.gedcomx.common.URI; import org.gedcomx.rt.CommonModels; import org.gedcomx.rt.SupportsExtensionAttributes; -import org.gedcomx.rt.XmlTypeIdResolver; import javax.xml.XMLConstants; import javax.xml.bind.annotation.*; @@ -41,8 +38,6 @@ * @author Ryan Heaton */ @XmlType ( name = "Literal", namespace = CommonModels.RDFS_NAMESPACE ) -@JsonTypeInfo ( use =JsonTypeInfo.Id.CUSTOM, property = XmlTypeIdResolver.TYPE_PROPERTY_NAME) -@JsonTypeIdResolver (XmlTypeIdResolver.class) public final class RDFLiteral implements SupportsExtensionAttributes { private static final URI DATE_DATATYPE = URI.create("http://www.w3.org/2001/XMLSchema#dateTime"); diff --git a/gedcomx-metadata/src/main/java/org/gedcomx/metadata/rdf/RDFValue.java b/gedcomx-metadata/src/main/java/org/gedcomx/metadata/rdf/RDFValue.java index f4c550ea..bb91c960 100644 --- a/gedcomx-metadata/src/main/java/org/gedcomx/metadata/rdf/RDFValue.java +++ b/gedcomx-metadata/src/main/java/org/gedcomx/metadata/rdf/RDFValue.java @@ -1,91 +1,301 @@ -/** - * Copyright 2011-2012 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.metadata.rdf; - -import org.codehaus.jackson.annotate.JsonTypeInfo; -import org.codehaus.jackson.map.annotate.JsonTypeIdResolver; -import org.gedcomx.common.ResourceReference; -import org.gedcomx.rt.CommonModels; -import org.gedcomx.rt.XmlTypeIdResolver; - -import javax.xml.XMLConstants; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlType; - -/** - * An element representing an RDF value. For more information, see RDF Schema, Section 4.5.3, - * RDF Primer, Section 4.4 - * and Using RDF properties in profiles: a technical primer. - * - * @link http://www.w3.org/TR/rdf-schema/#ch_value - * @link http://www.w3.org/TR/2004/REC-rdf-primer-20040210/#rdfvalue - * @author Ryan Heaton - */ -@XmlType ( name = "Resource", namespace = CommonModels.RDFS_NAMESPACE ) -@JsonTypeInfo ( use =JsonTypeInfo.Id.CUSTOM, property = XmlTypeIdResolver.TYPE_PROPERTY_NAME) -@JsonTypeIdResolver (XmlTypeIdResolver.class) -public final class RDFValue extends ResourceReference { - - private String lang; - private String value; - - public RDFValue() { - } - - public RDFValue(String value) { - this.value = value; - } - - /** - * The language of the value of the property. See http://www.w3.org/International/articles/language-tags/ - * - * @param lang The language of the value of the property. - */ - public void setLang(String lang) { - this.lang = lang; - } - - /** - * The value of the property, if it can be expressed as a string. If the value can't be expressed as a string, use {@link #getResource() the resource ref}. - * - * @return The value of the property. - */ - @XmlElement ( name = "value", namespace = CommonModels.RDF_NAMESPACE ) - public String getValue() { - return value; - } - - /** - * The value of the property, if it can be expressed as a string. If the value can't be expressed as a string, use {@link #getResource() the resource ref}. - * - * @param value The value of the property. - */ - public void setValue(String value) { - this.value = value; - } - -} +/** + * Copyright 2011-2012 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.metadata.rdf; + +import org.codehaus.enunciate.doc.DocumentationExample; +import org.codehaus.jackson.annotate.JsonIgnore; +import org.codehaus.jackson.annotate.JsonProperty; +import org.gedcomx.common.URI; +import org.gedcomx.rt.CommonModels; +import org.gedcomx.rt.SupportsExtensionAttributes; +import org.gedcomx.rt.SupportsExtensionElements; +import org.gedcomx.types.ResourceType; +import org.gedcomx.types.TypeReference; + +import javax.xml.XMLConstants; +import javax.xml.bind.annotation.*; +import javax.xml.namespace.QName; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * An element representing an RDF value. For more information, see RDF Schema, Section 4.5.3, + * RDF Primer, Section 4.4 + * and Using RDF properties in profiles: a technical primer. + * + * @link http://www.w3.org/TR/rdf-schema/#ch_value + * @link http://www.w3.org/TR/2004/REC-rdf-primer-20040210/#rdfvalue + * @author Ryan Heaton + */ +@XmlType ( name = "Resource", namespace = CommonModels.RDFS_NAMESPACE ) +public final class RDFValue implements SupportsExtensionAttributes, SupportsExtensionElements { + + private String id; + private String lang; + private String value; + @XmlElement (namespace = CommonModels.RDF_NAMESPACE) + @JsonProperty + private TypeReference type; + private URI resource; + private Map extensionAttributes; + private List extensionElements; + + public RDFValue() { + } + + public RDFValue(String value) { + this.value = value; + } + + /** + * The id of this resource reference. Note the distinction between this id and the id of the + * resource being referenced. + * + * @return The id of this resource reference. Note the distinction between this id and the id of the + * resource being referenced. + */ + @XmlID + @XmlAttribute( name = "ID", namespace = CommonModels.RDF_NAMESPACE ) + @DocumentationExample (exclude = true) + public String getId() { + return id; + } + + /** + * The id of this resource reference. Note the distinction between this id and the id of the + * resource being referenced. + * + * @param id The id of this resource reference. Note the distinction between this id and the id of the + * resource being referenced. + */ + public void setId(String id) { + this.id = id; + } + + /** + * The language of the value of the property. See http://www.w3.org/International/articles/language-tags/ + * + * @param lang The language of the value of the property. + */ + public void setLang(String lang) { + this.lang = lang; + } + + /** + * The value of the property, if it can be expressed as a string. If the value can't be expressed as a string, use {@link #getResource() the resource ref}. + * + * @return The value of the property. + */ + @XmlElement ( name = "value", namespace = CommonModels.RDF_NAMESPACE ) + public String getValue() { + return value; + } + + /** + * The value of the property, if it can be expressed as a string. If the value can't be expressed as a string, use {@link #getResource() the resource ref}. + * + * @param value The value of the property. + */ + public void setValue(String value) { + this.value = value; + } + + /** + * The type of the resource being referenced. + * + * @return The type of the resource being referenced. + */ + @XmlTransient + @JsonIgnore + public URI getType() { + return this.type == null ? null : this.type.getType(); + } + + /** + * The type of the resource being referenced. + * + * @param type The type of the resource being referenced. + */ + @JsonIgnore + public void setType(URI type) { + this.type = type == null ? null : new TypeReference(type); + } + + /** + * The enum referencing the known type of the resource being referenced, or {@link org.gedcomx.types.ResourceType#OTHER} if not known. + * + * @return The enum referencing the known type of the source reference, or {@link org.gedcomx.types.ResourceType#OTHER} if not known. + */ + @XmlTransient + @JsonIgnore + public ResourceType getKnownType() { + return this.type == null ? null : ResourceType.fromQNameURI(this.type.getType()); + } + + /** + * Set the type of this reference from an enumeration of known source reference types. + * + * @param knownType The reference type. + */ + @JsonIgnore + public void setKnownType(ResourceType knownType) { + this.type = knownType == null ? null : new TypeReference(knownType); + } + + /** + * The URI to the resource. For more information, see Architecture of the World + * Wide Web, Volume One, Section 2 + * + * @link http://www.w3.org/TR/webarch/#identification + * @return The URI to the resource. + */ + @XmlAttribute (namespace= CommonModels.RDF_NAMESPACE) + @XmlSchemaType (name = "anyURI", namespace = XMLConstants.W3C_XML_SCHEMA_NS_URI) + public URI getResource() { + return resource; + } + + /** + * The URI to the resource. For more information, see Architecture of the World + * Wide Web, Volume One, Section 2 + * + * @link http://www.w3.org/TR/webarch/#identification + * @param resource The URI to the resource. + */ + public void setResource(URI resource) { + this.resource = resource; + } + + /** + * Custom attributes applicable to this resource reference. + * + * @return Custom attributes applicable to this resource reference. + */ + @XmlAnyAttribute + @JsonIgnore + public Map getExtensionAttributes() { + return extensionAttributes; + } + + /** + * Custom attributes applicable to this resource reference. + * + * @param extensionAttributes Custom attributes applicable to this resource reference. + */ + @JsonIgnore + public void setExtensionAttributes(Map extensionAttributes) { + this.extensionAttributes = extensionAttributes; + } + + /** + * Add a custom extension attribute. + * + * @param qname The qname of the attribute. + * @param value The value of the attribute. + */ + public void addExtensionAttribute(QName qname, String value) { + if (this.extensionAttributes == null) { + this.extensionAttributes = new HashMap(); + } + + this.extensionAttributes.put(qname, value); + } + + /** + * Custom attributes applicable to this resource reference. + * + * @return Custom attributes applicable to this resource reference. + */ + @XmlAnyElement ( lax = true ) + @JsonIgnore + public List getExtensionElements() { + return extensionElements; + } + + /** + * Custom attributes applicable to this resource reference. + * + * @param extensionElements Custom attributes applicable to this resource reference. + */ + @JsonIgnore + public void setExtensionElements(List extensionElements) { + this.extensionElements = extensionElements; + } + + /** + * Add an extension element. + * + * @param element The extension element to add. + */ + public void addExtensionElement(Object element) { + if (this.extensionElements == null) { + this.extensionElements = new ArrayList(); + } + + this.extensionElements.add(element); + } + + /** + * Finds the first extension of a specified type. + * + * @param clazz The type. + * @return The extension, or null if none found. + */ + @SuppressWarnings ( {"unchecked"} ) + public E findExtensionOfType(Class clazz) { + if (this.extensionElements != null) { + for (Object extension : extensionElements) { + if (clazz.isInstance(extension)) { + return (E) extension; + } + } + } + + return null; + } + + /** + * Find the extensions of a specified type. + * + * @param clazz The type. + * @return The extensions, possibly empty but not null. + */ + @SuppressWarnings ( {"unchecked"} ) + public List findExtensionsOfType(Class clazz) { + List ext = new ArrayList(); + if (this.extensionElements != null) { + for (Object extension : extensionElements) { + if (clazz.isInstance(extension)) { + ext.add((E) extension); + } + } + } + + return ext; + } +} diff --git a/gedcomx-metadata/src/test/java/org/gedcomx/metadata/dc/DublinCoreDescriptionDecoratorTest.java b/gedcomx-metadata/src/test/java/org/gedcomx/metadata/dc/DublinCoreDescriptionDecoratorTest.java index ec6b98de..3c94a980 100644 --- a/gedcomx-metadata/src/test/java/org/gedcomx/metadata/dc/DublinCoreDescriptionDecoratorTest.java +++ b/gedcomx-metadata/src/test/java/org/gedcomx/metadata/dc/DublinCoreDescriptionDecoratorTest.java @@ -6,6 +6,8 @@ import org.testng.annotations.Test; import javax.xml.bind.JAXBContext; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.Date; import static org.gedcomx.rt.SerializationUtil.processThroughJson; @@ -17,9 +19,14 @@ */ @Test public class DublinCoreDescriptionDecoratorTest { + private static final SimpleDateFormat dateFormat; + static { + dateFormat = (SimpleDateFormat)DateFormat.getDateTimeInstance(); + dateFormat.applyPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); + } /** - * tests alternate id xml + * tests id xml */ public void testDublinCoreMetadataXml() throws Exception { DublinCoreDescriptionDecorator metadata = createMetadata(); @@ -28,7 +35,7 @@ public void testDublinCoreMetadataXml() throws Exception { } /** - * tests alternate id json + * tests id json */ public void testDublinCoreMetadataJson() throws Exception { DublinCoreDescriptionDecorator metadata = createMetadata(); @@ -544,6 +551,8 @@ private DublinCoreDescriptionDecorator createMetadata() { } private void assertMetadata(DublinCoreDescriptionDecorator metadata) { + Date date; + /** * A summary of the resource. * @@ -623,8 +632,11 @@ private void assertMetadata(DublinCoreDescriptionDecorator metadata) { * * @link http://dublincore.org/documents/dcmi-terms/#terms-available */ + assertEquals(1, metadata.getAvailableAsDate().size()); + date = metadata.getAvailableAsDate().get(0); + assertEquals("available".hashCode(), date.getTime()); assertEquals(1, metadata.getAvailable().size()); - assertEquals("available".hashCode(), metadata.getAvailable().get(0).getTime()); + assertEquals(toW3CDTF(date), metadata.getAvailable().get(0).getValue()); /** * A bibliographic reference for the resource. Recommended practice is to include sufficient @@ -675,8 +687,11 @@ private void assertMetadata(DublinCoreDescriptionDecorator metadata) { * * @link http://dublincore.org/documents/dcmi-terms/#terms-created */ + assertEquals(1, metadata.getCreatedAsDate().size()); + date = metadata.getCreatedAsDate().get(0); + assertEquals("created".hashCode(), date.getTime()); assertEquals(1, metadata.getCreated().size()); - assertEquals("created".hashCode(), metadata.getCreated().get(0).getTime()); + assertEquals(toW3CDTF(date), metadata.getCreated().get(0).getValue()); /** * Entities primarily responsible for making the resource. @@ -695,8 +710,11 @@ private void assertMetadata(DublinCoreDescriptionDecorator metadata) { * * @link http://dublincore.org/documents/dcmi-terms/#terms-date */ + assertEquals(1, metadata.getDateAsDate().size()); + date = metadata.getDateAsDate().get(0); + assertEquals("date".hashCode(), date.getTime()); assertEquals(1, metadata.getDate().size()); - assertEquals("date".hashCode(), metadata.getDate().get(0).getTime()); + assertEquals(toW3CDTF(date), metadata.getDate().get(0).getValue()); /** * Date of acceptance of the resource. @@ -705,8 +723,11 @@ private void assertMetadata(DublinCoreDescriptionDecorator metadata) { * * @link http://dublincore.org/documents/dcmi-terms/#terms-dateAccepted */ + assertEquals(1, metadata.getDateAcceptedAsDate().size()); + date = metadata.getDateAcceptedAsDate().get(0); + assertEquals("dateAccepted".hashCode(), date.getTime()); assertEquals(1, metadata.getDateAccepted().size()); - assertEquals("dateAccepted".hashCode(), metadata.getDateAccepted().get(0).getTime()); + assertEquals(toW3CDTF(date), metadata.getDateAccepted().get(0).getValue()); /** * Date of copyright. @@ -715,8 +736,11 @@ private void assertMetadata(DublinCoreDescriptionDecorator metadata) { * * @link http://dublincore.org/documents/dcmi-terms/#terms-dateCopyrighted */ + assertEquals(1, metadata.getDateCopyrightedAsDate().size()); + date = metadata.getDateCopyrightedAsDate().get(0); + assertEquals("dateCopyrighted".hashCode(), date.getTime()); assertEquals(1, metadata.getDateCopyrighted().size()); - assertEquals("dateCopyrighted".hashCode(), metadata.getDateCopyrighted().get(0).getTime()); + assertEquals(toW3CDTF(date), metadata.getDateCopyrighted().get(0).getValue()); /** * Date of submission of the resource. @@ -725,8 +749,11 @@ private void assertMetadata(DublinCoreDescriptionDecorator metadata) { * * @link http://dublincore.org/documents/dcmi-terms/#terms-dateSubmitted */ + assertEquals(1, metadata.getDateSubmittedAsDate().size()); + date = metadata.getDateSubmittedAsDate().get(0); + assertEquals("dateSubmitted".hashCode(), date.getTime()); assertEquals(1, metadata.getDateSubmitted().size()); - assertEquals("dateSubmitted".hashCode(), metadata.getDateSubmitted().get(0).getTime()); + assertEquals(toW3CDTF(date), metadata.getDateSubmitted().get(0).getValue()); /** * An account of the resource. @@ -882,8 +909,11 @@ private void assertMetadata(DublinCoreDescriptionDecorator metadata) { * * @link http://dublincore.org/documents/dcmi-terms/#terms-issued */ + assertEquals(1, metadata.getIssuedAsDate().size()); + date = metadata.getIssuedAsDate().get(0); + assertEquals("issued".hashCode(), date.getTime()); assertEquals(1, metadata.getIssued().size()); - assertEquals("issued".hashCode(), metadata.getIssued().get(0).getTime()); + assertEquals(toW3CDTF(date), metadata.getIssued().get(0).getValue()); /** * A related resource of which the described resource is a version, edition, or adaptation. Changes in version imply substantive changes @@ -944,8 +974,11 @@ private void assertMetadata(DublinCoreDescriptionDecorator metadata) { * * @link http://dublincore.org/documents/dcmi-terms/#terms-modified */ + assertEquals(1, metadata.getModifiedAsDate().size()); + date = metadata.getModifiedAsDate().get(0); + assertEquals("modified".hashCode(), date.getTime()); assertEquals(1, metadata.getModified().size()); - assertEquals("modified".hashCode(), metadata.getModified().get(0).getTime()); + assertEquals(toW3CDTF(date), metadata.getModified().get(0).getValue()); /** * A statement of any changes in ownership and custody of the resource since its creation that are significant for its authenticity, integrity, and interpretation. @@ -1098,8 +1131,19 @@ private void assertMetadata(DublinCoreDescriptionDecorator metadata) { * * @link http://dublincore.org/documents/dcmi-terms/#terms-valid */ + assertEquals(1, metadata.getValidAsDate().size()); + date = metadata.getValidAsDate().get(0); + assertEquals("valid".hashCode(), date.getTime()); assertEquals(1, metadata.getValid().size()); - assertEquals("valid".hashCode(), metadata.getValid().get(0).getTime()); + assertEquals(toW3CDTF(date), metadata.getValid().get(0).getValue()); } + private String toW3CDTF(Date date) { + StringBuilder builder = new StringBuilder(dateFormat.format(date)); + int length = builder.length(); + if (builder.charAt(length - 1) != 'Z') { + builder.insert(length - 2, ':'); + } + return builder.toString(); + } } diff --git a/gedcomx-metadata/src/test/java/org/gedcomx/metadata/dc/SourceOfASourceRecipesTest.java b/gedcomx-metadata/src/test/java/org/gedcomx/metadata/dc/SourceOfASourceRecipesTest.java new file mode 100644 index 00000000..ec5a8675 --- /dev/null +++ b/gedcomx-metadata/src/test/java/org/gedcomx/metadata/dc/SourceOfASourceRecipesTest.java @@ -0,0 +1,98 @@ +package org.gedcomx.metadata.dc; + +import org.gedcomx.common.ResourceSet; +import org.gedcomx.common.URI; +import org.gedcomx.metadata.rdf.Description; +import org.gedcomx.metadata.rdf.RDFLiteral; +import org.gedcomx.metadata.rdf.RDFValue; +import org.gedcomx.rt.SerializationProcessListener; +import org.gedcomx.test.RecipeTest; +import org.gedcomx.test.Snippet; +import org.testng.annotations.Test; + +import javax.xml.bind.JAXBContext; + +import static org.gedcomx.rt.SerializationUtil.processThroughJson; +import static org.gedcomx.rt.SerializationUtil.processThroughXml; + +/** + * @author Ryan Heaton + */ +public class SourceOfASourceRecipesTest extends RecipeTest { + + @Test + public void testTexasDeaths() throws Exception { + createRecipe("Describing a Texas Deaths Online Record") + .withDescription("Example for describing an online Texas Death record.") + .applicableTo(Description.class); + + String sourceId = "1"; + String sourceOfSourceId = "2"; + + RDFValue sourceOfSourceRef = new RDFValue(); + sourceOfSourceRef.setResource(URI.create("#" + sourceOfSourceId)); + + DublinCoreDescriptionDecorator source = DublinCoreDescriptionDecorator.newInstance() + .bibliographicCitation(new RDFLiteral("\"Texas Deaths, 1890-1976,\" index and images, FamilySearch (https://familysearch.org/pal:/MM9.1.1/J69H-GV1 : accessed 13 April 2012), Lyndon Baines Johnson, 1973")) + .title(new RDFLiteral("Texas Deaths, 1890-1976")) + .creator(new RDFValue("Lyndon Baines Johnson")) + .description(new RDFValue("index and images")) + .publisher(new RDFValue("FamilySearch")) + .identifier(new RDFLiteral("https://familysearch.org/pal:/MM9.1.1/J69H-GV1")) + .temporal(new RDFValue("1890-1976")) + .spatial(new RDFValue("Texas, United States")) + .source(sourceOfSourceRef); + source.getDecoratedDescription().setAbout(URI.create("https://familysearch.org/pal:/MM9.1.1/J69H-GV1")); + source.getDecoratedDescription().setId(sourceId); + + DublinCoreDescriptionDecorator sourceOfTheSource = DublinCoreDescriptionDecorator.newInstance() + .bibliographicCitation(new RDFLiteral("Bexar County, Texas, certificate 00340, Bureau of Vital Statistics, Department of Health, Austin; FHL microfilm 2,242,245.")); + sourceOfTheSource.getDecoratedDescription().setId(sourceOfSourceId); + + ResourceSet resourceSet = new ResourceSet(); + resourceSet.addExtensionElement(source.getDecoratedDescription()); + resourceSet.addExtensionElement(sourceOfTheSource.getDecoratedDescription()); + + Snippet snippet = new Snippet(); + resourceSet = processThroughXml(resourceSet, ResourceSet.class, JAXBContext.newInstance(ResourceSet.class, Description.class, ObjectFactory.class), (SerializationProcessListener)snippet); + //todo: verify person. + resourceSet = processThroughJson(resourceSet, (SerializationProcessListener) snippet); + //todo: verify person. + addSnippet(snippet); + + } + + @Test + public void test1930Census() throws Exception { + createRecipe("Describing a 1930 Census Online Record") + .withDescription("Example for describing an online 1930 Census Record.") + .applicableTo(Description.class); + + String sourceId = "1"; + String sourceOfSourceId = "2"; + + RDFValue sourceOfSourceRef = new RDFValue(); + sourceOfSourceRef.setResource(URI.create("#" + sourceOfSourceId)); + + DublinCoreDescriptionDecorator source = DublinCoreDescriptionDecorator.newInstance() + .bibliographicCitation(new RDFLiteral("\"United States Census, 1930,\" index and images, FamilySearch (https://familysearch.org/pal:/MM9.1.1/XSYY-Q62 : accessed 13 April 2012), John E. Reagan, Dixon, Lee, Illinois")) + .source(sourceOfSourceRef); + source.getDecoratedDescription().setId(sourceId); + + DublinCoreDescriptionDecorator sourceOfTheSource = DublinCoreDescriptionDecorator.newInstance() + .bibliographicCitation(new RDFLiteral("enumeration district 0017, sheet 7A, family 207, line 44, National Archives microfilm publication T626, roll 523.")); + sourceOfTheSource.getDecoratedDescription().setId(sourceOfSourceId); + + ResourceSet resourceSet = new ResourceSet(); + resourceSet.addExtensionElement(source.getDecoratedDescription()); + resourceSet.addExtensionElement(sourceOfTheSource.getDecoratedDescription()); + + Snippet snippet = new Snippet(); + resourceSet = processThroughXml(resourceSet, ResourceSet.class, JAXBContext.newInstance(ResourceSet.class, Description.class, ObjectFactory.class), (SerializationProcessListener)snippet); + //todo: verify person. + resourceSet = processThroughJson(resourceSet, (SerializationProcessListener) snippet); + //todo: verify person. + addSnippet(snippet); + + } +} diff --git a/gedcomx-metadata/src/test/java/org/gedcomx/metadata/foaf/PersonTest.java b/gedcomx-metadata/src/test/java/org/gedcomx/metadata/foaf/PersonTest.java index e50fa5fd..9a4b4e6e 100644 --- a/gedcomx-metadata/src/test/java/org/gedcomx/metadata/foaf/PersonTest.java +++ b/gedcomx-metadata/src/test/java/org/gedcomx/metadata/foaf/PersonTest.java @@ -24,7 +24,7 @@ public void testPersonXml() throws Exception { } /** - * tests alternate id json + * tests id json */ public void testPersonJson() throws Exception { Person person = createPerson(); @@ -47,6 +47,7 @@ private Person createPerson() { person.getAccounts().add(account); person.setAddresses(new ArrayList
()); Address address = new Address(); + address.setValue("street1\nstreet2\nstreet3\ncity UT, 88888\ncountry"); address.setCity("city"); address.setCountry("country"); address.setId("id"); @@ -80,6 +81,7 @@ private void assertPerson(Person person) { assertEquals("id", person.getAccounts().get(0).getId()); assertEquals("http://familysearch.org", person.getAccounts().get(0).getServiceHomepage().getResource().toString()); assertEquals(1, person.getAddresses().size()); + assertEquals("street1\nstreet2\nstreet3\ncity UT, 88888\ncountry", person.getAddresses().get(0).getValue()); assertEquals("city", person.getAddresses().get(0).getCity()); assertEquals("country", person.getAddresses().get(0).getCountry()); assertEquals("id", person.getAddresses().get(0).getId()); diff --git a/gedcomx-metadata/src/test/java/org/gedcomx/metadata/rdf/DescriptionTest.java b/gedcomx-metadata/src/test/java/org/gedcomx/metadata/rdf/DescriptionTest.java index 3eac48f8..aa1240b3 100644 --- a/gedcomx-metadata/src/test/java/org/gedcomx/metadata/rdf/DescriptionTest.java +++ b/gedcomx-metadata/src/test/java/org/gedcomx/metadata/rdf/DescriptionTest.java @@ -21,7 +21,7 @@ public class DescriptionTest { /** - * tests alternate id xml + * tests id xml */ public void testRDFMetadataXml() throws Exception { Description meta = new Description(); @@ -39,7 +39,7 @@ public void testRDFMetadataXml() throws Exception { } /** - * tests alternate id json + * tests id json */ public void testRDFMetadataJson() throws Exception { Description meta = new Description(); diff --git a/gedcomx-rt-support/pom.xml b/gedcomx-rt-support/pom.xml index 9dd7ca22..ea0cfbd3 100644 --- a/gedcomx-rt-support/pom.xml +++ b/gedcomx-rt-support/pom.xml @@ -7,7 +7,7 @@ org.gedcomx gedcomx-parent - 0.14.0-SNAPSHOT + 0.18.0-SNAPSHOT diff --git a/gedcomx-rt-support/src/main/java/org/gedcomx/rt/GedcomNamespaceManager.java b/gedcomx-rt-support/src/main/java/org/gedcomx/rt/GedcomNamespaceManager.java index 2fc314a8..296ebd71 100644 --- a/gedcomx-rt-support/src/main/java/org/gedcomx/rt/GedcomNamespaceManager.java +++ b/gedcomx-rt-support/src/main/java/org/gedcomx/rt/GedcomNamespaceManager.java @@ -16,11 +16,15 @@ package org.gedcomx.rt; import com.sun.xml.bind.marshaller.NamespacePrefixMapper; +import org.gedcomx.rt.json.JsonElementWrapper; +import javax.xml.XMLConstants; import javax.xml.bind.annotation.XmlElementDecl; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlSchema; +import javax.xml.bind.annotation.XmlType; import javax.xml.namespace.QName; +import java.beans.Introspector; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; @@ -42,7 +46,10 @@ public class GedcomNamespaceManager extends NamespacePrefixMapper { private static boolean INITIALIZED = false; private static final Map KNOWN_PREFIXES = new HashMap(); private static final Map RUNTIME_VERSIONS = new HashMap(); - private static final Map KNOWN_JSON_ELEMENT_WRAPPER_NAMES = new HashMap(); + private static final Map> WRAPPED_JSON_TYPES_BY_NAME = new HashMap>(); + private static final Map QNAME_WRAPPER_JSON_NAMES = new HashMap(); + private static final Map> KNOWN_JSON_TYPES_BY_NAME = new HashMap>(); + private static final Map> KNOWN_JSON_TYPES_BY_TYPE_ID = new HashMap>(); public GedcomNamespaceManager(Class rootClass) { this(getDefaultNamespace(rootClass)); @@ -122,7 +129,8 @@ protected static synchronized void init(ClassLoader loader) { namespacePrefixes.put("http://gedcomx.org/record/v1/", "gxr"); namespacePrefixes.put("http://gedcomx.org/conclusion/v1/", "gxc"); - Map elementWrappers = new HashMap(); + Map wrapperJsonNames = new HashMap(); + Map> wrappedJsonTypes = new HashMap>(); Set> modelClasses = new HashSet>(); modelClasses.add(CommonModels.class); @@ -158,7 +166,7 @@ protected static synchronized void init(ClassLoader loader) { JsonElementWrapper jsonElementWrapper = method.getAnnotation(JsonElementWrapper.class); if (jsonElementWrapper != null) { XmlElementDecl elementDecl = method.getAnnotation(XmlElementDecl.class); - if (elementDecl != null) { + if (elementDecl != null && method.getParameterTypes().length == 1) { String ns = elementDecl.namespace(); if ("##default".equals(ns)) { if (objectFactory.getPackage().isAnnotationPresent(XmlSchema.class)) { @@ -170,7 +178,9 @@ protected static synchronized void init(ClassLoader loader) { } String name = elementDecl.name(); - elementWrappers.put(new QName(ns, name), new QName(jsonElementWrapper.namespace(), jsonElementWrapper.name())); + String jsonAttribute = jsonElementWrapper.namespace() + jsonElementWrapper.name(); + wrapperJsonNames.put(new QName(ns, name), jsonAttribute); + wrappedJsonTypes.put(jsonAttribute, method.getParameterTypes()[0]); } } } @@ -179,10 +189,24 @@ protected static synchronized void init(ClassLoader loader) { } KNOWN_PREFIXES.putAll(namespacePrefixes); - KNOWN_JSON_ELEMENT_WRAPPER_NAMES.putAll(elementWrappers); + QNAME_WRAPPER_JSON_NAMES.putAll(wrapperJsonNames); + WRAPPED_JSON_TYPES_BY_NAME.putAll(wrappedJsonTypes); INITIALIZED = true; } + public static String nameFromQName(String namespaceUri, String localPart) { + if (namespaceUri == null) { + namespaceUri = ""; + } + + StringBuilder nameBuilder = new StringBuilder(namespaceUri); + if (XMLConstants.XML_NS_URI.equals(namespaceUri)) { + nameBuilder.append('#'); + } + nameBuilder.append(localPart); + return nameBuilder.toString(); + } + @Override public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) { String choice = this.ns2prefix.get(namespaceUri); @@ -198,24 +222,24 @@ public String getPreferredPrefix(String namespaceUri, String suggestion, boolean /** * Get the json wrapper name for the specified XML element name. * - * @param elementName The XML element wrapper name. + * @param wrapperName The identifier for the wrapper name. * @return The json wrapper name, or null if none. */ - public static QName getJsonWrapperName(QName elementName) { + public static String getJsonNameForWrapperName(QName wrapperName) { init(Thread.currentThread().getContextClassLoader()); - return KNOWN_JSON_ELEMENT_WRAPPER_NAMES.get(elementName); + return QNAME_WRAPPER_JSON_NAMES.get(wrapperName); } /** - * Get the qname for the specified json wrapper name. + * Get the wrapper name for the specified json name. * - * @param jsonWrapperName The json wrapper name. - * @return The XML QName. + * @param jsonName The json name. + * @return The wrapper qname. */ - public static QName findQNameFromJsonWrapperName(String jsonWrapperName) { + public static QName findWrapperNameForJsonName(String jsonName) { init(Thread.currentThread().getContextClassLoader()); - for (Map.Entry entry : KNOWN_JSON_ELEMENT_WRAPPER_NAMES.entrySet()) { - if ((entry.getValue().getNamespaceURI() + entry.getValue().getLocalPart()).equals(jsonWrapperName)) { + for (Map.Entry entry : QNAME_WRAPPER_JSON_NAMES.entrySet()) { + if (entry.getValue().equals(jsonName)) { return entry.getKey(); } } @@ -223,6 +247,114 @@ public static QName findQNameFromJsonWrapperName(String jsonWrapperName) { return null; } + /** + * Get the type of the wrapped object for the specified json name. + * + * @param jsonName The json name. + * @return The wrapped type. + */ + public static Class getWrappedTypeForJsonName(String jsonName) { + init(Thread.currentThread().getContextClassLoader()); + return WRAPPED_JSON_TYPES_BY_NAME.get(jsonName); + } + + /** + * Register a known JSON type. It must be annotated with either @JsonElementWrapper or @XmlRootElement. + * + * @param type the type to register. + */ + public static void registerKnownJsonType(Class type) { + String jsonName = getJsonName(type); + if (jsonName != null) { + KNOWN_JSON_TYPES_BY_NAME.put(jsonName, type); + } + KNOWN_JSON_TYPES_BY_TYPE_ID.put(getTypeIdName(type), type); + } + + /** + * Get the JSON name for the specified type. + * + * @param type The type. + * @return The json name. + */ + public static String getJsonName(Class type) { + if (type.isAnnotationPresent(JsonElementWrapper.class)) { + //support custom json element name + JsonElementWrapper ext = type.getAnnotation(JsonElementWrapper.class); + return nameFromQName(ext.namespace(), ext.name()); + } + else if (type.isAnnotationPresent(XmlRootElement.class)) { + XmlRootElement rootElement = type.getAnnotation(XmlRootElement.class); + if (rootElement != null) { + String localPart = rootElement.name(); + if ("##default".equals(localPart)) { + localPart = Introspector.decapitalize(type.getSimpleName()); + } + String namespaceURI = rootElement.namespace(); + if ("##default".equals(namespaceURI)) { + Package pkg = type.getPackage(); + if (pkg != null && pkg.isAnnotationPresent(XmlSchema.class)) { + namespaceURI = pkg.getAnnotation(XmlSchema.class).namespace(); + } + else { + namespaceURI = ""; + } + } + + return nameFromQName(namespaceURI, localPart); + } + } + + return null; + } + + /** + * Get the id for the specified type. + * + * @param type The type. + * @return The type id. + */ + static String getTypeIdName(Class type) { + String ns = ""; + if (type.getPackage() != null && type.getPackage().isAnnotationPresent(XmlSchema.class)) { + ns = type.getPackage().getAnnotation(XmlSchema.class).namespace(); + } + + String name = Introspector.decapitalize(type.getSimpleName()); + if (type.isAnnotationPresent(XmlType.class)) { + XmlType typeMeta = type.getAnnotation(XmlType.class); + if (!"##default".equals(typeMeta.name())) { + name = typeMeta.name(); + } + + if (!"##default".equals(typeMeta.namespace())) { + ns = typeMeta.namespace(); + } + } + + return ns + name; + } + + /** + * Get the known type for the given JSON name. + * + * @param jsonName The json name. + * @return The known type, or null if not known. + */ + public static Class getKnownJsonType(String jsonName) { + return KNOWN_JSON_TYPES_BY_NAME.get(jsonName); + } + + /** + * Get the known type for the given data type. + * + * @param typeId The type id. + * @return The known type, or null if not known. + */ + public static Class getKnownTypeById(String typeId) { + return KNOWN_JSON_TYPES_BY_NAME.get(typeId); + } + /** * Get the version of the runtime java library that defines the model for the given namespace. * diff --git a/gedcomx-rt-support/src/main/java/org/gedcomx/rt/SerializationUtil.java b/gedcomx-rt-support/src/main/java/org/gedcomx/rt/SerializationUtil.java index 090d630a..e71bbf1a 100644 --- a/gedcomx-rt-support/src/main/java/org/gedcomx/rt/SerializationUtil.java +++ b/gedcomx-rt-support/src/main/java/org/gedcomx/rt/SerializationUtil.java @@ -19,6 +19,7 @@ import org.codehaus.jackson.map.SerializationConfig; import org.codehaus.jackson.map.annotate.JsonSerialize; import org.codehaus.jackson.node.ObjectNode; +import org.gedcomx.rt.json.GedcomJsonProvider; import org.w3c.dom.Document; import javax.xml.bind.JAXBContext; @@ -155,6 +156,7 @@ public static byte[] toJsonStream(Object reference, Class insta } protected static byte[] toJsonStream(Object reference, Class instanceClass, ObjectMapper mapper, SerializationProcessListener... listeners) throws IOException { + GedcomNamespaceManager.registerKnownJsonType(instanceClass); ByteArrayOutputStream out = new ByteArrayOutputStream(); mapper.getSerializationConfig().enable(SerializationConfig.Feature.INDENT_OUTPUT); mapper.getSerializationConfig().setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL); diff --git a/gedcomx-rt-support/src/main/java/org/gedcomx/rt/XmlTypeIdResolver.java b/gedcomx-rt-support/src/main/java/org/gedcomx/rt/XmlTypeIdResolver.java deleted file mode 100644 index da47cae6..00000000 --- a/gedcomx-rt-support/src/main/java/org/gedcomx/rt/XmlTypeIdResolver.java +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Copyright 2011-2012 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.rt; - -import org.codehaus.jackson.annotate.JsonTypeInfo; -import org.codehaus.jackson.map.jsontype.TypeIdResolver; -import org.codehaus.jackson.map.type.SimpleType; -import org.codehaus.jackson.type.JavaType; - -import javax.xml.bind.annotation.XmlSchema; -import javax.xml.bind.annotation.XmlTransient; -import javax.xml.bind.annotation.XmlType; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * JSON type id resolver for supporting polymorphic type handling in JSON. - * - * @author Ryan Heaton - */ -@XmlTransient -public class XmlTypeIdResolver implements TypeIdResolver { - - public static final String TYPE_PROPERTY_NAME = "@type"; - - private static final Map ID_TO_TYPE = new ConcurrentHashMap(); - private static final Map, String> TYPE_TO_ID = new ConcurrentHashMap, String>(); - - public static void initContextClass(JavaType javaType) { - Class rawClass = javaType.getRawClass(); - String typeQName = getTypeURI(rawClass); - ID_TO_TYPE.put(typeQName, javaType); - TYPE_TO_ID.put(rawClass, typeQName); - } - - public void init(JavaType javaType) { - initContextClass(javaType); - } - - public String idFromValue(Object o) { - return idFromValueAndType(o, o.getClass()); - } - - public String idFromValueAndType(Object o, Class clazz) { - String id = TYPE_TO_ID.get(clazz); - if (id == null) { - init(SimpleType.construct(clazz)); - } - return TYPE_TO_ID.get(clazz); - } - - public JavaType typeFromId(String s) { - return ID_TO_TYPE.get(s); - } - - public JsonTypeInfo.Id getMechanism() { - return JsonTypeInfo.Id.CLASS; - } - - public static String getTypeURI(Class rawClass) { - String ns = ""; - Package pckg = rawClass.getPackage(); - if (pckg != null) { - XmlSchema schemaInfo = pckg.getAnnotation(XmlSchema.class); - if (schemaInfo != null) { - ns = schemaInfo.namespace(); - } - } - - String name = java.beans.Introspector.decapitalize(rawClass.getSimpleName()); - XmlType annotation = rawClass.getAnnotation(XmlType.class); - if (annotation != null) { - if (!"##default".equals(annotation.namespace())) { - ns = annotation.namespace(); - } - if (!"##default".equals(annotation.name())) { - name = annotation.name(); - } - } - - return new StringBuilder(ns).append(name).toString(); - } - -} diff --git a/gedcomx-rt-support/src/main/java/org/gedcomx/rt/ExtensibleObjectDeserializer.java b/gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/ExtensibleObjectDeserializer.java similarity index 55% rename from gedcomx-rt-support/src/main/java/org/gedcomx/rt/ExtensibleObjectDeserializer.java rename to gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/ExtensibleObjectDeserializer.java index 1fe2268b..04b57bac 100644 --- a/gedcomx-rt-support/src/main/java/org/gedcomx/rt/ExtensibleObjectDeserializer.java +++ b/gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/ExtensibleObjectDeserializer.java @@ -13,19 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.gedcomx.rt; +package org.gedcomx.rt.json; import org.codehaus.jackson.JsonParser; import org.codehaus.jackson.JsonProcessingException; import org.codehaus.jackson.JsonToken; import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.JsonMappingException; import org.codehaus.jackson.map.deser.BeanDeserializer; -import org.codehaus.jackson.map.jsontype.impl.AsPropertyTypeDeserializer; -import org.codehaus.jackson.map.type.SimpleType; +import org.gedcomx.rt.GedcomNamespaceManager; +import org.gedcomx.rt.SupportsExtensionAttributes; +import org.gedcomx.rt.SupportsExtensionElements; import javax.xml.XMLConstants; import javax.xml.bind.JAXBElement; -import javax.xml.bind.annotation.XmlRootElement; import javax.xml.namespace.QName; import java.io.IOException; import java.util.ArrayList; @@ -38,23 +39,56 @@ */ public class ExtensibleObjectDeserializer extends BeanDeserializer { - private final XmlTypeIdResolver xmlTypeIdResolver; - private final AsPropertyTypeDeserializer typeDeserializer; - public ExtensibleObjectDeserializer(BeanDeserializer src) { super(src); - this.xmlTypeIdResolver = new XmlTypeIdResolver(); - this.typeDeserializer = new AsPropertyTypeDeserializer(SimpleType.construct(Object.class), this.xmlTypeIdResolver, null, XmlTypeIdResolver.TYPE_PROPERTY_NAME); } @Override protected void handleUnknownProperty(JsonParser jp, DeserializationContext ctxt, Object beanOrClass, String propName) throws IOException, JsonProcessingException { - if (XmlTypeIdResolver.TYPE_PROPERTY_NAME.equals(propName)) { + if (beanOrClass instanceof SupportsExtensionElements) { + SupportsExtensionElements target = (SupportsExtensionElements) beanOrClass; + //first check if it's a known json type + Class type = GedcomNamespaceManager.getKnownJsonType(propName); + if (type != null) { + //it's a known json type. + if (HasJsonKey.class.isAssignableFrom(type)) { + for (Object ext : readKeyedMapOf(type, jp, ctxt)) { + target.addExtensionElement(ext); + } + } + else { + //otherwise just deserialize as a list and go. + for (Object ext : readArrayOf(type, jp, ctxt)) { + target.addExtensionElement(ext); + } + } + return; + } + else { + QName wrapper = getWrapperName(propName); + type = GedcomNamespaceManager.getWrappedTypeForJsonName(propName); + if (type != null) { + List objects = readArrayOf(type, jp, ctxt); + for (Object ext : objects) { + target.addExtensionElement(new JAXBElement(wrapper, type, ext)); + } + return; + } + } + } + + if (beanOrClass instanceof SupportsExtensionAttributes && jp.getCurrentToken().isScalarValue()) { + ((SupportsExtensionAttributes) beanOrClass).addExtensionAttribute(getWrapperName(propName), jp.getText()); return; } - - QName qname = null; - if (propName.indexOf(':') >= 0) { + + super.handleUnknownProperty(jp, ctxt, beanOrClass, propName); + } + + private QName getWrapperName(String propName) { + QName qname = GedcomNamespaceManager.findWrapperNameForJsonName(propName); + + if (qname == null && propName.indexOf(':') >= 0) { //if the propname has a ':', we'll treat it as a qname, because all qnames I know have a ':' in them. List knownNS = new ArrayList(GedcomNamespaceManager.getKnownPrefixes().keySet()); knownNS.add(XMLConstants.XML_NS_URI + "#"); @@ -90,39 +124,36 @@ protected void handleUnknownProperty(JsonParser jp, DeserializationContext ctxt, } } - if (qname == null) { - qname = GedcomNamespaceManager.findQNameFromJsonWrapperName(propName); - } - if (qname == null) { qname = new QName("", propName); } - if (beanOrClass instanceof SupportsExtensionAttributes && jp.getCurrentToken().isScalarValue()) { - ((SupportsExtensionAttributes) beanOrClass).addExtensionAttribute(qname, jp.getText()); - } - else if (beanOrClass instanceof SupportsExtensionElements) { - if (jp.getCurrentToken() == JsonToken.START_ARRAY) { + return qname; + } + + private List readArrayOf(Class type, JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + ArrayList objects = new ArrayList(); + + if (jp.getCurrentToken() == JsonToken.START_ARRAY) { + jp.nextToken(); + while (jp.getCurrentToken() != JsonToken.END_ARRAY) { + objects.add(jp.readValueAs(type)); jp.nextToken(); - while (jp.getCurrentToken() != JsonToken.END_ARRAY) { - Object element = this.typeDeserializer.deserializeTypedFromAny(jp, ctxt); - if (element != null && !element.getClass().isAnnotationPresent(XmlRootElement.class)) { - element = new JAXBElement(qname, element.getClass(), element); - } - ((SupportsExtensionElements) beanOrClass).addExtensionElement(element); - jp.nextToken(); - } - } - else { - Object element = this.typeDeserializer.deserializeTypedFromAny(jp, ctxt); - if (element != null && !element.getClass().isAnnotationPresent(XmlRootElement.class)) { - element = new JAXBElement(qname, element.getClass(), element); - } - ((SupportsExtensionElements) beanOrClass).addExtensionElement(element); } } else { - super.handleUnknownProperty(jp, ctxt, beanOrClass, propName); + objects.add(jp.readValueAs(type)); + } + + return objects; + } + + private List readKeyedMapOf(Class type, JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + if (jp.getCurrentToken() == JsonToken.START_OBJECT) { + return KeyedListDeserializer.deserializeGeneric(jp, ctxt, type); + } + else { + throw new JsonMappingException("Unable to parse keyed map of " + type.getName() + ": expect start object, but got: " + jp.getCurrentToken().name()); } } diff --git a/gedcomx-rt-support/src/main/java/org/gedcomx/rt/ExtensibleObjectSerializer.java b/gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/ExtensibleObjectSerializer.java similarity index 66% rename from gedcomx-rt-support/src/main/java/org/gedcomx/rt/ExtensibleObjectSerializer.java rename to gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/ExtensibleObjectSerializer.java index 9a78ac8c..7500a6b1 100644 --- a/gedcomx-rt-support/src/main/java/org/gedcomx/rt/ExtensibleObjectSerializer.java +++ b/gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/ExtensibleObjectSerializer.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.gedcomx.rt; +package org.gedcomx.rt.json; import org.codehaus.jackson.JsonGenerationException; import org.codehaus.jackson.JsonGenerator; @@ -21,15 +21,14 @@ import org.codehaus.jackson.map.JsonMappingException; import org.codehaus.jackson.map.SerializerProvider; import org.codehaus.jackson.map.ser.BeanSerializer; +import org.gedcomx.rt.GedcomNamespaceManager; +import org.gedcomx.rt.SupportsExtensionAttributes; +import org.gedcomx.rt.SupportsExtensionElements; import org.w3c.dom.Element; import org.w3c.dom.Node; -import javax.xml.XMLConstants; import javax.xml.bind.JAXBElement; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlSchema; import javax.xml.namespace.QName; -import java.beans.Introspector; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; @@ -88,59 +87,30 @@ public void serializeExtensionElements(SupportsExtensionElements value, JsonGene Map> extensionProperties = new HashMap>(); for (Object element : extensionElements) { if (element != null) { - QName name; + String name; if (element instanceof Element) { Element el = (Element) element; - name = new QName(el.getNamespaceURI() == null ? "" : el.getNamespaceURI(), el.getLocalName()); + name = GedcomNamespaceManager.nameFromQName(el.getNamespaceURI(), el.getLocalName()); } else if (element instanceof JAXBElement) { - name = GedcomNamespaceManager.getJsonWrapperName(((JAXBElement) element).getName()); + name = GedcomNamespaceManager.getJsonNameForWrapperName(((JAXBElement) element).getName()); if (name == null) { - name = ((JAXBElement) element).getName(); + name = GedcomNamespaceManager.nameFromQName(((JAXBElement) element).getName().getNamespaceURI(), ((JAXBElement) element).getName().getLocalPart()); } element = ((JAXBElement) element).getValue(); } - else if (element.getClass().isAnnotationPresent(JsonElementWrapper.class)) { - //support custom json element name - JsonElementWrapper ext = element.getClass().getAnnotation(JsonElementWrapper.class); - name = new QName(ext.namespace(), ext.name()); - } else { - XmlRootElement rootElement = element.getClass().getAnnotation(XmlRootElement.class); - if (rootElement != null) { - String localPart = rootElement.name(); - if ("##default".equals(localPart)) { - localPart = Introspector.decapitalize(element.getClass().getSimpleName()); - } - String namespaceURI = rootElement.namespace(); - if ("##default".equals(namespaceURI)) { - Package pkg = element.getClass().getPackage(); - if (pkg != null && pkg.isAnnotationPresent(XmlSchema.class)) { - namespaceURI = pkg.getAnnotation(XmlSchema.class).namespace(); - } - else { - namespaceURI = ""; - } - } - - name = new QName(namespaceURI, localPart); - } - else { + name = GedcomNamespaceManager.getJsonName(element.getClass()); + if (name == null) { throw new JsonMappingException("Unable to serialize custom element " + value + - " because it isn't annotated with @XmlRootElement. If you need to, wrap it in a javax.xml.bind.JAXBElement so we can identify its name."); + " because it's not a JAXBElement, DOM element, nor is it annotated with either @JsonElementWrapper or @XmlRootElement."); } } - String fullname = name.getNamespaceURI(); - if (XMLConstants.XML_NS_URI.equals(name.getNamespaceURI())) { - fullname += "#"; - } - fullname += name.getLocalPart(); - - List propList = extensionProperties.get(fullname); + List propList = extensionProperties.get(name); if (propList == null) { propList = new ArrayList(); - extensionProperties.put(fullname, propList); + extensionProperties.put(name, propList); } propList.add(element); @@ -148,16 +118,23 @@ else if (element.getClass().isAnnotationPresent(JsonElementWrapper.class)) { } for (Map.Entry> prop : extensionProperties.entrySet()) { - jgen.writeArrayFieldStart(prop.getKey()); - for (Object element : prop.getValue()) { - if (element instanceof Element) { - serializeElement((Element) element, jgen); - } - else { - provider.findTypedValueSerializer(element.getClass(), true, null).serialize(element, jgen, provider); + if (prop.getValue().get(0) instanceof HasJsonKey) { + //we're serialize out this list as a keyed map. + jgen.writeFieldName(prop.getKey()); + KeyedListSerializer.serializeGeneric(prop.getValue(), jgen, provider); + } + else { + jgen.writeArrayFieldStart(prop.getKey()); + for (Object element : prop.getValue()) { + if (element instanceof Element) { + serializeElement((Element) element, jgen); + } + else { + provider.findTypedValueSerializer(element.getClass(), true, null).serialize(element, jgen, provider); + } } + jgen.writeEndArray(); } - jgen.writeEndArray(); } } } diff --git a/gedcomx-rt-support/src/main/java/org/gedcomx/rt/GedcomBeanDeserializerModifier.java b/gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/GedcomBeanDeserializerModifier.java similarity index 95% rename from gedcomx-rt-support/src/main/java/org/gedcomx/rt/GedcomBeanDeserializerModifier.java rename to gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/GedcomBeanDeserializerModifier.java index a0d0d514..2bd136d5 100644 --- a/gedcomx-rt-support/src/main/java/org/gedcomx/rt/GedcomBeanDeserializerModifier.java +++ b/gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/GedcomBeanDeserializerModifier.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.gedcomx.rt; +package org.gedcomx.rt.json; import org.codehaus.jackson.map.DeserializationConfig; import org.codehaus.jackson.map.JsonDeserializer; diff --git a/gedcomx-rt-support/src/main/java/org/gedcomx/rt/GedcomBeanSerializerModifier.java b/gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/GedcomBeanSerializerModifier.java similarity index 95% rename from gedcomx-rt-support/src/main/java/org/gedcomx/rt/GedcomBeanSerializerModifier.java rename to gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/GedcomBeanSerializerModifier.java index 02d8afb7..c99e029b 100644 --- a/gedcomx-rt-support/src/main/java/org/gedcomx/rt/GedcomBeanSerializerModifier.java +++ b/gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/GedcomBeanSerializerModifier.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.gedcomx.rt; +package org.gedcomx.rt.json; import org.codehaus.jackson.map.JsonSerializer; import org.codehaus.jackson.map.SerializationConfig; diff --git a/gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/GedcomJacksonModule.java b/gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/GedcomJacksonModule.java new file mode 100644 index 00000000..70118b97 --- /dev/null +++ b/gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/GedcomJacksonModule.java @@ -0,0 +1,72 @@ +/** + * Copyright 2011-2012 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.rt.json; + +import org.codehaus.jackson.Version; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.type.CollectionType; + +/** + * GEDCOM Jackson module for Jackson customizations. + * + * @author Ryan Heaton + */ +public class GedcomJacksonModule extends Module { + + @Override + public String getModuleName() { + return "gedcomx"; + } + + @Override + public Version version() { + return new Version(1,0,0,null); + } + + @Override + public void setupModule(SetupContext context) { + context.addBeanSerializerModifier(new GedcomBeanSerializerModifier()); + context.addBeanDeserializerModifier(new GedcomBeanDeserializerModifier()); + context.addDeserializers(new GedcomDeserializers()); + context.addSerializers(new GedcomSerializers()); + } + + protected static class GedcomSerializers extends Serializers.None { + + @Override + public JsonSerializer findCollectionSerializer(SerializationConfig config, CollectionType type, BeanDescription beanDesc, BeanProperty property, TypeSerializer elementTypeSerializer, JsonSerializer elementValueSerializer) { + if (type.getContentType() != null && HasJsonKey.class.isAssignableFrom(type.getContentType().getRawClass())) { + return new KeyedListSerializer(); + } + + return super.findCollectionSerializer(config, type, beanDesc, property, elementTypeSerializer, elementValueSerializer); + } + } + + protected static class GedcomDeserializers extends Deserializers.None { + + @Override + public JsonDeserializer findCollectionDeserializer(CollectionType type, DeserializationConfig config, DeserializerProvider provider, BeanDescription beanDesc, BeanProperty property, TypeDeserializer elementTypeDeserializer, JsonDeserializer elementDeserializer) throws JsonMappingException { + if (type.getContentType() != null && HasJsonKey.class.isAssignableFrom(type.getContentType().getRawClass())) { + return new KeyedListDeserializer(type.getContentType().getRawClass()); + } + + return super.findCollectionDeserializer(type, config, provider, beanDesc, property, elementTypeDeserializer, elementDeserializer); + } + + } + +} diff --git a/gedcomx-rt-support/src/main/java/org/gedcomx/rt/GedcomJsonProvider.java b/gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/GedcomJsonProvider.java similarity index 69% rename from gedcomx-rt-support/src/main/java/org/gedcomx/rt/GedcomJsonProvider.java rename to gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/GedcomJsonProvider.java index 2165d847..6286cc19 100644 --- a/gedcomx-rt-support/src/main/java/org/gedcomx/rt/GedcomJsonProvider.java +++ b/gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/GedcomJsonProvider.java @@ -13,19 +13,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.gedcomx.rt; +package org.gedcomx.rt.json; import org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider; import org.codehaus.jackson.map.AnnotationIntrospector; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.introspect.JacksonAnnotationIntrospector; -import org.codehaus.jackson.map.type.SimpleType; import org.codehaus.jackson.xc.JaxbAnnotationIntrospector; +import org.gedcomx.rt.GedcomNamespaceManager; import javax.ws.rs.Consumes; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.ext.Provider; +import java.io.IOException; +import java.io.InputStream; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; /** * The custom json provider for GEDCOM JSON data. @@ -58,8 +63,20 @@ public static ObjectMapper createObjectMapper(Class... classes) { mapper.getDeserializationConfig().withAnnotationIntrospector(introspector); mapper.registerModule(new GedcomJacksonModule()); for (Class contextClass : classes) { - XmlTypeIdResolver.initContextClass(SimpleType.construct(contextClass)); + GedcomNamespaceManager.registerKnownJsonType(contextClass); } return mapper; } + + @Override + public Object readFrom(Class type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap httpHeaders, InputStream entityStream) throws IOException { + String dataType = httpHeaders.getFirst("X-type"); + if (dataType != null) { + Class knownType = (Class) GedcomNamespaceManager.getKnownTypeById(dataType); + if (type != null && knownType != null && type.isAssignableFrom(knownType)) { + type = knownType; + } + } + return super.readFrom(type, genericType, annotations, mediaType, httpHeaders, entityStream); + } } diff --git a/gedcomx-rt-support/src/main/java/org/gedcomx/rt/GedcomJacksonModule.java b/gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/HasJsonKey.java similarity index 51% rename from gedcomx-rt-support/src/main/java/org/gedcomx/rt/GedcomJacksonModule.java rename to gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/HasJsonKey.java index c36b75b9..8df79857 100644 --- a/gedcomx-rt-support/src/main/java/org/gedcomx/rt/GedcomJacksonModule.java +++ b/gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/HasJsonKey.java @@ -1,44 +1,39 @@ -/** - * Copyright 2011-2012 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.rt; - -import org.codehaus.jackson.Version; -import org.codehaus.jackson.map.Module; - -/** - * GEDCOM Jackson module for Jackson customizations. - * - * @author Ryan Heaton - */ -public class GedcomJacksonModule extends Module { - - @Override - public String getModuleName() { - return "gedcomx"; - } - - @Override - public Version version() { - return new Version(1,0,0,null); - } - - @Override - public void setupModule(SetupContext context) { - context.addBeanSerializerModifier(new GedcomBeanSerializerModifier()); - context.addBeanDeserializerModifier(new GedcomBeanDeserializerModifier()); - } - -} +/** + * Copyright 2011-2012 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.rt.json; + +/** + * Interface for objects that support access by a JSON map instead of access by a list when a list of the objects are supplied. + * + * @author Ryan Heaton + */ +public interface HasJsonKey { + + /** + * The JSON key in the map for this object. + * + * @return The key in the map. + */ + String getJsonKey(); + + /** + * The JSON key in the map for this object. + * + * @param jsonKey The key in the map. + */ + void setJsonKey(String jsonKey); + +} diff --git a/gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/HasUniqueJsonKey.java b/gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/HasUniqueJsonKey.java new file mode 100644 index 00000000..76d005a7 --- /dev/null +++ b/gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/HasUniqueJsonKey.java @@ -0,0 +1,25 @@ +/** + * Copyright 2011-2012 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.rt.json; + +/** + * Marker interface used as an indicator that each of these objects in a list have a unique json key. + * + * @author Ryan Heaton + */ +public interface HasUniqueJsonKey extends HasJsonKey { + +} diff --git a/gedcomx-rt-support/src/main/java/org/gedcomx/rt/JsonElementWrapper.java b/gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/JsonElementWrapper.java similarity index 95% rename from gedcomx-rt-support/src/main/java/org/gedcomx/rt/JsonElementWrapper.java rename to gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/JsonElementWrapper.java index f8392588..5d370294 100644 --- a/gedcomx-rt-support/src/main/java/org/gedcomx/rt/JsonElementWrapper.java +++ b/gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/JsonElementWrapper.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.gedcomx.rt; +package org.gedcomx.rt.json; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/JsonSimpleValue.java b/gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/JsonSimpleValue.java new file mode 100644 index 00000000..83c54335 --- /dev/null +++ b/gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/JsonSimpleValue.java @@ -0,0 +1,39 @@ +/** + * Copyright 2011-2012 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.rt.json; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marker to denote an object that is serialized as a JSON simple value. + * + * @author Ryan Heaton + */ +@Retention ( RetentionPolicy.RUNTIME ) +@Target ( { ElementType.TYPE, ElementType.METHOD } ) +public @interface JsonSimpleValue { + + /** + * The example value, if any, for documentation purposes. + * + * @return The example value, if any, for documentation purposes. + */ + String example() default "##default"; + +} diff --git a/gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/KeyedListDeserializer.java b/gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/KeyedListDeserializer.java new file mode 100644 index 00000000..105127be --- /dev/null +++ b/gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/KeyedListDeserializer.java @@ -0,0 +1,89 @@ +/** + * Copyright 2011-2012 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.rt.json; + +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.JsonToken; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.JsonDeserializer; +import org.codehaus.jackson.map.JsonMappingException; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Ryan Heaton + */ +public class KeyedListDeserializer extends JsonDeserializer> { + + private final Class itemType; + + public KeyedListDeserializer(Class itemType) { + if (itemType == null) { + throw new NullPointerException(); + } + this.itemType = itemType; + } + + @Override + public List deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + return deserializeGeneric(jp, ctxt, this.itemType); + } + + static List deserializeGeneric(JsonParser jp, DeserializationContext ctxt, Class itemType) throws IOException, JsonProcessingException { + if (jp.getCurrentToken() == JsonToken.START_OBJECT) { + jp.nextToken(); + } + else { + throw new JsonMappingException("Unable to deserialize keyed list: unexpected token: " + jp.getCurrentToken().name()); + } + + ArrayList list = new ArrayList(); + for (; jp.getCurrentToken() != JsonToken.END_OBJECT; jp.nextToken()) { + String key = jp.getCurrentName(); + jp.nextToken(); + if (jp.isExpectedStartArrayToken()) { + JsonToken t; + while ((t = jp.nextToken()) != JsonToken.END_ARRAY) { + HasJsonKey value; + + if (t == JsonToken.VALUE_NULL) { + value = null; + } + else { + value = (HasJsonKey) jp.readValueAs(itemType); + if (!KeyedListSerializer.JSON_DEFAULT_KEY.equals(key)) { + value.setJsonKey(key); + } + } + + list.add(value); + } + } + else { + HasJsonKey value = (HasJsonKey) jp.readValueAs(itemType); + if (!KeyedListSerializer.JSON_DEFAULT_KEY.equals(key)) { + value.setJsonKey(key); + } + list.add(value); + } + } + + return list; + } +} diff --git a/gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/KeyedListSerializer.java b/gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/KeyedListSerializer.java new file mode 100644 index 00000000..b562cd41 --- /dev/null +++ b/gedcomx-rt-support/src/main/java/org/gedcomx/rt/json/KeyedListSerializer.java @@ -0,0 +1,78 @@ +/** + * Copyright 2011-2012 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.rt.json; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.SerializerProvider; + +import java.io.IOException; +import java.util.*; + +/** + * @author Ryan Heaton + */ +public class KeyedListSerializer extends JsonSerializer> { + + public static final String JSON_DEFAULT_KEY = "$"; + + @Override + public void serialize(Collection value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { + serializeGeneric(value, jgen, provider); + } + + static void serializeGeneric(Collection value, JsonGenerator jgen, SerializerProvider provider) throws IOException { + if (value == null) { + jgen.writeNull(); + } + else { + jgen.writeStartObject(); + Map> bykey = new HashMap>(); + for (Object keyed : value) { + String jsonKey = ((HasJsonKey) keyed).getJsonKey(); + if (jsonKey == null) { + jsonKey = JSON_DEFAULT_KEY; + } + + List keyedList = bykey.get(jsonKey); + if (keyedList == null) { + keyedList = new ArrayList(); + bykey.put(jsonKey, keyedList); + } + keyedList.add(keyed); + } + + for (Map.Entry> keyedObjects : bykey.entrySet()) { + String jsonKey = keyedObjects.getKey(); + jgen.writeFieldName(jsonKey); + boolean notUnique = keyedObjects.getValue().size() != 1 || (!(keyedObjects.getValue().get(0) instanceof HasUniqueJsonKey)); + if (notUnique) { + jgen.writeStartArray(); + } + + for (Object keyed : keyedObjects.getValue()) { + provider.findTypedValueSerializer(keyed.getClass(), true, null).serialize(keyed, jgen, provider); + } + + if (notUnique) { + jgen.writeEndArray(); + } + } + jgen.writeEndObject(); + } + } +} diff --git a/gedcomx-test-support/pom.xml b/gedcomx-test-support/pom.xml index 9fbbc9d0..6667c99c 100644 --- a/gedcomx-test-support/pom.xml +++ b/gedcomx-test-support/pom.xml @@ -8,7 +8,7 @@ org.gedcomx gedcomx-parent - 0.14.0-SNAPSHOT + 0.18.0-SNAPSHOT @@ -30,7 +30,7 @@ org.gedcomx gedcomx-rt-support - 0.14.0-SNAPSHOT + ${project.version} diff --git a/pom.xml b/pom.xml index 7d4e69c9..77e37f93 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ gedcomx-parent org.gedcomx GEDCOM X - Parent Project - 0.14.0-SNAPSHOT + 0.18.0-SNAPSHOT pom @@ -163,7 +163,7 @@ org.gedcomx enunciate-gedcomx-support - 0.14.0-SNAPSHOT + 0.18.0-SNAPSHOT diff --git a/specifications/conceptual-model-specification.md b/specifications/conceptual-model-specification.md new file mode 100644 index 00000000..c46e0dea --- /dev/null +++ b/specifications/conceptual-model-specification.md @@ -0,0 +1,1007 @@ +# The GEDCOM X Conceptual Model + +## Status + +This document specifies a standard conceptual model for exchanging genealogical data, +and requests discussion and suggestions for improvements. + +## Copyright Notice + +Copyright 2011-2012 Intellectual Reserve, Inc. + +## License + +This document is distributed under a Creative Commons Attribution-ShareAlike license. +For details, see: + +http://creativecommons.org/licenses/by-sa/3.0/ + +# 1. Introduction + +The GEDCOM X conceptual model is a specification of formal concepts and types +that are used to provide a standard model and vocabulary for describing genealogical +data. Genealogical data is structured by data types such as persons, +relationships, and sources. + +## 1.1 Identifier and Version + +The identifier for this specification is: + +`http://gedcomx.org/conceptual-model/v1` + +For convenience, the GEDCOM X conceptual model may be referred to as "GEDCOM X 1.0". +This specification uses "GEDCOM X" internally. + +## 1.2 Notational Conventions + +This specification uses the term "data type" to refer to a formal description of +a data structure, including the properties that define valid instances of the +data type. For example, information about a person might be contained within a +data structure that supplies the person's name, birth date, and gender. A "data +type" defines the formal properties of the data structure. + +When a property of a data type is specified as being of a particular data type, the +property inherits the corresponding requirements from that data type's definition. +When a data type is specified as an extension of another data type, the extending +data type inherits the corresponding requirements from the extended data type's +definition. + +Data types are defined by the following sections: + +1. The *identifier* for the data type, which takes the form of a URI. +2. The *extension* of the data type (if any) which specifies which data type + is extended by the data type. +3. The *properties* of the data type, which define the information the data type + encapsulates. + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", +"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this +document are to be interpreted as described in BCP 14, +[RFC2119](http://tools.ietf.org/html/rfc2119), as scoped to those conformance +targets. + +# 2. Common Data Types + +Many data types of the GEDCOM X conceptual model share common structures. This section +defines the data types of those shared structures and their requirements for convenient +reference by the other data type definitions. + + + +## 2.1 The URI + +The Uniform Resource Identifier ("URI") is fundamental to the GEDCOM X conceptual model. +The URI is used to identify specific resources, such as persons, relationships, and +sources. The URI is also used to identify the data structures that describe those resources +and even the data types that define those data structures. The URI is specified by +[RFC3986](http://tools.ietf.org/html/rfc3986). + + + +## 2.2 The "Identifier" Data Type + +The `Identifier` data type defines the data structure used to supply an identifier of a +genealogical resource in a specific data set. + +### identifier + +The identifier for the "Identifier" data type is: + +`http://gedcomx.org/Identifier` + +### properties + +name | description | data type +------|-------------|---------- +value | The value of the identifier. | string (possibly interpreted as a URI, depending on the type of the identifier). +type | URI identifying the type of the identifier. | [URI](#uri) - MUST resolve to an identifier type. Refer to the list of [known identifier types](#known-identifier-types). + + + +### known identifier types + +The following identifier types are defined by GEDCOM X. + +URI | description +----|------------ +`http://gedcomx.org/Forwarded` | + +### examples + +todo: fill in some examples. + + + +## 2.3 The "Attribution" Data Type + +The `Attribution` data type defines the data structure used to supply the attribution (including +who, when, and why) of genealogical data. + +### identifier + +The identifier for the "Attribution" data type is: + +`http://gedcomx.org/Attribution` + +### properties + +name | description | data type +------|-------------|---------- +contributor | Reference to the contributor to whom the attributed data is attributed. | [URI](#uri) - MUST resolve to an instance of [`http://xmlns.com/foaf/0.1/Person`](#foaf-person) or [`http://xmlns.com/foaf/0.1/Organization`](#organization). +confidence | Reference to the confidence level of the contributor of the attributed data. | [URI](#uri) - MUST resolve to a confidence level. Refer to the list of [known confidence levels](#known-confidence-levels). +modified | Timestamp of when the attributed data was contributed. | timestamp +proofStatement | A statement of proof provided by the contributor of the attributed data | string + + + +### known confidence levels + +The following confidence levels are defined by GEDCOM X. For more information, refer to +Mills, Elizabeth Shown. "Fundamentals of Evidence Analysis." Evidence Explained. 2nd ed. +(Baltimore, Maryland: Genealogical Publishing Company, 2009), 19-20 (Section 1.6). + +URI | description +----|------------ +`http://gedcomx.org/Certainly`|The contributor has no reasonable doubt about the assertion, based upon sound research and good evidence. +`http://gedcomx.org/Probably`|The contributor feels the assertion is more likely than not, based upon sound research and good evidence. +`http://gedcomx.org/Possibly`|The contributor feels some evidence supports the assertion, but the assertion is far from proved. +`http://gedcomx.org/Likely`|The contributor feels the odds weigh at least slightly in favor of the assertion. +`http://gedcomx.org/Apparently`|The contributor has formed an impression or presumption, typically based upon common experience, but has not tested the matter. +`http://gedcomx.org/Perhaps`|The contributor suggests that an idea is plausible, although it remains to be tested. + +### examples + +todo: + + + +## 2.4 The "FormalValue" Data Type + +The `FormalValue` data type defines the data structure used to supply a normalized and/or +standardized value. The formal value is used to supply a formal interpretation of a +value that has been supplied by a user. If the value has been reformatted for the purpose of easier +processing (e.g. for display purposes), it is said to be "normalized". If the value has +been resolved to a discrete, machine-identifiable value based on a specific standard, it is +said to be "standardized". + +The `FormalValue` data type does NOT support extension properties (see [Extension Properties](#extension-properties)). + +### identifier + +The identifier for the "FormalValue" data type is: + +`http://gedcomx.org/FormalValue` + +### properties + +name | description | data type +------|-------------|---------- +value | A string supplying the value of the formal value. If the value has been standardized, a datatype will be supplied to identify how the string is to be parsed. | string +datatype | URI identifying the way the value is to be processed according to a specific standard. | [URI](#uri) +resource | URI identifying the resource to which the formal value has been standardized. | [URI](#uri) + +If a value is supplied for the `datatype` property, a value SHALL NOT be supplied for the `resource` property. +If a value is supplied for the `resource` property, a value SHALL NOT be supplied for the `datatype` property. + +### examples + +* A user supplies the text "jan 1 1890" as the value of a genealogical date. If a process + (either automated or by user-interaction) normalizes this text to "1 January 1890", the formal + value containing the results of this normalization will have a value of "1 January 1890" + and no values specified for either the datatype or the resource. +* A user supplies the text "jan 1 1890" as the value of a genealogical date. If a process + (either automated or by user-interaction) standardizes this text to a specific date such as + midnight UTC of the first day of January of the year 1890 A.D. of the Gregorian calendar, + the formal value containing the results of this standardization might have a value of + "1890-01-01T00:00:00Z" and a datatype of "http://www.w3.org/2001/XMLSchema#dateTime" and no value + specified for the resource. +* A user supplies "boston, MA" as the value for a genealogical place. If a process (either + automated or by user-interaction) standardizes this place to a unique resource (e.g. the + actual city know today as Boston, Massachusetts) identified by a specific URI (e.g. + "http://places.com/12345"), the formal value containing the results of this standardization + will have "http://places.com/12345" as the value of its "resource" property. The formal value + MAY also supply a value for the "value" property that contains the results of normalizing + the user-supplied text (e.g. "Boston, Suffolk, Massachusetts, United States"). + + +## 2.5 The "GenealogicalResource" Data Type + +The `GenealogicalResource` data type defines an abstract data structure that defines a basic +genealogical resource. The `GenealogicalResource` data type is not designed to be used independently, +but instead as an abstraction from with other data types can inherit. + +### identifier + +The identifier for the "GenealogicalResource" data type is: + +`http://gedcomx.org/GenealogicalResource` + +### properties + +name | description | data type +------|-------------|---------- +id | A local, transient identifier for the genealogical resource being described. Note that as a local, transient identifier, the id may only be used to resolve references within a well-defined scope (such as a single web service request or a single file). | string +attribution | The attribution of this resource. | [`http://gedcomx.org/Attribution`](#attribution) + + + + +## 2.6 The "Note" Data Type + +The `Note` data type defines a note that was contributed from genealogical research. + +### extension + +This data type extends the following data type: + +`http://gedcomx.org/GenealogicalResource` + +### identifier + +The identifier for the "Note" data type is: + +`http://gedcomx.org/Note` + +### properties + +name | description | data type +------|-------------|---------- +lang | The language of the note. | `http://www.w3.org/XML/1998/namespace#lang` +text | The text of the note. | string + + + +## 2.7 The "RDF Literal" Data Type + +The `RDF Literal` data type defines a literal RDF value. The `Literal` is +defined by the Resource Description Framework (RDF), but its definition is included here +for convenience. + +### identifier + +The identifier for the "RDF Literal" data type is: + +`http://www.w3.org/2000/01/rdf-schema#Literal` + +### properties + +name | description | data type +------|-------------|---------- +value | The literal value. A datatype MAY be supplied to identify how the string is to be parsed. | string +datatype | URI identifying the way the value is to be processed according to a specific standard. | [URI](#uri) +lang | The language of the literal value. | `http://www.w3.org/XML/1998/namespace#lang` + + +## 2.8 The "RDF Value" Data Type + +The `RDF Value` data type defines the value of an RDF resource. This data type is defined by the +Resource Description Framework (RDF), but its definition is included here for convenience. + +### identifier + +The identifier for the "RDF Value" data type is: + +`http://www.w3.org/2000/01/rdf-schema#Resource` + +### properties + +name | description | data type +------|-------------|---------- +id | A local identifier for the value. | string +resource | Identifier for the value | [URI](#uri) (No restrictions on what the URI must resolve to. It could be an image, a conclusion, a book, etc.) +type | Reference to the type of the identifier. | [URI](#uri) - MUST resolve to a resource type. See the list of [known resource types](#known-resource-types). +value | The string form of the value. | string +lang | The language of the string form of the value. | `http://www.w3.org/XML/1998/namespace#lang` + + + + +## 2.9 Resource Types + +The following resource types are defined by GEDCOM X: + +URI | description +----|------------- +`http://gedcomx.org/Person`| +`http://gedcomx.org/Relationship`| + +In addition to the resource types defined by GEDCOM X, GEDCOM X recognizes the +[Dublin Core Type Vocabulary](http://dublincore.org/documents/dcmi-type-vocabulary/) as +valid resource types. + + + +# 3. Data Types for Describing Sources + +Citing sound evidence is a critical component to the exchange of genealogical data. The source of +a piece of genealogical data has to be completely and accurately described in order to be +consistently evaluated by other genealogical researchers. Many sources do not have a digital +representation (e.g. books or other physical artifacts). These sources are instead _described_ +and their _description_ is provided in digital form. + +This section defines the data types that are used for describing and referencing sources. + + + +## 3.1 The "Description" Data Type + +The `Description` data type defines a description of a resource. The `Description` is +defined by the Resource Description Framework (RDF), but its definition is included here +for convenience. + +### identifier + +The identifier for the "Description" data type is: + +`http://www.w3.org/1999/02/22-rdf-syntax-ns#Description` + +### properties + +name | description | data type +-----|-------------|---------- +id | A local, transient identifier for the resource being described. Note that as a local, transient identifier, the id may only be used to resolve references to the resource within a well-defined scope (such as a single web service request or a single file). | string +about | A uniform resource identifier (URI) for the resource being described. | [URI](#uri) +type | Reference to the type of the resource being described. | [URI](#uri) - MUST resolve to a resource type. See the list of [known resource types](#known-resource-types). + +### standard extension properties + +As defined by RDF, the RDF description may contain additional "extension" properties that +are used to provide additional details about the resource being described. + +GEDCOM X recognizes the [Dublin Core Metadata Terms](http://dublincore.org/documents/dcmi-terms/) as +standard properties for a description of a resource. + +todo: list the dublin core terms here with their types and descriptions for convenience. + + + +## 3.2 The "SourceReference" Data Type + +The `SourceReference` data type defines a reference to a source. Genealogical data cites its evidence +using an instance of `SourceReference`. + +### identifier + +The identifier for the "SourceReference" data type is: + +`http://gedcomx.org/conclusion/v1/SourceReference` + +### properties + +name | description | data type +-----|-------------|---------- +id | A local identifier for the source reference. Note that this id MUST NOT be processed as an identifier for the resource being referenced, but instead as a transient identifier for the reference itself. | string +resource | Identifier for the resource being cited. | [URI](#uri) (No restrictions on what the URI must resolve to. It could be an image, a conclusion, a book, etc.) +type | Reference to the type of the source being referenced. | [URI](#uri) - MUST resolve to a resource type. See the list of [known resource types](#known-resource-types). +description | Reference to a _description_ of the source being referenced. | [URI](#uri) - MUST resolve to an instance of [`http://www.w3.org/1999/02/22-rdf-syntax-ns#Description`](#rdf-description) +attribution | The attribution of this source reference. | [`http://gedcomx.org/Attribution`](#attribution) + + +# 4. Data Types for Describing Contributors + +Genealogical research is performed and data is gathered by a living person or organization. +This section describes the data types that are used to provide information about +contributors of genealogical data. + +GEDCOM X refers to the [Friend of a Friend](http://www.foaf-project.org/) project to define the +data types for describing contributors. The data types are duplicated here for convenience +and consistency. + + + +## 4.1 The "OnlineAccount" Data Type + +The `OnlineAccount` data type defines a description of an account in an online web application. + +### identifier + +The identifier for the `OnlineAccount` data type is: + +`http://xmlns.com/foaf/0.1/OnlineAccount` + +### properties + +name | description | data type +-----|-------------|---------- +id | A local, transient identifier for the online account. | string +serviceHomepage | The home page of the service. | [URI](#uri) +accountName | The name of the account. | [`http://www.w3.org/2000/01/rdf-schema#Literal`](#rdf-literal) +displayName | A display name for the account. | [`http://www.w3.org/2000/01/rdf-schema#Literal`](#rdf-literal) + + + +## 4.2 The "Address" Data Type + +The `Address` data type defines a street address of a person or organization. The `Address` data type is +defined by the [Contact](http://www.w3.org/2000/10/swap/pim/contact) schema. + +### identifier + +The identifier for the `Address` data type is: + +`http://www.w3.org/2000/10/swap/pim/contact#Address` + +### properties + +name | description | data type +-----|-------------|---------- +id | A local, transient identifier for the address. | string +city | The city. | string +country | The country. | string +postalCode | The postal code. | string +stateOrProvince | The state or province. | string +street | The street. | string +street2 | The street (second line). | string +street3 | The street (third line). | string + + +## 4.3 The "Agent" Data Type + +The `Agent` data type defines data that is common to a living entity, such as a person (user) +or organization. The `Agent` data type use used as an abstraction to share properties +between contributor data types such as FOAF `Person` and `Organization`. + +### identifier + +The identifier for the `Agent` data type is: + +`http://xmlns.com/foaf/0.1/Agent` + +### extension + +This data type extends the following data type: + +`http://www.w3.org/1999/02/22-rdf-syntax-ns#Description` + +### properties + +name | description | data type +-----|-------------|---------- +name | The name of the person or organization. | [`http://www.w3.org/2000/01/rdf-schema#Literal`](#rdf-literal) +homepage | The homepage of the person or organization. | [`http://www.w3.org/2000/01/rdf-schema#Literal`](#rdf-literal) +openid | The [openid](http://openid.net/) of the person or organization. | [`http://www.w3.org/2000/01/rdf-schema#Literal`](#rdf-literal) +accounts | The online accounts of the person or organization. | Ordered list of [`http://xmlns.com/foaf/0.1/OnlineAccount`](#online-account) +emails | The email addresses of the person or organization. | Ordered list of [URI](#uri) - MUST resolve to a valid e-mail address (e.g. "mailto:someone@gedcomx.org") +phones | The phones (voice, fax, mobile) of the person or organization. | Ordered list of [URI](#uri) - MUST resolve to a valid phone number (e.g. "tel:+1-201-555-0123") +addresses | The addresses of the person or organization. | Ordered list of [`http://www.w3.org/2000/10/swap/pim/contact#Address`](#address) + + + +## 4.4 The "Organization" Data Type + +The `Organization` data type defines data describing an organization. + +### identifier + +The identifier for the `Organization` data type is: + +`http://xmlns.com/foaf/0.1/Organization` + +### extension + +This data type extends the following data type: + +`http://xmlns.com/foaf/0.1/Agent` + +### properties + +The `Organization` data type defines no additional properties beyond those defined by +its extended type. + + + +## 4.5 The "FOAF Person" Data Type + +The `Person` data type defines data that is common to a living person (user). The `Person` +data type is an extension of the `Agent` data type. + +### identifier + +The identifier for the `Person` data type is: + +`http://xmlns.com/foaf/0.1/Person` + +### extension + +This data type extends the following data type: + +`http://xmlns.com/foaf/0.1/Agent` + +### properties + +name | description | data type +-----|-------------|---------- +familyName | The family name of the person. | [`http://www.w3.org/2000/01/rdf-schema#Literal`](#rdf-literal) +givenName | The given name of the person. | [`http://www.w3.org/2000/01/rdf-schema#Literal`](#rdf-literal) +language | The language of the person. | [`http://www.w3.org/2000/01/rdf-schema#Literal`](#rdf-literal) + + +# 5. Data Types for Describing Conclusions + +This section describes the data types that are used to define conclusions about genealogical +data. + + +## 5.1 The "Conclusion" Data Type + +The `Conclusion` data type defines the base conceptual model for basic genealogical conclusions. +The `Conclusion` data type is an extension of the `GenealogicalResource` data type. + +### identifier + +The identifier for the `Conclusion` data type is: + +`http://gedcomx.org/conclusion/v1/Conclusion` + +### extension + +This data type extends the following data type: + +`http://gedcomx.org/GenealogicalResource` + +### properties + +name | description | data type +-----|-------------|---------- +sources | The list of references to the sources of the conclusion. The sources of a conclusion MUST also be sources of the conclusion's containing entity (i.e. [`Person`](#person) or [`Relationship`](#relationship) ).| Ordered list of [`http://gedcomx.org/conclusion/v1/SourceReference`](#source-reference). + + + +## 5.2 The "Date" Data Type + +The `Date` data type defines the value of a genealogical date. + +### identifier + +The identifier for the `Date` data type is: + +`http://gedcomx.org/conclusion/v1/Date` + +### properties + +name | description | data type +-----|-------------|---------- +original | The original value of the date as supplied by the contributor. | string +formal | The formal value of the date. | [`http://gedcomx.org/FormalValue`](#formal-value) + +### known date formats + +The following date formats are recognized by GEDCOM X: + +URI | description +----|------------- +`http://gedcomx.org/GEDCOM_5_5` | The date format specified by the GEDCOM 5.5 specification. +`iso:8601` | The date format specified by [ISO 8601](http://en.wikipedia.org/wiki/ISO_8601). + + + +## 5.3 The "Place" Data Type + +The `Place` data type defines the value of a genealogical place. + +### identifier + +The identifier for the `Place` data type is: + +`http://gedcomx.org/conclusion/v1/Place` + +### properties + +name | description | data type +-----|-------------|---------- +original | The original value of the place as supplied by the contributor. | string +formal | The formal value of the place. | [`http://gedcomx.org/FormalValue`](#formal-value) + + + +## 5.4 The "Fact" Data Type + +The `Fact` data type defines a conclusion about a fact of the life of a person or +the nature of a relationship. The `Fact` data type extends the `Conclusion` data type. + +### identifier + +The identifier for the `Fact` data type is: + +`http://gedcomx.org/conclusion/v1/Fact` + +### extension + +This data type extends the following data type: + +`http://gedcomx.org/conclusion/v1/Conclusion` + +### properties + +name | description | data type +-----|-------------|---------- +type | URI identifying the type of the fact. | [URI](#uri) - MUST resolve to a fact type. See the list of [known fact types](#known-fact-types). +date | The date of applicability of the fact. | [`http://gedcomx.org/conclusion/v1/Date`](#conclusion-date) +place | The place of applicability of the fact. | [`http://gedcomx.org/conclusion/v1/Place`](#conclusion-place) +original | The value of the fact as supplied by the contributor. | string +formal | The formal value of the fact. | [`http://gedcomx.org/FormalValue`](#formal-value) + + + +### known fact types + +The following fact types are defined by GEDCOM X: + +URI | description | scope +----|-------------|------ +`http://gedcomx.org/Adoption`| | person +`http://gedcomx.org/AdultChristening`| | person +`http://gedcomx.org/Affiliation`| | person +`http://gedcomx.org/Age`| | person +`http://gedcomx.org/Baptism`| | person +`http://gedcomx.org/BarMitzvah`| | person +`http://gedcomx.org/BatMitzvah`| | person +`http://gedcomx.org/Birth`| | person +`http://gedcomx.org/Blessing`| | person +`http://gedcomx.org/Burial`| | person +`http://gedcomx.org/CasteName`| | person +`http://gedcomx.org/Census`| | person +`http://gedcomx.org/Christening`| | person +`http://gedcomx.org/Circumcision`| | person +`http://gedcomx.org/Citizenship`| | person +`http://gedcomx.org/ClanName`| | person +`http://gedcomx.org/Confirmation`| | person +`http://gedcomx.org/CountOfChildren`| | person +`http://gedcomx.org/CountOfMarriages`| | person +`http://gedcomx.org/Cremation`| | person +`http://gedcomx.org/Death`| | person +`http://gedcomx.org/DiedBeforeEight`| | person +`http://gedcomx.org/Dwelling`| | person +`http://gedcomx.org/Emigration`| | person +`http://gedcomx.org/Ethnicity`| | person +`http://gedcomx.org/Excommunication`| | person +`http://gedcomx.org/FirstCommunion`| | person +`http://gedcomx.org/Flourish`| | person +`http://gedcomx.org/Funeral`| | person +`http://gedcomx.org/GedcomUUID`| | person +`http://gedcomx.org/Graduation`| | person +`http://gedcomx.org/Illness`| | person +`http://gedcomx.org/Immigration`| | person +`http://gedcomx.org/Interment`| | person +`http://gedcomx.org/Living`| | person +`http://gedcomx.org/MaritalStatus`| | person +`http://gedcomx.org/MilitaryAward`| | person +`http://gedcomx.org/MilitaryCompany`| | person +`http://gedcomx.org/MilitaryDischarge`| | person +`http://gedcomx.org/MilitaryRank`| | person +`http://gedcomx.org/MilitaryRegiment`| | person +`http://gedcomx.org/MilitaryService`| | person +`http://gedcomx.org/MilitaryServiceBranch`| | person +`http://gedcomx.org/Mission`| | person +`http://gedcomx.org/Move`| | person +`http://gedcomx.org/NameOfShip`| | person +`http://gedcomx.org/Naturalization`| | person +`http://gedcomx.org/Namesake`| | person +`http://gedcomx.org/NationalId`| | person +`http://gedcomx.org/NationalOrigin`| | person +`http://gedcomx.org/NeverHadChildren`| | person +`http://gedcomx.org/NeverMarried`| | person +`http://gedcomx.org/NotAccountable`| | person +`http://gedcomx.org/Occupation`| | person +`http://gedcomx.org/Ordinance`| | person +`http://gedcomx.org/Ordination`| | person +`http://gedcomx.org/PhysicalDescription`| | person +`http://gedcomx.org/PortOfDeparture`| | person +`http://gedcomx.org/PreviousResidence`| | person +`http://gedcomx.org/Probate`| | person +`http://gedcomx.org/Possessions`| | person +`http://gedcomx.org/Race`| | person +`http://gedcomx.org/RelationshipToHead`| | person +`http://gedcomx.org/ReligiousAffiliation`| | person +`http://gedcomx.org/Residence`| | person +`http://gedcomx.org/Retirement`| | person +`http://gedcomx.org/ScholasticAchievement`| | person +`http://gedcomx.org/SocialSecurityNumber`| | person +`http://gedcomx.org/Stillborn`| | person +`http://gedcomx.org/TitleOfNobility`| | person +`http://gedcomx.org/TribeName`| | person +`http://gedcomx.org/Twin`| | person +`http://gedcomx.org/Will`| | person +`http://gedcomx.org/Annulment`| | couple relationship +`http://gedcomx.org/CommonLawMarriage`| | couple relationship +`http://gedcomx.org/CurrentlySpouses`| | couple relationship +`http://gedcomx.org/Divorce`| | couple relationship +`http://gedcomx.org/DivorceFiling`| | couple relationship +`http://gedcomx.org/Engagement`| | couple relationship +`http://gedcomx.org/Marriage`| | couple relationship +`http://gedcomx.org/MarriageBanns`| | couple relationship +`http://gedcomx.org/MarriageContract`| | couple relationship +`http://gedcomx.org/MarriageIntent`| | couple relationship +`http://gedcomx.org/MarriageLicense`| | couple relationship +`http://gedcomx.org/MarriageNotice`| | couple relationship +`http://gedcomx.org/MarriageSettlement`| | couple relationship +`http://gedcomx.org/NumberOfChildren`| | couple relationship +`http://gedcomx.org/Separation`| | couple relationship +`http://gedcomx.org/UniversalId`| | couple relationship +`http://gedcomx.org/Biological`| | parent-child relationship +`http://gedcomx.org/Adopted`| | parent-child relationship +`http://gedcomx.org/Step`| | parent-child relationship +`http://gedcomx.org/Foster`| | parent-child relationship +`http://gedcomx.org/Guardianship`| | parent-child relationship + + + +## 5.5 The "Gender" Data Type + +The `Gender` data type defines a conclusion about the gender of a person. the `Gender` data type +extends the `Conclusion` data type. + +### identifier + +The identifier for the `Gender` data type is: + +`http://gedcomx.org/conclusion/v1/Gender` + +### extension + +This data type extends the following data type: + +`http://gedcomx.org/conclusion/v1/Conclusion` + +### properties + +name | description | data type +-----|-------------|---------- +type | URI identifying the type of the gender. | [URI](#uri) - MUST resolve to a gender type. Refer to the list of [known gender types](#known-gender-types). + + + +### known gender types + +The following gender types are defined by GEDCOM X: + +URI | description +----|------------- +`http://gedcomx.org/Male`| +`http://gedcomx.org/Female`| +`http://gedcomx.org/Unknown`| + + + +## 5.6 The "NamePart" Data Type + +The `NamePart` data type defines a part of a name of a person. + +### identifier + +The identifier for the `NamePart` data type is: + +`http://gedcomx.org/conclusion/v1/NamePart` + +### properties + +name | description | data type +-----|-------------|---------- +type | URI identifying the type of the name part. | [URI](#uri) - MUST resolve to a name part type. Refer to the list of [known name part types](#known-name-part-types). +text | The text of the name part. | string + + + +### known name part types + +The following name part types are defined by GEDCOM X: + +URI | description +----|------------- +`http://gedcomx.org/Prefix`| +`http://gedcomx.org/Suffix`| +`http://gedcomx.org/Given`| +`http://gedcomx.org/Surname`| + + +## 5.7 The "NameForm" Data Type + +The `NameForm` data type defines a form of a name of a person. + +### identifier + +The identifier for the `NameForm` data type is: + +`http://gedcomx.org/conclusion/v1/NameForm` + +### properties + +name | description | data type +-----|-------------|---------- +fullText | The full text of the name form. | string +parts | The parts of the name form. | Ordered list of [`http://gedcomx.org/conclusion/v1/NamePart`](#name-part) + + + +## 5.8 The "Name" Data Type + +The `Name` data type defines a conclusion about a name of a person. The `Name` data type +extends the `Conclusion` data type. + +### identifier + +The identifier for the `Name` data type is: + +`http://gedcomx.org/conclusion/v1/Name` + +### extension + +This data type extends the following data type: + +`http://gedcomx.org/conclusion/v1/Conclusion` + +### properties + +name | description | data type +-----|-------------|---------- +type | URI identifying the type of the name. | [URI](#uri) - MUST resolve to a name type. Refer to the list of [known name types](#known-name-types). +primaryForm | The primary form of the name. | `http://gedcomx.org/conclusion/v1/NameForm` +alternateForms | The alternate forms of the name. | Ordered list of `http://gedcomx.org/conclusion/v1/NameForm` +preferred | Whether this name is preferred above the other names of a person. | boolean + + + +### known name types + +The following name types are defined by GEDCOM X: + +URI | description +----|------------- +`http://gedcomx.org/Name`| +`http://gedcomx.org/BirthName`| +`http://gedcomx.org/DeathName`| +`http://gedcomx.org/MarriedName`| +`http://gedcomx.org/AlsoKnownAs`| +`http://gedcomx.org/MaidenName`| +`http://gedcomx.org/Nickname`| +`http://gedcomx.org/Adoptive`| +`http://gedcomx.org/Formal`| +`http://gedcomx.org/Religious`| + + + +# 6. The Person + +The person is the fundamental unit of genealogical research. + +## 6.1 The "Person" Data Type + +The `Person` data type defines a description of a person. The `Person` data type +extends the `GenealogicalResource` data type. + +### identifier + +The identifier for the `Person` data type is: + +`http://gedcomx.org/conclusion/v1/Person` + +### extension + +This data type extends the following data type: + +`http://gedcomx.org/GenealogicalResource` + +### properties + +name | description | data type +-----|-------------|---------- +identifiers | Identifiers for the person. | Ordered list of [`http://gedcomx.org/Identifier`](#identifier-type) +living | Whether the person is considered living. | boolean +gender | The conclusion about the gender of the person. | [`http://gedcomx.org/conclusion/v1/Gender`](#gender) +names | The conclusions about the names of the person. | Ordered list of [`http://gedcomx.org/conclusion/v1/Name`](#name-conclusion) +facts | The conclusions about the facts of the life of the person. | Ordered list of [`http://gedcomx.org/conclusion/v1/Fact`](#fact-conclusion) +sources | The list of references to the evidence of the person. | Ordered list of [`http://gedcomx.org/conclusion/v1/SourceReference`](#source-reference) +notes | Contributed notes about the person. | Ordered list of [`http://gedcomx.org/Note`](#note) + + + +# 7. The Relationship + +A relationship describes the relationship between two persons. + +## 7.1 The "Relationship" Data Type + +The `Relationship` data type defines a description of a relationship. The `Relationship` data type +extends the `GenealogicalResource` data type. + +### identifier + +The identifier for the `Relationship` data type is: + +`http://gedcomx.org/conclusion/v1/Relationship` + +### extension + +This data type extends the following data type: + +`http://gedcomx.org/GenealogicalResource` + +### properties + +name | description | data type +-----|-------------|---------- +type | URI identifying the type of the relationship. | [URI](#uri) - MUST resolve to a relationship type. Refer to the list of [known relationship types](#known-relationship-types) +person1 | Reference to the first person in the relationship. | [URI](#uri) - MUST resolve to an instance of [`http://gedcomx.org/conclusion/v1/Person`](#person) +person2 | Reference to the second person in the relationship. | [URI](#uri) - MUST resolve to an instance of [`http://gedcomx.org/conclusion/v1/Person`](#person) +facts | The conclusions about the facts of the life of the relationship. | Ordered list of [`http://gedcomx.org/conclusion/v1/Fact`](#fact-conclusion) +sources | The list of references to the evidence of the relationship. | Ordered list of [`http://gedcomx.org/conclusion/v1/SourceReference`](#source-reference) +notes | Contributed notes about the relationship. | Ordered list of [`http://gedcomx.org/Note`](#note) + +Note: when a relationship type implies direction, the relationship is said to +to *from* person1 *to* person2. For example, in a parent-child relationship, the +`person1` property refers to the parent and the `person2` property refers to the +child. + + + +### known relationship types + +The following relationship types are defined by GEDCOM X: + +URI | description +----|------------- +`http://gedcomx.org/Couple`| +`http://gedcomx.org/ParentChild`| + + +# 8. Extensibility + +## Extensions from Non-GEDCOM X Vocabularies + +This specification provides the data types and properties that define GEDCOM X. +Other data types and vocabularies ("foreign vocabularies") can be used in +GEDCOM X data types. + +## Extensions to the GEDCOM X Vocabulary + +The GEDCOM X namespaces are reserved for future forward-compatible revisions +of GEDCOM X. Future versions of this specification could add new data types and +properties to the GEDCOM X vocabulary. Software written to conform to this +version of the specification will not be able to process such extensions correctly +and, in fact, will not be able to distinguish such extensions from error. For +the purposes of this discussion, unrecognized data types and properties from the +GEDCOM X vocabulary will be considered "foreign vocabularies". + +## Processing Foreign Vocabularies + +GEDCOM X Processors that encounter foreign vocabularies in a location that is +legal according to this specification MUST NOT stop processing or +signal an error. It might be the case that the GEDCOM X Processor is +able to process the foreign vocabularies correctly and does so. Otherwise, +such vocabularies are termed "unknown foreign vocabularies". + +When unknown foreign vocabularies are encountered, GEDCOM X Processors MAY +bypass the foreign properties, type references, and textual content and +MUST NOT change their behavior as a result of the presence of the vocabulary. + + + +## Extension Properties + +GEDCOM X allows properties of foreign vocabularies in any data type, except +where it is explicitly forbidden. + +## Extension Types + +GEDCOM X allows data types of foreign vocabularies to be referenced anywhere +data types are defined to be referenced. Examples of data type references include +name types, fact types, resource types, etc. GEDCOM X supplies its own set of +"known" data types and implementors are encouraged to use the list of known data +types as much as possible to preserve maximum compatibility. + +## User-Defined Types + +Some applications MAY allow data types to be provided. For example, a genealogy +application may provide a feature that allows a user to supply a "custom" fact +about the life of a person when the list of known fact types doesn't contain +the type of fact the user may want to add. + +In the case where a user has supplied a title or description instead of selecting +a known data type, GEDCOM X recognizes the data URI scheme as defined by +[RFC 2397](http://tools.ietf.org/html/rfc2397). + +# 9. Miscellaneous To Do + +todo: add details about which properties are required. + +todo: supply details about how GEDCOM X defines its evidence model. \ No newline at end of file diff --git a/specifications/file-format-specification.md b/specifications/file-format-specification.md new file mode 100644 index 00000000..9cdcc32c --- /dev/null +++ b/specifications/file-format-specification.md @@ -0,0 +1,165 @@ +# The GEDCOM X File Format + +## Status + +This document specifies a file format for data defined by the [GEDCOM X standard conceptual +model](https://github.com/FamilySearch/gedcomx/blob/master/specifications/conceptual-model-specification.md), +and requests discussion and suggestions for improvements. + +## Copyright Notice + +Copyright 2011-2012 Intellectual Reserve, Inc. + +## License + +This document is distributed under a Creative Commons Attribution-ShareAlike license. +For details, see: + +http://creativecommons.org/licenses/by-sa/3.0/ + +# 1. Introduction + +A GEDCOM X file is a bundle of digital genealogical resources. Resources reference other resources, +which may be located within the same file or may be located external to the file. + +Perhaps the most familiar use of a GEDCOM X file is to bundle together conclusions about a pedigree. This +research is composed of a lot of different resources such as persons, relationships, citations and images. +The GEDCOM X File Format is designed to enable the bundling of all of these resources into a single file +and to specify how each resource may reference (or link to) other resources, which are either +bundled in the same file or are located external to the file, such as in an online database. + +## 1.1 Identifier, Version, and Dependencies + +The identifier for this specification is: + +`http://gedcomx.org/file/v1` + +For convenience, the GEDCOM X file format may be referred to as "GEDCOM X File Format 1.0". +This specification uses "GEDCOM X File Format" internally. + +This specification is depends on a variety of different standards and specifications. + +* The [ZIP file format](http://en.wikipedia.org/wiki/ZIP_file_format) is used to package + resources. +* Processors are required to support genealogical resources provided in the GEDCOM X XML 1.0 + format identified by [`http://gedcomx.org/xml/v1`](https://github.com/FamilySearch/gedcomx/blob/master/specifications/xml-format-specification.md). +* The [GEDCOM X Standard Header Set](https://github.com/FamilySearch/gedcomx/blob/master/specifications/standard-header-set-specification.md) + specification provides the set of attributes that are applicable to resources in the file. +* Conventions for supplying metadata for resources were adopted from the + [JAR file format](http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html). Processors MAY support + digital signatures as specified by the JAR file format. + + +## 1.2 Notational Conventions + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", +"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this +document are to be interpreted as described in BCP 14, +[RFC2119](http://tools.ietf.org/html/rfc2119), as scoped to those conformance +targets. + +# 2. Zip File + +The GEDCOM X File Format is an extension of the [ZIP file format](http://en.wikipedia.org/wiki/ZIP_file_format). +Each resource in the GEDCOM X file is defined as an entry in the file. +A GEDCOM X File must include a manifest file that provides metadata about the GEDCOM X file and resources +contained in it. + +# 3. GEDCOM X Resource Representations + +For all resources defined by the [GEDCOM X conceptual model](https://github.com/FamilySearch/gedcomx/blob/master/specifications/conceptual-model-specification.md), +file format processors MUST support the XML representation of those resources as defined by the +[XML format specification](https://github.com/FamilySearch/gedcomx/blob/master/specifications/xml-format-specification.md). Processors +MAY also support the JSON representation of the resource as defined by the +[JSON format specification](https://github.com/FamilySearch/gedcomx/blob/master/specifications/json-format-specification.md). + +# 4. The Manifest + +The manifest is a required entry in the GEDCOM X file that provides metadata about the GEDCOM X file and each of the +resources contained within the file. The manifest is the entry within the file named `META-INF/MANIFEST.MF` as defined +by the [JAR specification](http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html). +The metadata about the file and about each entry in the file +is supplied as Name-Value pairs grouped into Sections as specified by the JAR specification. Each Name-Value pair is referred to as an +"Attribute". + +## 4.1 Main Attributes + +Attributes that apply globally to the GEDCOM X file are defined in the "Main" section of the manifest and are referred to as "Main Attributes". + +Currently, the GEDCOM X File Format does not require any of the Main attributes specified by the JAR specification. + +All of the headers defined by the [GEDCOM X Standard Header Set](https://github.com/FamilySearch/gedcomx/blob/master/specifications/standard-header-set-specification.md) +MAY be used as main attributes and are interpreted to be applicable to the file itself. Some of the most notable include: + +* `X-DC-created`, used to determine when the file was created. +* `X-DC-creator`, used to identify the creator of the file. +* `X-DC-conformsTo`, used to identify the specification(s) this file conforms to. Conformance to `http://gedcomx.org/file/v1` is assumed for ALL files. +* `X-DC-requires`, used to identify the specification(s) that processors of this file are REQUIRED to comply with. If a processor does not recognize + or otherwise know how to comply with the specifications listed, it MUST NOT process the file. All processors MUST comply with `http://gedcomx.org/file/v1`. + +## 4.2 Per-Entry Attributes + +Attributes that apply to a specific resource in the file are referred to as +["Per-Entry Attributes" defined by the JAR specification](http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html#Per-Entry_Attributes). +As defined by the [JAR specification](http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html#JAR_Manifest), each section that supplies attributes +for a specific entry starts with an attribute with the name as "Name", and the value must be a relative path +to the file. + +All of the headers defined by the [GEDCOM X Standard Header Set](https://github.com/FamilySearch/gedcomx/blob/master/specifications/standard-header-set-specification.md) +MAY be used as per-entry attributes and are interpreted to be applicable to the resource associated with the entry. Some of the most notable include: + +* `Content-Type` is used to determine the media type of the resource in the file. If the media type is NOT among those identified by the GEDCOM X XML + 1.0 specification, the `Content-Type` attribute MUST be defined. +* `ETag` is used to supply a version for the resource. +* `X-DC-modified` is used to supply a timestamp of when the resource was last modified. + +In addition to the headers defined by the [GEDCOM X Standard Header Set](https://github.com/FamilySearch/gedcomx/blob/master/specifications/standard-header-set-specification.md), +The GEDCOM-X File Format defined the following per-entry attributes: + +### 4.2.1 Name + +The `Name` attribute is **required** for all entries of a GEDCOM X file and is the attribute that begins a new section for the next entry. +The `Name` attribute specifies the name of the resource and the value should always be a relative path i.e. it should not begin with a `/`. + +### 4.2.2 GX-Root + +A GEDCOM X file often contains object graphs, such as when the file contains a serialized pedigree. The `GX-Root` attribute is an _optional_ attribute +with a `boolean` value ("true" or "false") that is used to hint that the entry is to be considered a root of an object graph in the file. + +# 5. Local Resource References + +Resources in a GEDCOM X file refer to other resources in the file using URIs. If a resource refers to an external resource, such +as an online resource, the URI must be an absolute URI. References to resources that are contained within the same GEDCOM X file +are referred to as local resource references. Local references take the form of a relative URI that is to be resolved to an entry per +[RFC 3986 Section 5](http://tools.ietf.org/html/rfc3986#section-5). + +For example, consider a relationship found in a GEDCOM X file that refers to two persons, one contained within the same GEDCOM X +file as the relationship and the other presumably found external to the file in an online database: + +
+<relationship xmlns="http://gedcomx.org/conclusion/v1"
+        xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+  ...
+  <person1 rdf:resource="/persons/12345-ABCDE"/>
+  <person2 rdf:resource="https://example.com/persons/98765-ZYXWV"/>
+  ...
+</person>
+
+ +# 6. Digital Signatures + +The GEDCOM X File Format also specifies how genealogical data within the file can be digitally signed. A +digital signature can be used to identify the provider of the data and to verify that the data was not +modified since it was signed. Signing entries is optional and if provided is defined +by the [JAR specification](http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html) + +# 7. Conventions and Best Practices + +In order to promote familiarity and ease of use, it is recommended to conform to the following conventions and best practices: + +* Use the file extension: .gedx +* Place resources of similar types in the same sub-directory. The common names are: + - persons + - relationships + - images +* Name of the entry for a resource should be the Id if exists. For example a resource for a person with Id of X324 would be stored in the entry persons/X324 \ No newline at end of file diff --git a/specifications/json-format-specification.md b/specifications/json-format-specification.md new file mode 100644 index 00000000..cd4b1f93 --- /dev/null +++ b/specifications/json-format-specification.md @@ -0,0 +1,913 @@ +# The GEDCOM X JSON Serialization Format + +## Status + +This document specifies a JSON serialization format for the [GEDCOM X standard conceptual +model](https://github.com/FamilySearch/gedcomx/blob/master/specifications/conceptual-model-specification.md), and requests discussion and suggestions for improvements. + +## Copyright Notice + +Copyright 2011-2012 Intellectual Reserve, Inc. + +## License + +This document is distributed under a Creative Commons Attribution-ShareAlike license. +For details, see: + +http://creativecommons.org/licenses/by-sa/3.0/ + +# 1. Introduction + +The GEDCOM X conceptual model is a specification of formal concepts and types +that are used to provide a standard model and vocabulary for describing genealogical +data. + +The GEDCOM X JSON Serialization Format is a specification that defines the way that +the GEDCOM X conceptual model is serialized to and deserialized from +[JSON](http://json.org). + +## 1.1 Identifier, Version, and Dependencies + +The identifier for this specification is: + +`http://gedcomx.org/json/v1` + +For convenience, the GEDCOM X JSON Format may be referred to as "GEDCOM X JSON 1.0". + +This specification is depends on the conceptual model specification identified +by [`http://gedcomx.org/conceptual-model/v1`](https://github.com/FamilySearch/gedcomx/blob/master/specifications/conceptual-model-specification.md). + +## 1.2 Examples + +The following example shows the serialization of a [person data type](https://github.com/FamilySearch/gedcomx/blob/master/specifications/conceptual-model-specification.md#person) +in JSON according to this specification: + +```json +{ + "names" : [ { + "primaryForm" : { + "fullText" : "George Washington", + "parts" : [ { + "type" : "http://gedcomx.org/Given", + "text" : "George" + }, { + "type" : "http://gedcomx.org/Surname", + "text" : "Washington" + } ] + }, + "preferred" : true, + "id" : "789", + "attribution" : { + "contributor" : "https://familysearch.org/platform/contributors/STV-WXZY" + } + } ], + "sources" : [ { + "type" : "http://purl.org/dc/dcmitype/Text", + "attribution" : { + "contributor" : "https://familysearch.org/platform/contributors/STV-WXZY" + }, + "uri" : "http://en.wikipedia.org/wiki/George_washington" + } ], + "gender" : { + "type" : "http://gedcomx.org/Male" + }, + "facts" : [ { + "type" : "http://gedcomx.org/Birth", + "date" : { + "original" : "February 22, 1732", + "formal" : { + "text" : "1732-02-22", + "datatype" : "http://www.w3.org/2001/XMLSchema#date" + } + }, + "place" : { + "original" : "Pope's Creek, Westmoreland, Virginia", + "formal" : { + "resource" : "https://familysearch.org/platform/places/12345", + "text" : "Pope's Creek, Westmoreland, Virginia" + } + }, + "id" : "123", + "attribution" : { + "contributor" : "https://familysearch.org/platform/contributors/BCD-FGHJ" + } + }, { + "type" : "http://gedcomx.org/Death", + "date" : { + "original" : "December 14, 1799", + "formal" : { + "text" : "1799-12-14T22:00:00", + "datatype" : "http://www.w3.org/2001/XMLSchema#dateTime" + } + }, + "place" : { + "original" : "Mount Vernon, Virginia", + "formal" : { + "resource" : "https://familysearch.org/platform/places/67890", + "text" : "Mount Vernon, Fairfax County, Virginia" + } + }, + "id" : "456", + "attribution" : { + "contributor" : "https://familysearch.org/platform/contributors/KLM-NPQR" + } + } ], + "id" : "BBB-BBBB" +} +``` + +The following example shows the serialization of a relationship between two persons in +JSON according to this specification: + +```json +{ + "type" : "http://gedcomx.org/Couple", + "sources" : [ { + "type" : "http://purl.org/dc/dcmitype/Text", + "id" : "5678", + "resource" : "http://en.wikipedia.org/wiki/George_washington" + } ], + "person1" : "https://familysearch.org/platform/persons/DDD-DDDD", + "person2" : "https://familysearch.org/platform/persons/FFF-FFFF", + "facts" : [ { + "type" : "http://gedcomx.org/Marriage", + "date" : { + "original" : "January 6, 1759", + "formal" : { + "text" : "1759-01-06", + "datatype" : "http://www.w3.org/2001/XMLSchema#date" + } + }, + "id" : "123", + "attribution" : { + "contributor" : "https://familysearch.org/platform/contributors/HHH-HHHH" + } + } ], + "id" : "CCC-CCCC", + "attribution" : { + "contributor" : "https://familysearch.org/platform/contributors/BCD-FGHJ", + "proofStatement" : "(proof statement here)" + } +} +``` + + +## 1.3 Notational Conventions + +For each data type specified by the GEDCOM X conceptual model, a +JSON data format is supplied which specifies how each of the +properties of the data type are to be serialized in JSON. Each instance +of a data type is serialized as a JSON object. The properties +of each data type are serialized as members of the JSON object. + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", +"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this +document are to be interpreted as described in BCP 14, +[RFC2119](http://tools.ietf.org/html/rfc2119), as scoped to those conformance +targets. + +## 1.4 Data Type Identification in JSON Using +Because JSON is not a formally typed data format, a mechanism for +identifying the data type must be specified so that GEDCOM X JSON processors +may identify how to semantically process a JSON object that +appears as either a standalone document or as an extension property. + +GEDCOM X specifies that JSON objects MAY supply the identifier +for their data type using theas a standalone document or as an extension property, the JSON object +MUST specify its data type using thethe + +# 2. Common Data Types + +This section provides JSON object definitions for each data type defined +under the "Common Data Types" section of the conceptual model specification. + +
+ +## 2.1 The URI + +URIs are supplied as JSON strings. + + + +## 2.2 The "Identifier" Data Type + +The JSON object used to (de)serialize the `http://gedcomx.org/Identifier` data type is defined as follows: + +### properties + +name | description | JSON member | JSON object type +-----|-------------|--------------|--------- +value | The value of the identifier. | value | string +type | URI identifying the type of the identifier. | type | [`URI`](#uri) + +### examples + +```json +{ + "value" : "value_of_identifier", + "type" : "http://gedcomx.org/IdentifierType" +} +``` + + + +## 2.3 The "Attribution" Data Type + +The JSON object used to (de)serialize the `http://gedcomx.org/Attribution` data type is defined as follows: + +### properties + +name | description | JSON member | JSON object type +-----|-------------|--------------|--------- +contributor | Reference to the contributor to whom the attributed data is attributed. | contributor | [`URI`](#uri) +confidence | Reference to the confidence level of the contributor of the attributed data. | confidence | [`URI`](#uri) +modified | Timestamp of when the attributed data was contributed. | modified | number (milliseconds since epoch) +proofStatement | A statement of proof provided by the contributor of the attributed data | proofStatement | string + +### examples + +```json +{ + "contributor" : "http://identifier/for/contributor", + "confidence" : "http://gedcomx.org/Certainly", + "modified" : "1338394969", + "proofStatement" : "...proof statement here..." +} +``` + + + +## 2.4 The "FormalValue" Data Type + +The JSON object used to (de)serialize the `http://gedcomx.org/FormalValue` data type is defined as follows: + +### properties + +name | description | JSON member | JSON object type +-----|-------------|--------------|--------- +value | A string supplying the value of the formal value. If the value has been standardized, a datatype will be supplied to identify how the string is to be parsed. | value | string +datatype | URI identifying the way the value is to be processed according to a specific standard. | datatype | string +resource | URI identifying the resource to which the formal value has been standardized. | resource | string + +### examples + +Standardized value with a specified datatype: + +```json +{ + "datatype" : "http://www.w3.org/2001/XMLSchema#date", + "value" : "1732-02-22" +} +``` + +Normalized value: + +```json +{ + "value" : "...text of the normalized value..." +} +``` +Standardized value: + +```json +{ + "resource" : "http://identifier/for/standardized/value" +} +``` + +Standardized and normalized value: + +```json +{ + "resource" : "http://identifier/for/standardized/value", + "value" : "...text of the normalized value..." +} +``` + +## 2.5 The "GenealogicalResource" Data Type + +The JSON object used to (de)serialize the `http://gedcomx.org/GenealogicalResource` data type is defined as follows: + +### properties + +name | description | JSON member | JSON object type +-----|-------------|--------------|--------- +id | A local, transient identifier for the genealogical resource being described. | id | string +attribution | The attribution of this resource. | attribution | [`Attribution`](#attribution) + +### examples + +```json +{ + "id" : "some_local_id", + "attribution" : { + ... + } +} +``` + + + +## 2.6 The "Note" Data Type + +The JSON object used to (de)serialize the `http://gedcomx.org/Note` data type is defined as follows: + +### properties + +name | description | JSON member | JSON object type +-----|-------------|--------------|--------- +lang | The language of the note. | lang | string +text | The text of the note. | text | string + +### examples + +```json +{ + "lang" : "en", + "text" : "...text of the note..." +} +``` + + + +## 2.7 The "RDF Literal" Data Type + +The JSON object used to (de)serialize the `http://www.w3.org/2000/01/rdf-schema#Literal` data type is defined as follows: + +### properties + +name | description | JSON member | JSON object type +-----|-------------|--------------|--------- +value | The literal value. | value | string +datatype | URI identifying the way the value is to be processed according to a specific standard. | datatype | string +lang | The language of the literal value. | lang | string + +### examples + +```json +{ + "datatype" : "...", + "lang" : "en", + "value" : "...text of the literal value..." +} +``` + + +## 2.8 The "RDF Value" Data Type + +The JSON object used to (de)serialize the `http://www.w3.org/2000/01/rdf-schema#Resource` data type is defined as follows: + +### properties + +name | description | JSON member | JSON object type +-----|-------------|--------------|--------- +id | A local identifier for the value. | id | string +resource | Identifier for the value | resource | [URI](#uri) +type | Reference to the type of the value. | type | [`URI`](#uri) +value | The string form of the value. | value | string +lang | The language of the string form of the value. | lang | string + +### examples + +A value that can be specified as a string: + +```json +{ + "id" : "...", + "resource" : "http://identifier/for/the/value", + "lang" : "en", + "value" : "...text of the value..." +} +``` + +A value that has to be resolved, perhaps because more structure is needed +than a string. + +```json +{ + "resource" : "http://identifier/for/the/value", + "type" : "http://identifier/for/the/type/of/resource" + "value" : "...text of the value..." +} +``` + +# 3. Data Types for Describing Sources + +This section defines JSON types for each of the data types specified by the +"Data Types for Describing Sources" section of the conceptual model specification. + + + +## 3.1 The "Description" Data Type + +The JSON object used to (de)serialize the `http://www.w3.org/1999/02/22-rdf-syntax-ns#Description` +data type is defined as follows: + +### properties + +name | description | JSON member | JSON object type +-----|-------------|--------------|--------- +id | A local, transient identifier for the resource being described. | id | string +about | A uniform resource identifier (URI) for the resource being described. | about | string +type | Reference to the type of the resource being described. | type | [`URI`](#uri) + +### standard extension properties + +As stated by the conceptual model specification, GEDCOM X recognizes the +[Dublin Core Metadata Terms](http://dublincore.org/documents/dcmi-terms/) as standard properties for a +description of a resource. The DCMI terms are supported as arrays of members of an instance of the +"Description" JSON object. + +### examples + +```json +{ + "id" : "local_id", + "about" : "http://identifier/for/the/resource/being/described", + "type" : "http://identifier/for/the/type/of/resource/being/described", + "titles" : [ {...}, {...} ], + "creators" : [ {...}, {...} ], + ... +} +``` + + + +## 3.2 The "SourceReference" Data Type + +The JSON object used to (de)serialize the `http://gedcomx.org/conclusion/v1/SourceReference` +data type is defined as follows: + +### properties + +name | description | JSON member | JSON object type +-----|-------------|--------------|--------- +id | A local identifier for the source reference. | id | string +resource | Identifier for the source being referenced. | uri | [`URI`](#uri) +type | Reference to the type of the resource being referenced. | type | [`URI`](#uri) +description | Reference to a _description_ of the source being referenced. | description | [`URI`](#uri) +attribution | The attribution of this source reference. | attribution | [`attribution`](#attribution) + +### examples + +```json +{ + "id" : "local_id", + "uri" : "http://identifier/for/the/source/being/referenced", + "type" : "http://identifier/for/the/type/of/resource/being/referenced", + "description" : "http://identifier/for/the/description/of/resource/being/referenced", + "attribution" : { ... } +} +``` + +# 4. Data Types for Describing Contributors + +This section defines JSON types for each of the data types specified by the +"Data Types for Describing Contributors" section of the conceptual model specification. + + + +## 4.1 The "OnlineAccount" Data Type + +The JSON object used to (de)serialize the `http://xmlns.com/foaf/0.1/OnlineAccount` data type is defined as follows: + +### properties + +name | description | JSON member | JSON object type +-----|-------------|--------------|--------- +id | A local, transient identifier for the online account. | id | string +serviceHomepage | The home page of the service. | serviceHomepage | [`URI`](#uri) +accountName | The name of the account. | accountName | [`Literal`](#rdf-literal) +displayName | A display name for the account. | displayName | [`Literal`](#rdf-literal) + +### examples + +```json +{ + "id" : "local_id", + "serviceHomepage" : "http://familysearch.org/", + "accountName" : { + "value" : "...name of the account..." + }, + "displayName" : { + "value" : "...display name of the account..." + } +} +``` + + + +## 4.2 The "Address" Data Type + +The JSON object used to (de)serialize the `http://www.w3.org/2000/10/swap/pim/contact#Address` data type is defined as follows: + +### properties + +name | description | JSON member | JSON object type +-----|-------------|--------------|--------- +id | A local, transient identifier for the address. | id | string +city | The city. | city | string +country | The country. | country | string +postalCode | The postal code. | postalCode | string +stateOrProvince | The state or province. | stateOrProvince | string +street | The street. | street | string +street2 | The street (second line). | street2 | string +street3 | The street (third line). | street3 | string + +### examples + +```json +{ + "id" : "local_id", + "city" : "...", + "country" : "...", + "postalCode" : "...", + "stateOrProvince" : "...", + "street" : "...", + "street2" : "...", + "street3" : "..." +} +``` + +## 4.3 The "Agent" Data Type + +The JSON object used to (de)serialize the `http://xmlns.com/foaf/0.1/Agent` data type is defined as follows: + +### properties + +name | description | JSON member | JSON object type +-----|-------------|--------------|--------- +name | The name of the person or organization. | name | [`Literal`](#rdf-literal) +homepage | The homepage of the person or organization. | homepage | [`Literal`](#rdf-literal) +openid | The [openid](http://openid.net/) of the person or organization. | openid | [`Literal`](#rdf-literal) +accounts | The online accounts of the person or organization. | accounts | array of [`OnlineAccount`](#online-account) +emails | The email addresses of the person or organization. | emails | array of [`URI`](#uri) +phones | The phones (voice, fax, mobile) of the person or organization. | phones | array of [`URI`](#uri) +addresses | The addresses of the person or organization. | addresses | array of [`Address`](#address) + +### examples + +```json +{ + "id" : "local_id", + "name" : { + "value" : "..." + }, + "homepage" : { + "value" : "..." + }, + "openid" : { + "value" : "..." + }, + "accounts" : [ { ... }, { ... } ], + "emails" : [ "mailto:someone@gedcomx.org" , "mailto:someone@somewhere-else.org" ], + "phones" : [ "tel:+1-201-555-0123" , "fax:+1-201-555-5555" ], + "addresses" : [ { ... }, { ... } ] +} +``` + + + + +## 4.4 The "Organization" Data Type + +The JSON object used to (de)serialize the `http://xmlns.com/foaf/0.1/Organization` data type is defined as follows: + +### properties + +The `Organization` data type defines no additional properties beyond those defined by +its extended type. + + + + +## 4.5 The "FOAF Person" Data Type + +The JSON object used to (de)serialize the `http://xmlns.com/foaf/0.1/Person` data type is defined as follows: + +### properties + +name | description | JSON member | JSON object type +-----|-------------|--------------|--------- +familyName | The family name of the person. | familyName | [`Literal`](#rdf-literal) +givenName | The given name of the person. | givenName | [`Literal`](#rdf-literal) +language | The language of the person. | language | [`Literal`](#rdf-literal) + +### examples + +```json +{ + "id" : "local_id", + "familyName" : { + "value" : "..." + }, + "givenName" : { + "value" : "..." + }, + "language" : { + "value" : "..." + } +} +``` + +# 5. Data Types for Describing Conclusions + +This section defines JSON types for each of the data types specified by the +"Data Types for Describing Conclusions" section of the conceptual model specification. + +## 5.1 The "Conclusion" Data Type + +The JSON object used to (de)serialize the `http://gedcomx.org/conclusion/v1/Conclusion` data type is defined as follows: + +### properties + +name | description | JSON member | JSON object type +-----|-------------|--------------|--------- +sources | The list of references to the sources of the conclusion. | sources | array of [`SourceReference`](#source-reference). + +### examples + +```json +{ + "id" : "local_id", + "sources" : [ { resource : "http://identifier/for/the/source" }, { resource : "http://identifier/for/the/source" } ] +} +``` + + + +## 5.2 The "Date" Data Type + +The JSON object used to (de)serialize the `http://gedcomx.org/conclusion/v1/Date` data type is defined as follows: + +### properties + +name | description | JSON member | JSON object type +-----|-------------|--------------|--------- +original | The original value of the date as supplied by the contributor. | original | string +formal | The formal value of the date. | formal | [`FormalValue`](#formal-value) + +### examples + +```json +{ + "id" : "local_id", + "original" : "...the original text...", + "formal" : { + ... + } +} +``` + + + +## 5.3 The "Place" Data Type + +The JSON object used to (de)serialize the `http://gedcomx.org/conclusion/v1/Place` data type is defined as follows: + +### properties + +name | description | JSON member | JSON object type +-----|-------------|--------------|--------- +original | The original value of the place as supplied by the contributor. | original | string +formal | The formal value of the place. | formal | [`FormalValue`](#formal-value) + +### examples + +```json +{ + "id" : "local_id", + "original" : "...the original text...", + "formal" : { + ... + } +} +``` + + + +## 5.4 The "Fact" Data Type + +The JSON object used to (de)serialize the `http://gedcomx.org/conclusion/v1/Fact` data type is defined as follows: + +### properties + +name | description | JSON member | JSON object type +-----|-------------|--------------|--------- +type | URI identifying the type of the fact. | type | [`URI`](#uri) +date | The date of applicability of the fact. | date | [`Date`](#conclusion-date) +place | The place of applicability of the fact. | place | [`Place`](#conclusion-place) +original | The value of the fact as supplied by the contributor. | original | string +formal | The formal value of the fact. | formal | [`FormalValue`](#formal-value) + +### examples + +```json +{ + "id" : "local_id", + "type" : "http://gedcomx.org/Birth", + "date" : { + ... + }, + "place" : { + ... + }, + "original" : "...the original value of the fact...", + "formal" : { + ... + } +} +``` + + + + +## 5.5 The "Gender" Data Type + +The JSON object used to (de)serialize the `http://gedcomx.org/conclusion/v1/Gender` data type is defined as follows: + +### properties + +name | description | JSON member | JSON object type +-----|-------------|--------------|--------- +type | URI identifying the type of the gender. | type | [`URI`](#uri) + +### examples + +```json +{ + "id" : "local_id", + "type" : "http://gedcomx.org/Male" +} +``` + + + +## 5.6 The "NamePart" Data Type + +The JSON object used to (de)serialize the `http://gedcomx.org/conclusion/v1/NamePart` data type is defined as follows: + +### properties + +name | description | JSON member | JSON object type +-----|-------------|--------------|--------- +type | URI identifying the type of the name part. | type | [`URI`](#uri) +text | The text of the name part. | text | string + +### examples + +```json +{ + "type" : "http://gedcomx.org/Prefix", + "text" : "...text of the name piece..." +} +``` + +## 5.7 The "NameForm" Data Type + +The JSON object used to (de)serialize the `http://gedcomx.org/conclusion/v1/NameForm` data type is defined as follows: + +### properties + +name | description | JSON member | JSON object type +-----|-------------|--------------|--------- +fullText | The full text of the name form. | fullText | string +parts | The parts of the name form. | parts | array of [`NamePart`](#name-part) + +### examples + +```json +{ + "fullText" : "...full text of the name form...", + "parts" : [ { ... }, { ... } ] +} +``` + + + +## 5.8 The "Name" Data Type + +The JSON object used to (de)serialize the `http://gedcomx.org/conclusion/v1/Name` data type is defined as follows: + +### properties + +name | description | JSON member | JSON object type +-----|-------------|--------------|--------- +type | URI identifying the type of the name. | type | [`URI`](#uri) +primaryForm | The primary form of the name. | primaryForm | `NameForm` +alternateForms | The alternate forms of the name. | alternateForms | array of `NameForm` +preferred | Whether this name is preferred above the other names of a person. | preferred | true or false + +### examples + +```json +{ + "id" : "local_id", + "type" : "http://gedcomx.org/BirthName", + "primaryForm" : { ... }, + "alternateForms" : [ { ... }, { ... } ] +} +``` + + + +# 6. The Person + +This section defines the `Person` JSON type corresponding to the `Person` data type +specified by the section titled "The Person" of the conceptual model specification. + +## 6.1 The "Person" Data Type + +The JSON object used to (de)serialize the `http://gedcomx.org/conclusion/v1/Person` data type is defined as follows: + +### properties + +name | description | JSON member | JSON object type +-----|-------------|--------------|--------- +identifiers | Identifiers for the person. | identifiers | array of [`Identifier`](#identifier-type) +living | Whether the person is considered living. | living | true or false +gender | The conclusion about the gender of the person. | gender | [`Gender`](#gender) +names | The conclusions about the names of the person. | names | array of [`Name`](#name-conclusion) +facts | The conclusions about the facts of the life of the person. | facts | array of [`Fact`](#fact-conclusion) +sources | The list of references to the evidence of the person. | sources | array of [`SourceReference`](#source-reference) +notes | Contributed notes about the person. | notes | array of [`Note`](#note) + +### examples + +```json +{ + "id" : "local_id", + "identifiers" : [ { ... }, { ... } ], + "living" : true, + "gender" : { + ... + }, + "names" : [ { ... }, { ... } ] + "facts" : [ { ... }, { ... } ] + "sources" : [ { ... }, { ... } ] + "notes" : [ { ... }, { ... } ] +} +``` + + + +# 7. The Relationship + +This section defines the `Relationship` JSON type corresponding to the `Relationship` data type +specified by the section titled "The Relationship" of the conceptual model specification. + +## 7.1 The "Relationship" Data Type + +The JSON object used to (de)serialize the `http://gedcomx.org/conclusion/v1/Relationship` data type is defined as follows: + +### properties + +name | description | JSON member | JSON object type +-----|-------------|--------------|--------- +type | URI identifying the type of the relationship. | type | [`URI`](#uri) +person1 | Reference to the first person in the relationship. | person1 | [`URI`](#uri) +person2 | Reference to the second person in the relationship. | person2 | [`URI`](#uri) +facts | The conclusions about the facts of the life of the relationship. | facts | array of [`Fact`](#fact-conclusion) +sources | The list of references to the evidence of the relationship. | sources | array of [`SourceReference`](#source-reference) +notes | Contributed notes about the relationship. | notes | array of [`Note`](#note) + +### examples + +```json +{ + "id" : "local_id", + "type" : "http://gedcomx.org/Couple", + "person1" : "http://identifier/for/person/1", + "person2" : "http://identifier/for/person/2", + "facts" : [ { ... }, { ... } ], + "sources" : [ { ... }, { ... } ], + "notes" : [ { ... }, { ... } ] +} +``` + +# 8. Known JSON Extension Members + +GEDCOM X defines the notion of extension properties, and the JSON serialization +supports the extensibility requirements detailed in the GEDCOM X conceptual model +specification. When an extension property is provided in a JSON object, the type +of the object can be determined by the value of thesection 1.3 above. + +For convenience, GEDCOM X reserves the use of the following member names as +"known" extension members: + +name | JSON object type +-----|----------------- +persons | array of [Person](#person) +relationships | array of [Relationship](#relationship) +notes | array of [Note](#note) +facts | array of [Fact](#fact-conclusion) +names | array of [Name](#name-conclusion) +genders | array of [Gender](#gender-conclusion) +sources | array of [SourceReference](#source-reference) +descriptions | array of [Description](#rdf-description) + +//todo: include all the dublin core terms as extension members. + +# 9. Miscellaneous To Do + +todo: diff --git a/specifications/standard-header-set-specification.md b/specifications/standard-header-set-specification.md new file mode 100644 index 00000000..11e8e44d --- /dev/null +++ b/specifications/standard-header-set-specification.md @@ -0,0 +1,163 @@ +# The GEDCOM X Standard Header Set + +## Status + +This document specifies a standard set of headers used to supply metadata for +genealogical resources such as those defined by the +[GEDCOM X standard conceptual model](https://github.com/FamilySearch/gedcomx/blob/master/specifications/conceptual-model-specification.md), +and requests discussion and suggestions for improvements. + +## Copyright Notice + +Copyright 2011-2012 Intellectual Reserve, Inc. + +## License + +This document is distributed under a Creative Commons Attribution-ShareAlike license. +For details, see: + +http://creativecommons.org/licenses/by-sa/3.0/ + +# 1. Introduction + +When processing a set of genealogical resources (such as those defined by the +[GEDCOM X standard conceptual model](https://github.com/FamilySearch/gedcomx/blob/master/specifications/conceptual-model-specification.md)) +it is often useful--sometimes even necessary--to process metadata for the resource before processing +it. Examples of this kind of metadata include: + +* The data format for the resource. +* Caching directives such as the last modified timestamp or version. +* Identifiers for the resource. +* Bibliographic metadata, such as a bibliographic citation. +* Display names or titles. + +The GEDCOM X Standard Header Set specifies the set of metadata terms that are +recognized for genealogical resources and the mechanism for providing that metadata. + +## 1.1 Identifier, Version, and Dependencies + +The identifier for this specification is: + +`http://gedcomx.org/headers/v1` + +For convenience, this specification may be referred to as "GEDCOM X Standard Header Set 1.0". +This specification uses "GEDCOM X Headers" internally. + +This specification is depends on the following standards and specifications: + +* [RFC 822](http://www.w3.org/Protocols/rfc822/) defines the mechanism for supplying headers. +* Headers are specified for each of the [Dublin Core Terms](http://dublincore.org/documents/dcmi-terms/). +* Some of the [HTTP Standard Headers](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html) are + imported by the GEDCOM X Standard Header Set. + +## 1.2 Notational Conventions + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", +"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this +document are to be interpreted as described in BCP 14, +[RFC2119](http://tools.ietf.org/html/rfc2119), as scoped to those conformance +targets. + +# 2. Providing Headers + +Headers are provided follow the same generic format as that given in Section 3.1 of +[RFC 822](http://www.w3.org/Protocols/rfc822/). Each header consists of a name +followed by a colon (":") and the header value. Header names are case-insensitive. The +value MAY be preceded by any amount of LWS, though a single SP is preferred. +Headers can be extended over multiple lines by preceding each extra line with at +least one SP or HT. The header values contain either text or combinations of token, +separators, and quoted-string as specified by RFC 822. + +The order in which header fields with differing field names are received is not significant. + +# 3. Header Values + +Each header MAY supply multiple values. This is done either in a single name-value pair +by separating each value by a comma OR in multiple headers of the same name. Order of +the values MUST be preserved and MAY be significant based on the definition of the header. + +## 3.1. Text Headers + +Values of headers designated as text headers are to be interpreted as text. + +## 3.2. URI Headers + +Values of headers designated as URI headers are to be interpreted as a URI that +identifies the value of the metadata. For cases in which the value of the metadata +may not have an identifier except for its text value, the text value is +encoded according to the data URI scheme defined by [RFC 2397](http://tools.ietf.org/html/rfc2397). + +## 3.3. Date Headers + +Values of headers designated as date headers are to be interpreted as dates +according to [ISO 8601](http://en.wikipedia.org/wiki/ISO_8601). + +# 4. The Standard Header Set + +The GEDCOM X Standard Header Set includes the following headers: + +name | value type | description +-----|------------|------------ +Content-Type | text (media type) | The media type of the resource, as defined by [RFC 2616, Section 14](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html). +Content-Encoding | text | The encoding of the resource, as defined by [RFC 2616, Section 14](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html). +Content-Language | text | The language of the content of the resource, as defined by [RFC 2616, Section 14](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html). +Content-Length | text | The size of the resource, as defined by [RFC 2616, Section 14](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html). +Content-Location | text | The location of the resource, as defined by [RFC 2616, Section 14](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html). +Content-MD5 | text | The MD5 sum of the resource for integrity checks, as defined by [RFC 2616, Section 14](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html). +ETag | text | Version of the resource, as defined by [RFC 2616, Section 14](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html). +User-Agent | text | Information about the user agent originating the request or file, as defined by [RFC 2616, Section 14](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html). +X-type | URI | Identifier for the data type of the resource. +X-DC-abstract | text | A summary of the resource, as defined by [http://purl.org/dc/terms/abstract](http://dublincore.org/documents/dcmi-terms/#terms-abstract). +X-DC-accessRights | URI | Identifier for information about who can access the resource or an indication of its security status, as defined by [http://purl.org/dc/terms/accessRights](http://dublincore.org/documents/dcmi-terms/#terms-accessRights). +X-DC-accrualMethod | URI | Identifier for the method by which items are added to a collection, as defined by [http://purl.org/dc/terms/accrualMethod](http://dublincore.org/documents/dcmi-terms/#terms-accrualMethod). +X-DC-accrualPeriodicity | date | The frequency with which items are added to a collection, as defined by [http://purl.org/dc/terms/accrualPeriodicity](http://dublincore.org/documents/dcmi-terms/#terms-accrualPeriodicity). +X-DC-accrualPolicy | URI | Identifier for the policy governing the addition of items to a collection, as defined by [http://purl.org/dc/terms/accrualPolicy](http://dublincore.org/documents/dcmi-terms/#terms-accrualPolicy). +X-DC-alternative | text | An alternative name for the resource, as defined by [http://purl.org/dc/terms/alternative](http://dublincore.org/documents/dcmi-terms/#terms-alternative). +X-DC-audience | URI | Identifier for a class of entity for whom the resource is intended or useful, as defined by [http://purl.org/dc/terms/audience](http://dublincore.org/documents/dcmi-terms/#terms-audience). +X-DC-available | date | Date (often a range) that the resource became or will become available, as defined by [http://purl.org/dc/terms/available](http://dublincore.org/documents/dcmi-terms/#terms-available). +X-DC-bibliographicCitation | text | A bibliographic reference for the resource, as defined by [http://purl.org/dc/terms/bibliographicCitation](http://dublincore.org/documents/dcmi-terms/#terms-bibliographicCitation). +X-DC-conformsTo | URI | Identifier for an established standard to which the described resource conforms, as defined by [http://purl.org/dc/terms/conformsTo](http://dublincore.org/documents/dcmi-terms/#terms-conformsTo). +X-DC-contributor | URI | Identifier for an entity responsible for making contributions to the resource, as defined by [http://purl.org/dc/terms/contributor](http://dublincore.org/documents/dcmi-terms/#terms-contributor). +X-DC-coverage | text | The spatial or temporal topic of the resource, the spatial applicability of the resource, or the jurisdiction under which the resource is relevant, as defined by [http://purl.org/dc/terms/coverage](http://dublincore.org/documents/dcmi-terms/#terms-coverage). +X-DC-created | date | Date of creation of the resource, as defined by [http://purl.org/dc/terms/created](http://dublincore.org/documents/dcmi-terms/#terms-created). +X-DC-creator | URI | Identifier for an entity primarily responsible for making the resource, as defined by [http://purl.org/dc/terms/creator](http://dublincore.org/documents/dcmi-terms/#terms-creator). +X-DC-date | date | A point or period of time associated with an event in the lifecycle of the resource, as defined by [http://purl.org/dc/terms/date](http://dublincore.org/documents/dcmi-terms/#terms-date). +X-DC-dateAccepted | date | Date of acceptance of the resource, as defined by [http://purl.org/dc/terms/dateAccepted](http://dublincore.org/documents/dcmi-terms/#terms-dateAccepted). +X-DC-dateCopyrighted | date | Date of copyright, as defined by [http://purl.org/dc/terms/dateCopyrighted](http://dublincore.org/documents/dcmi-terms/#terms-dateCopyrighted). +X-DC-dateSubmitted | date | Date of submission of the resource, as defined by [http://purl.org/dc/terms/dateSubmitted](http://dublincore.org/documents/dcmi-terms/#terms-dateSubmitted). +X-DC-description | text | An account of the resource, as defined by [http://purl.org/dc/terms/description](http://dublincore.org/documents/dcmi-terms/#terms-description). +X-DC-educationLevel | URI | Identifier for a class of entity, defined in terms of progression through an educational or training context, for which the described resource is intended, as defined by [http://purl.org/dc/terms/educationLevel](http://dublincore.org/documents/dcmi-terms/#terms-educationLevel). +X-DC-extent | text | The size or duration of the resource, as defined by [http://purl.org/dc/terms/extent](http://dublincore.org/documents/dcmi-terms/#terms-extent). +X-DC-format | text | The file format, physical medium, or dimensions of the resource, as defined by [http://purl.org/dc/terms/format](http://dublincore.org/documents/dcmi-terms/#terms-format). +X-DC-hasFormat | URI | Identifier for a related resource that is substantially the same as the pre-existing described resource, but in another format, as defined by [http://purl.org/dc/terms/hasFormat](http://dublincore.org/documents/dcmi-terms/#terms-hasFormat). +X-DC-hasPart | URI | Identifier for a related resource that is included either physically or logically in the described resource, as defined by [http://purl.org/dc/terms/hasPart](http://dublincore.org/documents/dcmi-terms/#terms-hasPart). +X-DC-hasVersion | URI | Identifier for a related resource that is a version, edition, or adaptation of the described resource, as defined by [http://purl.org/dc/terms/hasVersion](http://dublincore.org/documents/dcmi-terms/#terms-hasVersion). +X-DC-identifier | text | An unambiguous reference to the resource within a given context, as defined by [http://purl.org/dc/terms/identifier](http://dublincore.org/documents/dcmi-terms/#terms-identifier). +X-DC-instructionalMethod | URI | Identifier for a process, used to engender knowledge, attitudes and skills, that the described resource is designed to support, as defined by [http://purl.org/dc/terms/instructionalMethod](http://dublincore.org/documents/dcmi-terms/#terms-instructionalMethod). +X-DC-isFormatOf | URI | Identifier for a related resource that is substantially the same as the described resource, but in another format, as defined by [http://purl.org/dc/terms/isFormatOf](http://dublincore.org/documents/dcmi-terms/#terms-isFormatOf). +X-DC-isPartOf | URI | Identifier for a related resource in which the described resource is physically or logically included, as defined by [http://purl.org/dc/terms/isPartOf](http://dublincore.org/documents/dcmi-terms/#terms-isPartOf). +X-DC-isReferencedBy | URI | Identifier for a related resource that references, cites, or otherwise points to the described resource, as defined by [http://purl.org/dc/terms/isReferencedBy](http://dublincore.org/documents/dcmi-terms/#terms-isReferencedBy). +X-DC-isReplacedBy | URI | Identifier for a related resource that supplants, displaces, or supersedes the described resource, as defined by [http://purl.org/dc/terms/isReplacedBy](http://dublincore.org/documents/dcmi-terms/#terms-isReplacedBy). +X-DC-isRequiredBy | URI | Identifier for a related resource that requires the described resource to support its function, delivery, or coherence, as defined by [http://purl.org/dc/terms/isRequiredBy](http://dublincore.org/documents/dcmi-terms/#terms-isRequiredBy). +X-DC-issued | date | Date of formal issuance (e.g., publication) of the resource, as defined by [http://purl.org/dc/terms/issued](http://dublincore.org/documents/dcmi-terms/#terms-issued). +X-DC-isVersionOf | URI | Identifier for a related resource of which the described resource is a version, edition, or adaptation, as defined by [http://purl.org/dc/terms/isVersionOf](http://dublincore.org/documents/dcmi-terms/#terms-isVersionOf). +X-DC-language | text | A language of the resource interpreted per RFC 4646, as defined by [http://purl.org/dc/terms/language](http://dublincore.org/documents/dcmi-terms/#terms-language). +X-DC-license | URI | Identifier for a legal document giving official permission to do something with the resource, as defined by [http://purl.org/dc/terms/license](http://dublincore.org/documents/dcmi-terms/#terms-license). +X-DC-mediator | URI | Identifier for an entity that mediates access to the resource and for whom the resource is intended or useful, as defined by [http://purl.org/dc/terms/mediator](http://dublincore.org/documents/dcmi-terms/#terms-mediator). +X-DC-medium | URI | Identifier for the material or physical carrier of the resource, as defined by [http://purl.org/dc/terms/medium](http://dublincore.org/documents/dcmi-terms/#terms-medium). +X-DC-modified | date | Date on which the resource was changed, as defined by [http://purl.org/dc/terms/modified](http://dublincore.org/documents/dcmi-terms/#terms-modified). +X-DC-provenance | text | A statement of any changes in ownership and custody of the resource since its creation that are significant for its authenticity, integrity, and interpretation, as defined by [http://purl.org/dc/terms/provenance](http://dublincore.org/documents/dcmi-terms/#terms-provenance). +X-DC-publisher | URI | Identifier for an entity responsible for making the resource available, as defined by [http://purl.org/dc/terms/publisher](http://dublincore.org/documents/dcmi-terms/#terms-publisher). +X-DC-references | URI | Identifier for a related resource that is referenced, cited, or otherwise pointed to by the described resource, as defined by [http://purl.org/dc/terms/references](http://dublincore.org/documents/dcmi-terms/#terms-references). +X-DC-relation | URI | Identifier for a related resource, as defined by [http://purl.org/dc/terms/relation](http://dublincore.org/documents/dcmi-terms/#terms-relation). +X-DC-replaces | URI | Identifier for a related resource that is supplanted, displaced, or superseded by the described resource, as defined by [http://purl.org/dc/terms/replaces](http://dublincore.org/documents/dcmi-terms/#terms-replaces). +X-DC-requires | URI | Identifier for a related resource that is required by the described resource to support its function, delivery, or coherence, as defined by [http://purl.org/dc/terms/requires](http://dublincore.org/documents/dcmi-terms/#terms-requires). +X-DC-rights | URI | Identifier for information about rights held in and over the resource, as defined by [http://purl.org/dc/terms/rights](http://dublincore.org/documents/dcmi-terms/#terms-rights). +X-DC-rightsHolder | URI | Identifier for a person or organization owning or managing rights over the resource, as defined by [http://purl.org/dc/terms/rightsHolder](http://dublincore.org/documents/dcmi-terms/#terms-rightsHolder). +X-DC-source | URI | Identifier for a related resource from which the described resource is derived, as defined by [http://purl.org/dc/terms/source](http://dublincore.org/documents/dcmi-terms/#terms-source). +X-DC-spatial | text | Spatial characteristics of the resource, as defined by [http://purl.org/dc/terms/spatial](http://dublincore.org/documents/dcmi-terms/#terms-spatial). +X-DC-subject | text | The topic of the resource, as defined by [http://purl.org/dc/terms/subject](http://dublincore.org/documents/dcmi-terms/#terms-subject). +X-DC-tableOfContents | URI | Identifier for a list of subunits of the resource, as defined by [http://purl.org/dc/terms/tableOfContents](http://dublincore.org/documents/dcmi-terms/#terms-tableOfContents). +X-DC-temporal | text | Temporal characteristics of the resource, as defined by [http://purl.org/dc/terms/temporal](http://dublincore.org/documents/dcmi-terms/#terms-temporal). +X-DC-title | text | A name given to the resource, as defined by [http://purl.org/dc/terms/title](http://dublincore.org/documents/dcmi-terms/#terms-title). +X-DC-valid | date | Date (often a range) of validity of a resource, as defined by [http://purl.org/dc/terms/valid](http://dublincore.org/documents/dcmi-terms/#terms-valid). \ No newline at end of file diff --git a/specifications/support/conceptual-model-conclusion.bnf b/specifications/support/conceptual-model-conclusion.bnf new file mode 100644 index 00000000..3b760990 --- /dev/null +++ b/specifications/support/conceptual-model-conclusion.bnf @@ -0,0 +1,23 @@ +Person ::= ( identifier )* ( living | ) ( gender | ) ( name )* ( fact )* ( source )* ( note )* +Relationship ::= type person1 person2 ( fact )* ( source )* ( note )* +identifier ::= type resource +living ::= ( | ) +gender ::= conclusion_properties type +name ::= conclusion_properties type primaryForm ( alternateForm )* ( preferred | ) +fact ::= conclusion_properties type ( date | ) ( place | ) ( original | ) ( formal | ) +date ::= original formal +place ::= original formal +original ::= text +primaryForm ::= nameForm +alternateForm ::= nameForm +nameForm ::= ( fullText | ) ( namePart )* +namePart ::= type text +preferred ::= ( | ) +conclusion_properties ::= genealogical_resource_properties ( source )* +genealogical_resource_properties ::= ( id | ) attribution +attribution ::= ( contributor | ) ( confidence | ) ( modified | ) ( proofStatement | ) +formal ::= ( value | ) ( datatype | ) ( resource | ) +resource ::= URI +contributor ::= resource +type ::= resource +note ::= ( lang | ) text \ No newline at end of file diff --git a/specifications/support/conceptual-model-contributor.bnf b/specifications/support/conceptual-model-contributor.bnf new file mode 100644 index 00000000..4b0c5f70 --- /dev/null +++ b/specifications/support/conceptual-model-contributor.bnf @@ -0,0 +1,5 @@ +Contributor ::= agent ( familyName | ) ( givenName | ) ( language | ) +Organization ::= agent +agent ::= ( name | ) ( homepage | ) ( openid | ) ( account )* ( email )* ( phone )* ( address )* +address ::= ( id | ) ( city | ) ( country | ) ( postalCode | ) ( stateOrProvince | ) ( street | ) ( street2 | ) ( street3 | ) +account ::= ( id | ) ( serviceHomepage | ) ( accountName | ) ( displayName | ) \ No newline at end of file diff --git a/specifications/support/conceptual-model-sources.bnf b/specifications/support/conceptual-model-sources.bnf new file mode 100644 index 00000000..a87b49a5 --- /dev/null +++ b/specifications/support/conceptual-model-sources.bnf @@ -0,0 +1,6 @@ +Description ::= ( id | ) ( type | ) ( about | ) ( dublin_core_term )* +SourceReference ::= ( id | ) ( type | ) ( description | ) ( attribution | ) +description ::= URI +attribution ::= ( contributor | ) ( confidence | ) ( modified | ) ( proofStatement | ) +about ::= URI +contributor ::= URI \ No newline at end of file diff --git a/specifications/support/gedcomx.zargo b/specifications/support/gedcomx.zargo new file mode 100644 index 00000000..f9795778 Binary files /dev/null and b/specifications/support/gedcomx.zargo differ diff --git a/specifications/xml-format-specification.md b/specifications/xml-format-specification.md new file mode 100644 index 00000000..8a0d5f1b --- /dev/null +++ b/specifications/xml-format-specification.md @@ -0,0 +1,957 @@ +# The GEDCOM X XML Serialization Format + +## Status + +This document specifies an XML serialization format for the [GEDCOM X standard conceptual +model](https://github.com/FamilySearch/gedcomx/blob/master/specifications/conceptual-model-specification.md), and requests discussion and suggestions for improvements. + +## Copyright Notice + +Copyright 2011-2012 Intellectual Reserve, Inc. + +## License + +This document is distributed under a Creative Commons Attribution-ShareAlike license. +For details, see: + +http://creativecommons.org/licenses/by-sa/3.0/ + +# 1. Introduction + +The GEDCOM X conceptual model is a specification of formal concepts and types +that are used to provide a standard model and vocabulary for describing genealogical +data. + +The GEDCOM X XML Serialization Format is a specification that defines the way that +the GEDCOM X conceptual model is serialized to and deserialized from +[XML](http://www.w3.org/TR/REC-xml/). + +## 1.1 Identifier, Version, and Dependencies + +The identifier for this specification is: + +`http://gedcomx.org/xml/v1` + +For convenience, the GEDCOM X XML Format may be referred to as "GEDCOM X XML 1.0". + +This specification is depends on the conceptual model specification identified +by [`http://gedcomx.org/conceptual-model/v1`](https://github.com/FamilySearch/gedcomx/blob/master/specifications/conceptual-model-specification.md). + +## 1.2 Examples + +The following example shows the serialization of a [person data type](https://github.com/FamilySearch/gedcomx/blob/master/specifications/conceptual-model-specification.md#person) +in XML according to this specification: + +```xml + + + + + + + + + + true + + George Washington + + + George + + + + Washington + + + + + + + + + + February 22, 1732 + 1732-02-22 + + + Pope's Creek, Westmoreland, Virginia + Pope's Creek, Westmoreland, Virginia + + + + + + + + + December 14, 1799 + 1799-12-14T22:00:00 + + + Mount Vernon, Virginia + Mount Vernon, Fairfax County, Virginia + + + + + + + + + +``` + +The following example shows the serialization of a relationship between two persons in +XML according to this specification: + +```xml + + + + (proof statement here) + + + + + + + + + + + + January 6, 1759 + 1759-01-06 + + + + + + +``` + + +## 1.3 Notational Conventions + +This document uses the following namespace prefixes: + +prefix | namespace +-------|---------- +gx | `http://gedcomx.org/` +gxc | `http://gedcomx.org/conclusion/v1/` +rdf | `http://www.w3.org/1999/02/22-rdf-syntax-ns#` +dc | `http://purl.org/dc/terms/` +foaf | `http://xmlns.com/foaf/0.1/` +contact | `http://www.w3.org/2000/10/swap/pim/contact#` +xsd | `http://www.w3.org/2001/XMLSchema` + +For each data type specified by the GEDCOM X conceptual model, an +associated [XML schema](http://www.w3.org/TR/xmlschema-0/) type is +supplied which specifies how each of the properties of the data +type are to be serialized in XML. + +The properties of each data type are serialized as either an XML +attribute or as an XML child element of the containing XML element. +For each data type specified in the GEDCOM X conceptual model, an +associated XML type is supplied by this document that details how +each property is to be serialized. + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", +"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this +document are to be interpreted as described in BCP 14, +[RFC2119](http://tools.ietf.org/html/rfc2119), as scoped to those conformance +targets. + + +# 2. Common Data Types + +This section provides XML types for each data type defined under the "Common Data Types" +section of the conceptual model specification. + + + +## 2.1 The URI + +The [`xsd:anyURI`](http://www.w3.org/TR/2004/REC-xmlschema-2-20041028/datatypes.html#anyURI) +XML type defined by the XML schema specification will be used to (de)serialize the URI. + + + +## 2.2 The "ResourceReference" Data Type + +The GEDCOM X XML format uses the `rdf:resource` XML attribute to refer to other resources, +in conformance to the RDF specification. + +### properties + +name | description | XML property | XML type +-----|-------------|--------------|--------- +resource | The URI to the resource being referenced. | rdf:value (attribute) | [anyURI](#uri) + +### examples + +```xml +<... rdf:resource="http://uri/to/resource/being/referenced"/> +``` + + + +## 2.3 The "Identifier" Data Type + +The `gx:Identifier` XML type is used to (de)serialize the `http://gedcomx.org/Identifier` +data type. + +### properties + +name | description | XML property | XML type +-----|-------------|--------------|--------- +value | The value of the identifier. | rdf:value | xsd:string +type | URI identifying the type of the identifier. | rdf:type | [`rdf:ResourceReference`](#resource-reference) + +### examples + +```xml + <...> + value_of_identifier + + +``` + + + +## 2.4 The "Attribution" Data Type + +The `gx:Attribution` XML type is used to (de)serialize the `http://gedcomx.org/Attribution` +data type. + +### properties + +name | description | XML property | XML type +-----|-------------|--------------|--------- +contributor | Reference to the contributor to whom the attributed data is attributed. | gx:contributor | [`rdf#ResourceReference`](#resource-reference) +confidence | Reference to the confidence level of the contributor of the attributed data. | gx:confidence | [`rdf#ResourceReference`](#resource-reference) +modified | Timestamp of when the attributed data was contributed. | gx:modified | xsd:dateTime +proofStatement | A statement of proof provided by the contributor of the attributed data | gx:proofStatement | xsd:string + +### examples + +```xml + <...> + + + 2012-05-29T00:00:00 + ...proof statement here... + +``` + + + +## 2.5 The "FormalValue" Data Type + +The `gx:FormalValue` XML type is used to (de)serialize the `http://gedcomx.org/FormalValue` +data type. + +### properties + +name | description | XML property | XML type +-----|-------------|--------------|--------- +value | A string supplying the value of the formal value. If the value has been standardized, a datatype will be supplied to identify how the string is to be parsed. | (child text) | xsd:string +datatype | URI identifying the way the value is to be processed according to a specific standard. | rdf:datatype (attribute) | [anyURI](#uri) +resource | URI identifying the resource to which the formal value has been standardized. | rdf:resource (attribute) | [anyURI](#uri) + +### examples + +Standardized value with a specified datatype: + +```xml + <... rdf:datatype="http://www.w3.org/2001/XMLSchema#date">1732-02-22 +``` + +Normalized value: + +```xml + <...>...text of the normalized value... +``` +Standardized value: + +```xml + <... rdf:resource="http://identifier/for/standardized/value"/> +``` + +Standardized and normalized value: + +```xml + <... rdf:resource="http://identifier/for/standardized/value">...text of the normalized value... +``` + +## 2.6 The "GenealogicalResource" Data Type + +The `gx:GenealogicalResource` XML type is used to (de)serialize the `http://gedcomx.org/GenealogicalResource` +data type. + +### properties + +name | description | XML property | XML type +-----|-------------|--------------|--------- +id | A local, transient identifier for the genealogical resource being described. | rdf:ID (attribute) | xsd:string +attribution | The attribution of this resource. | gx:attribution | [`gx:Attribution`](#attribution) + +### examples + +```xml + <... rdf:ID="some_local_id"> + + ... + + +``` + + + +## 2.7 The "Note" Data Type + +The `gx:Note` XML type is used to (de)serialize the `http://gedcomx.org/Note` data type. + +### properties + +name | description | XML property | XML type +-----|-------------|--------------|--------- +lang | The language of the note. | xml:lang (attribute) | xml:lang +text | The text of the note. | gx:text | xsd:string + +### examples + +```xml + <... xml:lang="en"> + ...text of the note... + +``` + + + +## 2.8 The "RDF Literal" Data Type + +The `rdfs:Literal` XML type is used to (de)serialize the `http://www.w3.org/2000/01/rdf-schema#Literal` +data type. + +### properties + +name | description | XML property | XML type +-----|-------------|--------------|--------- +value | The literal value. | (child text) | xsd:string +datatype | URI identifying the way the value is to be processed according to a specific standard. | rdf:datatype (attribute) | [anyURI](#uri) +lang | The language of the literal value. | xml:lang (attribute) | xml:lang + +### examples + +```xml + <... xml:lang="en" rdf:datatype="...">...text of the literal value... +``` + + +## 2.9 The "RDF Value" Data Type + +The `rdf:Resource` XML type is used to (de)serialize the `http://www.w3.org/2000/01/rdf-schema#Resource` +data type. + +### properties + +name | description | XML property | XML type +-----|-------------|--------------|--------- +id | A local identifier for the value. | rdf:ID (attribute) | xsd:string +type | Reference to the type of the value. | rdf:type | [`rdf:ResourceReference`](#resource-reference) +value | The string form of the value. | rdf:value | xsd:string +lang | The language of the string form of the value. | xml:lang (attribute) | xml:lang + +### examples + +A value that can be specified as a string: + +```xml + <... xml:lang="en" rdf:ID="..."> + ...text of the value... + +``` + +A value that has to be resolved, perhaps because more structure is needed +than a string. + +```xml + <... rdf:resource="http://identifier/for/the/value"> + + +``` + +# 3. Data Types for Describing Sources + +This section defines XML types for each of the data types specified by the +"Data Types for Describing Sources" section of the conceptual model specification. + + + +## 3.1 The "Description" Data Type + +The `rdf:Description` XML type is used to (de)serialize the +`http://www.w3.org/1999/02/22-rdf-syntax-ns#Description` data type. + +### properties + +name | description | XML property | XML type +-----|-------------|--------------|--------- +id | A local, transient identifier for the resource being described. | rdf:ID (attribute) | xsd:string +about | A uniform resource identifier (URI) for the resource being described. | rdf:about (attribute) | [anyURI](#uri) +type | Reference to the type of the resource being described. | rdf:type | [`rdf:ResourceReference`](#resource-reference) + +### standard extension properties + +As stated by the conceptual model specification, GEDCOM X recognizes the +[Dublin Core Metadata Terms](http://dublincore.org/documents/dcmi-terms/) as standard properties for a +description of a resource. The DCMI terms are supported as elements of an instance of the +rdf:Description XML Type. + +### examples + +```xml + <... rdf:ID="local_id" rdf:about="http://identifier/for/the/resource/being/described"> + + ... + ... + ... + +``` + + + +## 3.2 The "SourceReference" Data Type + +The `gxc:SourceReference` XML type is used to (de)serialized the `http://gedcomx.org/conclusion/v1/SourceReference` +data type. + +### properties + +name | description | XML property | XML type +-----|-------------|--------------|--------- +id | A local identifier for the source reference. | rdf:ID (attribute) | xsd:string +type | Reference to the type of the resource being referenced. | rdf:type | [`rdf:ResourceReference`](#resource-reference) +description | Reference to a _description_ of the source being referenced. | gx:description | [`rdf:ResourceReference`](#resource-reference) +attribution | The attribution of this source reference. | gx:attribution | [`gx:attribution`](#attribution) + +### examples + +```xml + <... rdf:ID="local_id"> + + + ... + ... + +``` + +# 4. Data Types for Describing Contributors + +This section defines XML types for each of the data types specified by the +"Data Types for Describing Contributors" section of the conceptual model specification. + + + +## 4.1 The "OnlineAccount" Data Type + +The `foaf:OnlineAccount` XML type is used to (de)serialize the `http://xmlns.com/foaf/0.1/OnlineAccount` +data type. + +### properties + +name | description | XML property | XML type +-----|-------------|--------------|--------- +id | A local, transient identifier for the online account. | rdf:ID (attribute) | xsd:string +serviceHomepage | The home page of the service. | foaf:serviceHomepage | [`rdf:ResourceReference`](#resource-reference) +accountName | The name of the account. | foaf:accountName | [`rdfs:Literal`](#rdf-literal) +displayName | A display name for the account. | foaf:displayName | [`rdfs:Literal`](#rdf-literal) + +### examples + +```xml + <... rdf:ID="local_id"> + + ...name of the account... + ...display name of the account... + +``` + + + +## 4.2 The "Address" Data Type + +The `contact:Address` XML type is used to (de)serialize the `http://www.w3.org/2000/10/swap/pim/contact#Address` +data type. + +### properties + +name | description | XML property | XML type +-----|-------------|--------------|--------- +id | A local, transient identifier for the address. | rdf:ID (attribute) | xsd:string +city | The city. | contact:city | xsd:string +country | The country. | contact:country | xsd:string +postalCode | The postal code. | contact:postalCode | xsd:string +stateOrProvince | The state or province. | contact:stateOrProvince | xsd:string +street | The street. | contact:street | xsd:string +street2 | The street (second line). | contact:street2 | xsd:string +street3 | The street (third line). | contact:street3 | xsd:string + +### examples + +```xml + <... rdf:ID="local_id"> + ... + ... + ... + ... + ... + ... + ... + +``` + +## 4.3 The "Agent" Data Type + +The `foaf:Agent` XML type is used to (de)serialize the `http://xmlns.com/foaf/0.1/Agent` +data type. + +### properties + +name | description | XML property | XML type +-----|-------------|--------------|--------- +name | The name of the person or organization. | foaf:name | [`rdfs:Literal`](#rdf-literal) +homepage | The homepage of the person or organization. | foaf:homepage | [`rdfs:Literal`](#rdf-literal) +openid | The [openid](http://openid.net/) of the person or organization. | foaf:openid | [`rdfs:Literal`](#rdf-literal) +accounts | The online accounts of the person or organization. | foaf:account | [`foaf:OnlineAccount`](#online-account) +emails | The email addresses of the person or organization. | foaf:mbox | [`rdf:ResourceReference`](#resource-reference) +phones | The phones (voice, fax, mobile) of the person or organization. | foaf:phone | [`rdf:ResourceReference`](#resource-reference) +addresses | The addresses of the person or organization. | contact:address | [`contact:Address`](#address) + +### examples + +```xml + <... rdf:ID="local_id"> + ... + ... + ... + + ... + + + ... + + + + + + + ... + + +``` + + + + +## 4.4 The "Organization" Data Type + +The `foaf:Organization` XML type is used to (de)serialize the `http://xmlns.com/foaf/0.1/Organization` +data type. + +### properties + +The `Organization` data type defines no additional properties beyond those defined by +its extended type. + + + + +## 4.5 The "FOAF Person" Data Type + +The `foaf:Person` XML type is used to (de)serialize the `http://xmlns.com/foaf/0.1/Person` +data type. + +### properties + +name | description | XML property | XML type +-----|-------------|--------------|--------- +familyName | The family name of the person. | foaf:familyName | [`rdfs:Literal`](#rdf-literal) +givenName | The given name of the person. | foaf:givenName | [`rdfs:Literal`](#rdf-literal) +language | The language of the person. | foaf:language | [`rdfs:Literal`](#rdf-literal) + +### examples + +```xml + <... rdf:ID="local_id"> + ... + ... + ... + +``` + +# 5. Data Types for Describing Conclusions + +This section defines XML types for each of the data types specified by the +"Data Types for Describing Conclusions" section of the conceptual model specification. + +## 5.1 The "Conclusion" Data Type + +The `gxc:Conclusion` XML type is used to (de)serialize the `http://gedcomx.org/conclusion/v1/Conclusion` +data type. + +### properties + +name | description | XML property | XML type +-----|-------------|--------------|--------- +sources | The list of references to the sources of the conclusion. | gxc:source | [`gxc:SourceReference`](#source-reference). + +### examples + +```xml + <... rdf:ID="local_id"> + + + ... + +``` + + + +## 5.2 The "Date" Data Type + +The `gxc:Date` XML type is used to (de)serialize the `http://gedcomx.org/conclusion/v1/Date` +data type. + +### properties + +name | description | XML property | XML type +-----|-------------|--------------|--------- +original | The original value of the date as supplied by the contributor. | gxc:original | xsd:string +formal | The formal value of the date. | gxc:formal | [`gx:FormalValue`](#formal-value) + +### examples + +```xml + <...> + ...the original text... + + ... + + +``` + + + +## 5.3 The "Place" Data Type + +The `gxc:Place` XML type is used to (de)serialize the `http://gedcomx.org/conclusion/v1/Place` +data type. + +### properties + +name | description | XML property | XML type +-----|-------------|--------------|--------- +original | The original value of the place as supplied by the contributor. | gxc:original | xsd:string +formal | The formal value of the place. | gxc:formal | [`gx:FormalValue`](#formal-value) + +### examples + +```xml + <...> + ...the original text... + + ... + + +``` + + + +## 5.4 The "Fact" Data Type + +The `gxc:Fact` XML type is used to (de)serialize the `http://gedcomx.org/conclusion/v1/Fact` +data type. + +### properties + +name | description | XML property | XML type +-----|-------------|--------------|--------- +type | URI identifying the type of the fact. | gxc:type | [`rdf:ResourceReference`](#resource-reference) +date | The date of applicability of the fact. | gxc:date | [`gxc:Date`](#conclusion-date) +place | The place of applicability of the fact. | gxc:place | [`gxc:Place`](#conclusion-place) +original | The value of the fact as supplied by the contributor. | gxc:original | xsd:string +formal | The formal value of the fact. | gxc:formal | [`gxc:FormalValue`](#formal-value) + +### examples + +```xml + <... rdf:ID="local_id"> + + + ... + + + ... + + ...original value of the fact... + + ... + + +``` + + + + +## 5.5 The "Gender" Data Type + +The `gxc:Gender` XML type is used to (de)serialize the `http://gedcomx.org/conclusion/v1/Gender` +data type. + +### properties + +name | description | XML property | XML type +-----|-------------|--------------|--------- +type | URI identifying the type of the gender. | gxc:type | [`rdf:ResourceReference`](#resource-reference) + +### examples + +```xml + <... rdf:ID="local_id"> + + +``` + + + +## 5.6 The "NamePart" Data Type + +The `gxc:NamePart` XML type is used to (de)serialize the `http://gedcomx.org/conclusion/v1/NamePart` +data type. + +### properties + +name | description | XML property | XML type +-----|-------------|--------------|--------- +type | URI identifying the type of the name part. | gxc:type | [`rdf:ResourceReference`](#resource-reference) +text | The text of the name part. | gxc:text | xsd:string + +### examples + +```xml + <...> + + ...text of the name piece... + +``` + +## 5.7 The "NameForm" Data Type + +The `NameForm` XML type is used to (de)serialize the `http://gedcomx.org/conclusion/v1/NameForm` +data type. + +### properties + +name | description | XML property | XML type +-----|-------------|--------------|--------- +fullText | The full text of the name form. | gxc:fullText | xsd:string +parts | The parts of the name form. | gxc:part | [`gxc:NamePart`](#name-part) + +### examples + +```xml + <...> + ...full text of the name form... + + ... + + + ... + + + ... + + +``` + + + +## 5.8 The "Name" Data Type + +The `gxc:Name` XML type is used to (de)serialize the `http://gedcomx.org/conclusion/v1/Name` +data type. + +### properties + +name | description | XML property | XML type +-----|-------------|--------------|--------- +type | URI identifying the type of the name. | gxc:type | [`rdf:ResourceReference`](#resource-reference) +primaryForm | The primary form of the name. | gxc:primaryForm | `gxc:NameForm` +alternateForms | The alternate forms of the name. | gxc:alternateForm | `gxc:NameForm` +preferred | Whether this name is preferred above the other names of a person. | gxc:preferred | xsd:boolean + +### examples + +```xml + <... rdf:ID="local_id"> + + true + + ... + + + ... + + + ... + + +``` + + + +# 6. The Person + +This section defines the `Person` XML type corresponding to the `Person` data type +specified by the section titled "The Person" of the conceptual model specification. + +## 6.1 The "Person" Data Type + +The `gxc:Person` XML type is used to (de)serialize the `http://gedcomx.org/conclusion/v1/Person` +data type. + +### properties + +name | description | XML property | XML type +-----|-------------|--------------|--------- +identifiers | Identifiers for the person. | gxc:identifier | [`gx:Identifier`](#identifier-type) +living | Whether the person is considered living. | gxc:living | xsd:boolean +gender | The conclusion about the gender of the person. | gxc:gender | [`gxc:Gender`](#gender) +names | The conclusions about the names of the person. | gxc:name | [`gxc:Name`](#name-conclusion) +facts | The conclusions about the facts of the life of the person. | gxc:fact | [`gxc:Fact`](#fact-conclusion) +sources | The list of references to the evidence of the person. | gxc:source | [`gxc:SourceReference`](#source-reference) +notes | Contributed notes about the person. | gxc:note | [`gxc:Note`](#note) + +### examples + +```xml + <... rdf:ID="local_id"> + + ... + + true + + ... + + + ... + + + ... + + + ... + + + ... + + + ... + + + ... + + + ... + + + ... + + +``` + + + +# 7. The Relationship + +This section defines the `Relationship` XML type corresponding to the `Relationship` data type +specified by the section titled "The Relationship" of the conceptual model specification. + +## 7.1 The "Relationship" Data Type + +The `Relationship` XML type is used to (de)serialize the `http://gedcomx.org/conclusion/v1/Relationship` +data type. + +### properties + +name | description | XML property | XML type +-----|-------------|--------------|--------- +type | URI identifying the type of the relationship. | gxc:type | [`rdf:ResourceReference`](#resource-reference) +person1 | Reference to the first person in the relationship. | gxc:person1 | [`rdf:ResourceReference`](#resource-reference) +person2 | Reference to the second person in the relationship. | gxc:person2 | [`rdf:ResourceReference`](#resource-reference) +facts | The conclusions about the facts of the life of the relationship. | gxc:fact | [`gxc:Fact`](#fact-conclusion) +sources | The list of references to the evidence of the relationship. | gxc:source | [`gxc:SourceReference`](#source-reference) +notes | Contributed notes about the relationship. | gxc:note | [`gxc:Note`](#note) + +### examples + +```xml + <... rdf:ID="local_id"> + + + + + ... + + + ... + + + ... + + + ... + + + ... + + + ... + + + ... + + + ... + + +``` + +# 8. XML Elements + +XML types are not enough to provide an XML serialization format for a data model. XML requires elements to be defined +that can be used as the "root" of an XML document. XML elements are also used to identify any extension properties that +have been added to a data structure. + +The XML serialization of the GEDCOM X conceptual model identifies the following XML elements. When +these elements are encountered during processing (either as root elements of a document or as +extension properties), the XML types are identified as follows: + +name | XML type +-----|----------------- +gxc:person | [gxc:Person](#person) +gxc:relationship | [gxc:Relationship](#relationship) +gxc:fact | [gxc:Fact](#fact-conclusion) +gxc:name | [gxc:Name](#name-conclusion) +gxc:gender | [gxc:Gender](#gender-conclusion) +gxc:sourceReference | [gxc:SourceReference](#source-reference) +rdf:Description | [rdf:Description](#rdf-description) +foaf:Person | [foaf:Person](#foaf-person) +foaf:Organization | [foaf:Organization](#organization) + +# 9. Miscellaneous To Do + +todo: provide the normative XML schema (inline)?