@@ -5,6 +5,8 @@ define(["underscore", "backbone", "models/metadata/eml211/EMLAnnotation"], (
55 Backbone ,
66 EMLAnnotation ,
77) => {
8+ const SCHEMA_ORG_SAME_AS = "http://www.w3.org/2002/07/owl#sameAs" ;
9+ const PROV_WAS_DERIVED_FROM = "http://www.w3.org/ns/prov#wasDerivedFrom" ;
810 /**
911 * @class EMLAnnotations
1012 * @classdesc A collection of EMLAnnotations.
@@ -56,6 +58,135 @@ define(["underscore", "backbone", "models/metadata/eml211/EMLAnnotation"], (
5658 }
5759 this . add ( annotation ) ;
5860 } ,
61+
62+ /**
63+ * Find all annotations with the given propertyURI.
64+ * @param {string } propertyURI The propertyURI to search for.
65+ * @returns {EMLAnnotation[] } An array of EMLAnnotations with the given
66+ * propertyURI.
67+ * @since 0.0.0
68+ */
69+ findByProperty ( propertyURI ) {
70+ return this . where ( { propertyURI } ) ;
71+ } ,
72+
73+ /**
74+ * Adds canonical dataset annotations to this collection. A canonical
75+ * dataset is the one that is considered the authoritative version; the
76+ * current EML doc being essentially a duplicate version.
77+ * @param {string } sourceId The DOI or URL of the canonical dataset.
78+ * @returns {void }
79+ * @since 0.0.0
80+ */
81+ addCanonicalDatasetAnnotation ( sourceId ) {
82+ if ( ! sourceId ) return null ;
83+ // TODO: Check that sourceId is a valid DOI or URL
84+
85+ // TODO: Check that there is not already a canonical dataset annotation
86+ // before adding a new one, since there should only be one.
87+ return this . add ( [
88+ {
89+ propertyLabel : "derivedFrom" ,
90+ propertyURI : PROV_WAS_DERIVED_FROM ,
91+ valueLabel : sourceId ,
92+ valueURI : sourceId ,
93+ } ,
94+ {
95+ propertyLabel : "sameAs" ,
96+ propertyURI : SCHEMA_ORG_SAME_AS ,
97+ valueLabel : sourceId ,
98+ valueURI : sourceId ,
99+ } ,
100+ ] ) ;
101+ } ,
102+
103+ /**
104+ * Find the annotations that make up the canonical dataset annotation. A
105+ * canonical dataset is identified by having both a "derivedFrom" and a
106+ * "sameAs" annotation with the same DOI or URL for the valueURI.
107+ * @returns {object } An object with the derivedFrom and sameAs
108+ * annotations.
109+ * @since 0.0.0
110+ */
111+ findCanonicalDatasetAnnotation ( ) {
112+ // There must be at least one derivedFrom and one sameAs annotation
113+ // for this to have a canonical dataset annotation
114+ if ( ! this . length ) return null ;
115+ const derivedFrom = this . findByProperty ( PROV_WAS_DERIVED_FROM ) ;
116+ if ( ! derivedFrom ?. length ) return null ;
117+ const sameAs = this . findByProperty ( SCHEMA_ORG_SAME_AS ) ;
118+ if ( ! sameAs ?. length ) return null ;
119+
120+ // Find all pairs that have matching valueURIs
121+ const pairs = [ ] ;
122+ derivedFrom . forEach ( ( derived ) => {
123+ sameAs . forEach ( ( same ) => {
124+ if ( derived . get ( "valueURI" ) === same . get ( "valueURI" ) ) {
125+ // TODO? Check that the URI is a valid DOI or URL
126+ pairs . push ( { derived, same, uri : derived . get ( "valueURI" ) } ) ;
127+ }
128+ } ) ;
129+ } ) ;
130+
131+ // If there are multiple pairs, we cannot determine which is the
132+ // canonical dataset.
133+ if ( pairs . length > 1 || ! pairs . length ) return null ;
134+
135+ // There is only one pair, so return it
136+ return pairs [ 0 ] ;
137+ } ,
138+
139+ /**
140+ * Updates the canonical dataset annotations to have the given ID. If
141+ * there is no canonical dataset annotation, one is added. If the ID is a
142+ * falsy value, the canonical dataset annotation is removed.
143+ * @param {string } newSourceId The DOI or URL of the canonical dataset.
144+ * @returns {object } An object with the derivedFrom and sameAs annotations
145+ * if the canonical dataset annotations were updated.
146+ * @since 0.0.0
147+ */
148+ updateCanonicalDataset ( newSourceId ) {
149+ if ( ! newSourceId ) {
150+ this . removeCanonicalDatasetAnnotation ( ) ;
151+ return null ;
152+ }
153+ const canonical = this . findCanonicalDatasetAnnotation ( ) ;
154+ if ( ! canonical ) {
155+ return this . addCanonicalDatasetAnnotation ( newSourceId ) ;
156+ }
157+
158+ const { derived, same, uri } = canonical ;
159+ if ( uri === newSourceId ) return null ;
160+
161+ derived . set ( "valueURI" , newSourceId ) ;
162+ derived . set ( "valueLabel" , newSourceId ) ;
163+ same . set ( "valueURI" , newSourceId ) ;
164+ same . set ( "valueLabel" , newSourceId ) ;
165+
166+ return [ derived , same ] ;
167+ } ,
168+
169+ /**
170+ * Removes the canonical dataset annotations from this collection.
171+ * @returns {EMLAnnotation[] } The canonical dataset annotations that were
172+ * removed.
173+ * @since 0.0.0
174+ */
175+ removeCanonicalDatasetAnnotation ( ) {
176+ const canonical = this . findCanonicalDatasetAnnotation ( ) ;
177+ if ( ! canonical ) return null ;
178+ return this . remove ( [ canonical . derived , canonical . same ] ) ;
179+ } ,
180+
181+ /**
182+ * Returns the URI of the canonical dataset.
183+ * @returns {string } The URI of the canonical dataset.
184+ * @since 0.0.0
185+ */
186+ getCanonicalURI ( ) {
187+ const canonical = this . findCanonicalDatasetAnnotation ( ) ;
188+ return canonical ?. uri ;
189+ } ,
59190 } ,
60191 ) ;
61192
0 commit comments