/* * 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.aps.system.services.widgettype.api; import com.agiletec.aps.system.SystemConstants; import com.agiletec.aps.system.exception.ApsSystemException; import com.agiletec.aps.system.services.page.IPage; import com.agiletec.aps.system.services.page.IPageManager; import java.util.ArrayList; import java.util.List; import java.util.Properties; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.apache.commons.lang.StringUtils; import org.entando.entando.aps.system.services.api.IApiErrorCodes; import org.entando.entando.aps.system.services.api.IApiExportable; 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.LinkedListItem; import org.entando.entando.aps.system.services.api.model.StringApiResponse; import org.entando.entando.aps.system.services.api.server.IResponseBuilder; import org.entando.entando.aps.system.services.guifragment.GuiFragment; import org.entando.entando.aps.system.services.guifragment.IGuiFragmentManager; import org.entando.entando.aps.system.services.guifragment.api.JAXBGuiFragment; import org.entando.entando.aps.system.services.widgettype.IWidgetTypeManager; import org.entando.entando.aps.system.services.widgettype.WidgetType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author E.Santoboni */ public class ApiWidgetTypeInterface implements IApiExportable { private static final Logger _logger = LoggerFactory.getLogger(ApiWidgetTypeInterface.class); public List<LinkedListItem> getWidgetTypes(Properties properties) throws Throwable { List<LinkedListItem> list = new ArrayList<LinkedListItem>(); try { List<WidgetType> types = this.getWidgetTypeManager().getWidgetTypes(); for (int i = 0; i < types.size(); i++) { WidgetType widgetType = types.get(i); String url = this.getApiResourceUrl(widgetType, properties.getProperty(SystemConstants.API_APPLICATION_BASE_URL_PARAMETER), properties.getProperty(SystemConstants.API_LANG_CODE_PARAMETER), (MediaType) properties.get(SystemConstants.API_PRODUCES_MEDIA_TYPE_PARAMETER)); LinkedListItem item = new LinkedListItem(); item.setCode(widgetType.getCode()); item.setUrl(url); list.add(item); } } catch (Throwable t) { _logger.error("Error extracting list of widget types", t); throw t; } return list; } public JAXBWidgetType getWidgetType(Properties properties) throws ApiException, Throwable { String widgetTypeCode = properties.getProperty("code"); JAXBWidgetType jaxbWidgetType = null; try { WidgetType widgetType = this.getWidgetTypeManager().getWidgetType(widgetTypeCode); if (null == widgetType) { throw new ApiException(IApiErrorCodes.API_VALIDATION_ERROR, "WidgetType with code '" + widgetTypeCode + "' does not exist", Response.Status.CONFLICT); } GuiFragment singleGuiFragment = null; List<GuiFragment> fragments = new ArrayList<GuiFragment>(); if (!widgetType.isLogic()) { singleGuiFragment = this.getGuiFragmentManager().getUniqueGuiFragmentByWidgetType(widgetTypeCode); } else { List<String> fragmentCodes = this.getGuiFragmentManager().getGuiFragmentCodesByWidgetType(widgetTypeCode); if (null != fragmentCodes) { for (int i = 0; i < fragmentCodes.size(); i++) { String fragmentCode = fragmentCodes.get(i); GuiFragment fragment = this.getGuiFragmentManager().getGuiFragment(fragmentCode); if (null != fragment) { fragments.add(fragment); } } } } jaxbWidgetType = new JAXBWidgetType(widgetType, singleGuiFragment, fragments); } catch (ApiException ae) { throw ae; } catch (Throwable t) { _logger.error("Error creating widget type - code '{}'", widgetTypeCode, t); throw t; } return jaxbWidgetType; } public void addWidgetType(JAXBWidgetType jaxbWidgetType) throws ApiException, Throwable { List<GuiFragment> addedFragments = new ArrayList<GuiFragment>(); List<GuiFragment> updatedFragments = new ArrayList<GuiFragment>(); try { WidgetType widgetType = this.getWidgetTypeManager().getWidgetType(jaxbWidgetType.getCode()); if (null != widgetType) { throw new ApiException(IApiErrorCodes.API_VALIDATION_ERROR, "WidgetType with code " + jaxbWidgetType.getCode() + " already exists", Response.Status.CONFLICT); } widgetType = jaxbWidgetType.getNewWidgetType(this.getWidgetTypeManager()); if (!widgetType.isLogic() && StringUtils.isBlank(jaxbWidgetType.getGui())) { throw new ApiException(IApiErrorCodes.API_VALIDATION_ERROR, "Gui is mandatory", Response.Status.CONFLICT); } if (widgetType.isLogic() && (StringUtils.isNotBlank(jaxbWidgetType.getGui()) || (null != jaxbWidgetType.getFragments() && jaxbWidgetType.getFragments().size() > 0))) { throw new ApiException(IApiErrorCodes.API_VALIDATION_ERROR, "Fragment mustn't be added on the new logic widget type", Response.Status.CONFLICT); } if (widgetType.isLogic() && this.isInternalServletWidget(widgetType.getParentType().getCode())) { throw new ApiException(IApiErrorCodes.API_VALIDATION_ERROR, "Logic type with parent 'Internal Servlet' widget mustn't be added", Response.Status.CONFLICT); } this.getWidgetTypeManager().addWidgetType(widgetType); if (!widgetType.isLogic()) { this.checkAndSaveFragment(widgetType, jaxbWidgetType, true, null, addedFragments, updatedFragments); } } catch (ApiException ae) { this.revertPreviousObject(null, addedFragments, updatedFragments); throw ae; } catch (Throwable t) { this.revertPreviousObject(null, addedFragments, updatedFragments); this.getWidgetTypeManager().deleteWidgetType(jaxbWidgetType.getCode()); _logger.error("Error adding new widget type", t); throw t; } } public StringApiResponse updateWidgetType(JAXBWidgetType jaxbWidgetType) throws ApiException, Throwable { StringApiResponse response = new StringApiResponse(); WidgetType widgetTypeToUpdate = null; List<GuiFragment> addedFragments = new ArrayList<GuiFragment>(); List<GuiFragment> updatedFragments = new ArrayList<GuiFragment>(); try { widgetTypeToUpdate = this.getWidgetTypeManager().getWidgetType(jaxbWidgetType.getCode()); if (null == widgetTypeToUpdate) { throw new ApiException(IApiErrorCodes.API_VALIDATION_ERROR, "WidgetType with code " + jaxbWidgetType.getCode() + " does not exists", Response.Status.CONFLICT); } WidgetType widgetType = jaxbWidgetType.getModifiedWidgetType(this.getWidgetTypeManager()); this.checkAndSaveFragment(widgetType, jaxbWidgetType, false, response, addedFragments, updatedFragments); this.getWidgetTypeManager().updateWidgetType(widgetType.getCode(), widgetType.getTitles(), widgetType.getConfig(), widgetType.getMainGroup()); response.setResult(IResponseBuilder.SUCCESS, null); } catch (ApiException ae) { this.revertPreviousObject(widgetTypeToUpdate, addedFragments, updatedFragments); throw ae; } catch (Throwable t) { this.revertPreviousObject(widgetTypeToUpdate, addedFragments, updatedFragments); _logger.error("Error updating widget type", t); throw t; } return response; } private void revertPreviousObject(WidgetType widgetTypeToUpdate, List<GuiFragment> addedFragments, List<GuiFragment> updatedFragments) throws Throwable { if (null != widgetTypeToUpdate) { this.getWidgetTypeManager().updateWidgetType(widgetTypeToUpdate.getCode(), widgetTypeToUpdate.getTitles(), widgetTypeToUpdate.getConfig(), widgetTypeToUpdate.getMainGroup()); } for (int i = 0; i < addedFragments.size(); i++) { GuiFragment guiFragment = addedFragments.get(i); this.getGuiFragmentManager().deleteGuiFragment(guiFragment.getCode()); } for (int i = 0; i < updatedFragments.size(); i++) { GuiFragment guiFragment = updatedFragments.get(i); this.getGuiFragmentManager().updateGuiFragment(guiFragment); } } protected void checkAndSaveFragment(WidgetType type, JAXBWidgetType jaxbWidgetType, boolean isAdd, StringApiResponse response, List<GuiFragment> addedFragments, List<GuiFragment> updatedFragment) throws Throwable { try { if (!type.isLogic() && !this.isInternalServletWidget(type.getCode())) { GuiFragment guiFragment = this.getGuiFragmentManager().getUniqueGuiFragmentByWidgetType(type.getCode()); if (StringUtils.isNotBlank(jaxbWidgetType.getGui())) { if (null == guiFragment) { guiFragment = new GuiFragment(); String code = this.extractUniqueGuiFragmentCode(type.getCode()); guiFragment.setCode(code); guiFragment.setPluginCode(type.getPluginCode()); guiFragment.setGui(jaxbWidgetType.getGui()); guiFragment.setWidgetTypeCode(type.getCode()); addedFragments.add(guiFragment); this.getGuiFragmentManager().addGuiFragment(guiFragment); } else if (!isAdd) { GuiFragment clone = guiFragment.clone(); updatedFragment.add(guiFragment); clone.setGui(jaxbWidgetType.getGui()); this.getGuiFragmentManager().updateGuiFragment(clone); } } else { if (null != guiFragment && !isAdd) { if (StringUtils.isNotBlank(guiFragment.getDefaultGui())) { GuiFragment clone = guiFragment.clone(); updatedFragment.add(guiFragment); clone.setGui(null); this.getGuiFragmentManager().updateGuiFragment(clone); } else { //nothing to do... //this.getGuiFragmentManager().deleteGuiFragment(guiFragment.getCode()); } } } } else if (type.isLogic() && !isAdd) { boolean isInternalServlet = this.isInternalServletWidget(type.getParentType().getCode()); if (!isInternalServlet && (null != jaxbWidgetType.getFragments() && jaxbWidgetType.getFragments().size() > 0)) { if (null != response) { ApiError error = new ApiError(IApiErrorCodes.API_VALIDATION_ERROR, "Fragments mustn't be updated on a 'not internal servlet' logic widget type"); response.addError(error); } //throw new ApiException(IApiErrorCodes.API_VALIDATION_ERROR, "Fragments mustn't be updated on a 'not internal servlet' logic widget type", Response.Status.CONFLICT); } else { List<JAXBGuiFragment> fragments = jaxbWidgetType.getFragments(); if (null != fragments && fragments.size() > 0) { for (int i = 0; i < fragments.size(); i++) { JAXBGuiFragment jaxbGuiFragment = fragments.get(i); GuiFragment fragment = jaxbGuiFragment.getGuiFragment(); GuiFragment existingFragment = this.getGuiFragmentManager().getGuiFragment(fragment.getCode()); if (null != existingFragment) { if (StringUtils.isBlank(existingFragment.getDefaultGui()) && StringUtils.isBlank(jaxbWidgetType.getGui())) { ApiError error = new ApiError(IApiErrorCodes.API_VALIDATION_ERROR, "one between A and B must be valued on fragment '" + existingFragment.getCode() + "'"); response.addError(error); continue; } GuiFragment clone = existingFragment.clone(); updatedFragment.add(existingFragment); clone.setGui(jaxbGuiFragment.getGui()); } else { ApiError error = new ApiError(IApiErrorCodes.API_VALIDATION_ERROR, "Fragment '" + fragment.getCode() + "' does not exists"); response.addError(error); } } } } } } catch (Throwable t) { _logger.error("error checking and saving fragment", t); throw new ApsSystemException("error checking and saving fragment", t); } } // duplicated code protected String extractUniqueGuiFragmentCode(String widgetTypeCode) throws ApsSystemException { String uniqueCode = widgetTypeCode; if (null != this.getGuiFragmentManager().getGuiFragment(uniqueCode)) { int index = 0; String currentCode = null; do { index++; currentCode = uniqueCode + "_" + index; } while (null != this.getGuiFragmentManager().getGuiFragment(currentCode)); uniqueCode = currentCode; } return uniqueCode; } public void deleteWidgetType(Properties properties) throws ApiException, Throwable { String code = properties.getProperty("code"); try { WidgetType widgetType = this.getWidgetTypeManager().getWidgetType(code); if (null == widgetType) { throw new ApiException(IApiErrorCodes.API_VALIDATION_ERROR, "Widget Type with code " + code + " does not exists", Response.Status.CONFLICT); } if (widgetType.isLocked()) { throw new ApiException(IApiErrorCodes.API_VALIDATION_ERROR, "Widget Type '" + code + "' is locked", Response.Status.CONFLICT); } List<IPage> referencedPages = this.getPageManager().getWidgetUtilizers(code); if (null != referencedPages && !referencedPages.isEmpty()) { throw new ApiException(IApiErrorCodes.API_VALIDATION_ERROR, "Widget Type '" + code + "' is published into some pages", Response.Status.CONFLICT); } this.getWidgetTypeManager().deleteWidgetType(code); } catch (ApiException ae) { throw ae; } catch (Throwable t) { _logger.error("Error deleting widget type throw api", t); throw t; } } @Override public String getApiResourceUrl(Object object, String applicationBaseUrl, String langCode, MediaType mediaType) { if (!(object instanceof WidgetType) || null == applicationBaseUrl || null == langCode) { return null; } WidgetType widgetType = (WidgetType) object; StringBuilder stringBuilder = new StringBuilder(applicationBaseUrl); stringBuilder.append("api/rs/").append(langCode).append("/core/widgetType");//?code=").append(widgetType.getCode()); if (null == mediaType || mediaType.equals(MediaType.APPLICATION_XML_TYPE)) { stringBuilder.append(".xml"); } else { stringBuilder.append(".json"); } stringBuilder.append("?code=").append(widgetType.getCode()); return stringBuilder.toString(); } public boolean isInternalServletWidget(String widgetTypeCode) { return this.getInternalServletWidgetCode().equals(widgetTypeCode); } protected String getInternalServletWidgetCode() { return _internalServletWidgetCode; } public void setInternalServletWidgetCode(String internalServletWidgetCode) { this._internalServletWidgetCode = internalServletWidgetCode; } protected IPageManager getPageManager() { return _pageManager; } public void setPageManager(IPageManager pageManager) { this._pageManager = pageManager; } protected IWidgetTypeManager getWidgetTypeManager() { return _widgetTypeManager; } public void setWidgetTypeManager(IWidgetTypeManager widgetTypeManager) { this._widgetTypeManager = widgetTypeManager; } protected IGuiFragmentManager getGuiFragmentManager() { return _guiFragmentManager; } public void setGuiFragmentManager(IGuiFragmentManager guiFragmentManager) { this._guiFragmentManager = guiFragmentManager; } private String _internalServletWidgetCode; private IPageManager _pageManager; private IWidgetTypeManager _widgetTypeManager; private IGuiFragmentManager _guiFragmentManager; }