de.hybris.platform.order.interceptors.DefaultAbstractOrderEntryPreparer.java Source code

Java tutorial

Introduction

Here is the source code for de.hybris.platform.order.interceptors.DefaultAbstractOrderEntryPreparer.java

Source

/*
 * [y] hybris Platform
 *
 * Copyright (c) 2000-2013 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.platform.order.interceptors;

import de.hybris.platform.core.model.ItemModel;
import de.hybris.platform.core.model.order.AbstractOrderEntryModel;
import de.hybris.platform.core.model.order.AbstractOrderModel;
import de.hybris.platform.core.model.product.ProductModel;
import de.hybris.platform.core.model.type.ComposedTypeModel;
import de.hybris.platform.servicelayer.config.ConfigurationService;
import de.hybris.platform.servicelayer.exceptions.AttributeNotSupportedException;
import de.hybris.platform.servicelayer.interceptor.InterceptorContext;
import de.hybris.platform.servicelayer.interceptor.InterceptorException;
import de.hybris.platform.servicelayer.interceptor.PrepareInterceptor;
import de.hybris.platform.servicelayer.type.TypeService;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Collections;

import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Required;

public class DefaultAbstractOrderEntryPreparer extends AbstractAttributesModificationAwareInterceptor
        implements PrepareInterceptor {

    private static final Logger LOG = Logger.getLogger(DefaultAbstractOrderEntryPreparer.class);
    private static final String NOT_AVAILABLE = "n/a";
    protected static final int APPEND_AS_LAST = -1;
    private TypeService typeService;
    private ConfigurationService configurationService;

    private Collection<String> attributesForOrderRecalculation;

    @Override
    public void onPrepare(final Object model, final InterceptorContext ctx) throws InterceptorException {
        if (model instanceof AbstractOrderEntryModel && !ctx.isRemoved(model)) {
            final AbstractOrderEntryModel entryModel = (AbstractOrderEntryModel) model;

            //change calculated flag if any of the subjected attributed has changed, but not if calculated flag is dirty.
            if (isOneOfAttributesModified(entryModel, getAttributesForOrderRecalculation(), ctx)
                    && !ctx.isModified(entryModel, AbstractOrderEntryModel.CALCULATED)) {
                entryModel.setCalculated(Boolean.FALSE);
                final AbstractOrderModel ownerOrder = entryModel.getOrder();
                if (ownerOrder != null && Boolean.TRUE.equals(ownerOrder.getCalculated())) {
                    ownerOrder.setCalculated(Boolean.FALSE);
                    ctx.registerElement(ownerOrder, getModelSource(ctx, ownerOrder));
                }
            }
            if (isAttributeModified(entryModel, AbstractOrderEntryModel.PRODUCT, ctx)) {
                //automatically generate info
                entryModel.setInfo(createEntryInformation(entryModel, ctx));
            }

            if (ctx.isNew(entryModel)) {
                if (entryModel.getTaxValues() == null) {
                    entryModel.setTaxValues(Collections.EMPTY_LIST);
                }
                if (entryModel.getDiscountValues() == null) {
                    entryModel.setDiscountValues(Collections.EMPTY_LIST);
                }

            }

            if (isAttributeModified(entryModel, AbstractOrderEntryModel.ENTRYNUMBER, ctx)) {
                final Integer entryNumber = entryModel.getEntryNumber();
                final AbstractOrderModel order = entryModel.getOrder();
                final List<AbstractOrderEntryModel> currentOrderEntries = order.getEntries();
                if (entryNumber == null || APPEND_AS_LAST >= entryNumber.intValue()) {
                    setEntryNumberAslast(entryModel, currentOrderEntries);
                }
                final List<AbstractOrderEntryModel> newEntries = currentOrderEntries == null
                        ? new ArrayList<AbstractOrderEntryModel>()
                        : new ArrayList<AbstractOrderEntryModel>(currentOrderEntries);
                if (!newEntries.contains(entryModel)) {
                    newEntries.add(entryModel);
                    order.setEntries(newEntries);
                }
            }
        }
    }

    private void setEntryNumberAslast(final AbstractOrderEntryModel entryModel,
            final List<AbstractOrderEntryModel> currentOrderEntries) {
        int targetEntryNumber = 0;
        if (CollectionUtils.isNotEmpty(currentOrderEntries)) {
            //normally it's enough just to take the entryNumber from last orderEntry in the list.
            //Unfortunatelly - the context may contain some entries with entryNumber not set yet (e.g. not processed by the
            // interceptors yet). Therefore, we must find the last entry with already defined entryNumber
            for (int i = 0; i < currentOrderEntries.size(); i++) {
                final Integer potentialMaxEntryNumber = currentOrderEntries.get(i).getEntryNumber();
                if (!(potentialMaxEntryNumber == null || APPEND_AS_LAST >= potentialMaxEntryNumber.intValue())) {
                    if (potentialMaxEntryNumber.intValue() >= targetEntryNumber) {
                        targetEntryNumber = potentialMaxEntryNumber.intValue() + 1;
                    }
                }
            }
        }
        entryModel.setEntryNumber(Integer.valueOf(targetEntryNumber));
    }

    protected String createEntryInformation(final AbstractOrderEntryModel newEntry, final InterceptorContext ctx)
            throws InterceptorException {

        final ProductModel product = newEntry.getProduct();
        // find pattern in local.properties (or project.properties)
        if (product == null) {
            return NOT_AVAILABLE;
        } else {
            ComposedTypeModel type = typeService.getComposedTypeForClass(product.getClass());
            String infoField = configurationService.getConfiguration()
                    .getString("orderentry.infofield." + type.getCode().toLowerCase(), null);
            boolean hasInfoFieldAValue = true;

            while (infoField == null) //if pattern for current type is not found, search for pattern of supertype
            {
                if (type.getSuperType() == null) {
                    hasInfoFieldAValue = false;
                    break;
                } else {
                    type = type.getSuperType();
                    infoField = configurationService.getConfiguration()
                            .getString("orderentry.infofield." + type.getCode().toLowerCase(), null);
                }
            }

            final String defaultstring = product.getCode(); //default string for info field, is only the product code
            final StringBuilder returnString = new StringBuilder(defaultstring);
            if (hasInfoFieldAValue) // got a pattern?
            {
                returnString.setLength(0); //throw defaultstring away
                int openTag = infoField.indexOf("${");
                int closeTag = infoField.indexOf('}');
                int start = 0;

                ItemModel item = product;

                while (openTag != -1 && closeTag != -1) // for each attribut founded in ${ }
                {
                    returnString.append(infoField.substring(start, openTag));
                    String code = infoField.substring((openTag + 2), closeTag);

                    int attr_start = 0;
                    int attr_dot = code.indexOf('.');
                    while (attr_dot != -1) // is ther a 'path'?
                    {
                        //browse throught all instances till last dot
                        try {
                            item = goToConcreteItem(item, code.substring(attr_start, attr_dot), ctx);
                        } catch (final AttributeNotSupportedException e) {
                            throw new InterceptorException(
                                    "pattern '" + infoField + "' contains a missing attribute '" + code);
                        }
                        attr_start = attr_dot + 1;
                        attr_dot = code.indexOf('.', attr_start);
                    }

                    if (attr_start > 0 && attr_dot == -1) {
                        code = code.substring(attr_start, code.length()); // all after the last dot is the attribute which should be
                        // in the info field
                    }

                    try {
                        final Object value = ctx.getModelService().getAttributeValue(item, code);
                        returnString.append(value != null ? value.toString() : "n/a"); // could be null, so a readible 'n/a'
                    } catch (final AttributeNotSupportedException e) {
                        final String itemTypeCode = ctx.getModelService().getModelType(item);
                        throw new InterceptorException(
                                "pattern '" + infoField + "' contains a missing attribute '" + code //NOPMD
                                        + "' for type " + itemTypeCode,
                                e);
                    }

                    start = closeTag + 1;
                    openTag = infoField.indexOf("${", start);
                    closeTag = infoField.indexOf('}', start);
                }
                if (start < infoField.length()) {
                    returnString.append(infoField.substring(start));
                }
            }
            return returnString.toString();
        }

    }

    private ItemModel goToConcreteItem(final ItemModel item, final String substring, final InterceptorContext ctx)
            throws InterceptorException {

        final Object value = ctx.getModelService().getAttributeValue(item, substring);
        if (value instanceof ItemModel) {
            return (ItemModel) value;
        } else {
            throw new InterceptorException("Unknown type " + substring);
        }

    }

    @Required
    public void setTypeService(final TypeService typeService) {
        this.typeService = typeService;
    }

    @Required
    public void setConfigurationService(final ConfigurationService configurationService) {
        this.configurationService = configurationService;
    }

    public void setAttributesForOrderRecalculation(final Collection<String> attributesForOrderRecalculation) {
        this.attributesForOrderRecalculation = attributesForOrderRecalculation;
    }

    private Collection<String> getAttributesForOrderRecalculation() {
        if (attributesForOrderRecalculation != null) {
            return attributesForOrderRecalculation;
        } else {
            //fallback list of attributes (the same set results from jalo layer logic)
            return Arrays.asList(AbstractOrderEntryModel.PRODUCT, AbstractOrderEntryModel.QUANTITY,
                    AbstractOrderEntryModel.UNIT, AbstractOrderEntryModel.BASEPRICE,
                    AbstractOrderEntryModel.TAXVALUES, AbstractOrderEntryModel.DISCOUNTVALUES,
                    AbstractOrderEntryModel.GIVEAWAY, AbstractOrderEntryModel.REJECTED);
        }

    }

    @Override
    public Logger getLogger() {
        return LOG;
    }

    private Object getModelSource(final InterceptorContext ctx, final ItemModel model) {
        if (ctx.isNew(model)) {
            return null;
        } else {
            return ctx.getModelService().getSource(model);
        }
    }

}