Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package com.adobe.cq.commerce.common;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Currency;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.query.Query;
import javax.jcr.query.QueryManager;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.apache.jackrabbit.util.Text;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ValueMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/*************************************************************************
*
* ADOBE CONFIDENTIAL
* __________________
*
* Copyright 2013 Adobe Systems Incorporated
* All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of Adobe Systems Incorporated and its suppliers,
* if any. The intellectual and technical concepts contained
* herein are proprietary to Adobe Systems Incorporated and its
* suppliers and are protected by trade secret or copyright law.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from Adobe Systems Incorporated.
**************************************************************************/
import com.adobe.cq.commerce.api.CommerceException;
import com.adobe.cq.commerce.api.CommerceSession;
import com.adobe.cq.commerce.api.PlacedOrder;
import com.adobe.cq.commerce.api.PriceInfo;
import com.adobe.cq.commerce.api.Product;
import com.adobe.cq.commerce.api.conf.CommerceBasePathsService;
import com.adobe.cq.commerce.api.promotion.PromotionInfo;
import com.adobe.cq.commerce.api.promotion.Voucher;
import com.adobe.cq.commerce.api.promotion.VoucherInfo;
import com.adobe.cq.commerce.impl.promotion.JcrVoucherImpl;
import com.day.cq.commons.jcr.JcrUtil;
/**
* An editable implementation of a {@link PlacedOrder}, for use in order administration.
*
* NB: models vendor records in /var/commerce/orders/, not shopper records in ~/commerce/orders/.
* For (read-only) access to shopper records, see {@link DefaultJcrPlacedOrder}.
*/
public class VendorJcrPlacedOrder implements PlacedOrder {
protected static final Logger log = LoggerFactory.getLogger(VendorJcrPlacedOrder.class);
protected Resource order;
protected Map details;
protected List prices;
protected List entries;
protected AbstractJcrCommerceService commerceService;
protected Locale locale;
/**
* Instantiate a new, writable PlacedOrder record.
*
* @param commerceService The owning CommerceService
* @param orderId An ID uniquely identifying the placed order. Can either be the orderId property, or
* the path to the order node. (The path is obviously quicker, but the orderId might
* be used to track the order in external systems, such as fulfillment systems.)
* @param locale
*/
public VendorJcrPlacedOrder(AbstractJcrCommerceService commerceService, String orderId, Locale locale) {
this.commerceService = commerceService;
this.locale = locale;
this.order = getPlacedOrder(orderId);
}
@Override
public String getOrderId() throws CommerceException {
if (details == null) {
lazyLoadOrderDetails();
}
return (String) details.get("orderId");
}
@Override
public Map getOrder() throws CommerceException {
if (details == null) {
lazyLoadOrderDetails();
}
return details;
}
/**
* Update a number of properties in the order record. Currently this is a "raw" update;
* there is no re-calculation involved.
* @param delta The properties to update. Properties not in this set will NOT be removed;
* to remove a property include it with a value of null.
* @param autoSave If true, the current session will be saved after updating the order.
* @throws CommerceException
*/
public void updateOrder(Map delta, boolean autoSave) throws CommerceException {
try {
Node orderNode = order.adaptTo(Node.class);
for (Map.Entry entry : delta.entrySet()) {
String key = entry.getKey();
// skip synthetic properties
if ("orderPath".equals(key) || key.endsWith("Formatted")) {
continue;
}
setProperty(orderNode, key, entry.getValue());
}
if (autoSave) {
orderNode.getSession().save();
}
} catch (RepositoryException e) {
throw new CommerceException("Failed to persist the order properties", e);
} finally {
// caches will need re-loading...
details = null;
prices = null;
entries = null;
}
}
protected void setProperty(Node node, String propertyPath, Object value) throws RepositoryException {
String propertyName = propertyPath;
int lastSlash = propertyPath.lastIndexOf('/');
if (lastSlash >= 0) {
node = JcrUtil.createPath(node, propertyPath.substring(0, lastSlash), false, "nt:unstructured", "nt:unstructured",
node.getSession(), false);
propertyName = propertyPath.substring(lastSlash + 1);
}
if (value instanceof Calendar) {
node.setProperty(propertyName, (Calendar) value);
} else if (value instanceof BigDecimal) {
node.setProperty(propertyName, (BigDecimal) value);
} else if (value instanceof String) {
String stringValue = (String) value;
if (stringValue.startsWith("[") && stringValue.endsWith("]")) {
String[] stringValues = stringValue.substring(1, stringValue.length()-1).split(",");
node.setProperty(propertyName, stringValues);
} else {
node.setProperty(propertyName, stringValue);
}
} else if (value instanceof String[]) {
node.setProperty(propertyName, (String[]) value);
}
}
//
// On-demand loads the details member variable from the order data.
//
private void lazyLoadOrderDetails() throws CommerceException {
details = new HashMap();
if (order != null) {
final SimpleDateFormat dateFmt = new SimpleDateFormat("dd MMM, yyyy");
details.put("orderPath", order.getPath());
ValueMap orderProperties = order.getValueMap();
for (Map.Entry entry : orderProperties.entrySet()) {
String key = entry.getKey();
if ("cartItems".equals(key)) {
// returned by getPlacedOrderEntries()
} else {
Object property = entry.getValue();
if (property instanceof Calendar) {
// explode date into 'property' and 'propertyFormatted'
details.put(key, property);
details.put(key + "Formatted", dateFmt.format(((Calendar) property).getTime()));
} else {
details.put(key, property);
}
}
}
Resource orderDetailsChild = order.getChild("order-details");
if (orderDetailsChild != null) {
ValueMap orderDetailProperties = orderDetailsChild.getValueMap();
for (ValueMap.Entry detailProperty : orderDetailProperties.entrySet()) {
String key = detailProperty.getKey();
Object property = detailProperty.getValue();
if (property instanceof Calendar) {
// explode date into 'property' and 'propertyFormatted'
details.put("order-details/" + key, property);
details.put("order-details/" + key + "Formatted", dateFmt.format(((Calendar) property).getTime()));
} else {
details.put("order-details/" + key, property);
}
}
}
}
}
@Override
public List getCartPriceInfo(Predicate filter) throws CommerceException {
if (prices == null) {
lazyLoadPriceInfo();
}
List filteredPrices = new ArrayList();
CollectionUtils.select(prices, filter, filteredPrices);
return filteredPrices;
}
@Override
public String getCartPrice(Predicate filter) throws CommerceException {
if (prices == null) {
lazyLoadPriceInfo();
}
PriceInfo price = (PriceInfo) CollectionUtils.find(prices, filter);
if (price != null) {
return price.getFormattedString();
} else {
return "";
}
}
//
// On-demand loads the prices member variable from the order data.
//
protected void lazyLoadPriceInfo() throws CommerceException {
prices = new ArrayList();
if (order != null) {
ValueMap orderMap = order.getValueMap();
String currencyCode = orderMap.get("currencyCode", String.class);
if (currencyCode == null) {
log.error("Missing currencyCode in order: " + order.getPath());
log.error("Assuming 'USD'");
currencyCode = "USD";
}
Currency currency = Currency.getInstance(currencyCode);
//
// Note: order is important; non-fully-specified price requests will get the first match.
//
PriceInfo price = new PriceInfo(orderMap.get("orderTotalPrice", BigDecimal.class), locale, currency);
price.put(PriceFilter.PN_TYPES, new HashSet(Arrays.asList("orderTotalPrice")));
prices.add(price);
price = new PriceInfo(orderMap.get("orderTotalTax", BigDecimal.class), locale, currency);
price.put(PriceFilter.PN_TYPES, new HashSet(Arrays.asList("orderTotalTax")));
prices.add(price);
price = new PriceInfo(orderMap.get("cartSubtotal", BigDecimal.class), locale, currency);
price.put(PriceFilter.PN_TYPES, new HashSet(Arrays.asList("cartSubtotal")));
prices.add(price);
price = new PriceInfo(orderMap.get("orderShipping", BigDecimal.class), locale, currency);
price.put(PriceFilter.PN_TYPES, new HashSet(Arrays.asList("orderShipping")));
prices.add(price);
}
}
@Override
public List getCartEntries() throws CommerceException {
if (entries == null) {
lazyLoadCartEntries();
}
return entries;
}
//
// On-demand loads the entries member variable form the order data.
//
protected void lazyLoadCartEntries() throws CommerceException {
entries = new ArrayList();
if (order != null) {
String[] serializedEntries = order.getValueMap().get("cartItems", new String[0]);
for (String serializedEntry : serializedEntries) {
try {
CommerceSession.CartEntry entry = deserializeCartEntry(serializedEntry, entries.size());
entries.add(entry);
} catch (Exception e) { // NOSONAR (catch any errors thrown attempting to parse/decode entry)
log.error("Unable to load product from order: {}", serializedEntry);
}
}
}
}
protected CommerceSession.CartEntry deserializeCartEntry(String str, int index) throws CommerceException {
Object[] entryData = commerceService.deserializeCartEntryData(str);
Product product = (Product) entryData[0];
int quantity = (Integer) entryData[1];
DefaultJcrCartEntry entry = commerceService.newCartEntryImpl(index, product, quantity);
if (entryData[2] == null) {
return entry;
}
@SuppressWarnings("unchecked")
Map properties = (Map) entryData[2];
entry.updateProperties(properties);
return entry;
}
@Override
public List getPromotions() throws CommerceException {
List infos = new ArrayList();
if (order != null) {
String[] records = order.getValueMap().get("promotions", new String[]{});
for (String record : records) {
try {
String[] fields = record.split(";", 3);
String path = "null".equals(fields[0]) ? null : fields[0];
Integer entryIndex = "null".equals(fields[1]) ? null : Integer.parseInt(fields[1]);
String message = "null".equals(fields[2]) ? null : fields[2];
infos.add(new PromotionInfo(path, "", PromotionInfo.PromotionStatus.FIRED, "", message, entryIndex));
} catch (Exception e) { // NOSONAR (catch any errors thrown attempting to parse/decode entry)
log.error("Unable to load promotion: " + record, e);
}
}
}
return infos;
}
@Override
public List getVoucherInfos() throws CommerceException {
List infos = new ArrayList();
if (order != null) {
String[] records = order.getValueMap().get("vouchers", new String[]{});
for (String record : records) {
String[] fields = record.split(";", 3);
try {
if (fields.length == 1) {
// 5.6 only wrote out the path of JCR vouchers. Since we have no way of knowing if the
// Voucher has materially changed since the order was placed (or even if the Voucher
// still exists, for that matter), just attempt to fetch the voucher code out of it.
String path = fields[0];
Voucher voucher = new JcrVoucherImpl(order.getResourceResolver().getResource(path));
infos.add(new VoucherInfo(voucher.getCode(), voucher.getPath(), "", "", true, ""));
} else {
// 6.0 serializes code;path;message
String code = "null".equals(fields[0]) ? null : fields[0];
String path = "null".equals(fields[1]) ? null : fields[1];
String message = "null".equals(fields[2]) ? null : fields[2];
infos.add(new VoucherInfo(code, path, "", "", true, message));
}
} catch (Exception e) { // NOSONAR (catch any errors thrown attempting to parse/decode entry)
log.error("Unable to load voucher from order: {}", record);
}
}
}
return infos;
}
/**
* Return the resource for a placed order identified by path or primary key. (A path is obviously
* quicker, but a primary key might be used to track the order in external systems, such as fulfillment
* systems.)
*/
protected Resource getPlacedOrder(String orderId) {
try {
//
// Quick way -- orderId is already a path:
//
if (orderId.startsWith("/")) {
return commerceService.resolver.getResource(orderId);
}
//
// Slow way -- orderId needs to be looked up in the user's home directory:
//
// example query: /jcr:root/var/commerce/orders//element(*)[@orderId='foo')]
CommerceBasePathsService cbps = commerceService.resolver.adaptTo(CommerceBasePathsService.class);
StringBuilder buffer = new StringBuilder();
buffer.append("/jcr:root" + cbps.getOrdersBasePath() + "//element(*)[@orderId = '")
.append(Text.escapeIllegalXpathSearchChars(orderId).replaceAll("'", "''"))
.append("']");
final QueryManager queryManager = commerceService.resolver.adaptTo(Session.class).getWorkspace().getQueryManager();
final Query query = queryManager.createQuery(buffer.toString(), Query.XPATH);
NodeIterator nodeIterator = query.execute().getNodes();
if (nodeIterator.hasNext()) {
return commerceService.resolver.getResource(nodeIterator.nextNode().getPath());
}
} catch (Exception e) { // NOSONAR (fail-safe for when the query above contains errors)
log.error("Error while searching for order history with orderId '" + orderId + "'", e);
}
return null;
}
}