/* * [Electronic.java] * * Summary: Electronic macro. Sell electronics and other non book/dvd products from Amazon, TigerDirect and Newegg. * * Copyright: (c) 2007-2017 Roedy Green, Canadian Mind Products, http://mindprod.com * * Licence: This software may be copied and used freely for any purpose but military. * http://mindprod.com/contact/nonmil.html * * Requires: JDK 1.8+ * * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/ * * Version History: * 1.0 2007-08-29 split from DVDMacro * 1.1 2011-09-28 get rid of impression counters. New format for link. * 1.2 2013-01-28 allow multiple asin numbers. * 1.3 2016-07-09 refactor to allow all estores to have muliple product numbers for a product */ package com.mindprod.stores; import com.mindprod.common18.EIO; import com.mindprod.common18.ST; import com.mindprod.fastcat.FastCat; import com.mindprod.htmlmacros.macro.CountryFlag; import com.mindprod.htmlmacros.macro.Dim; import com.mindprod.htmlmacros.macro.GoogleCannedSearch; import com.mindprod.htmlmacros.macro.Macro; import com.mindprod.htmlmacros.support.BuildImage; import com.mindprod.htmlmacros.support.ImageAlignment; import com.mindprod.htmlmacros.support.Tools; import com.mindprod.hunkio.HunkIO; import java.io.File; import java.io.IOException; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.regex.Pattern; import static com.mindprod.htmlmacros.macro.Global.configuration; import static com.mindprod.stores.EStore.*; import static com.mindprod.stores.StockStatus.INSTOCK; import static java.lang.System.*; /** * Electronic macro. Sell electronics and other non book/dvd products from Amazon, TigerDirect and Newegg. * * @author Roedy Green, Canadian Mind Products * @version 1.3 2016-07-09 refactor to allow all estores to have muliple product numbers for a product * @see com.mindprod.stores.EStore * @since 2007-08-29 */ public class Electronic extends Macro { // declarations /** * this item goes on the left side. */ private static final boolean ON_LEFT = false; /** * this item goes on the right side. */ private static final boolean ON_RIGHT = true; /** * Google search modifier to ensure find only other estores */ private static final String JUST_OTHER_ESTORES = "-amazon -newegg -tigerdirect -bestbuysku"; /** * list of image formats we support for electronic cover to display in HTML. */ private static final String[] SUPPORTED_EXTENSIONS = { ".png", ".jpg", ".gif" }; /** * how to use the macro */ private static final String USAGE = "\nElectronic macro needs needs asin=a, [price=$9,9999.99] " + "[bestbuyskucawebcode=,] [bestbuysku=,] [canadacomputersitemids=,] " + "[ncixcasku=,] [ncixussku=,] " + "[neweggcaitem=,] [neweggitem=,] " + "[staplescaitem=,] [staplesitem=,] " + "[tigercaedpno=,] [tigeredpnoedpno=,] " + "title= [dim=9 x 9 x 9 in] [weight=1 pound][notes=] [discontinued=]"; /** * format for non-display of price */ private static final DecimalFormat DOLLAR_FORMAT = new DecimalFormat( "'$'###,##0.00" ); /** * split isbns at comma, gets rid of spaces around comma */ private static final Pattern SPLIT_ON_COMMA = Pattern.compile( "\\s*,\\s*" ); private static final Pattern SPLIT_ON_SPACE = Pattern.compile( "\\s+" ); // /declarations // methods /** * true if one or more stores was grayed out for beingout of stock or not carried */ private boolean greyed = false; /** * find best isbn to display for this store, ideally instock * * @param eStore eStore * @param preferredProducts list of products in preferred order * * @return best fit productt null if no fit. will be NOTCARRIED, OUTOFSTOCK or INSTOCK. */ private static BestResult best( EStore eStore, String[] preferredProducts ) { String bestProduct = null; StockStatus bestStockStatus = StockStatus.UNKNOWN; for ( String product : preferredProducts ) { final StockStatus stockStatus = eStore.getProductStatus( product, true ); if ( stockStatus.compareTo( bestStockStatus ) > 0 ) { bestStockStatus = stockStatus; bestProduct = product; // if we find an isbn in stock, no point in continuing to search. if ( bestStockStatus == StockStatus.INSTOCK ) { break; } } } // end for // we might have fallen out the loop without finding anything if ( bestStockStatus.compareTo( StockStatus.NOTCARRIED ) < 0 ) { return new BestResult( eStore, null, bestStockStatus ); } else { return new BestResult( eStore, bestProduct, bestStockStatus ); } }// /method /** * Build a link to a book at dummy vendor * * @param onRight true if inserting on right side of table. * * @return HTML for a filler, dummy vendor. */ @SuppressWarnings( { "SameParameterValue" } ) private static String buildDummy( boolean onRight ) { return onRight ? "\n" : ""; }// /method /** * Get filename of the electroniccover of the form B00005Y726.gif or B00005Y726.jpg * * @param primaryAsin item number without dashes or spaces. single Asin * * @return filename of cover image. Will return dummy noimage.png if there is no match. */ private static String getElectronicCoverName( String PrimaryAsin ) { for ( String ext : SUPPORTED_EXTENSIONS ) { final String candidateElectronicCoverImageName = PrimaryAsin + ext; if ( Tools.toFileFromUPath( "image/electroniccover/" + candidateElectronicCoverImageName ) .exists() ) { return candidateElectronicCoverImageName; } } err.println( "Warning no image for electronic asin " + PrimaryAsin ); // could not find an image return "noasinimage.png"; }// /method /** * is one of these products in stock at this store. * * @param eStore stare * @param products commalist products * * @return true if one if these products in instock at this store. */ private static boolean inStock( EStore eStore, String products ) { if ( !eStore.isAlive() ) { return false; } if ( ST.isEmpty( products ) ) { return false; } final BestResult br = best( eStore, splitProducts( products ) ); return br.stockStatus == INSTOCK; } /** * is this electronic device stocked anywhere * * * * @param asin amazon part number * @param bestbuycawebcode bestbuy.ca webcode * @param bestbuysku bestbuy.com sku * @param canadacomputersitemid canadacomputers.com part number * @param neweggcaitem newegg.cam part number * @param neweggitem newegg.com part number * @param staplescaitem staples.ca part number * @param staplesitem staples.com part number * @param tigercaedpno tigerdirect.ca EdpNo * @param tigeredpno tigerdirect.com EdpNo * * @return true if in stock in at most one store. */ private static boolean isStockedSomewhere( final String asin, final String bestbuycawebcode, final String bestbuysku, final String canadacomputersitemid, final String ncixcasku, final String ncixussku, final String neweggcaitem, final String neweggitem, final String staplescaitem, final String staplesitem, final String tigercaedpno, final String tigeredpno ) { final String[] asins = splitProducts( asin ); for ( EStore e : AMAZON_ESTORES ) { if ( !e.isAlive() ) { continue; } final BestResult br = best( e, asins ); if ( br.stockStatus == INSTOCK ) { return true; } } if ( inStock( BESTBUYCA, bestbuycawebcode ) ) { return true; } if ( inStock( BESTBUY, bestbuysku ) ) { return true; } if ( inStock( CANADACOMPUTERS, canadacomputersitemid ) ) { return true; } if ( inStock( NCIXCA, ncixcasku ) ) { return true; } if ( inStock( NCIXUS, ncixussku ) ) { return true; } if ( inStock( NEWEGGCA, neweggcaitem ) ) { return true; } if ( inStock( NEWEGG, neweggitem ) ) { return true; } if ( inStock( STAPLESCA, staplescaitem ) ) { return true; } if ( inStock( STAPLES, staplesitem ) ) { return true; } if ( inStock( TIGERCA, tigercaedpno ) ) { return true; } return inStock( TIGER, tigeredpno ); }// /method /** * Create a little *.nostockers file to warn of products nobody stocks. * * @param productCategory BOOK DVD etc. * @param product THe product number * @param pageUrl the url of the product description file on the vendor website * @param title title of the book */ private static void reportUnstockedProduct( final String productCategory, final String product, final String pageUrl, final String title ) { final String responseProblemFile = "C:\\temp\\" + productCategory.toUpperCase() + "_" + product + ".nostockers"; final FastCat sb = new FastCat( 9 ); sb.append( "N O S T O C K E R S\n" ); sb.append( productCategory, " not in stock at any store and not registered as rare in Configuration.isProductRare\n" ); sb.append( " pageUrl: ", pageUrl, "\n" ); sb.append( " title: ", title, "\n" ); final String problem = sb.toString(); try { HunkIO.writeEntireFile( new File( responseProblemFile ), problem, HunkIO.UTF8 ); } catch ( IOException e ) { err.println( "Unable to capture .nostockers file" ); } }// /method /** * create list of product ids * * @param productLists, comma-separated product list * * @return array of products, combining inputs */ private static String[] splitProducts( final String... productLists ) { ArrayList a = new ArrayList<>( 10 ); for ( String productList : productLists ) { if ( ST.isEmpty( productList ) ) { continue; } final String[] products = SPLIT_ON_COMMA.split( productList ); for ( String product : products ) { if ( ST.isEmpty( product ) || a.contains( product ) ) { // duplicate continue; } a.add( product ); } } return a.toArray( new String[ a.size() ] ); }// /method /** * validate a macro parameter * * @param fieldName name of the field we are testing * @param minLength min field length * @param maxLength max field length * @param mustBeNumeric true if field must be numeric * @param value value of the field, possibly a comma list */ private static void validate( final String fieldName, final int minLength, final int maxLength, final boolean mustBeNumeric, final String value ) { final String[] products = splitProducts( value ); for ( String product : products ) { switch ( fieldName ) { case "asin": if ( !( product.startsWith( "B00" ) || product.startsWith( "B01" ) || product.startsWith( "B07" ) ) ) { throw new IllegalArgumentException( "asin =" + value + " must start with B00, B01 or B07" ); } if ( product.length() < 10 || product.length() > 10 ) { throw new IllegalArgumentException( " asin =" + value + " should have length 10" ); } break; case "tigeredpno": case "tigercaedpno": // e.g. / 4146198 254148 59565 or YWR-102587509 final boolean tigerOk; switch ( product.length() ) { case 5: case 6: case 7: case 8: tigerOk = ST.isNumeric( product ); break; case 13: tigerOk = true; break; default: tigerOk = false; } if ( !tigerOk ) { throw new IllegalArgumentException( fieldName + "=" + value + " must be length 5-8 or 13" ); } break; default: if ( product.length() < minLength || product.length() > maxLength || ( mustBeNumeric && !ST.isNumeric( product ) ) ) { throw new IllegalArgumentException( fieldName + "=" + value + " should have length " + minLength + ".." + maxLength + "." + ( mustBeNumeric ? " Must be numeric." : "" ) ); } } } // /methods } /** * build link with flag * * @param onright true if flag on right * @param eStore which store * @param preferredProducts array of ISBNs in order to preference * @param title title of book */ private String buildProductLinkWithFlag( boolean onright, EStore eStore, String[] preferredProducts, final String title ) { // flag comes from the store CountryFlag flag = eStore.getFlag(); final FastCat sb = new FastCat( 12 ); sb.append( leadingCountryFlag( onright, flag ) ); if ( eStore.isAlive() ) { final BestResult br = best( eStore, preferredProducts ); final String product = br.product; final StockStatus status = br.stockStatus; sb.append( "" ); greyed = true; break; case INSTOCK: if ( eStore.takesPayPal() ) { sb.append( " paypal" ); } sb.append( "\" rel=\"nofollow\" href=\"" ); sb.append( eStore.buildProductLink( product ), "\">" ); break; case NOTCARRIED: default: // unknown will show up here if there is no product number sb.append( "\" rel=\"nofollow\" href=\"" ); sb.append( eStore.buildQueryLink( title, null ), "\">" ); greyed = true; } sb.append( eStore.getDecoratedStoreName(), "" ); } else { sb.append( "", eStore.getDecoratedStoreName(), "" ); } sb.append( trailingCountryFlag( onright, flag ) ); return sb.toString(); }// /method /** * build link with flag * * @param onright true if flag on right * @param topic topic of search book title * * @return generated HTML to links to Google Search */ private String buildSearchLinkWithUNFlag( boolean onright, String topic ) { CountryFlag flag = CountryFlag.UN; // search web with google for this topic final FastCat sb = new FastCat( 3 ); sb.append( leadingCountryFlag( onright, flag ) ); sb.append( GoogleCannedSearch.expand( false, JUST_OTHER_ESTORES, topic, "other stores", fileBeingDistributed ) ); sb.append( trailingCountryFlag( onright, flag ) ); return sb.toString(); }// /method /** * Build grid of store buttons * * @param asin possible amazon part numbers * @param bestbuycawebcode webcode * @param bestbuysku sku * @param canadacomputersitemid canadacomputers.com part number * @param ncixcasku ncix canada * @param ncixussku ncix usa * @param neweggcaitem newegg.ca part number * @param neweggitem newegg.com part number * @param staplescaitem staples.ca part number * @param staplesitem staples.com part number * @param tigercaedpno tigerdirect.ca epdno * @param tigeredpno tigerdirect.com epdno * @param title name of product * * @return HTML for store button grid */ private String buildStoreButtons( final String asin, final String bestbuycawebcode, final String bestbuysku, final String canadacomputersitemid, final String ncixcasku, final String ncixussku, final String neweggcaitem, final String neweggitem, final String staplescaitem, final String staplesitem, final String tigercaedpno, final String tigeredpno, final String title ) { greyed = false; final String[] asins = splitProducts( asin ); final FastCat sb = new FastCat( 22 ); sb.append( "" ); sb.append( "\n" ); sb.append( "" ); sb.append( "" ); sb.append( "" ); sb.append( "" ); sb.append( "" ); sb.append( "" ); sb.append( "\n" ); /* L A Y O U T LEFT RIGHT amazon.com bestbuy.ca amazon.ca canadacomputers.com amazon.de ncixca amazon.es neweggca amazon.fr staplesca amazon.it tigerca amazon.co.uk bestbuy junglee ncixus other stores newegg -- staples -- tiger */ sb.append( Book.interleave( new String[] { buildProductLinkWithFlag( ON_LEFT, AMAZONCOM, asins, title ), buildProductLinkWithFlag( ON_LEFT, AMAZONCA, asins, title ), buildProductLinkWithFlag( ON_LEFT, AMAZONDE, asins, title ), buildProductLinkWithFlag( ON_LEFT, AMAZONES, asins, title ), buildProductLinkWithFlag( ON_LEFT, AMAZONFR, asins, title ), buildProductLinkWithFlag( ON_LEFT, AMAZONIT, asins, title ), buildProductLinkWithFlag( ON_LEFT, AMAZONUK, asins, title ), buildProductLinkWithFlag( ON_LEFT, JUNGLEE, asins, title ), buildSearchLinkWithUNFlag( ON_LEFT, title ), buildDummy( ON_LEFT ), buildDummy( ON_LEFT ), }, new String[] { buildProductLinkWithFlag( ON_RIGHT, BESTBUYCA, splitProducts( bestbuycawebcode ), title ), buildProductLinkWithFlag( ON_RIGHT, CANADACOMPUTERS, splitProducts( canadacomputersitemid ), title ), buildProductLinkWithFlag( ON_RIGHT, NCIXCA, splitProducts( ncixcasku ), title ), buildProductLinkWithFlag( ON_RIGHT, NEWEGGCA, splitProducts( neweggcaitem ), title ), buildProductLinkWithFlag( ON_RIGHT, STAPLESCA, splitProducts( staplescaitem ), title ), buildProductLinkWithFlag( ON_RIGHT, TIGERCA, splitProducts( tigercaedpno ), title ), buildProductLinkWithFlag( ON_RIGHT, BESTBUY, splitProducts( bestbuysku ), title ), buildProductLinkWithFlag( ON_RIGHT, NCIXUS, splitProducts( ncixussku ), title ), buildProductLinkWithFlag( ON_RIGHT, NEWEGG, splitProducts( neweggitem ), title ), buildProductLinkWithFlag( ON_RIGHT, STAPLES, splitProducts( staplesitem ), title ), buildProductLinkWithFlag( ON_RIGHT, TIGER, splitProducts( tigeredpno ), title ), } ) ); // end inner sellclassgrid table sb.append( "
" ); sb.append( "Online electronic stores carrying " ); sb.append( Tools.stripHTMLTags( title ) ); sb.append( "
\n" ); sb.append( "Greyed out stores probably do " + "not have the item in stock\n" ); return sb.toString(); }// /method /** * Generate HTML for one electronic product. Assumes all data is clean. All fields must be HTML, * i.e. ampersands must be * shown as ampersand-amp; etc. Does NOT generate the <!-- macro, <!-- generated or <!-- /generated. * * @param asin Amazon order numbers for electronic products without dashes or spaces. * @param bestbuycawebcode bestbuy.ca webcode * @param bestbuysku bestbuysku.com sku * @param canadacomputersitemid canadacomputers.com part number * @param ncixcasku ncix.ca sku number * @param ncixussku ncix us sku number * @param neweggcaitem newegg.cam part number * @param neweggitem newegg.com part number * @param stablescaitem staples.ca part number * @param staplesitem staples.com part number * @param tigercaedpno tigerdirect.ca EdpNo * @param tigeredpno tigeredpnodirect.com EdpNo * @param title short description of the product. * @param notes Notes about the product. May contain embedded newlines. * @param price price in US dollars of product. Not displayed. Just used to sort in ascending order. * @param discontinued is this product discontinued. * * @return String representing all the HTML needed for one electronic referral. */ @SuppressWarnings( "SameParameterValue" ) private String expand( final String asin, final String bestbuycawebcode, final String bestbuysku, final String canadacomputersitemid, final String ncixcasku, final String ncixussku, final String neweggcaitem, final String neweggitem, final String staplescaitem, final String staplesitem, final String tigercaedpno, final String tigeredpno, final String title, final String dim, final String weight, final String notes, final double price, final boolean discontinued ) { // THIS IS NOT THE CODE FOR THE BOOK MACRO. THIS IS FOR SELLING ELECTRONICS. // see Book and DVD macros. final String primaryAsin = splitProducts( asin )[ 0 ]; final boolean haveDim = dim.length() > 0; final boolean haveWeight = weight.length() > 0; boolean stockedSomewhere = isStockedSomewhere( asin, bestbuycawebcode, bestbuysku, canadacomputersitemid, ncixcasku, ncixussku, neweggcaitem, neweggitem, staplescaitem, staplesitem, tigercaedpno, tigeredpno ); if ( !stockedSomewhere && !configuration.isProductRare( primaryAsin ) ) { reportUnstockedProduct( "electronics", primaryAsin, EIO.getCanOrAbsPath( fileBeingProcessed ), title ); } final FastCat sb = new FastCat( 37 ); sb.append( "" ); sb.append( DOLLAR_FORMAT.format( price ) ); sb.append( "" ); sb.append( "\n" ); sb.append( "" ); int rows = 2; // always have title and asin if ( haveDim ) { rows++; } if ( haveWeight ) { rows++; } if ( discontinued ) { rows++; } sb.append( "\n as title sb.append( Tools.completeLink( "electronic/" + primaryAsin + ".html", BuildImage.buildImgTag( "navigate/pigeon.png", "to electronic home", ImageAlignment.floatright, null, fileBeingDistributed ), "plain", fileBeingDistributed ) ); } sb.append( "\n" ); sb.append( "\n\n" ); if ( haveDim ) { sb.append( "\n\n" ); } if ( haveWeight ) { sb.append( "\n\n" ); } if ( discontinued ) { sb.append( "" ); } if ( notes.length() > 0 || !stockedSomewhere ) { sb.append( "\n" ); } sb.append( buildStoreButtons( asin, bestbuycawebcode, bestbuysku, canadacomputersitemid, ncixcasku, ncixussku, neweggcaitem, neweggitem, staplescaitem, staplesitem, tigercaedpno, tigeredpno, title ) ); sb.append( "
" ); sb.append( "electronic link to " ); sb.append( Tools.stripHTMLTags( title ) ); sb.append( "
" ); sb.append( BuildImage.buildImgTag( "electroniccover/" + getElectronicCoverName( primaryAsin ), "electronic product image", null /* align */, null /* css class */, fileBeingDistributed ) ); // pigeon icon takes you to the electronic home which is copied to other places. final boolean needPigeon = !fileBeingDistributed.getParent().endsWith( "electronic" ); // L A Y O U T // image title/pigeon // image x : y // 1 2 3 sb.append( "recommend " + "electronic⇒" ); sb.append( title ); if ( needPigeon ) { // put into same ..
asin" ); sb.append( primaryAsin ); sb.append( "
dim" ); try { String dimExp = new Dim().expandMacro( SPLIT_ON_SPACE.split( dim + " br" ), true /* quiet */, false /* verbose */ ); // override css class to get smaller type sb.append( dimExp.replace( "metric", "smallmetric" ).replace( "imperial", "smallimperial" ) ); } catch ( IllegalArgumentException e ) { throw new IllegalArgumentException( "Electronic macro dim parameter invalid " + dim ); } sb.append( "
weight" ); try { sb.append( new Dim().expandMacro( SPLIT_ON_SPACE.split( weight ), true /* quiet */, false /* verbose */ ) ); } catch ( IllegalArgumentException e ) { throw new IllegalArgumentException( "Electronic macro weight parameter invalid " + weight ); } sb.append( "
" ); sb.append( BuildImage.buildImgTag( "electronic/discontinued.png", "discontinued icon", ImageAlignment.center, "plain", fileBeingDistributed ) ); sb.append( "
" ); if ( !stockedSomewhere ) { sb.append( "This product is not in stock at any of the Amazon stores. " ); } sb.append( notes ); sb.append( "
\n" ); sb.append( "\n" ); return sb.toString(); }// /method /** * Insert optional country flag on left of link. *

* * @param onRight true if inserting on right side of table. * @param flag CountryFlag country. * * @return HTML to display the flag */ private String leadingCountryFlag( boolean onRight, CountryFlag flag ) { return onRight ? "" : "" + flag.getFlagRef( fileBeingDistributed ) + "\n"; }// /method /** * Insert optional country flag on right of link. * * @param onRight true if inserting on right side of table. * @param flag CountryFlag country. * * @return HTML to display the flag */ private String trailingCountryFlag( boolean onRight, CountryFlag flag ) { return onRight ? "\n" + flag.getFlagRef( fileBeingDistributed ) + "\n" : "\n"; }// /method /** * Generate macro expansion for electronic macro * * @param parms parsed params for the macro. parms typically look like this: &tl;!-- macro electronic * asin="B0007P8KZA" title="Toshiba HDTV" notes={ 1 x 1 metre} class=sellelectronic --> Parms * may be in any order. * @param quiet true if want output suppressed. * @param verbose @return expanded text */ public String expandMacro( String[] parms, final boolean quiet, final boolean verbose ) { if ( parms.length < 2 * 2 ) { throw new IllegalArgumentException( USAGE ); } // must have even number of parms if ( ( parms.length & 1 ) != 0 ) { throw new IllegalArgumentException( "Electronic macro syntax error: must have parm=value pairs\n" + USAGE ); } // set defaults String asin = null; String bestbuycawebcode = null; String bestbuysku = null; String canadacomputersitemid = null; boolean discontinued = false; String ncixcasku = null; String ncixussku = null; String neweggcaitem = null; String neweggitem = null; String staplescaitem = null; String staplesitem = null; String tigeredpno = null; String tigercaedpno = null; String title = "unknown"; String notes = " "; double price = 0.00d; String dim = ""; String weight = ""; // extract data from parms for ( int i = 0; i < parms.length; i += 2 ) { String name = parms[ i ]; String value = parms[ i + 1 ]; switch ( name ) { case "asin": validate( "asin", 10, 10, false /* alphanumeric */, value ); asin = value; // commalist break; case "bestbuycawebcode": // 10294555 10200553 validate( "bestbuycawebcode", 8, 8, true, value ); bestbuycawebcode = value; break; case "bestbuysku": validate( "bestbuysku", 7, 10, false, value ); bestbuysku = value; break; case "canadacomputersitemid": // e.g. or 71888Q or 5308133 . not itemcode validate( "canadacomputersitemid", 6, 7, false, value ); canadacomputersitemid = value; break; case "discontinued": discontinued = value.equalsIgnoreCase( "yes" ); break; case "dim": // dimensions of product dim = value; break; case "ncixcasku": validate( "ncixcasku", 4, 12, false, value ); ncixcasku = value; break; case "ncixussku": validate( "ncixussku", 4, 9, false, value ); ncixussku = value; break; case "neweggcaitem": // eg.N82E16823672004 CVF N82E16826106164,9SIA41A1AR3858, 0ZS-000J-00053 , // 0GA-007E-00052CVF validate( "neweggcaitem", 14, 18, false, value ); neweggcaitem = value; break; case "neweggitem": // e.g. N82E16873109049 SIA19P0ME9135 02D-00X0-00010 N82E16813131735R validate( "neweggitem", 13, 16, false, value ); neweggitem = value; break; case "staplescaitem": validate( "staplescaitem", 5, 9, false, value ); staplescaitem = value; break; case "staplesitem": validate( "staplesitem", 6, 9, false, value ); staplesitem = value; break; case "tigercaedpno": validate( "tigercaedpno", 5, 13, false, value ); // e.g. 4146198 254148 59565 tigercaedpno = value; break; case "tigeredpno": // e.g. / 4146198 254148 59565 or YWR-102587509 validate( "tigeredpno", 5, 13, false, value ); tigeredpno = value; break; case "title": title = value; break; case "notes": notes = value; break; case "price": // electronic does not want us displaying prices, especially out of date prices. // we display it hidden so that we can sort item by price. price = Double.parseDouble( ST.trimLeading( value, '$' ).replaceAll( ",", "" ) ); break; case "weight": // weight of product weight = value; break; default: throw new IllegalArgumentException( "Electronic macro syntax error: unknown parm: " + name + "\n" + USAGE ); } } // end for // generate the HTML to refer this electronic product. return expand( asin, bestbuycawebcode, bestbuysku, canadacomputersitemid, ncixcasku, ncixussku, neweggcaitem, neweggitem, staplescaitem, staplesitem, tigercaedpno, tigeredpno, title, dim, weight, notes, price, discontinued ); }// /method }