/* * Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library 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 Lesser General Public License for more * details. */ package org.entando.entando.plugins.jacms.aps.system.services.api; import java.util.ArrayList; import java.util.List; import java.util.Properties; import javax.ws.rs.core.Response; import org.entando.entando.aps.system.services.api.IApiErrorCodes; import org.entando.entando.aps.system.services.api.model.ApiError; import org.entando.entando.aps.system.services.api.model.ApiException; import org.entando.entando.aps.system.services.api.model.StringApiResponse; import org.entando.entando.aps.system.services.api.server.IResponseBuilder; import org.entando.entando.plugins.jacms.aps.system.services.api.model.ApiContentListBean; import org.entando.entando.plugins.jacms.aps.system.services.api.model.JAXBContent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.agiletec.aps.system.SystemConstants; import com.agiletec.aps.system.common.entity.model.AttributeFieldError; import com.agiletec.aps.system.common.entity.model.EntitySearchFilter; import com.agiletec.aps.system.common.entity.model.FieldError; import com.agiletec.aps.system.exception.ApsSystemException; import com.agiletec.aps.system.services.category.ICategoryManager; import com.agiletec.aps.system.services.group.IGroupManager; import com.agiletec.aps.system.services.page.IPageManager; import com.agiletec.aps.system.services.user.IUserManager; import com.agiletec.aps.system.services.user.UserDetails; import com.agiletec.plugins.jacms.aps.system.services.content.ContentUtilizer; import com.agiletec.plugins.jacms.aps.system.services.content.helper.IContentAuthorizationHelper; import com.agiletec.plugins.jacms.aps.system.services.content.helper.IContentListHelper; import com.agiletec.plugins.jacms.aps.system.services.content.model.Content; import com.agiletec.plugins.jacms.aps.system.services.content.model.ContentRecordVO; import com.agiletec.plugins.jacms.aps.system.services.contentmodel.ContentModel; import com.agiletec.plugins.jacms.aps.system.services.dispenser.ContentRenderizationInfo; import com.agiletec.plugins.jacms.aps.system.services.dispenser.IContentDispenser; import com.agiletec.plugins.jacms.aps.system.services.resource.IResourceManager; /** * @author E.Santoboni */ public class ApiContentInterface extends AbstractCmsApiInterface { private static final Logger _logger = LoggerFactory.getLogger(ApiContentInterface.class); public List<String> getContents(Properties properties) throws Throwable { return this.extractContents(properties); } protected List<String> extractContents(Properties properties) throws Throwable { List<String> contentsId = null; try { ApiContentListBean bean = this.buildSearchBean(properties); UserDetails user = (UserDetails) properties.get(SystemConstants.API_USER_PARAMETER); contentsId = this.getContentListHelper().getContentsId(bean, user); } catch (ApiException ae) { throw ae; } catch (Throwable t) { _logger.error("error in extractContents", t); throw new ApsSystemException("Error into API method", t); } return contentsId; } protected ApiContentListBean buildSearchBean(Properties properties) throws ApiException, Throwable { ApiContentListBean bean = null; try { String contentType = properties.getProperty("contentType"); if (null == this.getContentManager().getSmallContentTypesMap().get(contentType)) { throw new ApiException(IApiErrorCodes.API_PARAMETER_VALIDATION_ERROR, "Content Type '" + contentType + "' does not exist", Response.Status.CONFLICT); } String langCode = properties.getProperty(SystemConstants.API_LANG_CODE_PARAMETER); String filtersParam = properties.getProperty("filters"); EntitySearchFilter[] filters = this.getContentListHelper().getFilters(contentType, filtersParam, langCode); String[] categoryCodes = null; String categoriesParam = properties.getProperty("categories"); if (null != categoriesParam && categoriesParam.trim().length() > 0) { categoryCodes = categoriesParam.split(IContentListHelper.CATEGORIES_SEPARATOR); } bean = new ApiContentListBean(contentType, filters, categoryCodes); } catch (ApiException ae) { throw ae; } catch (Throwable t) { _logger.error("error in buildSearchBean", t); throw new ApsSystemException("Error into API method", t); } return bean; } public String getContentsToHtml(Properties properties) throws Throwable { StringBuilder render = new StringBuilder(); try { String modelId = properties.getProperty("modelId"); if (null == modelId || modelId.trim().length() == 0) { return null; } String contentType = properties.getProperty("contentType"); Content prototype = (Content) this.getContentManager().getEntityPrototype(contentType); Integer modelIdInteger = this.checkModel(modelId, prototype); if (null == modelIdInteger) { return null; } List<String> contentsId = this.extractContents(properties); String langCode = properties.getProperty(SystemConstants.API_LANG_CODE_PARAMETER); render.append(this.getItemsStartElement()); for (int i = 0; i < contentsId.size(); i++) { render.append(this.getItemStartElement()); String renderedContent = this.getRenderedContent(contentsId.get(i), modelIdInteger, langCode); if (null != renderedContent) { render.append(renderedContent); } render.append(this.getItemEndElement()); } render.append(this.getItemsEndElement()); } catch (ApiException ae) { throw ae; } catch (Throwable t) { _logger.error("error in getContentsToHtml", t); throw new ApsSystemException("Error into API method", t); } return render.toString(); } public JAXBContent getContent(Properties properties) throws ApiException, Throwable { JAXBContent jaxbContent = null; String id = properties.getProperty("id"); try { String langCode = properties.getProperty(SystemConstants.API_LANG_CODE_PARAMETER); Content mainContent = this.getPublicContent(id); jaxbContent = this.getJAXBContentInstance(mainContent, langCode); UserDetails user = (UserDetails) properties.get(SystemConstants.API_USER_PARAMETER); if (null == user) { user = this.getUserManager().getGuestUser(); } if (!this.getContentAuthorizationHelper().isAuth(user, mainContent)) { throw new ApiException(IApiErrorCodes.API_VALIDATION_ERROR, "Required content '" + id + "' does not allowed", Response.Status.FORBIDDEN); } } catch (ApiException ae) { throw ae; } catch (Throwable t) { _logger.error("error in getContent", t); throw new ApsSystemException("Error into API method", t); } return jaxbContent; } protected JAXBContent getJAXBContentInstance(Content mainContent, String langCode) { return new JAXBContent(mainContent, langCode); } public String getContentToHtml(Properties properties) throws ApiException, Throwable { String render = null; String id = properties.getProperty("id"); String modelId = properties.getProperty("modelId"); try { if (null == modelId || modelId.trim().length() == 0) { return null; } Content mainContent = this.getPublicContent(id); Integer modelIdInteger = this.checkModel(modelId, mainContent); if (null != modelIdInteger) { String langCode = properties.getProperty(SystemConstants.API_LANG_CODE_PARAMETER); render = this.getRenderedContent(id, modelIdInteger, langCode); } } catch (ApiException ae) { throw ae; } catch (Throwable t) { _logger.error("error in getContentToHtml", t); throw new ApsSystemException("Error into API method", t); } return render; } protected String getRenderedContent(String id, int modelId, String langCode) { String renderedContent = null; ContentRenderizationInfo renderizationInfo = this.getContentDispenser().getRenderizationInfo(id, modelId, langCode, null, true); if (null != renderizationInfo) { this.getContentDispenser().resolveLinks(renderizationInfo, null); renderedContent = renderizationInfo.getRenderedContent(); } return renderedContent; } protected Content getPublicContent(String id) throws ApiException, Throwable { Content content = null; try { content = this.getContentManager().loadContent(id, true); if (null == content) { throw new ApiException(IApiErrorCodes.API_PARAMETER_VALIDATION_ERROR, "Null content by id '" + id + "'", Response.Status.CONFLICT); } } catch (ApiException ae) { throw ae; } catch (Throwable t) { _logger.error("Error extracting content by id '{}'",id, t); throw new ApsSystemException("Error extracting content by id '" + id + "'", t); } return content; } protected Integer checkModel(String modelId, Content content) throws ApiException, Throwable { Integer modelIdInteger = null; try { if (null == modelId || modelId.trim().length() == 0) { return null; } if (modelId.equals("default")) { if (null == content.getDefaultModel()) { throw new ApiException(IApiErrorCodes.API_PARAMETER_VALIDATION_ERROR, "Invalid 'default' system model for content type '" + content.getTypeCode() + "' - Contact the administrators", Response.Status.ACCEPTED); } modelIdInteger = Integer.parseInt(content.getDefaultModel()); } else if (modelId.equals("list")) { if (null == content.getListModel()) { throw new ApiException(IApiErrorCodes.API_PARAMETER_VALIDATION_ERROR, "Invalid 'list' system model for content type '" + content.getTypeCode() + "' - Contact the administrators", Response.Status.ACCEPTED); } modelIdInteger = Integer.parseInt(content.getListModel()); } else { try { modelIdInteger = Integer.parseInt(modelId); } catch (Throwable t) { throw new ApiException(IApiErrorCodes.API_PARAMETER_VALIDATION_ERROR, "The model id must be an integer or 'default' or 'list' - '" + modelId + "'", Response.Status.ACCEPTED); } } ContentModel model = this.getContentModelManager().getContentModel(modelIdInteger); if (model == null) { throw new ApiException(IApiErrorCodes.API_PARAMETER_VALIDATION_ERROR, "The content model with id '" + modelId + "' does not exist", Response.Status.ACCEPTED); } else if (!content.getTypeCode().equals(model.getContentType())) { throw new ApiException(IApiErrorCodes.API_PARAMETER_VALIDATION_ERROR, "The content model with id '" + modelId + "' does not match with content of type '" + content.getTypeDescription() + "' ", Response.Status.ACCEPTED); } } catch (ApiException ae) { throw ae; } catch (Throwable t) { _logger.error("Error checking model id '{}'", modelId, t); throw new ApsSystemException("Error checking model id '" + modelId + "'", t); } return modelIdInteger; } public StringApiResponse addContent(JAXBContent jaxbContent, Properties properties) throws Throwable { StringApiResponse response = new StringApiResponse(); try { String typeCode = jaxbContent.getTypeCode(); Content prototype = (Content) this.getContentManager().getEntityPrototype(typeCode); if (null == prototype) { throw new ApiException(IApiErrorCodes.API_VALIDATION_ERROR, "Content type with code '" + typeCode + "' does not exist", Response.Status.CONFLICT); } Content content = (Content) jaxbContent.buildEntity(prototype, this.getCategoryManager()); if (null != content.getId()) { throw new ApiException(IApiErrorCodes.API_VALIDATION_ERROR, "You cannot specify Content Id", Response.Status.CONFLICT); } UserDetails user = (UserDetails) properties.get(SystemConstants.API_USER_PARAMETER); content.setFirstEditor((null != user) ? user.getUsername() : SystemConstants.GUEST_USER_NAME); response = this.validateAndSaveContent(content, properties); } catch (ApiException ae) { response.addErrors(ae.getErrors()); response.setResult(IResponseBuilder.FAILURE, null); } catch (Throwable t) { _logger.error("Error adding content", t); throw new ApsSystemException("Error adding content", t); } return response; } public StringApiResponse updateContent(JAXBContent jaxbContent, Properties properties) throws Throwable { StringApiResponse response = new StringApiResponse(); try { String typeCode = jaxbContent.getTypeCode(); Content prototype = (Content) this.getContentManager().getEntityPrototype(typeCode); if (null == prototype) { throw new ApiException(IApiErrorCodes.API_VALIDATION_ERROR, "Content type with code '" + typeCode + "' does not exist", Response.Status.CONFLICT); } Content content = (Content) jaxbContent.buildEntity(prototype, this.getCategoryManager()); Content masterContent = this.getContentManager().loadContent(content.getId(), false); if (null == masterContent) { throw new ApiException(IApiErrorCodes.API_VALIDATION_ERROR, "Content with code '" + content.getId() + "' does not exist", Response.Status.CONFLICT); } else if (!masterContent.getMainGroup().equals(content.getMainGroup())) { throw new ApiException(IApiErrorCodes.API_VALIDATION_ERROR, "Invalid main group " + content.getMainGroup() + " not equals then master " + masterContent.getMainGroup(), Response.Status.CONFLICT); } response = this.validateAndSaveContent(content, properties); } catch (ApiException ae) { response.addErrors(ae.getErrors()); response.setResult(IResponseBuilder.FAILURE, null); } catch (Throwable t) { _logger.error("Error updating content", t); throw new ApsSystemException("Error updating content", t); } return response; } protected StringApiResponse validateAndSaveContent(Content content, Properties properties) throws ApiException, Throwable { StringApiResponse response = new StringApiResponse(); try { UserDetails user = (UserDetails) properties.get(SystemConstants.API_USER_PARAMETER); if (null == user) { user = this.getUserManager().getGuestUser(); } if (!this.getContentAuthorizationHelper().isAuth(user, content)) { throw new ApiException(IApiErrorCodes.API_VALIDATION_ERROR, "Content groups makes the new content not allowed for user " + user.getUsername(), Response.Status.FORBIDDEN); } List<ApiError> errors = this.validate(content); if (errors.size() > 0) { response.addErrors(errors); response.setResult(IResponseBuilder.FAILURE, null); return response; } String insertOnLineString = properties.getProperty("insertOnLine"); boolean insertOnLine = (null != insertOnLineString) ? Boolean.parseBoolean(insertOnLineString) : false; if (!insertOnLine) { this.getContentManager().saveContent(content); } else { this.getContentManager().insertOnLineContent(content); } response.setResult(IResponseBuilder.SUCCESS, null); } catch (ApiException ae) { response.addErrors(ae.getErrors()); response.setResult(IResponseBuilder.FAILURE, null); } catch (Throwable t) { _logger.error("error in validateAndSaveContent", t); throw new ApsSystemException("Error adding content", t); } return response; } private List<ApiError> validate(Content content) throws ApsSystemException { List<ApiError> errors = new ArrayList<ApiError>(); try { if (null == content.getMainGroup()) { errors.add(new ApiError(IApiErrorCodes.API_VALIDATION_ERROR, "Main group null", Response.Status.CONFLICT)); } List<FieldError> fieldErrors = content.validate(this.getGroupManager()); if (null != fieldErrors) { for (int i = 0; i < fieldErrors.size(); i++) { FieldError fieldError = fieldErrors.get(i); if (fieldError instanceof AttributeFieldError) { AttributeFieldError attributeError = (AttributeFieldError) fieldError; errors.add(new ApiError(IApiErrorCodes.API_VALIDATION_ERROR, attributeError.getFullMessage(), Response.Status.CONFLICT)); } else { errors.add(new ApiError(IApiErrorCodes.API_VALIDATION_ERROR, fieldError.getMessage(), Response.Status.CONFLICT)); } } } } catch (Throwable t) { _logger.error("Error validating content", t); throw new ApsSystemException("Error validating content", t); } return errors; } public StringApiResponse deleteContent(Properties properties) throws Throwable { StringApiResponse response = new StringApiResponse(); try { String id = properties.getProperty("id"); Content masterContent = this.getContentManager().loadContent(id, false); if (null == masterContent) { throw new ApiException(IApiErrorCodes.API_VALIDATION_ERROR, "Content with code '" + id + "' does not exist", Response.Status.CONFLICT); } UserDetails user = (UserDetails) properties.get(SystemConstants.API_USER_PARAMETER); if (null == user) { user = this.getUserManager().getGuestUser(); } if (!this.getContentAuthorizationHelper().isAuth(user, masterContent)) { throw new ApiException(IApiErrorCodes.API_VALIDATION_ERROR, "Content groups makes the new content not allowed for user " + user.getUsername(), Response.Status.FORBIDDEN); } List<String> references = ((ContentUtilizer) this.getContentManager()).getContentUtilizers(id); if (references != null && references.size() > 0) { boolean found = false; for (int i = 0; i < references.size(); i++) { String reference = references.get(i); ContentRecordVO record = this.getContentManager().loadContentVO(reference); if (null != record) { found = true; response.addError(new ApiError(IApiErrorCodes.API_VALIDATION_ERROR, "Content " + id + " referenced to content " + record.getId() + " - '" + record.getDescr() + "'", Response.Status.CONFLICT)); } } if (found) { response.setResult(IResponseBuilder.FAILURE, null); return response; } } if (masterContent.isOnLine()) { this.getContentManager().removeOnLineContent(masterContent); } String removeWorkVersionString = properties.getProperty("removeWorkVersion"); boolean removeWorkVersion = (null != removeWorkVersionString) ? Boolean.parseBoolean(removeWorkVersionString) : false; if (removeWorkVersion) { this.getContentManager().deleteContent(masterContent); } response.setResult(IResponseBuilder.SUCCESS, null); } catch (ApiException ae) { response.addErrors(ae.getErrors()); response.setResult(IResponseBuilder.FAILURE, null); } catch (Throwable t) { _logger.error("Error deleting content", t); throw new ApsSystemException("Error deleting content", t); } return response; } protected IContentListHelper getContentListHelper() { return _contentListHelper; } public void setContentListHelper(IContentListHelper contentListHelper) { this._contentListHelper = contentListHelper; } protected IUserManager getUserManager() { return _userManager; } public void setUserManager(IUserManager userManager) { this._userManager = userManager; } protected ICategoryManager getCategoryManager() { return _categoryManager; } public void setCategoryManager(ICategoryManager categoryManager) { this._categoryManager = categoryManager; } protected IGroupManager getGroupManager() { return _groupManager; } public void setGroupManager(IGroupManager groupManager) { this._groupManager = groupManager; } protected IPageManager getPageManager() { return _pageManager; } public void setPageManager(IPageManager pageManager) { this._pageManager = pageManager; } protected IResourceManager getResourceManager() { return _resourceManager; } public void setResourceManager(IResourceManager resourceManager) { this._resourceManager = resourceManager; } protected IContentAuthorizationHelper getContentAuthorizationHelper() { return _contentAuthorizationHelper; } public void setContentAuthorizationHelper(IContentAuthorizationHelper contentAuthorizationHelper) { this._contentAuthorizationHelper = contentAuthorizationHelper; } protected IContentDispenser getContentDispenser() { return _contentDispenser; } public void setContentDispenser(IContentDispenser contentDispenser) { this._contentDispenser = contentDispenser; } public String getItemsStartElement() { return _itemsStartElement; } public void setItemsStartElement(String itemsStartElement) { this._itemsStartElement = itemsStartElement; } public String getItemStartElement() { return _itemStartElement; } public void setItemStartElement(String itemStartElement) { this._itemStartElement = itemStartElement; } public String getItemEndElement() { return _itemEndElement; } public void setItemEndElement(String itemEndElement) { this._itemEndElement = itemEndElement; } public String getItemsEndElement() { return _itemsEndElement; } public void setItemsEndElement(String itemsEndElement) { this._itemsEndElement = itemsEndElement; } private IContentListHelper _contentListHelper; private IUserManager _userManager; private ICategoryManager _categoryManager; private IGroupManager _groupManager; private IPageManager _pageManager; private IResourceManager _resourceManager; private IContentAuthorizationHelper _contentAuthorizationHelper; private IContentDispenser _contentDispenser; private String _itemsStartElement = "<ul>"; private String _itemStartElement = "<li>"; private String _itemEndElement = "</li>"; private String _itemsEndElement = "</ul>"; }