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