00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00030 #include "arts.h"
00031 #include <map>
00032 #include "make_array.h"
00033 #include "methods.h"
00034 #include "wsv_aux.h"
00035 #include "workspace_ng.h"
00036
00037
00038 void limit_line_length( ostream& os, ostringstream& curline,
00039 ostringstream& token, const String& indent,
00040 size_t linelen);
00041
00043
00049 MdRecord::MdRecord(const char name[],
00050 const char description[],
00051 const MakeArray<String>& authors,
00052 const MakeArray<String>& output,
00053 const MakeArray<String>& gout,
00054 const MakeArray<String>& gouttype,
00055 const MakeArray<String>& goutdesc,
00056 const MakeArray<String>& input,
00057 const MakeArray<String>& gin,
00058 const MakeArray<String>& gintype,
00059 const MakeArray<String>& gindefault,
00060 const MakeArray<String>& gindesc,
00061 bool set_method,
00062 bool agenda_method,
00063 bool suppress_header,
00064 bool pass_workspace,
00065 bool pass_wsv_names ) :
00066 mname( name ),
00067 mdescription( description ),
00068 mauthors( authors ),
00069 moutput( 0 ),
00070 mgout( gout ),
00071 mgouttype( 0 ),
00072 mgoutdesc( goutdesc ),
00073 minput( 0 ),
00074 mgin( gin ),
00075 mgintype( 0 ),
00076 mgindefault( gindefault ),
00077 mgindesc( gindesc ),
00078 mset_method( set_method ),
00079 magenda_method( agenda_method ),
00080 msupergeneric( false ),
00081 msuppress_header( suppress_header ),
00082 mpass_workspace( pass_workspace ),
00083 mpass_wsv_names( pass_wsv_names ),
00084 mactual_groups( "" )
00085 {
00086
00087
00088
00089
00090
00091
00092 assert( mgout.nelem() == gouttype.nelem() );
00093 assert( mgout.nelem() == goutdesc.nelem() );
00094 assert( mgin.nelem() == mgindefault.nelem() );
00095 assert( mgin.nelem() == gintype.nelem() );
00096 assert( mgin.nelem() == gindesc.nelem() );
00097
00098
00099 moutput.resize(output.nelem());
00100 for ( Index j=0; j<output.nelem(); ++j )
00101 {
00102 moutput[j] = get_wsv_id (output[j]);
00103 if (moutput[j] == -1)
00104 {
00105 ostringstream os;
00106 os << "Unknown WSV " << output[j] << " for output "
00107 << "in WSM " << mname;
00108 throw runtime_error( os.str() );
00109 }
00110 }
00111
00112 minput.resize(input.nelem());
00113 for ( Index j=0; j<input.nelem(); ++j )
00114 {
00115 minput[j] = get_wsv_id (input[j]);
00116 if (minput[j] == -1)
00117 {
00118 ostringstream os;
00119 os << "Unknown WSV " << input[j] << " for input "
00120 << "in WSM " << mname;
00121 throw runtime_error( os.str() );
00122 }
00123 }
00124
00125
00126 mgoutspectype.resize(gouttype.nelem());
00127 mgouttype.resize(gouttype.nelem());
00128 for ( Index j=0; j<gouttype.nelem(); ++j )
00129 {
00130 ArrayOfIndex types;
00131 get_wsv_group_ids (types, gouttype[j]);
00132
00133 if (types.nelem() == 1)
00134 {
00135 mgouttype[j] = types[0];
00136 mgoutspectype[j].resize(0);
00137 }
00138 else if (types.nelem() > 1)
00139 {
00140 mgouttype[j] = get_wsv_group_id ("Any");
00141 mgoutspectype[j] = types;
00142 }
00143 else
00144 {
00145 ostringstream os;
00146 os << "Unknown WSV Group " << gouttype[j] << " for generic output "
00147 << "in WSM " << mname;
00148 throw runtime_error( os.str() );
00149 }
00150
00151 }
00152
00153 mginspectype.resize(gintype.nelem());
00154 mgintype.resize(gintype.nelem());
00155 for ( Index j=0; j<gintype.nelem(); ++j )
00156 {
00157 ArrayOfIndex types;
00158 get_wsv_group_ids (types, gintype[j]);
00159
00160 if (types.nelem() == 1)
00161 {
00162 mgintype[j] = get_wsv_group_id (gintype[j]);
00163 mginspectype[j].resize(0);
00164 }
00165 else if (types.nelem() > 1)
00166 {
00167 mgintype[j] = get_wsv_group_id ("Any");
00168 mginspectype[j] = types;
00169 }
00170 else
00171 {
00172 ostringstream os;
00173 os << "Unknown WSV Group " << gintype[j] << " for generic input "
00174 << "in WSM " << mname;
00175 throw runtime_error( os.str() );
00176 }
00177 }
00178
00179
00180
00181 if (mginspectype.nelem() && mgoutspectype.nelem())
00182 {
00183 bool consistent = true;
00184 Index nspecs = 0;
00185 for (Index i = 0; consistent && i < mginspectype.nelem(); i++)
00186 {
00187 if (mginspectype[0].nelem())
00188 {
00189 if (!nspecs) nspecs = mginspectype[0].nelem();
00190 else if (nspecs != mginspectype[0].nelem()) consistent = false;
00191 }
00192 }
00193
00194 for (Index i = 0; consistent && i < mgoutspectype.nelem(); i++)
00195 {
00196 if (mgoutspectype[0].nelem())
00197 {
00198 if (!nspecs) nspecs = mgoutspectype[0].nelem();
00199 else if (nspecs != mgoutspectype[0].nelem()) consistent = false;
00200 }
00201 }
00202 if (!consistent)
00203 {
00204 ostringstream os;
00205 os << "Inconsistent number of types given for supergeneric variables"
00206 << endl << "in WSM " << mname << "." << endl;
00207 throw runtime_error (os.str());
00208 }
00209 }
00210
00211
00212
00213 for ( Index j=0; j<mgouttype.nelem(); ++j )
00214 if ( get_wsv_group_id("Any") == mgouttype[j] )
00215 msupergeneric = true;
00216 for ( Index j=0; j<mgintype.nelem(); ++j )
00217 if ( get_wsv_group_id("Any") == mgintype[j] )
00218 msupergeneric = true;
00219
00220
00221 minonly = minput;
00222 for (ArrayOfIndex::const_iterator j=moutput.begin(); j<moutput.end(); ++j)
00223 for (ArrayOfIndex::iterator k=minonly.begin(); k<minonly.end(); ++k)
00224 if ( *j == *k )
00225 {
00226 k = minonly.erase(k) - 1;
00227
00228
00229
00230
00231 }
00232
00233
00234 minout.resize(0);
00235 Index i = 0;
00236 for (ArrayOfIndex::const_iterator j=moutput.begin(); j<moutput.end(); ++j,++i)
00237 for (ArrayOfIndex::const_iterator k=minput.begin(); k<minput.end(); ++k)
00238 if ( *j == *k )
00239 minout.push_back(i);
00240 }
00241
00242
00244
00253 void MdRecord::subst_any_with_group( Index g )
00254 {
00255 const Index wsv_group_id_Any = get_wsv_group_id("Any");
00256
00257 extern const ArrayOfString wsv_group_names;
00258
00259
00260 assert( 0 != wsv_group_names.nelem() );
00261
00262
00263
00264 assert( 0 <= g );
00265 assert( wsv_group_id_Any != g );
00266 assert( g < wsv_group_names.nelem() );
00267
00268
00269 assert( Supergeneric() );
00270
00271
00272
00273
00274
00275
00276
00277
00278 for ( Index j=0; j<mgouttype.nelem(); ++j )
00279 if ( wsv_group_id_Any == mgouttype[j] ) mgouttype[j] = g;
00280 for ( Index j=0; j<mgintype.nelem(); ++j )
00281 if ( wsv_group_id_Any == mgintype[j] ) mgintype[j] = g;
00282
00283
00284 mactual_groups = wsv_group_names[g];
00285 }
00286
00287
00289
00298 void MdRecord::subst_any_with_specific_group( Index g )
00299 {
00300
00301 extern const ArrayOfString wsv_group_names;
00302
00303 const Index wsv_group_id_Any = get_wsv_group_id("Any");
00304
00305
00306
00307 assert( 0 <= g );
00308
00309
00310 assert( Supergeneric() );
00311
00312
00313
00314
00315
00316
00317
00318
00319 mactual_groups = "";
00320 for ( Index j=0; j<mgouttype.nelem(); ++j )
00321 if ( wsv_group_id_Any == mgouttype[j] )
00322 {
00323 mgouttype[j] = mgoutspectype[j][g];
00324
00325 mactual_groups += wsv_group_names[mgoutspectype[j][g]];
00326 }
00327
00328 for ( Index j=0; j<mgintype.nelem(); ++j )
00329 if ( wsv_group_id_Any == mgintype[j] )
00330 {
00331 mgintype[j] = mginspectype[j][g];
00332
00333 mactual_groups += wsv_group_names[mginspectype[j][g]];
00334 }
00335
00336 }
00337
00338
00340
00349 void expand_md_data_raw_to_md_data()
00350 {
00351 extern const Array<MdRecord> md_data_raw;
00352 extern Array<MdRecord> md_data;
00353
00354
00355 extern const ArrayOfString wsv_group_names;
00356
00357 const Index wsv_group_id_Any = get_wsv_group_id("Any");
00358
00359
00360 assert ( 0!=wsv_group_names.nelem() );
00361
00362
00363 md_data.resize(0);
00364
00365 for ( Index i=0; i<md_data_raw.nelem(); ++i )
00366 {
00367 const MdRecord& mdd = md_data_raw[i];
00368
00369 if ( !mdd.Supergeneric() )
00370 {
00371 md_data.push_back(mdd);
00372 }
00373 else
00374 {
00375
00376
00377
00378
00379
00380 if ((mdd.GInSpecType().nelem() && mdd.GInSpecType()[0].nelem())
00381 || (mdd.GOutSpecType().nelem() && mdd.GOutSpecType()[0].nelem()))
00382 {
00383 Index max = 0;
00384 if (mdd.GInSpecType().nelem())
00385 max = mdd.GInSpecType()[0].nelem();
00386 if (mdd.GOutSpecType().nelem()
00387 && mdd.GOutSpecType()[0].nelem() > max )
00388 max = mdd.GOutSpecType()[0].nelem();
00389
00390 for (Index k=0; k<max; k++)
00391 {
00392 MdRecord mdlocal = mdd;
00393
00394 mdlocal.subst_any_with_specific_group(k);
00395
00396 md_data.push_back(mdlocal);
00397 }
00398 }
00399 else
00400 {
00401 for ( Index j=0; j<wsv_group_names.nelem(); ++j )
00402 {
00403
00404
00405 if ( wsv_group_id_Any != j )
00406 {
00407
00408
00409 MdRecord mdlocal = mdd;
00410
00411 mdlocal.subst_any_with_group( j );
00412
00413 md_data.push_back(mdlocal);
00414 }
00415 }
00416 }
00417 }
00418 }
00419 }
00420
00422
00425 void define_md_map()
00426 {
00427
00428 extern Array<MdRecord> md_data;
00429 extern map<String, Index> MdMap;
00430 DEBUG_ONLY( extern const ArrayOfString wsv_group_names; )
00431
00432
00433 assert( 0 != md_data.nelem() );
00434 assert( 0 != wsv_group_names.nelem() );
00435
00436 for ( Index i=0 ; i<md_data.nelem() ; ++i)
00437 {
00438 const MdRecord& mdd = md_data[i];
00439
00440
00441 String methodname;
00442 ostringstream os;
00443 if ( mdd.Supergeneric() )
00444 {
00445 os << mdd.Name() << "_sg_"
00446 << mdd.ActualGroups();
00447 }
00448 else
00449 {
00450 os << mdd.Name();
00451 }
00452 methodname = os.str();
00453
00454 MdMap[methodname] = i;
00455 }
00456 }
00457
00459
00467 void define_md_raw_map()
00468 {
00469 extern const Array<MdRecord> md_data_raw;
00470 extern map<String, Index> MdRawMap;
00471
00472 for ( Index i=0 ; i<md_data_raw.nelem() ; ++i)
00473 {
00474 MdRawMap[md_data_raw[i].Name()] = i;
00475 }
00476 }
00477
00478
00479 bool format_paragraph (String &s, const String &indent, const size_t linelen,
00480 const size_t offset = 0)
00481 {
00482 bool fit = true;
00483 String out;
00484 String token;
00485 size_t lastreturn = 0;
00486 size_t currentlinelength = offset;
00487 for (size_t i = 0; i < s.length(); i++)
00488 {
00489 if (s[i] == '\n') s[i] = ' ';
00490 token += s[i];
00491 if (s[i] == ' ')
00492 {
00493 if (currentlinelength + token.length() > linelen)
00494 {
00495 out += '\n' + indent;
00496 lastreturn = i;
00497 currentlinelength = indent.length();
00498 fit = false;
00499 }
00500 out += token;
00501 currentlinelength += token.length();
00502 token = "";
00503 }
00504 }
00505
00506 if (token.length())
00507 {
00508 if (currentlinelength + token.length() > linelen)
00509 {
00510 out += '\n' + indent;
00511 fit = false;
00512 }
00513 out += token;
00514 }
00515 s = out;
00516 return fit;
00517 }
00518
00519
00520 void get_short_wsv_description(String &s, const String &desc)
00521 {
00522 Index pos;
00523 Index pos2;
00524
00525
00526 pos = desc.find(".\n");
00527 pos2 = desc.find(". ");
00528 if (pos == String::npos || (pos2 != String::npos && pos2 < pos)) pos = pos2;
00529 if (pos == String::npos) pos = desc.find("\n");
00530 if (pos != String::npos)
00531 s = desc.substr(0, pos+1);
00532 else
00533 s = desc;
00534
00535
00536 while ((pos = s.find("\n")) != String::npos)
00537 {
00538 s.replace (pos, 1, " ");
00539 }
00540 }
00541
00542
00543 ostream& MdRecord::PrintTemplate(ostream& os,
00544 bool show_description) const
00545 {
00546 extern const ArrayOfString wsv_group_names;
00547
00548 if (show_description)
00549 {
00550
00551 }
00552
00553 os << Name();
00554
00555
00556 if ( 0 != GOutType().nelem()+GInType().nelem() )
00557 {
00558
00559 bool first=true;
00560
00561 os << '(';
00562
00563 for (Index i=0; i<GOutType().nelem(); ++i)
00564 {
00565 if (first) first=false;
00566 else os << ",\n";
00567
00568 os << wsv_group_names[GOutType()[i]];
00569 }
00570
00571 for (Index i=0; i<GInType().nelem(); ++i)
00572 {
00573 if (first) first=false;
00574 else os << ",\n";
00575
00576 os << wsv_group_names[GInType()[i]];
00577 }
00578
00579 os << ')';
00580 }
00581
00582
00583
00584 os << '{';
00585
00586
00587 Index maxsize = 0;
00588 for (Index i=0; i<GIn().nelem(); ++i)
00589 if ( GIn()[i].nelem() > maxsize )
00590 maxsize = GIn()[i].nelem();
00591
00592
00593 for (Index i=0; i<GIn().nelem(); ++i)
00594 {
00595 os << "\t" << setw((int)maxsize)
00596 << GIn()[i] << " = \n";
00597 }
00598
00599 os << '}';
00600
00601 return os;
00602 }
00603
00604
00606
00611 void limit_line_length( ostream& os,
00612 ostringstream& curline,
00613 ostringstream& token,
00614 const String& indent,
00615 size_t linelen)
00616 {
00617 if (indent.length() + curline.str().length() + token.str().length() > linelen)
00618 {
00619 os << curline.str() << endl << indent;
00620 curline.str("");
00621 }
00622 curline << token.str();
00623 token.str("");
00624 }
00625
00626
00628 ostream& operator<<(ostream& os, const MdRecord& mdr)
00629 {
00630 extern const ArrayOfString wsv_group_names;
00631 bool first;
00632 ostringstream buf;
00633 ostringstream param;
00634 String indent = "";
00635 const size_t linelen = 68;
00636 bool fit;
00637 size_t lastlen;
00638
00639 os << "\n*-------------------------------------------------------------------*\n"
00640 << "Workspace method = " << mdr.Name() <<
00641 "\n---------------------------------------------------------------------\n"
00642 << "\n" << mdr.Description() << "\n";
00643
00644 if (mdr.Description()[mdr.Description().nelem() - 1] != '\n')
00645 {
00646 os << "\n";
00647 }
00648
00649
00650 while (indent.length() < mdr.Name().length() + 2) indent += ' ';
00651
00652 os << "\nSynopsis:\n\n";
00653 buf << mdr.Name() << "( ";
00654 first = true;
00655 for ( Index i=0; i<mdr.Out().nelem(); ++i )
00656 {
00657 if (first) first=false; else buf << ", ";
00658 param << Workspace::wsv_data[mdr.Out()[i]].Name();
00659
00660 limit_line_length( os, buf, param, indent, linelen );
00661 }
00662
00663 for ( Index i=0; i<mdr.GOutType().nelem(); ++i )
00664 {
00665 if (first) first=false; else buf << ", ";
00666 if (mdr.GOut()[i].length())
00667 param << mdr.GOut()[i];
00668 else
00669 param << "gout" << i;
00670
00671 limit_line_length( os, buf, param, indent, linelen );
00672 }
00673
00674 const ArrayOfIndex &inonly = mdr.InOnly();
00675 for ( Index i=0; i<inonly.nelem(); ++i )
00676 {
00677 if (first) first=false; else buf << ", ";
00678 param << Workspace::wsv_data[inonly[i]].Name();
00679
00680 limit_line_length( os, buf, param, indent, linelen );
00681 }
00682
00683 for ( Index i=0; i<mdr.GInType().nelem(); ++i )
00684 {
00685 if (first) first=false; else buf << ", ";
00686 if (mdr.GIn()[i].length())
00687 {
00688 param << mdr.GIn()[i];
00689 }
00690 else
00691 {
00692 param << "gin" << i;
00693 }
00694
00695 limit_line_length( os, buf, param, indent, linelen );
00696 }
00697 if (buf.str().length()) os << buf.str();
00698
00699 os << " )\n\n\n";
00700
00701 {
00702 bool is_first_author = true;
00703 for (Index i = 0; i < mdr.Authors().nelem(); i++)
00704 {
00705 if (is_first_author)
00706 {
00707 os << "Authors: ";
00708 is_first_author = false;
00709 }
00710 else
00711 os << ", ";
00712
00713 os << mdr.Authors()[i];
00714 }
00715 os << "\n";
00716 }
00717
00718 os << "\n\nVariables:\n\n";
00719
00720
00721
00722
00723
00724 first = true;
00725 indent = String(6);
00726 String desc;
00727 for ( Index i=0; i<mdr.Out().nelem(); ++i )
00728 {
00729 buf.str("");
00730 buf << "OUT ";
00731
00732 buf << Workspace::wsv_data[mdr.Out()[i]].Name();
00733 buf << " (";
00734 buf << wsv_group_names[Workspace::wsv_data[mdr.Out()[i]].Group()];
00735 buf << "): ";
00736
00737 get_short_wsv_description(
00738 desc, Workspace::wsv_data[mdr.Out()[i]].Description());
00739
00740 if (buf.str().length() + desc.length() > linelen)
00741 {
00742 format_paragraph (desc, indent, linelen);
00743 buf << endl << indent << desc;
00744 }
00745 else
00746 {
00747 buf << desc;
00748 }
00749
00750 os << buf.str() << endl;
00751 }
00752
00753 for ( Index i=0; i<mdr.GOut().nelem(); ++i )
00754 {
00755 buf.str("");
00756 buf << "GOUT " << mdr.GOut()[i] << " (";
00757 if (mdr.GOutType()[i] == get_wsv_group_id("Any")
00758 && mdr.GOutSpecType()[i].nelem())
00759 {
00760 bool firstarg = true;
00761 for (Index j = 0; j < mdr.GOutSpecType()[i].nelem(); j++)
00762 {
00763 if (!firstarg) buf << ", "; else firstarg = false;
00764 buf << wsv_group_names[mdr.GOutSpecType()[i][j]];
00765 }
00766 }
00767 else
00768 {
00769 buf << wsv_group_names[mdr.GOutType()[i]];
00770 }
00771
00772 buf << "): ";
00773 desc = buf.str();
00774 lastlen = desc.length();
00775 fit = format_paragraph (desc, indent, linelen);
00776 buf.str("");
00777 os << desc;
00778
00779 desc = mdr.GOutDescription()[i];
00780 if (!fit)
00781 {
00782 format_paragraph (desc, indent, linelen);
00783 buf << endl << indent << desc;
00784 }
00785 else if (lastlen + desc.length() > linelen)
00786 {
00787 format_paragraph (desc, indent, linelen, lastlen);
00788 buf << endl << desc;
00789 }
00790 else
00791 {
00792 buf << desc;
00793 }
00794
00795 os << buf.str() << endl;
00796 }
00797
00798 for ( Index i=0; i<mdr.In().nelem(); ++i )
00799 {
00800 buf.str("");
00801 buf << "IN ";
00802
00803 buf << Workspace::wsv_data[mdr.In()[i]].Name();
00804 buf << " (";
00805 buf << wsv_group_names[Workspace::wsv_data[mdr.In()[i]].Group()];
00806 buf << "): ";
00807
00808 get_short_wsv_description(
00809 desc, Workspace::wsv_data[mdr.In()[i]].Description());
00810
00811 if (buf.str().length() + desc.length() > linelen)
00812 {
00813 format_paragraph (desc, indent, linelen, indent.length());
00814 buf << endl << indent << desc;
00815 }
00816 else
00817 {
00818 buf << desc;
00819 }
00820
00821 os << buf.str() << endl;
00822 }
00823
00824 for ( Index i=0; i<mdr.GIn().nelem(); ++i )
00825 {
00826 buf.str("");
00827 buf << "GIN " << mdr.GIn()[i] << " (";
00828 if (mdr.GInType()[i] == get_wsv_group_id("Any")
00829 && mdr.GInSpecType()[i].nelem())
00830 {
00831 bool firstarg = true;
00832 for (Index j = 0; j < mdr.GInSpecType()[i].nelem(); j++)
00833 {
00834 if (!firstarg) buf << ", "; else firstarg = false;
00835 buf << wsv_group_names[mdr.GInSpecType()[i][j]];
00836 }
00837 }
00838 else
00839 {
00840 buf << wsv_group_names[mdr.GInType()[i]];
00841 }
00842
00843 if (mdr.GInDefault()[i] != NODEF)
00844 {
00845 buf << ", Default: ";
00846 if (mdr.GInType()[i] == get_wsv_group_id ("String"))
00847 {
00848 buf << "\"" << mdr.GInDefault()[i] << "\"";
00849 }
00850 else
00851 {
00852 buf << mdr.GInDefault()[i];
00853 }
00854
00855 }
00856
00857 buf << "): ";
00858 desc = buf.str();
00859 lastlen = desc.length();
00860 fit = format_paragraph (desc, indent, linelen);
00861 buf.str("");
00862 os << desc;
00863
00864 desc = mdr.GInDescription()[i];
00865 if (!fit)
00866 {
00867 format_paragraph (desc, indent, linelen);
00868 buf << endl << indent << desc;
00869 }
00870 else if (lastlen + desc.length() > linelen)
00871 {
00872 format_paragraph (desc, indent, linelen, indent.length());
00873 buf << endl << indent << desc;
00874 }
00875 else
00876 {
00877 buf << desc;
00878 }
00879
00880 os << buf.str() << endl;
00881 }
00882
00883 os << "\n*-------------------------------------------------------------------*\n";
00884
00885 return os;
00886 }
00887