com.adobe.cq.commerce.common.DefaultJcrCartEntry Maven / Gradle / Ivy
package com.adobe.cq.commerce.common;
import com.adobe.cq.commerce.api.CommerceException;
import com.adobe.cq.commerce.api.CommerceSession;
import com.adobe.cq.commerce.api.PriceInfo;
import com.adobe.cq.commerce.api.Product;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.apache.sling.api.resource.ValueMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* The default implementation for a {@link CommerceSession.CartEntry} used by
* {@link AbstractJcrCommerceSession}.
*
* Implementations requiring customization should extend this class and override
* {@link AbstractJcrCommerceService#newCartEntryImpl(int, com.adobe.cq.commerce.api.Product, int)}
* to return said extension.
*/
public class DefaultJcrCartEntry implements CommerceSession.CartEntry {
private int index;
private Product product;
private int quantity;
private List prices;
private ValueMap properties;
public DefaultJcrCartEntry(int index, Product product, int quantity) {
this.index = index;
this.product = product;
this.quantity = quantity;
this.properties = new ValueMapDecorator(new HashMap());
}
@Override
public int getEntryIndex() {
return index;
}
public void setEntryIndex(int index) {
this.index = index;
}
@Override
public Product getProduct() throws CommerceException {
return product;
}
@Override
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
@Override
public List getPriceInfo(Predicate filter) throws CommerceException {
if (filter != null) {
final List filtered = new ArrayList();
CollectionUtils.select(prices, filter, filtered);
return filtered;
}
return prices;
}
@Override
public String getPrice(Predicate filter) throws CommerceException {
final List filtered = getPriceInfo(filter);
if (filtered != null && filtered.size() > 0) {
return filtered.get(0).getFormattedString();
}
return "";
}
/**
* A helper routine which updates the cart entry prices with a new {@link PriceInfo}. If all
* the priceInfo's types match an existing entry, the entry will be updated.
*
* Note: automatically add the priceInfo's currencyCode as an additional tag to ease
* filtering on currency.
*
* @param priceInfo A {@link PriceInfo} containing the amount and currency.
* @param types Classifiers indicating the usage of the PriceInfo (ie: "UNIT", "PRE_TAX").
*/
public void setPrice(PriceInfo priceInfo, String... types) {
if (prices == null) {
prices = new ArrayList();
}
List typeList = new ArrayList(Arrays.asList(types));
// Append the currencyCode to the typeList so it's easier to filter on currency...
typeList.add(priceInfo.getCurrency().getCurrencyCode());
int index = prices.size();
for (int i=0; i < prices.size(); i++) {
final PriceInfo price = prices.get(i);
@SuppressWarnings("unchecked")
final Set priceTypes = (Set) price.get(PriceFilter.PN_TYPES);
if (CollectionUtils.isEqualCollection(priceTypes, typeList)) {
index = i;
break;
}
}
priceInfo.put(PriceFilter.PN_TYPES, new HashSet(typeList));
if (index == prices.size()) {
prices.add(priceInfo);
} else {
prices.set(index, priceInfo);
}
}
@Override
public T getProperty(String name, Class type) {
return properties == null ? null : properties.get(name, type);
}
/**
* Update the properties of this cart entry.
* Entries with valid key and null value results in the removal of a property.
* The entry with key equal to {@link CommerceSession#PN_QUANTITY} updates the {@code quantity} filed.
*
* @param propertyMap a map of property changes
*/
protected void updateProperties(Map propertyMap) {
if (propertyMap == null)
return;
Map internalMap = new HashMap();
for (Map.Entry entry : propertyMap.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
if (CommerceSession.PN_QUANTITY.equals(key)) {
if (value == null) {
setQuantity(0);
} else {
if (value instanceof Number) {
setQuantity(((Number) value).intValue());
} else {
//best effort
try {
setQuantity((Double.valueOf(String.valueOf(value))).intValue());
} catch (NumberFormatException x) {
//ignore
}
}
}
} else if (key != null) {
internalMap.put(key, value);
}
}
if (internalMap.isEmpty())
return;
if (this.properties.isEmpty()) {
this.properties = new ValueMapDecorator(internalMap);
} else {
for (Map.Entry entry : internalMap.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
if (value == null) {
this.properties.remove(key);
} else {
this.properties.put(key, value);
}
}
}
}
/**
* Returns the properties of this cart entry or an empty map if there are no properties.
*/
public ValueMap getProperties() {
return properties;
}
/*
* ==================================================================================================
* Deprecated methods. For backwards-compatibility only.
* ==================================================================================================
*/
@Deprecated // since 5.6
public String getUnitPrice() {
try {
return getPriceInfo(new PriceFilter("UNIT")).get(0).getFormattedString();
} catch(CommerceException e) {
return "";
}
}
@Deprecated // since 5.6
public String getPreTaxPrice() {
try {
return getPriceInfo(new PriceFilter("LINE", "PRE_TAX")).get(0).getFormattedString();
} catch(CommerceException e) {
return "";
}
}
@Deprecated // since 5.6
public String getTax() {
try {
return getPriceInfo(new PriceFilter("LINE", "TAX")).get(0).getFormattedString();
} catch(CommerceException e) {
return "";
}
}
@Deprecated // since 5.6
public String getTotalPrice() {
try {
return getPriceInfo(new PriceFilter("LINE", "POST_TAX")).get(0).getFormattedString();
} catch(CommerceException e) {
return "";
}
}
}