Subversion Repositories SmartDukaan

Rev

Rev 10457 | Blame | Compare with Previous | Last modification | View Log | RSS feed

package com.amazonservices.mws.orders.samples;

import in.shop2020.feeds.products.AmazonEnvelope;
import in.shop2020.feeds.products.AmazonEnvelope.Message;
import in.shop2020.feeds.products.OrderAcknowledgement;
import in.shop2020.feeds.products.Header;
import in.shop2020.logistics.LogisticsServiceException;
import in.shop2020.logistics.PickUpType;
import in.shop2020.model.v1.inventory.AmazonInventorySnapshot;
import in.shop2020.model.v1.order.AmazonOrdersToAcknowledge;
import in.shop2020.model.v1.order.OrderSource;
import in.shop2020.model.v1.order.OrderType;
import in.shop2020.model.v1.order.SourceDetail;
import in.shop2020.model.v1.order.TransactionServiceException;
import in.shop2020.model.v1.order.TransactionStatus;
import in.shop2020.model.v1.user.User;
import in.shop2020.model.v1.user.UserContextException;
import in.shop2020.payments.PaymentException;
import in.shop2020.payments.PaymentStatus;
import in.shop2020.thrift.clients.InventoryClient;
import in.shop2020.thrift.clients.PaymentClient;
import in.shop2020.thrift.clients.TransactionClient;
import in.shop2020.thrift.clients.UserClient;
import in.shop2020.utils.GmailUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.math.BigInteger;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import com.amazonaws.mws.model.SubmitFeedRequest;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.transform.Result;

import org.apache.http.HttpStatus;
import org.apache.thrift.TException;
import org.apache.thrift.transport.TTransportException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.amazonaws.mws.MarketplaceWebService;
import com.amazonaws.mws.MarketplaceWebServiceClient;
import com.amazonaws.mws.MarketplaceWebServiceConfig;
import com.amazonaws.mws.MarketplaceWebServiceException;
import com.amazonaws.mws.model.FeedSubmissionInfo;
import com.amazonaws.mws.model.IdList;
import com.amazonaws.mws.model.ResponseMetadata;
import com.amazonaws.mws.model.SubmitFeedRequest;
import com.amazonaws.mws.model.SubmitFeedResponse;
import com.amazonaws.mws.model.SubmitFeedResult;
import com.amazonservices.mws.orders.MarketplaceWebServiceOrders;
import com.amazonservices.mws.orders.MarketplaceWebServiceOrdersClient;
import com.amazonservices.mws.orders.MarketplaceWebServiceOrdersException;
import com.amazonservices.mws.orders.model.FulfillmentChannelEnum;
import com.amazonservices.mws.orders.model.ListOrderItemsByNextTokenRequest;
import com.amazonservices.mws.orders.model.ListOrderItemsByNextTokenResponse;
import com.amazonservices.mws.orders.model.ListOrderItemsByNextTokenResult;
import com.amazonservices.mws.orders.model.ListOrderItemsRequest;
import com.amazonservices.mws.orders.model.ListOrderItemsResponse;
import com.amazonservices.mws.orders.model.ListOrderItemsResult;
import com.amazonservices.mws.orders.model.ListOrdersByNextTokenRequest;
import com.amazonservices.mws.orders.model.ListOrdersByNextTokenResponse;
import com.amazonservices.mws.orders.model.ListOrdersByNextTokenResult;
import com.amazonservices.mws.orders.model.ListOrdersRequest;
import com.amazonservices.mws.orders.model.ListOrdersResponse;
import com.amazonservices.mws.orders.model.ListOrdersResult;
import com.amazonservices.mws.orders.model.MarketplaceIdList;
import com.amazonservices.mws.orders.model.Order;
import com.amazonservices.mws.orders.model.OrderItem;
import com.amazonservices.mws.orders.model.OrderStatusEnum;
import com.amazonservices.mws.orders.model.OrderStatusList;

/**
 * This sample illustrates continuous order updates retrieval. It contains a
 * order updates fetcher job that fetches updates every 15 minutes.
 */

public class FetchOrderUpdatesJob {

        /*
         * Add required parameters in OrdersConfig.java before trying out this
         * sample.
         */

        public static final Log log = LogFactory.getLog(OrderFetcherSample.class);
        //private volatile boolean keepRunning = true;
        private boolean keepRunning = true;
        /*************************************
         * Throttling Limits in Milliseconds *
         *************************************/
        // 1 call per 10 mins
        static final long LIST_ORDERS_THROTTLE_LIMIT = 600000L;
        // 1 call per 12 secs
        static final long LIST_ORDER_ITEMS_THROTTLE_LIMIT = 12000L;

        final public static String AMAZON_ORDER_ACKNOWLEDGEMENT_XML = "/home/vikram/OrderAcknowledgeMent.xml";

        static final int INTERVAL_IN_MINS = 30; // 1-minute update interval

        //static final int INTERVAL_IN_MINS = 15; // 15-minute update interval

        protected MarketplaceWebServiceOrders service;
        protected String sellerId = null;
        protected MarketplaceIdList marketplaceIdList = null;
        private File file;

        public FetchOrderUpdatesJob(
                        MarketplaceWebServiceOrders marketplaceWebServiceOrdersClient,
                        String sellerId, MarketplaceIdList marketplaceIdList) {
                if (marketplaceWebServiceOrdersClient == null) {
                        throw new IllegalArgumentException(
                        "MarketplaceWebServiceOrders object cannot be null.");
                }
                this.service = marketplaceWebServiceOrdersClient;
                this.sellerId = sellerId;
                this.marketplaceIdList = marketplaceIdList;
        }

        public static void main(String... args) {
                MarketplaceWebServiceOrders client = new MarketplaceWebServiceOrdersClient(
                                OrdersConfig.accessKeyId,
                                OrdersConfig.secretAccessKey,
                                OrdersConfig.applicationName,
                                OrdersConfig.applicationVersion,
                                OrdersConfig.config);
                final FetchOrderUpdatesJob orderFetcher = new FetchOrderUpdatesJob(
                                client, OrdersConfig.sellerId,
                                OrdersConfig.marketplaceIdList);

                /*      Thread fetchOrderUpdatesJobThread = new Thread(new Runnable() {
                        public void run() {
                                orderFetcher.startPeriodicSynch();
                        }
                });

                // Start the FetchOrderUpdatesJobandAcknowledge in the second thread.
                fetchOrderUpdatesJobThread.start();

                /*
                 * The following code puts this thread to sleep for an hour and then the
                 * stopSynch() method is called which stops the job in the second
                 * thread.
                 */

                /*
                 * 
                 * for some other length of time .
                 */
                try {
                        orderFetcher.startPeriodicSynch();
                        //log.info("Main thread sleeping.");
                        //Thread.sleep(3600000L); // = 1 hour
                        //log.info("Main thread awake.");
                } catch (Exception e) {
                        log.error(e.getMessage(), e);
                        return;
                }

                //log.info("Main thread setting keepRunning to false.");
                //orderFetcher.stopSynch(); // Stops the FetchOrderUpdatesJobandAcknowledge thread.

                // Join the two threads and wait for the fetchOrderUpdatesJobThread to
                // finish.

                /*      try {
                        fetchOrderUpdatesJobThread.join();
                } catch (InterruptedException e) {
                        log.error(e.getMessage(), e);
                        return;
                }*/
        }

        /**
         * Call this method to start this job. Note that the job will run until the
         * keepRunning flag is set to false.
         */
        public void startPeriodicSynch() {

                DatatypeFactory df = null;
                try {
                        df = DatatypeFactory.newInstance();
                } catch (DatatypeConfigurationException e) {
                        log.error(e.getMessage(), e);
                }
                TransactionClient tcl=null;
                long time=0;
                try {
                        tcl = new TransactionClient();
                        time = tcl.getClient().getSourceDetail(3).getLastUpdatedOn();
                } catch (TException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                }


                GregorianCalendar Time = new GregorianCalendar();
                Time.setTimeInMillis(time);
                XMLGregorianCalendar startTime = df.newXMLGregorianCalendar(Time);
                // endTime = now -2. So, startTime = now - 2 - INTERVAL_IN_MINS.
                System.out.println("Sync job start time." + startTime.getDay() +"-"+ startTime.getMonth()+"-" + startTime.getHour()+":"+startTime.getMinute());


                //startTime.add(df.newDurationDayTime(false, 0, 0, INTERVAL_IN_MINS ,   0));
                //System.out.println("Sync job start time after add .." + startTime.getDay() +"-"+ startTime.getMonth()+"-" + startTime.getHour()+":"+startTime.getMinute());
                /*
                 * This loop keeps running until the stopSynch() method is called.
                 * stopSynch() sets keepRunning to false.
                 */
                System.out.println("Sync job starting.");
                log.info("Sync job starting.");
                while (keepRunning) {
                        // Subtract 2 minutes because endTime returned from server = now - 2
                        // mins.
                        long timeWaited = System.currentTimeMillis()
                        - startTime.toGregorianCalendar().getTimeInMillis()
                        - 120000;

                        System.out.println("Time waited : " + timeWaited/60000 + "Minutes");
                        /*
                         * If the timeWaited is greater than 30 times the interval, we exit
                         * from the loop as the job is lagging far behind in getting new
                         * orders.
                         */
                        //if (timeWaited > 24 * 4 * INTERVAL_IN_MINS * 60L * 1000L) {
                        if (timeWaited > 100000 * 60L * 1000L) {        
                                keepRunning = false;
                                System.out.println("Setting keep running to false");
                                log.info("timeWaited is greater than 30 times the interval. This a too large a time interval for which to fetch orders.");
                        }
                        /*
                         * If the time lapsed is greater than or equal to 15 mins, we will
                         * try to fetchOrderUpdates giving it a startTime.
                         */
                        else if (timeWaited >= INTERVAL_IN_MINS * 60L * 1000L) {
                                log.info("Time to fetch new order updates.");

                                XMLGregorianCalendar endTime = fetchOrderUpdatesSince(startTime);
                                //System.out.println("End Time is : " + endTime.getDay() +"-"+ endTime.getMonth()+"-" + endTime.getHour()+":"+endTime.getMinute());
                                //createandsubmitOrderAcknowlegementFeed();
                                if (endTime != null) {
                                        startTime = endTime;

                                        try {
                                                tcl.getClient().updateSourceDetailTimestamp(3,endTime.toGregorianCalendar().getTimeInMillis());
                                        } catch (TException e) {
                                                // TODO Auto-generated catch block
                                                e.printStackTrace();
                                        }
                                } else {
                                        log.info("endTime returned is null. Sleeping for "
                                                        + INTERVAL_IN_MINS + " minutes.");
                                        try {
                                                Thread.sleep(INTERVAL_IN_MINS * 60L * 1000L);
                                        } catch (InterruptedException e) {
                                                log.error(e.getMessage(), e);
                                                stopSynch();
                                                break;
                                        }
                                }
                        } else {
                                try {
                                        long timeToSleepInMilliseconds = INTERVAL_IN_MINS * 60000L
                                        - timeWaited;
                                        log.info("Thread sleeping for "
                                                        + Math.round(timeToSleepInMilliseconds / 60000)
                                                        + " minutes.");
                                        // Sleep in 1 minute intervals for timeToSleepInMilliseconds
                                        // or until keepRunning is set to false.
                                        for (long i = timeToSleepInMilliseconds; i > 0
                                        && keepRunning; i = i - 60000L) {
                                                if (i < 60000L) {
                                                        Thread.sleep(i);
                                                } else {
                                                        Thread.sleep(60000L);
                                                }
                                        }

                                } catch (InterruptedException e) {
                                        log.error(e.getMessage(), e);
                                        stopSynch();
                                        break;
                                }
                        }
                }
                log.info("Sync job ending.");
        }

        /**
         * Call this method to stop execution of this job. The job will stop after
         * it has finished processing the current call (if it is in the middle of
         * processing any). For example if a listOrders call has been invoked, then
         * it will terminate the job only after the call returns with valid results.
         * If this method is called while the thread is sleeping, because a request
         * was throttled, the job will terminate after it wakes up.
         */
        public void stopSynch() {
                //keepRunning = false;
        }

        /**
         * Gets all orders updated between the given startTime and the calculated
         * endTime. The endTime is calculated by the service as server's system
         * clock time minus 2 mins. The method returns this endTime.
         * 
         */
        protected XMLGregorianCalendar fetchOrderUpdatesSince(
                        XMLGregorianCalendar startTime) {
                System.out.println("Fetching order updates since " + startTime.toString());
                log.info("Fetching order updates since " + startTime.toString());
                ListOrdersRequest listOrdersRequest = new ListOrdersRequest();

                listOrdersRequest.setSellerId(sellerId);
                if (OrdersConfig.marketplaceIdList != null) {
                        listOrdersRequest
                        .setMarketplaceId(OrdersConfig.marketplaceIdList);
                }
                listOrdersRequest.setLastUpdatedAfter(startTime);
                OrderStatusList statusList = new OrderStatusList();
                List<OrderStatusEnum> orderstatusList = new ArrayList<OrderStatusEnum>();
                orderstatusList.add(OrderStatusEnum.UNSHIPPED);
                orderstatusList.add(OrderStatusEnum.PARTIALLY_SHIPPED);
                //orderstatusList.add(OrderStatusEnum.CANCELED);

                statusList.setStatus(orderstatusList);
                listOrdersRequest.setOrderStatus(statusList);
                XMLGregorianCalendar lastUpdatedDate = null;

                try {
                        ListOrdersResult listOrdersResult = listOrders(listOrdersRequest);
                        if (listOrdersResult.isSetLastUpdatedBefore()) {
                                lastUpdatedDate = listOrdersResult.getLastUpdatedBefore();
                        }

                        if (listOrdersResult != null && listOrdersResult.isSetNextToken()) {
                                ListOrdersByNextTokenRequest listOrdersByNextTokenRequest = new ListOrdersByNextTokenRequest();
                                listOrdersByNextTokenRequest.setSellerId(sellerId);
                                String nextToken = listOrdersResult.getNextToken();
                                ListOrdersByNextTokenResult listOrdersByNextTokenResult = null;
                                while (nextToken != null && keepRunning) {
                                        listOrdersByNextTokenRequest.setNextToken(nextToken);
                                        listOrdersByNextTokenResult = listOrdersByNextToken(listOrdersByNextTokenRequest);
                                        nextToken = listOrdersByNextTokenResult.getNextToken();
                                }
                                if (listOrdersByNextTokenResult.isSetLastUpdatedBefore()) {
                                        lastUpdatedDate = listOrdersByNextTokenResult
                                        .getLastUpdatedBefore();
                                }
                        }
                        return lastUpdatedDate;
                } catch (MarketplaceWebServiceOrdersException ex) {
                        log.error(ex.getMessage(), ex);
                        System.out.println("Caught Exception: " + ex.getMessage());
                        System.out.println("Response Status Code: " + ex.getStatusCode());
                        System.out.println("Error Code: " + ex.getErrorCode());
                        System.out.println("Error Type: " + ex.getErrorType());
                        System.out.println("Request ID: " + ex.getRequestId());
                        System.out.print("XML: " + ex.getXML());
                        return null;
                }
        }
        //This method will create Order Acknowledgement FEED
        public void createandsubmitOrderAcknowlegementFeed() {
                TransactionClient tcl=null;
                List<AmazonOrdersToAcknowledge> amazonOrdersToAcknowledge=null;
                try {
                        tcl = new TransactionClient();
                        amazonOrdersToAcknowledge = tcl.getClient().getAmazonOrdersToAcknowledge(OrderSource.AMAZON);
                } catch (TTransportException e2) {
                        // TODO Auto-generated catch block
                        e2.printStackTrace();
                } catch (TException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                }
                if(amazonOrdersToAcknowledge!=null && amazonOrdersToAcknowledge.size() > 0){
                        file = new File(AMAZON_ORDER_ACKNOWLEDGEMENT_XML);
                        AmazonEnvelope amazonenvelope = new AmazonEnvelope();
                        Header header = new Header();
                        header.setDocumentVersion("1.0");
                        header.setMerchantIdentifier("AF6E3O0VE0X4D");
                        header.setOverrideReleaseId(null);
                        amazonenvelope.setHeader(header);
                        amazonenvelope.setMessageType("OrderAcknowledgement");
                        amazonenvelope.setMarketplaceName(null);
                        List<Message> messages = amazonenvelope.getMessage();
                        Map<String,Long> amazonOrdertxnMap = new HashMap<String,Long>();
                        Map<String,List<String>> amazonOrderIdOrderItemMap = new HashMap<String,List<String>>();
                        Map<String,Integer> amazonOrderItemSuccessMap = new HashMap<String,Integer>();
                        Map<String,Integer> amazonOrderItemFailureMap = new HashMap<String,Integer>();
                        for(AmazonOrdersToAcknowledge amazonOrderToAcknowledge:amazonOrdersToAcknowledge ){
                                if(!amazonOrdertxnMap.containsKey(amazonOrderToAcknowledge.getAmazonOrderId())){
                                        amazonOrdertxnMap.put(amazonOrderToAcknowledge.getAmazonOrderId(),amazonOrderToAcknowledge.getTransaction_id());
                                }
                                if(!amazonOrderIdOrderItemMap.containsKey(amazonOrderToAcknowledge.getAmazonOrderId())){
                                        List<String> orderItemsList = new ArrayList<String>();
                                        orderItemsList.add(amazonOrderToAcknowledge.getAmazonOrderItemId());
                                        amazonOrderIdOrderItemMap.put(amazonOrderToAcknowledge.getAmazonOrderId(),orderItemsList);
                                }
                                else{
                                        if(!amazonOrderIdOrderItemMap.get(amazonOrderToAcknowledge.getAmazonOrderId()).contains(amazonOrderToAcknowledge.getAmazonOrderItemId()))
                                                amazonOrderIdOrderItemMap.get(amazonOrderToAcknowledge.getAmazonOrderId()).add(amazonOrderToAcknowledge.getAmazonOrderItemId());
                                }
                                if(amazonOrderToAcknowledge.getStatus().equals("Order-Payment-Success")){
                                        amazonOrderItemSuccessMap.put(amazonOrderToAcknowledge.getAmazonOrderId()+amazonOrderToAcknowledge.getAmazonOrderItemId(),amazonOrderToAcknowledge.getCount());
                                }
                                if(amazonOrderToAcknowledge.getStatus().equals("Order-Payment-Failure")){
                                        amazonOrderItemFailureMap.put(amazonOrderToAcknowledge.getAmazonOrderId()+amazonOrderToAcknowledge.getAmazonOrderItemId(),amazonOrderToAcknowledge.getCount());
                                }       
                        }
                        JAXBContext context;
                        Marshaller m=null;
                        try {
                                context = JAXBContext.newInstance(AmazonEnvelope.class);
                                m = context.createMarshaller();
                        } catch (JAXBException e1) {
                                // TODO Auto-generated catch block
                                e1.printStackTrace();
                        }

                        for (Map.Entry<String,List<String>> entry : amazonOrderIdOrderItemMap.entrySet()){
                                OrderAcknowledgement orderAcknowLedgement = new OrderAcknowledgement();
                                List<OrderAcknowledgement.Item> acknowledgementItems = orderAcknowLedgement.getItem();
                                String orderid = entry.getKey();
                                orderAcknowLedgement.setAmazonOrderID(orderid);
                                orderAcknowLedgement.setMerchantOrderID(amazonOrdertxnMap.get(orderid).toString());
                                orderAcknowLedgement.setStatusCode("Failure");
                                for(String orderItemId :entry.getValue()){
                                        OrderAcknowledgement.Item orderAcknowledgementItem = new OrderAcknowledgement.Item();
                                        if(amazonOrderItemSuccessMap.get(orderid+orderItemId)!=null && amazonOrderItemSuccessMap.get(orderid+orderItemId) > 0){
                                                orderAcknowledgementItem.setAmazonOrderItemCode(orderItemId);
                                                orderAcknowLedgement.setStatusCode("Success");
                                        }
                                        else{
                                                orderAcknowledgementItem.setAmazonOrderItemCode(orderItemId);
                                                orderAcknowledgementItem.setCancelReason("ShippingAddressUndeliverable");
                                        }
                                        acknowledgementItems.add(orderAcknowledgementItem);

                                }
                                AmazonEnvelope.Message message = new AmazonEnvelope.Message();
                                Random rand = new Random();
                                message.setMessageID(BigInteger.valueOf(Math.abs(rand.nextInt())));
                                message.setOrderAcknowledgement(orderAcknowLedgement);
                                messages.add(message);
                        }

                        System.out.println("Messages is " + messages);
                        try {
                                m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
                                m.marshal(amazonenvelope, file);
                                m.marshal(amazonenvelope, System.out);

                        } catch (Exception e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();

                        }
                        if(submitAcknowledgementFeed()==0);
                        //if(true)
                        {
                                for (Map.Entry<String,Long> entry : amazonOrdertxnMap.entrySet()){
                                        try {
                                                tcl.getClient().changeAmazonOrderStatus(entry.getKey(),"Acknowledgement-Sent");
                                        } catch (TException e) {
                                                // TODO Auto-generated catch block
                                                e.printStackTrace();
                                        }
                                        
                                }
                        }
//                      GmailUtils  gm = GmailUtils();
//                      gm.sendSSLMessage(arg0, arg1, arg2, arg3, arg4, arg5)
                }


        }

        /*
         * listOrders call. If a request is throttled, this method calls the
         * throttling handler and sets the retry flag to true.
         */
        protected ListOrdersResult listOrders(ListOrdersRequest request)
        throws MarketplaceWebServiceOrdersException {
                boolean retry;
                ListOrdersResponse listOrdersResponse = null;
                ListOrdersResult listOrdersResult = null;
                do {
                        retry = false;
                        try {
                                System.out.println("Calling ListOrders.");
                                log.info("Calling ListOrders.");
                                listOrdersResponse = service.listOrders(request);
                        } catch (MarketplaceWebServiceOrdersException ex) {
                                if (ex.getStatusCode() == HttpStatus.SC_SERVICE_UNAVAILABLE
                                                && "RequestThrottled".equals(ex.getErrorCode())) {
                                        retry = true;
                                        requestThrottledExceptionHandler(LIST_ORDERS_THROTTLE_LIMIT);
                                } else {
                                        throw ex;
                                }
                        }
                        if (listOrdersResponse != null
                                        && listOrdersResponse.isSetListOrdersResult()) {
                                listOrdersResult = listOrdersResponse.getListOrdersResult();
                                if (listOrdersResult.isSetOrders()
                                                && listOrdersResult.getOrders().isSetOrder()) {
                                        processOrderUpdates(listOrdersResult.getOrders().getOrder());
                                }
                        }
                } while (retry && keepRunning);
                return listOrdersResult;
        }

        /*
         * listOrdersByNextToken call. If a request is throttled, this method calls
         * the throttling handler and sets the retry flag to true.
         */
        protected ListOrdersByNextTokenResult listOrdersByNextToken(
                        ListOrdersByNextTokenRequest listOrdersByNextTokenRequest)
        throws MarketplaceWebServiceOrdersException {
                boolean retry;
                ListOrdersByNextTokenResponse listOrdersByNextTokenResponse = null;
                ListOrdersByNextTokenResult listOrdersByNextTokenResult = null;
                do {
                        retry = false;
                        try {
                                log.info("Calling ListOrdersByNextToken.");
                                listOrdersByNextTokenResponse = service
                                .listOrdersByNextToken(listOrdersByNextTokenRequest);
                        } catch (MarketplaceWebServiceOrdersException ex) {
                                if (ex.getStatusCode() == HttpStatus.SC_SERVICE_UNAVAILABLE
                                                && "RequestThrottled".equals(ex.getErrorCode())) {
                                        retry = true;
                                        requestThrottledExceptionHandler(LIST_ORDERS_THROTTLE_LIMIT);
                                } else {
                                        throw ex;
                                }
                        }
                        if (listOrdersByNextTokenResponse != null
                                        && listOrdersByNextTokenResponse
                                        .isSetListOrdersByNextTokenResult()) {
                                listOrdersByNextTokenResult = listOrdersByNextTokenResponse
                                .getListOrdersByNextTokenResult();
                                if (listOrdersByNextTokenResult.isSetOrders()
                                                && listOrdersByNextTokenResult.getOrders().isSetOrder()) {
                                        processOrderUpdates(listOrdersByNextTokenResult.getOrders()
                                                        .getOrder());
                                }
                        }
                } while (retry && keepRunning);
                return listOrdersByNextTokenResult;
        }

        /**
         * This method is called to process updates on each of the orders that are
         * returned by the ListOrders and ListOrdersByNextToken calls.
         */
        protected void processOrderUpdates(List<Order> orders)
        throws MarketplaceWebServiceOrdersException {
                ListOrderItemsResult listOrderItemsResult;
                log.info("Processing order updates.");
                for (Order order : orders) {
                        if (shouldFetchOrderItems(order)) {
                                log.info("Order being processed: " + order.getAmazonOrderId());
                                listOrderItemsResult = listOrderItems(order);
                                if (listOrderItemsResult != null
                                                && listOrderItemsResult.isSetNextToken()) {
                                        ListOrderItemsByNextTokenRequest listOrderItemsByNextTokenRequest = new ListOrderItemsByNextTokenRequest();
                                        listOrderItemsByNextTokenRequest
                                        .setSellerId(OrdersConfig.sellerId);
                                        String nextToken = listOrderItemsResult.getNextToken();

                                        ListOrderItemsByNextTokenResult listOrderItemsByNextTokenResult = null;

                                        while (nextToken != null && keepRunning) {
                                                listOrderItemsByNextTokenRequest
                                                .setNextToken(nextToken);
                                                listOrderItemsByNextTokenResult = listOrderItemsByNextToken(
                                                                listOrderItemsByNextTokenRequest, order);
                                                nextToken = listOrderItemsByNextTokenResult
                                                .getNextToken();
                                        }
                                }
                        }
                }
        }

        /*
         * listOrderItems call. If a request is throttled, this method calls the
         * throttling handler and sets the retry flag to true.
         */
        protected ListOrderItemsResult listOrderItems(Order order)
        throws MarketplaceWebServiceOrdersException {
                System.out.println("Calling ListOrderItems.");
                log.info("Calling ListOrderItems.");
                boolean retry;
                List<OrderItem> items;
                ListOrderItemsRequest listOrderItemsRequest = new ListOrderItemsRequest();
                listOrderItemsRequest.setSellerId(sellerId);
                listOrderItemsRequest.setAmazonOrderId(order.getAmazonOrderId());
                ListOrderItemsResponse listOrderItemsResponse = null;
                ListOrderItemsResult listOrderItemsResult = null;

                do {
                        retry = false;
                        try {
                                listOrderItemsResponse = service
                                .listOrderItems(listOrderItemsRequest);
                        } catch (MarketplaceWebServiceOrdersException ex) {
                                if (ex.getStatusCode() == HttpStatus.SC_SERVICE_UNAVAILABLE
                                                && "RequestThrottled".equals(ex.getErrorCode())) {
                                        retry = true;
                                        requestThrottledExceptionHandler(LIST_ORDER_ITEMS_THROTTLE_LIMIT);
                                } else {
                                        throw ex;
                                }
                        }
                        if (listOrderItemsResponse != null
                                        && listOrderItemsResponse.isSetListOrderItemsResult()) {
                                listOrderItemsResult = listOrderItemsResponse
                                .getListOrderItemsResult();
                                if (listOrderItemsResult.isSetOrderItems()
                                                && listOrderItemsResult.getOrderItems()
                                                .isSetOrderItem()) {
                                        items = listOrderItemsResponse.getListOrderItemsResult()
                                        .getOrderItems().getOrderItem();
                                        processOrderItems(order, items);
                                }
                        }

                } while (retry && keepRunning);

                return listOrderItemsResult;
        }

        /*
         * listOrderItemsByNextToken call. If a request is throttled, this method
         * calls the throttling handler and sets the retry flag to true.
         */
        protected ListOrderItemsByNextTokenResult listOrderItemsByNextToken(
                        ListOrderItemsByNextTokenRequest listOrderItemsByNextTokenRequest,
                        Order order) throws MarketplaceWebServiceOrdersException {
                log.info("Calling ListOrderItemsByNextToken.");
                boolean retry;
                List<OrderItem> items;
                ListOrderItemsByNextTokenResponse listOrderItemsByNextTokenResponse = null;
                ListOrderItemsByNextTokenResult listOrderItemsByNextTokenResult = null;

                do {
                        retry = false;
                        try {
                                listOrderItemsByNextTokenResponse = service
                                .listOrderItemsByNextToken(listOrderItemsByNextTokenRequest);
                        } catch (MarketplaceWebServiceOrdersException ex) {
                                if (ex.getStatusCode() == HttpStatus.SC_SERVICE_UNAVAILABLE
                                                && "RequestThrottled".equals(ex.getErrorCode())) {
                                        retry = true;
                                        requestThrottledExceptionHandler(LIST_ORDER_ITEMS_THROTTLE_LIMIT);
                                } else {
                                        throw ex;
                                }
                        }
                        if (listOrderItemsByNextTokenResponse != null
                                        && listOrderItemsByNextTokenResponse
                                        .isSetListOrderItemsByNextTokenResult()) {
                                listOrderItemsByNextTokenResult = listOrderItemsByNextTokenResponse
                                .getListOrderItemsByNextTokenResult();
                                if (listOrderItemsByNextTokenResult.isSetOrderItems()
                                                && listOrderItemsByNextTokenResult.getOrderItems()
                                                .isSetOrderItem()) {
                                        items = listOrderItemsByNextTokenResponse
                                        .getListOrderItemsByNextTokenResult()
                                        .getOrderItems().getOrderItem();
                                        processOrderItems(order, items);
                                }
                        }
                } while (retry && keepRunning);

                return listOrderItemsByNextTokenResult;
        }

        /**
         * Checks if order exists in the system 
         * If not then only processes the order
         */
        protected boolean shouldFetchOrderItems(Order order) {
                TransactionClient tcl=null;
                try {
                        tcl = new TransactionClient();
                        List<in.shop2020.model.v1.order.AmazonOrder> amazonOrderItems = tcl.getClient().getAmazonOrderByAmazonOrderId(order.getAmazonOrderId());
                        if(amazonOrderItems.size()==0){
                                return true;
                        }
                        else{
                                return false;
                        }
                                
                } catch (TException e) {
                        e.printStackTrace();
                }
                return false;
        }

        /**
         * 
         * Processes Order Items
         */
        public void processOrderItems(Order order, List<OrderItem> orderItems) {
                log.info("****************** Order info********************");
                log.info(order.toString());
                System.out.println("------------------------------------------");
                System.out.println("--------Amazon Order Details START--------");
                System.out.println("------------------------------------------");
                System.out.println("Amazon Order ID                  :  " + order.getAmazonOrderId());
                System.out.println("Buyer Email                      :  " + order.getBuyerEmail());
                System.out.println("Buyer Name                       :  " + order.getBuyerName());
                System.out.println("MarketPlace ID                   :  " + order.getMarketplaceId());
                System.out.println("Order Channel                    :  " + order.getOrderChannel());
                System.out.println("Sales Channel                    :  " + order.getSalesChannel());
                System.out.println("Seller Order ID                  :  " + order.getSellerOrderId());
                System.out.println("Shipment Service Level Category  :  " + order.getShipmentServiceLevelCategory());
                System.out.println("Shipment Service Level           :  " + order.getShipServiceLevel());
                System.out.println("TFM Shipment Status              :  " + order.getTFMShipmentStatus());
                System.out.println("Number of Items Shipped          :  " + order.getNumberOfItemsShipped());
                System.out.println("Number of Items UnShipped        :  " + order.getNumberOfItemsUnshipped());
                System.out.println("Fulfillment Channel              :  " + order.getFulfillmentChannel());
                System.out.println("Last Updated Date                :  " + order.getLastUpdateDate());
                System.out.println("Order Status                     :  " + order.getOrderStatus());
                //System.out.println("Order Currency code              :  " + order.getOrderTotal().getCurrencyCode());
                //System.out.println("Order Amount                     :  " + order.getOrderTotal().getAmount());
                System.out.println("Payment Method                   :  " + order.getPaymentMethod());
                System.out.println("Payment Execution Detail         :  " + order.getPaymentExecutionDetail());
                System.out.println("Purchase Date                    :  " + order.getPurchaseDate());
                System.out.println("Shipping Address                 :  " + order.getShippingAddress());
                System.out.println("------------------------------------------");
                System.out.println("-----------Amazon Order Details END-------");
                System.out.println("------------------------------------");
                Map<String,String> orderItemSkuMap = new HashMap<String,String>();
                if (orderItems != null && orderItems.size() > 0) {
                        log.info("================== Order Items info ====================");
                        System.out.println("================== Order Items info ====================");
                        int i = 0;
                        for (OrderItem item : orderItems) {
                                log.info(item.toString());
                                System.out.println("===================================");
                                System.out.println("Order Item : " + (i+1));
                                System.out.println("Item ASIN :  " + item.getASIN());
                                System.out.println("Item Gift Message Text :  " + item.getGiftMessageText());
                                System.out.println("Item Gift Wrap Level   :  " + item.getGiftWrapLevel());
                                System.out.println("Order Item ID          :  " + item.getOrderItemId());
                                System.out.println("Quantity Ordered       :  " + item.getQuantityOrdered());
                                System.out.println("Saholic Item ID        :  " + item.getSellerSKU());
                                System.out.println("Item Description       :  " + item.getTitle());
                                System.out.println("Item Quantity Shipped  :  " + item.getQuantityShipped());
                                System.out.println("Item Quantity Ordered  :  " + item.getQuantityOrdered());
                                System.out.println("COD Fees               :  " + item.getCODFee());
                                System.out.println("COD Fees Discount      :  " + item.getCODFeeDiscount());
                                System.out.println("Gift Wrap Price        :  " + item.getGiftWrapPrice());
                                System.out.println("Gift Wrap Text         :  " + item.getGiftWrapTax());
                                System.out.println("Invoice Data           :  " + item.getInvoiceData());
                                System.out.println("Item Price             :  " + item.getItemPrice());
                                System.out.println("Item Tax               :  " + item.getItemTax());
                                System.out.println("Promotion Discount     :  " + item.getPromotionDiscount());
                                System.out.println("Promotion IDs          :  " + item.getPromotionIds());
                                System.out.println("Shipping Discounts     :  " + item.getShippingDiscount());
                                System.out.println("Shipping Price         :  " + item.getShippingPrice());
                                System.out.println("Shipping Tax           :  " + item.getShippingTax());
                                System.out.println("===================================");
                                orderItemSkuMap.put(item.getSellerSKU(),item.getOrderItemId());
                                System.out.println("SKU and Order Item Code are  : " + item.getSellerSKU() + " " +item.getOrderItemId() );
                                i++;
                        }
                        //if(order.getFulfillmentChannel().equals(FulfillmentChannelEnum.MFN) && (order.getOrderStatus().equals(OrderStatusEnum.UNSHIPPED) || order.getOrderStatus().equals(OrderStatusEnum.CANCELED))){
                        //if(order.getFulfillmentChannel().equals(FulfillmentChannelEnum.MFN) && (order.getOrderStatus().equals(OrderStatusEnum.UNSHIPPED) || order.getOrderStatus().equals(OrderStatusEnum.PARTIALLY_SHIPPED))){
                        if(order.getFulfillmentChannel().equals(FulfillmentChannelEnum.MFN) && order.getOrderStatus().equals(OrderStatusEnum.UNSHIPPED) && order.getSellerOrderId()==null ){
                                String userEmail = order.getBuyerEmail();
                        User user = new User();
                        user.setCommunicationEmail(userEmail);
                        user.setEmail(userEmail);
                        user.setName(order.getBuyerName());
                        user.setMobileNumber(order.getShippingAddress().getPhone());
                        user.setPassword("amazon");
                        try {
                                UserClient ucl = new UserClient();
                                user = ucl.getClient().createUser(user);
                        } catch(Exception e) {
                                //////////////log.error("Unable to get default source", e);
                        }
                        
                        long userId = user.getUserId();
                                AmazonOrder amazonOrder = new AmazonOrder();
                                long txnId = amazonOrder.persistTransaction(userId, user.getActiveCartId(), user.getEmail(), order, orderItems);
                                
                                TransactionClient tcl=null;
                                InventoryClient icl = null;
                                PaymentClient pcl = null;
                                Map<Long,Double> saholicItemMap = new HashMap<Long,Double>();
                                if (txnId != -1){
                                        List<in.shop2020.model.v1.order.AmazonOrder> amazonOrders = new ArrayList<in.shop2020.model.v1.order.AmazonOrder>();
                                        try {
                                                 
                                                tcl = new TransactionClient();
                                                icl = new InventoryClient();
                                                pcl = new PaymentClient();;
                                                System.out.println("temp id is" +userId);
                                                List<in.shop2020.model.v1.order.Order>  saholicOrders =tcl.getClient().getOrdersForTransaction(txnId,userId);
                                                for(in.shop2020.model.v1.order.Order saholicOrder:saholicOrders)
                                                {
                                                        List<in.shop2020.model.v1.order.LineItem> lineitems= saholicOrder.getLineitems();
                                                        long itemId=0; 
                                                        for(in.shop2020.model.v1.order.LineItem lineitem:lineitems){
                                                                itemId = lineitem.getItem_id();
                                                                if(saholicItemMap.get(lineitem.getItem_id())!=null)
                                                                        saholicItemMap.put(lineitem.getItem_id(),saholicItemMap.get(lineitem.getItem_id())+1);
                                                                else
                                                                        saholicItemMap.put(lineitem.getItem_id(),lineitem.getQuantity());       
                                                        }
                                                        in.shop2020.model.v1.order.AmazonOrder aOrder = new in.shop2020.model.v1.order.AmazonOrder();
                                                        aOrder.setAmazonOrderCode(order.getAmazonOrderId());
                                                        aOrder.setAmazonOrderItemCode(orderItemSkuMap.get(Long.toString(itemId)));
                                                        aOrder.setItem_id(itemId);
                                                        aOrder.setOrderId(saholicOrder.getId());
                                                        aOrder.setTransactionId(txnId);
                                                        aOrder.setStatus("Order-Creation-Success");
                                                        tcl.getClient().addAmazonOrder(aOrder);
                                                        amazonOrders.add(aOrder);
                                                }
                                                long merchantPaymentId = pcl.getClient().createPayment(userId, Double.parseDouble(order.getOrderTotal().getAmount()), 15, txnId, false);
                                                pcl.getClient().updatePaymentDetails(merchantPaymentId, "", "", "15", "", "", "", "", "", PaymentStatus.SUCCESS, "", null);
                                                boolean success=tcl.getClient().changeTransactionStatus(txnId, TransactionStatus.AUTHORIZED, "Payment authorized", PickUpType.COURIER.getValue(), OrderType.B2C, OrderSource.AMAZON);
                                                if(success){
                                                        for(in.shop2020.model.v1.order.AmazonOrder aorder:amazonOrders){
                                                                AmazonInventorySnapshot amazonInventorySnapshot=icl.getClient().getAmazonInventoryForItem(aorder.getItem_id());
                                                                long reserved = (amazonInventorySnapshot.getReserved()+1);
                                                                amazonInventorySnapshot.setReserved(reserved);
                                                                icl.getClient().addOrUpdateAmazonInventoryForItem((amazonInventorySnapshot),0);
                                                                tcl.getClient().updateAmazonOrderStatus(aorder.getOrderId(),"Order-Payment-Success");
                                                        }
                                                }
                                        }
                                        catch (TTransportException e) {
                                                try{
                                                        tcl = new TransactionClient();  
                                                }
                                                catch (TTransportException ex) {
                                                        
                                                }
                                                
                                                for(in.shop2020.model.v1.order.AmazonOrder aorder:amazonOrders){
                                                        try {
                                                                tcl.getClient().updateAmazonOrderStatus(aorder.getOrderId(),"Order-Payment-Failure");
                                                        } catch (TException e1) {
                                                                // TODO Auto-generated catch block
                                                                e1.printStackTrace();
                                                        }
                                                }
                                        
                                                //e.printStackTrace();
                                        } catch (TException e) {
                                                // TODO Auto-generated catch block
                                                e.printStackTrace();
                                        } catch (PaymentException e) {
                                                // TODO Auto-generated catch block
                                                e.printStackTrace();
                                        } catch (TransactionServiceException e) {
                                                // TODO Auto-generated catch block
                                                e.printStackTrace();
                                        }
                                }
                        }

                }
        }


        /*
         * When a request is throttled, this method is called to make the thread
         * sleep for a period of time specified by the throttling limit.
         */
        private void requestThrottledExceptionHandler(
                        long throttlingLimitInMilliseconds) {
                try {
                        log.info("Request throttled. Sleeping for "
                                        + throttlingLimitInMilliseconds / 1000 + " seconds.");

                        // Sleep in 1 minute intervals for throttlingLimitInMillis or until
                        // keepRunning is set to false.
                        for (long i = throttlingLimitInMilliseconds; i > 0 && keepRunning; i = i - 60000L) {
                                if (i < 60000L) {
                                        Thread.sleep(i);
                                } else {
                                        Thread.sleep(60000L);
                                }
                        }
                } catch (InterruptedException e) {
                        log.error(e.getMessage(), e);
                        return;
                }
        }

        public static String computeContentMD5HeaderValue( FileInputStream fis) {
                try {
                        DigestInputStream dis = new DigestInputStream( fis,
                                        MessageDigest.getInstance( "MD5" ));
                        byte[] buffer = new byte[8192];
                        while( dis.read( buffer ) > 0 );
                        String md5Content = new String(Base64.encodeBase64(dis.getMessageDigest().digest())
                        );
                        // Effectively resets the stream to be beginning of the file via a
                        fis.getChannel().position( 0 );
                        return md5Content;
                } catch (NoSuchAlgorithmException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                }
                return null;

        }

        public int submitAcknowledgementFeed(){

                SubmitFeedRequest request= new SubmitFeedRequest();
                final String merchantId = "AF6E3O0VE0X4D";      
                // marketplaces to which this feed will be submitted; look at the
                // API reference document on the MWS website to see which marketplaces are
                // included if you do not specify the list yourself
                final IdList marketplaces = new IdList(Arrays.asList(
                "A21TJRUUN4KGV"));
                request.setMerchant(merchantId);
                FileInputStream fis=null;
                try {
                        fis = new FileInputStream(AMAZON_ORDER_ACKNOWLEDGEMENT_XML);
                } catch (FileNotFoundException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                        return -1;
                }
                final String accessKeyId = "AKIAII3SGRXBJDPCHSGQ";
                final String secretAccessKey = "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";

                final String appName = "Test";
                final String appVersion = "1.0";

                MarketplaceWebServiceConfig config = new MarketplaceWebServiceConfig();

                // India
                config.setServiceURL("https://mws.amazonservices.in");

                request.setContentMD5(computeContentMD5HeaderValue(fis));
                request.setFeedContent(fis);
                request.setMarketplaceIdList(marketplaces);
                request.setFeedType("_POST_ORDER_ACKNOWLEDGEMENT_DATA_");
                MarketplaceWebService s_service = new MarketplaceWebServiceClient(
                                accessKeyId, secretAccessKey, appName, appVersion, config);

                try {

                        SubmitFeedResponse response = s_service.submitFeed(request);

                        System.out.println("SubmitFeed Action Response");
                        System.out
                        .println("=============================================================================");
                        System.out.println();

                        System.out.print("    SubmitFeedResponse");
                        System.out.println();
                        if (response.isSetSubmitFeedResult()) {
                                System.out.print("        SubmitFeedResult");
                                //      System.out.println();
                                SubmitFeedResult submitFeedResult = response
                                .getSubmitFeedResult();
                                if (submitFeedResult.isSetFeedSubmissionInfo()) {
                                        //      System.out.print("            FeedSubmissionInfo");
                                        //      System.out.println();
                                        FeedSubmissionInfo feedSubmissionInfo = submitFeedResult
                                        .getFeedSubmissionInfo();
                                        if (feedSubmissionInfo.isSetFeedSubmissionId()) {
                                                System.out.print("                FeedSubmissionId");
                                                System.out.println();
                                                System.out.print("                    "
                                                                + feedSubmissionInfo.getFeedSubmissionId());

                                                System.out.println();
                                        }
                                        if (feedSubmissionInfo.isSetFeedType()) {
                                                System.out.print("                FeedType");
                                                System.out.println();
                                                System.out.print("                    "
                                                                + feedSubmissionInfo.getFeedType());
                                                System.out.println();
                                        }
                                        if (feedSubmissionInfo.isSetSubmittedDate()) {
                                                System.out.print("                SubmittedDate");
                                                System.out.println();
                                                System.out.print("                    "
                                                                + feedSubmissionInfo.getSubmittedDate());
                                                System.out.println();
                                        }
                                        if (feedSubmissionInfo.isSetFeedProcessingStatus()) {
                                                System.out
                                                .print("                FeedProcessingStatus");
                                                System.out.println();
                                                System.out.print("                    "
                                                                + feedSubmissionInfo.getFeedProcessingStatus());
                                                System.out.println();
                                        }
                                        if (feedSubmissionInfo.isSetStartedProcessingDate()) {
                                                System.out
                                                .print("                StartedProcessingDate");
                                                System.out.println();
                                                System.out
                                                .print("                    "
                                                                + feedSubmissionInfo
                                                                .getStartedProcessingDate());
                                                System.out.println();
                                        }
                                        if (feedSubmissionInfo.isSetCompletedProcessingDate()) {
                                                System.out
                                                .print("                CompletedProcessingDate");
                                                System.out.println();
                                                System.out.print("                    "
                                                                + feedSubmissionInfo
                                                                .getCompletedProcessingDate());
                                                System.out.println();
                                        }
                                }
                        }
                        if (response.isSetResponseMetadata()) {
                                System.out.print("        ResponseMetadata");
                                System.out.println();
                                ResponseMetadata responseMetadata = response
                                .getResponseMetadata();
                                if (responseMetadata.isSetRequestId()) {
                                        System.out.print("            RequestId");
                                        System.out.println();
                                        System.out.print("                "
                                                        + responseMetadata.getRequestId());
                                        System.out.println();
                                }
                        }
                        System.out.println(response.getResponseHeaderMetadata());
                        System.out.println();
                        System.out.println();
                        return 0;

                } catch (MarketplaceWebServiceException ex) {

                        System.out.println("Caught Exception: " + ex.getMessage());
                        System.out.println("Response Status Code: " + ex.getStatusCode());
                        System.out.println("Error Code: " + ex.getErrorCode());
                        System.out.println("Error Type: " + ex.getErrorType());
                        System.out.println("Request ID: " + ex.getRequestId());
                        System.out.print("XML: " + ex.getXML());
                        System.out.println("ResponseHeaderMetadata: " + ex.getResponseHeaderMetadata());
                        return -1;
                }

        }

}