Class StatementValueObject

java.lang.Object
ubic.gemma.model.common.IdentifiableValueObject<Statement>
ubic.gemma.model.expression.experiment.StatementValueObject
All Implemented Interfaces:
Serializable, Comparable<StatementValueObject>, Identifiable

public class StatementValueObject extends IdentifiableValueObject<Statement> implements Comparable<StatementValueObject>
Represents a VO for a Statement, typically part of a FactorValueBasicValueObject.

The REST representation was settled by #814, closed in dff752727c: the predicate* / object* slots are public, and a compound statement's second clause reaches clients flattened by AbstractFactorValueValueObjectSerializer rather than through the second* fields — see those fields for why they stay off the wire. This javadoc previously said the question was still open; it has not been since November 2023.

Author:
poirigui
See Also:
  • Constructor Details

    • StatementValueObject

      public StatementValueObject()
    • StatementValueObject

      public StatementValueObject(Statement s)
  • Method Details

    • compareTo

      public int compareTo(@NonNull StatementValueObject other)
      Specified by:
      compareTo in interface Comparable<StatementValueObject>
    • getCategory

      public String getCategory()
    • getCategoryUri

      @Nullable public String getCategoryUri()
    • getSubject

      public String getSubject()
    • getSubjectUri

      @Nullable public String getSubjectUri()
    • getPredicate

      @Nullable public String getPredicate()
      The predicate and object halves are absent rather than null when nothing was said.

      This is the rule AbstractFactorValueValueObjectSerializer#writeStatement already applies when it emits the same VO by hand on the factor-value path — "null reads as 'this was cleared', and a subject-only statement has nothing to clear" — and these four annotations make the bean path agree with it. Before, the two serializations of one type disagreed about the commonest statement there is.

      The subject and category halves keep their nulls, on the same serializer's reasoning: they describe a term that IS there, and subjectUri: null says it is ungrounded.

      Measured on GET /datasets/3937/samples: predicate, predicateUri, object, objectUri, objectId, subjectId and id were null on all 5,291 statements in the response, costing 587,301 of 5,265,852 bytes — 11.2% — to say nothing seven times over.

    • getPredicateUri

      @Nullable public String getPredicateUri()
    • getObject

      @Nullable public String getObject()
    • getObjectUri

      @Nullable public String getObjectUri()
    • getSecondPredicate

      public String getSecondPredicate()
      The second clause of a compound statement (e.g. the "for 12 weeks" of "HFD for 12 weeks").

      These four are withheld because AbstractFactorValueValueObjectSerializer already puts them on the wire, flattened: a statement with a second object is emitted as two entries in the statements array sharing one subject, the second carrying this clause under the generic predicate / object keys. Serializing the raw fields as well would publish the same clause twice under two names. That flattening arrived with the fields' exposure in dff752727c ("Serialize statements", fix #814), which is why the first four slots are public here and these are not.

      AnnotationValueObject exposes its own second* fields directly, and that is not an inconsistency: it is serialized as a plain bean with no flattener, so direct fields are the only way to carry the compound shape there.

    • getSecondPredicateUri

      @Nullable public String getSecondPredicateUri()
    • getSecondObject

      public String getSecondObject()
    • getSecondObjectUri

      @Nullable public String getSecondObjectUri()
    • getSubjectId

      @Nullable public String getSubjectId()
      A unique ontology identifier (i.e. IRI) for this subject.

      Assigned by AbstractFactorValueValueObjectSerializer, which is the only thing that populates it; nothing sets it on the bean path, so it is null on every statement GET /datasets/{id}/samples returns. Absent rather than null for that reason.

    • getObjectId

      @Nullable public String getObjectId()
      A unique ontology identifier (i.e. IRI) for this object. Assigned and omitted on the same terms as subjectId.
    • getSupportingEvidence

      @Nullable public com.fasterxml.jackson.databind.JsonNode getSupportingEvidence()
      Verbatim provenance backing this statement — a JSON array of {quote, source, location, …} items the curation agents emitted. Gemma stores and serves it opaquely; the agents repo owns the schema.

      A Statement is a Characteristic, so the storage (the SUPPORTING_EVIDENCE column) has always existed — it was simply never surfaced here, which left the design read path unable to answer "where did this factor value's term come from" even for rows that recorded it. Null means "nothing recorded", the expected reading for most rows.

      Provenance rather than identity, so it is excluded from equals/hashCode and from COMPARATOR: the same statement with and without recorded evidence is the same statement, and the comparator's ordering is relied upon to assign annotation ids.

    • getEvidenceCode

      @Nullable public String getEvidenceCode()
      How this statement was arrived at, as a GOEvidenceCode name (IC, IEA, IIA, TAS, …). The uppercase enum name is the wire form this field carries everywhere it appears — AnnotationValueObject#evidenceCode and PublicationAssociationValueObject#evidenceCode spell it the same way.

      Storage is the EVIDENCE_CODE column Statement inherits from Characteristic; like supportingEvidence it was never surfaced here, so a design write could not say who decided and a design read could not tell a curator's call from a program's.

      Provenance rather than identity, so it is excluded from equals/hashCode and from COMPARATOR for the same reason supportingEvidence is: the comparator's ordering assigns annotation ids.

    • setCategory

      public void setCategory(String category)
    • setCategoryUri

      public void setCategoryUri(@Nullable String categoryUri)
    • setSubject

      public void setSubject(String subject)
    • setSubjectUri

      public void setSubjectUri(@Nullable String subjectUri)
    • setPredicate

      public void setPredicate(@Nullable String predicate)
      The predicate and object halves are absent rather than null when nothing was said.

      This is the rule AbstractFactorValueValueObjectSerializer#writeStatement already applies when it emits the same VO by hand on the factor-value path — "null reads as 'this was cleared', and a subject-only statement has nothing to clear" — and these four annotations make the bean path agree with it. Before, the two serializations of one type disagreed about the commonest statement there is.

      The subject and category halves keep their nulls, on the same serializer's reasoning: they describe a term that IS there, and subjectUri: null says it is ungrounded.

      Measured on GET /datasets/3937/samples: predicate, predicateUri, object, objectUri, objectId, subjectId and id were null on all 5,291 statements in the response, costing 587,301 of 5,265,852 bytes — 11.2% — to say nothing seven times over.

    • setPredicateUri

      public void setPredicateUri(@Nullable String predicateUri)
    • setObject

      public void setObject(@Nullable String object)
    • setObjectUri

      public void setObjectUri(@Nullable String objectUri)
    • setSecondPredicate

      public void setSecondPredicate(String secondPredicate)
      The second clause of a compound statement (e.g. the "for 12 weeks" of "HFD for 12 weeks").

      These four are withheld because AbstractFactorValueValueObjectSerializer already puts them on the wire, flattened: a statement with a second object is emitted as two entries in the statements array sharing one subject, the second carrying this clause under the generic predicate / object keys. Serializing the raw fields as well would publish the same clause twice under two names. That flattening arrived with the fields' exposure in dff752727c ("Serialize statements", fix #814), which is why the first four slots are public here and these are not.

      AnnotationValueObject exposes its own second* fields directly, and that is not an inconsistency: it is serialized as a plain bean with no flattener, so direct fields are the only way to carry the compound shape there.

    • setSecondPredicateUri

      public void setSecondPredicateUri(@Nullable String secondPredicateUri)
    • setSecondObject

      public void setSecondObject(String secondObject)
    • setSecondObjectUri

      public void setSecondObjectUri(@Nullable String secondObjectUri)
    • setSubjectId

      public void setSubjectId(@Nullable String subjectId)
      A unique ontology identifier (i.e. IRI) for this subject.

      Assigned by AbstractFactorValueValueObjectSerializer, which is the only thing that populates it; nothing sets it on the bean path, so it is null on every statement GET /datasets/{id}/samples returns. Absent rather than null for that reason.

    • setObjectId

      public void setObjectId(@Nullable String objectId)
      A unique ontology identifier (i.e. IRI) for this object. Assigned and omitted on the same terms as subjectId.
    • setSupportingEvidence

      public void setSupportingEvidence(@Nullable com.fasterxml.jackson.databind.JsonNode supportingEvidence)
      Verbatim provenance backing this statement — a JSON array of {quote, source, location, …} items the curation agents emitted. Gemma stores and serves it opaquely; the agents repo owns the schema.

      A Statement is a Characteristic, so the storage (the SUPPORTING_EVIDENCE column) has always existed — it was simply never surfaced here, which left the design read path unable to answer "where did this factor value's term come from" even for rows that recorded it. Null means "nothing recorded", the expected reading for most rows.

      Provenance rather than identity, so it is excluded from equals/hashCode and from COMPARATOR: the same statement with and without recorded evidence is the same statement, and the comparator's ordering is relied upon to assign annotation ids.

    • setEvidenceCode

      public void setEvidenceCode(@Nullable String evidenceCode)
      How this statement was arrived at, as a GOEvidenceCode name (IC, IEA, IIA, TAS, …). The uppercase enum name is the wire form this field carries everywhere it appears — AnnotationValueObject#evidenceCode and PublicationAssociationValueObject#evidenceCode spell it the same way.

      Storage is the EVIDENCE_CODE column Statement inherits from Characteristic; like supportingEvidence it was never surfaced here, so a design write could not say who decided and a design read could not tell a curator's call from a program's.

      Provenance rather than identity, so it is excluded from equals/hashCode and from COMPARATOR for the same reason supportingEvidence is: the comparator's ordering assigns annotation ids.

    • toString

      public String toString()
      Overrides:
      toString in class IdentifiableValueObject<Statement>
    • equals

      public boolean equals(Object o)
      Overrides:
      equals in class IdentifiableValueObject<Statement>
    • canEqual

      protected boolean canEqual(Object other)
      Overrides:
      canEqual in class IdentifiableValueObject<Statement>
    • hashCode

      public int hashCode()
      Overrides:
      hashCode in class IdentifiableValueObject<Statement>