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.
/*************************************************************************
*
* ADOBE CONFIDENTIAL
* __________________
*
* Copyright 2012 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.
**************************************************************************/
package com.adobe.cq.commerce.common;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import com.adobe.cq.commerce.api.CommerceConstants;
import com.adobe.cq.commerce.api.CommerceException;
import com.adobe.cq.commerce.api.CommerceService;
import com.adobe.cq.commerce.api.Product;
import com.adobe.cq.commerce.api.asset.ProductAssetManager;
import com.adobe.cq.commerce.api.VariantFilter;
import com.day.cq.commons.ImageResource;
import com.day.cq.commons.inherit.ComponentInheritanceValueMap;
import aQute.bnd.annotation.ConsumerType;
import com.day.cq.commons.inherit.HierarchyNodeInheritanceValueMap;
import com.day.cq.commons.inherit.InheritanceValueMap;
import com.day.cq.dam.api.Asset;
import com.day.cq.dam.api.DamConstants;
import com.day.cq.dam.commons.util.DamUtil;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.EncoderException;
import org.apache.commons.codec.net.URLCodec;
import org.apache.commons.lang.StringUtils;
import org.apache.sling.adapter.SlingAdaptable;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ValueMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class is meant to be used as a base class for a {@link Product} implementation built on top of
* a JCR repository. GeoProductImpl is an example.
*/
@ConsumerType
public abstract class AbstractJcrProduct extends SlingAdaptable implements Product {
private static final String[] IMG_MIME_TYPES = {
DamConstants.THUMBNAIL_MIMETYPE, "image/jpeg", "image/tiff", "image/png",
"image/bmp", "image/gif", "image/pipeg", "image/x-portable-anymap",
"image/x-portable-bitmap", "image/x-portable-graymap",
"image/x-portable-pixmap", "image/x-rgb", "image/x-xbitmap",
"image/x-xpixmap", "image/x-icon", "image/photoshop",
"image/x-photoshop", "image/psd", "application/photoshop", "application/psd",
"image/vnd.adobe.photoshop"};
private static final List IMG_MIME_TYPE = Arrays.asList(IMG_MIME_TYPES);
// This first set is just here for backwards compatibility. "Truth" is now held in CommerceConstants.
protected static final String PN_PRODUCT_TYPE = CommerceConstants.PN_COMMERCE_TYPE;
protected static final String PN_PRODUCT_VARIANT_AXES = CommerceConstants.PN_PRODUCT_VARIANT_AXES;
protected static final String PN_PRODUCT_DATA = CommerceConstants.PN_PRODUCT_DATA;
protected static final String PN_PRODUCT_TITLE = "jcr:title";
protected static final String PN_PRODUCT_DESCRIPTION = "jcr:description";
protected static final String PN_PRODUCT_ASSET_CATEGORY = "assetCategory";
private static final String PN_ASSET_FILE_REFERENCE = "fileReference";
protected static final Logger log = LoggerFactory.getLogger(AbstractJcrProduct.class);
protected Resource resource;
protected Product baseProduct;
protected ProductAssetManager productAssetManager;
/**
* Constructor
* @param resource the Resource storing the product (or variant) info
*/
public AbstractJcrProduct(Resource resource) {
this.resource = resource;
this.productAssetManager = resource.getResourceResolver().adaptTo(ProductAssetManager.class);
}
@Override
public String getPath() {
return resource.getPath();
}
@Override
public String getPagePath() {
PageManager pm = resource.getResourceResolver().adaptTo(PageManager.class);
Page page = pm.getContainingPage(resource);
return (page != null) ? page.getPath() + ".html#" + getSKU() : null;
}
@Override
public String getTitle() {
return getProperty(PN_PRODUCT_TITLE, String.class);
}
@Override
public String getTitle(String selectorString) {
return getProperty(PN_PRODUCT_TITLE, selectorString, String.class);
}
@Override
public String getDescription() {
return getProperty(PN_PRODUCT_DESCRIPTION, String.class);
}
@Override
public String getDescription(String selectorString) {
return getProperty(PN_PRODUCT_DESCRIPTION, selectorString, String.class);
}
@Override
@Deprecated
public String getImagePath() {
final ImageResource image = getImage();
if (image != null) {
return image.getPath();
}
return "";
}
@Override
@Deprecated
public String getImageUrl() {
return getImagePath();
}
@Override
@Deprecated
public ImageResource getThumbnail() {
final ImageResource thumbnail = getImage();
if (thumbnail != null) {
thumbnail.setSelector(".thumbnail");
}
return thumbnail;
}
@Override
public String getThumbnailUrl() {
return getThumbnailUrl("");
}
@Override
public String getThumbnailUrl(int width) {
final String selector = Integer.toString(width);
return getThumbnailUrl(selector);
}
/**
* When the {@code selectorString} contains "image", it returns the thumbnail based on the product image by
* calling {@link #getImage()}, otherwise it returns the thumbnail based on the product asset by calling
* {@link #getAsset()}
*/
@Override
public String getThumbnailUrl(String selectorString) {
String selectors[] = (selectorString != null)? selectorString.split("\\.") : new String[] {""};
Resource assetRes = Arrays.asList(selectors).contains("image") ? getImage() : getAsset();
return assetRes == null ? null : productAssetManager.getThumbnailUrl(
assetRes.getPath(), selectorString);
}
@Override
public ImageResource getImage() {
Resource image = getAsset(IMG_MIME_TYPE);
if (image != null) {
return new ImageResource(image);
}
return null;
}
@Override
public Resource getAsset() {
return getAsset(null);
}
protected Resource getAsset(List mimeTypes) {
final List assets = getAssets(mimeTypes);
// the product has one asset: we return it
if (assets.size() == 1) {
return assets.get(0);
}
// the product has several images
if (assets.size() > 1) {
// get the asset category to be displayed
// 1. look up the product properties
String assetCategoryToDisplay = resource.getValueMap().get(PN_PRODUCT_ASSET_CATEGORY, String.class);
// 2. for a variant: look up the base product properties
if (StringUtils.isEmpty(assetCategoryToDisplay) && isAVariant(resource)) {
try {
baseProduct = this.getBaseProduct();
if (baseProduct != null) {
assetCategoryToDisplay = baseProduct.getProperty(PN_PRODUCT_ASSET_CATEGORY, String.class);
}
} catch (CommerceException e) {
log.error("Error while retrieving the base product.", e);
}
}
// 3. look up the asset category set by the blueprint for all the pages going up the hierarchy
if (StringUtils.isEmpty(assetCategoryToDisplay)) {
PageManager pm = resource.getResourceResolver().adaptTo(PageManager.class);
Page page = pm.getContainingPage(resource);
if (page != null) {
Resource pageContent = page.getContentResource();
InheritanceValueMap dataMap = new HierarchyNodeInheritanceValueMap(pageContent);
assetCategoryToDisplay = dataMap.getInherited(PN_PRODUCT_ASSET_CATEGORY, String.class);
}
}
// 4. look up in the product data
if (StringUtils.isEmpty(assetCategoryToDisplay)) {
assetCategoryToDisplay = getProperty(PN_PRODUCT_ASSET_CATEGORY, String.class);
}
// find the asset that has the same assetCategory
for (Resource asset : assets) {
String category = asset.getValueMap().get(PN_PRODUCT_ASSET_CATEGORY, String.class);
if (StringUtils.isNotEmpty(category) && category.equals(assetCategoryToDisplay)) {
return asset;
}
}
//return the asset that contains the fileReference property
for (Resource asset : assets) {
if (StringUtils.isNotEmpty(asset.getValueMap().get(PN_ASSET_FILE_REFERENCE, String.class))) {
return asset;
}
}
// 4. best effort: return the first asset of the set
return assets.get(0);
}
return null;
}
@Override
public List getImages() {
final List result = new ArrayList();
final List images = getAssets(IMG_MIME_TYPE);
if (images == null || images.isEmpty()) {
return result;
}
final Iterator imagesIterator = images.iterator();
while (imagesIterator.hasNext()) {
Resource assetRes = imagesIterator.next();
result.add(new ImageResource(assetRes));
}
return result;
}
@Override
public List getAssets() {
// See if there's an immediate value:
List assets = getAssets(resource);
if (assets.size() > 0) {
return assets;
}
// Else check pim reference or inheritance:
Resource ancestor;
final String productDataPath = resource.getValueMap().get(PN_PRODUCT_DATA, String.class);
if (StringUtils.isNotEmpty(productDataPath)) {
ancestor = resource.getResourceResolver().getResource(productDataPath);
if (ancestor == null) {
log.warn("Product data not found at [{}].", productDataPath);
return Collections.emptyList();
}
} else {
ancestor = resource.getParent();
}
while (ancestor != null && isAProductOrVariant(ancestor)) {
assets = getAssets(ancestor);
if (assets.size() > 0) {
return assets;
}
ancestor = ancestor.getParent();
}
return Collections.emptyList();
}
/**
* Returns the assets filtered by the mime type
* @param mimeTypes
* @return
*/
public List getAssets(List mimeTypes) {
final List assets = getAssets();
return filterResources(assets, mimeTypes);
}
// get all the assets below the product node
protected List getAssets(final Resource resource) {
final List result = new ArrayList();
// add the legacy image/ node to the assets
final Resource legacyImageResource = resource.getChild("image");
if (legacyImageResource != null) {
result.add(legacyImageResource);
}
// add the assets below assets/ to the assets
final Resource assetsResource = resource.getChild("assets");
if (assetsResource != null) {
final Iterator assets = assetsResource.listChildren();
while (assets.hasNext()) {
result.add(assets.next());
}
}
return result;
}
// Returns the assets filtered by the mime type
protected List getAssets(final Resource resource, List mimeTypes) {
final List assets = getAssets(resource);
return filterResources(assets, mimeTypes);
}
// Filters the assets based on the mime type of the original asset
private List filterResources(List assetResources, List mimeTypes) {
final List result = new ArrayList();
if (assetResources == null || assetResources.isEmpty()) {
return result;
}
if (mimeTypes == null || mimeTypes.isEmpty()) {
return assetResources;
}
final Iterator assetsIterator = assetResources.iterator();
while (assetsIterator.hasNext()) {
Resource assetRes = assetsIterator.next();
String assetReference = productAssetManager.getReferencedAsset(assetRes.getPath());
Asset asset = mapToAsset(assetReference);
if (asset != null && mimeTypes.contains(asset.getMimeType())) {
result.add(assetRes);
}
}
return result;
}
private Asset mapToAsset(String assetReference) {
if (StringUtils.isEmpty(assetReference)) {
return null;
}
try {
// decode fileReference (e.g. if it contains "%20" for whitespaces)
URLCodec urlCodec = new URLCodec();
// encode first to convert any GB18030 characters for safe decoding
assetReference = urlCodec.encode(assetReference);
assetReference = urlCodec.decode(assetReference);
} catch (EncoderException e) {
log.error("Error while encoding fileReference: {}", assetReference);
} catch (DecoderException e) {
log.error("Error while decoding fileReference: {}", assetReference);
}
Resource assetRes = resource.getResourceResolver().getResource(assetReference);
if (assetRes == null) {
return null;
}
return DamUtil.resolveToAsset(assetRes);
}
protected List getImages(final Resource resource) {
final List result = new ArrayList();
final List images = getAssets(resource, IMG_MIME_TYPE);
if (images == null || images.isEmpty()) {
return result;
}
final Iterator imagesIterator = images.iterator();
while (imagesIterator.hasNext()) {
Resource assetRes = imagesIterator.next();
result.add(new ImageResource(assetRes));
}
return result;
}
@Override
public T getProperty(String name, Class type) {
// See if there's an immediate value:
ValueMap properties = resource.getValueMap();
if (properties.containsKey(name)) {
return properties.get(name, type);
}
// Else check pim reference or local inheritance:
Resource ancestor;
if (properties.containsKey(PN_PRODUCT_DATA)) {
String productDataPath = properties.get(PN_PRODUCT_DATA, String.class);
ancestor = resource.getResourceResolver().getResource(productDataPath);
if (ancestor == null) {
log.warn("Product data not found at [{}].", productDataPath);
return null;
}
} else {
ancestor = resource.getParent();
}
return (new ComponentInheritanceValueMap(ancestor)).getInherited(name, type);
}
@Override
public T getProperty(String name, String selectorString, Class type) {
if (StringUtils.isNotEmpty(selectorString)) {
T selectorSpecificValue = getProperty(name + "." + selectorString, type);
if (selectorSpecificValue != null) {
return selectorSpecificValue;
}
}
return getProperty(name, type);
}
@Override
public Iterator getVariants() throws CommerceException {
return getVariants(null);
}
@Override
public boolean axisIsVariant(String axis) {
Iterator axes = getVariantAxes();
while (axes.hasNext()) {
if (axes.next().equals(axis)) {
return true;
}
}
return false;
}
@Override
public Iterator getVariants(VariantFilter filter) throws CommerceException {
List variants = new ArrayList();
collectVariants(getBaseProduct(), filter, variants);
return variants.iterator();
}
@Override
public Iterator getVariantAxes() {
String[] axes = getProperty(PN_PRODUCT_VARIANT_AXES, String[].class);
if (axes != null) {
return Arrays.asList(axes).iterator();
} else {
return new ArrayList().iterator();
}
}
@Override
public Product getBaseProduct() throws CommerceException {
if (baseProduct == null) {
if (!isAProductOrVariant(resource)) {
log.error("Node isn't a product: " + resource.getPath());
return null;
}
Resource tempResource = resource;
while (isAVariant(tempResource)) {
tempResource = tempResource.getParent();
}
if (isABaseProduct(tempResource)) {
CommerceService service = tempResource.adaptTo(CommerceService.class);
baseProduct = service.getProduct(tempResource.getPath());
} else {
log.error("Variant product node [{}] didn't have a product parent.", resource.getPath());
return null;
}
}
return baseProduct;
}
@Override
public Product getPIMProduct() throws CommerceException {
String productDataPath = resource.getValueMap().get(PN_PRODUCT_DATA, String.class);
if (StringUtils.isNotEmpty(productDataPath)) {
Resource productData = resource.getResourceResolver().getResource(productDataPath);
if (productData == null) {
log.warn("Product data not found at [{}].", productDataPath);
return null;
} else {
return productData.adaptTo(Product.class);
}
}
return null;
}
/**
* Returns true if resource's cq:commerceType is "variant".
* @param resource
* @return
*/
public static boolean isAVariant(Resource resource) {
return resource.getValueMap().get(PN_PRODUCT_TYPE, "").equals("variant");
}
/**
* Returns true if resource's cq:commerceType is "product".
* @param resource
* @return
*/
public static boolean isABaseProduct(Resource resource) {
return resource.getValueMap().get(PN_PRODUCT_TYPE, "").equals("product");
}
/**
* Returns true if resource's cq:commerceType is "product" or "variant".
* @param resource
* @return
*/
public static boolean isAProductOrVariant(Resource resource) {
String commerceType = resource.getValueMap().get(PN_PRODUCT_TYPE, "");
return commerceType.equals("product") || commerceType.equals("variant");
}
//
// Recursive descent of the resource tree, checking any leaf nodes against the
// filter for inclusion.
//
protected void collectVariants(Product p, VariantFilter filter, List variants) {
boolean isLeaf = true;
Iterator i = resource.getResourceResolver().listChildren(p.adaptTo(Resource.class));
while (i != null && i.hasNext()) {
Resource child = i.next();
if (isAVariant(child)) {
isLeaf = false;
collectVariants(child.adaptTo(Product.class), filter, variants);
}
}
if (isLeaf) {
if (filter == null || filter.includes(p)) {
variants.add(p);
}
}
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
public AdapterType adaptTo(Class type) {
if (type == Resource.class) {
return (AdapterType)resource;
} else if(type == InheritanceValueMap.class) {
return (AdapterType) new ComponentInheritanceValueMap(resource);
}
AdapterType ret = super.adaptTo(type);
if (ret == null) {
ret = resource.adaptTo(type);
}
return ret;
}
//-------------< Object overrides >-------------------------------------------------------
// enable comparing 2 products based on their paths
@Override
public boolean equals(final Object obj) {
return obj instanceof Product && ((Product) obj).getPath().equals(getPath());
}
@Override
public int hashCode() {
return getPath().hashCode();
}
}