001 /* 002 * Copyright 2011 The Kuali Foundation. 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 /* 017 * Created on Feb 13, 2006 018 * 019 */ 020 package org.kuali.kfs.module.purap.businessobject; 021 022 import java.math.BigDecimal; 023 import java.text.ParseException; 024 import java.text.SimpleDateFormat; 025 import java.util.ArrayList; 026 import java.util.Collections; 027 import java.util.Comparator; 028 import java.util.Date; 029 import java.util.Iterator; 030 import java.util.List; 031 import java.util.Locale; 032 033 import org.apache.commons.lang.builder.ToStringBuilder; 034 import org.kuali.kfs.module.purap.PurapConstants; 035 import org.kuali.kfs.module.purap.service.ElectronicInvoiceMappingService; 036 import org.kuali.kfs.module.purap.util.ElectronicInvoiceUtils; 037 038 public class ElectronicInvoiceOrder { 039 private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(ElectronicInvoiceOrder.class); 040 041 public static boolean INVOICE_ORDER_REJECTED = true; 042 public static boolean INVOICE_ORDER_NOT_REJECTED = false; 043 044 // the following fields come from the <InvoiceDetailOrderInfo> tag 045 private String orderReferenceOrderID; 046 private String orderReferenceDocumentRefPayloadID; 047 private String orderReferenceDocumentRef; 048 private String masterAgreementReferenceID; 049 private Date masterAgreementReferenceDate; 050 private String masterAgreementReferenceDateString; 051 private String masterAgreementIDInfoID; 052 private Date masterAgreementIDInfoDate; 053 private String masterAgreementIDInfoDateString; 054 private String orderIDInfoID; 055 private Date orderIDInfoDate; 056 private String orderIDInfoDateString; 057 private String supplierOrderInfoID; 058 059 private String invoicePurchaseOrderID; 060 private String orderReferenceOrderDateString; 061 private Integer purchaseOrderID = null; 062 private String purchaseOrderCampusCode; 063 064 private boolean rejected = INVOICE_ORDER_NOT_REJECTED; 065 private List orderRejectReasons = new ArrayList(); 066 067 private List invoiceItems = new ArrayList(); 068 069 public ElectronicInvoiceOrder() { 070 super(); 071 } 072 073 public ElectronicInvoiceItem getElectronicInvoiceItemByPOLineNumber(Integer poLineNumber) { 074 for (Iterator iter = this.invoiceItems.iterator(); iter.hasNext();) { 075 ElectronicInvoiceItem eii = (ElectronicInvoiceItem) iter.next(); 076 if ((poLineNumber.compareTo(eii.getReferenceLineNumberInteger())) == 0) { 077 return eii; 078 } 079 } 080 return null; 081 } 082 083 /** 084 * This method takes in a roleID string and an addressName (constants from mapping file) 085 * and returns a valid ElectronicInvoicePostalAddress or null if not found. If the addressName string 086 * is null then the roleID is used to find the first available 087 * 088 * @param roleID Cxml role id attribute value 089 * @param addressName Cxml name attribute of postaladdress tag 090 * @return CxmlPostal Address relating to given parameters 091 */ 092 public ElectronicInvoicePostalAddress getCxmlPostalAddressByRoleID(String roleID,String addressName) { 093 if (roleID != null) { 094 ElectronicInvoiceContact contact = this.getCxmlContactByRoleID(roleID); 095 if (contact != null) { 096 for (Iterator iterator = contact.getPostalAddresses().iterator(); iterator.hasNext();) { 097 ElectronicInvoicePostalAddress cpa = (ElectronicInvoicePostalAddress) iterator.next(); 098 if (addressName == null) { 099 return cpa; 100 } else { 101 if (addressName.equalsIgnoreCase(cpa.getName())) { 102 return cpa; 103 } 104 } 105 } 106 } 107 } 108 return null; 109 } 110 111 public ElectronicInvoiceContact getCxmlContactByRoleID(String roleID) { 112 if (roleID != null) { 113 for (Iterator itemIter = this.invoiceItems.iterator(); itemIter.hasNext();) { 114 ElectronicInvoiceItem eii = (ElectronicInvoiceItem) itemIter.next(); 115 for (Iterator iter = eii.getInvoiceShippingContacts().iterator(); iter.hasNext();) { 116 ElectronicInvoiceContact contact = (ElectronicInvoiceContact) iter.next(); 117 if (roleID.equalsIgnoreCase(contact.getRole())) { 118 return contact; 119 } 120 } 121 } 122 } 123 return null; 124 } 125 /** 126 * This method returns the first shipping date found in the list of items. This 127 * is called if shipping information is in line. Since system only allows for one 128 * shipping date per invoice-order we take the first date we find 129 * 130 * @return Date defining first shipping date found or null if none are found 131 */ 132 public Date getInvoiceShippingDate() { 133 for (Iterator iter = this.invoiceItems.iterator(); iter.hasNext();) { 134 ElectronicInvoiceItem eii = (ElectronicInvoiceItem) iter.next(); 135 Date testDate = eii.getShippingDate(); 136 if (testDate != null) { 137 return testDate; 138 } 139 } 140 return null; 141 } 142 143 /** 144 * This method returns the first shipping date string found in the list of items. This 145 * is called if shipping information is in line. Since system only allows for one shipping 146 * date per invoice-order we take the first date string we find 147 * 148 * @return Date defining first shipping date found or null if none are found 149 */ 150 public String getInvoiceShippingDateString() { 151 for (Iterator iter = this.invoiceItems.iterator(); iter.hasNext();) { 152 ElectronicInvoiceItem eii = (ElectronicInvoiceItem) iter.next(); 153 String testDateString = eii.getShippingDateString(); 154 if ( (testDateString != null) && (!("".equals(testDateString))) ) { 155 return testDateString; 156 } 157 } 158 return null; 159 } 160 161 public String getInvoiceTaxDescription() { 162 BigDecimal total = BigDecimal.ZERO; 163 for (Iterator iter = this.invoiceItems.iterator(); iter.hasNext();) { 164 ElectronicInvoiceItem eii = (ElectronicInvoiceItem) iter.next(); 165 BigDecimal taxAmount = eii.getInvoiceLineTaxAmountBigDecimal(); 166 if ( (taxAmount != null) && (BigDecimal.ZERO.compareTo(taxAmount) != 0) ) { 167 return eii.getTaxDescription(); 168 } 169 } 170 return null; 171 } 172 173 public String getInvoiceShippingDescription() { 174 BigDecimal total = BigDecimal.ZERO; 175 for (Iterator iter = this.invoiceItems.iterator(); iter.hasNext();) { 176 ElectronicInvoiceItem eii = (ElectronicInvoiceItem) iter.next(); 177 BigDecimal shippingAmount = eii.getInvoiceLineShippingAmountBigDecimal(); 178 if ( (shippingAmount != null) && (BigDecimal.ZERO.compareTo(shippingAmount) != 0) ) { 179 return PurapConstants.ElectronicInvoice.DEFAULT_SHIPPING_DESCRIPTION; 180 } 181 } 182 return null; 183 } 184 185 public String getInvoiceSpecialHandlingDescription() { 186 BigDecimal total = BigDecimal.ZERO; 187 for (Iterator iter = this.invoiceItems.iterator(); iter.hasNext();) { 188 ElectronicInvoiceItem eii = (ElectronicInvoiceItem) iter.next(); 189 BigDecimal specialHandlingAmount = eii.getInvoiceLineSpecialHandlingAmountBigDecimal(); 190 if ( (specialHandlingAmount != null) && (BigDecimal.ZERO.compareTo(specialHandlingAmount) != 0) ) { 191 return PurapConstants.ElectronicInvoice.DEFAULT_SPECIAL_HANDLING_DESCRIPTION; 192 } 193 } 194 return null; 195 } 196 197 198 public BigDecimal getInvoiceSubTotalAmount() { 199 BigDecimal total = BigDecimal.ZERO; 200 for (Iterator iter = this.invoiceItems.iterator(); iter.hasNext();) { 201 ElectronicInvoiceItem eii = (ElectronicInvoiceItem) iter.next(); 202 total = total.add(eii.getInvoiceLineSubTotalAmountBigDecimal()); 203 } 204 return total; 205 } 206 207 public BigDecimal getInvoiceTaxAmount() { 208 BigDecimal total = BigDecimal.ZERO; 209 for (Iterator iter = this.invoiceItems.iterator(); iter.hasNext();) { 210 ElectronicInvoiceItem eii = (ElectronicInvoiceItem) iter.next(); 211 total = total.add(eii.getInvoiceLineTaxAmountBigDecimal()); 212 } 213 return total; 214 } 215 216 public BigDecimal getInvoiceSpecialHandlingAmount() { 217 BigDecimal total = BigDecimal.ZERO; 218 for (Iterator iter = this.invoiceItems.iterator(); iter.hasNext();) { 219 ElectronicInvoiceItem eii = (ElectronicInvoiceItem) iter.next(); 220 total = total.add(eii.getInvoiceLineSpecialHandlingAmountBigDecimal()); 221 } 222 return total; 223 } 224 225 public BigDecimal getInvoiceShippingAmount() { 226 BigDecimal total = BigDecimal.ZERO; 227 for (Iterator iter = this.invoiceItems.iterator(); iter.hasNext();) { 228 ElectronicInvoiceItem eii = (ElectronicInvoiceItem) iter.next(); 229 total = total.add(eii.getInvoiceLineShippingAmountBigDecimal()); 230 } 231 return total; 232 } 233 234 public BigDecimal getInvoiceGrossAmount() { 235 BigDecimal total = BigDecimal.ZERO; 236 for (Iterator iter = this.invoiceItems.iterator(); iter.hasNext();) { 237 ElectronicInvoiceItem eii = (ElectronicInvoiceItem) iter.next(); 238 total = total.add(eii.getInvoiceLineGrossAmountBigDecimal()); 239 } 240 return total; 241 } 242 243 public BigDecimal getInvoiceDiscountAmount() { 244 BigDecimal total = BigDecimal.ZERO; 245 for (Iterator iter = this.invoiceItems.iterator(); iter.hasNext();) { 246 ElectronicInvoiceItem eii = (ElectronicInvoiceItem) iter.next(); 247 total = total.add(eii.getInvoiceLineDiscountAmountBigDecimal()); 248 } 249 return total; 250 } 251 252 public BigDecimal getInvoiceNetAmount() { 253 BigDecimal total = BigDecimal.ZERO; 254 for (Iterator iter = this.invoiceItems.iterator(); iter.hasNext();) { 255 ElectronicInvoiceItem eii = (ElectronicInvoiceItem) iter.next(); 256 total = total.add(eii.getInvoiceLineNetAmountBigDecimal()); 257 } 258 return total; 259 } 260 261 public void addRejectReasonToList(ElectronicInvoiceRejectReason reason) { 262 this.orderRejectReasons.add(reason); 263 } 264 265 /** 266 * Altered for special circumstances 267 * 268 * @param masterAgreementIDInfoDateString The masterAgreementIDInfoDateString to set. 269 */ 270 public void setMasterAgreementIDInfoDateString(String masterAgreementIDInfoDateString) { 271 this.masterAgreementIDInfoDateString = masterAgreementIDInfoDateString; 272 /*if ( (masterAgreementIDInfoDateString != null) && (!("".equals(masterAgreementIDInfoDateString))) ) { 273 SimpleDateFormat sdf = new SimpleDateFormat(PurapConstants.ElectronicInvoice.CXML_DATE_FORMAT, Locale.US); 274 try { 275 this.masterAgreementIDInfoDate = sdf.parse(masterAgreementIDInfoDateString); 276 } catch (ParseException e) { 277 // setting invoice date to null to identify problem 278 LOG.error("setInvoiceDateString() SimpleDateFormat parser error attempting to set invalid date string " + masterAgreementIDInfoDateString + " in masterAgreementIDInfoDate field... setting date to null"); 279 this.masterAgreementIDInfoDate = null; 280 } 281 } else { 282 this.masterAgreementIDInfoDate = null; 283 }*/ 284 setMasterAgreementIDInfoDate(ElectronicInvoiceUtils.getDate(masterAgreementIDInfoDateString)); 285 } 286 /** 287 * Altered for special circumstances 288 * 289 * @param masterAgreementReferenceDateString The masterAgreementReferenceDateString to set. 290 */ 291 public void setMasterAgreementReferenceDateString(String masterAgreementReferenceDateString) { 292 this.masterAgreementReferenceDateString = masterAgreementReferenceDateString; 293 /*if ( (masterAgreementReferenceDateString != null) && (!("".equals(masterAgreementReferenceDateString))) ) { 294 SimpleDateFormat sdf = new SimpleDateFormat(PurapConstants.ElectronicInvoice.CXML_DATE_FORMAT, Locale.US); 295 try { 296 this.masterAgreementReferenceDate = sdf.parse(masterAgreementReferenceDateString); 297 } catch (ParseException e) { 298 // setting invoice date to null to identify problem 299 LOG.error("setInvoiceDateString() SimpleDateFormat parser error attempting to set invalid date string " + masterAgreementReferenceDateString + " in masterAgreementReferenceDate field... setting date to null"); 300 this.masterAgreementReferenceDate = null; 301 } 302 } else { 303 this.masterAgreementIDInfoDate = null; 304 }*/ 305 setMasterAgreementIDInfoDate(ElectronicInvoiceUtils.getDate(masterAgreementReferenceDateString)); 306 } 307 /** 308 * Altered for special circumstances 309 * 310 * @param orderIDInfoDateString The orderIDInfoDateString to set. 311 */ 312 public void setOrderIDInfoDateString(String orderIDInfoDateString) { 313 this.orderIDInfoDateString = orderIDInfoDateString; 314 /*if ( (orderIDInfoDateString != null) && (!("".equals(orderIDInfoDateString))) ) { 315 SimpleDateFormat sdf = new SimpleDateFormat(PurapConstants.ElectronicInvoice.CXML_DATE_FORMAT, Locale.US); 316 try { 317 this.orderIDInfoDate = sdf.parse(orderIDInfoDateString); 318 } catch (ParseException e) { 319 // setting invoice date to null to identify problem 320 LOG.error("setInvoiceDateString() SimpleDateFormat parser error attempting to set invalid date string " + orderIDInfoDateString + " in orderIDInfoDate field... setting date to null"); 321 this.orderIDInfoDate = null; 322 } 323 } else { 324 this.orderIDInfoDate = null; 325 }*/ 326 setOrderIDInfoDate(ElectronicInvoiceUtils.getDate(orderIDInfoDateString)); 327 } 328 /** 329 * @return Returns the invoiceItems. 330 */ 331 public List<ElectronicInvoiceItem> getInvoiceItems() { 332 return invoiceItems; 333 } 334 /** 335 * @param invoiceItems The invoiceItems to set. 336 */ 337 public void setInvoiceItems(List<ElectronicInvoiceItem> invoiceItems) { 338 this.invoiceItems = invoiceItems; 339 } 340 /** 341 * @return Returns the invoicePurchaseOrderID. 342 */ 343 public String getInvoicePurchaseOrderID() { 344 return invoicePurchaseOrderID; 345 } 346 /** 347 * @param invoicePurchaseOrderID The invoicePurchaseOrderID to set. 348 */ 349 public void setInvoicePurchaseOrderID(String invoicePurchaseOrderID) { 350 this.invoicePurchaseOrderID = invoicePurchaseOrderID; 351 } 352 /** 353 * @return Returns the masterAgreementIDInfoDate. 354 */ 355 public Date getMasterAgreementIDInfoDate() { 356 return masterAgreementIDInfoDate; 357 } 358 /** 359 * @param masterAgreementIDInfoDate The masterAgreementIDInfoDate to set. 360 */ 361 public void setMasterAgreementIDInfoDate(Date masterAgreementIDInfoDate) { 362 this.masterAgreementIDInfoDate = masterAgreementIDInfoDate; 363 } 364 /** 365 * @return Returns the masterAgreementIDInfoID. 366 */ 367 public String getMasterAgreementIDInfoID() { 368 return masterAgreementIDInfoID; 369 } 370 /** 371 * @param masterAgreementIDInfoID The masterAgreementIDInfoID to set. 372 */ 373 public void setMasterAgreementIDInfoID(String masterAgreementIDInfoID) { 374 this.masterAgreementIDInfoID = masterAgreementIDInfoID; 375 } 376 /** 377 * @return Returns the masterAgreementReferenceDate. 378 */ 379 public Date getMasterAgreementReferenceDate() { 380 return masterAgreementReferenceDate; 381 } 382 /** 383 * @param masterAgreementReferenceDate The masterAgreementReferenceDate to set. 384 */ 385 public void setMasterAgreementReferenceDate(Date masterAgreementReferenceDate) { 386 this.masterAgreementReferenceDate = masterAgreementReferenceDate; 387 } 388 /** 389 * @return Returns the masterAgreementReferenceID. 390 */ 391 public String getMasterAgreementReferenceID() { 392 return masterAgreementReferenceID; 393 } 394 /** 395 * @param masterAgreementReferenceID The masterAgreementReferenceID to set. 396 */ 397 public void setMasterAgreementReferenceID(String masterAgreementReferenceID) { 398 this.masterAgreementReferenceID = masterAgreementReferenceID; 399 } 400 /** 401 * @return Returns the orderIDInfoDate. 402 */ 403 public Date getOrderIDInfoDate() { 404 return orderIDInfoDate; 405 } 406 /** 407 * @param orderIDInfoDate The orderIDInfoDate to set. 408 */ 409 public void setOrderIDInfoDate(Date orderIDInfoDate) { 410 this.orderIDInfoDate = orderIDInfoDate; 411 } 412 /** 413 * @return Returns the orderIDInfoID. 414 */ 415 public String getOrderIDInfoID() { 416 return orderIDInfoID; 417 } 418 /** 419 * @param orderIDInfoID The orderIDInfoID to set. 420 */ 421 public void setOrderIDInfoID(String orderIDInfoID) { 422 this.orderIDInfoID = orderIDInfoID; 423 } 424 /** 425 * @return Returns the orderReferenceDocumentRef. 426 */ 427 public String getOrderReferenceDocumentRef() { 428 return orderReferenceDocumentRef; 429 } 430 /** 431 * @param orderReferenceDocumentRef The orderReferenceDocumentRef to set. 432 */ 433 public void setOrderReferenceDocumentRef(String orderReferenceDocumentRef) { 434 this.orderReferenceDocumentRef = orderReferenceDocumentRef; 435 } 436 /** 437 * @return Returns the orderReferenceDocumentRefPayloadID. 438 */ 439 public String getOrderReferenceDocumentRefPayloadID() { 440 return orderReferenceDocumentRefPayloadID; 441 } 442 /** 443 * @param orderReferenceDocumentRefPayloadID The orderReferenceDocumentRefPayloadID to set. 444 */ 445 public void setOrderReferenceDocumentRefPayloadID(String orderReferenceDocumentRefPayloadID) { 446 this.orderReferenceDocumentRefPayloadID = orderReferenceDocumentRefPayloadID; 447 } 448 /** 449 * @return Returns the orderReferenceOrderID. 450 */ 451 public String getOrderReferenceOrderID() { 452 return orderReferenceOrderID; 453 } 454 /** 455 * @param orderReferenceOrderID The orderReferenceOrderID to set. 456 */ 457 public void setOrderReferenceOrderID(String orderReferenceOrderID) { 458 this.orderReferenceOrderID = orderReferenceOrderID; 459 } 460 /** 461 * @return Returns the orderRejectReasons. 462 */ 463 public List<ElectronicInvoiceRejectReason> getOrderRejectReasons() { 464 return orderRejectReasons; 465 } 466 /** 467 * @param orderRejectReasons The orderRejectReasons to set. 468 */ 469 public void setOrderRejectReasons(List<ElectronicInvoiceRejectReason> orderRejectReasons) { 470 this.orderRejectReasons = orderRejectReasons; 471 } 472 /** 473 * @return Returns the purchaseOrderCampusCode. 474 */ 475 public String getPurchaseOrderCampusCode() { 476 return purchaseOrderCampusCode; 477 } 478 /** 479 * @param purchaseOrderCampusCode The purchaseOrderCampusCode to set. 480 */ 481 public void setPurchaseOrderCampusCode(String purchaseOrderCampusCode) { 482 this.purchaseOrderCampusCode = purchaseOrderCampusCode; 483 } 484 /** 485 * @return Returns the purchaseOrderID. 486 */ 487 public Integer getPurchaseOrderID() { 488 return purchaseOrderID; 489 } 490 /** 491 * @param purchaseOrderID The purchaseOrderID to set. 492 */ 493 public void setPurchaseOrderID(Integer purchaseOrderID) { 494 this.purchaseOrderID = purchaseOrderID; 495 } 496 /** 497 * @return Returns the rejected. 498 */ 499 public boolean isRejected() { 500 return rejected; 501 } 502 /** 503 * @param rejected The rejected to set. 504 */ 505 public void setRejected(boolean rejected) { 506 this.rejected = rejected; 507 } 508 /** 509 * @return Returns the supplierOrderInfoID. 510 */ 511 public String getSupplierOrderInfoID() { 512 return supplierOrderInfoID; 513 } 514 /** 515 * @param supplierOrderInfoID The supplierOrderInfoID to set. 516 */ 517 public void setSupplierOrderInfoID(String supplierOrderInfoID) { 518 this.supplierOrderInfoID = supplierOrderInfoID; 519 } 520 /** 521 * @return Returns the masterAgreementIDInfoDateString. 522 */ 523 public String getMasterAgreementIDInfoDateString() { 524 return masterAgreementIDInfoDateString; 525 } 526 /** 527 * @return Returns the masterAgreementReferenceDateString. 528 */ 529 public String getMasterAgreementReferenceDateString() { 530 return masterAgreementReferenceDateString; 531 } 532 /** 533 * @return Returns the orderIDInfoDateString. 534 */ 535 public String getOrderIDInfoDateString() { 536 return orderIDInfoDateString; 537 } 538 539 public void addInvoiceItem(ElectronicInvoiceItem electronicInvoiceItem){ 540 invoiceItems.add(electronicInvoiceItem); 541 /** 542 * TODO: This is not the right place for sorting... Have to move this to getter method with some flag to avoid 543 * this sorting whenever the getter is called 544 */ 545 Collections.sort(invoiceItems, new Comparator() { 546 public int compare (Object o1, Object o2) { 547 return (((ElectronicInvoiceItem)o1).getReferenceLineNumberInteger()).compareTo(((ElectronicInvoiceItem)o2).getReferenceLineNumberInteger()); 548 } 549 } 550 ); 551 } 552 553 public ElectronicInvoiceItem[] getInvoiceItemsAsArray(){ 554 if (invoiceItems.size() > 0){ 555 ElectronicInvoiceItem[] tempItems = new ElectronicInvoiceItem[invoiceItems.size()]; 556 invoiceItems.toArray(tempItems); 557 return tempItems; 558 } 559 return null; 560 } 561 562 public String getOrderReferenceOrderDateString() { 563 return orderReferenceOrderDateString; 564 } 565 566 public void setOrderReferenceOrderDateString(String orderReferenceOrderDateString) { 567 this.orderReferenceOrderDateString = orderReferenceOrderDateString; 568 } 569 570 public String toString(){ 571 572 ToStringBuilder toString = new ToStringBuilder(this); 573 574 toString.append("orderReferenceOrderID",getOrderReferenceOrderID()); 575 toString.append("orderReferenceOrderDate",getOrderReferenceOrderDateString()); 576 toString.append("orderReferenceDocumentRefPayloadID",getOrderReferenceDocumentRefPayloadID()); 577 toString.append("orderReferenceDocumentRef",getOrderReferenceDocumentRef()); 578 toString.append("masterAgreementReferenceID",getMasterAgreementReferenceID()); 579 toString.append("masterAgreementReferenceDateString",getMasterAgreementReferenceDateString()); 580 toString.append("masterAgreementIDInfoID",getMasterAgreementIDInfoID()); 581 toString.append("masterAgreementIDInfoDateString",getMasterAgreementIDInfoDateString()); 582 toString.append("orderIDInfoID",getOrderIDInfoID()); 583 toString.append("orderIDInfoDateString",getOrderIDInfoDateString()); 584 toString.append("supplierOrderInfoID",getSupplierOrderInfoID()); 585 toString.append("invoiceItems",getInvoiceItems()); 586 587 return toString.toString(); 588 589 } 590 591 592 }