@@ -16,6 +16,7 @@ import type {
1616 MartiDestAttributes ,
1717 Link ,
1818 LinkAttributes ,
19+ CreatorAttributes ,
1920 VideoAttributes ,
2021 SensorAttributes ,
2122 VideoConnectionEntryAttributes ,
@@ -77,7 +78,17 @@ export default class CoT {
7778 // Does the CoT belong to a folder - defaults to "/"
7879 path : string ;
7980
80- constructor ( cot : Buffer | Static < typeof JSONCoT > | object | string ) {
81+ constructor (
82+ cot : Buffer | Static < typeof JSONCoT > | object | string ,
83+ opts : {
84+ creator ?: CoT | {
85+ uid : string ,
86+ type : string ,
87+ callsign : string ,
88+ time ?: Date | string ,
89+ }
90+ } = { }
91+ ) {
8192 if ( typeof cot === 'string' || cot instanceof Buffer ) {
8293 const raw = xmljs . xml2js ( String ( cot ) , { compact : true } ) ;
8394 this . raw = raw as Static < typeof JSONCoT > ;
@@ -102,6 +113,15 @@ export default class CoT {
102113 if ( this . raw . event . detail . archive && Object . keys ( this . raw . event . detail . archive ) . length === 0 ) {
103114 this . raw . event . detail . archive = { _attributes : { } } ;
104115 }
116+
117+ if ( opts . creator ) {
118+ this . creator ( {
119+ uid : opts . creator instanceof CoT ? opts . creator . uid ( ) : opts . creator . uid ,
120+ type : opts . creator instanceof CoT ? opts . creator . type ( ) : opts . creator . type ,
121+ callsign : opts . creator instanceof CoT ? opts . creator . callsign ( ) : opts . creator . callsign ,
122+ time : opts . creator instanceof CoT ? new Date ( ) : opts . creator . time
123+ } ) ;
124+ }
105125 }
106126
107127 /**
@@ -150,6 +170,14 @@ export default class CoT {
150170 return diffs . length > 0 ;
151171 }
152172
173+ /**
174+ * Returns or sets the UID of the CoT
175+ */
176+ uid ( uid ?: string ) : string {
177+ if ( uid ) this . raw . event . _attributes . uid = uid ;
178+ return this . raw . event . _attributes . uid ;
179+ }
180+
153181 /**
154182 * Returns or sets the Callsign of the CoT
155183 */
@@ -163,48 +191,51 @@ export default class CoT {
163191
164192 /**
165193 * Returns or sets the Callsign of the CoT
194+ *
195+ * @param callsign - Optional Callsign to set
166196 */
167197 callsign ( callsign ?: string ) : string {
168- if ( ! this . raw . event . detail ) this . raw . event . detail = { } ;
198+ const detail = this . detail ( ) ;
169199
170- if ( callsign && ! this . raw . event . detail . contact ) {
171- this . raw . event . detail . contact = { _attributes : { callsign } } ;
172- } else if ( callsign && this . raw . event . detail . contact ) {
173- this . raw . event . detail . contact . _attributes . callsign = callsign ;
200+ if ( callsign && ! detail . contact ) {
201+ detail . contact = { _attributes : { callsign } } ;
202+ } else if ( callsign && detail . contact ) {
203+ detail . contact . _attributes . callsign = callsign ;
174204 }
175205
176- if ( this . raw . event . detail . contact && this . raw . event . detail . contact . _attributes && typeof this . raw . event . detail . contact . _attributes . callsign === 'string' ) {
177- return this . raw . event . detail . contact . _attributes . callsign ;
206+ if ( detail . contact && detail . contact . _attributes && typeof detail . contact . _attributes . callsign === 'string' ) {
207+ return detail . contact . _attributes . callsign ;
178208 } else {
179209 return 'UNKNOWN'
180210 }
181211 }
182212
183213 /**
184- * Returns or sets the UID of the CoT
214+ * Return Detail Object of CoT or create one if it doesn't yet exist and pass a reference
185215 */
186- uid ( uid ?: string ) : string {
187- if ( uid ) this . raw . event . _attributes . uid = uid ;
188- return this . raw . event . _attributes . uid ;
216+ detail ( ) : Static < typeof Detail > {
217+ if ( ! this . raw . event . detail ) this . raw . event . detail = { } ;
218+ return this . raw . event . detail ;
189219 }
190220
191221 /**
192222 * Add a given Dest tag to a CoT
193223 */
194224 addDest ( dest : Static < typeof MartiDestAttributes > ) : CoT {
195- if ( ! this . raw . event . detail ) this . raw . event . detail = { } ;
196- if ( ! this . raw . event . detail . marti ) this . raw . event . detail . marti = { } ;
225+ const detail = this . detail ( ) ;
226+
227+ if ( ! detail . marti ) detail . marti = { } ;
197228
198229 let destArr : Array < Static < typeof MartiDest > > = [ ] ;
199- if ( this . raw . event . detail . marti . dest && ! Array . isArray ( this . raw . event . detail . marti . dest ) ) {
200- destArr = [ this . raw . event . detail . marti . dest ]
201- } else if ( this . raw . event . detail . marti . dest && Array . isArray ( this . raw . event . detail . marti . dest ) ) {
202- destArr = this . raw . event . detail . marti . dest ;
230+ if ( detail . marti . dest && ! Array . isArray ( detail . marti . dest ) ) {
231+ destArr = [ detail . marti . dest ]
232+ } else if ( detail . marti . dest && Array . isArray ( detail . marti . dest ) ) {
233+ destArr = detail . marti . dest ;
203234 }
204235
205236 destArr . push ( { _attributes : dest } ) ;
206237
207- this . raw . event . detail . marti . dest = destArr ;
238+ detail . marti . dest = destArr ;
208239
209240 return this ;
210241 }
@@ -213,8 +244,8 @@ export default class CoT {
213244 video : Static < typeof VideoAttributes > ,
214245 connection ?: Static < typeof VideoConnectionEntryAttributes >
215246 ) : CoT {
216- if ( ! this . raw . event . detail ) this . raw . event . detail = { } ;
217- if ( this . raw . event . detail . __video ) throw new Err ( 400 , null , 'A video stream already exists on this CoT' ) ;
247+ const detail = this . detail ( ) ;
248+ if ( detail . __video ) throw new Err ( 400 , null , 'A video stream already exists on this CoT' ) ;
218249
219250 if ( ! video . url ) throw new Err ( 400 , null , 'A Video URL must be provided' ) ;
220251
@@ -226,16 +257,16 @@ export default class CoT {
226257 video . uid = crypto . randomUUID ( ) ;
227258 }
228259
229- this . raw . event . detail . __video = {
260+ detail . __video = {
230261 _attributes : video
231262 } ;
232263
233264 if ( connection ) {
234- this . raw . event . detail . __video . ConnectionEntry = {
265+ detail . __video . ConnectionEntry = {
235266 _attributes : connection
236267 }
237268 } else {
238- this . raw . event . detail . __video . ConnectionEntry = {
269+ detail . __video . ConnectionEntry = {
239270 _attributes : {
240271 uid : video . uid ,
241272 networkTimeout : 12000 ,
@@ -268,37 +299,71 @@ export default class CoT {
268299 }
269300
270301 sensor ( sensor ?: Static < typeof SensorAttributes > ) : Static < typeof Polygon > | null {
271- if ( ! this . raw . event . detail ) this . raw . event . detail = { } ;
302+ const detail = this . detail ( ) ;
272303
273304 if ( sensor ) {
274- this . raw . event . detail . sensor = {
305+ detail . sensor = {
275306 _attributes : sensor
276307 }
277308 }
278309
279- if ( ! this . raw . event . detail . sensor || ! this . raw . event . detail . sensor . _attributes ) {
310+ if ( ! detail . sensor || ! detail . sensor . _attributes ) {
280311 return null ;
281312 }
282313
283314 return new Sensor (
284315 this . position ( ) ,
285- this . raw . event . detail . sensor . _attributes
316+ detail . sensor . _attributes
286317 ) . to_geojson ( ) ;
287318 } ;
288319
320+ creator (
321+ creator ?: {
322+ uid : string ,
323+ type : string ,
324+ callsign : string ,
325+ time : Date | string | undefined ,
326+ }
327+ ) : Static < typeof CreatorAttributes > | undefined {
328+ const detail = this . detail ( ) ;
329+
330+ if ( creator ) {
331+ this . addLink ( {
332+ uid : creator . uid ,
333+ production_time : creator . time ? new Date ( creator . time ) . toISOString ( ) : new Date ( ) . toISOString ( ) ,
334+ type : creator . type ,
335+ parent_callsign : creator . callsign ,
336+ relation : 'p-p'
337+ } ) ;
338+
339+ detail . creator = {
340+ _attributes : {
341+ ...creator ,
342+ time : creator . time ? new Date ( creator . time ) . toISOString ( ) : new Date ( ) . toISOString ( ) ,
343+ }
344+ } ;
345+ }
346+
347+ if ( detail . creator ) {
348+ return detail . creator . _attributes ;
349+ } else {
350+ return ;
351+ }
352+ }
353+
289354 addLink ( link : Static < typeof LinkAttributes > ) : CoT {
290- if ( ! this . raw . event . detail ) this . raw . event . detail = { } ;
355+ const detail = this . detail ( ) ;
291356
292357 let linkArr : Array < Static < typeof Link > > = [ ] ;
293- if ( this . raw . event . detail . link && ! Array . isArray ( this . raw . event . detail . link ) ) {
294- linkArr = [ this . raw . event . detail . link ]
295- } else if ( this . raw . event . detail . link && Array . isArray ( this . raw . event . detail . link ) ) {
296- linkArr = this . raw . event . detail . link ;
358+ if ( detail . link && ! Array . isArray ( detail . link ) ) {
359+ linkArr = [ detail . link ]
360+ } else if ( detail . link && Array . isArray ( detail . link ) ) {
361+ linkArr = detail . link ;
297362 }
298363
299364 linkArr . push ( { _attributes : link } ) ;
300365
301- this . raw . event . detail . link = linkArr ;
366+ detail . link = linkArr ;
302367
303368 return this ;
304369 }
@@ -375,6 +440,10 @@ export default class CoT {
375440 feat . properties . contact = contact ;
376441 }
377442
443+ if ( this . creator ( ) ) {
444+ feat . properties . creator = this . creator ( ) ;
445+ }
446+
378447 if ( raw . event . detail . remarks && raw . event . detail . remarks . _text ) {
379448 feat . properties . remarks = raw . event . detail . remarks . _text ;
380449 }
@@ -978,6 +1047,10 @@ export default class CoT {
9781047 cot . event . detail . takv = { _attributes : { ...feature . properties . takv } } ;
9791048 }
9801049
1050+ if ( feature . properties . creator ) {
1051+ cot . event . detail . creator = { _attributes : { ...feature . properties . creator } } ;
1052+ }
1053+
9811054 if ( feature . properties . geofence ) {
9821055 cot . event . detail . __geofence = { _attributes : { ...feature . properties . geofence } } ;
9831056 }
0 commit comments