package utils; import java.io.IOException; import java.math.BigDecimal; import java.text.NumberFormat; import java.util.*; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.github.jknack.handlebars.*; import com.github.jknack.handlebars.io.*; import com.neovisionaries.i18n.CountryCode; import controllers.routes; import io.sphere.client.model.Money; import io.sphere.client.model.SearchResult; import io.sphere.client.shop.model.*; import org.apache.commons.lang3.text.WordUtils; import play.Play; import play.mvc.Call; import play.mvc.Http; import sphere.Sphere; import static utils.ControllerHelper.getGrossPrice; public class ViewHelper { /** * Returns the current Cart in session. */ public static Cart getCurrentCart() { return Sphere.getInstance().currentCart().fetch(); } public static Customer getCurrentCustomer() { Customer customer = null; if (Sphere.getInstance().isLoggedIn()) { customer = Sphere.getInstance().currentCustomer().fetch(); } return customer; } public static boolean isLoggedIn() { return Sphere.getInstance().isLoggedIn(); } /** * Returns the list of root categories */ public static List<Category> getRootCategories() { return Sphere.getInstance().categories().getRoots(); } public static String capitalizeInitials(String text) { return WordUtils.capitalizeFully(text); } public static String getCountryName(String code) { try { return CountryCode.getByCode(code).getName(); } catch (Exception e) { return ""; } } /** * Compares the categories and returns the 'active' class if are the same. * @return 'active' if categories are the same, otherwise an empty string. */ public static String getActiveClass(Category category, Category currentCategory) { String active = ""; if (currentCategory != null && currentCategory.getPathInTree().contains(category)) { active = "active"; } return active; } public static String getStockInformation(Variant variant) { if (variant.getAvailability() == null) return ""; return variant.getAvailability().isOnStock()? "In stock" : "Not available"; } public static BigDecimal getPercentage(double amount) { return BigDecimal.valueOf(amount * 100).stripTrailingZeros(); } public static boolean isSet(Object object) { return object != null; } /** * TEMPLATE UTIL METHODS */ public static Handlebars initializeHandlebars() throws IOException{ TemplateLoader loader = new ClassPathTemplateLoader("/public/templates"); return new Handlebars(loader); } public static Template getTemplate(String templateName) { try { return initializeHandlebars().compile(templateName); } catch (IOException ioe) { play.Logger.error(ioe.getMessage()); } return null; } public static String getJavaScriptTemplate(String templateName) { try { return initializeHandlebars().compileInline("{{precompile \"" + templateName + "\"}}").apply(""); } catch (IOException ioe) { play.Logger.error(ioe.getMessage()); } return ""; } public static String renderTemplate(Template template, JsonNode model) { if (template == null) return ""; try { String html = template.apply(Context.newBuilder(model).resolver(JsonNodeValueResolver.INSTANCE).build()); // TODO Remove when Handlebars java fixes this bug that adds quotes to arrays // https://github.com/jknack/handlebars.java/issues/260 return html.replace(""", ""); } catch(IOException ioe) { play.Logger.error("Could not render item with template"); } return ""; } public static String renderTemplateProductList(Template template, ObjectNode json) { String html = ""; for (JsonNode model : json.path("product")) { html += renderTemplate(template, model); } return html; } /** * PRICE UTIL METHODS */ public static Money getShippingCost() { // TODO Implement correct shipping cost return new Money(BigDecimal.valueOf(10), "EUR"); } /* Methods for printing prices */ public static String printPrice(Money money) { if (money == null) return ""; return printPriceAmount(money) + " " + printPriceCurrency(money.getCurrencyCode()); } public static String printPriceAmount(Money money) { if (money == null) return ""; NumberFormat format = NumberFormat.getInstance(Locale.GERMANY); format.setMinimumFractionDigits(2); return format.format(money.getAmount()); } public static String printPriceCurrency(String currencyCode) { return Currency.getInstance(currencyCode).getSymbol(Locale.GERMANY); } /* Calculate total price for all line items */ public static Money getLineItemsTotalPrice(Order order) { Money itemsTotalPrice = new Money(BigDecimal.ZERO, order.getCurrency().getCurrencyCode()); for (LineItem item : order.getLineItems()) { itemsTotalPrice = itemsTotalPrice.plus(getPrice(item)); } return itemsTotalPrice; } /* Set of methods to get correct price */ public static Money getPrice(Cart cart) { if (cart == null) return null; if (cart.getTaxedPrice() == null) return cart.getTotalPrice(); return cart.getTaxedPrice().getTotalGross(); } public static Money getPrice(Order order) { if (order == null) return null; if (order.getTaxedPrice() == null) return order.getTotalPrice(); return order.getTaxedPrice().getTotalGross(); } public static Money getPrice(ShippingInfo shippingInfo) { if (shippingInfo == null) return null; return getPrice(shippingInfo.getPrice(), shippingInfo.getTaxRate()); } public static Money getPrice(LineItem item) { if (item == null) return null; return getPrice(item.getTotalPrice(), item.getTaxRate()); } public static Money getPrice(CustomLineItem item) { if (item == null) return null; return getPrice(item.getMoney().multiply(item.getQuantity()), item.getTaxRate()); } public static Money getPrice(Variant variant) { if (variant == null || variant.getPrice() == null) return null; return variant.getPrice().getValue(); } public static Money getPrice(Money price, TaxRate rate) { return getGrossPrice(price, rate); } /** * URLS UTIL METHODS */ public static Call getProductListUrl(SearchResult<Product> search, String sort, Category category) { if (search.getCurrentPage() >= search.getTotalPages() - 1) { return null; } // Convert from 0..N-1 to 1..N int nextPage = search.getCurrentPage() + 2; return getProductListUrl(nextPage, sort, category); } public static Call getProductListUrl(int page, String sort, Category category) { String categorySlug = ""; if (category != null) { categorySlug = category.getSlug(); } return routes.Categories.listProducts(categorySlug, sort, page); } public static Call getCategoryUrl(Category category) { return getCategoryUrl(category, 1); } public static Call getCategoryUrl(Category category, int page) { return routes.Categories.select(category.getSlug(), "", page); } public static Call getCategoryUrl(Category category, String sort, int page) { return routes.Categories.select(category.getSlug(), sort, page); } public static Call getProductUrl(Product product, Variant variant, Category category) { return routes.Products.select(product.getSlug(), variant.getId()); } public static String getReturnUrl() { return Http.Context.current().session().get("returnUrl"); } public static String paymillPublicKey() { return Play.application().configuration().getString("paymill.key.public", ""); } /** * PRODUCTS UTIL METHODS */ /** * Check whether the given product has more than one attribute value * @return true if the product has more than one attribute value, false otherwise */ public static boolean hasMoreAttributeValues(Product product, String attributeName) { return product.getVariants().getAvailableAttributes(attributeName).size() > 1; } /** * Check whether the given Product has more than one 'color' attribute * @return true if the product has more than one color, false otherwise */ public static boolean hasMoreColors(Product product) { return hasMoreAttributeValues(product, "color"); } /** * Check whether the given Product has more than one 'size' attribute * @return true if the product has more than one size, false otherwise */ public static boolean hasMoreSizes(Product product) { return hasMoreAttributeValues(product, "size"); } /* Get possible variant sizes for a particular variant */ public static List<String> getPossibleSizes(Product product, Variant variant) { List<Variant> variants = getPossibleVariants(product, variant, "size"); List<String> sizes = new ArrayList<String>(); for (Variant matchedVariant : variants) { sizes.add(matchedVariant.getString("size")); } return sizes; } /* Get variants with matching attributes but with different selected attribute * This method can be simplified if fixed and variable attributes are known beforehand */ public static List<Variant> getPossibleVariants(Product product, Variant variant, String selectedAttribute) { List<Variant> matchingVariantList = new ArrayList<Variant>(); List<Attribute> desiredAttributes = new ArrayList<Attribute>(); // Get all other attributes with more than one different value for (Attribute attribute : variant.getAttributes()) { if (!selectedAttribute.equals(attribute.getName()) && hasMoreAttributeValues(product, attribute.getName())) { desiredAttributes.add(attribute); } } // Get variants matching all these other attributes but different selected attribute VariantList variantList = product.getVariants().byAttributes(desiredAttributes); for (Attribute attr : product.getVariants().getAvailableAttributes(selectedAttribute)) { if (variantList.byAttributes(attr).size() < 1) { matchingVariantList.add((product.getVariants().byAttributes(attr).first()).orNull()); } else { matchingVariantList.add((variantList.byAttributes(attr).first()).orNull()); } } matchingVariantList.removeAll(Collections.singleton(null)); return matchingVariantList; } }