package com.mindprod.aws;
import com.mindprod.aws.jax.AWSECommerceService;
import com.mindprod.aws.jax.AWSECommerceServicePortType;
import com.mindprod.aws.jax.AwsHandlerResolver;
import com.mindprod.aws.jax.Item;
import com.mindprod.aws.jax.ItemLookup;
import com.mindprod.aws.jax.ItemLookupRequest;
import com.mindprod.aws.jax.Items;
import com.mindprod.aws.jax.Offer;
import com.mindprod.aws.jax.OfferListing;
import com.mindprod.aws.jax.OperationRequest;
import com.mindprod.isbn.ISBNValidate;
import javax.xml.namespace.QName;
import javax.xml.ws.Holder;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import static java.lang.System.*;
/**
* Find out if a given ISBN/ASIN is in stock using AWS API. D E M O C O D E.
*
* @author Roedy Green, Canadian Mind Products
* @version 1.0 2012-03-26 initial version
* @see com.mindprod.aws.FetchBookFacts
* @see ProbeViaAWS#isAsinInStockViaAWS(String, com.mindprod.stores.OnlineStore)
* @since 2012-03-26
*/
public class IsASINInStock
{
/**
* true if debugging, and want extra output
*/
private static final boolean DEBUGGING = false;
/**
* true if probe amazon.ca , false amazon.com. Surprisingly this is only referenced twice in the program.
*/
private static final boolean IS_CANADIAN = true;
/**
* fetch public amazon.com-assigned associateTag from environment set awsassociatetag=xxxxx
*/
private static final String ASSOCIATE_TAG = IS_CANADIAN ? System.getenv( "awsassociatetagca" ) : System.getenv(
"awsassociatetag" );
/**
* fetch confidential amazon.com-assigned awsAccessKeyId from environment set awsaccesskeyid=xxxxx
*/
private static final String AWS_ACCESS_KEY_ID = System.getenv( "awsaccesskeyid" );
/**
* fetch confidential amazon.com-assigned awsSecretAccessKey assigned by Amazon set awssecretaccesskey=xxxxx
*/
private static final String AWS_SECRET_ACCESS_KEY = System.getenv( "awssecretaccesskey" );
/**
* identifies the context in which names should be interpreted in the schema.
* Why do we need to specify this? It appears FOUR times in the wsdl file. Perhaps as a check the code
* matches the generated Java.
*/
private static final String NAME_SPACE_URI = "http://webservices.amazon.com/AWSECommerceService/2013-08-01";
/**
* name of the SOAP service
*/
private static final String QNAME = "AWSECommerceService";
/**
* location of JAX schmo, locally cached. for amazon.com in the USA. Would have to be modified for other countries.
* Original came from http://ecs.amazonaws.com/AWSECommerceService/AWSECommerceService.wsd
* Both Amazon.ca and Amazon.com use the same WSDL.
*/
private static final String WSDL_LOCATION = "file:///E:/com/mindprod/aws/jax/AWSECommerceService.wsdl";
/**
* standard boilerplate to connect to amazon.com AWS server with SOAP
*
* @return port to use to send requests.
* @throws java.net.MalformedURLException if some URLs were mis-specified in the following code.
*/
private static AWSECommerceServicePortType getPort() throws MalformedURLException
{
AWSECommerceService service = new AWSECommerceService( new URL( WSDL_LOCATION ), new QName( NAME_SPACE_URI,
QNAME ) );
service.setHandlerResolver( new AwsHandlerResolver( AWS_SECRET_ACCESS_KEY ) );
return IS_CANADIAN ? service.getAWSECommerceServicePortCA() : service.getAWSECommerceServicePort();
}
/**
* probe the amazon AWS api to find if a given asin is in stock.
*
* @param asin Amazon part number
*
* @return true if product is in stock.
* @throws java.net.MalformedURLException if generated URL is malformed
*/
private static boolean isAsinInStock( final String asin ) throws MalformedURLException
{
final AWSECommerceServicePortType port = getPort();
final ItemLookup itemLookup = new ItemLookup();
final ItemLookupRequest itemLookupRequest = new ItemLookupRequest();
final List<ItemLookupRequest> itemLookupRequests = itemLookup.getRequest();
itemLookupRequests.add( itemLookupRequest );
itemLookupRequest.setIdType( "ASIN" );
itemLookupRequest.getItemId().add( asin );
itemLookupRequest.setMerchantId( "All" );
itemLookupRequest.setCondition( "All" );
final List<String> responseGroup = itemLookupRequest.getResponseGroup();
responseGroup.add( "Offers" );
final Holder<OperationRequest> operationRequest = new Holder<>();
final Holder<List<Items>> items = new Holder<>();
final String marketplaceDomain = "";
final String xmlEscaping = "Single";
final String validate = "";
port.itemLookup( marketplaceDomain, AWS_ACCESS_KEY_ID, ASSOCIATE_TAG, validate, xmlEscaping,
itemLookupRequest, itemLookupRequests, operationRequest, items );
final List<Items> result = items.value;
final int size = result.get( 0 ).getItem().size();
for ( int i = 0; i < size; i++ )
{
final Item item = result.get( 0 ).getItem().get( i );
for ( Offer offer : item.getOffers().getOffer() )
{
for ( OfferListing offerListing : offer.getOfferListing() )
{
final String availabilityType = offerListing.getAvailabilityAttributes().getAvailabilityType();
if ( true )
{
out.println( "asin = " + asin + " availabilityType = " + availabilityType );
}
if ( availabilityType.equals( "now" ) )
{
return true;
}
}
}
}
return false;
}
/**
* convert isbn13 to asin
*
* @param isbn13 isbn13
*
* @return corresponding asin, if no match, returns null.
* @throws java.net.MalformedURLException if generated URL is malformed.
*/
private static String isbnToAsin( final String isbn13 ) throws MalformedURLException
{
final AWSECommerceServicePortType port = getPort();
final ItemLookup itemLookup = new ItemLookup();
final ItemLookupRequest itemLookupRequest = new ItemLookupRequest();
final List<ItemLookupRequest> itemLookupRequests = itemLookup.getRequest();
itemLookupRequests.add( itemLookupRequest );
itemLookupRequest.setSearchIndex( "Books" );
itemLookupRequest.setIdType( "EAN" );
itemLookupRequest.getItemId().add( isbn13 );
itemLookupRequest.setMerchantId( "All" );
itemLookupRequest.setCondition( "All" );
final List<String> responseGroup = itemLookupRequest.getResponseGroup();
responseGroup.add( "ItemAttributes" );
final Holder<OperationRequest> operationrequest = new Holder<>();
final Holder<List<Items>> items = new Holder<>();
final String marketplaceDomain = "";
final String xmlEscaping = "Single";
final String validate = "";
port.itemLookup( marketplaceDomain, AWS_ACCESS_KEY_ID, ASSOCIATE_TAG, validate, xmlEscaping,
itemLookupRequest, itemLookupRequests, operationrequest, items );
final List<Items> result = items.value;
final int size = result.get( 0 ).getItem().size();
for ( int i = 0; i < size; i++ )
{
final Item item = result.get( 0 ).getItem().get( i );
final String asin = item.getASIN();
if ( asin != null )
{
return asin;
}
}
return null;
}
/**
* Probe the amazon AWS api for isbn13 or asin to find out if instock.
* Gives extremely inaccurate results compared with going to the website.
* Probes US website.
*
* @param args list of isbn13/asins to probe.
*
* @throws java.io.IOException if trouble reading/writing files
*/
public static void main( String[] args ) throws IOException
{
if ( DEBUGGING )
{
out.println( "ASSOCIATE_TAG = " + ASSOCIATE_TAG );
out.println( "AWS_ACCESS_KEY_ID = " + AWS_ACCESS_KEY_ID );
out.println( "AWS_SECRET_ACCESS_KEY = " + AWS_SECRET_ACCESS_KEY );
}
for ( String arg : args )
{
if ( arg.length() == 13 )
{
final String isbn13 = ISBNValidate.tidyISBN10or13RemovingDashes( arg );
final String asin = isbnToAsin( isbn13 );
if ( asin == null )
{
err.println( isbn13 + " is has no valid asin" );
}
else
{
final boolean inStock = isAsinInStock( asin );
out.println( "isbn13: " + arg + " asin: " + asin + " " + inStock );
}
}
else
{
final boolean inStock = isAsinInStock( arg );
out.println( "asin: " + arg + " " + inStock );
}
}
}
}