Skip to content

Commit

Permalink
add support for delegating value provider and resolver
Browse files Browse the repository at this point in the history
  • Loading branch information
bechte committed Jul 16, 2024
1 parent 7ce812d commit 87aee8e
Show file tree
Hide file tree
Showing 2 changed files with 173 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package tools.sapcx.commerce.search.provider;

import static org.apache.commons.collections4.MapUtils.emptyIfNull;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import de.hybris.platform.core.model.ItemModel;
import de.hybris.platform.servicelayer.model.ModelService;
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.FieldValue;
import de.hybris.platform.solrfacetsearch.provider.FieldValueProvider;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class CxReferencedItemDelegatingFieldValueProvider implements FieldValueProvider, ApplicationContextAware {
private static final String MISSING_VALUEPROVIDERPARAMETER_EXCEPTION = "Missing required value provider parameter '%s', please check configuration of indexed property '%s'!";
private static final String MISSING_VALUEPROVIDERBEAN_EXCEPTION = "Could not find delegated FieldValueProvider with ID '%s', please check configuration of indexed property '%s'!";

private static final String REFERENCE_ATTRIBUTE_KEY = "referenceAttribute";
private static final String DELEGATE_KEY = "delegate";

private ApplicationContext applicationContext;
private ModelService modelService;

public CxReferencedItemDelegatingFieldValueProvider(ModelService modelService) {
this.modelService = modelService;
}

@Override
public Collection<FieldValue> getFieldValues(IndexConfig indexConfig, IndexedProperty indexedProperty, Object object) throws FieldValueProviderException {
final FieldValueProvider delegate = getDelegate(indexedProperty);
final String referencedAttributeName = getRequiredValueProviderParameter(indexedProperty, REFERENCE_ATTRIBUTE_KEY);

if (object instanceof ItemModel) {
final ItemModel item = (ItemModel) object;
final Object referencedObject = modelService.getAttributeValue(item, referencedAttributeName);
if (referencedObject instanceof ItemModel) {
final ItemModel referencedItem = (ItemModel) referencedObject;
return getFieldValuesFromDelegate(indexConfig, indexedProperty, referencedItem, delegate);
} else if (referencedObject instanceof Collection<?> elements) {
final Collection<FieldValue> fieldValues = new ArrayList<>();
for (Object element : elements) {
fieldValues.addAll(getFieldValuesFromDelegate(indexConfig, indexedProperty, element, delegate));
}
return fieldValues;
}
}

return List.of();
}

private Collection<FieldValue> getFieldValuesFromDelegate(IndexConfig indexConfig, IndexedProperty indexedProperty, Object referencedObject, FieldValueProvider delegate)
throws FieldValueProviderException {
return delegate.getFieldValues(indexConfig, indexedProperty, referencedObject);
}

private FieldValueProvider getDelegate(IndexedProperty indexedProperty) throws FieldValueProviderException {
final String delegateBeanId = getRequiredValueProviderParameter(indexedProperty, DELEGATE_KEY);
try {
return applicationContext.getBean(delegateBeanId, FieldValueProvider.class);
} catch (BeansException e) {
final String msg = String.format(MISSING_VALUEPROVIDERBEAN_EXCEPTION, delegateBeanId, indexedProperty.getName());
throw new FieldValueProviderException(msg, e);
}
}

private String getRequiredValueProviderParameter(final IndexedProperty indexedProperty, final String key) throws FieldValueProviderException {
final Map<String, String> valueProviderParameters = emptyIfNull(indexedProperty.getValueProviderParameters());
final String parameterValue = valueProviderParameters.get(key);
return Optional.ofNullable(parameterValue)
.orElseThrow(() -> {
final String msg = String.format(MISSING_VALUEPROVIDERPARAMETER_EXCEPTION, DELEGATE_KEY, indexedProperty.getName());
return new FieldValueProviderException(msg);
});
}

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package tools.sapcx.commerce.search.resolver;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import de.hybris.platform.core.model.ItemModel;
import de.hybris.platform.servicelayer.model.ModelService;
import de.hybris.platform.solrfacetsearch.config.IndexedProperty;
import de.hybris.platform.solrfacetsearch.config.exceptions.FieldValueProviderException;
import de.hybris.platform.solrfacetsearch.indexer.IndexerBatchContext;
import de.hybris.platform.solrfacetsearch.indexer.spi.InputDocument;
import de.hybris.platform.solrfacetsearch.provider.ValueResolver;

import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class CxReferencedItemDelegatingValueResolver implements ValueResolver<ItemModel>, ApplicationContextAware {
private static final String MISSING_VALUERESOLVERPARAMETER_EXCEPTION = "Missing required value resolver parameter '%s', please check configuration of indexed property '%s'!";
private static final String MISSING_VALUERESOLVERBEAN_EXCEPTION = "Could not find delegated ValueResolver with ID '%s', please check configuration of indexed property '%s'!";

private static final String REFERENCE_ATTRIBUTE_KEY = "referenceAttribute";
private static final String DELEGATE_KEY = "delegate";

private ApplicationContext applicationContext;
private ModelService modelService;

public CxReferencedItemDelegatingValueResolver(ModelService modelService) {
this.modelService = modelService;
}

@Override
public void resolve(InputDocument inputDocument, IndexerBatchContext indexerBatchContext, Collection<IndexedProperty> indexedProperties, ItemModel item)
throws FieldValueProviderException {
for (IndexedProperty indexedProperty : indexedProperties) {
final ValueResolver<ItemModel> delegate = getDelegate(indexedProperty);
final String referencedAttributeName = getRequiredValueProviderParameter(indexedProperty, REFERENCE_ATTRIBUTE_KEY);
final Object referencedObject = modelService.getAttributeValue(item, referencedAttributeName);
if (referencedObject instanceof ItemModel) {
final ItemModel referencedItem = (ItemModel) referencedObject;
resolveWithDelegate(inputDocument, indexerBatchContext, indexedProperty, referencedItem, delegate);
} else if (referencedObject instanceof Collection) {
for (Object element : (Collection) referencedObject) {
if (element instanceof ItemModel referencedItem) {
resolveWithDelegate(inputDocument, indexerBatchContext, indexedProperty, referencedItem, delegate);
}
}
}
}
}

private void resolveWithDelegate(InputDocument inputDocument, IndexerBatchContext indexerBatchContext, IndexedProperty indexedProperty, ItemModel referencedItem,
ValueResolver<ItemModel> delegate) throws FieldValueProviderException {
delegate.resolve(inputDocument, indexerBatchContext, List.of(indexedProperty), referencedItem);
}

private ValueResolver<ItemModel> getDelegate(IndexedProperty indexedProperty) throws FieldValueProviderException {
final String delegateBeanId = getRequiredValueProviderParameter(indexedProperty, DELEGATE_KEY);
try {
return applicationContext.getBean(delegateBeanId, ValueResolver.class);
} catch (BeansException e) {
final String msg = String.format(MISSING_VALUERESOLVERBEAN_EXCEPTION, delegateBeanId, indexedProperty.getName());
throw new FieldValueProviderException(msg, e);
}
}

private String getRequiredValueProviderParameter(final IndexedProperty indexedProperty, final String key) throws FieldValueProviderException {
final Map<String, String> valueProviderParameters = MapUtils.emptyIfNull(indexedProperty.getValueProviderParameters());
final String parameterValue = valueProviderParameters.get(key);
return Optional.ofNullable(parameterValue)
.orElseThrow(() -> {
final String msg = String.format(MISSING_VALUERESOLVERPARAMETER_EXCEPTION, DELEGATE_KEY, indexedProperty.getName());
return new FieldValueProviderException(msg);
});
}

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}

0 comments on commit 87aee8e

Please sign in to comment.