1 //
2 // This file is part of the SDTS++ toolkit, written by the U.S.
3 // Geological Survey. It is experimental software, written to support
4 // USGS research and cartographic data production.
5 //
6 // SDTS++ is public domain software. It may be freely copied,
7 // distributed, and modified. The USGS welcomes user feedback, but makes
8 // no committment to any level of support for this code. See the SDTS
9 // web site at http://mcmcweb.er.usgs.gov/sdts for more information,
10 // including points of contact.
11 //
12
13 #ifdef _MSC_VER
14 #pragma warning( disable : 4786 )
15 #endif
16
17
18 #include <sdts++/builder/sb_Xref.h>
19
20 #include <iostream>
21 #include <strstream>
22
23 #include <limits.h>
24
25 #ifndef INCLUDED_SB_UTILS_H
26 #include <sdts++/builder/sb_Utils.h>
27 #endif
28
29 #ifdef NOT_IMPLEMENTED
30 #ifndef INCLUDED_SB_FOREIGNID_H
31 #include <sdts++/builder/sb_ForeignID.h>
32 #endif
33 #endif
34
35 #ifndef INCLUDED_SC_RECORD_H
36 #include <sdts++/container/sc_Record.h>
37 #endif
38
39 #ifndef INCLUDED_SC_FIELD_H
40 #include <sdts++/container/sc_Field.h>
41 #endif
42
43 #ifndef INCLUDED_SC_SUBFIELD_H
44 #include <sdts++/container/sc_Subfield.h>
45 #endif
46
47 #ifndef INCLUDED_SIO_8211CONVERTER_H
48 #include <sdts++/io/sio_8211Converter.h>
49 #endif
50
51
52 using namespace std;
53
54
55 static const char* ident_ = "$Id: sb_Xref.cpp,v 1.7 2002/11/24 22:07:43 mcoletti Exp $";
56
57 // Strings and integers are initialized with these values; they're used
58 // to indicate whether a given module value has been assigned a value or not.
59
60 // (XXX I arbitrarily chose 0x4 as the sentinal value. I hate ad hoc crap.)
61
62 static const string UNVALUED_STRING(1, static_cast<string::value_type>(0x4) );
63
64 static const long UNVALUED_LONG = INT_MIN;
65
66 static set<string> RSNM_domain;
67 static set<string> SDAT_domain;
68
69 struct sb_Xref_Imp
70 {
71 string comment_;
72 string refDoc_;
73 string refSysName_;
74 #ifdef NOT_RASTER_PROFILE
75 string vertDatum_;
76 string soundDatum_;
77 #endif
78 string horizDatum_;
79 string zoneNum_;
80 string projection_;
81
82 #ifdef NOT_IMPLEMENTED
83 list<sb_ForeignID> attID_; // list of attribute ID's
84 #endif
85
sb_Xref_Impsb_Xref_Imp86 sb_Xref_Imp()
87 : comment_( UNVALUED_STRING ),
88 refDoc_( UNVALUED_STRING ),
89 refSysName_( UNVALUED_STRING ),
90 #ifdef NOT_RASTER_PROFILE
91 vertDatum_( UNVALUED_STRING ),
92 soundDatum_( UNVALUED_STRING ),
93 #endif
94 horizDatum_( UNVALUED_STRING ),
95 zoneNum_( UNVALUED_STRING ),
96 projection_( UNVALUED_STRING )
97 {}
98
99 }; // struct sb_Xref_Imp
100
101
102
sb_Xref()103 sb_Xref::sb_Xref()
104 : imp_( new sb_Xref_Imp )
105 {
106 setMnemonic( "XREF" );
107 setID( 1 );
108
109 if ( RSNM_domain.empty() ) // initialize static set if necessary
110 {
111 RSNM_domain.insert( "GEO" ); // these are the valid reference
112 RSNM_domain.insert( "SPCS" ); // mnemonics
113 RSNM_domain.insert( "UTM" );
114 RSNM_domain.insert( "UPS" );
115 RSNM_domain.insert( "OTHR" );
116 RSNM_domain.insert( "UNSP" );
117 }
118 #ifdef NOT_RASTER_PROFILE
119 if ( SDAT_domain.empty() )
120 {
121 SDAT_domain.insert( "MHW" );
122 SDAT_domain.insert( "MHWN" );
123 SDAT_domain.insert( "MHWS" );
124 SDAT_domain.insert( "MHHW" );
125 SDAT_domain.insert( "MLW" );
126 SDAT_domain.insert( "MLWN" );
127 SDAT_domain.insert( "MLWS" );
128 SDAT_domain.insert( "MLLW" );
129 }
130 #endif
131 }
132
133
~sb_Xref()134 sb_Xref::~sb_Xref()
135 {
136 delete imp_;
137 }
138
139 static sio_8211Converter_I converter_I; // XXX should define these in
140 static sio_8211Converter_A converter_A; // XXX sio_8211Converter.h
141
142
143 static sio_8211Schema schema_; // XREF schema
144
145
146 sio_8211Schema&
schema_()147 sb_Xref::schema_()
148 {
149 return ::schema_;
150 } // sb_Xref::schema_()
151
152
153
154
155 void
buildSpecificSchema_()156 sb_Xref::buildSpecificSchema_( )
157 {
158 schema_().push_back( sio_8211FieldFormat() );
159
160 sio_8211FieldFormat& field_format = schema_().back();
161
162 field_format.setDataStructCode( sio_8211FieldFormat::vector );
163 field_format.setDataTypeCode( sio_8211FieldFormat::mixed_data_type );
164 field_format.setName( "EXTERNAL SPATIAL REFERENCE" );
165 field_format.setTag( "XREF" );
166
167 field_format.push_back( sio_8211SubfieldFormat() );
168
169 field_format.back().setLabel( "MODN" );
170 field_format.back().setType( sio_8211SubfieldFormat::A );
171 field_format.back().setFormat( sio_8211SubfieldFormat::variable );
172 field_format.back().setConverter( &converter_A );
173
174 field_format.push_back( sio_8211SubfieldFormat() );
175
176 field_format.back().setLabel( "RCID" );
177 field_format.back().setType( sio_8211SubfieldFormat::I );
178 field_format.back().setFormat( sio_8211SubfieldFormat::variable );
179 field_format.back().setConverter( &converter_I );
180
181
182 field_format.push_back( sio_8211SubfieldFormat() );
183
184 field_format.back().setLabel( "COMT" );
185 field_format.back().setType( sio_8211SubfieldFormat::A );
186 field_format.back().setFormat( sio_8211SubfieldFormat::variable );
187 field_format.back().setConverter( &converter_A );
188
189
190
191 field_format.push_back( sio_8211SubfieldFormat() );
192
193 field_format.back().setLabel( "RDOC" );
194 field_format.back().setType( sio_8211SubfieldFormat::A );
195 field_format.back().setFormat( sio_8211SubfieldFormat::variable );
196 field_format.back().setConverter( &converter_A );
197
198
199
200 field_format.push_back( sio_8211SubfieldFormat() );
201
202 field_format.back().setLabel( "RSNM" );
203 field_format.back().setType( sio_8211SubfieldFormat::A );
204 field_format.back().setFormat( sio_8211SubfieldFormat::variable );
205 field_format.back().setConverter( &converter_A );
206
207
208 #ifdef NOT_RASTER_PROFILE
209 field_format.push_back( sio_8211SubfieldFormat() );
210
211 field_format.back().setLabel( "VDAT" );
212 field_format.back().setType( sio_8211SubfieldFormat::A );
213 field_format.back().setFormat( sio_8211SubfieldFormat::variable );
214 field_format.back().setConverter( &converter_A );
215
216
217
218 field_format.push_back( sio_8211SubfieldFormat() );
219
220 field_format.back().setLabel( "SDAT" );
221 field_format.back().setType( sio_8211SubfieldFormat::A );
222 field_format.back().setFormat( sio_8211SubfieldFormat::variable );
223 field_format.back().setConverter( &converter_A );
224 #endif
225
226
227 field_format.push_back( sio_8211SubfieldFormat() );
228
229 field_format.back().setLabel( "HDAT" );
230 field_format.back().setType( sio_8211SubfieldFormat::A );
231 field_format.back().setFormat( sio_8211SubfieldFormat::variable );
232 field_format.back().setConverter( &converter_A );
233
234
235
236 field_format.push_back( sio_8211SubfieldFormat() );
237
238 field_format.back().setLabel( "ZONE" );
239 field_format.back().setType( sio_8211SubfieldFormat::A );
240 field_format.back().setFormat( sio_8211SubfieldFormat::variable );
241 field_format.back().setConverter( &converter_A );
242
243
244
245 field_format.push_back( sio_8211SubfieldFormat() );
246
247 field_format.back().setLabel( "PROJ" );
248 field_format.back().setType( sio_8211SubfieldFormat::A );
249 field_format.back().setFormat( sio_8211SubfieldFormat::variable );
250 field_format.back().setConverter( &converter_A );
251
252
253 // XXX ATID and VATT and SATT not implemented
254
255 } // build__schema
256
257
258
259 //
260 // Build an sb_Xref from an sc_Record
261 //
262 static
263 bool
ingest_record_(sb_Xref & xref,sb_Xref_Imp & xref_imp,sc_Record const & recprox)264 ingest_record_( sb_Xref& xref, sb_Xref_Imp& xref_imp, sc_Record const& recprox )
265 {
266
267 // Make sure we have a record from an
268 // External Spatial Reference module.
269
270 sc_FieldCntr::const_iterator curfield;
271
272 if ( ! sb_Utils::getFieldByMnem(recprox,"XREF",curfield) )
273 {
274 #ifdef SDTSXX_DEBUG
275 cerr << "sb_Xref::sb_Xref(sc_Record const&): "
276 << "Not an External Spatial Reference module record.";
277 cerr << endl;
278 #endif
279 return false;
280 }
281
282 // We have a primary field from a module. Start
283 // picking it apart.
284
285 sc_SubfieldCntr::const_iterator cursubfield;
286
287 string tmp_str;
288 long tmp_int;
289
290 // MODN
291 if (sb_Utils::getSubfieldByMnem(*curfield,"MODN",cursubfield))
292 {
293 cursubfield->getA( tmp_str );
294 xref.setMnemonic( tmp_str );
295 }
296
297 // RCID
298 if (sb_Utils::getSubfieldByMnem(*curfield,"RCID",cursubfield))
299 {
300 cursubfield->getI( tmp_int );
301 xref.setID( tmp_int );
302 }
303
304
305 // COMT
306 if (sb_Utils::getSubfieldByMnem(*curfield,"COMT",cursubfield))
307 cursubfield->getA( xref_imp.comment_);
308
309 // RDOC
310 if (sb_Utils::getSubfieldByMnem(*curfield,"RDOC",cursubfield))
311 cursubfield->getA( xref_imp.refDoc_);
312
313 // RSNM
314 if (sb_Utils::getSubfieldByMnem(*curfield,"RSNM",cursubfield))
315 cursubfield->getA( xref_imp.refSysName_);
316
317 #ifdef NOT_RASTER_PROFILE
318 // VDAT
319 if (sb_Utils::getSubfieldByMnem(*curfield,"VDAT",cursubfield))
320 cursubfield->getA( xref_imp.vertDatum_);
321
322 // SDAT
323 if (sb_Utils::getSubfieldByMnem(*curfield,"SDAT",cursubfield))
324 cursubfield->getA( xref_imp.soundDatum_);
325 #endif
326
327 // HDAT
328 if (sb_Utils::getSubfieldByMnem(*curfield,"HDAT",cursubfield))
329 cursubfield->getA( xref_imp.horizDatum_);
330
331 // ZONE
332 if (sb_Utils::getSubfieldByMnem(*curfield,"ZONE",cursubfield))
333 cursubfield->getA( xref_imp.zoneNum_);
334
335 // PROJ
336 if (sb_Utils::getSubfieldByMnem(*curfield,"PROJ",cursubfield))
337 cursubfield->getA( xref_imp.projection_);
338
339 // Secondary Fields
340
341 // Attribute ID (ATID) Field
342 // XXX What about repeating fields?
343 #ifdef NOT_IMPLEMENTED
344 if (sb_Utils::getFieldByMnem(recprox,"ATID",curfield))
345 xref_imp.attID_.push_back( sb_ForeignID(*curfield) );
346 #endif
347
348 return true;
349
350 } // ingest__record
351
352
353
354 bool
getComment(string & val) const355 sb_Xref::getComment( string & val ) const
356 {
357 if ( imp_->comment_ == UNVALUED_STRING )
358 return false;
359
360 val = imp_->comment_;
361
362 return true;
363 } // sb_Xref::getComment
364
365
366
367 bool
getReferenceDocumentation(string & val) const368 sb_Xref::getReferenceDocumentation( string & val ) const
369 {
370 if ( imp_->refDoc_ == UNVALUED_STRING )
371 return false;
372
373 val = imp_->refDoc_;
374
375 return true;
376 } // sb_Xref::getReferenceDocumentation
377
378
379
380 bool
getReferenceSystemName(string & val) const381 sb_Xref::getReferenceSystemName( string & val ) const
382 {
383 if ( imp_->refSysName_ == UNVALUED_STRING )
384 return false;
385
386 val = imp_->refSysName_;
387
388 return true;
389 } // sb_Xref::getReferenceSystemName
390
391
392
393 #ifdef NOT_RASTER_PROFILE
394 bool
getVerticalDatum(string & val) const395 sb_Xref::getVerticalDatum( string & val ) const
396 {
397 if ( imp_->vertDatum_ == UNVALUED_STRING )
398 return false;
399
400 val = imp_->vertDatum_;
401
402 return true;
403 } // sb_Xref::getVerticalDatum
404
405
406 bool
getSoundingDatum(string & val) const407 sb_Xref::getSoundingDatum( string & val ) const
408 {
409 if ( imp_->soundDatum_ == UNVALUED_STRING )
410 return false;
411
412 val = imp_->soundDatum_;
413
414 return true;
415 } // sb_Xref::getSoundingDatum
416 #endif
417
418
419 bool
getHorizontalDatum(string & val) const420 sb_Xref::getHorizontalDatum( string & val ) const
421 {
422 if ( imp_->horizDatum_ == UNVALUED_STRING )
423 return false;
424
425 val = imp_->horizDatum_;
426
427 return true;
428 } // sb_Xref::getHorizontalDatum
429
430
431 bool
getZoneReferenceNumber(string & val) const432 sb_Xref::getZoneReferenceNumber( string & val ) const
433 {
434 if ( imp_->zoneNum_ == UNVALUED_STRING )
435 return false;
436
437 val = imp_->zoneNum_;
438
439 return true;
440 } // sb_Xref::getZoneReferenceNumber
441
442
443 bool
getProjection(string & val) const444 sb_Xref::getProjection( string & val ) const
445 {
446 if ( imp_->projection_ == UNVALUED_STRING )
447 return false;
448
449 val = imp_->projection_;
450
451 return true;
452 } // sb_Xref::getProjection
453
454
455 #ifdef NOT_IMPLEMENTED
456 bool
getAttID(list<sb_ForeignID> & val) const457 sb_Xref::getAttID( list<sb_ForeignID> & val ) const
458 {
459 // if ( imp_->attID_ == UNVALUED_STRING ) XXX need way to determine
460 // return false; XXX that aid has not been given a value
461
462 val = imp_->attID_;
463
464 return true;
465 } // sb_Xref::getAttID
466 #endif
467
468
469
470
471
472 bool
getRecord(sc_Record & record) const473 sb_Xref::getRecord( sc_Record & record ) const
474 {
475 record.clear(); // start with a clean slate
476
477 // XREF field
478
479 record.push_back( sc_Field() );
480
481 record.back().setMnemonic( "XREF" );
482
483 string tmp_str;
484
485 getMnemonic( tmp_str );
486 sb_Utils::add_subfield( record.back(), "MODN", tmp_str );
487 sb_Utils::add_subfield( record.back(), "RCID", getID() );
488
489 if ( getCOMT( tmp_str ) )
490 {
491 sb_Utils::add_subfield( record.back(),"COMT", tmp_str );
492 }
493 else
494 {
495 sb_Utils::add_empty_subfield( record.back(), "COMT", sc_Subfield::is_A );
496 }
497
498 if ( getRDOC( tmp_str ) )
499 {
500 sb_Utils::add_subfield( record.back(),"RDOC", tmp_str );
501 }
502 else
503 {
504 sb_Utils::add_empty_subfield( record.back(), "RDOC", sc_Subfield::is_A );
505 }
506
507 string rsnm;
508
509 if ( ! getRSNM( rsnm ) )
510 {
511 return false;
512 }
513 else
514 {
515 if ( ! sb_Utils::valid_domain( rsnm, RSNM_domain ) )
516 {
517 return false;
518 }
519 }
520
521 sb_Utils::add_subfield( record.back(),"RSNM", rsnm );
522
523
524 #ifdef NOT_RASTER_PROFILE
525 if ( getVDAT( tmp_str ) )
526 {
527 sb_Utils::add_subfield( record.back(),"VDAT", tmp_str );
528 }
529 else
530 {
531 sb_Utils::add_empty_subfield( record.back(), "VDAT", sc_Subfield::is_A );
532 }
533
534
535 if ( getSDAT( tmp_str ) )
536 {
537 if ( ! sb_Utils::valid_domain( tmp_str, SDAT_domain ) )
538 {
539 return false;
540 }
541 sb_Utils::add_subfield( record.back(),"SDAT", tmp_str );
542 }
543 else
544 {
545 sb_Utils::add_empty_subfield( record.back(), "SDAT", sc_Subfield::is_A );
546 }
547 #endif
548
549
550 if ( getHDAT( tmp_str ) )
551 {
552 sb_Utils::add_subfield( record.back(),"HDAT", tmp_str );
553 }
554 else
555 {
556 sb_Utils::add_empty_subfield( record.back(), "HDAT", sc_Subfield::is_A );
557 }
558
559
560 if ( rsnm == "SPCS" ||
561 rsnm == "UTM" ||
562 rsnm == "UPS" )
563 {
564 if ( ! getZONE( tmp_str ) )
565 {
566 return false;
567 }
568
569 sb_Utils::add_subfield( record.back(),"ZONE", tmp_str );
570 }
571 else
572 {
573 sb_Utils::add_empty_subfield( record.back(), "ZONE", sc_Subfield::is_A );
574 }
575
576
577 if ( rsnm == "OTHR" )
578 {
579
580 if ( ! getPROJ( tmp_str ) )
581 {
582 return false;
583 }
584
585 sb_Utils::add_subfield( record.back(),"PROJ", tmp_str );
586 }
587 else
588 {
589 sb_Utils::add_empty_subfield( record.back(), "PROJ", sc_Subfield::is_A );
590 }
591
592 // XXX add support for attribute ID's
593
594 return true;
595
596 } // sb_Xref::setRecord
597
598
599
600
601
602
603
604
605 bool
setRecord(sc_Record const & record)606 sb_Xref::setRecord( sc_Record const& record )
607 {
608 return ingest_record_( *this, *imp_, record );
609 } // sb_Xref::setRecord
610
611
612
613 bool
setComment(string const & val)614 sb_Xref::setComment( string const & val )
615 {
616 imp_->comment_ = val;
617 return true;
618 } // sb_Xref::setComment
619
620
621
622 bool
setReferenceDocumentation(string const & val)623 sb_Xref::setReferenceDocumentation( string const & val )
624 {
625 imp_->refDoc_ = val;
626 return true;
627 } // sb_Xref::setReferenceDocumentation
628
629
630
631 bool
setReferenceSystemName(string const & val)632 sb_Xref::setReferenceSystemName( string const & val )
633 {
634 if ( ! sb_Utils::valid_domain( val, RSNM_domain ) )
635 {
636 return false;
637 }
638 imp_->refSysName_ = val;
639 return true;
640 } // sb_Xref::setReferenceSystemName
641
642
643
644 #ifdef NOT_RASTER_PROFILE
645 bool
setVerticalDatum(string const & val)646 sb_Xref::setVerticalDatum( string const & val )
647 {
648 imp_->vertDatum_ = val;
649 return true;
650 } // sb_Xref::setVerticalDatum
651
652
653
654 bool
setSoundingDatum(string const & val)655 sb_Xref::setSoundingDatum( string const & val )
656 {
657 if ( ! sb_Utils::valid_domain( val, SDAT_domain ) )
658 {
659 return false;
660 }
661 imp_->soundDatum_ = val;
662 return true;
663 } // sb_Xref::setSoundingDatum
664 #endif
665
666
667 bool
setHorizontalDatum(string const & val)668 sb_Xref::setHorizontalDatum( string const & val )
669 {
670 imp_->horizDatum_ = val;
671 return true;
672 } // sb_Xref::setHorizontalDatum
673
674
675
676 bool
setZoneReferenceNumber(string const & val)677 sb_Xref::setZoneReferenceNumber( string const & val )
678 {
679 imp_->zoneNum_ = val;
680 return true;
681 } // sb_Xref::setZoneReferenceNumber
682
683
684 bool
setZoneReferenceNumber(int val)685 sb_Xref::setZoneReferenceNumber( int val )
686 {
687 strstream ss;
688
689 ss << val;// << ends;
690
691 if ( ! (ss >> imp_->zoneNum_) ) return false;
692
693 return true;
694 } // sb_Xref::setZoneReferenceNumber
695
696
697
698 bool
setProjection(string const & val)699 sb_Xref::setProjection( string const & val )
700 {
701 imp_->projection_ = val;
702 return true;
703 } // sb_Xref::setProjection
704
705