Java tutorial
/******************************************************************************* * Crafter Studio Web-content authoring solution * Copyright (C) 2007-2013 Crafter Software Corporation. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. ******************************************************************************/ package org.craftercms.cstudio.alfresco.dm.script; import javolution.util.FastList; import net.sf.json.JSONArray; import net.sf.json.JSONException; import net.sf.json.JSONObject; import org.alfresco.repo.processor.BaseProcessorExtension; import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.service.cmr.model.FileInfo; import org.alfresco.service.cmr.repository.NodeRef; import org.apache.commons.lang.StringUtils; import org.craftercms.cstudio.alfresco.constant.CStudioConstants; import org.craftercms.cstudio.alfresco.constant.CStudioContentModel; import org.craftercms.cstudio.alfresco.dm.constant.DmConstants; import org.craftercms.cstudio.alfresco.dm.service.api.*; import org.craftercms.cstudio.alfresco.dm.service.impl.DependencyRules; import org.craftercms.cstudio.alfresco.dm.to.DmContentItemTO; import org.craftercms.cstudio.alfresco.dm.to.DmDependencyTO; import org.craftercms.cstudio.alfresco.dm.to.DmError; import org.craftercms.cstudio.alfresco.dm.to.DmPathTO; import org.craftercms.cstudio.alfresco.dm.util.DmContentItemComparator; import org.craftercms.cstudio.alfresco.dm.util.DmUtils; import org.craftercms.cstudio.alfresco.dm.util.ThreadLocalContainer; import org.craftercms.cstudio.alfresco.dm.workflow.MultiChannelPublishingContext; import org.craftercms.cstudio.alfresco.dm.workflow.RequestContext; import org.craftercms.cstudio.alfresco.dm.workflow.RequestContextBuilder; import org.craftercms.cstudio.alfresco.service.ServicesManager; import org.craftercms.cstudio.alfresco.service.api.*; import org.craftercms.cstudio.alfresco.service.exception.ServiceException; import org.craftercms.cstudio.alfresco.to.PublishingChannelConfigTO; import org.craftercms.cstudio.alfresco.to.ResultTO; import org.craftercms.cstudio.alfresco.util.ContentFormatUtils; import org.craftercms.cstudio.alfresco.util.TransactionHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.Serializable; import java.text.SimpleDateFormat; import java.util.*; /** * A wrapper class of WorkflowService that exposes WCM WorkflowService in * Alfresco javascript API * * @author hyanghee * @author Dejan Brkic */ public class DmWorkflowServiceScript extends BaseProcessorExtension { private static final Logger logger = LoggerFactory.getLogger(DmWorkflowServiceScript.class); protected String JSON_KEY_ASSETS = "assets"; protected String JSON_KEY_CHILDREN = "children"; protected String JSON_KEY_COMPONENTS = "components"; protected String JSON_KEY_DELETED = "deleted"; protected String JSON_KEY_DOCUMENTS = "documents"; protected String JSON_KEY_DELETED_ITEMS = "deletedItems"; protected String JSON_KEY_IS_NOW = "now"; protected String JSON_KEY_ITEMS = "items"; protected String JSON_KEY_REASON = "reason"; protected String JSON_KEY_SCHEDULED_DATE = "scheduledDate"; protected String JSON_KEY_SUBMITTED_FOR_DELETION = "submittedForDeletion"; protected String JSON_KEY_SUBMITTED = "submitted"; protected String JSON_KEY_IN_PROGRESS = "inProgress"; protected String JSON_KEY_IN_REFERENCE = "reference"; protected String JSON_KEY_SEND_EMAIL = "sendEmail"; protected String JSON_KEY_URI = "uri"; protected String JSON_KEY_USER = "user"; protected String JSON_KEY_RENDERING_TEMPLATES = "renderingTemplates"; protected String JSON_KEY_LEVEL_DESCRIPTORS = "levelDescriptors"; protected String JSON_KEY_PUBLISH_CHANNEL = "publishChannel"; protected String JSON_KEY_STATUS_CHANNEL = "channels"; protected String JSON_KEY_STATUS_SET = "status"; protected String JSON_KEY_STATUS_MESSAGE = "message"; protected String JSON_KEY_SUBMISSION_COMMENT = "submissionComment"; protected ServicesManager _servicesManager; public ServicesManager getServicesManager() { return _servicesManager; } public void setServicesManager(ServicesManager servicesManager) { this._servicesManager = servicesManager; } private boolean deploymentEngine; public void setDeploymentEngine(boolean deploymentEngine) { this.deploymentEngine = deploymentEngine; } protected enum Operation { GOLIVE, DELETE } /** * submit items to go live queue by creating associations between the top * level items and their children and dependencies and add * cstudio-core-workflow:submitted aspect * * @param site * @param sub * @param request * @return call result * @throws org.craftercms.cstudio.alfresco.service.exception.ServiceException * */ public ResultTO submitToGoLive(String site, String sub, String request) throws ServiceException { return submitForApproval(site, sub, request, false); } public ResultTO submitForApproval(final String site, final String sub, final String request, final boolean delete) throws ServiceException { DmTransactionService dmTransactionService = getServicesManager().getService(DmTransactionService.class); TransactionHelper transactionHelper = dmTransactionService.getTransactionHelper(); ResultTO to = null; try { to = transactionHelper .doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<ResultTO>() { @Override public ResultTO execute() throws Throwable { return _submit(site, sub, request, delete); } }); return to; } catch (ServiceException e) { if (logger.isErrorEnabled()) { logger.error("Error during submit", e); } throw e; } } protected ResultTO _submit(String site, String sub, String request, boolean delete) { PersistenceManagerService persistenceManagerService = getServicesManager() .getService(PersistenceManagerService.class); ServicesConfig servicesConfig = getServicesManager().getService(ServicesConfig.class); String submittedBy = persistenceManagerService.getCurrentUserName(); RequestContext requestContext = RequestContextBuilder.buildSubmitContext(site, servicesConfig, submittedBy); ResultTO result = new ResultTO(); DmWorkflowService dmWorkflowService = getServicesManager().getService(DmWorkflowService.class); NotificationService notificationService = getServicesManager().getService(NotificationService.class); try { SimpleDateFormat format = new SimpleDateFormat(CStudioConstants.DATE_PATTERN_WORKFLOW); JSONObject requestObject = JSONObject.fromObject(request); boolean isNow = (requestObject.containsKey(JSON_KEY_IS_NOW)) ? requestObject.getBoolean(JSON_KEY_IS_NOW) : false; Date scheduledDate = null; if (!isNow) { scheduledDate = (requestObject.containsKey(JSON_KEY_SCHEDULED_DATE)) ? getScheduledDate(site, format, requestObject.getString(JSON_KEY_SCHEDULED_DATE)) : null; } boolean sendEmail = (requestObject.containsKey(JSON_KEY_SEND_EMAIL)) ? requestObject.getBoolean(JSON_KEY_SEND_EMAIL) : false; String submissionComment = (requestObject != null && requestObject.containsKey(JSON_KEY_SUBMISSION_COMMENT)) ? requestObject.getString(JSON_KEY_SUBMISSION_COMMENT) : null; // TODO: check scheduled date to make sure it is not null when isNow // = true and also it is not past JSONArray items = requestObject.getJSONArray(JSON_KEY_ITEMS); int length = items.size(); String schDate = null; if (requestObject.containsKey(JSON_KEY_SCHEDULED_DATE)) { schDate = requestObject.getString(JSON_KEY_SCHEDULED_DATE); } List<String> itemsToDelete = new FastList<String>(length); if (length > 0) { List<DmDependencyTO> submittedItems = new ArrayList<DmDependencyTO>(); for (int index = 0; index < length; index++) { JSONObject item = items.getJSONObject(index); DmDependencyTO submittedItem = getSubmittedItem(site, item, format, schDate); String user = item.getString(JSON_KEY_USER); submittedItems.add(submittedItem); if (delete) { submittedItem.setSubmittedForDeletion(true); } } List<String> submittedPaths = new FastList<String>(); String siteRootPath = servicesConfig.getRepositoryRootPath(site); for (DmDependencyTO goLiveItem : submittedItems) { String fullPath = siteRootPath + goLiveItem.getUri(); submittedPaths.add(fullPath); persistenceManagerService.setSystemProcessing(fullPath, true); DependencyRules rule = new DependencyRules(site, getServicesManager()); Set<DmDependencyTO> depSet = rule.applySubmitRule(goLiveItem); for (DmDependencyTO dep : depSet) { String depPath = siteRootPath + dep.getUri(); submittedPaths.add(depPath); persistenceManagerService.setSystemProcessing(depPath, true); } } List<DmError> errors = dmWorkflowService.submitToGoLive(submittedItems, scheduledDate, sendEmail, delete, requestContext, submissionComment); result.setSuccess(true); result.setMessage(notificationService.getCompleteMessage(site, NotificationService.COMPLETE_SUBMIT_TO_GO_LIVE)); for (String fullPath : submittedPaths) { persistenceManagerService.setSystemProcessing(fullPath, false); } } } catch (Exception e) { result.setSuccess(false); result.setMessage(e.getMessage()); if (logger.isErrorEnabled()) { logger.error(e.getMessage(), e); } } return result; } /** * parse the given date * * @param site * @param format * @param dateStr * @return date */ public Date getScheduledDate(String site, SimpleDateFormat format, String dateStr) { ServicesConfig servicesConfig = getServicesManager().getService(ServicesConfig.class); return ContentFormatUtils.parseDate(format, dateStr, servicesConfig.getDefaultTimezone(site)); } protected String getPublishChannel(JSONObject jsonPublishChannel) { return jsonPublishChannel.containsKey("name") ? jsonPublishChannel.getString("name") : null; } protected List<String> getStatusUpdateChannels(JSONArray jsonStatusChannels) { List<String> toRet = new FastList<String>(); Iterator<JSONObject> iter = jsonStatusChannels.iterator(); while (iter.hasNext()) { JSONObject channel = iter.next(); toRet.add(channel.getString("name")); } return toRet; } /** * get a submitted item from a JSON item * * @param site * @param item * @param format * @return * @throws net.sf.json.JSONException */ protected DmDependencyTO getSubmittedItem(String site, JSONObject item, SimpleDateFormat format, String globalSchDate) throws JSONException { PersistenceManagerService persistenceManagerService = getServicesManager() .getService(PersistenceManagerService.class); DmDependencyTO submittedItem = new DmDependencyTO(); String uri = item.getString(JSON_KEY_URI); submittedItem.setUri(uri); boolean deleted = (item.containsKey(JSON_KEY_DELETED)) ? item.getBoolean(JSON_KEY_DELETED) : false; submittedItem.setDeleted(deleted); boolean isNow = (item.containsKey(JSON_KEY_IS_NOW)) ? item.getBoolean(JSON_KEY_IS_NOW) : false; submittedItem.setNow(isNow); boolean submittedForDeletion = (item.containsKey(JSON_KEY_SUBMITTED_FOR_DELETION)) ? item.getBoolean(JSON_KEY_SUBMITTED_FOR_DELETION) : false; boolean submitted = (item.containsKey(JSON_KEY_SUBMITTED)) ? item.getBoolean(JSON_KEY_SUBMITTED) : false; boolean inProgress = (item.containsKey(JSON_KEY_IN_PROGRESS)) ? item.getBoolean(JSON_KEY_IN_PROGRESS) : false; boolean isReference = (item.containsKey(JSON_KEY_IN_REFERENCE)) ? item.getBoolean(JSON_KEY_IN_REFERENCE) : false; submittedItem.setReference(isReference); // boolean submittedForDeletion = // (item.containsKey(JSON_KEY_SUBMITTED_FOR_DELETION)) ? // item.getBoolean(JSON_KEY_SUBMITTED_FOR_DELETION) : false; submittedItem.setSubmittedForDeletion(submittedForDeletion); submittedItem.setSubmitted(submitted); submittedItem.setInProgress(inProgress); // TODO: check scheduled date to make sure it is not null when isNow = // true and also it is not past Date scheduledDate = null; if (globalSchDate != null && !StringUtils.isEmpty(globalSchDate)) { scheduledDate = getScheduledDate(site, format, globalSchDate); } else { if (item.containsKey(JSON_KEY_SCHEDULED_DATE)) { String dateStr = item.getString(JSON_KEY_SCHEDULED_DATE); if (!StringUtils.isEmpty(dateStr)) { scheduledDate = getScheduledDate(site, format, dateStr); } } } if (scheduledDate == null && isNow == false) { submittedItem.setNow(true); } submittedItem.setScheduledDate(scheduledDate); JSONArray components = (item.containsKey(JSON_KEY_COMPONENTS)) ? item.getJSONArray(JSON_KEY_COMPONENTS) : null; List<DmDependencyTO> submittedComponents = getSubmittedItems(site, components, format, globalSchDate); submittedItem.setComponents(submittedComponents); JSONArray documents = (item.containsKey(JSON_KEY_DOCUMENTS)) ? item.getJSONArray(JSON_KEY_DOCUMENTS) : null; List<DmDependencyTO> submittedDocuments = getSubmittedItems(site, documents, format, globalSchDate); submittedItem.setDocuments(submittedDocuments); JSONArray assets = (item.containsKey(JSON_KEY_ASSETS)) ? item.getJSONArray(JSON_KEY_ASSETS) : null; List<DmDependencyTO> submittedAssets = getSubmittedItems(site, assets, format, globalSchDate); submittedItem.setAssets(submittedAssets); JSONArray templates = (item.containsKey(JSON_KEY_RENDERING_TEMPLATES)) ? item.getJSONArray(JSON_KEY_RENDERING_TEMPLATES) : null; List<DmDependencyTO> submittedTemplates = getSubmittedItems(site, templates, format, globalSchDate); submittedItem.setRenderingTemplates(submittedTemplates); JSONArray deletedItems = (item.containsKey(JSON_KEY_DELETED_ITEMS)) ? item.getJSONArray(JSON_KEY_DELETED_ITEMS) : null; List<DmDependencyTO> deletes = getSubmittedItems(site, deletedItems, format, globalSchDate); submittedItem.setDeletedItems(deletes); JSONArray children = (item.containsKey(JSON_KEY_CHILDREN)) ? item.getJSONArray(JSON_KEY_CHILDREN) : null; List<DmDependencyTO> submittedChidren = getSubmittedItems(site, children, format, globalSchDate); submittedItem.setChildren(submittedChidren); DmDependencyService dmDependencyService = getServicesManager().getService(DmDependencyService.class); if (uri.endsWith(DmConstants.XML_PATTERN)) { /** * Get dependent pages */ DmDependencyTO dmDependencyTo = dmDependencyService.getDependencies(site, null, item.getString(JSON_KEY_URI), false, true); List<DmDependencyTO> dependentPages = dmDependencyTo.getPages(); submittedItem.setPages(dependentPages); /** * Get Dependent Documents */ if (submittedItem.getDocuments() == null) { List<DmDependencyTO> dependentDocuments = dmDependencyTo.getDocuments(); submittedItem.setDocuments(dependentDocuments); } /** * get sendEmail property if it is there */ try { String fullPath = getFullPath(site, submittedItem); // PropertyValue sendEmailValue = // _avmService.getNodeProperty(-1, fullPath, // CStudioContentModel.PROP_WEB_WF_SEND_EMAIL); Serializable sendEmailValue = persistenceManagerService.getProperty( persistenceManagerService.getNodeRef(fullPath), CStudioContentModel.PROP_WEB_WF_SEND_EMAIL); boolean sendEmail = (sendEmailValue != null) ? Boolean.getBoolean(sendEmailValue.toString()) : false; submittedItem.setSendEmail(sendEmail); String user = item.getString(JSON_KEY_USER); submittedItem.setSubmittedBy(user); } catch (Exception e) { e.printStackTrace(); // To change body of catch statement use // File | Settings | File Templates. } } return submittedItem; } /** * get submitted items from JSON request * * @param site * @param items * @param format * @return submitted items * @throws JSONException */ protected List<DmDependencyTO> getSubmittedItems(String site, JSONArray items, SimpleDateFormat format, String schDate) throws JSONException { if (items != null) { int length = items.size(); if (length > 0) { List<DmDependencyTO> submittedItems = new FastList<DmDependencyTO>(); for (int index = 0; index < length; index++) { JSONObject item = items.getJSONObject(index); DmDependencyTO submittedItem = getSubmittedItem(site, item, format, schDate); submittedItems.add(submittedItem); } return submittedItems; } } return null; } protected String getFullPath(String site, DmDependencyTO submittedItem) { DmContentService dmContentService = getServicesManager().getService(DmContentService.class); String uri = submittedItem.getUri(); if (submittedItem.isDeleted()) { // if deleted, replace with the folder path uri = uri.replace("/" + DmConstants.INDEX_FILE, ""); } String fullPath = dmContentService.getContentFullPath(site, uri); return fullPath; } /** * get go live items waiting for approval * * @param site * @param sub * @param sort * @param ascending * @param inProgressOnly * @return go live items in JSON * @throws ServiceException */ public String getInProgressItems(String site, String sub, String sort, String ascending, String inProgressOnly) throws ServiceException { boolean asc = (StringUtils.isEmpty(ascending)) ? false : ascending.equalsIgnoreCase("true"); boolean inProgress = (inProgressOnly != null && inProgressOnly.equals("true")) ? true : false; DmContentItemComparator comparator = new DmContentItemComparator(sort, asc, true, true); DmWorkflowService dmWorkflowService = getServicesManager().getService(DmWorkflowService.class); List<DmContentItemTO> items = dmWorkflowService.getInProgressItems(site, sub, comparator, inProgress); JSONObject jsonObject = new JSONObject(); int total = 0; if (items != null) { for (DmContentItemTO item : items) { total += item.getNumOfChildren(); } } jsonObject.put(CStudioConstants.PROPERTY_TOTAL, total); jsonObject.put(CStudioConstants.PROPERTY_SORTED_BY, sort); jsonObject.put(CStudioConstants.PROPERTY_SORT_ASCENDING, String.valueOf(asc)); jsonObject.put(CStudioConstants.PROPERTY_DOCUMENTS, items); return jsonObject.toString(); } /** * get go live items waiting for approval * * @param site * @param sub * @param sort * @param ascending * @return go live items in JSON * @throws ServiceException */ public String getGoLiveItems(final String site, final String sub, final String sort, final String ascending) throws ServiceException { DmTransactionService dmTransactionService = getServicesManager().getService(DmTransactionService.class); TransactionHelper transactionHelper = dmTransactionService.getTransactionHelper(); try { return transactionHelper .doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<String>() { @Override public String execute() throws Throwable { try { boolean asc = (StringUtils.isEmpty(ascending)) ? false : ascending.equalsIgnoreCase("true"); DmContentItemComparator comparator = new DmContentItemComparator(sort, asc, false, false); DmWorkflowService dmWorkflowService = getServicesManager() .getService(DmWorkflowService.class); List<DmContentItemTO> items = dmWorkflowService.getGoLiveItems(site, sub, comparator); JSONObject jsonObject = new JSONObject(); int total = 0; if (items != null) { for (DmContentItemTO item : items) { total += item.getNumOfChildren(); } } jsonObject.put(CStudioConstants.PROPERTY_TOTAL, total); jsonObject.put(CStudioConstants.PROPERTY_SORTED_BY, sort); jsonObject.put(CStudioConstants.PROPERTY_SORT_ASCENDING, String.valueOf(asc)); jsonObject.put(CStudioConstants.PROPERTY_DOCUMENTS, items); return jsonObject.toString(); } catch (ServiceException e) { if (logger.isErrorEnabled()) { logger.error("Error fetching go live queue", e); } throw e; } catch (RuntimeException e) { if (logger.isErrorEnabled()) { logger.error("Error fetching go live queue", e); } throw e; } } }); } catch (ServiceException e) { if (logger.isErrorEnabled()) { logger.error("Error fetching go live", e); } throw e; } catch (RuntimeException e) { if (logger.isErrorEnabled()) { logger.error("Error fetching go live", e); } throw e; } } /** * approve workflows and schedule them as specified in the request * * @param site * @param sub * @param request * @return call result * @throws ServiceException */ public ResultTO goLive(final String site, final String sub, final String request) throws ServiceException { GeneralLockService generalLockService = getServicesManager().getService(GeneralLockService.class); String lockKey = DmConstants.PUBLISHING_LOCK_KEY.replace("{SITE}", site.toUpperCase()); generalLockService.lock(lockKey); try { DmTransactionService dmTransactionService = getServicesManager().getService(DmTransactionService.class); TransactionHelper transactionHelper = dmTransactionService.getTransactionHelper(); try { return approve(site, sub, request, Operation.GOLIVE); } catch (RuntimeException e) { if (logger.isErrorEnabled()) { logger.error("error making go live", e); } throw e; } } catch (RuntimeException e) { throw e; } finally { generalLockService.unlock(lockKey); } } /** * approve workflows and schedule them as specified in the request * * @param site * @param sub * @param request * @return call result * @throws ServiceException */ public ResultTO approve(String site, String sub, String request, Operation operation) { PersistenceManagerService persistenceManagerService = getServicesManager() .getService(PersistenceManagerService.class); String approver = persistenceManagerService.getCurrentUserName(); ResultTO result = new ResultTO(); try { JSONObject requestObject = JSONObject.fromObject(request); JSONArray items = requestObject.getJSONArray(JSON_KEY_ITEMS); String scheduledDate = null; if (requestObject.containsKey(JSON_KEY_SCHEDULED_DATE)) { scheduledDate = requestObject.getString(JSON_KEY_SCHEDULED_DATE); } boolean isNow = (requestObject.containsKey(JSON_KEY_IS_NOW)) ? requestObject.getBoolean(JSON_KEY_IS_NOW) : false; String publishChannelGroupName = (requestObject.containsKey(JSON_KEY_PUBLISH_CHANNEL)) ? getPublishChannel(requestObject.getJSONObject(JSON_KEY_PUBLISH_CHANNEL)) : null; JSONObject jsonObjectStatus = requestObject.getJSONObject(JSON_KEY_STATUS_SET); // List<String> statusUpdateChannelNames = (jsonObjectStatus != null // && jsonObjectStatus.containsKey(JSON_KEY_STATUS_CHANNEL)) ? // getStatusUpdateChannels(jsonObjectStatus.getJSONArray(JSON_KEY_STATUS_CHANNEL)) // : (new FastList<String>()); String statusMessage = (jsonObjectStatus != null && jsonObjectStatus.containsKey(JSON_KEY_STATUS_MESSAGE)) ? jsonObjectStatus.getString(JSON_KEY_STATUS_MESSAGE) : null; String submissionComment = (requestObject != null && requestObject.containsKey(JSON_KEY_SUBMISSION_COMMENT)) ? requestObject.getString(JSON_KEY_SUBMISSION_COMMENT) : "Test Go Live"; MultiChannelPublishingContext mcpContext = new MultiChannelPublishingContext(publishChannelGroupName, statusMessage, submissionComment); DmPublishService publishingService = getServicesManager().getService(DmPublishService.class); if (operation != Operation.DELETE && !publishingService.hasChannelsConfigure(site, mcpContext)) { ResultTO toReturn = new ResultTO(); List<PublishingChannelConfigTO> channelsList = getServicesManager().getService(SiteService.class) .getPublishingChannelGroupConfigs(site).get(mcpContext.getPublishingChannelGroup()) .getChannels(); String channels = StringUtils.join(channelsList, " "); toReturn.setMessage(" Specified target '" + channels + "' was not found. Please check if an endpoint or channel with name '" + channels + "' exists in site configuration"); toReturn.setSuccess(false); toReturn.setInvalidateCache(false); return toReturn; } int length = items.size(); if (length == 0) { throw new ServiceException("No items provided to go live."); } String responseMessageKey = null; SimpleDateFormat format = new SimpleDateFormat(CStudioConstants.DATE_PATTERN_WORKFLOW); List<DmDependencyTO> submittedItems = new FastList<DmDependencyTO>(); for (int index = 0; index < length; index++) { JSONObject item = items.getJSONObject(index); DmDependencyTO submittedItem = getSubmittedItem(site, item, format, scheduledDate); List<DmDependencyTO> submitForDeleteChildren = removeSubmitToDeleteChildrenForGoLive(submittedItem, operation); if (submittedItem.isReference()) { submittedItem.setReference(false); } submittedItems.add(submittedItem); submittedItems.addAll(submitForDeleteChildren); } // AuthenticationUtil.setFullyAuthenticatedUser(approver); ServicesConfig servicesConfig = getServicesManager().getService(ServicesConfig.class); DmRenameService dmRenameService = getServicesManager().getService(DmRenameService.class); DmWorkflowService dmWorkflowService = getServicesManager().getService(DmWorkflowService.class); switch (operation) { case GOLIVE: if (scheduledDate != null && isNow == false) { responseMessageKey = NotificationService.COMPLETE_SCHEDULE_GO_LIVE; } else { responseMessageKey = NotificationService.COMPLETE_GO_LIVE; } List<DmDependencyTO> submitToDeleteItems = new FastList<DmDependencyTO>(); List<DmDependencyTO> goLiveItems = new FastList<DmDependencyTO>(); List<DmDependencyTO> renameItems = new FastList<DmDependencyTO>(); for (DmDependencyTO item : submittedItems) { if (item.isSubmittedForDeletion()) { submitToDeleteItems.add(item); } else { if (!dmRenameService.isItemRenamed(site, item)) { goLiveItems.add(item); } else { renameItems.add(item); } } } if (!submitToDeleteItems.isEmpty()) { dmWorkflowService.doDelete(site, sub, submitToDeleteItems, approver); } if (!goLiveItems.isEmpty()) { List<DmDependencyTO> references = getRefAndChildOfDiffDateFromParent(site, goLiveItems, true); List<DmDependencyTO> children = getRefAndChildOfDiffDateFromParent(site, goLiveItems, false); goLiveItems.addAll(references); goLiveItems.addAll(children); List<String> goLivePaths = new FastList<String>(); for (DmDependencyTO goLiveItem : goLiveItems) { resolveSubmittedPaths(site, goLiveItem, goLivePaths); } List<String> nodeRefs = new FastList<String>(); for (String fullPath : goLivePaths) { NodeRef nr = persistenceManagerService.getNodeRef(fullPath); if (nr != null) { nodeRefs.add(nr.getId()); } } dmWorkflowService.goLive(site, sub, goLiveItems, approver, mcpContext); } if (!renameItems.isEmpty()) { List<String> renamePaths = new FastList<String>(); List<DmDependencyTO> renamedChildren = new FastList<DmDependencyTO>(); for (DmDependencyTO renameItem : renameItems) { renamedChildren.addAll(getChildrenForRenamedItem(site, renameItem)); String fullPath = servicesConfig.getRepositoryRootPath(site) + renameItem.getUri(); renamePaths.add(fullPath); persistenceManagerService.setSystemProcessing(fullPath, true); } for (DmDependencyTO renamedChild : renamedChildren) { String fullPath = servicesConfig.getRepositoryRootPath(site) + renamedChild.getUri(); renamePaths.add(fullPath); persistenceManagerService.setSystemProcessing(fullPath, true); } renameItems.addAll(renamedChildren); //Set proper information of all renameItems before send them to GoLive for (int i = 0; i < renameItems.size(); i++) { DmDependencyTO renamedItem = renameItems.get(i); if (renamedItem.getScheduledDate() != null && renamedItem.getScheduledDate().after(new Date())) { renamedItem.setNow(false); } else { renamedItem.setNow(true); } renameItems.set(i, renamedItem); } dmRenameService.goLive(site, sub, renameItems, approver, mcpContext); } break; case DELETE: responseMessageKey = NotificationService.COMPLETE_DELETE; List<String> deletePaths = new FastList<String>(); List<String> nodeRefs = new ArrayList<String>(); for (DmDependencyTO deletedItem : submittedItems) { String fullPath = servicesConfig.getRepositoryRootPath(site) + deletedItem.getUri(); //deletedItem.setScheduledDate(getScheduledDate(site, format, scheduledDate)); deletePaths.add(fullPath); NodeRef nodeRef = persistenceManagerService.getNodeRef(fullPath); if (nodeRef != null) { nodeRefs.add(nodeRef.getId()); } } dmWorkflowService.doDelete(site, sub, submittedItems, approver); } result.setSuccess(true); NotificationService notificationService = getServicesManager().getService(NotificationService.class); result.setMessage(notificationService.getCompleteMessage(site, responseMessageKey)); } catch (JSONException e) { if (logger.isErrorEnabled()) { logger.error("error performing operation " + operation + " " + e); } result.setSuccess(false); result.setMessage(e.getMessage()); } catch (ServiceException e) { if (logger.isErrorEnabled()) { logger.error("error performing operation " + operation + " " + e); } result.setSuccess(false); result.setMessage(e.getMessage()); } return result; } protected List<DmDependencyTO> getChildrenForRenamedItem(String site, DmDependencyTO renameItem) { ServicesConfig servicesConfig = getServicesManager().getService(ServicesConfig.class); PersistenceManagerService persistenceManagerService = getServicesManager() .getService(PersistenceManagerService.class); String siteRoot = servicesConfig.getRepositoryRootPath(site); List<DmDependencyTO> toRet = new FastList<DmDependencyTO>(); List<DmDependencyTO> children = renameItem.getChildren(); Date date = renameItem.getScheduledDate(); if (children != null) { Iterator<DmDependencyTO> childItr = children.iterator(); while (childItr.hasNext()) { DmDependencyTO child = childItr.next(); Date pageDate = child.getScheduledDate(); if ((date == null && pageDate != null) || (date != null && !date.equals(pageDate))) { if (!renameItem.isNow()) { child.setNow(false); if (date != null && (pageDate != null && pageDate.before(date))) { child.setScheduledDate(date); } } toRet.add(child); List<DmDependencyTO> childDeps = child.flattenChildren(); for (DmDependencyTO childDep : childDeps) { String depPath = siteRoot + childDep.getUri(); ObjectStateService.State depState = persistenceManagerService.getObjectState(depPath); if (ObjectStateService.State.isUpdateOrNew(depState)) { toRet.add(childDep); } } child.setReference(false); childItr.remove(); } } } return toRet; } protected List<DmDependencyTO> getChildrenDependenciesForRenamedItem(String site, FileInfo fileInfo) { List<DmDependencyTO> toRet = new FastList<DmDependencyTO>(); PersistenceManagerService persistenceManagerService = getServicesManager() .getService(PersistenceManagerService.class); DmDependencyService dmDependencyService = getServicesManager().getService(DmDependencyService.class); if (fileInfo.isFolder()) { List<FileInfo> children = persistenceManagerService.list(fileInfo.getNodeRef()); for (FileInfo childInfo : children) { toRet.addAll(getChildrenDependenciesForRenamedItem(site, childInfo)); } } else { DmPathTO childPathTO = new DmPathTO(persistenceManagerService.getNodePath(fileInfo.getNodeRef())); DmDependencyTO childDep = dmDependencyService.getDependencies(site, null, childPathTO.getRelativePath(), false, true); toRet.add(childDep); } return toRet; } protected void resolveSubmittedPaths(String site, DmDependencyTO item, List<String> submittedPaths) { ServicesConfig servicesConfig = getServicesManager().getService(ServicesConfig.class); PersistenceManagerService persistenceManagerService = getServicesManager() .getService(PersistenceManagerService.class); String fullPath = servicesConfig.getRepositoryRootPath(site) + item.getUri(); if (!submittedPaths.contains(fullPath)) { submittedPaths.add(fullPath); } List<DmDependencyTO> children = item.getChildren(); if (children != null) { for (DmDependencyTO child : children) { String childPath = servicesConfig.getRepositoryRootPath(site) + child.getUri(); ObjectStateService.State depState = persistenceManagerService.getObjectState(childPath); if (ObjectStateService.State.isUpdateOrNew(depState)) { if (!submittedPaths.contains(childPath)) { submittedPaths.add(childPath); } resolveSubmittedPaths(site, child, submittedPaths); } } } DependencyRules rule = new DependencyRules(site, getServicesManager()); Set<DmDependencyTO> deps = rule.applySubmitRule(item); if (deps != null) { for (DmDependencyTO dep : deps) { String depPath = servicesConfig.getRepositoryRootPath(site) + dep.getUri(); ObjectStateService.State depState = persistenceManagerService.getObjectState(depPath); if (ObjectStateService.State.isUpdateOrNew(depState)) { if (!submittedPaths.contains(depPath)) { submittedPaths.add(depPath); } } resolveSubmittedPaths(site, dep, submittedPaths); } } } protected List<DmDependencyTO> getRefAndChildOfDiffDateFromParent(String site, List<DmDependencyTO> submittedItems, boolean removeInPages) { ServicesConfig servicesConfig = getServicesManager().getService(ServicesConfig.class); PersistenceManagerService persistenceManagerService = getServicesManager() .getService(PersistenceManagerService.class); String siteRoot = servicesConfig.getRepositoryRootPath(site); List<DmDependencyTO> childAndReferences = new FastList<DmDependencyTO>(); for (DmDependencyTO submittedItem : submittedItems) { List<DmDependencyTO> children = submittedItem.getChildren(); Date date = submittedItem.getScheduledDate(); if (children != null) { Iterator<DmDependencyTO> childItr = children.iterator(); while (childItr.hasNext()) { DmDependencyTO child = childItr.next(); Date pageDate = child.getScheduledDate(); if ((date == null && pageDate != null) || (date != null && !date.equals(pageDate))) { if (!submittedItem.isNow()) { child.setNow(false); if (date != null && (pageDate != null && pageDate.before(date))) { child.setScheduledDate(date); } } childAndReferences.add(child); List<DmDependencyTO> childDeps = child.flattenChildren(); for (DmDependencyTO childDep : childDeps) { String depPath = siteRoot + childDep.getUri(); ObjectStateService.State depState = persistenceManagerService.getObjectState(depPath); if (ObjectStateService.State.isUpdateOrNew(depState)) { childAndReferences.add(childDep); } } child.setReference(false); childItr.remove(); if (removeInPages) { String uri = child.getUri(); List<DmDependencyTO> pages = submittedItem.getPages(); if (pages != null) { Iterator<DmDependencyTO> pagesIter = pages.iterator(); while (pagesIter.hasNext()) { DmDependencyTO page = pagesIter.next(); if (page.getUri().equals(uri)) { pagesIter.remove(); } } } } } } } /* * List<DmDependencyTO> deps = * submittedItem.getDirectDependencies(); if (deps != null) { * Iterator<DmDependencyTO> depItr = deps.iterator(); while * (depItr.hasNext()) { DmDependencyTO dep = depItr.next(); String * depPath = siteRoot + dep.getUri(); ObjectStateService.State * depState = persistenceManagerService.getObjectState(depPath); if * (ObjectStateService.State.isUpdateOrNew(depState)) { Date * pageDate = dep.getScheduledDate(); if ( (date==null && * pageDate!=null) || (date!=null && !date.equals(pageDate))) { * childAndReferences.add(dep); dep.setReference(false); * depItr.remove(); if (removeInPages) { String uri = dep.getUri(); * List<DmDependencyTO> pages = submittedItem.getPages(); if (pages * != null) { Iterator<DmDependencyTO> pagesIter = pages.iterator(); * while (pagesIter.hasNext()) { DmDependencyTO page = * pagesIter.next(); if (page.getUri().equals(uri)) { * pagesIter.remove(); } } } } } } * childAndReferences.addAll(getRefAndChildOfDiffDateFromParent * (site, dep.getDirectDependencies(), removeInPages)); } } */ DependencyRules rule = new DependencyRules(site, getServicesManager()); childAndReferences.addAll(rule.applySubmitRule(submittedItem)); } return childAndReferences; } /** * removes the child items which are in submit to delete state from * submitted items as these have to be routed for deletion. it applies to * GoLive operation. * * @param dependencyTO * @param operation * @return */ protected List<DmDependencyTO> removeSubmitToDeleteChildrenForGoLive(DmDependencyTO dependencyTO, Operation operation) { List<DmDependencyTO> submitForDeleteChilds = new FastList<DmDependencyTO>(); if (operation == Operation.GOLIVE && !dependencyTO.isSubmittedForDeletion()) { List<DmDependencyTO> children = dependencyTO.getChildren(); if (children != null) { for (DmDependencyTO child : children) { if (child.isSubmittedForDeletion()) { submitForDeleteChilds.add(child); } } for (DmDependencyTO submitForDeleteChild : submitForDeleteChilds) { children.remove(submitForDeleteChild); } } } return submitForDeleteChilds; } /** * reject items that are currently in workflow and send a rejection notice * to the user * * @param site * @param sub * @param request * @return call result * @throws ServiceException */ public ResultTO reject(String site, String sub, String request) { ResultTO result = new ResultTO(); PersistenceManagerService persistenceManagerService = getServicesManager() .getService(PersistenceManagerService.class); try { String approver = persistenceManagerService.getCurrentUserName(); JSONObject requestObject = JSONObject.fromObject(request); String reason = (requestObject.containsKey(JSON_KEY_REASON)) ? requestObject.getString(JSON_KEY_REASON) : ""; JSONArray items = requestObject.getJSONArray(JSON_KEY_ITEMS); String scheduledDate = null; if (requestObject.containsKey(JSON_KEY_SCHEDULED_DATE)) { scheduledDate = requestObject.getString(JSON_KEY_SCHEDULED_DATE); } int length = items.size(); ObjectStateService objectStateService = getServicesManager().getService(ObjectStateService.class); ServicesConfig servicesConfig = getServicesManager().getService(ServicesConfig.class); if (length > 0) { SimpleDateFormat format = new SimpleDateFormat(CStudioConstants.DATE_PATTERN_WORKFLOW); List<DmDependencyTO> submittedItems = new FastList<DmDependencyTO>(); for (int index = 0; index < length; index++) { JSONObject item = items.getJSONObject(index); DmDependencyTO submittedItem = getSubmittedItem(site, item, format, scheduledDate); submittedItems.add(submittedItem); } List<String> nodeRefs = new FastList<String>(); for (DmDependencyTO goLiveItem : submittedItems) { String fullPath = servicesConfig.getRepositoryRootPath(site) + goLiveItem.getUri(); NodeRef nodeRef = persistenceManagerService.getNodeRef(fullPath); if (nodeRef != null) { nodeRefs.add(nodeRef.getId()); } } persistenceManagerService.setSystemProcessingBulk(nodeRefs, true); DmWorkflowService dmWorkflowService = getServicesManager().getService(DmWorkflowService.class); dmWorkflowService.reject(site, sub, submittedItems, reason, approver); persistenceManagerService.setSystemProcessingBulk(nodeRefs, false); result.setSuccess(true); NotificationService notificationService = getServicesManager() .getService(NotificationService.class); result.setMessage( notificationService.getCompleteMessage(site, NotificationService.COMPLETE_REJECT)); } else { result.setSuccess(false); result.setMessage("No items provided for preparation."); } } catch (JSONException e) { result.setSuccess(false); result.setMessage(e.getMessage()); } return result; } /** * get scheduled items that are approved and awaiting for deployment * * @param site * @param sub * @param sort sort key for categories * @param ascending * @param subSort sort key for category items * @param subAscending * @return scheduled items in JSON * @throws ServiceException */ public String getScheduledItems(String site, String sub, String sort, boolean ascending, String subSort, boolean subAscending, String filterType) throws ServiceException { if (StringUtils.isEmpty(sort)) { sort = DmContentItemComparator.SORT_EVENT_DATE; } DmContentItemComparator comparator = new DmContentItemComparator(sort, ascending, true, true); DmContentItemComparator subComparator = new DmContentItemComparator(subSort, subAscending, true, true); DmWorkflowService dmWorkflowService = getServicesManager().getService(DmWorkflowService.class); List<DmContentItemTO> items = null; items = dmWorkflowService.getScheduledItems(site, sub, comparator, subComparator, filterType); JSONObject jsonObject = new JSONObject(); int total = 0; if (items != null) { for (DmContentItemTO item : items) { total += item.getNumOfChildren(); } } jsonObject.put(CStudioConstants.PROPERTY_TOTAL, total); jsonObject.put(CStudioConstants.PROPERTY_SORTED_BY, sort); jsonObject.put(CStudioConstants.PROPERTY_SORT_ASCENDING, String.valueOf(ascending)); jsonObject.put(CStudioConstants.PROPERTY_DOCUMENTS, items); return jsonObject.toString(); } /** * approve workflows and schedule them as specified in the request * * @param site * @param sub * @param request * @return call result * @throws ServiceException */ public ResultTO goDelete(String site, String sub, String request, String user) { String md5 = DmUtils.getMd5ForFile(request); String id = site + ":" + user + ":" + md5; GeneralLockService generalLockService = _servicesManager.getService(GeneralLockService.class); if (!generalLockService.tryLock(id)) { generalLockService.lock(id); generalLockService.unlock(id); return new ResultTO(); } try { Map<String, String> map = new HashMap<String, String>(); map.put(CStudioConstants.USER, user); ThreadLocalContainer.set(map); return approve(site, sub, request, Operation.DELETE); } finally { ThreadLocalContainer.remove(); generalLockService.unlock(id); } } /** * update all items that are associated with the current task to be * scheduled * * @param packageRef */ public void updateItemStatusToScheduled(NodeRef packageRef, Date date, String desc) { DmWorkflowService dmWorkflowService = getServicesManager().getService(DmWorkflowService.class); dmWorkflowService.updateItemStatus(packageRef, DmConstants.DM_STATUS_SCHEDULED, date); } public void scheduleDeleteSubmission(NodeRef packageRef, String workflowId, String description) { DmWorkflowService dmWorkflowService = getServicesManager().getService(DmWorkflowService.class); dmWorkflowService.scheduleDeleteSubmission(packageRef, workflowId, description); } public String getWorkflowAffectedPaths(String site, String path) { DmWorkflowService dmWorkflowService = getServicesManager().getService(DmWorkflowService.class); List<DmContentItemTO> affectedItems = dmWorkflowService.getWorkflowAffectedPaths(site, path); JSONObject jsonResponse = prepareAffectedPathsResult(affectedItems, site); return jsonResponse.toString(); } private JSONObject prepareAffectedPathsResult(List<DmContentItemTO> items, String site) { JSONObject toReturn = new JSONObject(); JSONArray jsonItems = new JSONArray(); for (DmContentItemTO item : items) { JSONObject jsonItem = new JSONObject(); jsonItem.put("path", item.getUri()); jsonItem.put("browserUri", item.getBrowserUri()); if (StringUtils.isNotEmpty(item.getInternalName())) { jsonItem.put("name", item.getInternalName()); } else { jsonItem.put("name", item.getName()); } jsonItems.add(jsonItem); } toReturn.put("items", jsonItems); return toReturn; } }