de.hybris.platform.classification.impl.DefaultClassificationClassesResolverStrategy.java Source code

Java tutorial

Introduction

Here is the source code for de.hybris.platform.classification.impl.DefaultClassificationClassesResolverStrategy.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.classification.impl;

import static de.hybris.platform.servicelayer.util.ServicesUtil.validateParameterNotNull;

import de.hybris.platform.catalog.CatalogVersionService;
import de.hybris.platform.catalog.model.classification.ClassAttributeAssignmentModel;
import de.hybris.platform.catalog.model.classification.ClassificationClassModel;
import de.hybris.platform.catalog.model.classification.ClassificationSystemVersionModel;
import de.hybris.platform.category.model.CategoryModel;
import de.hybris.platform.classification.ClassificationClassesResolverStrategy;
import de.hybris.platform.core.model.ItemModel;
import de.hybris.platform.core.model.product.ProductModel;
import de.hybris.platform.util.Config;
import de.hybris.platform.variants.model.VariantProductModel;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

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

/**
 * Implementation of of the {@link ClassificationClassesResolverStrategy}.
 */
public class DefaultClassificationClassesResolverStrategy implements ClassificationClassesResolverStrategy {
    private CatalogVersionService catalogVersionService;

    private final SuperCategoriesResolver<ProductModel> productSuperCatResolver = new SuperCategoriesResolver<ProductModel>() {
        @Override
        public Set<CategoryModel> getSuperCategories(final ProductModel item) {
            if (item == null) {
                return Collections.EMPTY_SET;
            }
            // avoid recursive creation *many* sets -> create one and pass it on
            return addSuperCategories(item, new LinkedHashSet<CategoryModel>());
        }

        Set<CategoryModel> addSuperCategories(final ProductModel item, final Set<CategoryModel> toAddTo) {
            if (item != null) {
                final Collection<CategoryModel> superCategories = item.getSupercategories();
                if (CollectionUtils.isNotEmpty(superCategories)) {
                    toAddTo.addAll(superCategories);
                }
                if (item instanceof VariantProductModel) {
                    // recursively get categories for the base product ( PLA-13578: may be a variant as well )
                    addSuperCategories(((VariantProductModel) item).getBaseProduct(), toAddTo);
                }
            }
            return toAddTo;
        }
    };

    private final SuperCategoriesResolver<CategoryModel> catSuperCatResolver = new SuperCategoriesResolver<CategoryModel>() {

        @Override
        public Set<CategoryModel> getSuperCategories(final CategoryModel item) {
            if (item == null) {
                return Collections.EMPTY_SET;
            } else {
                final Collection<CategoryModel> superCategories = item.getSupercategories();
                if (superCategories == null) {
                    return Collections.EMPTY_SET;
                } else {
                    return new LinkedHashSet<CategoryModel>(superCategories);
                }
            }
        }
    };

    @Override
    public Set<ClassificationClassModel> resolve(final ProductModel item) {
        return resolve(item, productSuperCatResolver);
    }

    private Set<ClassificationClassModel> resolve(final ProductModel item,
            final SuperCategoriesResolver<ProductModel> scr) {
        return resolveClasses(item, scr, getAllClassificationSystemVersions());
    }

    private Collection<ClassificationSystemVersionModel> getAllClassificationSystemVersions() {
        return catalogVersionService.getAllCatalogVersionsOfType(ClassificationSystemVersionModel.class);
    }

    @Override
    public Set<ClassificationClassModel> resolve(final CategoryModel item) {
        return resolve(item, catSuperCatResolver);
    }

    private Set<ClassificationClassModel> resolve(final CategoryModel item,
            final SuperCategoriesResolver<CategoryModel> scr) {
        return resolveClasses(item, scr, getAllClassificationSystemVersions());
    }

    @Override
    public Set<ClassificationClassModel> resolve(final ProductModel item,
            final ClassificationSystemVersionModel systemVersion) {
        return resolve(item, productSuperCatResolver, systemVersion);
    }

    public Set<ClassificationClassModel> resolve(final ProductModel item,
            final SuperCategoriesResolver<ProductModel> scr, final ClassificationSystemVersionModel systemVersion) {
        return resolveClasses(item, scr, Collections.singleton(systemVersion));
    }

    @Override
    public Set<ClassificationClassModel> resolve(final CategoryModel item,
            final ClassificationSystemVersionModel systemVersion) {
        return resolve(item, catSuperCatResolver, systemVersion);
    }

    private Set<ClassificationClassModel> resolve(final CategoryModel item,
            final SuperCategoriesResolver<CategoryModel> scr,
            final ClassificationSystemVersionModel systemVersion) {
        return resolveClasses(item, scr, Collections.singleton(systemVersion));
    }

    @Override
    public Set<ClassificationClassModel> resolve(final ProductModel item,
            final Collection<ClassificationSystemVersionModel> systemVersions) {
        return resolve(item, productSuperCatResolver, systemVersions);
    }

    private Set<ClassificationClassModel> resolve(final ProductModel item,
            final SuperCategoriesResolver<ProductModel> scr,
            final Collection<ClassificationSystemVersionModel> systemVersions) {
        return resolveClasses(item, scr, systemVersions);
    }

    @Override
    public Set<ClassificationClassModel> resolve(final CategoryModel item,
            final Collection<ClassificationSystemVersionModel> systemVersions) {
        return resolve(item, catSuperCatResolver, systemVersions);
    }

    private Set<ClassificationClassModel> resolve(final CategoryModel item,
            final SuperCategoriesResolver<CategoryModel> scr,
            final Collection<ClassificationSystemVersionModel> systemVersions) {
        return resolveClasses(item, scr, systemVersions);
    }

    private <T extends ItemModel> Set<ClassificationClassModel> resolveClasses(final T item,
            final SuperCategoriesResolver<T> scr,
            final Collection<ClassificationSystemVersionModel> systemVersions) {
        validateParameterNotNull(item, "item must not be null!");
        validateParameterNotNull(scr, "scr must not be null!");
        validateParameterNotNull(systemVersions, "systemVersions must not be null!");

        if (item instanceof ClassificationClassModel) {
            return Collections.singleton((ClassificationClassModel) item);
        } else {
            final boolean includeOnlyClosestClasses = isIncludingOnlyClosestClasses();

            Set<CategoryModel> touchedCategorieModels = null;
            Set<ClassificationClassModel> returnCCModels = null;
            final Map<ClassificationSystemVersionModel, Set<ClassificationClassModel>> permittedVersions = new HashMap<ClassificationSystemVersionModel, Set<ClassificationClassModel>>();
            for (final ClassificationSystemVersionModel clSysVer : systemVersions) {
                permittedVersions.put(clSysVer, null);
            }
            Set<CategoryModel> currentCategoriesLevel = scr.getSuperCategories(item);
            while (currentCategoriesLevel != null && !currentCategoriesLevel.isEmpty()
                    && !permittedVersions.isEmpty()) {
                Set<CategoryModel> nextCategoriesLevel = null;
                for (final CategoryModel category : currentCategoriesLevel) {
                    // avoid endless turns due to cycles using a control set
                    if (touchedCategorieModels == null) {
                        touchedCategorieModels = new HashSet<CategoryModel>();
                        touchedCategorieModels.add(category);
                    } else if (!touchedCategorieModels.add(category)) {
                        continue; // skip this category since we've ran across it before
                    }

                    // filter by system if required
                    if (category instanceof ClassificationClassModel) {
                        final ClassificationClassModel cCcategory = (ClassificationClassModel) category;
                        final ClassificationSystemVersionModel clVer = cCcategory.getCatalogVersion();
                        if (permittedVersions.containsKey(clVer)) {
                            // only closest: needs some extra work to collect classes for that version on *this* level only ( see below )
                            if (includeOnlyClosestClasses) {
                                Set<ClassificationClassModel> matchSet = permittedVersions.get(clVer);
                                if (matchSet == null) {
                                    permittedVersions.put(clVer,
                                            matchSet = new LinkedHashSet<ClassificationClassModel>());
                                }
                                matchSet.add(cCcategory);
                            }
                            // all: we can add them to the result right away
                            else {
                                if (returnCCModels == null) {
                                    returnCCModels = new LinkedHashSet<ClassificationClassModel>();
                                }
                                returnCCModels.add(cCcategory);
                            }
                        }
                        continue; // never add a classification class super category to next level
                    }
                    // no need to go further if at least one class has been found on this level
                    else {
                        if (nextCategoriesLevel == null) {
                            nextCategoriesLevel = new LinkedHashSet<CategoryModel>();
                        }
                        nextCategoriesLevel.addAll(category.getSupercategories());
                    }
                }

                if (includeOnlyClosestClasses) {
                    /*
                     * now prune all matching versions to avoid finding classes for them within next level
                     */
                    for (final Iterator<Map.Entry<ClassificationSystemVersionModel, Set<ClassificationClassModel>>> it = permittedVersions
                            .entrySet().iterator(); it.hasNext();) {
                        if (returnCCModels == null) {
                            returnCCModels = new LinkedHashSet<ClassificationClassModel>();
                        }
                        final Map.Entry<ClassificationSystemVersionModel, Set<ClassificationClassModel>> mapentry = it
                                .next();
                        if (mapentry.getValue() != null && !mapentry.getValue().isEmpty()) {
                            returnCCModels.addAll(mapentry.getValue());
                            it.remove(); // stop looking for classes for this version ( since we just want 'closest' classes )
                        }
                    }
                }
                currentCategoriesLevel = nextCategoriesLevel;
            }
            return returnCCModels == null ? Collections.EMPTY_SET : returnCCModels;
        }
    }

    protected boolean isIncludingOnlyClosestClasses() {
        return "closest".equalsIgnoreCase(Config.getParameter("classification.resolve.classes.mode"));
    }

    @Deprecated
    @Override
    public List<ClassAttributeAssignmentModel> getClassAttributeAssignments(
            final Set<ClassificationClassModel> classificationClasses) {
        return getDeclaredClassAttributeAssignments(classificationClasses);
    }

    @Required
    public void setCatalogVersionService(final CatalogVersionService catalogVersionService) {
        this.catalogVersionService = catalogVersionService;
    }

    @Override
    public List<ClassAttributeAssignmentModel> getAllClassAttributeAssignments(
            final Set<ClassificationClassModel> classificationClasses) {
        if (classificationClasses != null && !classificationClasses.isEmpty()) {
            final LinkedHashSet<ClassAttributeAssignmentModel> list = new LinkedHashSet<ClassAttributeAssignmentModel>();
            for (final ClassificationClassModel ccl : classificationClasses) {
                list.addAll(ccl.getAllClassificationAttributeAssignments());
            }
            return new ArrayList(list);
        } else {
            return Collections.EMPTY_LIST;
        }
    }

    @Override
    public List<ClassAttributeAssignmentModel> getDeclaredClassAttributeAssignments(
            final Set<ClassificationClassModel> classificationClasses) {
        if (classificationClasses != null && !classificationClasses.isEmpty()) {
            final List<ClassAttributeAssignmentModel> list = new ArrayList<ClassAttributeAssignmentModel>();
            for (final ClassificationClassModel ccl : classificationClasses) {
                final List<ClassAttributeAssignmentModel> declaredClassificationAttributeAssignments = ccl
                        .getDeclaredClassificationAttributeAssignments();
                if (declaredClassificationAttributeAssignments != null) {
                    list.addAll(declaredClassificationAttributeAssignments);
                }
            }
            return list;
        } else {
            return Collections.EMPTY_LIST;
        }
    }
}