创建加速器代码库
在cmd命令提示符窗口,切换到YOURPATH\bin\platform,使用以下命令从platform的build.xml中运行modulegen
ant modulegen
选择默认模板accelerator,输入模块扩展名(例如:merchandise)和包名(例如:de.hybris.merchandise)
modulegen:
[input]
[input] Please choose a template for generation.
[input] Press [Enter] to use the default value ([accelerator], b2baccelerator, telcoaccelerator, commercewebservices)
[input]
[input] Please choose the name of your module extension. It has to start with a letter followed by letters and/or numbers.
[input] Press [Enter] to use the default value [training]
merchandise
[input]
[input] Please choose the base package name of your extensions. It has to fulfill java package name convention. Each extension in the module will add its name to this package.
[input] Press [Enter] to use the default value [org.training]
de.hybris.merchandise
上述操作,将在YOURPATH\bin下自动生成如下7个自定义扩展
/custom/merchandise/merchandisecockpits
/custom/merchandise/merchandisecore
/custom/merchandise/merchandisefacades
/custom/merchandise/merchandisefulfilmentprocess
/custom/merchandise/merchandiseinitialdata
/custom/merchandise/merchandisestorefront
/custom/merchandise/merchandisetest
按照modulegen output说明,完成localextensions.xml配置
[echo]
[echo] Next steps:
[echo]
[echo] 1) Add your extension to your E:\test\hybris\config/localextensions.xml
[echo]
[echo] <extension dir="E:\test\hybris\bin/custom/merchandise/merchandisefulfilmentprocess"/>
[echo] <extension dir="E:\test\hybris\bin/custom/merchandise/merchandisecore"/>
[echo] <extension dir="E:\test\hybris\bin/custom/merchandise/merchandiseinitialdata"/>
[echo] <extension dir="E:\test\hybris\bin/custom/merchandise/merchandisefacades"/>
[echo] <extension dir="E:\test\hybris\bin/custom/merchandise/merchandisetest"/>
[echo] <extension dir="E:\test\hybris\bin/custom/merchandise/merchandisestorefront"/>
[echo] <extension dir="E:\test\hybris\bin/custom/merchandise/merchandisecockpits"/>
[echo] 2) Remove the following extensions from your E:\test\hybris\config/localextensions.xml
[echo] yacceleratorfulfilmentprocess,yacceleratorcore,yacceleratorinitialdata,yacceleratorfacades,yacceleratortest,yacceleratorstorefront,yacceleratorcockpits
[echo] 3) Make sure the applicationserver is stopped before you build the extension the first time.
[echo]
[echo] 4) Perform 'ant' in your hybris/platform directory.
[echo] 5) Restart the applicationserver
[echo]
[echo]
注意:不要添加merchandisetest扩展到localextensions.xml,因为它包含大量的数据for example storefront(例如:electronics and appare)会加长系统初始化所需时间,另外localextensions.xml中所有的yb2b扩展也要移除
注意:在hybris-commerce-suite-5.5.1.2.zip中,经测试,在上述modulegen output第4步操作之前,需修改merchandisecore扩展,添加下面的几段代码,否则第5步服务器启动会出现错误
以下文件相对位置为YOURPATH/bin/custom/merchandise/merchandisecore/src/
de/hybris/merchandise/core/solr/provider/ProductVolumePricesProvider.java
/*
* [y] hybris Platform
*
* Copyright (c) 2000-2015 hybris AG
* All rights reserved.
*
* This software is the confidential and proprietary information of hybris
* ("Confidential Information"). You shall not disclose such Confidential
* Information and shall use it only in accordance with the terms of the
* license agreement you entered into with hybris.
*
*
*/
package de.hybris.merchandise.core.solr.provider;
import de.hybris.platform.core.model.c2l.CurrencyModel;
import de.hybris.platform.core.model.product.ProductModel;
import de.hybris.platform.europe1.jalo.PriceRow;
import de.hybris.platform.jalo.order.price.PriceInformation;
import de.hybris.platform.product.PriceService;
import de.hybris.platform.solrfacetsearch.config.IndexConfig;
import de.hybris.platform.solrfacetsearch.config.IndexedProperty;
import de.hybris.platform.solrfacetsearch.config.exceptions.FieldValueProviderException;
import de.hybris.platform.solrfacetsearch.provider.FieldNameProvider;
import de.hybris.platform.solrfacetsearch.provider.FieldValue;
import de.hybris.platform.solrfacetsearch.provider.FieldValueProvider;
import de.hybris.platform.solrfacetsearch.provider.impl.AbstractPropertyFieldValueProvider;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.annotation.Required;
/**
* Provides value for volumePrices flag. "true" if product has volume prices, "false" otherwise.
*/
public class ProductVolumePricesProvider extends AbstractPropertyFieldValueProvider implements FieldValueProvider
{
private FieldNameProvider fieldNameProvider;
private PriceService priceService;
@Override
public Collection<FieldValue> getFieldValues(final IndexConfig indexConfig, final IndexedProperty indexedProperty,
final Object model) throws FieldValueProviderException
{
final ProductModel product = (ProductModel) model;//this provider shall only be used with products
final Collection<FieldValue> fieldValues = new ArrayList<FieldValue>();
final CurrencyModel sessionCurrency = i18nService.getCurrentCurrency();
try
{
for (final CurrencyModel currency : indexConfig.getCurrencies())
{
i18nService.setCurrentCurrency(currency);
final List<PriceInformation> prices = getPriceService().getPriceInformationsForProduct(product);
if (prices != null && !prices.isEmpty())
{
final Collection<String> fieldNames = getFieldNameProvider().getFieldNames(indexedProperty,
currency.getIsocode().toLowerCase());
final Boolean hasVolumePrices = hasVolumePrices(product);
for (final String fieldName : fieldNames)
{
fieldValues.add(new FieldValue(fieldName, hasVolumePrices));
}
}
}
}
finally
{
i18nService.setCurrentCurrency(sessionCurrency);
}
return fieldValues;
}
protected Boolean hasVolumePrices(final ProductModel product)
{
final Set<Long> volumes = new HashSet<Long>();
final List<PriceInformation> priceInfos = getPriceService().getPriceInformationsForProduct(product);
for (final PriceInformation priceInfo : priceInfos)
{
if (priceInfo.getQualifiers().containsKey(PriceRow.MINQTD))
{
final Long volume = (Long) priceInfo.getQualifiers().get(PriceRow.MINQTD);
volumes.add(volume);
}
}
if (volumes.size() > 1)//one volume price (probably with minqt=1) is not taken into account
{
return Boolean.TRUE;
}
else
{
return Boolean.FALSE;
}
}
protected PriceService getPriceService()
{
return priceService;
}
@Required
public void setPriceService(final PriceService priceService)
{
this.priceService = priceService;
}
protected FieldNameProvider getFieldNameProvider()
{
return fieldNameProvider;
}
@Required
public void setFieldNameProvider(final FieldNameProvider fieldNameProvider)
{
this.fieldNameProvider = fieldNameProvider;
}
}
de/hybris/merchandise/core/solr/provider/VolumeAwareProductPriceValueProvider
/*
* [y] hybris Platform
*
* Copyright (c) 2000-2015 hybris AG
* All rights reserved.
*
* This software is the confidential and proprietary information of hybris
* ("Confidential Information"). You shall not disclose such Confidential
* Information and shall use it only in accordance with the terms of the
* license agreement you entered into with hybris.
*
*
*/
package de.hybris.merchandise.core.solr.provider;
import de.hybris.platform.catalog.CatalogVersionService;
import de.hybris.platform.catalog.model.CatalogVersionModel;
import de.hybris.platform.catalog.model.classification.ClassificationSystemVersionModel;
import de.hybris.platform.cms2.model.contents.ContentCatalogModel;
import de.hybris.platform.core.model.c2l.CurrencyModel;
import de.hybris.platform.core.model.product.ProductModel;
import de.hybris.platform.jalo.order.price.PriceInformation;
import de.hybris.platform.product.PriceService;
import de.hybris.platform.servicelayer.i18n.CommonI18NService;
import de.hybris.platform.servicelayer.session.SessionExecutionBody;
import de.hybris.platform.servicelayer.session.SessionService;
import de.hybris.platform.servicelayer.user.UserService;
import de.hybris.platform.solrfacetsearch.config.IndexConfig;
import de.hybris.platform.solrfacetsearch.config.IndexedProperty;
import de.hybris.platform.solrfacetsearch.config.exceptions.FieldValueProviderException;
import de.hybris.platform.solrfacetsearch.provider.FieldNameProvider;
import de.hybris.platform.solrfacetsearch.provider.FieldValue;
import de.hybris.platform.solrfacetsearch.provider.FieldValueProvider;
import de.hybris.platform.solrfacetsearch.provider.impl.AbstractPropertyFieldValueProvider;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Required;
/**
* {@link FieldValueProvider} for prices. Supports multi-currencies.<br>
* The list of prices is loaded for the anonymous user and current catalog version. <br>
*/
public class VolumeAwareProductPriceValueProvider extends AbstractPropertyFieldValueProvider implements FieldValueProvider,
Serializable
{
protected static final Logger LOG = Logger.getLogger(FieldValueProvider.class.getName());
private FieldNameProvider fieldNameProvider;
private PriceService priceService;
private UserService userService;
private SessionService sessionService;
private CommonI18NService commonI18NService;
private Comparator<PriceInformation> priceComparator;
private CatalogVersionService catalogVersionService;
@Override
public Collection<FieldValue> getFieldValues(final IndexConfig indexConfig, final IndexedProperty indexedProperty,
final Object model) throws FieldValueProviderException
{
final Collection<FieldValue> fieldValues = new ArrayList<FieldValue>();
try
{
List<String> rangeNameList;
if (!(model instanceof ProductModel))
{
throw new FieldValueProviderException("Cannot evaluate price of non-product item");
}
final Collection<CatalogVersionModel> filteredCatalogVersions = filterCatalogVersions(getCatalogVersionService()
.getSessionCatalogVersions());
if (indexConfig.getCurrencies().isEmpty())
{
final List<PriceInformation> prices = new ArrayList<PriceInformation>();
sessionService.executeInLocalView(new SessionExecutionBody()
{
@Override
public void executeWithoutResult()
{
getCatalogVersionService().setSessionCatalogVersions(filteredCatalogVersions);
prices.addAll(priceService.getPriceInformationsForProduct((ProductModel) model));
}
}, userService.getAnonymousUser());
if (!prices.isEmpty())
{
Collections.sort(prices, priceComparator);
final PriceInformation price = prices.get(0);
final Double value = Double.valueOf(price.getPriceValue().getValue());
rangeNameList = getRangeNameList(indexedProperty, value);
final Collection<String> fieldNames = fieldNameProvider.getFieldNames(indexedProperty, price.getPriceValue()
.getCurrencyIso());
for (final String fieldName : fieldNames)
{
if (rangeNameList.isEmpty())
{
fieldValues.add(new FieldValue(fieldName, value));
}
else
{
for (final String rangeName : rangeNameList)
{
fieldValues.add(new FieldValue(fieldName, rangeName == null ? value : rangeName));
}
}
}
}
}
else
{
for (final CurrencyModel currency : indexConfig.getCurrencies())
{
final List<PriceInformation> prices = new ArrayList<PriceInformation>();
sessionService.executeInLocalView(new SessionExecutionBody()
{
@Override
public void executeWithoutResult()
{
getCatalogVersionService().setSessionCatalogVersions(filteredCatalogVersions);
commonI18NService.setCurrentCurrency(currency);
prices.addAll(priceService.getPriceInformationsForProduct((ProductModel) model));
}
}, userService.getAnonymousUser());
if (!prices.isEmpty())
{
Collections.sort(prices, priceComparator);
final Double value = Double.valueOf(prices.get(0).getPriceValue().getValue());
rangeNameList = getRangeNameList(indexedProperty, value, currency.getIsocode());
final Collection<String> fieldNames = fieldNameProvider.getFieldNames(indexedProperty, currency.getIsocode()
.toLowerCase());
for (final String fieldName : fieldNames)
{
if (rangeNameList.isEmpty())
{
fieldValues.add(new FieldValue(fieldName, value));
}
else
{
for (final String rangeName : rangeNameList)
{
fieldValues.add(new FieldValue(fieldName, rangeName == null ? value : rangeName));
}
}
}
}
}
}
}
catch (final Exception e)
{
LOG.error("Failed to generate volume price", e);
throw new FieldValueProviderException("Cannot evaluate " + indexedProperty.getName() + " using "
+ this.getClass().getName(), e);
}
return fieldValues;
}
protected Collection<CatalogVersionModel> filterCatalogVersions(final Collection<CatalogVersionModel> sessionCatalogVersions)
{
final List<CatalogVersionModel> result = new ArrayList<CatalogVersionModel>(sessionCatalogVersions.size());
for (final CatalogVersionModel catalogVersion : sessionCatalogVersions)
{
if (!(catalogVersion instanceof ClassificationSystemVersionModel)
&& !(catalogVersion.getCatalog() instanceof ContentCatalogModel))
{
result.add(catalogVersion);
}
}
return result;
}
protected FieldNameProvider getFieldNameProvider()
{
return fieldNameProvider;
}
@Required
public void setFieldNameProvider(final FieldNameProvider fieldNameProvider)
{
this.fieldNameProvider = fieldNameProvider;
}
protected PriceService getPriceService()
{
return priceService;
}
@Required
public void setPriceService(final PriceService priceService)
{
this.priceService = priceService;
}
protected UserService getUserService()
{
return userService;
}
@Required
public void setUserService(final UserService userService)
{
this.userService = userService;
}
protected SessionService getSessionService()
{
return sessionService;
}
@Required
public void setSessionService(final SessionService sessionService)
{
this.sessionService = sessionService;
}
protected CommonI18NService getCommonI18NService()
{
return commonI18NService;
}
@Required
public void setCommonI18NService(final CommonI18NService commonI18NService)
{
this.commonI18NService = commonI18NService;
}
protected Comparator<PriceInformation> getPriceComparator()
{
return priceComparator;
}
@Required
public void setPriceComparator(final Comparator<PriceInformation> priceComparator)
{
this.priceComparator = priceComparator;
}
protected CatalogVersionService getCatalogVersionService()
{
return catalogVersionService;
}
@Required
public void setCatalogVersionService(final CatalogVersionService catalogVersionService)
{
this.catalogVersionService = catalogVersionService;
}
}
de/hybris/merchandise/core/comparator/VolumeAwarePriceInformationComparator
/*
* [y] hybris Platform
*
* Copyright (c) 2000-2015 hybris AG
* All rights reserved.
*
* This software is the confidential and proprietary information of hybris
* ("Confidential Information"). You shall not disclose such Confidential
* Information and shall use it only in accordance with the terms of the
* license agreement you entered into with hybris.
*
*
*/
package de.hybris.merchandise.core.comparator;
import de.hybris.platform.europe1.jalo.PriceRow;
import de.hybris.platform.jalo.order.price.PriceInformation;
import de.hybris.platform.util.PriceValue;
import java.util.Comparator;
/**
* Compares two prices.<br>
* The prices are compared by minqty and the lowest minqty (or null) is treated as lower. <br>
* If there are multiple prices then the lowest price is treated as lower. <br>
* If there are still multiple records then the first is treated as lower.
*/
public class VolumeAwarePriceInformationComparator implements Comparator<PriceInformation>
{
@Override
public int compare(final PriceInformation priceInfo1, final PriceInformation priceInfo2)
{
final Long o1Quantity = (Long) priceInfo1.getQualifierValue(PriceRow.MINQTD);
final Long o2Quantity = (Long) priceInfo2.getQualifierValue(PriceRow.MINQTD);
if (o1Quantity == null && o2Quantity == null)
{
return 0;
}
if (o1Quantity == null)
{
return -1;
}
if (o2Quantity == null)
{
return 1;
}
if (o1Quantity.longValue() == o2Quantity.longValue())
{
final PriceValue pv1 = priceInfo1.getPriceValue();
final PriceValue pv2 = priceInfo2.getPriceValue();
return Double.compare(pv1.getValue(), pv2.getValue());
}
return o1Quantity.compareTo(o2Quantity);
}
}
以下文件相对位置为YOURPATH/bin/custom/merchandise/merchandisecore/resources/
merchandisecore-spring.xml
<bean id="powertoolsCategorySource" parent="abstractCategorySource">
<property name="rootCategory" value="1"/>
<!-- '1' is the root icecat category -->
</bean>
<bean id="powertoolsBrandCategorySource" parent="abstractCategorySource">
<property name="rootCategory" value="brands"/>
<!-- 'brands' is the root of the brands hierarchy -->
</bean>
<bean id="powertoolsVariantCategorySource" parent="variantCategorySource"/>
<bean id="powertoolsCategoryCodeValueProvider" parent="abstractCategoryCodeValueProvider">
<property name="categorySource" ref="powertoolsCategorySource"/>
</bean>
<bean id="powertoolsBrandCategoryCodeValueProvider" parent="abstractCategoryCodeValueProvider">
<property name="categorySource" ref="powertoolsBrandCategorySource"/>
</bean>
<bean id="powertoolsCategoryNameValueProvider" parent="abstractCategoryNameValueProvider">
<property name="categorySource" ref="powertoolsCategorySource"/>
</bean>
<bean id="powertoolsBrandCategoryNameValueProvider" parent="abstractCategoryNameValueProvider">
<property name="categorySource" ref="powertoolsBrandCategorySource"/>
</bean>
<bean id="powertoolsVariantCategoryCodeValueProvider" parent="abstractCategoryCodeValueProvider">
<property name="categorySource" ref="powertoolsVariantCategorySource"/>
</bean>
<bean id="productVolumePricesProvider"
class="de.hybris.merchandise.core.solr.provider.ProductVolumePricesProvider"
parent="abstractPropertyFieldValueProvider">
<property name="fieldNameProvider" ref="solrFieldNameProvider"/>
<property name="priceService" ref="priceService"/>
</bean>
<bean id="volumePriceComparator" class="de.hybris.merchandise.core.comparator.VolumeAwarePriceInformationComparator" scope="singleton"/>
<bean id="volumeAwareProductPriceValueProvider"
class="de.hybris.merchandise.core.solr.provider.VolumeAwareProductPriceValueProvider"
parent="abstractPropertyFieldValueProvider">
<property name="fieldNameProvider" ref="solrFieldNameProvider"/>
<property name="priceService" ref="priceService"/>
<property name="commonI18NService" ref="commonI18NService"/>
<property name="sessionService" ref="sessionService"/>
<property name="userService" ref="userService"/>
<property name="priceComparator" ref="volumePriceComparator"/>
<property name="catalogVersionService" ref="catalogVersionService"/>
</bean>