package oracle.fodemo.storefront.store.service;


import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;

import oracle.adf.share.ADFContext;
import oracle.adf.share.logging.ADFLogger;
import oracle.adf.share.security.SecurityContext;

import oracle.fodemo.storefront.account.queries.CustomerAddressVOImpl;
import oracle.fodemo.storefront.account.queries.CustomerRegistrationVORowImpl;
import oracle.fodemo.storefront.adfextensions.FODApplicationModuleImpl;
import oracle.fodemo.storefront.store.queries.AddressesAndUsagesVOImpl;
import oracle.fodemo.storefront.store.queries.OrderItemsVOImpl;
import oracle.fodemo.storefront.store.queries.OrdersVOImpl;
import oracle.fodemo.storefront.store.queries.PersonsVOImpl;
import oracle.fodemo.storefront.store.queries.ShoppingCartTransientVOImpl;
import oracle.fodemo.storefront.store.service.common.StoreServiceAM;

import oracle.jbo.JboException;
import oracle.jbo.Key;
import oracle.jbo.Row;
import oracle.jbo.RowIterator;
import oracle.jbo.RowSetIterator;
import oracle.jbo.Variable;
import oracle.jbo.ViewCriteria;
import oracle.jbo.ViewCriteriaRow;
import oracle.jbo.ViewObject;
import oracle.jbo.domain.DBSequence;
import oracle.jbo.domain.Number;
import oracle.jbo.server.ViewLinkImpl;
import oracle.jbo.server.ViewObjectImpl;


// ---------------------------------------------------------------------
// ---    File generated by Oracle ADF Business Components Design Time.
// ---    Custom code may be added to this class.
// ---    Warning: Do not modify method signatures of generated methods.
// ---------------------------------------------------------------------
public class StoreServiceAMImpl extends FODApplicationModuleImpl implements StoreServiceAM {
    private static ADFLogger LOGGER = ADFLogger.createADFLogger(StoreServiceAMImpl.class); 
    // Order status code for user shopping carts
    private static String CART_STATUS_CODE = "CART";
    // Persistent shopping cart vo constants
    private static String PERSISTENT_CART_VO = "pShoppingCart";
    private static String ORDER_ITEMS_VO_DEF = "oracle.fodemo.storefront.store.queries.OrderItemsVO";
    private static String SHIPPING_ADDR_CODE = "SH";


    /**This is the default constructor (do not remove).
     */
    public StoreServiceAMImpl() {}

    /**
     * Updates the quantity of an existing item in the 
     * shopping cart. If the item does not exist a new
     * entry will be created.
     * 
     * @param productId
     * @param quantity
     * @param isSet
     */
    public void updateItemInCart(Integer productId, Integer quantity, Boolean isSet){
        // 1. update transient vo
        updateTransientCartItem(productId, quantity, isSet);
        SecurityContext securityContext = ADFContext.getCurrent().getSecurityContext();
        // 2. authentication check 
        if(securityContext.isAuthenticated()){
            String username = securityContext.getUserName();                            
            // 3. find shopping cart id for user
            long orderId = this.findCartIdForUser(username);
            if(orderId >= 0){
                // 4. update cart item
                updatePersistentCartItem(orderId, productId, quantity, isSet);
            }
        }
    }

    /**
     * Remove an item from the cart.
     * 
     * @param productId
     */
    public void removeItemFromCart(Integer productId){
        // 1. update transient vo
        removeItemFromTransientCart(productId);
        SecurityContext securityContext = ADFContext.getCurrent().getSecurityContext();
        // 2. authentication check 
        if(securityContext.isAuthenticated()){
            String username = securityContext.getUserName();                            
            // 3. find shopping cart id for user
            long orderId = this.findCartIdForUser(username);
            if(orderId >= 0){
                // 4. add cart item
                removeItemFromPersistentCart(orderId, productId);
            }
        }
    }

    /**
     * Remove all items from cart.
     */
    public void removeAllItemsFromCart(){
        // 1. update transient vo
        removeAllItemsFromTransientCart();
        SecurityContext securityContext = ADFContext.getCurrent().getSecurityContext();
        // 2. authentication check 
        if(securityContext.isAuthenticated()){
            String username = securityContext.getUserName();                            
            // 3. find shopping cart id for user
            long orderId = this.findCartIdForUser(username);
            // 4. add cart item
            if(orderId >= 0){
                removeAllItemsFromPersistentCart(orderId);
            }
        }
    }
    

    /**
     * Updates the quantity of an existing item in the
     * shopping cart. If the item does not exist a new
     * entry will be created.
     *
     * @param productId
     * @param quantity
     * @param isSet
     */
    public void updateTransientCartItem(Integer productId, Integer quantity, Boolean isSet){        
        // 1. check for existence of product in cart
        ViewObjectImpl shoppingCartVO = getMyShoppingCart();         
        Row[] rows = shoppingCartVO.findByKey( new Key(new Object[]{productId}) ,1);
        if(rows.length > 0){
            // 2. update quantity of existing item 
            if(!isSet){
                Integer currQuantity = (Integer)rows[0].getAttribute("Quantity");
                quantity =  currQuantity.intValue() + quantity;
            }   
            rows[0].setAttribute("Quantity", quantity);
            return;
        } 
        // 3. The product has not been add to the cart.
        addItemToTransientCart(productId, quantity);   
    }

    /**
     * Updates the quantity of an existing item in the
     * shopping cart. If the item does not exist a new
     * entry will be created.
     *
     * @param orderId
     * @param productId
     * @param quantity
     * @param isSet
     */
    public void updatePersistentCartItem(Long orderId, Integer productId, Integer quantity, Boolean isSet){        
        // 1. create instance of persitent shopping cart.
        OrderItemsVOImpl shoppingCartVO = createPersistentShoppingCartVO();
        // 2. limit view to order of interest.
        shoppingCartVO.showOrderItemForOrderIdAndProductId(orderId ,productId);
        // 3. find view item in view.
        Row shoppingCartRow = shoppingCartVO.first();         
        if(shoppingCartRow != null){
            // 4. update quantity of existing item 
            if(!isSet){
                Integer currQuantity = (Integer)shoppingCartRow.getAttribute("Quantity");
                quantity =  currQuantity.intValue() + quantity;
            }
            shoppingCartRow.setAttribute("Quantity", quantity);
            getDBTransaction().commit();
            return;
        }
        // 5. The product has not been add to the cart.
        addItemToPersistentCart(orderId, productId, quantity);   
    }

    /**
     * Adds item to peristent shopping cart.
     * 
     * @param orderId
     * @param productId
     * @param quantity
     */
    public void addItemToPersistentCart(Long orderId, Integer productId, Integer quantity){
        // 1. create instance of persitent shopping cart.
        OrderItemsVOImpl shoppingCartVO = createPersistentShoppingCartVO();
        Row productRow = findProductByVC(getProducts(), productId);
        if(productRow != null){
            // 2. Create new row in cart and copy product row values
            //    to new cart row.
            Row newShoppingCartRow = shoppingCartVO.createRow();
            newShoppingCartRow.setAttribute( "ProductId", productId );
            newShoppingCartRow.setAttribute( "OrderId", orderId );
            newShoppingCartRow.setAttribute( "UnitPrice", productRow.getAttribute("ListPrice") );        
            newShoppingCartRow.setAttribute( "Quantity", quantity );        
            shoppingCartVO.insertRow(newShoppingCartRow);
            getDBTransaction().commit();
        } else {        
        }
    }

    /**
     * Remove item from shopping cart.
     *
     * @param orderId
     * @param productId
     */
    public void removeItemFromPersistentCart(Long orderId, Integer productId){
        // 1. create instance of persitent shopping cart.
        OrderItemsVOImpl shoppingCartVO = createPersistentShoppingCartVO();
        shoppingCartVO.showOrderItemForOrderIdAndProductId(orderId, productId);
        Row itemToRemoveRow = shoppingCartVO.first();
        if(itemToRemoveRow != null){
            itemToRemoveRow.remove();
            getDBTransaction().commit();
        } else {
            LOGGER.info("No item to remove from the persistent cart.");        
        }
    }

    /**
     * Remove all items from shopping cart.
     * @param orderId
     */
    public void removeAllItemsFromPersistentCart(Long orderId){
        // 1. create instance of persitent shopping cart.
        OrderItemsVOImpl shoppingCartVO = createPersistentShoppingCartVO();
        shoppingCartVO.showOrderItemsForOrderId(orderId);
        while(shoppingCartVO.hasNext()){
            Row itemToRemoveRow = shoppingCartVO.next();
            itemToRemoveRow.remove();
        }
        getDBTransaction().commit();
    }

    /**
     * Adds a new item to the shopping cart.
     * 
     * @param productId
     * @param quantity
     */
    public void addItemToTransientCart(Integer productId, Integer quantity){
        //    1. Find the product so its values can be copied to a
        //       row in the cart.
        Row productRow = findProductByVC(getProducts(), productId);
        if(productRow != null){
            ViewObjectImpl shoppingCartVO = getMyShoppingCart();
            // 2. Check if the item already exists in the cart.
            Row[] cartItem = shoppingCartVO.findByKey( new Key(new Object[]{productId}) ,1);
            if(cartItem.length == 0){
                // 3. Create new row in cart and copy product row values
                //    to new cart row.
                Row newShoppingCartRow = shoppingCartVO.createRow();
                newShoppingCartRow.setAttribute( "ProductId", productRow.getAttribute("ProductId") );
                newShoppingCartRow.setAttribute( "ProductName", productRow.getAttribute("ProductName") );
                newShoppingCartRow.setAttribute( "Description", productRow.getAttribute("Description") );
                newShoppingCartRow.setAttribute( "AdditionalInformation", productRow.getAttribute("AdditionalInfo") );        
                newShoppingCartRow.setAttribute( "ListPrice", productRow.getAttribute("ListPrice") );        
                newShoppingCartRow.setAttribute( "CategoryName", productRow.getAttribute("CategoryName") );        
                newShoppingCartRow.setAttribute( "Quantity", quantity );        
                shoppingCartVO.insertRow(newShoppingCartRow);
            } else{
                LOGGER.info( "Product #" + productId + " already exists in transient cart." );
            }
        } 
    }

    /**
     * Remove item from shopping cart.
     * 
     * @param productId
     */
    public void removeItemFromTransientCart(Integer productId){
        ViewObjectImpl shoppingCartVO = getMyShoppingCart();
        Row[] rows = shoppingCartVO.findByKey( new Key(new Object[]{productId}) ,1);
        if(rows.length > 0){
            rows[0].remove();
        } else {
            LOGGER.info("No item to remove from the transient cart.");        
        }
    }

    /**
     * Remove all items from shopping cart.
     */
    public void removeAllItemsFromTransientCart(){
        ViewObjectImpl shoppingCartVO = getMyShoppingCart();
        // 1. reset iterator to start before first row
        shoppingCartVO.setRangeSize(-1);
        Row[] rows = shoppingCartVO.getAllRowsInRange();
        // 2. iterate over rows and remove each instance
        for(Row row: rows){
            row.remove(); 
        }
    }

    /**
     * Use this method to merge the values in the
     * persistent and tranisent shopping cart.
     * @throws JboException
     */
    public void reconcileShoppingCart() throws JboException {
       String userName = ADFContext.getCurrent().getSecurityContext().getUserName();
        if(ADFContext.getCurrent().getSecurityContext().isAuthenticated()){
            // 1. Get id for customer
            Row personsRow = this.findCustomerIdForUserName(userName);
            if(personsRow == null) return;
            long customerId = ((DBSequence)personsRow.getAttribute("PersonId")).getValue();
            // 2. Locate OrderId for user's shopping cart.
            Row shoppingCartRow = findShoppingCartForUser(customerId);            
            long orderId = ((DBSequence)shoppingCartRow.getAttribute("OrderId")).getValue();
            // Merge transient shopping cart with persistent VO
            // 1. Copy rows from transient vo to persitent vo and update
            //    existing items.
            ViewObjectImpl tShoppingCartVO = this.getMyShoppingCart();
            //         a. Reset iterator to start before first slot
            tShoppingCartVO.setRangeSize(-1);
            Row[] tRows = tShoppingCartVO.getAllRowsInRange();
            for(Row tItemRow : tRows) {
                Number productId = (Number)tItemRow.getAttribute("ProductId");
                Row pItemRow = findLineItem(orderId, productId);
                if(pItemRow != null){
                    // b. update quantity of existing records.
                    pItemRow.setAttribute("Quantity",
                                          ((Integer) tItemRow.getAttribute("Quantity")));
                } else {
                    // c. insert any items not present in persistent vo.       
                    OrderItemsVOImpl orderItemsVO = createPersistentShoppingCartVO();
                    Row newOrderItemRow = orderItemsVO.createRow();
                    newOrderItemRow.setAttribute("OrderId", orderId);
                    newOrderItemRow.setAttribute("ProductId", productId);
                    newOrderItemRow.setAttribute("UnitPrice", tItemRow.getAttribute("ListPrice"));
                    newOrderItemRow.setAttribute("Quantity", tItemRow.getAttribute("Quantity"));
                    orderItemsVO.insertRow(newOrderItemRow);
                }
            }
            
            // Finally, commit changes
            getDBTransaction().commit();

            // 2. Copy persistent shopping cart items to transient vo. 
            //     a. clear cart 
            removeAllItemsFromTransientCart();
            OrderItemsVOImpl pLineItemsVO = this.createPersistentShoppingCartVO();
            pLineItemsVO.showOrderItemsForOrderId(orderId);
            while(pLineItemsVO.hasNext()){
                // b. add each persistent order item to the transient cart
                Row pLineItemRow = pLineItemsVO.next();
                Number productId = (Number)pLineItemRow.getAttribute("ProductId");
                Integer quantity = (Integer)pLineItemRow.getAttribute("Quantity");
                addItemToTransientCart(productId.intValue(), quantity.intValue());
    }
}
    }
    /**
     * Creates/Looksup a private instance of the OrderItemsVO that
     * the shopping cart uses for queries. This avoids the need to 
     * alter the state of a vo instance that is bound to the UI.
     * 
     * @return OrderItemsVO
     */
    private OrderItemsVOImpl createPersistentShoppingCartVO(){
        OrderItemsVOImpl shoppingCartVO = (OrderItemsVOImpl)findViewObject( PERSISTENT_CART_VO );
        if(shoppingCartVO == null){
            shoppingCartVO = (OrderItemsVOImpl)createViewObject( PERSISTENT_CART_VO, ORDER_ITEMS_VO_DEF );
        }
        return shoppingCartVO;
    }
    
    private Row findProductByVC(ViewObjectImpl vo, Integer productId){
        ViewCriteria productsVC = vo.createViewCriteria();
        ViewCriteriaRow productsVCR = productsVC.createViewCriteriaRow();
        productsVCR.setAttribute("ProductId", "=" + productId);
        productsVC.addElement(productsVCR);
        RowIterator productsItr =
        vo.findByViewCriteria(productsVC, -1, ViewObject.QUERY_MODE_SCAN_DATABASE_TABLES);            
        return productsItr.first();
    }

    private Row findLineItem(Long orderId, Number productId){
        OrderItemsVOImpl vo = this.createPersistentShoppingCartVO();
        vo.clearCache();
        vo.showOrderItemsForOrderId(orderId);
        ViewCriteria lineItemsVC = vo.createViewCriteria();
        ViewCriteriaRow lineItemsVCR = lineItemsVC.createViewCriteriaRow();
        lineItemsVCR.setAttribute("OrderId", "=" + orderId);
        lineItemsVCR.setAttribute("ProductId", "=" + productId);
        lineItemsVC.addElement(lineItemsVCR);
        RowIterator lineItemsItr = vo.findByViewCriteria(lineItemsVC, -1, ViewObject.QUERY_MODE_SCAN_DATABASE_TABLES);
        return lineItemsItr.first();
    }

    private long findCartIdForUser(String username){
        Row personsRow = findCustomerIdForUserName(username);
        if(personsRow == null) return -1;
        long customerId = ((DBSequence)personsRow.getAttribute("PersonId")).getValue();
        Row shoppingCartRow = findShoppingCartForUser(customerId);
        long orderId = ((DBSequence)shoppingCartRow.getAttribute("OrderId")).getValue();    
        return orderId;
    }

    private Row findShoppingCartForUser(Long customerId) {
        Number shippingAddress = 
            findShippingAddressIdForCustomer(customerId);
        // 1. locate existing cart.
        ViewObjectImpl ordersVO = this.getOrders();
        ordersVO.clearCache();
        ordersVO.clearViewCriterias();
        ViewCriteria vc = ordersVO.createViewCriteria();
        ViewCriteriaRow vcr = vc.createViewCriteriaRow();
        vcr.setAttribute("CustomerId", "=" + customerId);
        vcr.setAttribute("OrderStatusCode", "='CART'");
        vc.addElement(vcr);
        RowIterator itr = 
            ordersVO.findByViewCriteria(vc, -1, ViewObject.QUERY_MODE_SCAN_DATABASE_TABLES);
        Row shoppingCartRow = itr.first();
        if (shoppingCartRow == null) {
            // 2. create new shopping cart if no cart order is present
            shoppingCartRow = ordersVO.createRow();
            shoppingCartRow.setAttribute("OrderStatusCode", CART_STATUS_CODE);
            shoppingCartRow.setAttribute("ShipToAddressId", 
                                         shippingAddress);
            shoppingCartRow.setAttribute("DiscountId", new Number(1));
            shoppingCartRow.setAttribute("CouponId", new Number(1));
            shoppingCartRow.setAttribute("CustomerId", customerId);
            Number paymentOption = findPaymentOptionIdForCustomer(customerId);
            shoppingCartRow.setAttribute("PaymentOptionId", paymentOption);
            shoppingCartRow.setAttribute("GiftwrapFlag", 'N');
            ordersVO.insertRow(shoppingCartRow);
            this.getDBTransaction().commit();
        }
        return shoppingCartRow;
    }

    private Row findCustomerIdForUserName(String principalName){
        ViewObjectImpl personsImpl = this.getPersons();
          Key key = new Key(new Object[]{principalName.toUpperCase()});
          RowIterator personsItr = personsImpl.findByAltKey("PrincipalName_AltKey", key, 1, false);
        return personsItr.first();
    }

    private Number findShippingAddressIdForCustomer(Long customerId){
        Number result = new Number();
        PersonsVOImpl personsImpl = (PersonsVOImpl)this.getPersons();
        Row[] personRow = personsImpl.findByKey( new Key(new Object[]{customerId}) ,1);
        if(personRow != null){
            ViewObjectImpl addressUsages = this.getAddressesAndUsagesVO1();
            ViewCriteria vc = addressUsages.createViewCriteria();
            ViewCriteriaRow vcr = vc.createViewCriteriaRow();
            vcr.setAttribute("AssociatedOwnerId", "=" + customerId);
            vc.addElement(vcr);
            RowIterator itr = addressUsages.findByViewCriteria(vc, -1, ViewObject.QUERY_MODE_SCAN_DATABASE_TABLES);
            //Query all addresses for customer to see if one of them is type SH
            boolean isShippingAddress = false;
            for (Row row : itr.getAllRowsInRange()) {
                String typeCode = row.getAttribute("UsageTypeCode").toString();
                if (typeCode.equals(SHIPPING_ADDR_CODE)){    
               isShippingAddress = true;   
                    result=(Number)row.getAttribute("AddressId");    
                break;    
                }
            }
            if (!isShippingAddress){    
            Row addressRow = itr.first();
                // if no shipping address exists, create one
                    Row shippingAddressRow = addressUsages.createRow();
                    shippingAddressRow.setAttribute("OwnerTypeCode", personRow[0].getAttribute("PersonTypeCode"));
                    shippingAddressRow.setAttribute("AddressId", addressRow.getAttribute("AddressId"));
                    shippingAddressRow.setAttribute("UsageTypeCode", SHIPPING_ADDR_CODE);
                    shippingAddressRow.setAttribute("AssociatedOwnerId", personRow[0].getAttribute("PersonId"));
                    shippingAddressRow.setAttribute("Address1", addressRow.getAttribute("Address1"));
                    shippingAddressRow.setAttribute("Address2", addressRow.getAttribute("Address2"));
                    shippingAddressRow.setAttribute("City", addressRow.getAttribute("City"));
                    shippingAddressRow.setAttribute("PostalCode", addressRow.getAttribute("PostalCode"));
                    shippingAddressRow.setAttribute("StateProvince", addressRow.getAttribute("StateProvince"));
                    shippingAddressRow.setAttribute("CountryId", addressRow.getAttribute("CountryId"));
                    addressUsages.insertRow(shippingAddressRow);
                    result = (Number)shippingAddressRow.getAttribute("AddressId");
                    this.getDBTransaction().commit();
            }
        }
        return result;
    }

    private Number findPaymentOptionIdForCustomer(Long customerId){
        Number result = new Number(1);
        ViewObjectImpl vo = this.getPaymentOptions();
        ViewCriteria vc = vo.createViewCriteria();
        ViewCriteriaRow vcr = vc.createViewCriteriaRow();
        vcr.setAttribute("CustomerId", "=" + customerId);
        vc.addElement(vcr);
        RowIterator itr = 
        vo.findByViewCriteria(vc, -1, ViewObject.QUERY_MODE_SCAN_DATABASE_TABLES);            
        Row row = itr.first();
        if(row != null){
            result = new Number(((DBSequence)row.getAttribute("PaymentOptionId")).getValue());
        } 
        return result;
    }

    public void deleteCurrentMyOrderItem(){
        OrderItemsVOImpl orderItemsVO = (OrderItemsVOImpl)this.getMyOrderItems();
        Row orderItemRow = orderItemsVO.getCurrentRow();
        orderItemRow.remove();
        OrdersVOImpl orders = (OrdersVOImpl)this.getMyOrders();
        Row ordersRow  = orders.getCurrentRow();
        ordersRow.setAttribute("OrderTotal", ordersRow.getAttribute("InvoiceTotal"));
        if( orderItemsVO.getRowCount() <= 0 ){
            ordersRow.setAttribute("OrderStatusCode", "CANCEL");
        }
        this.getDBTransaction().commit();
    }

    /**
     * @return
     * @throws JboException
     */
    public Row setAuthenticatedUser() throws JboException {
        String username = ADFContext.getCurrent().getSecurityContext().getUserName();
        if(username != null){
            ViewObjectImpl authenticatedUser = this.getAuthenticatedUser();
            if(authenticatedUser.first() == null ||
               !((String)authenticatedUser.first().getAttribute("PrincipalName")).equalsIgnoreCase(username) ) {
                authenticatedUser.setNamedWhereClauseParam("userPrincipal", 
                                                           username);
                authenticatedUser.executeQuery();
                return authenticatedUser.first();
            }
        } else {
            throw new JboException( "There is no authenticated user in the security context." );         
        }
        return null;
    }
    
    public void resetProductQueryCriteria(){
        ViewObjectImpl products = this.getProducts();
        ViewCriteria vcarray[] = products.getAllViewCriterias();
        for (int index=0; index<vcarray.length; index++){
            ViewCriteria vc = vcarray[index];
            vc.resetCriteria();
        }
    }

    //======[End Custom Code]========


    /**Container's getter for Addresses.
     * @return
     */
    public ViewObjectImpl getAddresses() {
        return (ViewObjectImpl)findViewObject("Addresses");
    }


    /**Container's getter for MostPopularProductsByCategories.
     * @return
     */
    public ViewObjectImpl getMostPopularProductsByCategories() {
        return (ViewObjectImpl)findViewObject("MostPopularProductsByCategories");
    }

    /**Container's getter for ProductsByCategories.
     * @return
     */
    public ViewObjectImpl getProductsByCategories() {
        return (ViewObjectImpl)findViewObject("ProductsByCategories");
    }


    /**Container's getter for WarehouseStockLevels.
     * @return
     */
    public ViewObjectImpl getWarehouseStockLevels() {
        return (ViewObjectImpl)findViewObject("WarehouseStockLevels");
    }


    /**Container's getter for PaymentOptions.
     * @return
     */
    public ViewObjectImpl getPaymentOptions() {
        return (ViewObjectImpl)findViewObject("PaymentOptions");
    }

    /**Container's getter for Products.
     * @return
     */
    public ViewObjectImpl getProducts() {
        return (ViewObjectImpl)findViewObject("Products");
    }

    /**Container's getter for ParentProductCategories.
     * @return
     */
    public ViewObjectImpl getParentProductCategories() {
        return (ViewObjectImpl)findViewObject("ParentProductCategories");
    }

    /**Container's getter for Persons.
     * @return
     */
    public ViewObjectImpl getPersons() {
        return (ViewObjectImpl)findViewObject("Persons");
    }

    /**Container's getter for AuthenticatedUser.
     * @return
     */
    public ViewObjectImpl getAuthenticatedUser() {
        return (ViewObjectImpl)findViewObject("AuthenticatedUser");
    }

    /**Container's getter for MostPopularProductsByCategoriesToWarehouseStockLevels.
     * @return
     */
    public ViewObjectImpl getMostPopularProductsByCategoriesToWarehouseStockLevels() {
        return (ViewObjectImpl)findViewObject("MostPopularProductsByCategoriesToWarehouseStockLevels");
    }

    /**Container's getter for ProductsByCategoriesToWarehouseStockLevels.
     * @return
     */
    public ViewObjectImpl getProductsByCategoriesToWarehouseStockLevels() {
        return (ViewObjectImpl)findViewObject("ProductsByCategoriesToWarehouseStockLevels");
    }

    /**Container's getter for ProductCategories.
     * @return
     */
    public ViewObjectImpl getProductCategories() {
        return (ViewObjectImpl)findViewObject("ProductCategories");
    }

    /**Container's getter for ProductCategoriesToParentProductCategories.
     * @return
     */
    public ViewObjectImpl getProductCategoriesToParentProductCategories() {
        return (ViewObjectImpl)findViewObject("ProductCategoriesToParentProductCategories");
    }

    /**Container's getter for ParentProductCategoriesToProductCategories.
     * @return
     */
    public ViewObjectImpl getParentProductCategoriesToProductCategories() {
        return (ViewObjectImpl)findViewObject("ParentProductCategoriesToProductCategories");
    }

    /**Container's getter for ProductQuantities.
     * @return
     */
    public ViewObjectImpl getProductQuantities() {
        return (ViewObjectImpl)findViewObject("ProductQuantities");
    }

    /**Container's getter for ProductImages.
     * @return
     */
    public ViewObjectImpl getProductImages() {
        return (ViewObjectImpl)findViewObject("ProductImages");
    }


    /**Container's getter for MostPopularProductsByCategoriesToWarehouseStockLevels1.
     * @return
     */
    public ViewLinkImpl getMostPopularProductsByCategoriesToWarehouseStockLevels1() {
        return (ViewLinkImpl)findViewLink("MostPopularProductsByCategoriesToWarehouseStockLevels1");
    }

    /**Container's getter for ProductsByCategoriesToWarehouseStockLevels1.
     * @return
     */
    public ViewLinkImpl getProductsByCategoriesToWarehouseStockLevels1() {
        return (ViewLinkImpl)findViewLink("ProductsByCategoriesToWarehouseStockLevels1");
    }

    /**Container's getter for ParentProductCategoriesToProductCategories2.
     * @return
     */
    public ViewLinkImpl getParentProductCategoriesToProductCategories2() {
        return (ViewLinkImpl)findViewLink("ParentProductCategoriesToProductCategories2");
    }


    /**Container's getter for ShoppingCart.
     * @return
     */
    public ViewObjectImpl getShoppingCart() {
        return (ViewObjectImpl)findViewObject("ShoppingCart");
    }

    /**Container's getter for ShoppingCartItems.
     * @return
     */
    public ViewObjectImpl getShoppingCartItems() {
        return (ViewObjectImpl)findViewObject("ShoppingCartItems");
    }

    /**Container's getter for MyOrders.
     * @return
     */
    public ViewObjectImpl getMyOrders() {
        return (ViewObjectImpl)findViewObject("MyOrders");
    }

    /**Container's getter for MyOrderItems.
     * @return
     */
    public ViewObjectImpl getMyOrderItems() {
        return (ViewObjectImpl)findViewObject("MyOrderItems");
    }

    /**Container's getter for PersonsToOrders1.
     * @return
     */
    public ViewLinkImpl getPersonsToOrders1() {
        return (ViewLinkImpl)findViewLink("PersonsToOrders1");
    }

    /**Container's getter for OrdersToOrderItems2.
     * @return
     */
    public ViewLinkImpl getOrdersToOrderItems2() {
        return (ViewLinkImpl)findViewLink("OrdersToOrderItems2");
    }

    /**Container's getter for PersonsToOrders2.
     * @return
     */
    public ViewLinkImpl getPersonsToOrders2() {
        return (ViewLinkImpl)findViewLink("PersonsToOrders2");
    }

    /**Container's getter for OrdersToOrderItems3.
     * @return
     */
    public ViewLinkImpl getOrdersToOrderItems3() {
        return (ViewLinkImpl)findViewLink("OrdersToOrderItems3");
    }

    /**Container's getter for ZipStateCityVO1.
     * @return
     */
    public ViewObjectImpl getZipStateCityVO1() {
        return (ViewObjectImpl)findViewObject("ZipStateCityVO1");
    }

    /**Container's getter for ZipCityStateVO1.
     * @return
     */
    public ViewObjectImpl getZipCityStateVO1() {
        return (ViewObjectImpl)findViewObject("ZipCityStateVO1");
    }


    /**Container's getter for ShippingOptionsVO1.
     * @return
     */
    public ViewObjectImpl getShippingOptionsVO1() {
        return (ViewObjectImpl)findViewObject("ShippingOptionsVO1");
    }


    /**Container's getter for PaymentOptionsForUser.
     * @return
     */
    public ViewObjectImpl getPaymentOptionsForUser() {
        return (ViewObjectImpl)findViewObject("PaymentOptionsForUser");
    }

    /**Container's getter for PersonsToPaymentOptions1.
     * @return
     */
    public ViewLinkImpl getPersonsToPaymentOptions1() {
        return (ViewLinkImpl)findViewLink("PersonsToPaymentOptions1");
    }

    /**Container's getter for PersonsToMembershipDiscounts1.
     * @return
     */
    public ViewLinkImpl getPersonsToMembershipDiscounts1() {
        return (ViewLinkImpl)findViewLink("PersonsToMembershipDiscounts1");
    }

    /**Container's getter for MembershipDiscounts.
     * @return
     */
    public ViewObjectImpl getMembershipDiscounts() {
        return (ViewObjectImpl)findViewObject("MembershipDiscounts");
    }

    /**Container's getter for CustomerRegistration.
     * @return
     */
    public ViewObjectImpl getCustomerRegistration() {
        return (ViewObjectImpl)findViewObject("CustomerRegistration");
    }

    /**Container's getter for FindAddressesById.
     * @return
     */
    public ViewObjectImpl getFindAddressesById() {
        return (ViewObjectImpl)findViewObject("FindAddressesById");
    }

    /**Container's getter for FindOrdersById.
     * @return
     */
    public ViewObjectImpl getFindOrdersById() {
        return (ViewObjectImpl)findViewObject("FindOrdersById");
    }

    /**Container's getter for SelectedCategoriesShuttleList.
     * @return
     */
    public ViewObjectImpl getSelectedCategoriesShuttleList() {
        return (ViewObjectImpl)findViewObject("SelectedCategoriesShuttleList");
    }

    /**Container's getter for AvailableCategoriesShuttleList.
     * @return
     */
    public ViewObjectImpl getAvailableCategoriesShuttleList() {
        return (ViewObjectImpl)findViewObject("AvailableCategoriesShuttleList");
    }

    /**Container's getter for CustomerAddress.
     * @return
     */
    public ViewObjectImpl getCustomerAddress() {
        return (ViewObjectImpl)findViewObject("CustomerAddress");
    }

    /**Container's getter for CustomerRegistrationToCustomerInterestsVO1.
     * @return
     */
    public ViewLinkImpl getCustomerRegistrationToCustomerInterestsVO1() {
        return (ViewLinkImpl)findViewLink("CustomerRegistrationToCustomerInterestsVO1");
    }

    /**Container's getter for CustomerRegistrationToCustomerAddress1.
     * @return
     */
    public ViewLinkImpl getCustomerRegistrationToCustomerAddress1() {
        return (ViewLinkImpl)findViewLink("CustomerRegistrationToCustomerAddress1");
    }

    /**Container's getter for CustomerPaymentOption.
     * @return
     */
    public ViewObjectImpl getCustomerPaymentOption() {
        return (ViewObjectImpl)findViewObject("CustomerPaymentOption");
    }

    /**Container's getter for CustomerRegistrationToCustomerPaymentOption1.
     * @return
     */
    public ViewLinkImpl getCustomerRegistrationToCustomerPaymentOption1() {
        return (ViewLinkImpl)findViewLink("CustomerRegistrationToCustomerPaymentOption1");
    }

    public void userRegistrationCreateAddress(){
        ViewObject userVO = this.getCustomerRegistration();
        ViewObject addressVO = this.getCustomerAddress();
        if (addressVO.getRowCount() == 0){
           Row currentRow = addressVO.createRow();
           addressVO.insertRow(currentRow);  
        }     
        else {   
            Row currentRow = addressVO.createRow();   
            addressVO.insertRow(currentRow);        
        }
    }

    /**
     * @param userType
     */
    public void userRegistrationCreate(String userType){
        ViewObject userVO = this.getCustomerRegistration();
        Row currentRow = userVO.createRow();
        currentRow.setAttribute("PersonTypeCode",userType);
        userVO.insertRow(currentRow);       
    }
    
    
    public void userRegistrationPOCreate(){
//        Row personsRow = this.getCustomerPaymentOption().getCurrentRow();
//        long customerId = ((DBSequence)personsRow.getAttribute("PersonId")).getValue();
        ViewObject paymentOptionVO = this.getCustomerPaymentOption();
        Row currentRow = paymentOptionVO.createRow();
//        currentRow.setAttribute("CustomerId", currCustomerId);
        paymentOptionVO.insertRow(currentRow);            
    }

    /**
     * Update the preferred interests for the current user
     * in the UserRegistration view object instance to match the list of interest id's
     * passed in as a parameter. The method 
     * (1) Receives the list of Ids
     * (2) Copies them to a local variable
     * (3) Checks if the current selected Ids are all in the incoming list and the ones that are found are removed from the local List variable
     * (4) The remaining Ids in the local List variable are the ones to be inserted, and so they are...
     * 
     * @param pCategoryIds List of product ids for customer interests areas
     */
    public void updateCustomerInterests(List pCategoryIds) {
        if (pCategoryIds != null && pCategoryIds.size() > 0) {
            List<Integer> copyOfCategoryIds = (List<Integer>) this.cloneList(pCategoryIds);
            ViewObject selectedCategories = 
                this.getSelectedCategoriesShuttleList();

            RowSetIterator rsi = selectedCategories.createRowSetIterator(null);
            // remove any rows for the current user that aren't in the list of product keys
            while (rsi.hasNext()) {
                Row r = rsi.next();
                Number interestId = (Number)r.getAttribute("CategoryId");
                // if the existing row is in the list, we're ok, so remove from list.
                if (copyOfCategoryIds.contains(interestId)) {
                    copyOfCategoryIds.remove(interestId);
                }
                // if the existing row is in not list, remove it.
                else {
                    r.remove();
                }
            }
            rsi.closeRowSetIterator();
            // at this point, we need to add new rows for the keys that are left
                    for (int i =0 ;i < copyOfCategoryIds.size(); i++ )  {
                        Row newRow = selectedCategories.createRow();
                        selectedCategories.insertRow(newRow);
                        newRow.setAttribute("CategoryId", (String) copyOfCategoryIds.get(i).toString());
                    }
        }
    }

    /**
     * Update the preferred interests for the current user
     * while the user is in the updateInfo pages 
     * (1) Receives the list of Ids
     * (2) Copies them to a local variable
     * (3) Checks if the current selected Ids are all in the incoming list and the ones that are found are removed from the local List variable
     * (4) The remaining Ids in the local List variable are the ones to be inserted, and so they are...
     * 
     * @param pCategoryIds List of product ids for customer interests areas
     */
    public void updateUserInterests(List pCategoryIds) {
        if (pCategoryIds != null && pCategoryIds.size() > 0) {
            List<Number> copyOfCategoryIds = (List<Number>) this.cloneList(pCategoryIds);
            ViewObject selectedCategories = 
                this.getCustomerInterestsVO1();
            RowSetIterator rsi = selectedCategories.createRowSetIterator(null);
            // remove any rows for the current user that aren't in the list of product keys
            while (rsi.hasNext()) {
                Row r = rsi.next();
                Number interestId = (Number)r.getAttribute("CategoryId");
                // if the existing row is in the list, we're ok, so remove from list.
                if (copyOfCategoryIds.contains(interestId)) {
                    copyOfCategoryIds.remove(interestId);
                }
                // if the existing row is in not list, remove it.
                else {
                    r.remove();
                }
            }
            rsi.closeRowSetIterator();
            // at this point, we need to add new rows for the keys that are left
                    for (int i =0 ;i < copyOfCategoryIds.size(); i++ )  {
                        Row newRow = selectedCategories.createRow();
                        selectedCategories.insertRow(newRow);
                        newRow.setAttribute("CategoryId", (Number) copyOfCategoryIds.get(i));
                    }
        }
    }
    
    private List cloneList(List original) {
        List clonedList = new ArrayList();
        for (Object o : original) {
            clonedList.add(o);
        }
        return clonedList;
    }

    public void executeMyOrdersForCustomerVO() {
        
        Row authenticatedUserInfo = this.setAuthenticatedUser();

    }

    /**Container's getter for ProductsToWarehouseStockLevels1.
     * @return
     */
    public ViewLinkImpl getProductsToWarehouseStockLevels1() {
        return (ViewLinkImpl)findViewLink("ProductsToWarehouseStockLevels1");
    }

    /**Container's getter for ProductsToWarehouseStockLevels2.
     * @return
     */
    public ViewLinkImpl getProductsToWarehouseStockLevels2() {
        return (ViewLinkImpl)findViewLink("ProductsToWarehouseStockLevels2");
    }

    /**Container's getter for ProductsToWarehouseStockLevels3.
     * @return
     */
    public ViewLinkImpl getProductsToWarehouseStockLevels3() {
        return (ViewLinkImpl)findViewLink("ProductsToWarehouseStockLevels3");
    }

    /**Container's getter for ProductOrdersCountVO1.
     * @return
     */
    public ViewObjectImpl getProductOrdersCountVO1() {
        return (ViewObjectImpl)findViewObject("ProductOrdersCountVO1");
    }

    /**Container's getter for AddressUsagesVO.
     * @return
     */
    public ViewObjectImpl getAddressUsagesVO() {
        return (ViewObjectImpl)findViewObject("AddressUsagesVO");
    }

    /**Container's getter for ProductOrdersCount.
     * @return
     */
    public ViewObjectImpl getProductOrdersCount() {
        return (ViewObjectImpl)findViewObject("ProductOrdersCount");
    }

    /**Container's getter for MostPopularProductsByCategoriesToWarehouseStockLevels2.
     * @return
     */
    public ViewLinkImpl getMostPopularProductsByCategoriesToWarehouseStockLevels2() {
        return (ViewLinkImpl)findViewLink("MostPopularProductsByCategoriesToWarehouseStockLevels2");
    }

    /**Container's getter for AddressesAndUsages.
     * @return
     */
    public ViewObjectImpl getAddressesAndUsages() {
        return (ViewObjectImpl)findViewObject("AddressesAndUsages");
    }

    /**Container's getter for PersonsToAddressesAndAddressUsages1.
     * @return
     */
    public ViewLinkImpl getPersonsToAddressesAndAddressUsages1() {
        return (ViewLinkImpl)findViewLink("PersonsToAddressesAndAddressUsages1");
    }

    /**Container's getter for AddressesAndAddressUsages.
     * @return
     */
    public ViewLinkImpl getAddressesAndAddressUsages() {
        return (ViewLinkImpl)findViewLink("AddressesAndAddressUsages");
    }

    /**Container's getter for FindPaymentOptionsById.
     * @return
     */
    public ViewObjectImpl getFindPaymentOptionsById() {
        return (ViewObjectImpl)findViewObject("FindPaymentOptionsById");
    }

    /**Container's getter for OrdersToAddresses1.
     * @return
     */
    public ViewLinkImpl getOrdersToAddresses1() {
        return (ViewLinkImpl)findViewLink("OrdersToAddresses1");
    }

    /**Container's getter for ShipToAddresses.
     * @return
     */
    public ViewObjectImpl getShipToAddresses() {
        return (ViewObjectImpl)findViewObject("ShipToAddresses");
    }

    /**Container's getter for OrdersToPaymentOptions1.
     * @return
     */
    public ViewLinkImpl getOrdersToPaymentOptions1() {
        return (ViewLinkImpl)findViewLink("OrdersToPaymentOptions1");
    }

    /**Container's getter for OrderPaymentOptions.
     * @return
     */
    public ViewObjectImpl getOrderPaymentOptions() {
        return (ViewObjectImpl)findViewObject("OrderPaymentOptions");
    }

    /**Container's getter for PaymentOptionsToAddresses1.
     * @return
     */
    public ViewLinkImpl getPaymentOptionsToAddresses1() {
        return (ViewLinkImpl)findViewLink("PaymentOptionsToAddresses1");
    }

    /**Container's getter for OrderBillingAddresses.
     * @return
     */
    public ViewObjectImpl getOrderBillingAddresses() {
        return (ViewObjectImpl)findViewObject("OrderBillingAddresses");
    }

    /**Container's getter for ProductsVO1.
     * @return
     */
    public ViewObjectImpl getProductsVO1() {
        return (ViewObjectImpl)findViewObject("ProductsVO1");
    }

    /**Container's getter for FindProductById.
     * @return
     */
    public ViewObjectImpl getFindProductById() {
        return (ViewObjectImpl)findViewObject("FindProductById");
    }

    /**Container's getter for MyOrdersAddresses.
     * @return
     */
    public ViewObjectImpl getMyOrdersAddresses() {
        return (ViewObjectImpl)findViewObject("MyOrdersAddresses");
    }

    /**Container's getter for OrdersToAddresses2.
     * @return
     */
    public ViewLinkImpl getOrdersToAddresses2() {
        return (ViewLinkImpl)findViewLink("OrdersToAddresses2");
    }

    /**Container's getter for MyOrdersPaymentOptions.
     * @return
     */
    public ViewObjectImpl getMyOrdersPaymentOptions() {
        return (ViewObjectImpl)findViewObject("MyOrdersPaymentOptions");
    }

    /**Container's getter for OrdersToPaymentOptions2.
     * @return
     */
    public ViewLinkImpl getOrdersToPaymentOptions2() {
        return (ViewLinkImpl)findViewLink("OrdersToPaymentOptions2");
    }

    /**Container's getter for MyOrdersBillingAddresses.
     * @return
     */
    public ViewObjectImpl getMyOrdersBillingAddresses() {
        return (ViewObjectImpl)findViewObject("MyOrdersBillingAddresses");
    }

    /**Container's getter for PaymentOptionsToAddresses2.
     * @return
     */
    public ViewLinkImpl getPaymentOptionsToAddresses2() {
        return (ViewLinkImpl)findViewLink("PaymentOptionsToAddresses2");
    }

    /**Container's getter for Orders.
     * @return
     */
    public OrdersVOImpl getOrders() {
        return (OrdersVOImpl)findViewObject("Orders");
    }

    /**Container's getter for OrderItems.
     * @return
     */
    public OrderItemsVOImpl getOrderItems() {
        return (OrderItemsVOImpl)findViewObject("OrderItems");
    }

    /**Container's getter for OrdersToOrderItems.
     * @return
     */
    public ViewLinkImpl getOrdersToOrderItems() {
        return (ViewLinkImpl)findViewLink("OrdersToOrderItems");
    }

    /**Container's getter for MyShoppingCart.
     * @return
     */
    public ShoppingCartTransientVOImpl getMyShoppingCart() {
       ShoppingCartTransientVOImpl shoppingCartVO =  (ShoppingCartTransientVOImpl)findViewObject("MyShoppingCart");
       return shoppingCartVO;
    }

    /**
     * Container's getter for CustomerInterestsVO1.
     * @return CustomerInterestsVO1
     */
    public ViewObjectImpl getCustomerInterestsVO1() {
        return (ViewObjectImpl)findViewObject("CustomerInterestsVO1");
    }

    /**
     * Container's getter for PersonsToPersonsInterestsVO2.
     * @return PersonsToPersonsInterestsVO2
     */
    public ViewLinkImpl getPersonsToPersonsInterestsVO2() {
        return (ViewLinkImpl)findViewLink("PersonsToPersonsInterestsVO2");
    }

    /**
     * Container's getter for OrderInfoVO1.
     * @return OrderInfoVO1
     */
    public ViewObjectImpl getOrderInfoVO1() {
        return (ViewObjectImpl)findViewObject("OrderInfoVO1");
    }

    /**
     * Container's getter for OrderItemsInfoVO1.
     * @return OrderItemsInfoVO1
     */
    public ViewObjectImpl getOrderItemsInfoVO1() {
        return (ViewObjectImpl)findViewObject("OrderItemsInfoVO1");
    }

    /**
     * Container's getter for OrderInfoToOrderItemInfo1.
     * @return OrderInfoToOrderItemInfo1
     */
    public ViewLinkImpl getOrderInfoToOrderItemInfo1() {
        return (ViewLinkImpl)findViewLink("OrderInfoToOrderItemInfo1");
    }

    /**
     * Container's getter for CustomerInfoVO1.
     * @return CustomerInfoVO1
     */
    public ViewObjectImpl getCustomerInfoVO1() {
        return (ViewObjectImpl)findViewObject("CustomerInfoVO1");
    }

    /**
     * Container's getter for DiscountTranslations1.
     * @return DiscountTranslations1
     */
    public ViewObjectImpl getDiscountTranslations1() {
        return (ViewObjectImpl)findViewObject("DiscountTranslations1");
    }

    /**
     * Container's getter for AddressesAndUsagesVO1.
     * @return AddressesAndUsagesVO1
     */
    public AddressesAndUsagesVOImpl getAddressesAndUsagesVO1() {
        return (AddressesAndUsagesVOImpl)findViewObject("AddressesAndUsagesVO1");
    }

    /** Container's getter for FeaturedItem.
    * @return FeaturedItem
    */
    public ViewObjectImpl getFeaturedItem() {
       return (ViewObjectImpl)findViewObject("FeaturedItem");
    }

    /**
     * Container's getter for ProductOrdersMaxQuantity.
     * @return ProductOrdersMaxQuantity
     */
    public ViewObjectImpl getProductOrdersMaxQuantity() {
        return (ViewObjectImpl)findViewObject("ProductOrdersMaxQuantity");
    }

    /**
     * Sample exportable method.
     */
    public void sampleStoreServiceAMImplExportable() {
    }

    /**
     * Sample exportable method.
     */
    public void sampleStoreServiceAMImplExportable2(String testParam1) {
    }

    /**
     * Sample exportable method.
     */
    public List<String> sampleStoreServiceAMImplExportable3(List<String> listParam,
                                                            String testParam1) {
        return listParam;
    }

    /**
     * Sample exportable method.
     */
    public HashMap<String, String> sampleStoreServiceAMImplExportable4(HashMap<String, String> hashParam,
                                                                       String testParam1) {
        return hashParam;
    }


}
