com.sdl.dxa.tridion.mapping.impl.GraphQLContentProvider Maven / Gradle / Ivy
The newest version!
package com.sdl.dxa.tridion.mapping.impl;
import com.sdl.dxa.api.datamodel.model.ContentModelData;
import com.sdl.dxa.api.datamodel.model.EntityModelData;
import com.sdl.dxa.api.datamodel.model.PageModelData;
import com.sdl.dxa.caching.statistics.CacheStatisticsProvider;
import com.sdl.dxa.common.dto.EntityRequestDto;
import com.sdl.dxa.common.dto.PageRequestDto;
import com.sdl.dxa.common.dto.StaticContentRequestDto;
import com.sdl.dxa.tridion.broker.GraphQLQueryProvider;
import com.sdl.dxa.tridion.broker.QueryProvider;
import com.sdl.dxa.tridion.content.StaticContentResolver;
import com.sdl.dxa.tridion.graphql.GraphQLProvider;
import com.sdl.dxa.tridion.mapping.ModelBuilderPipeline;
import com.sdl.dxa.tridion.pcaclient.ApiClientProvider;
import com.sdl.web.pca.client.contentmodel.enums.ContentType;
import com.sdl.web.pca.client.contentmodel.enums.DataModelType;
import com.sdl.web.pca.client.contentmodel.enums.PageInclusion;
import com.sdl.web.pca.client.contentmodel.generated.Component;
import com.sdl.web.pca.client.contentmodel.generated.CustomMetaEdge;
import com.sdl.web.pca.client.contentmodel.generated.Item;
import com.sdl.webapp.common.api.WebRequestContext;
import com.sdl.webapp.common.api.content.ContentProvider;
import com.sdl.webapp.common.api.content.ContentProviderException;
import com.sdl.webapp.common.api.content.Dxa22ContentProvider;
import com.sdl.webapp.common.api.content.StaticContentItem;
import com.sdl.webapp.common.api.localization.Localization;
import com.sdl.webapp.common.api.model.EntityModel;
import com.sdl.webapp.common.api.model.PageModel;
import com.sdl.webapp.common.api.model.entity.DynamicList;
import com.sdl.webapp.common.api.model.query.SimpleBrokerQuery;
import com.sdl.webapp.common.exceptions.DxaException;
import com.sdl.webapp.common.exceptions.DxaRuntimeException;
import com.sdl.webapp.common.util.FileUtils;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import jakarta.servlet.http.HttpSession;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Content Provider GraphQL implementation. Look at {@link ContentProvider} documentation for details.
*
*/
@Service(value = "GraphQLContentProvider")
@Profile("!cil.providers.active")
@Primary
@Slf4j
public class GraphQLContentProvider extends AbstractContentProvider implements ContentProvider, Dxa22ContentProvider {
private ModelBuilderPipeline builderPipeline;
private StaticContentResolver staticContentResolver;
private GraphQLProvider graphQLProvider;
private final WebRequestContext webRequestContext;
private ApiClientProvider pcaClientProvider;
private CacheManager cacheManager;
private CacheStatisticsProvider cacheStatisticsProvider;
@Autowired
public GraphQLContentProvider(WebRequestContext webRequestContext,
StaticContentResolver staticContentResolver,
ModelBuilderPipeline builderPipeline, GraphQLProvider graphQLProvider,
ApiClientProvider pcaClientProvider,
@Qualifier("compositeCacheManager") CacheManager cacheManager,
CacheStatisticsProvider cacheStatisticsProvider) {
super(webRequestContext, cacheManager);
this.webRequestContext = webRequestContext;
this.pcaClientProvider = pcaClientProvider;
this.cacheManager = cacheManager;
this.staticContentResolver = staticContentResolver;
this.builderPipeline = builderPipeline;
this.graphQLProvider = graphQLProvider;
this.cacheStatisticsProvider = cacheStatisticsProvider;
}
/**
* {@inheritDoc}
*
*/
@Override
public void populateDynamicList(DynamicList dynamicList, Localization localization) throws ContentProviderException {
if (localization == null) {
log.info("Localization should not be null to populate dynamic list {}, skipping", dynamicList);
return;
}
SimpleBrokerQuery simpleBrokerQuery = dynamicList.getQuery(localization);
// get our cursor indexer for this list
CursorIndexer cursors = CursorIndexer.getCursorIndexer(dynamicList.getId());
// given our start index into the paged list we need to translate that to a cursor
int start = simpleBrokerQuery.getStartAt();
simpleBrokerQuery.setCursor(cursors.get(start));
// the cursor retrieved may of came from a different start index so we update start
simpleBrokerQuery.setStartAt(start);
dynamicList.setStart(cursors.getStart());
QueryProvider brokerQuery = new GraphQLQueryProvider(pcaClientProvider, cacheManager, webRequestContext);
List- components = brokerQuery.executeQueryItems(simpleBrokerQuery);
log.debug("Broker query returned {} results. hasMore={}", components.size(), brokerQuery.hasMore());
if (components.size() > 0) {
Class
resultType = dynamicList.getEntityType();
dynamicList.setQueryResults(
components.stream().map(c -> {
try {
return builderPipeline.createEntityModel(createEntityModelData((Component) c), resultType);
} catch (DxaException e) {
throw new DxaRuntimeException(e);
}
}).collect(Collectors.toList()),
brokerQuery.hasMore()
);
}
if (brokerQuery.hasMore()) {
cursors.cursors.put(simpleBrokerQuery.getStartAt() + simpleBrokerQuery.getPageSize(), brokerQuery.getCursor());
}
}
private EntityModelData createEntityModelData(Component component) {
ContentModelData standardMeta = new ContentModelData();
for (CustomMetaEdge meta : component.getCustomMetas().getEdges()) {
standardMeta.put(meta.getNode().getKey(), meta.getNode().getValue());
}
// The semantic mapping requires that some metadata fields exist. This may not be the case so we map some component meta properties onto them
// if they don't exist.
if (!standardMeta.containsKey("dateCreated")) {
standardMeta.put("dateCreated", component.getLastPublishDate());
}
if (!standardMeta.containsKey("name")) {
standardMeta.put("name", component.getTitle());
}
EntityModelData result = new EntityModelData();
result.setId("" + component.getItemId());
result.setSchemaId("" + component.getSchemaId());
ContentModelData meta = new ContentModelData();
meta.put("standardMeta", standardMeta);
result.setMetadata(meta);
return result;
}
private boolean isNoMediaCache(String path, String localizationPath) {
return !FileUtils.isEssentialConfiguration(path, localizationPath) && webRequestContext.isSessionPreview();
}
/**
* {@inheritDoc}
*
*/
@Override
public @NotNull StaticContentItem getStaticContent(String path, String localizationId, String localizationPath)
throws ContentProviderException {
StaticContentRequestDto requestDto = StaticContentRequestDto.builder(path, localizationId)
.localizationPath(localizationPath)
.baseUrl(webRequestContext.getBaseUrl())
.noMediaCache(isNoMediaCache(path, localizationPath))
.build();
StaticContentItem staticContentItem = staticContentResolver.getStaticContent(requestDto);
if (cacheStatisticsProvider != null) {
cacheStatisticsProvider.storeStatsInfo("staticContentItems", staticContentItem);
}
return staticContentItem;
}
protected PageModel loadPage(String path, Localization localization) throws ContentProviderException {
PageRequestDto pageRequest = PageRequestDto.builder(localization.getId(), path)
.includePages(PageRequestDto.PageInclusion.INCLUDE)
.uriType(localization.getCmUriScheme())
.build();
PageModelData pageModelData = graphQLProvider.loadPage(PageModelData.class, pageRequest, ContentType.MODEL);
return builderPipeline.createPageModel(pageModelData);
}
@Override
PageModel loadPage(int pageId, Localization localization) throws ContentProviderException {
PageModelData pageModelData = graphQLProvider.loadPage(PageModelData.class,
localization.getCmUriScheme(), Integer.parseInt(localization.getId()), pageId,
ContentType.MODEL, DataModelType.R2, PageInclusion.INCLUDE, null);
return builderPipeline.createPageModel(pageModelData);
}
@NotNull
protected EntityModel getEntityModel(String componentId) throws ContentProviderException {
Localization localization = webRequestContext.getLocalization();
EntityRequestDto entityRequest = EntityRequestDto.builder(localization.getId(), componentId).build();
EntityModelData entityModelData = graphQLProvider.getEntityModelData(entityRequest);
try {
return builderPipeline.createEntityModel(entityModelData);
} catch (DxaException ex) {
throw new ContentProviderException("Cannot build the entity model for componentId: " + componentId, ex);
}
}
@Override
@Cacheable(condition = "#binaryId != null && #localization != null && #localization.id != null",
cacheNames = "staticContentItems",
key = "{#binaryId, #localization.id}",
sync = true)
public StaticContentItem getStaticContent(int binaryId, Localization localization) throws ContentProviderException {
String localizationId = localization.getId();
String localizationPath = localization.getPath();
String contentNamespace = localization.getCmUriScheme();
StaticContentRequestDto requestDto = StaticContentRequestDto.builder(binaryId, localizationId)
.localizationPath(localizationPath)
.baseUrl(webRequestContext.getBaseUrl())
.uriType(contentNamespace)
.build();
return staticContentResolver.getStaticContent(requestDto);
}
@Override
@NotNull
public StaticContentItem getStaticContent(String path, Localization localization) throws ContentProviderException {
String localizationId = localization.getId();
String localizationPath = localization.getPath();
String namespace = localization.getCmUriScheme();
StaticContentRequestDto requestDto = StaticContentRequestDto.builder(path, localizationId)
.localizationPath(localizationPath)
.baseUrl(webRequestContext.getBaseUrl())
.noMediaCache(isNoMediaCache(path, localizationPath))
.uriType(namespace)
.build();
return staticContentResolver.getStaticContent(requestDto);
}
private static class CursorIndexer implements Serializable {
public static final String SESSION_KEY = "dxa_indexer";
private Map cursors = new HashMap<>();
private int startIndex;
public CursorIndexer() {
}
public static CursorIndexer getCursorIndexer(String id) {
HttpSession session = (HttpSession) RequestContextHolder.getRequestAttributes().getSessionMutex();
Map indexer = (Map) session.getAttribute(SESSION_KEY);
if (indexer == null) {
indexer = new HashMap<>();
}
if (!indexer.containsKey(id)) {
indexer.put(id, new CursorIndexer());
}
session.setAttribute(SESSION_KEY, indexer);
return indexer.get(id);
}
public String get(int index) {
if (index == 0) {
startIndex = 0;
return null;
}
if (cursors.isEmpty()) {
startIndex = 0;
return null;
}
if (cursors.containsKey(index)) {
startIndex = index;
return cursors.get(index);
}
int min = 0;
for (Integer x : cursors.keySet()) {
if (x >= min && x < index) min = x;
}
startIndex = min;
return startIndex == 0 ? null : cursors.get(startIndex);
}
public void set(int index, String value) {
cursors.put(index, value);
}
public int getStart() {
return startIndex;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy