AjaxPublicationsListServlet.java
/*
* Copyright (C) 2000 - 2026 Silverpeas
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* As a special exception to the terms and conditions of version 3.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* Open Source Software ("FLOSS") applications as described in Silverpeas's
* FLOSS exception. You should have received a copy of the text describing
* the FLOSS exception, and it is also available here:
* "https://www.silverpeas.org/legal/floss_exception.html"
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.silverpeas.components.kmelia.servlets;
import org.apache.commons.lang3.StringUtils;
import org.silverpeas.components.kmelia.KmeliaConstants;
import org.silverpeas.components.kmelia.control.KmeliaSessionController;
import org.silverpeas.components.kmelia.model.TopicDetail;
import org.silverpeas.components.kmelia.service.KmeliaHelper;
import org.silverpeas.components.kmelia.servlets.renderers.*;
import org.silverpeas.core.admin.user.model.SilverpeasRole;
import org.silverpeas.core.contribution.content.form.FieldTemplate;
import org.silverpeas.core.contribution.content.form.Form;
import org.silverpeas.core.contribution.content.form.PagesContext;
import org.silverpeas.core.contribution.publication.model.PublicationPK;
import org.silverpeas.core.index.indexing.model.FieldDescription;
import org.silverpeas.core.index.search.model.QueryDescription;
import org.silverpeas.core.node.model.NodePK;
import org.silverpeas.core.util.ArrayUtil;
import org.silverpeas.core.web.http.HttpRequest;
import org.silverpeas.core.web.mvc.controller.ComponentContext;
import org.silverpeas.core.web.mvc.controller.MainSessionController;
import org.silverpeas.core.web.util.viewgenerator.html.GraphicElementFactory;
import org.silverpeas.kernel.logging.SilverLogger;
import org.silverpeas.kernel.util.StringUtil;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import static java.util.Optional.ofNullable;
/**
* @author ehugonnet
*/
public class AjaxPublicationsListServlet extends HttpServlet {
private static final long serialVersionUID = 1003665785797438465L;
@Override
public void doGet(HttpServletRequest req, HttpServletResponse res) {
try {
doPost(req, res);
} catch (IOException e) {
SilverLogger.getLogger(this).error(e);
}
}
@Override
public void doPost(HttpServletRequest request, HttpServletResponse res) throws IOException {
final HttpRequest req = HttpRequest.decorate(request);
final HttpSession session = req.getSession(true);
String componentId = req.getParameter("ComponentId");
String nodeId = req.getParameter("Id");
String topicToLinkId = req.getParameter("TopicToLinkId");
RenderingContext ctx = getRenderingContext(req, session, componentId);
if (ctx == null) return;
initTopic(session, ctx, nodeId, topicToLinkId);
String query = req.getParameter("Query");
boolean searchRequest = req.getParameterAsBoolean("SearchRequest");
KmeliaSessionController kmeliaSC = ctx.getSessionController();
QueryDescription queryDescription = new QueryDescription(query);
PagesContext formContext = new PagesContext();
initSearch(queryDescription, formContext, req, kmeliaSC);
initPublicationsSelection(req, ctx);
Integer index = req.getParameterAsInteger("Index");
Integer nbItemsPerPage = req.getParameterAsInteger("NbItemsPerPage");
initPublicationsPagination(kmeliaSC, index, nbItemsPerPage);
Integer sort = req.getParameterAsInteger("Sort");
boolean resetManualSort = StringUtil.getBooleanValue(req.getParameter("ResetManualSort"));
initPublicationsSorting(kmeliaSC, sort, resetManualSort);
boolean searchContextExists = kmeliaSC.getSearchContext() != null;
boolean newSearchInProgress = searchRequest && !queryDescription.isEmpty();
if (!newSearchInProgress && searchContextExists && (searchRequest || index == null) &&
nbItemsPerPage == null && sort == null) {
kmeliaSC.setSearchContext(null);
searchContextExists = false;
kmeliaSC.loadPublicationsOfCurrentFolder();
}
loadPublications(req, ctx, formContext, queryDescription);
if (ctx.isAttachmentToLink()) {
ctx.setSortAllowed(false).setLinksAllowed(false).setSeeAlso(false);
kmeliaSC.setSearchContext(null);
searchContextExists = false;
}
if (KmeliaHelper.isToolbox(componentId)) {
String profile = kmeliaSC.getUserTopicProfile(kmeliaSC.getCurrentFolderId());
ctx.setLinksAllowed(!SilverpeasRole.USER.isInRole(profile));
}
ctx.setSearchInProgress(newSearchInProgress || searchContextExists);
renderWebPage(res, ctx);
}
private static void initPublicationsPagination(KmeliaSessionController kmeliaSC, Integer index,
Integer nbItemsPerPage) {
boolean inSearchContext = kmeliaSC.getSearchContext() != null;
if (index != null) {
if (inSearchContext) {
kmeliaSC.getSearchContext().setPaginationIndex(index);
} else {
kmeliaSC.setIndexOfFirstPubToDisplay(index);
}
}
if (nbItemsPerPage != null) {
kmeliaSC.setNbPublicationsPerPage(nbItemsPerPage);
}
}
private static void initPublicationsSelection(HttpRequest req, RenderingContext ctx) {
String selectedPublicationIds = req.getParameter("SelectedPubIds");
String notSelectedPublicationIds = req.getParameter("NotSelectedPubIds");
List<PublicationPK> selectedIds = ctx.getSessionController()
.processSelectedPublicationIds(selectedPublicationIds, notSelectedPublicationIds);
ctx.setSelectedPublications(selectedIds);
}
private static void initPublicationsSorting(KmeliaSessionController kmeliaSC, Integer sort,
boolean resetManualSort) {
if (sort != null) {
kmeliaSC.setSortValue(sort);
final String contentLanguage = kmeliaSC.getCurrentLanguage();
ofNullable(kmeliaSC.getSearchContext()).ifPresent(c -> c.applySort(sort, contentLanguage));
} else if (resetManualSort) {
kmeliaSC.resetPublicationsOrder();
}
}
private static void initTopic(HttpSession session, RenderingContext ctx, String nodeId,
String topicToLinkId) {
var kmeliaSC = ctx.getSessionController();
if (StringUtil.isDefined(nodeId)) {
kmeliaSC.setCurrentFolderId(nodeId, true);
kmeliaSC.loadPublicationsOfCurrentFolder();
// used by drag n drop
session.setAttribute("Silverpeas_DragAndDrop_TopicId", nodeId);
}
if ((ctx.isToLink() || ctx.isAttachmentToLink()) && StringUtil.isDefined(topicToLinkId)) {
TopicDetail currentTopicToLink = kmeliaSC.getTopic(topicToLinkId, false);
kmeliaSC.setSessionTopicToLink(currentTopicToLink);
}
}
private static RenderingContext getRenderingContext(HttpRequest req, HttpSession session,
String componentId) {
// check if trying to link attachment
boolean attachmentToLink = req.getParameterAsBoolean("attachmentLink");
boolean toLink = StringUtil.getBooleanValue(req.getParameter("ToLink"));
String pubIdToHighlight = req.getParameter("PubIdToHighLight");
KmeliaSessionController kmeliaSc =
(KmeliaSessionController) session.getAttribute("Silverpeas_kmelia_" + componentId);
GraphicElementFactory gef =
(GraphicElementFactory) session.getAttribute(GraphicElementFactory.GE_FACTORY_SESSION_ATT);
if (kmeliaSc == null && (toLink || attachmentToLink)) {
kmeliaSc = createSessionController(session, componentId);
}
if (kmeliaSc == null) {
return null;
}
var ctx = new RenderingContext(kmeliaSc, gef);
return ctx.setToLink(toLink).setAttachmentToLink(attachmentToLink).
setPublicationToHighlight(pubIdToHighlight);
}
private void renderWebPage(HttpServletResponse res, RenderingContext ctx) {
res.setContentType("text/xml");
res.setCharacterEncoding("UTF-8");
try {
var kmeliaSC = ctx.getSessionController();
int previousSort = kmeliaSC.getSort().getCurrentSort();
Renderer renderer;
if (kmeliaSC.isRightsOnTopicsEnabled() && !kmeliaSC.isCurrentTopicAvailable()) {
renderer = new ForbiddenAccessRenderer();
} else if (!ctx.isToLink() && NodePK.ROOT_NODE_ID.equals(kmeliaSC.getCurrentFolderId()) &&
kmeliaSC.getNbPublicationsOnRoot() != 0 && kmeliaSC.isTreeStructure() &&
!ctx.isSearchInProgress()) {
renderer = new LastPublicationsRenderer();
} else if (ctx.displayPublications()) {
renderer = new PublicationsRenderer();
} else {
renderer = new NothingRenderer();
}
renderer.render(res.getWriter(), ctx);
//We roll back with previous sort of the topic
if (ctx.isToLink()) {
kmeliaSC.getSort().setCurrentSort(previousSort);
}
} catch (IOException e) {
SilverLogger.getLogger(this).error(e);
}
}
private void loadPublications(HttpRequest req, RenderingContext ctx, PagesContext formContext,
QueryDescription queryDescription) {
ctx.setSortAllowed(true).setLinksAllowed(true);
var kmeliaSC = ctx.getSessionController();
boolean toPortlet = req.getParameterAsBoolean("ToPortlet");
boolean searchRequest = req.getParameterAsBoolean("SearchRequest");
boolean newSearchInProgress = searchRequest && !queryDescription.isEmpty();
boolean searchContextExists = kmeliaSC.getSearchContext() != null;
TopicDetail currentTopic;
ctx.setRole(kmeliaSC.getProfile());
if (ctx.isToLink()) {
currentTopic = kmeliaSC.getSessionTopicToLink();
ctx.setLinksAllowed(false).setSeeAlso(true);
// get selected publication ids from session
ctx.setSelectedPublications(processPublicationsToLink(req));
var publications = kmeliaSC.getKmeliaService()
.getAuthorizedPublicationsOfFolder(new NodePK(currentTopic.getNodePK().getId(),
currentTopic.getNodePK().getComponentInstanceId()),
kmeliaSC.getUserTopicProfile(currentTopic.getNodePK().getId()), kmeliaSC.getUserId()
,kmeliaSC.isTreeStructure());
kmeliaSC.setSessionPublicationsList(publications);
ctx.setPublications(kmeliaSC.getSessionPublicationsList());
} else if (toPortlet) {
ctx.setSortAllowed(false);
var publications = kmeliaSC.getSessionPublicationsList();
ctx.setPublications(publications);
ctx.setRole(SilverpeasRole.USER.toString());
} else if (newSearchInProgress) {
var publications = kmeliaSC.search(queryDescription, formContext);
ctx.setPublications(publications);
} else if (searchContextExists) {
var publications = kmeliaSC.getSearchContext().getResults();
ctx.setPublications(publications);
} else {
var publications = kmeliaSC.getSessionPublicationsList();
ctx.setPublications(publications);
}
}
@SuppressWarnings("unchecked")
private List<PublicationPK> processPublicationsToLink(HttpServletRequest request) {
// get from session the list of publications to link with current publication
HashSet<String> list = (HashSet<String>) request.getSession()
.getAttribute(KmeliaConstants.PUB_TO_LINK_SESSION_KEY);
// store the publication identifiers in an array list
List<PublicationPK> publicationsToLink = new ArrayList<>();
if (list != null) {
for (String link : list) {
String[] tokens = StringUtil.splitByWholeSeparator(link, "-");
publicationsToLink.add(new PublicationPK(tokens[0], tokens[1]));
}
}
return publicationsToLink;
}
private static KmeliaSessionController createSessionController(HttpSession session,
String componentId) {
KmeliaSessionController kmeliaSC;
MainSessionController mainSessionCtrl = (MainSessionController) session
.getAttribute(MainSessionController.MAIN_SESSION_CONTROLLER_ATT);
ComponentContext componentContext = mainSessionCtrl.createComponentContext(null, componentId);
kmeliaSC = new KmeliaSessionController(mainSessionCtrl, componentContext);
session.setAttribute("Silverpeas_kmelia_" + componentId, kmeliaSC);
return kmeliaSC;
}
private void initSearch(QueryDescription queryDescription, PagesContext formContext,
HttpServletRequest req, KmeliaSessionController kmeliaSC) {
Form searchForm = kmeliaSC.getXmlFormSearchForPublications();
if (searchForm != null) {
List<FieldTemplate> fields = searchForm.getFieldTemplates();
for (FieldTemplate field : fields) {
String fieldName = field.getFieldName();
String[] fieldValues = req.getParameterValues(fieldName);
if (ArrayUtil.isNotEmpty(fieldValues)) {
String fieldValue = fieldValues[0];
if (fieldValues.length > 1) {
String operator = req.getParameter(fieldName + "Operator");
formContext.setSearchOperator(fieldName, operator);
fieldValue = StringUtils.join(fieldValues, " " + operator + " ");
}
queryDescription.addFieldQuery(
new FieldDescription(searchForm.getFormName() + "$$" + fieldName,
fieldValue, kmeliaSC.getLanguage()));
}
}
}
}
}