1 4 package com.openedit.store.retailproconvert; 5 6 import java.io.File ; 7 import java.io.FileFilter ; 8 import java.io.FileInputStream ; 9 import java.io.FileOutputStream ; 10 import java.io.IOException ; 11 import java.io.InputStreamReader ; 12 import java.io.Reader ; 13 import java.util.ArrayList ; 14 import java.util.Arrays ; 15 import java.util.Collections ; 16 import java.util.Enumeration ; 17 import java.util.Iterator ; 18 import java.util.List ; 19 import java.util.zip.ZipEntry ; 20 import java.util.zip.ZipFile ; 21 22 import org.apache.commons.logging.Log; 23 import org.apache.commons.logging.LogFactory; 24 import org.dom4j.Document; 25 import org.dom4j.Element; 26 import org.dom4j.io.OutputFormat; 27 import org.dom4j.io.SAXReader; 28 import org.dom4j.io.XMLWriter; 29 import org.openedit.money.Money; 30 31 import com.openedit.store.CatalogConverter; 32 import com.openedit.store.Category; 33 import com.openedit.store.InventoryItem; 34 import com.openedit.store.Option; 35 import com.openedit.store.Price; 36 import com.openedit.store.PriceTier; 37 import com.openedit.store.Product; 38 import com.openedit.store.Store; 39 import com.openedit.store.StoreException; 40 import com.openedit.util.OutputFiller; 41 import com.openedit.util.ZipUtil; 42 43 49 public class RetailProCatalogConverter extends CatalogConverter 50 { 51 String INDEX = "index"; 52 protected OutputFiller fieldOutputFiller; 53 54 private static final Log log = LogFactory.getLog(RetailProCatalogConverter.class); 55 56 public synchronized boolean convert(Store inStore, List inErrorLog) throws Exception 57 { 58 File uploadHome = new File ( inStore.getStoreDirectory(), "/upload"); 59 if ( !uploadHome.exists()) 60 { 61 inErrorLog.add("No upload directory"); 62 return false; 63 } 64 File [] zipFiles = uploadHome.listFiles( getStyleZipFileFilter() ); 65 66 boolean didAnything = false; 67 File inputHome = new File (inStore.getStoreDirectory(), "/tmp/"); 68 inputHome.mkdirs(); 69 70 if ( zipFiles == null || zipFiles.length == 0) 72 { 73 inErrorLog.add("No input files found"); 74 log.info("No style inputs found"); 75 } 76 else 77 { 78 List inputs = new ArrayList ( Arrays.asList( zipFiles) ); 79 Collections.sort(inputs); 80 for (Iterator iter = inputs.iterator(); iter.hasNext();) 81 { 82 clearStoreUploadDir(inputHome); List outputAllProducts = new ArrayList (); 84 File file = (File ) iter.next(); 85 86 unzip(new File [] { file },inputHome); 87 89 List styles = listStyleXmls(inputHome); 90 91 for (Iterator siter = styles.iterator(); siter.hasNext();) 92 { 93 File style = (File ) siter.next(); 94 95 Document page = cleanXml( style ); 96 log.info("Converting styles..."); 97 convertStyles(inStore, page, outputAllProducts ); 98 inErrorLog.add("Completed " + outputAllProducts.size() + " products"); 99 boolean hadAvailability = updateInventoryLevels(inStore, page, outputAllProducts ); 100 log.info("Completed " + outputAllProducts.size() + " products. Avail: " + hadAvailability + " file size:" + style.length() ); 101 if ( style.length() > 5000000 && !hadAvailability ) { 103 log.info("Marking remaining products not available"); 104 markRemainingProductsUnavailable(inStore,outputAllProducts); 105 } 106 didAnything = true; 107 108 } 109 convertCatTree(inStore, inputHome); 110 inStore.clearProducts(); 111 moveUploadFile(file); } 113 } 114 log.info("Moving images..."); 115 File [] imagezips = uploadHome.listFiles( getImagesZipFileFilter() ); 117 if ( imagezips != null && imagezips.length > 0) 118 { 119 List sortedImages = new ArrayList (Arrays.asList(imagezips ) ); 120 Collections.sort(sortedImages); 121 for (Iterator iter = sortedImages.iterator(); iter.hasNext();) 122 { 123 File zip = (File ) iter.next(); 124 copyPhotos(inStore, zip); 125 moveUploadFile(zip); 126 didAnything = true; 127 } 128 inStore.clearProducts(); 129 } 130 File [] customerZips = uploadHome.listFiles(getCustomerZipFileFilter()); 131 if ( customerZips != null && customerZips.length > 0) 132 { 133 unzip( customerZips, inputHome ); 134 135 CustomerListConverter users = new CustomerListConverter(); 137 users.setCustomerArchive(inStore.getCustomerArchive()); 138 users.convert(inStore, inErrorLog); 139 140 for (int i = 0; i < customerZips.length; i++) 141 { 142 moveUploadFile(customerZips[i]); 143 didAnything = true; 144 } 145 } 146 return didAnything; 147 148 } 149 150 private void convertStyles(Store inStore, Document page, List outputAllProducts) throws Exception 151 { 152 int count = 0; 153 for (Iterator iter = page.getRootElement().elementIterator("Style"); iter.hasNext();) 154 { 155 Element styleE = (Element) iter.next(); 156 String id = styleE.attributeValue("fldStyleSID"); 157 log.info("Converting style " + id); 158 Product newproduct = inStore.getProduct(id); if ( newproduct == null ) 160 { 161 newproduct = new Product(); 162 newproduct.setId(id); 163 } 164 else 165 { 166 newproduct.clearItems(); 168 169 } 170 newproduct.setPriceSupport(null); 171 newproduct.clearOptions(); 172 String name = styleE.attributeValue("fldStyleName"); 173 if (name == null) 174 { 175 name = "no name"; 177 } 178 newproduct.setId(styleE.attributeValue("fldStyleSID")); 179 newproduct.setName(name); 180 populateItems(newproduct, styleE); 181 182 String mesg = styleE.attributeValue("fldProdAvail"); 184 if( mesg != null && mesg.equals("Sell Always")) 185 { 186 String fldOutStockMsg = styleE.attributeValue("fldOutStockMsg"); 187 if ( fldOutStockMsg != null && fldOutStockMsg.length() > 0) 188 { 189 newproduct.putAttribute("outOfStockMsg",fldOutStockMsg); 192 } 193 } 194 195 String desc = styleE.attributeValue("fldStyleLongDesc"); 196 if (desc == null) 197 { 198 desc = "no description available"; 199 } 200 String val = parseDescription( desc ); 201 202 val = val.replace('\\','/'); 204 val = val.replaceAll("R:/Web Pics/", inStore.getStoreHome() + "/products/images/extras/"); 205 newproduct.setDescription( val ); 206 207 newproduct.putAttribute("fldDesc1", styleE.attributeValue("fldDesc1")); 208 newproduct.putAttribute("fldDesc2", styleE.attributeValue("fldDesc2")); 209 newproduct.putAttribute("fldDesc3", styleE.attributeValue("fldDesc3")); 210 newproduct.putAttribute("fldDesc4", styleE.attributeValue("fldDesc4")); 211 212 String taxable = styleE.attributeValue("fldTaxCd"); 213 if (taxable != null && !taxable.trim().equalsIgnoreCase("Taxable")) 214 { 215 newproduct.setTaxExempt(true); 216 } 217 String handlingAmount = styleE.attributeValue("fldHandAmount"); 218 if ( handlingAmount != null ) 219 { 220 Option handlingCharge = createHandlingOption(new Money(handlingAmount)); 223 newproduct.addOption(handlingCharge); 224 } 225 count++; 227 newproduct.setOrdering(count); 228 newproduct.setAvailable(true); 230 outputAllProducts.add(id); 231 232 String keyword = parseKeywords( desc ); 233 if ( keyword != null) 234 { 235 keyword = keyword.replaceAll("CLSFD","classified"); 236 keyword = keyword.trim(); 237 if ( keyword.indexOf("classified") >= 0 ) 238 { 239 newproduct.setShippingMethodId("electronic"); 240 } 241 } 242 newproduct.setKeywords(keyword); 243 inStore.getProductArchive().saveProduct( newproduct ); 245 String fdesc = newproduct.getDescription(); 246 inStore.getProductArchive().saveProductDescription( newproduct,fdesc ); 247 248 inStore.getProductArchive().clearProduct(newproduct); 249 log.info("Completed style " + id); 250 } 251 } 254 255 private boolean updateInventoryLevels(Store inStore, Document page, List outputAllProducts) throws StoreException 256 { 257 boolean hasAvailability = false; 258 for (Iterator iter = page.getRootElement().elementIterator("Style_Avail"); iter.hasNext();) 259 { 260 hasAvailability = true; 261 Element styleE = (Element) iter.next(); 262 String id = styleE.attributeValue("fldStyleSID"); 264 Product aproduct = inStore.getProduct(id); 265 if ( aproduct != null ) 266 { 267 for (Iterator iterator = styleE.elementIterator("Item_Avail"); iterator.hasNext();) 268 { 269 Element element = (Element) iterator.next(); 270 String sku = styleE.attributeValue("fldItemNum"); 271 InventoryItem item = aproduct.getInventoryItemBySku(sku); 272 if ( item != null) 273 { 274 item.setQuantityInStock(Integer.parseInt(element.attributeValue("AvailQuantity"))); 275 } 276 } 277 aproduct.setAvailable(true); 278 outputAllProducts.add(id); 279 inStore.getProductArchive().saveProduct( aproduct ); 280 } 281 282 } 283 return hasAvailability; 284 } 285 286 private Document cleanXml(File input) throws Exception 287 { 288 SAXReader reader = new SAXReader(); 289 290 FileInputStream fi = new FileInputStream (input); 292 Reader stream = new InputStreamReader ( fi, "ISO-8859-1" ); 293 Document page = reader.read(stream); 294 fi.close(); 295 296 FileOutputStream out = new FileOutputStream (input); 298 OutputFormat format = OutputFormat.createPrettyPrint(); 299 format.setEncoding("ISO-8859-1"); 300 XMLWriter writer = new XMLWriter(out, format); 301 writer.write(page); 302 return page; 303 304 } 305 306 protected Option createHandlingOption(Money inHandlingAmount) 307 { 308 Option handlingCharge = new Option(); 309 handlingCharge.addTierPrice(1, new Price(inHandlingAmount)); 310 handlingCharge.setId("handling"); 311 handlingCharge.setName("Handling charge"); 312 handlingCharge.setRequired(true); 313 return handlingCharge; 314 } 315 316 319 protected void markRemainingProductsUnavailable(Store inStore, List inGoodProducts) throws StoreException 320 { 321 List ids = inStore.listAllKnownProductIds(); 323 for (Iterator iter = ids.iterator(); iter.hasNext();) 324 { 325 String id = (String ) iter.next(); 326 if ( findProductIn(id,inGoodProducts) ) 327 { 328 } 330 else 331 { 332 Product product = inStore.getProduct(id); 334 if ( product != null && product.isAvailable()) 335 { 336 product.setAvailable(false); 337 338 inStore.getProductArchive().saveProduct( product ); 339 String fdesc = product.getDescription(); 340 inStore.getProductArchive().saveProductDescription( product,fdesc ); 341 inStore.getProductArchive().clearProduct(product); 342 } 343 } 344 } 345 } 346 347 protected boolean findProductIn( String inId, List inList) 348 { 349 for (Iterator iter = inList.iterator(); iter.hasNext();) 350 { 351 String product = (String ) iter.next(); 352 if( product.equals(inId)) 353 { 354 return true; 355 } 356 } 357 return false; 358 } 359 360 protected void clearStoreUploadDir(File inputdir) 361 { 362 File [] files = inputdir.listFiles(); 363 for ( int i = 0; i < files.length; i++ ) 364 { 365 if ( !files[i].delete() ) 366 { 367 log.error("Could not delete file " + files[i].getName() ); 368 } 369 } 370 } 371 protected void moveUploadFile(File inInputFile) 372 { 373 if( !inInputFile.exists()) 374 { 375 return; 376 } 377 File tmpDir = new File ( inInputFile.getParentFile(),"completed" ); 379 tmpDir.mkdirs(); 380 383 String name = inInputFile.getName(); 384 File newFile = new File ( tmpDir, name ); 385 if ( newFile.exists() ) 386 { 387 newFile.delete(); 388 } 389 inInputFile.renameTo( newFile ); 390 } 392 393 protected void unzip(File [] zipFiles, File workingDir ) throws Exception 394 { 395 398 ZipUtil util = new ZipUtil(); 399 400 for ( int i = 0; i < zipFiles.length; i++ ) 401 { 402 try 403 { 404 util.unzip(zipFiles[i], workingDir); 405 } 406 catch ( Exception ex) 407 { 408 log.error("Could not unzip file. Deleting it " + zipFiles[i]); 409 zipFiles[i].delete(); 410 } 411 } 412 } 413 414 protected FileFilter getStyleZipFileFilter() 415 { 416 return new FileFilter () 417 { 418 public boolean accept( File pathname ) 419 { 420 String p = pathname.getName(); 421 if ( p.startsWith("N00") && p.endsWith(".zip")) 422 { 423 return true; 424 } 425 return false; 426 } 427 }; 428 } 429 protected FileFilter getImagesZipFileFilter() 430 { 431 return new FileFilter () 432 { 433 public boolean accept( File pathname ) 434 { 435 String p = pathname.getName(); 436 if ( p.startsWith("G00") && p.endsWith(".zip")) 437 { 438 return true; 439 } 440 return false; 441 } 442 }; 443 } 444 protected FileFilter getCustomerZipFileFilter() 445 { 446 return new FileFilter () 447 { 448 public boolean accept( File pathname ) 449 { 450 String p = pathname.getName(); 451 if ( p.startsWith("S00") && p.endsWith(".zip")) 452 { 453 return true; 454 } 455 return false; 456 } 457 }; 458 } 459 protected FileFilter getEcsStyleZipFileFilter() 460 { 461 return new FileFilter () 462 { 463 public boolean accept( File pathname ) 464 { 465 String p = pathname.getName().toLowerCase(); 466 if (p.startsWith("ecstyle_") && p.endsWith(".xml")) 467 { 468 return true; 469 } 470 return false; 471 } 472 }; 473 } 474 475 479 protected void convertCatTree(Store inStore, File inInputDir) throws Exception 480 { 481 File input = new File (inInputDir, "CatTree.xml"); 482 483 if ( input.exists() ) 484 { 485 SAXReader reader = new SAXReader(); 486 FileInputStream stream = new FileInputStream (input); 487 Document document = reader.read(stream); 488 489 CatalogWithProducts temproot = new CatalogWithProducts("index","Index"); 490 temproot.setProperty("sortfield", "priceOrderingUp"); 491 createCatalog( document.getRootElement(), temproot ); 492 493 inStore.getCatalogArchive().setRootCatalog(temproot); 494 inStore.getCatalogArchive().saveCatalogs(); 495 inStore.getCatalogArchive().reloadCatalogs(); 496 clearProductFromAllCategories(inStore); 497 updateProductsIn(inStore, temproot); 498 } 499 Category coupons = inStore.getCatalog("AMADAAAADJONALBD"); 501 if ( coupons != null) 502 { 503 inStore.getCatalogArchive().deleteCatalog(coupons); 504 } 505 } 506 507 protected void clearProductFromAllCategories(Store inStore) throws Exception 508 { 509 List ids = inStore.listAllKnownProductIds(); 510 for (Iterator iter = ids.iterator(); iter.hasNext();) 511 { 512 String id = (String ) iter.next(); 513 Product product = inStore.getProduct(id); 514 if ( product != null) 515 { 516 product.clearCatalogs(); 517 inStore.getProductArchive().saveProduct(product); 518 inStore.getProductArchive().clearProduct(product); 519 } 520 } 521 } 522 523 protected void createCatalog(Element inRootElement, CatalogWithProducts inParent) throws StoreException 524 { 525 for (Iterator iter = inRootElement.elementIterator("Style"); iter.hasNext();) 527 { 528 Element element = (Element) iter.next(); 529 String ordering = element.attributeValue("OrderNo"); 530 Style style = new Style(); 531 if ( ordering != null && ordering.length() > 0) 532 { 533 style.setOrdering(Integer.parseInt(ordering)); 534 } 535 style.setId(element.attributeValue("SID")); 536 inParent.addStyle(style); 537 } 538 for (Iterator iter = inRootElement.elementIterator("TreeNode"); iter.hasNext();) 539 { 540 Element element = (Element) iter.next(); 541 String id = element.attributeValue("SID"); 542 String name = element.attributeValue("Caption"); 543 CatalogWithProducts child = new CatalogWithProducts(id, name); 544 inParent.addChild(child); 545 createCatalog(element, child); 546 } 547 } 548 552 protected void updateProductsIn(Store inStore, CatalogWithProducts inCatalog) throws StoreException 553 { 554 if ( inCatalog.hasStyles() ) 555 { 556 for (Iterator iter = inCatalog.getStyles().iterator(); iter.hasNext();) 557 { 558 Style pid = (Style) iter.next(); 559 Product product = inStore.getProduct(pid.getId() ); 560 if ( product != null) 561 { 562 if ( product.getOrdering() != pid.getOrdering() || 563 !product.isInCatalog(inCatalog) ){ 564 565 product.setOrdering(pid.getOrdering()); 566 product.addCatalog(inCatalog); 567 568 inStore.getProductArchive().saveProduct( product ); 569 String fdesc = product.getDescription(); 570 inStore.getProductArchive().saveProductDescription( product,fdesc ); 571 572 inStore.getProductArchive().clearProduct(product); 573 } 574 } 575 else 576 { 577 log.error("CatTree specified invalid product " + pid.getId()); 578 } 579 } 580 } 581 for (Iterator iter = inCatalog.getChildren().iterator(); iter.hasNext();) 582 { 583 CatalogWithProducts child = (CatalogWithProducts) iter.next(); 584 updateProductsIn(inStore, child); 585 } 586 587 } 588 589 593 protected void copyPhotos(Store inStore, File inZip) throws IOException 594 { 595 597 File newImages = new File (inStore.getStoreDirectory(), "products/images"); 598 599 File largedir = new File (newImages, "original"); 600 largedir.mkdirs(); 601 602 File meddir = new File (newImages, "medium"); 603 meddir.mkdirs(); 604 605 File thumbdir = new File (newImages, "thumb"); 606 thumbdir.mkdirs(); 607 608 OutputFiller filler = new OutputFiller(); 609 ZipFile zip = new ZipFile ( inZip ); 610 for ( Enumeration iter = zip.entries(); iter.hasMoreElements(); ) 611 { 612 ZipEntry entry = (ZipEntry ) iter.nextElement(); 613 String fileName = entry.getName(); 614 if ( fileName.endsWith("t.jpg")) 615 { 616 String baseName = fileName.substring(0, fileName.indexOf("t.jpg")); 617 File outputFile = new File (thumbdir, baseName + "-100.jpg"); 618 FileOutputStream fos = new FileOutputStream ( outputFile ); 619 filler.fill( zip.getInputStream( entry ), fos ); 620 fos.flush(); 621 fos.close(); 622 } 623 else 624 { 625 String baseName = fileName.substring(0, fileName.indexOf(".jpg")); 626 File outputFile = new File (largedir, baseName + "-100.jpg"); 627 FileOutputStream fos = new FileOutputStream ( outputFile ); 629 filler.fill( zip.getInputStream( entry ), fos ); 630 fos.flush(); 631 fos.close(); 632 File medFile = new File ( meddir,baseName + "-100.jpg"); 633 filler.fill(outputFile,medFile); 635 } 636 } 637 } 638 639 public OutputFiller getOutputFiller() 640 { 641 if (fieldOutputFiller == null) 642 { 643 fieldOutputFiller = new OutputFiller(); 644 } 645 return fieldOutputFiller; 646 } 647 648 protected FileFilter largeImageFilter() 649 { 650 return new FileFilter () 651 { 652 public boolean accept( File inArg0 ) 653 { 654 if (inArg0.getName().endsWith("jpg") && !inArg0.getName().endsWith("t.jpg")) 655 { 656 return true; 657 } 658 return false; 659 } 660 }; 661 } 662 663 protected FileFilter thumbnailFilter() 664 { 665 return new FileFilter () 666 { 667 public boolean accept( File inArg0 ) 668 { 669 if (inArg0.getName().endsWith("t.jpg")) 670 { 671 return true; 672 } 673 return false; 674 } 675 }; 676 } 677 678 682 private void populateItems( Product inNewproduct, Element inProductE ) 683 { 684 686 for (Iterator iter = inProductE.elementIterator("Item"); iter.hasNext();) 687 { 688 Element eitem = (Element) iter.next(); 689 InventoryItem newItem = createItem(eitem); 690 newItem.setProduct(inNewproduct); 691 inNewproduct.addInventoryItem(newItem); 692 696 } 698 } 699 700 public InventoryItem createItem(Element inItemElem) 701 { 702 InventoryItem newItem = new InventoryItem(); 703 704 int q = Integer.parseInt(inItemElem.attributeValue("AvailQuantity")); 705 if ( q < 1) 706 { 707 String att = inItemElem.attributeValue("fldTotOnHnd"); 708 if ( att != null && att.length() > 0) 709 { 710 q = Integer.parseInt(att); 711 } 712 } 713 newItem.setQuantityInStock(q); 714 newItem.setColor(inItemElem.attributeValue("fldAttr")); 715 newItem.setSize(inItemElem.attributeValue("fldSize")); 716 newItem.setSku(inItemElem.attributeValue("fldItemNum")); 717 newItem.put("RTP_sid", inItemElem.attributeValue("fldItemSID")); 719 String itemHandlingAmountStr = inItemElem.attributeValue("fldHandAmount"); 720 if ( itemHandlingAmountStr != null ) 721 { 722 Money itemHandlingAmount = new Money(itemHandlingAmountStr); 723 newItem.addOption( createHandlingOption( itemHandlingAmount ) ); 724 } 725 newItem.setPriceSupport(null); 726 for (Iterator iterator = inItemElem.elementIterator("Price"); iterator.hasNext();) 727 { 728 729 Price price = null; 730 PriceTier tprice = newItem.getTier(0); 731 if ( tprice == null) 732 { 733 price = new Price(); 734 } 735 else 736 { 737 price = tprice.getPrice(); 738 } 739 Element priceElement = (Element) iterator.next(); 740 if ( priceElement != null) 741 { 742 String level = priceElement.attributeValue("Level"); 743 String value = priceElement.attributeValue("Value"); 744 if ( value != null && value.trim().length() > 0 ) 745 { 746 if ( "3".equals( level ) ) 747 { 748 price.setRetailPrice(new Money(value)); 749 } 750 755 if ( "4".equals( level ) ) 756 { 757 Money sale = new Money(value); 758 if ( !sale.isZero() ) 759 { 760 price.setSalePrice( sale ); 761 } 762 } 763 } 764 newItem.addTierPrice(1,price); 765 } 766 else 767 { 768 } 770 } 771 return newItem; 772 } 773 774 777 protected List listStyleXmls(File inPutHome) 778 { 779 File [] listinputs = inPutHome.listFiles(getEcsStyleZipFileFilter()); 781 List sorted = new ArrayList ( Arrays.asList(listinputs) ); 782 Collections.sort(sorted); 783 return sorted; 784 785 } 786 787 } | Popular Tags |