001/* 002* GlobalSection -- Encapsulates the IGES Global Section. 003* 004* Copyright (C) 2010-2016, Joseph A. Huwaldt. 005* All rights reserved. 006* 007* This library is free software; you can redistribute it and/or 008* modify it under the terms of the GNU Lesser General Public 009* License as published by the Free Software Foundation; either 010* version 2.1 of the License, or (at your option) any later version. 011* 012* This library is distributed in the hope that it will be useful, 013* but WITHOUT ANY WARRANTY; without even the implied warranty of 014* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015* Lesser General Public License for more details. 016* 017* You should have received a copy of the GNU Lesser General Public License 018* along with this program; if not, write to the Free Software 019* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 020* Or visit: http://www.gnu.org/licenses/lgpl.html 021* 022* Based on, but heavily modified from, IGESView ( http://ts.nist.gov/Standards/IGES/igesTools.cfm ) 023*/ 024package geomss.geom.reader.iges; 025 026import jahuwaldt.js.param.Parameter; 027import java.io.IOException; 028import java.io.PrintWriter; 029import java.io.RandomAccessFile; 030import java.text.SimpleDateFormat; 031import java.util.Date; 032import javax.measure.quantity.Length; 033import javax.measure.unit.NonSI; 034import javax.measure.unit.SI; 035import javax.measure.unit.Unit; 036 037/** 038 * The GlobalSection class encapsulates the IGES Global Section. This holds 039 * the "global variables" for the file. This class handles initialization, 040 * reading, access, and dumping of the values. 041 * 042 * <p> Modified by: Joseph A. Huwaldt </p> 043 * 044 * @author JDN, Version 1.0 045 * @version April 7, 2016 046 */ 047public class GlobalSection { 048 049 private char Delim = ','; // Parameter delimiter character 050 private char Term = ';'; // Record delimiter character 051 private String PName = ""; // Product identification from sending system 052 private String FName = ""; // File name 053 private String SysID = Constants.RESOURCES.getString("systemID"); // System ID 054 private String TranVrsn = Constants.RESOURCES.getString("tranVersion"); // Preprocessor version 055 private int IntSize = 32; // Number of binary bits for integer representation 056 private int FloatExp = 38; // Max power of ten for float 057 private int FloatMant = 6; // Number of significant digits for float 058 private int DoubleExp = 308; // Max power of ten for double 059 private int DoubleMant = 15; // Number of significant digits for double 060 private String DestName = ""; // Product identification for the receiving system 061 private double ModelScale = 1; // Model space scale 062 private int UnitFlg = 1; // Unit flag (unit code) 063 private String UnitType = "IN"; // Units name 064 private int LineWeights = 1; // Max number of line weight gradations 065 private double LineWidth = 0.01; // Width of max line weight in units 066 private String DateTime = ""; // Date and time of file generation 067 private double Grain = 0.01; // Min granularity of model in units 068 private double MaxValue = 0; // Max coordinate value in units 069 private String Author = ""; // Name of author 070 private String Organization = ""; // Author's organization 071 private int SpecVrsn = 11; // Version of specification for this file 072 private int DraftStd = 0; // Drafting standard of this file 073 private String ModDate = ""; // Date and time of last modification to the model. 074 private String AppProtocol = ""; // Application protocol, application subset, MIL-spec, etc. 075 076 private int start = 0; // Current string index for parsing 077 private String GlobalText = ""; // Global data as a string 078 079 /** 080 * Default constructor. 081 */ 082 public GlobalSection() { 083 } 084 085 /** 086 * Return char parameter from input string. The input string must be in Hollerith form 087 * (1H-), as per the IGES specification, and delimited by the global delimiter 088 * character. 089 * 090 * @param s input string from IGES file. 091 * @return single character 092 */ 093 private char getChar(String s) { 094 String sResult = ""; 095 096 while (s.charAt(start) == ' ') 097 start++; 098 099 // Deal with hitting the terminator right away. 100 int c = s.charAt(start); 101 if (c == Delim || c == Term) { 102 if (c == Delim) 103 ++start; // Advance only if it is the delimiter that is hit. 104 return '\0'; 105 } 106 107 if ((s.charAt(start) != Delim) && (s.charAt(start) != Term) && Character.isDigit(s.charAt(start))) { 108 // Should be in form ##Hchars 109 int sStart = s.indexOf('H', start); 110 String str = s.substring(start, sStart).trim(); 111 int iLen = Integer.parseInt(str); 112 int newstart = sStart + 2 + iLen; 113 114 if (newstart < 0) 115 sResult = ""; 116 else { 117 sResult = s.substring(sStart + 1, newstart - 1); 118 start = newstart - 1; 119 } 120 121 } else { 122 while ((s.charAt(start) != Delim) && (s.charAt(start) != Term)) { 123 sResult = sResult + s.charAt(start); 124 125 if (s.charAt(start + 1) == Term) 126 break; 127 else 128 start++; 129 } 130 131 // Not a proper string, so nullify it 132 sResult = ""; 133 } 134 135 if (s.charAt(start) != Term) 136 start++; 137 138 if (Constants.DEBUG) { 139 System.out.println("getChar - \"" + sResult + "\""); 140 } 141 142 if (sResult.length() == 0) 143 return '\0'; 144 return sResult.charAt(0); 145 } 146 147 /** 148 * Return string parameter from input string. The input may either be in Hollerith 149 * form (nH...), as per the IGES specification delimited by the global delimiter 150 * character or whatever characters are found between the delimiter character are 151 * returned. If the String equals "NULL", then an empty String is returned. 152 * 153 * @param s input string from IGES file. 154 * @return string stripped of Hollerith prefix, or empty string if the input string is 155 * invalid. 156 */ 157 private String getString(String s) { 158 159 while (s.charAt(start) == ' ') 160 start++; 161 162 // Deal with hitting the terminator right away. 163 int c = s.charAt(start); 164 if (c == Delim || c == Term) { 165 if (c == Delim) 166 ++start; // Advance only if it is the delimiter that is hit. 167 return ""; 168 } 169 170 // Pull out everything between the delimiters. 171 int newstart = start + 1; 172 c = s.charAt(newstart); 173 while (c != Delim && c != Term) { 174 ++newstart; 175 c = s.charAt(newstart); 176 } 177 String sResult = s.substring(start, newstart); 178 179 // Now convert from Hollerith form (if necessary). 180 try { 181 // Should be in form ##Hchars 182 int sStart = s.indexOf('H', start); 183 184 int iLen = Integer.parseInt((s.substring(start, sStart)).trim()); 185 int end = sStart + 2 + iLen; 186 187 if (end < 0) 188 sResult = ""; 189 else { 190 sResult = s.substring(sStart + 1, end - 1); 191 if (end - 1 > newstart) 192 newstart = end - 1; 193 } 194 195 } catch (Exception e) { 196 // Do nothing. Keep the entire string. 197 } 198 199 start = newstart; 200 if (s.charAt(start) != Term) 201 start++; 202 203 if ("NULL".equals(sResult)) 204 sResult = ""; 205 206 if (Constants.DEBUG) 207 System.out.println("getString - \"" + sResult + "\""); 208 209 return sResult; 210 } 211 212 /** 213 * Return real parameter from input string. The input string can be of single 214 * (1.0e+010) or double (1.0d+010) precision, and delimited by the global delimiter 215 * character. The field is blank, then Double.NaN is returned. 216 * 217 * @param s input string from IGES file. 218 * @return real number 219 */ 220 private double getReal(String s) { 221 String sResult = ""; 222 223 while (s.charAt(start) == ' ') 224 start++; 225 226 // Deal with hitting the terminator right away. 227 int c = s.charAt(start); 228 if (c == Delim || c == Term) { 229 if (c == Delim) 230 ++start; // Advance only if it is the delimiter that is hit. 231 return Double.NaN; 232 } 233 234 while ((s.charAt(start) != Delim) && (s.charAt(start) != Term)) { 235 sResult = sResult + s.charAt(start); 236 237 if (s.charAt(start + 1) == Term) 238 break; 239 else 240 start++; 241 } 242 243 if (s.charAt(start) != Term) 244 start++; 245 246 sResult = sResult.trim(); 247 248 if (Constants.DEBUG) 249 System.out.println("getReal - \"" + sResult + "\""); 250 251 return Constants.toDouble(sResult); 252 } 253 254 /** 255 * Return integer parameter from input string. The input string can be represent 256 * either a standard integer, or a float value (e.g. 1.000e+010), and delimited by the 257 * global delimiter character. If the field is blank, a 0 is returned. 258 * 259 * @param s input string from IGES file. 260 * @return integer number 261 */ 262 private int getInt(String s) { 263 String sResult = ""; 264 265 while (s.charAt(start) == ' ') 266 start++; 267 268 // Deal with hitting the terminator right away. 269 int c = s.charAt(start); 270 if (c == Delim || c == Term) { 271 if (c == Delim) 272 ++start; // Advance only if it is the delimiter that is hit. 273 return 0; 274 } 275 276 while ((s.charAt(start) != Delim) && (s.charAt(start) != Term)) { 277 sResult = sResult + s.charAt(start); 278 279 if (s.charAt(start + 1) == Term) 280 break; 281 else 282 start++; 283 } 284 285 if (s.charAt(start) != Term) 286 start++; 287 288 sResult = sResult.trim(); 289 290 if (Constants.DEBUG) { 291 System.out.println("getInt - \"" + sResult + "\""); 292 } 293 294 return Constants.toInt(sResult); 295 } 296 297 /** 298 * Return parameter delimiter character. This indicates which character is used to 299 * separate parameter values in the Global and Parameter Data sections. The default 300 * value is “comma.” 301 * 302 * @return parameter delimiter character 303 */ 304 public char getDelim() { 305 return Delim; 306 } 307 308 /** 309 * Return parameter terminator character. This indicates which character denotes the 310 * end of parameters in the Global Section and in each Parameter Data Section entry. 311 * The default value is “semicolon.” 312 * 313 * @return parameter terminator character 314 */ 315 public char getTerm() { 316 return Term; 317 } 318 319 /** 320 * Return the IGES product identification from the sending system for this Part. This 321 * contains the name or identifier which is used by the sender reference this product. 322 * 323 * @return The IGES product identification of the sending system. 324 */ 325 public String getProductName() { 326 return PName; 327 } 328 329 /** 330 * Set the IGES product identification from the sending system for this Part. This 331 * contains the name or identifier which is used by the sender reference this product. 332 * 333 * @param productName The name the sender uses to reference this product (Part). 334 */ 335 public void setProductName(String productName) { 336 PName = productName; 337 } 338 339 /** 340 * Return the IGES file name record which contains the name of the exchange file. 341 * 342 * @return The IGES file name 343 */ 344 public String getFileName() { 345 return FName; 346 } 347 348 /** 349 * Set the file name of the exchange file. 350 * 351 * @param fileName The file name for the exchange file. 352 */ 353 public void setFileName(String fileName) { 354 FName = fileName; 355 } 356 357 /** 358 * Return the Native System ID which identifies the native system software which 359 * created the native format file used to generate this exchange file. 360 * 361 * @return The Native System ID 362 */ 363 public String getSystemID() { 364 return SysID; 365 } 366 367 /** 368 * Set the Native System ID which identifies the native system software which created 369 * the native format file used to generate this exchange file. 370 * 371 * @param sysID The Native System ID to set. 372 */ 373 public void setSystemID(String sysID) { 374 SysID = sysID; 375 } 376 377 /** 378 * Return the IGES file preprocessor version. This uniquely identifies the version or 379 * release date of the preprocessor which created this file. 380 * @return The IGES file preprocessor version 381 */ 382 public String getPreprocesorVersion() { 383 return TranVrsn; 384 } 385 386 /** 387 * Set the preprocessor version. This uniquely identifies the version or release date 388 * of the preprocessor which created this file. 389 * 390 * @param version The IGES file preprocessor version to set. 391 */ 392 public void setPreprocessorVersion(String version) { 393 TranVrsn = version; 394 } 395 396 /** 397 * Return the model length unit's used in the IGES file. 398 * 399 * @return The length units used in this transfer. 400 */ 401 public Unit<Length> getUnit() { 402 Unit unit = NonSI.INCH; 403 switch (UnitFlg) { 404 case 2: 405 unit = SI.MILLIMETER; 406 break; 407 case 3: 408 // The unit is identified by symbol, not by code. 409 switch (UnitType) { 410 case "MM": 411 unit = SI.MILLIMETER; 412 break; 413 case "FT": 414 unit = NonSI.FOOT; 415 break; 416 case "MI": 417 unit = NonSI.MILE; 418 break; 419 case "M": 420 unit = SI.METER; 421 break; 422 case "KM": 423 unit = SI.KILOMETER; 424 break; 425 case "MIL": 426 unit = NonSI.INCH.times(0.001); 427 break; 428 case "UM": 429 unit = SI.METER.times(1.e-6); 430 break; 431 case "CM": 432 unit = SI.CENTIMETER; 433 break; 434 case "UIN": 435 unit = NonSI.INCH.times(1.e-6); 436 break; 437 } 438 break; 439 case 4: 440 unit = NonSI.FOOT; 441 break; 442 case 5: 443 unit = NonSI.MILE; 444 break; 445 case 6: 446 unit = SI.METER; 447 break; 448 case 7: 449 unit = SI.KILOMETER; 450 break; 451 case 8: 452 unit = NonSI.INCH.times(0.001); 453 break; 454 case 9: 455 unit = SI.METER.times(1.e-6); 456 break; 457 case 10: 458 unit = SI.CENTIMETER; 459 break; 460 case 11: 461 unit = NonSI.INCH.times(1.e-6); 462 break; 463 } 464 return unit; 465 } 466 467 /** 468 * Set the model length unit's used in the IGES file. 469 * 470 * @param unit The model length unit to save the data in. 471 */ 472 public void setUnit(Unit<Length> unit) { 473 // Turn the input unit into a unit flag and type value. 474 if (SI.MILLIMETER.equals(unit)) { 475 UnitFlg = 2; 476 UnitType = "MM"; 477 478 } else if (NonSI.FOOT.equals(unit)) { 479 UnitFlg = 4; 480 UnitType = "FT"; 481 482 } else if (NonSI.MILE.equals(unit)) { 483 UnitFlg = 5; 484 UnitType = "MI"; 485 486 } else if (SI.METER.equals(unit)) { 487 UnitFlg = 6; 488 UnitType = "M"; 489 490 } else if (SI.KILOMETER.equals(unit)) { 491 UnitFlg = 7; 492 UnitType = "KM"; 493 494 } else if (NonSI.INCH.times(0.001).equals(unit)) { 495 UnitFlg = 8; 496 UnitType = "MIL"; 497 498 } else if (SI.METER.times(1.e-6).equals(unit)) { 499 UnitFlg = 9; 500 UnitType = "UM"; 501 502 } else if (SI.CENTIMETER.equals(unit)) { 503 UnitFlg = 10; 504 UnitType = "CM"; 505 506 } else if (NonSI.INCH.times(1.e-6).equals(unit)) { 507 UnitFlg = 11; 508 UnitType = "UIN"; 509 510 } else { 511 // Default to inches. 512 UnitFlg = 1; 513 UnitType = "IN"; 514 } 515 } 516 517 /** 518 * Return number of line weights. 519 * 520 * @return number of line weights 521 */ 522 public int getLineWeights() { 523 return LineWeights; 524 } 525 526 /** 527 * Return maximum line width. 528 * 529 * @return maximum line width 530 */ 531 public double getLineWidth() { 532 return LineWidth; 533 } 534 535 /** 536 * Return the date and time of IGES file generation. 537 * 538 * @return The date and time of IGES file generation 539 */ 540 public String getDateTime() { 541 return DateTime; 542 } 543 544 /** 545 * Return Minimum User-Intended Resolution Granularity value. This specifies the 546 * smallest distance between coordinates, in model-space units, that the receiving 547 * system shall consider as discernible. 548 * 549 * @return the granularity value 550 */ 551 public double getGrain() { 552 return Grain; 553 } 554 555 /** 556 * Return Minimum User-Intended Resolution Granularity value. This specifies the 557 * smallest distance between coordinates, in model-space units, that the receiving 558 * system shall consider as discernible. 559 * 560 * @return the granularity value as a Parameter object. 561 */ 562 public Parameter<Length> getGrainParameter() { 563 return Parameter.valueOf(Grain, getUnit()); 564 } 565 566 /** 567 * Set the Minimum User-Intended Resolution or Granularity value. This specifies the 568 * smallest distance between coordinates, in model-space units, that the receiving 569 * system shall consider as discernible. 570 * 571 * @param value The granularity value 572 */ 573 public void setGrain(double value) { 574 Grain = value; 575 } 576 577 /** 578 * Return the date and time of the last modification of the model in this exchange 579 * file. 580 * @return The date and time of the last modification 581 */ 582 public String getModDateTime() { 583 return ModDate; 584 } 585 586 /** 587 * Set the date and time of the last modification of the model in this exchange file. 588 * 589 * @param modDate The date and time of the last modification as a String. 590 */ 591 public void setModDateTime(String modDate) { 592 ModDate = modDate; 593 } 594 595 /** 596 * Return the name of the person who created this exchange file. 597 * 598 * @return the author identification 599 */ 600 public String getAuthor() { 601 return Author; 602 } 603 604 /** 605 * Set the name of the person who created this exchange file. 606 * 607 * @param author The name of the author of the file. 608 */ 609 public void setAuthor(String author) { 610 Author = author; 611 } 612 613 /** 614 * Return the name of the organization or group with whom the author is associated. 615 * 616 * @return the author's organization identification 617 */ 618 public String getOrganization() { 619 return Organization; 620 } 621 622 /** 623 * Set the name of the organization or group with whom the author is associated. 624 * 625 * @param organization The name of the organization the author is associated with. 626 */ 627 public void setOrganization(String organization) { 628 Organization = organization; 629 } 630 631 /** 632 * Return the version of the IGES Specification to which the data in this file complies. 633 * 634 * @return The version of the IGES Specification to which the file complies. 635 */ 636 public int getSpecVersion() { 637 return SpecVrsn; 638 } 639 640 641 /** 642 * Read the Global Section from the input file. This method can handle missing or 643 * incorrect fields. 644 * 645 * @param in input file 646 * @throws IOException if there is any problem reading the IGES file. 647 */ 648 public void read(RandomAccessFile in) throws IOException { 649 boolean ok = false; 650 651 StringBuilder buffer = new StringBuilder(); 652 while (true) { 653 long curloc = in.getFilePointer(); 654 String line = Constants.myReadLine(in); 655 if (line.charAt(Constants.SECTID_COL) == 'G') { 656 // Deal with non-standard blank spaces between PDID_COL and SECTID_COL. 657 int end = Constants.SECTID_COL; 658 String rhs = line.substring(Constants.PDID_COL,Constants.SECTID_COL).trim(); 659 if (rhs.length() < 1) 660 end = Constants.PDID_COL; 661 buffer.append( line.substring(0,end) ); 662 } else { 663 in.seek(curloc); 664 ok = true; 665 break; 666 } 667 } 668 String s = buffer.toString(); 669 670 if (ok) { 671 Delim = getChar(s); if (Delim == '\0') Delim = ','; 672 Term = getChar(s); if (Term == '\0') Term = ';'; 673 PName = getString(s); 674 FName = getString(s); 675 SysID = getString(s); 676 TranVrsn = getString(s); 677 IntSize = getInt(s); 678 FloatExp = getInt(s); 679 FloatMant = getInt(s); 680 DoubleExp = getInt(s); 681 DoubleMant = getInt(s); 682 DestName = getString(s); 683 ModelScale = getReal(s); 684 UnitFlg = getInt(s); 685 UnitType = getString(s); 686 LineWeights = getInt(s); 687 LineWidth = getReal(s); 688 DateTime = getString(s); 689 Grain = getReal(s); 690 MaxValue = getReal(s); 691 if (Double.isNaN(MaxValue)) 692 MaxValue = 0; 693 Author = getString(s); 694 Organization = getString(s); 695 SpecVrsn = getInt(s); 696 DraftStd = getInt(s); 697 ModDate = getString(s); 698 AppProtocol = getString(s); 699 } 700 701 StringBuilder outStr = new StringBuilder(); 702 outStr.append("Delim = \""); outStr.append(Delim); outStr.append("\"\n"); 703 outStr.append("Term = \""); outStr.append(Term); outStr.append("\"\n"); 704 outStr.append("PName = \""); outStr.append(PName); outStr.append("\"\n"); 705 outStr.append("FName = \""); outStr.append(FName); outStr.append("\"\n"); 706 outStr.append("SysID = \""); outStr.append(SysID); outStr.append("\"\n"); 707 outStr.append("TranVrsn = \""); outStr.append(TranVrsn); outStr.append("\"\n"); 708 outStr.append("IntSize = "); outStr.append(IntSize); outStr.append("\n"); 709 outStr.append("FloatExp = "); outStr.append(FloatExp); outStr.append("\n"); 710 outStr.append("FloatMant = "); outStr.append(FloatMant); outStr.append("\n"); 711 outStr.append("DoubleExp = "); outStr.append(DoubleExp); outStr.append("\n"); 712 outStr.append("DoubleMant = "); outStr.append(DoubleMant); outStr.append("\n"); 713 outStr.append("DestName = \""); outStr.append(DestName); outStr.append("\"\n"); 714 outStr.append("ModelScale = "); outStr.append(ModelScale); outStr.append("\n"); 715 outStr.append("UnitFlg = "); outStr.append(UnitFlg); outStr.append("\n"); 716 outStr.append("UnitType = \""); outStr.append(UnitType); outStr.append("\"\n"); 717 outStr.append("LineWeights = "); outStr.append(LineWeights); outStr.append("\n"); 718 outStr.append("LineWidth = "); outStr.append(LineWidth); outStr.append("\n"); 719 outStr.append("DateTime = \""); outStr.append(DateTime); outStr.append("\"\n"); 720 outStr.append("Grain = "); outStr.append(Grain); outStr.append("\n"); 721 outStr.append("MaxValue = "); outStr.append(MaxValue); outStr.append("\n"); 722 outStr.append("Author = \""); outStr.append(Author); outStr.append("\"\n"); 723 outStr.append("Organization = \""); outStr.append(Organization);outStr.append("\"\n"); 724 outStr.append("SpecVrsn = "); outStr.append(SpecVrsn); outStr.append("\n"); 725 outStr.append("DraftStd = "); outStr.append(DraftStd); outStr.append("\n"); 726 outStr.append("ModDate = \""); outStr.append(ModDate); outStr.append("\n"); 727 outStr.append("AppProtocol = \""); outStr.append(AppProtocol); outStr.append("\"\n"); 728 729 GlobalText = outStr.toString(); 730 } 731 732 /** 733 * Write the Global Section to the specified writer. 734 * 735 * @param writer The PrintWriter to write the Global Section to. 736 * @return The number of lines written out to the global section. 737 * @throws IOException if there is any problem writing the section. 738 */ 739 public int write(PrintWriter writer) throws IOException { 740 741 // Construct the current date/time for output. 742 SimpleDateFormat dformat = new SimpleDateFormat("yyyyMMdd.HHmmss"); 743 DateTime = dformat.format(new Date()); 744 745 // Construct a long string with all the section's parameters in it. 746 StringBuilder buffer = new StringBuilder(); 747 buffer.append(makeHollerith(Delim)); buffer.append(Delim); 748 buffer.append(makeHollerith(Term)); buffer.append(Delim); 749 buffer.append(makeHollerith(PName)); buffer.append(Delim); 750 buffer.append(makeHollerith(FName)); buffer.append(Delim); 751 buffer.append(makeHollerith(SysID)); buffer.append(Delim); 752 buffer.append(makeHollerith(TranVrsn)); buffer.append(Delim); 753 buffer.append(IntSize); buffer.append(Delim); 754 buffer.append(FloatExp); buffer.append(Delim); 755 buffer.append(FloatMant); buffer.append(Delim); 756 buffer.append(DoubleExp); buffer.append(Delim); 757 buffer.append(DoubleMant); buffer.append(Delim); 758 buffer.append(makeHollerith(DestName)); buffer.append(Delim); 759 buffer.append(ModelScale); buffer.append(Delim); 760 buffer.append(UnitFlg); buffer.append(Delim); 761 buffer.append(makeHollerith(UnitType)); buffer.append(Delim); 762 buffer.append(LineWeights); buffer.append(Delim); 763 buffer.append(LineWidth); buffer.append(Delim); 764 buffer.append(makeHollerith(DateTime)); buffer.append(Delim); 765 buffer.append(Grain); buffer.append(Delim); 766 buffer.append(MaxValue); buffer.append(Delim); 767 buffer.append(makeHollerith(Author)); buffer.append(Delim); 768 buffer.append(makeHollerith(Organization)); buffer.append(Delim); 769 buffer.append(SpecVrsn); buffer.append(Delim); 770 buffer.append(DraftStd); buffer.append(Delim); 771 buffer.append(makeHollerith(ModDate)); buffer.append(Delim); 772 buffer.append(makeHollerith(AppProtocol)); buffer.append(Term); 773 774 // Now write out the string of data to form the global section. 775 int index = Constants.writeSection(writer, 1, "", 'G', buffer); 776 777 return index - 1; 778 } 779 780 /** 781 * Take the input and turn it into a Hollerith String. 782 */ 783 private static String makeHollerith(String input) { 784 if (input.length() == 0) 785 return input; 786 StringBuilder buffer = new StringBuilder(); 787 buffer.append(input.length()); 788 buffer.append("H"); 789 buffer.append(input); 790 return buffer.toString(); 791 } 792 793 /** 794 * Take the input and turn it into a Hollerith String. 795 */ 796 private static String makeHollerith(char input) { 797 StringBuilder buffer = new StringBuilder(); 798 buffer.append(1); 799 buffer.append("H"); 800 buffer.append(input); 801 return buffer.toString(); 802 } 803 804 /** 805 * Dump to String. 806 * 807 * @return String containing the resulting text. 808 */ 809 @Override 810 public String toString() { 811 return GlobalText; 812 } 813}