package com.trywildcard.pair.model.product; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; import com.trywildcard.pair.exception.CardBuilderException; import com.trywildcard.pair.model.Builder; import com.trywildcard.pair.extraction.MetaTagModel; import com.trywildcard.pair.validation.ValidationTool; import org.apache.commons.lang3.StringUtils; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @JsonPOJOBuilder(buildMethodName = "build", withPrefix = "") public class ProductBuilder implements Builder<Product> { protected ValidationTool v = new ValidationTool(); //required fields protected String name; protected String description; protected List<URL> images = new ArrayList<URL>(); //optional fields protected String merchant; protected String brand; protected List<ProductColor> colors = new ArrayList<ProductColor>(); protected Float rating; protected Float ratingScale; protected Integer ratingCount; protected List<URL> relatedItems = new ArrayList<URL>(); protected List<URL> referencedItems = new ArrayList<URL>(); protected Map<String, String> sizes = new HashMap<String, String>(); protected List<String> options = new ArrayList<String>(); protected Gender gender; protected String model; private ProductBuilder() { } /** * Construct an <code>ProductBuilder</code> provided a name, description and list of images. * * @param name */ public ProductBuilder(String name, String description, String image) throws CardBuilderException { name(name); description(description); image(image); } /** * Construct an <code>ProductBuilder</code> provided a name, description and list of images. * * @param name */ public ProductBuilder(String name, String description, List<String> images) throws CardBuilderException { name(name); description(description); images(images); } public ProductBuilder(MetaTagModel metaTagModel) throws CardBuilderException { if (metaTagModel == null) { throw new CardBuilderException("MetaTagModel is required"); } //try to build product first, it requires a name, description and image if (StringUtils.isEmpty(metaTagModel.getTitle()) || StringUtils.isEmpty(metaTagModel.getDescription()) || StringUtils.isEmpty(metaTagModel.getImageUrl())) { throw new CardBuilderException("Product title and/or product description and/or product image is not contained in meta tags and is required to create a ProductBuilder"); } name(metaTagModel.getTitle()); description(metaTagModel.getDescription()); image(metaTagModel.getImageUrl()); } public ProductBuilder model(String model) { boolean isValid = v.optional(v.notEmpty(model), "Tried to set model to an empty string."); if (isValid) { this.model = model; } return this; } public ProductBuilder gender(Gender gender) { this.gender = gender; return this; } public ProductBuilder sizes(Map<String, String> sizes) { boolean isValid = v.optional(v.notNull(sizes), "Sizes must not be null."); if (isValid) { for (String key : sizes.keySet()) { String value = sizes.get(key); boolean isValidSize = v.optional(v.notNullOrEmpty(value), "Tried to set a null or empty size value."); if (isValidSize) { this.sizes.put(key, value); } } } return this; } public ProductBuilder option(String option) { boolean isValid = v.optional(v.notNullOrEmpty(option), "Tried to add an empty option."); if (isValid) { this.options.add(option); } return this; } public ProductBuilder options(List<String> options) { boolean isValid = v.optional(v.notNull(options), "Options must not be null."); if (isValid) { for (String option : options) { boolean isValidOption = v.optional(v.notNullOrEmpty(option), "Tried to add an empty option."); if (isValidOption) { this.options.add(option); } } } return this; } public ProductBuilder relatedItem(String relatedItem) { boolean isValid = v.optional(v.notNull(relatedItem), "Tried to add an empty relatedItem."); if (isValid) { try { this.relatedItems.add(new URL(relatedItem)); } catch (MalformedURLException e) { v.optional(v.fail(), "Could not parse URL from relatedItem string."); } } return this; } public ProductBuilder relatedItems(List<String> relatedItems) { boolean isValid = v.optional(v.notNull(relatedItems), "relatedItems must not be null."); if (isValid) { for (String relatedItem : relatedItems) { boolean isValidRelatedItem = v.optional(v.notNull(relatedItem), "Tried to add an empty relatedItem."); if (isValidRelatedItem) { try { this.relatedItems.add(new URL(relatedItem)); } catch (MalformedURLException e) { v.optional(v.fail(), "Could not parse URL from relatedItem string."); } } } } return this; } public ProductBuilder referencedItem(String referencedItem) { boolean isValid = v.optional(v.notNull(referencedItem), "Tried to add an empty relatedItem."); if (isValid) { try { this.relatedItems.add(new URL(referencedItem)); } catch (MalformedURLException e) { v.optional(v.fail(), "Could not parse URL from string."); } } return this; } public ProductBuilder referencedItems(List<String> referencedItems) { boolean isValid = v.optional(v.notNull(referencedItems), "relatedItems must not be null."); if (isValid) { for (String referencedItem : referencedItems) { boolean isValidReferenceItem = v.optional(v.notNull(referencedItem), "Tried to add an empty relatedItem."); if (isValidReferenceItem) { try { this.referencedItems.add(new URL(referencedItem)); } catch (MalformedURLException e) { v.optional(v.fail(), "Could not parse URL from string."); } } } } return this; } public ProductBuilder ratingCount(Integer ratingCount) { boolean isValid = v.optional(v.notNegative(ratingCount), "ratingCount must be a positive integer."); if (isValid) { this.ratingCount = ratingCount; } return this; } public ProductBuilder ratingScale(Float ratingScale) { this.ratingScale = ratingScale; return this; } public ProductBuilder rating(Float rating) { this.rating = rating; return this; } private ProductBuilder image(String imgUrl) throws CardBuilderException { boolean isValid = v.required(v.notNull(imgUrl), "Tried to add a null imgUrl"); if (isValid) { try { images.add(new URL(imgUrl)); } catch (MalformedURLException e) { v.required(v.fail(), "Could not parse image URL from string."); } } return this; } private ProductBuilder images(List<String> images) throws CardBuilderException { boolean isValid = v.required(v.notNullOrEmpty(images), "images must not be null."); if (isValid) { for (String img : images) { boolean isValidImg = v.required(v.notNull(img), "Tried to add a null image"); if (isValidImg) { try { this.images.add(new URL(img)); } catch (MalformedURLException e) { v.required(v.fail(), "Could not parse image URL from string."); } } } } return this; } public ProductBuilder color(ProductColor color) { boolean isValid = v.optional(v.notNull(color), "Tried to add a null color"); if (isValid) { colors.add(color); } return this; } public ProductBuilder colors(List<ProductColor> colors) { boolean isValid = v.optional(v.notNull(colors), "colors must not be null."); if (isValid) { for (ProductColor color : colors) { boolean isValidColor = v.optional(v.notNull(color), "Tried to add a null color"); if (isValidColor) { this.colors.add(color); } } } return this; } public ProductBuilder description(String description) throws CardBuilderException { boolean isValid = v.required(v.notNullOrEmpty(description), "Product Description cannot be blank"); if (isValid) { this.description = description; } return this; } public ProductBuilder brand(String brand) { boolean isValid = v.optional(v.notEmpty(brand), "Tried to set brand to an empty string."); if (isValid) { this.brand = brand; } return this; } public ProductBuilder merchant(String merchant) { boolean isValid = v.optional(v.notEmpty(merchant), "Tried to set merchant to an empty string."); if (isValid) { this.merchant = merchant; } return this; } private ProductBuilder name(String name) throws CardBuilderException { boolean isValid = v.required(v.notNullOrEmpty(name), "Product name cannot be blank."); if (isValid) { this.name = name; } return this; } /** * Instantiate a <code>ProductCard</code> with the data in this builder. * * @return the constructed product card */ public Product build() { Product product = new Product(this); return product; } /** * Get a list of validation errors. * * @return the list of errors. */ public List<String> getErrors() { return v.getErrors(); } }