Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package org.books.integration; import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.ejb.EJB; import javax.ejb.Stateless; import org.apache.commons.lang3.StringUtils; import org.books.application.exception.BookNotFoundException; import org.books.base.Util; import org.books.integration.amazon.Errors.Error; import org.books.integration.amazon.Errors; import org.books.integration.amazon.Item; import org.books.integration.amazon.ItemAttributes; import org.books.integration.amazon.ItemLookup; import org.books.integration.amazon.ItemLookupRequest; import org.books.integration.amazon.ItemLookupResponse; import org.books.integration.amazon.Items; import org.books.integration.amazon.ItemSearch; import org.books.integration.amazon.ItemSearchRequest; import org.books.integration.amazon.ItemSearchResponse; import org.books.integration.amazon.OperationRequest; import org.books.integration.amazon.Price; import org.books.integration.amazon.Request; import org.books.persistence.dto.BookInfo; import org.books.persistence.entity.Book; import org.books.persistence.enumeration.BookBinding; /** * Catalog service bean to provide access to books * * @author me */ @Stateless(name = "AmazonCatalog", mappedName = "AmazonCatalog") public class AmazonCatalogBean implements AmazonCatalog { protected final static Logger LOGGER = Logger.getLogger(AmazonCatalogBean.class.getName()); private static final Pattern YEAR_PATTERN = Pattern.compile("(\\d\\d\\d\\d)"); private static final int MAX_ITEM_PAGE = 10; private static final int PAGE_PER_REQUEST = 2; @EJB private AmazonRequestsExecuter amazon; @Override public Book findBook(String isbn) throws BookNotFoundException { Book result = null; ItemLookup itemLookup = new ItemLookup(); ItemLookupRequest lookupRequest = new ItemLookupRequest(); lookupRequest.setSearchIndex("Books"); lookupRequest.setIdType("ISBN"); lookupRequest.getResponseGroup().add("ItemAttributes"); lookupRequest.getItemId().add(isbn); itemLookup.getRequest().add(lookupRequest); ItemLookupResponse response = amazon.itemLookup(itemLookup); OperationRequest operationRequest = response.getOperationRequest(); for (Items items : response.getItems()) { Request itemRequest = items.getRequest(); if (!itemRequest.getIsValid().equalsIgnoreCase("true")) { continue; } for (Item item : items.getItem()) { ItemAttributes itemAttributes = item.getItemAttributes(); String itemIsbn = extractIsbn(itemAttributes, isbn); if (itemIsbn == null) { continue; } if (itemAttributes != null) { result = toBook(itemAttributes, itemIsbn); } if (result != null) { break; } } if (result != null) { break; } } if (result == null) { throw new BookNotFoundException(); } return result; } @Override public List<BookInfo> searchBooks(String keywords) { if (Util.isNullOrEmpty(keywords)) { throw new IllegalArgumentException(); } // ItemSearch: for Books amazon offers following local information for US // search index: Books // root browse node: 1000 // sort value: relevancerank, salesrank, reviewrank, pricerank, inverse-pricerank, daterank, titlerank, -titlerank, -unit-sales, price, -price, -publication_date, // item search parameters: Author, Availability, ItemPage, Keywords, MaximumPrice, MerchantId, MinPercentageOff, MinimumPrice, Power, Publisher, Sort, Title // Valid item identifier in US: ASIN, EAN, EISBN, ISBN, SKU, UPC // Only the US have ISBN!!!!! List<BookInfo> bookInfoList = new ArrayList<BookInfo>(); int itemPage = 0; int maxItemPage = MAX_ITEM_PAGE; int totalItemPage = maxItemPage; // at the start we expect to get at least one page // Loop for to make the item page requests while (true) { itemPage++; if (itemPage > totalItemPage) { LOGGER.log(Level.INFO, "searchBooks: all item page are read. {0} book found", bookInfoList.size()); break; } if (itemPage > maxItemPage) { LOGGER.log(Level.INFO, "searchBooks: max item page reached. {0} book found", bookInfoList.size()); break; } ItemSearch itemElement = new ItemSearch(); for (int pages = 0; pages < PAGE_PER_REQUEST; pages++) { if (pages > 0) { // only increate if it is not the first page we add to the request itemPage++; } if (itemPage > totalItemPage) { // don't add aditional page because we would not get more result continue; } if (itemPage > maxItemPage) { // don't add aditional page because more then index 10 is not allowed continue; } ItemSearchRequest itemRequest = new ItemSearchRequest(); itemRequest.setSearchIndex("Books"); // search only books itemRequest.setAvailability("Available"); // IMPORTANT: only available books !!! itemRequest.getResponseGroup().add("ItemAttributes"); // get as much as possible attributes itemRequest.setSort("salesrank"); // IMPORTANT: order by sales rank itemRequest.setKeywords(keywords); // keywords which the resulting books shall have itemRequest.setItemPage(BigInteger.valueOf(itemPage)); itemElement.getRequest().add(itemRequest); } ItemSearchResponse response = null; try { response = amazon.itemSearch(itemElement); } catch (Exception ex) { LOGGER.log(Level.SEVERE, "searchBooks: catched a AmazonThrottlingException: {0}", ex.getMessage()); continue; } if (response == null) { LOGGER.log(Level.SEVERE, "searchBooks: responce is null"); break; } if (!checkOperationRequest("searchBooks", response.getOperationRequest())) { // logs made in the method break; } for (Items responseItem : response.getItems()) { Request request = responseItem.getRequest(); if (!request.getIsValid().equalsIgnoreCase("true")) { LOGGER.log(Level.SEVERE, "searchBooks: result is invalid"); if (request.getErrors() != null) { reportError("searchBooks", request.getErrors().getError()); } continue; } totalItemPage = responseItem.getTotalPages().intValue(); for (Item bookItem : responseItem.getItem()) { ItemAttributes itemAttributes = bookItem.getItemAttributes(); Book book = toBook(itemAttributes, null); if (book != null) { BookInfo bookInfo = new BookInfo(book.getIsbn(), book.getTitle(), book.getPrice()); bookInfoList.add(bookInfo); } } } } return bookInfoList; } private Book toBook(ItemAttributes itemAttributes, String isbn) { if (isbn == null) { isbn = extractIsbn(itemAttributes, null); } if (itemAttributes == null || isbn == null) { return null; } Book book = book = new Book(isbn); try { String title = itemAttributes.getTitle(); book.setTitle(title); String authors = StringUtils.join(itemAttributes.getAuthor(), "; "); book.setAuthors(authors); String publisher = itemAttributes.getPublisher(); book.setPublisher(publisher); String publicationDate = itemAttributes.getPublicationDate(); book.setPublicationYear(toYear(publicationDate)); String binding = itemAttributes.getBinding(); book.setBinding(toBinding(binding)); BigInteger numberOfPages = itemAttributes.getNumberOfPages(); book.setNumberOfPages(toInteger(numberOfPages)); Price price = itemAttributes.getListPrice(); book.setPrice(toPrice(price)); } catch (Exception e) { LOGGER.log(Level.WARNING, "Failed convertion. Assume book is not complete: {0}", e.getMessage()); book = null; } return book; } private Integer toYear(String publicationDate) { Matcher m = YEAR_PATTERN.matcher(publicationDate); if (m.find()) { return Integer.parseInt(m.group(0)); } throw new IllegalArgumentException("unexpected date format:" + publicationDate); } private BookBinding toBinding(String binding) { try { return BookBinding.valueOf(binding.toUpperCase()); } catch (IllegalArgumentException e) { return BookBinding.UNKNOWN; } } private Integer toInteger(BigInteger numberOfPages) { return numberOfPages.intValue(); } private BigDecimal toPrice(Price price) { return new BigDecimal(price.getAmount(), 2); } private String extractIsbn(ItemAttributes itemAttributes, String matchingIsbn) { if (itemAttributes == null) { return null; } if (isMatching(itemAttributes.getISBN(), matchingIsbn)) { return itemAttributes.getISBN(); } if (itemAttributes.getEANList() != null && itemAttributes.getEANList().getEANListElement() != null) { for (String ean : itemAttributes.getEANList().getEANListElement()) { if (isMatching(ean, matchingIsbn)) { return ean; } } } return null; } private boolean isMatching(String value, String matchingString) { if (value == null) { return false; } if (matchingString == null) { return true; } return value.compareToIgnoreCase(matchingString) == 0; } private boolean checkOperationRequest(String methodName, OperationRequest operationRequest) { if (operationRequest == null) { LOGGER.log(Level.SEVERE, "{0}: operation request is null", methodName); return false; } // operationRequest.getArguments() Errors errors = operationRequest.getErrors(); if (errors != null) { if (!errors.getError().isEmpty()) { reportError(methodName, errors.getError()); return false; } } return true; } private void reportError(String methodName, List<Error> errorList) { LOGGER.log(Level.SEVERE, "{0}: response with errors", methodName); for (Error error : errorList) { LOGGER.log(Level.SEVERE, "{0}: - error({1}): {2}", new Object[] { methodName, error.getCode(), error.getMessage() }); } } }