diff --git a/config/alfresco/messages/webclient.properties b/config/alfresco/messages/webclient.properties index 578aff3195..844a802d9f 100644 --- a/config/alfresco/messages/webclient.properties +++ b/config/alfresco/messages/webclient.properties @@ -661,17 +661,18 @@ create_form_form_details_desc=Enter information about the web form you want to c create_form_form_details_step1_desc=Select XML schema to use create_form_form_details_step2_desc=Specify details for new form. create_form_form_details_no_schema_selected= -create_form_configure_rendering_engine_templates_title=Step Two - Configure Rendering Engine Templates -create_form_configure_rendering_engine_templates_desc=Enter information about the rendering engine templates you want to use for this form. +create_form_configure_rendering_engine_templates_title=Step Two - Configure rendering engine templates +create_form_configure_rendering_engine_templates_desc=Enter information about the rendering engine templates you want to use for form {0}. create_form_configure_rendering_engine_templates_step1_desc=Select the rendering engine template to use create_form_configure_rendering_engine_templates_step2_desc=Specify details for the new rendering engine template create_form_select_default_workflow_title=Stop Three - Select default workflow -create_form_select_default_workflow_desc=Select the workflow you want to be used by default for this form. +create_form_select_default_workflow_desc=Select the workflow you want to be used by default for form {0}. create_web_content_summary_desc=The wizard has successfully created the content and all renditions. create_web_content_summary_content_details=Content Details create_web_content_summary_rendition_details=Rendition Details create_web_content_summary_uploaded_files_details=Uploaded File Details -create_web_content_summary_submit_message=Submit {0} when wizard finishes. +create_web_content_summary_submit_message=Submit {0,choice,0#__SHOULD NOT BE ZERO__|1#{1}|1 props = avmService.queryStorePropertyKey(store, QName.createQName(null, PROP_DNS + '%')); if (props.size() == 1) { - dns = props.entrySet().iterator().next().getKey().getLocalName().substring(PROP_DNS.length()); + dns = props.keySet().iterator().next().getLocalName().substring(PROP_DNS.length()); } return dns; @@ -221,11 +247,13 @@ public final class AVMConstants * is relative, otherwise used to extract the parent path portion up until * the webapp directory. * @param path a path relative to the parentAVMPath path, or if it is - * absolute, it is relative to the webapp used in the parentAVMPath. + * absolute, it is relative to the sandbox used in the parentAVMPath. * * @return an absolute path within the avm using the paths provided. */ - public static String buildAbsoluteAVMPath(final String parentAVMPath, final String path) + public static String buildAVMPath(final String parentAVMPath, + final String path, + final PathRelation relation) { String parent = parentAVMPath; if (path == null || path.length() == 0 || @@ -236,7 +264,7 @@ public final class AVMConstants if (path.charAt(0) == '/') { - final Matcher m = absoluteAVMPath.matcher(parent); + final Matcher m = relation.pattern().matcher(parent); if (m.matches()) { parent = m.group(1); @@ -258,10 +286,63 @@ public final class AVMConstants */ public static String getWebappRelativePath(final String absoluteAVMPath) { - final Matcher m = webappRelativePath.matcher(absoluteAVMPath); - return m.matches() && m.group(1).length() != 0 ? m.group(1) : "/"; + final Matcher m = WEBAPP_RELATIVE_PATH_PATTERN.matcher(absoluteAVMPath); + return m.matches() && m.group(3).length() != 0 ? m.group(3) : "/"; } + /** + * Returns the webapp within the path + * + * @param absoluteAVMPath the path from which to extract the webapp name + * + * @return an the webapp name contained within the path or null. + */ + public static String getWebapp(final String absoluteAVMPath) + { + final Matcher m = WEBAPP_RELATIVE_PATH_PATTERN.matcher(absoluteAVMPath); + return m.matches() && m.group(2).length() != 0 ? m.group(2) : null; + } + + /** + * Returns the path portion up the webap + * + * @param absoluteAVMPath the path from which to extract the webapp path + * + * @return an absolute avm path to the webapp contained within + * the path or null. + */ + public static String getWebappPath(final String absoluteAVMPath) + { + final Matcher m = WEBAPP_RELATIVE_PATH_PATTERN.matcher(absoluteAVMPath); + return m.matches() && m.group(1).length() != 0 ? m.group(1) : null; + } + + /** + * Returns a path relative to the sandbox porition of the avm path. + * + * @param absoluteAVMPath an absolute path within the avm + * @return a relative path within the sandbox. + */ + public static String getSandboxRelativePath(final String absoluteAVMPath) + { + final Matcher m = SANDBOX_RELATIVE_PATH_PATTERN.matcher(absoluteAVMPath); + return m.matches() && m.group(2).length() != 0 ? m.group(2) : "/"; + } + + /** + * Returns the path portion up the sandbox + * + * @param absoluteAVMPath the path from which to extract the sandbox path + * + * @return an absolute avm path to the sandbox contained within + * the path or null. + */ + public static String getSandboxPath(final String absoluteAVMPath) + { + final Matcher m = SANDBOX_RELATIVE_PATH_PATTERN.matcher(absoluteAVMPath); + return m.matches() && m.group(1).length() != 0 ? m.group(1) : null; + } + /** * @param path Path to match against * @@ -274,7 +355,7 @@ public final class AVMConstants throw new IllegalArgumentException("Path value is mandatory."); } - return webinfPathPattern.matcher(path).matches(); + return WEB_INF_PATH_PATTERN.matcher(path).matches(); } /** @@ -351,14 +432,15 @@ public final class AVMConstants private final static String PREVIEW_ASSET_URL = "http://www-{0}.{1}:{2}{3}"; // pattern for absolute AVM Path - private final static Pattern absoluteAVMPath = Pattern.compile( - "([^:]+:/" + AVMConstants.DIR_APPBASE + "/[^/]+/[^/]+).*"); - private final static Pattern webappRelativePath = Pattern.compile( - "[^:]+:/" + AVMConstants.DIR_APPBASE + - "/" + AVMConstants.DIR_WEBAPPS + "/[^/]+(.*)"); + private final static Pattern WEBAPP_RELATIVE_PATH_PATTERN = + Pattern.compile("([^:]+:/" + AVMConstants.DIR_APPBASE + + "/" + AVMConstants.DIR_WEBAPPS + "/([^/]+))(.*)"); + private final static Pattern SANDBOX_RELATIVE_PATH_PATTERN = + Pattern.compile("([^:]+:/" + AVMConstants.DIR_APPBASE + + "/" + AVMConstants.DIR_WEBAPPS + ")(.*)"); // patterns for WEB-INF files that require virtualisation server reload - private final static Pattern webinfPathPattern = Pattern.compile( + private final static Pattern WEB_INF_PATH_PATTERN = Pattern.compile( ".*:/" + AVMConstants.DIR_APPBASE + "/" + AVMConstants.DIR_WEBAPPS + "/.*/WEB-INF/((classes/.*)|(lib/.*)|(web.xml))", Pattern.CASE_INSENSITIVE); diff --git a/source/java/org/alfresco/web/bean/wcm/AVMEditBean.java b/source/java/org/alfresco/web/bean/wcm/AVMEditBean.java index 69bc59e236..9b42d4ae18 100644 --- a/source/java/org/alfresco/web/bean/wcm/AVMEditBean.java +++ b/source/java/org/alfresco/web/bean/wcm/AVMEditBean.java @@ -45,6 +45,7 @@ import org.alfresco.web.bean.CheckinCheckoutBean; import org.alfresco.web.bean.FileUploadBean; import org.alfresco.web.bean.repository.Repository; import org.alfresco.web.forms.Form; +import org.alfresco.web.forms.FormInstanceDataImpl; import org.alfresco.web.forms.FormProcessor; import org.alfresco.web.forms.FormsService; import org.alfresco.web.forms.Rendition; @@ -409,8 +410,8 @@ public class AVMEditBean // regenerate form content if (nodeService.hasAspect(avmRef, WCMAppModel.ASPECT_FORM_INSTANCE_DATA)) { - formsService.regenerateRenditions(avmRef); - NodeRef[] uploadedFiles = this.formProcessorSession.getUploadedFiles(); + formsService.regenerateRenditions(new FormInstanceDataImpl(avmRef)); + final NodeRef[] uploadedFiles = this.formProcessorSession.getUploadedFiles(); final List diffList = new ArrayList(uploadedFiles.length); for (NodeRef uploadedFile : uploadedFiles) { diff --git a/source/java/org/alfresco/web/bean/wcm/CreateFormWizard.java b/source/java/org/alfresco/web/bean/wcm/CreateFormWizard.java index a2566a9c3b..0cdf8fb99c 100644 --- a/source/java/org/alfresco/web/bean/wcm/CreateFormWizard.java +++ b/source/java/org/alfresco/web/bean/wcm/CreateFormWizard.java @@ -18,6 +18,7 @@ package org.alfresco.web.bean.wcm; import java.io.File; import java.io.Serializable; +import java.text.MessageFormat; import java.util.*; import javax.faces.context.FacesContext; import javax.faces.event.ActionEvent; @@ -366,19 +367,41 @@ public class CreateFormWizard // wizard implementations don't have to worry about // checking step numbers - boolean disabled = false; final int step = Application.getWizardManager().getCurrentStep(); switch(step) { - case 1: - { - disabled = (this.getSchemaFileName() == null || - this.getSchemaFileName().length() == 0); - break; - } + case 1: + { + return (this.getSchemaFileName() == null || + this.getSchemaFileName().length() == 0); + } + default: + { + return false; + } + } + } + + @Override + public String getStepDescription() + { + final ResourceBundle bundle = Application.getBundle(FacesContext.getCurrentInstance()); + final String stepName = Application.getWizardManager().getCurrentStepName(); + if ("configure_rendering_engine_templates".equals(stepName)) + { + return MessageFormat.format(bundle.getString("create_form_configure_rendering_engine_templates_desc"), + this.getFormName()); + } + else if ("select_default_workflow".equals(stepName)) + { + + return MessageFormat.format(bundle.getString("create_form_select_default_workflow_desc"), + this.getFormName()); + } + else + { + return super.getContainerDescription(); } - - return disabled; } /** diff --git a/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java b/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java index 1b8f4221a8..1353122936 100644 --- a/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java +++ b/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java @@ -306,11 +306,16 @@ public class CreateWebContentWizard extends BaseContentWizard // reset all paths and structures to the main store this.createdPath = this.createdPath.replaceFirst(AVMConstants.STORE_PREVIEW, AVMConstants.STORE_MAIN); + LOGGER.debug("reset path " + this.createdPath + " to main store"); + + boolean form = (MimetypeMap.MIMETYPE_XML.equals(this.mimeType) && this.formName != null); if (form) { this.formInstanceData = new FormInstanceDataImpl(AVMNodeConverter.ToNodeRef(-1, this.createdPath)); this.renditions = this.formInstanceData.getRenditions(); + LOGGER.debug("reset form instance data " + this.formInstanceData.getName() + + " and " + this.renditions.size() + " to main store"); } if (this.startWorkflow) { @@ -378,6 +383,8 @@ public class CreateWebContentWizard extends BaseContentWizard // create package paths (layered to user sandbox area as target) String stagingPath = AVMConstants.buildAVMStoreRootPath(this.avmBrowseBean.getStagingStore()); String packagesPath = AVMWorkflowUtil.createAVMLayeredPackage(this.avmService, stagingPath); + LOGGER.debug("created layered package " + packagesPath + + " above " + stagingPath); List diffs = new ArrayList(8); // construct diffs for selected items for submission @@ -484,7 +491,10 @@ public class CreateWebContentWizard extends BaseContentWizard path = path.replaceFirst(AVMConstants.STORE_MAIN, AVMConstants.STORE_PREVIEW); if (MimetypeMap.MIMETYPE_XML.equals(this.mimeType) && this.formName != null) { - path = this.getForm().getOutputPathForFormInstanceData(path, fileName, this.instanceDataDocument); + path = this.getForm().getOutputPathForFormInstanceData(this.instanceDataDocument, + fileName, + path, + this.avmBrowseBean.getWebapp()); this.content = FormsService.getInstance().writeXMLToString(this.instanceDataDocument); final String[] sb = AVMNodeConverter.SplitBase(path); path = sb[0]; @@ -505,7 +515,7 @@ public class CreateWebContentWizard extends BaseContentWizard new ByteArrayInputStream((this.content == null ? "" : this.content).getBytes())); // remember the created path - this.createdPath = path + '/' + fileName; + this.createdPath = AVMNodeConverter.ExtendAVMPath(path, fileName); // add titled aspect for the read/edit properties screens final NodeRef formInstanceDataNodeRef = AVMNodeConverter.ToNodeRef(-1, this.createdPath); @@ -517,7 +527,7 @@ public class CreateWebContentWizard extends BaseContentWizard { this.formInstanceData = new FormInstanceDataImpl(formInstanceDataNodeRef); this.getForm().registerFormInstanceData(formInstanceDataNodeRef); - this.renditions = FormsService.getInstance().generateRenditions(formInstanceDataNodeRef); + this.renditions = FormsService.getInstance().generateRenditions(this.formInstanceData); } else { @@ -706,7 +716,7 @@ public class CreateWebContentWizard extends BaseContentWizard { if (this.formProcessorSession == null) { - return Collections.emptyList(); + return Collections.EMPTY_LIST; } NodeRef[] uploadedFiles = this.formProcessorSession.getUploadedFiles(); @@ -727,6 +737,15 @@ public class CreateWebContentWizard extends BaseContentWizard return result; } + /** + * Returns the number of submittable files which is the total number of + * uploaded files, renditions, and the form instance data. + */ + public int getNumberOfSubmittableFiles() + { + return 1 + this.getUploadedFiles().size() + this.getRenditions().size(); + } + public boolean getFormSelectDisabled() { return this.formSelectDisabled; diff --git a/source/java/org/alfresco/web/bean/wcm/CreateWebappDialog.java b/source/java/org/alfresco/web/bean/wcm/CreateWebappDialog.java index 014f811db6..b140d016c8 100644 --- a/source/java/org/alfresco/web/bean/wcm/CreateWebappDialog.java +++ b/source/java/org/alfresco/web/bean/wcm/CreateWebappDialog.java @@ -20,8 +20,10 @@ import javax.faces.context.FacesContext; import org.alfresco.model.ApplicationModel; import org.alfresco.model.ContentModel; +import org.alfresco.model.WCMAppModel; import org.alfresco.repo.avm.AVMNodeConverter; -import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.repo.domain.PropertyValue; /** * Bean implementation for the AVM "Create Webapp Folder" dialog. @@ -39,15 +41,18 @@ public class CreateWebappDialog extends CreateFolderDialog @Override protected String finishImpl(FacesContext context, String outcome) throws Exception { - String parent = AVMConstants.buildAVMStoreRootPath(this.avmBrowseBean.getStagingStore()); + final String parent = AVMConstants.buildAVMStoreRootPath(this.avmBrowseBean.getStagingStore()); this.avmService.createDirectory(parent, this.name); - String path = parent + '/' + this.name; - NodeRef nodeRef = AVMNodeConverter.ToNodeRef(-1, path); - this.nodeService.addAspect(nodeRef, ApplicationModel.ASPECT_UIFACETS, null); + final String path = AVMNodeConverter.ExtendAVMPath(parent, this.name); + this.avmService.addAspect(path, ApplicationModel.ASPECT_UIFACETS); + this.avmService.addAspect(path, WCMAppModel.ASPECT_WEBAPP); if (this.description != null && this.description.length() != 0) { - this.nodeService.setProperty(nodeRef, ContentModel.PROP_DESCRIPTION, this.description); + this.avmService.setNodeProperty(path, + ContentModel.PROP_DESCRIPTION, + new PropertyValue(DataTypeDefinition.TEXT, + this.description)); } return outcome; diff --git a/source/java/org/alfresco/web/bean/wcm/CreateWebsiteWizard.java b/source/java/org/alfresco/web/bean/wcm/CreateWebsiteWizard.java index ff3890cbd2..dbf8040b5e 100644 --- a/source/java/org/alfresco/web/bean/wcm/CreateWebsiteWizard.java +++ b/source/java/org/alfresco/web/bean/wcm/CreateWebsiteWizard.java @@ -33,6 +33,7 @@ import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ApplicationModel; import org.alfresco.model.ContentModel; import org.alfresco.model.WCMAppModel; +import org.alfresco.repo.avm.AVMNodeConverter; import org.alfresco.service.cmr.avm.AVMService; import org.alfresco.service.cmr.model.FileInfo; import org.alfresco.service.cmr.repository.NodeRef; @@ -186,8 +187,12 @@ public class CreateWebsiteWizard extends BaseWizardBean SandboxFactory.createStagingSandbox(avmStore, wiz.getManagers()); // create the default webapp folder under the hidden system folders - String stagingStore = AVMConstants.buildAVMStagingStoreName(avmStore); - this.avmService.createDirectory(AVMConstants.buildAVMStoreRootPath(stagingStore), webapp); + final String stagingStore = AVMConstants.buildAVMStagingStoreName(avmStore); + final String stagingStoreRoot = AVMConstants.buildAVMStoreRootPath(stagingStore); + this.avmService.createDirectory(stagingStoreRoot, webapp); + this.avmService.addAspect(AVMNodeConverter.ExtendAVMPath(stagingStoreRoot, + webapp), + WCMAppModel.ASPECT_WEBAPP); // set the property on the node to reference the root AVM store this.nodeService.setProperty(nodeRef, WCMAppModel.PROP_AVMSTORE, avmStore); diff --git a/source/java/org/alfresco/web/bean/wizard/BaseWizardBean.java b/source/java/org/alfresco/web/bean/wizard/BaseWizardBean.java index fa9933e2c5..b8e55cdcb6 100644 --- a/source/java/org/alfresco/web/bean/wizard/BaseWizardBean.java +++ b/source/java/org/alfresco/web/bean/wizard/BaseWizardBean.java @@ -44,6 +44,16 @@ public abstract class BaseWizardBean extends BaseDialogBean implements IWizardBe { return Application.getMessage(FacesContext.getCurrentInstance(), "finish_button"); } + + public String getStepTitle() + { + return null; + } + + public String getStepDescription() + { + return null; + } /** * Build summary table from the specified list of Labels and Values diff --git a/source/java/org/alfresco/web/bean/wizard/IWizardBean.java b/source/java/org/alfresco/web/bean/wizard/IWizardBean.java index d8f46a7f0e..6c38cf08ed 100644 --- a/source/java/org/alfresco/web/bean/wizard/IWizardBean.java +++ b/source/java/org/alfresco/web/bean/wizard/IWizardBean.java @@ -43,4 +43,22 @@ public interface IWizardBean extends IDialogBean * @return true if the button should be disabled */ public boolean getNextButtonDisabled(); + + /** + * Returns the title to be used for the current step + *

If this returns null the WizardManager will + * lookup the title via the dialog configuration

+ * + * @return The title or null if the title is to be acquired via configuration + */ + public String getStepTitle(); + + /** + * Returns the description to be used for the current step + *

If this returns null the WizardManager will + * lookup the description via the dialog configuration

+ * + * @return The decsription or null if the title is to be acquired via configuration + */ + public String getStepDescription(); } diff --git a/source/java/org/alfresco/web/bean/wizard/WizardManager.java b/source/java/org/alfresco/web/bean/wizard/WizardManager.java index 050dee6257..9336e7446c 100644 --- a/source/java/org/alfresco/web/bean/wizard/WizardManager.java +++ b/source/java/org/alfresco/web/bean/wizard/WizardManager.java @@ -206,7 +206,6 @@ public final class WizardManager { // try and get the description directly from the dialog String desc = this.currentWizardState.getWizard().getContainerDescription(); - if (desc == null) { // try and get the description via a message bundle key @@ -324,18 +323,15 @@ public final class WizardManager */ public String getStepTitle() { - String title = this.currentWizardState.getCurrentPageCfg().getTitleId(); - - if (title != null) + String result = this.currentWizardState.getWizard().getStepTitle(); + if (result == null) { - title = Application.getMessage(FacesContext.getCurrentInstance(), title); + result = this.currentWizardState.getCurrentPageCfg().getTitleId(); + result = (result != null + ? Application.getMessage(FacesContext.getCurrentInstance(), result) + : this.currentWizardState.getCurrentPageCfg().getTitle()); } - else - { - title = this.currentWizardState.getCurrentPageCfg().getTitle(); - } - - return title; + return result; } /** @@ -345,18 +341,15 @@ public final class WizardManager */ public String getStepDescription() { - String desc = this.currentWizardState.getCurrentPageCfg().getDescriptionId(); - - if (desc != null) + String result = this.currentWizardState.getWizard().getStepDescription(); + if (result == null) { - desc = Application.getMessage(FacesContext.getCurrentInstance(), desc); + result = this.currentWizardState.getCurrentPageCfg().getDescriptionId(); + result = (result != null + ? Application.getMessage(FacesContext.getCurrentInstance(), result) + : this.currentWizardState.getCurrentPageCfg().getDescription()); } - else - { - desc = this.currentWizardState.getCurrentPageCfg().getDescription(); - } - - return desc; + return result; } /** @@ -397,14 +390,8 @@ public final class WizardManager */ public boolean getNextButtonDisabled() { - if (this.currentWizardState.getCurrentStep() == this.currentWizardState.getSteps().size()) - { - return true; - } - else - { - return this.currentWizardState.getWizard().getNextButtonDisabled(); - } + return (this.currentWizardState.getCurrentStep() == this.currentWizardState.getSteps().size() || + this.currentWizardState.getWizard().getNextButtonDisabled()); } /** @@ -424,14 +411,7 @@ public final class WizardManager */ public boolean getBackButtonDisabled() { - if (this.currentWizardState.getCurrentStep() == 1) - { - return true; - } - else - { - return false; - } + return this.currentWizardState.getCurrentStep() == 1; } /** @@ -461,14 +441,8 @@ public final class WizardManager */ public boolean getFinishButtonDisabled() { - if (this.currentWizardState.getCurrentStep() == this.currentWizardState.getSteps().size()) - { - return false; - } - else - { - return this.currentWizardState.getWizard().getFinishButtonDisabled(); - } + return (this.currentWizardState.getCurrentStep() != this.currentWizardState.getSteps().size() && + this.currentWizardState.getWizard().getFinishButtonDisabled()); } /** diff --git a/source/java/org/alfresco/web/bean/workflow/ManageTaskDialog.java b/source/java/org/alfresco/web/bean/workflow/ManageTaskDialog.java index f73afefd87..d2eb3c5503 100644 --- a/source/java/org/alfresco/web/bean/workflow/ManageTaskDialog.java +++ b/source/java/org/alfresco/web/bean/workflow/ManageTaskDialog.java @@ -34,6 +34,8 @@ import org.alfresco.web.bean.repository.Node; import org.alfresco.web.bean.repository.NodePropertyResolver; import org.alfresco.web.bean.repository.Repository; import org.alfresco.web.bean.repository.TransientNode; +import org.alfresco.web.bean.wcm.AVMConstants; +import org.alfresco.web.bean.wcm.AVMNode; import org.alfresco.web.config.DialogsConfigElement.DialogButtonConfig; import org.alfresco.web.ui.common.Utils; import org.alfresco.web.ui.common.component.UIActionLink; @@ -41,6 +43,14 @@ import org.alfresco.web.ui.common.component.data.UIRichList; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.alfresco.web.bean.wcm.AVMWorkflowUtil; +import org.alfresco.model.WCMModel; +import org.alfresco.repo.avm.AVMNodeConverter; +import org.alfresco.service.cmr.repository.Path; +import org.alfresco.service.cmr.avm.AVMService; +import org.alfresco.service.cmr.avmsync.AVMDifference; +import org.alfresco.service.cmr.avmsync.AVMSyncService; + /** * Bean implementation for the "Manage Task" dialog. * @@ -49,6 +59,8 @@ import org.apache.commons.logging.LogFactory; public class ManageTaskDialog extends BaseDialogBean { protected WorkflowService workflowService; + protected AVMService avmService; + protected AVMSyncService avmSyncService; protected Node taskNode; protected WorkflowTask task; protected WorkflowInstance workflowInstance; @@ -62,7 +74,7 @@ public class ManageTaskDialog extends BaseDialogBean protected String[] itemsToAdd; protected boolean isItemBeingAdded = false; - protected final Log logger = LogFactory.getLog(getClass()); + private final static Log LOGGER = LogFactory.getLog(ManageTaskDialog.class); protected static final String ID_PREFIX = "transition_"; protected static final String CLIENT_ID_PREFIX = AlfrescoNavigationHandler.DIALOG_PREFIX + ID_PREFIX; @@ -109,11 +121,11 @@ public class ManageTaskDialog extends BaseDialogBean // setup the workflow package for the task this.workflowPackage = (NodeRef)this.task.properties.get(WorkflowModel.ASSOC_PACKAGE); - if (logger.isDebugEnabled()) + if (LOGGER.isDebugEnabled()) { - logger.debug("Task: " + this.task); - logger.debug("Trasient node: " + this.taskNode); - logger.debug("Workflow package: " + this.workflowPackage ); + LOGGER.debug("Task: " + this.task); + LOGGER.debug("Trasient node: " + this.taskNode); + LOGGER.debug("Workflow package: " + this.workflowPackage ); } } } @@ -133,14 +145,14 @@ public class ManageTaskDialog extends BaseDialogBean protected String finishImpl(FacesContext context, String outcome) throws Exception { - if (logger.isDebugEnabled()) - logger.debug("Saving task: " + this.task.id); + if (LOGGER.isDebugEnabled()) + LOGGER.debug("Saving task: " + this.task.id); // prepare the edited parameters for saving Map params = WorkflowUtil.prepareTaskParams(this.taskNode); - if (logger.isDebugEnabled()) - logger.debug("Saving task with parameters: " + params); + if (LOGGER.isDebugEnabled()) + LOGGER.debug("Saving task with parameters: " + params); // remove any items the user selected to remove if (this.workflowPackage != null && this.packageItemsToRemove != null && @@ -232,8 +244,8 @@ public class ManageTaskDialog extends BaseDialogBean { String outcome = getDefaultFinishOutcome(); - if (logger.isDebugEnabled()) - logger.debug("Transitioning task: " + this.task.id); + if (LOGGER.isDebugEnabled()) + LOGGER.debug("Transitioning task: " + this.task.id); // to find out which transition button was pressed we need // to look for the button's id in the request parameters, @@ -263,8 +275,8 @@ public class ManageTaskDialog extends BaseDialogBean // prepare the edited parameters for saving Map params = WorkflowUtil.prepareTaskParams(this.taskNode); - if (logger.isDebugEnabled()) - logger.debug("Transitioning task with parameters: " + params); + if (LOGGER.isDebugEnabled()) + LOGGER.debug("Transitioning task with parameters: " + params); // update the task with the updated parameters this.workflowService.updateTask(this.task.id, params, null, null); @@ -275,8 +287,8 @@ public class ManageTaskDialog extends BaseDialogBean // commit the changes tx.commit(); - if (logger.isDebugEnabled()) - logger.debug("Ended task with transition: " + selectedTransition); + if (LOGGER.isDebugEnabled()) + LOGGER.debug("Ended task with transition: " + selectedTransition); } catch (Throwable e) { @@ -333,15 +345,15 @@ public class ManageTaskDialog extends BaseDialogBean { this.packageItemsToRemove.remove(item); - if (logger.isDebugEnabled()) - logger.debug("Removed item from the removed list: " + item); + if (LOGGER.isDebugEnabled()) + LOGGER.debug("Removed item from the removed list: " + item); } else { this.packageItemsToAdd.add(item); - if (logger.isDebugEnabled()) - logger.debug("Added item to the added list: " + item); + if (LOGGER.isDebugEnabled()) + LOGGER.debug("Added item to the added list: " + item); } } @@ -369,8 +381,8 @@ public class ManageTaskDialog extends BaseDialogBean // remove the item from the added list if it was added in this dialog session this.packageItemsToAdd.remove(nodeRef); - if (logger.isDebugEnabled()) - logger.debug("Removed item from the added list: " + nodeRef); + if (LOGGER.isDebugEnabled()) + LOGGER.debug("Removed item from the added list: " + nodeRef); } else { @@ -382,8 +394,8 @@ public class ManageTaskDialog extends BaseDialogBean this.packageItemsToRemove.add(nodeRef); - if (logger.isDebugEnabled()) - logger.debug("Added item to the removed list: " + nodeRef); + if (LOGGER.isDebugEnabled()) + LOGGER.debug("Added item to the removed list: " + nodeRef); } // reset the rich list so it re-renders @@ -523,54 +535,82 @@ public class ManageTaskDialog extends BaseDialogBean FacesContext context = FacesContext.getCurrentInstance(); tx = Repository.getUserTransaction(context, true); tx.begin(); - - // get existing workflow package items - List childRefs = this.nodeService.getChildAssocs( + + if ((Boolean)this.nodeService.getProperty(this.workflowPackage, + WorkflowModel.PROP_IS_SYSTEM_PACKAGE)) + { + final NodeRef stagingNodeRef = (NodeRef) + this.nodeService.getProperty(this.workflowPackage, + WCMModel.PROP_AVM_DIR_INDIRECTION); + final String fromAvmPath = (String)this.task.properties.get(AVMWorkflowUtil.PROP_FROM_PATH); + final String stagingAvmPath = AVMNodeConverter.ToAVMVersionPath(stagingNodeRef).getSecond(); + final String packageAvmPath = AVMNodeConverter.ToAVMVersionPath(this.workflowPackage).getSecond(); + LOGGER.debug("comparing " + packageAvmPath + + " with " + stagingAvmPath); + for (AVMDifference d : this.avmSyncService.compare(-1, packageAvmPath, + -1, stagingAvmPath, + null)) + { + LOGGER.debug("got difference " + d); + if (d.getDifferenceCode() == AVMDifference.NEWER || + d.getDifferenceCode() == AVMDifference.CONFLICT) + { + this.addAVMNode(new AVMNode(this.avmService.lookup(d.getSourceVersion(), + d.getSourcePath(), + true))); + } + } + } + else + { + // get existing workflow package items + List childRefs = this.nodeService.getChildAssocs( this.workflowPackage, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL); - for (ChildAssociationRef ref: childRefs) - { - // create our Node representation from the NodeRef - NodeRef nodeRef = ref.getChildRef(); - - if (this.nodeService.exists(nodeRef)) + for (ChildAssociationRef ref: childRefs) { - // find it's type so we can see if it's a node we are interested in - QName type = this.nodeService.getType(nodeRef); - - // make sure the type is defined in the data dictionary - TypeDefinition typeDef = this.dictionaryService.getType(type); - - if (typeDef != null) + // create our Node representation from the NodeRef + NodeRef nodeRef = ref.getChildRef(); + + if (!this.nodeService.exists(nodeRef)) { - // look for content nodes or links to content - // NOTE: folders within workflow packages are ignored for now - if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT) || - ApplicationModel.TYPE_FILELINK.equals(type)) - { - // if the node is not in the removed list then add create the - // client side representation and add to the list - if (this.packageItemsToRemove == null || - this.packageItemsToRemove.contains(nodeRef.toString()) == false) - { - createAndAddNode(nodeRef); - } - } + if (LOGGER.isDebugEnabled()) + LOGGER.debug("Ignoring " + nodeRef + " as it has been removed from the repository"); } else { - if (logger.isWarnEnabled()) - logger.warn("Found invalid object in database: id = " + nodeRef + ", type = " + type); + // find it's type so we can see if it's a node we are interested in + QName type = this.nodeService.getType(nodeRef); + + // make sure the type is defined in the data dictionary + TypeDefinition typeDef = this.dictionaryService.getType(type); + + if (typeDef == null) + { + if (LOGGER.isWarnEnabled()) + LOGGER.warn("Found invalid object in database: id = " + nodeRef + + ", type = " + type); + } + else + { + // look for content nodes or links to content + // NOTE: folders within workflow packages are ignored for now + if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT) || + ApplicationModel.TYPE_FILELINK.equals(type)) + { + // if the node is not in the removed list then add create the + // client side representation and add to the list + if (this.packageItemsToRemove == null || + this.packageItemsToRemove.contains(nodeRef.toString()) == false) + { + createAndAddNode(nodeRef); + } + } + } } } - else - { - if (logger.isDebugEnabled()) - logger.debug("Ignoring " + nodeRef + " as it has been removed from the repository"); - } } - // now iterate through the items to add list and add them to the list of resources if (this.packageItemsToAdd != null) { @@ -585,8 +625,8 @@ public class ManageTaskDialog extends BaseDialogBean } else { - if (logger.isDebugEnabled()) - logger.debug("Ignoring " + nodeRef + " as it has been removed from the repository"); + if (LOGGER.isDebugEnabled()) + LOGGER.debug("Ignoring " + nodeRef + " as it has been removed from the repository"); } } } @@ -602,9 +642,9 @@ public class ManageTaskDialog extends BaseDialogBean try { if (tx != null) {tx.rollback();} } catch (Exception tex) {} } } - else if (logger.isDebugEnabled()) + else if (LOGGER.isDebugEnabled()) { - logger.debug("Failed to find workflow package for task: " + this.task.id); + LOGGER.debug("Failed to find workflow package for task: " + this.task.id); } return this.resources; @@ -621,8 +661,65 @@ public class ManageTaskDialog extends BaseDialogBean this.workflowService = workflowService; } + /** + * Sets the avm service to use + * + * @param avmService + * AvmService instance + */ + public void setAvmService(final AVMService avmService) + { + this.avmService = avmService; + } + + /** + * Sets the avm sync service to use + * + * @param avmSyncService + * AvmSycService instance + */ + public void setAvmSyncService(final AVMSyncService avmSyncService) + { + this.avmSyncService = avmSyncService; + } + // ------------------------------------------------------------------------------ // Helper methods + + protected void addAVMNode(AVMNode node) + { + LOGGER.debug("adding node " + node); + node.getProperties().put("taskId", this.task.id); + this.browseBean.setupCommonBindingProperties(node); + final String packagePath = AVMNodeConverter.ToAVMVersionPath(this.workflowPackage).getSecond(); + NodePropertyResolver resolverPath = new NodePropertyResolver() + { + public Object get(Node node) + { + Path result = new Path(); + String s = node.getPath(); + s = s.substring(packagePath.length()); + for (final String s2 : s.split("/")) + { + if (s2.length() != 0) + { + result.append(new Path.Element() + { + public String getElementString() { return s2; } + }); + } + } + return result; + } + }; + node.remove("path"); + node.addPropertyResolver("path", resolverPath); + node.addPropertyResolver("displayPath", resolverPath); + + LOGGER.debug("created mapnode " + node); + + this.resources.add(node); + } protected void createAndAddNode(NodeRef nodeRef) { diff --git a/source/java/org/alfresco/web/forms/Form.java b/source/java/org/alfresco/web/forms/Form.java index d50ab0b09c..c928305a74 100644 --- a/source/java/org/alfresco/web/forms/Form.java +++ b/source/java/org/alfresco/web/forms/Form.java @@ -64,14 +64,16 @@ public interface Form * configured output path pattern. * * @param parentAVMPath the parent avm path + * @param webappname the current webapp name * @param formInstanceDataFileName the file name provided by the user. * @param formInstanceData the parsed xml content * * @return the path to use for writing the form instance data. */ - public String getOutputPathForFormInstanceData(final String parentAVMPath, + public String getOutputPathForFormInstanceData(final Document formInstanceData, final String formInstanceDataFileName, - final Document formInstanceData); + final String parentAVMPath, + final String webappName); //XXXarielb not used currently and not sure if it's necessary... // public void addInputMethod(final TemplateInputMethod in); diff --git a/source/java/org/alfresco/web/forms/FormImpl.java b/source/java/org/alfresco/web/forms/FormImpl.java index a1b670b89c..e0c2a69a44 100644 --- a/source/java/org/alfresco/web/forms/FormImpl.java +++ b/source/java/org/alfresco/web/forms/FormImpl.java @@ -108,13 +108,15 @@ class FormImpl : null); } - public String getOutputPathForFormInstanceData(final String parentAVMPath, + public String getOutputPathForFormInstanceData(final Document formInstanceData, final String formInstanceDataName, - final Document formInstanceData) + final String parentAVMPath, + final String webappName) { final String outputPathPattern = this.getOutputPathPattern(); final Map root = new HashMap(); + root.put("webapp", webappName); root.put("xml", NodeModel.wrap(formInstanceData)); root.put("name", formInstanceDataName); root.put("date", new SimpleDate(new Date(), SimpleDate.DATETIME)); @@ -124,7 +126,9 @@ class FormImpl String result = templateService.processTemplateString(null, outputPathPattern, new SimpleHash(root)); - result = AVMConstants.buildAbsoluteAVMPath(parentAVMPath, result); + result = AVMConstants.buildAVMPath(parentAVMPath, + result, + AVMConstants.PathRelation.SANDBOX_RELATIVE); LOGGER.debug("processed pattern " + outputPathPattern + " as " + result); return result; } diff --git a/source/java/org/alfresco/web/forms/FormInstanceData.java b/source/java/org/alfresco/web/forms/FormInstanceData.java index 9a85ce0216..e978fcb360 100644 --- a/source/java/org/alfresco/web/forms/FormInstanceData.java +++ b/source/java/org/alfresco/web/forms/FormInstanceData.java @@ -38,6 +38,12 @@ public interface FormInstanceData /** the path relative to the containing webapp */ public String getWebappRelativePath(); + /** the path relative to the sandbox */ + public String getSandboxRelativePath(); + + /** the path to the contents of this form instance data */ + public String getPath(); + /** the url to the asset */ public String getUrl(); diff --git a/source/java/org/alfresco/web/forms/FormInstanceDataImpl.java b/source/java/org/alfresco/web/forms/FormInstanceDataImpl.java index 5a7a9100c7..52861b264f 100644 --- a/source/java/org/alfresco/web/forms/FormInstanceDataImpl.java +++ b/source/java/org/alfresco/web/forms/FormInstanceDataImpl.java @@ -18,8 +18,6 @@ package org.alfresco.web.forms; import java.util.LinkedList; import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import javax.faces.context.FacesContext; import org.alfresco.model.ContentModel; import org.alfresco.model.WCMAppModel; @@ -66,15 +64,19 @@ public class FormInstanceDataImpl nodeService.getProperty(this.nodeRef, ContentModel.PROP_NAME); } - /** the path relative to the containing webapp */ public String getWebappRelativePath() { - final String path = AVMNodeConverter.ToAVMVersionPath(this.nodeRef).getSecond(); - final String p = ("[^:]+:/" + AVMConstants.DIR_APPBASE + - "/" + AVMConstants.DIR_WEBAPPS + - "/[^/]+(.*)/" + this.getName()); - final Matcher m = Pattern.compile(p).matcher(path); - return m.matches() && m.group(1).length() != 0 ? m.group(1) : "/"; + return AVMConstants.getWebappRelativePath(this.getPath()); + } + + public String getSandboxRelativePath() + { + return AVMConstants.getSandboxRelativePath(this.getPath()); + } + + public String getPath() + { + return AVMNodeConverter.ToAVMVersionPath(this.nodeRef).getSecond(); } public Form getForm() @@ -94,7 +96,7 @@ public class FormInstanceDataImpl public String getUrl() { - return AVMConstants.buildAVMAssetUrl(AVMNodeConverter.ToAVMVersionPath(this.nodeRef).getSecond()); + return AVMConstants.buildAVMAssetUrl(this.getPath()); } public List getRenditions() @@ -103,8 +105,7 @@ public class FormInstanceDataImpl final List result = new LinkedList(); for (RenderingEngineTemplate ret : this.getForm().getRenderingEngineTemplates()) { - final String renditionAvmPath = - FormsService.getOutputAvmPathForRendition(ret, this.getNodeRef()); + final String renditionAvmPath = ret.getOutputPathForRendition(this); if (avmService.lookup(-1, renditionAvmPath) == null) { LOGGER.warn("unable to locate rendition " + renditionAvmPath + diff --git a/source/java/org/alfresco/web/forms/FormsService.java b/source/java/org/alfresco/web/forms/FormsService.java index e39d8b755d..5c3b4e8b59 100644 --- a/source/java/org/alfresco/web/forms/FormsService.java +++ b/source/java/org/alfresco/web/forms/FormsService.java @@ -26,11 +26,13 @@ import java.io.OutputStream; import java.io.Serializable; import java.io.StringWriter; import java.io.Writer; +import java.text.MessageFormat; import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.ResourceBundle; import java.util.Stack; import javax.faces.context.FacesContext; @@ -266,28 +268,24 @@ public final class FormsService * * @param formInstanceDataNodeRef the noderef containing the form instance data */ - public List generateRenditions(final NodeRef formInstanceDataNodeRef) + public List generateRenditions(final FormInstanceData formInstanceData) throws IOException, SAXException, RenderingEngine.RenderingException { - final Form form = - this.getForm((NodeRef)this.nodeService.getProperty(formInstanceDataNodeRef, - WCMAppModel.PROP_PARENT_FORM)); - final Document formInstanceData = this.parseXML(formInstanceDataNodeRef); + final Form form = formInstanceData.getForm(); - final String formInstanceDataFileName = (String) - this.nodeService.getProperty(formInstanceDataNodeRef, ContentModel.PROP_NAME); - final String formInstanceDataAvmPath = - AVMNodeConverter.ToAVMVersionPath(formInstanceDataNodeRef).getSecond(); + final Document formInstanceDataDocument = this.parseXML(formInstanceData.getNodeRef()); + + final String formInstanceDataFileName = formInstanceData.getName(); + final String formInstanceDataAvmPath = formInstanceData.getPath(); LOGGER.debug("generating renditions for " + formInstanceDataAvmPath); final List result = new LinkedList(); for (RenderingEngineTemplate ret : form.getRenderingEngineTemplates()) { // get the node ref of the node that will contain the content - final String renditionAvmPath = - this.getOutputAvmPathForRendition(ret, formInstanceDataNodeRef); + final String renditionAvmPath = ret.getOutputPathForRendition(formInstanceData); final String parentAVMPath = AVMNodeConverter.SplitBase(renditionAvmPath)[0]; this.makeAllDirectories(parentAVMPath); final OutputStream out = this.avmService.createFile(parentAVMPath, @@ -299,18 +297,24 @@ public final class FormsService final HashMap parameters = this.getRenderingEngineParameters(formInstanceDataAvmPath, renditionAvmPath); - ret.getRenderingEngine().render(formInstanceData, ret, parameters, out); + ret.getRenderingEngine().render(formInstanceDataDocument, ret, parameters, out); out.close(); - final NodeRef renditionNodeRef = - AVMNodeConverter.ToNodeRef(-1, renditionAvmPath); + final NodeRef renditionNodeRef = AVMNodeConverter.ToNodeRef(-1, renditionAvmPath); + final Rendition rendition = new RenditionImpl(renditionNodeRef); form.registerFormInstanceData(renditionNodeRef); - ret.registerRendition(renditionNodeRef, formInstanceDataNodeRef); + ret.registerRendition(rendition, formInstanceData); Map props = new HashMap(1, 1.0f); props.put(ContentModel.PROP_TITLE, AVMNodeConverter.SplitBase(renditionAvmPath)[1]); + + final ResourceBundle bundle = Application.getBundle(FacesContext.getCurrentInstance()); + props.put(ContentModel.PROP_DESCRIPTION, + MessageFormat.format(bundle.getString("default_rendition_description"), + ret.getTitle(), + AVMConstants.getSandboxRelativePath(renditionAvmPath))); nodeService.addAspect(renditionNodeRef, ContentModel.ASPECT_TITLED, props); - result.add(new RenditionImpl(renditionNodeRef)); + result.add(rendition); if (LOGGER.isDebugEnabled()) LOGGER.debug("generated " + renditionAvmPath + " using " + ret); } @@ -322,33 +326,27 @@ public final class FormsService * * @param formInstanceDataNodeRef the node ref containing the form instance data. */ - public List regenerateRenditions(final NodeRef formInstanceDataNodeRef) + public List regenerateRenditions(final FormInstanceData formInstanceData) throws IOException, SAXException, RenderingEngine.RenderingException { - final NodeRef formNodeRef = (NodeRef) - nodeService.getProperty(formInstanceDataNodeRef, WCMAppModel.PROP_PARENT_FORM); - - final Form form = this.getForm(formNodeRef); + final Form form = formInstanceData.getForm(); - final ContentReader reader = contentService.getReader(formInstanceDataNodeRef, ContentModel.PROP_CONTENT); - final Document formInstanceData = this.parseXML(reader.getContentInputStream()); - final String formInstanceDataFileName = (String) - nodeService.getProperty(formInstanceDataNodeRef, ContentModel.PROP_NAME); + final Document formInstanceDataDocument = this.parseXML(formInstanceData.getNodeRef()); + final String formInstanceDataFileName = formInstanceData.getName(); // other parameter values passed to rendering engine - final String formInstanceDataAvmPath = AVMNodeConverter.ToAVMVersionPath(formInstanceDataNodeRef).getSecond(); + final String formInstanceDataAvmPath = formInstanceData.getPath(); LOGGER.debug("regenerating renditions for " + formInstanceDataAvmPath); final List result = new LinkedList(); for (RenderingEngineTemplate ret : form.getRenderingEngineTemplates()) { - final String renditionAvmPath = - this.getOutputAvmPathForRendition(ret, formInstanceDataNodeRef); + final String renditionAvmPath = ret.getOutputPathForRendition(formInstanceData); if (LOGGER.isDebugEnabled()) LOGGER.debug("regenerating file node for : " + formInstanceDataFileName + - " (" + formInstanceDataNodeRef.toString() + + " (" + formInstanceData.toString() + ") to " + renditionAvmPath); // get a writer for the content and put the file @@ -365,11 +363,10 @@ public final class FormsService final HashMap parameters = this.getRenderingEngineParameters(formInstanceDataAvmPath, renditionAvmPath); - ret.getRenderingEngine().render(formInstanceData, ret, parameters, out); + ret.getRenderingEngine().render(formInstanceDataDocument, ret, parameters, out); out.close(); - final NodeRef renditionNodeRef = - AVMNodeConverter.ToNodeRef(-1, renditionAvmPath); + final NodeRef renditionNodeRef = AVMNodeConverter.ToNodeRef(-1, renditionAvmPath); result.add(new RenditionImpl(renditionNodeRef)); if (LOGGER.isDebugEnabled()) LOGGER.debug("regenerated " + renditionAvmPath + " using " + ret); @@ -377,21 +374,6 @@ public final class FormsService return result; } - public static String getOutputAvmPathForRendition(final RenderingEngineTemplate ret, - final NodeRef formInstanceDataNodeRef) - { -// final String formInstanceDataAvmPath = -// AVMNodeConverter.ToAVMVersionPath(formInstanceDataNodeRef).getSecond(); -// String formInstanceDataFileName = AVMNodeConverter.SplitBase(formInstanceDataAvmPath)[1]; -// formInstanceDataFileName = FormsService.stripExtension(formInstanceDataFileName); - String result = ret.getOutputPathForRendition(formInstanceDataNodeRef); -// if (result != null && result.charAt(0) == '/') -// { -// -// } - return result; - } - private static HashMap getRenderingEngineParameters(final String formInstanceDataAvmPath, final String renditionAvmPath) { diff --git a/source/java/org/alfresco/web/forms/FreeMarkerRenderingEngine.java b/source/java/org/alfresco/web/forms/FreeMarkerRenderingEngine.java index 613e7669f6..e9859e9e0c 100644 --- a/source/java/org/alfresco/web/forms/FreeMarkerRenderingEngine.java +++ b/source/java/org/alfresco/web/forms/FreeMarkerRenderingEngine.java @@ -98,8 +98,10 @@ public class FreeMarkerRenderingEngine try { final FormDataFunctions ef = FreeMarkerRenderingEngine.getFormDataFunctions(); - final String path = AVMConstants.buildAbsoluteAVMPath(parameters.get("parent_path"), - (String)args.get(0)); + final String path = + AVMConstants.buildAVMPath(parameters.get("parent_path"), + (String)args.get(0), + AVMConstants.PathRelation.WEBAPP_RELATIVE); final Document d = ef.parseXMLDocument(path); return d != null ? d.getDocumentElement() : null; } @@ -119,8 +121,9 @@ public class FreeMarkerRenderingEngine { final FormDataFunctions ef = FreeMarkerRenderingEngine.getFormDataFunctions(); final String path = - AVMConstants.buildAbsoluteAVMPath(parameters.get("parent_path"), - args.size() == 1 ? "" : (String)args.get(1)); + AVMConstants.buildAVMPath(parameters.get("parent_path"), + args.size() == 1 ? "" : (String)args.get(1), + AVMConstants.PathRelation.WEBAPP_RELATIVE); final Map resultMap = ef.parseXMLDocuments((String)args.get(0), path); LOGGER.debug("received " + resultMap.size() + " documents in " + path); @@ -165,8 +168,9 @@ public class FreeMarkerRenderingEngine { try { - return AVMConstants.buildAbsoluteAVMPath(parameters.get("parent_path"), - (String)args.get(0)); + return AVMConstants.buildAVMPath(parameters.get("parent_path"), + (String)args.get(0), + AVMConstants.PathRelation.WEBAPP_RELATIVE); } catch (Exception e) { diff --git a/source/java/org/alfresco/web/forms/RenderingEngineTemplate.java b/source/java/org/alfresco/web/forms/RenderingEngineTemplate.java index 20bf0dc022..67c4f7ebf1 100644 --- a/source/java/org/alfresco/web/forms/RenderingEngineTemplate.java +++ b/source/java/org/alfresco/web/forms/RenderingEngineTemplate.java @@ -71,7 +71,7 @@ public interface RenderingEngineTemplate * * @return the output path for the rendition. */ - public String getOutputPathForRendition(final NodeRef formInstanceDataNodeRef); + public String getOutputPathForRendition(final FormInstanceData formInstanceData); /** * Returns the mimetype to use when generating content for this @@ -82,5 +82,6 @@ public interface RenderingEngineTemplate */ public String getMimetypeForRendition(); - public void registerRendition(final NodeRef rendition, final NodeRef primaryFormInstanceData); + public void registerRendition(final Rendition rendition, + final FormInstanceData primaryFormInstanceData); } diff --git a/source/java/org/alfresco/web/forms/RenderingEngineTemplateImpl.java b/source/java/org/alfresco/web/forms/RenderingEngineTemplateImpl.java index e5b2633bcf..f776403f37 100644 --- a/source/java/org/alfresco/web/forms/RenderingEngineTemplateImpl.java +++ b/source/java/org/alfresco/web/forms/RenderingEngineTemplateImpl.java @@ -34,6 +34,7 @@ import org.alfresco.model.ContentModel; import org.alfresco.model.WCMAppModel; import org.alfresco.repo.avm.AVMNodeConverter; import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.avm.AVMService; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.MimetypeService; @@ -132,36 +133,43 @@ public class RenderingEngineTemplateImpl * * @return the output path to use for renditions. */ - public String getOutputPathForRendition(final NodeRef formInstanceDataNodeRef) + public String getOutputPathForRendition(final FormInstanceData formInstanceData) { final ServiceRegistry sr = this.getServiceRegistry(); - final NodeService nodeService = this.getServiceRegistry().getNodeService(); + final NodeService nodeService = sr.getNodeService(); + final AVMService avmService = sr.getAVMService(); + final String outputPathPattern = (String) nodeService.getProperty(this.renditionPropertiesNodeRef, WCMAppModel.PROP_OUTPUT_PATH_PATTERN_RENDITION); - final String formInstanceDataAVMPath = - AVMNodeConverter.ToAVMVersionPath(formInstanceDataNodeRef).getSecond(); + final String formInstanceDataAVMPath = formInstanceData.getPath(); final Map root = new HashMap(); - final String formInstanceDataName = (String) - sr.getNodeService().getProperty(formInstanceDataNodeRef, ContentModel.PROP_NAME); - root.put("name", - formInstanceDataName.replaceAll("(.+)\\..*", "$1")); + final String webappName = + (avmService.hasAspect(-1, + AVMConstants.getWebappPath(formInstanceDataAVMPath), + WCMAppModel.ASPECT_WEBAPP) + ? AVMConstants.getWebapp(formInstanceDataAVMPath) + : null); + root.put("webapp", webappName); + + final String formInstanceDataName = formInstanceData.getName(); + root.put("name", formInstanceDataName.replaceAll("(.+)\\..*", "$1")); root.put("extension", sr.getMimetypeService().getExtension(this.getMimetypeForRendition())); try { final FormsService fs = FormsService.getInstance(); - root.put("xml", NodeModel.wrap(fs.parseXML(formInstanceDataNodeRef))); + root.put("xml", NodeModel.wrap(fs.parseXML(formInstanceData.getNodeRef()))); } catch (Exception e) { LOGGER.error(e); } - root.put("node", new TemplateNode(formInstanceDataNodeRef, sr, null)); + root.put("node", new TemplateNode(formInstanceData.getNodeRef(), sr, null)); root.put("date", new SimpleDate(new Date(), SimpleDate.DATETIME)); final TemplateService templateService = sr.getTemplateService(); @@ -169,7 +177,9 @@ public class RenderingEngineTemplateImpl outputPathPattern, new SimpleHash(root)); final String parentAVMPath = AVMNodeConverter.SplitBase(formInstanceDataAVMPath)[0]; - result = AVMConstants.buildAbsoluteAVMPath(parentAVMPath, result); + result = AVMConstants.buildAVMPath(parentAVMPath, + result, + AVMConstants.PathRelation.SANDBOX_RELATIVE); LOGGER.debug("processed pattern " + outputPathPattern + " as " + result); return result; } @@ -186,19 +196,19 @@ public class RenderingEngineTemplateImpl WCMAppModel.PROP_MIMETYPE_FOR_RENDITION); } - public void registerRendition(final NodeRef renditionNodeRef, - final NodeRef primaryFormInstanceDataNodeRef) + public void registerRendition(final Rendition rendition, + final FormInstanceData primaryFormInstanceData) { final NodeService nodeService = this.getServiceRegistry().getNodeService(); final Map props = new HashMap(2, 1.0f); props.put(WCMAppModel.PROP_PARENT_RENDERING_ENGINE_TEMPLATE, this.nodeRef); // extract a store relative path for the primary form instance data - String path = AVMNodeConverter.ToAVMVersionPath(primaryFormInstanceDataNodeRef).getSecond(); + String path = primaryFormInstanceData.getPath(); path = path.substring(path.indexOf(':') + 1); props.put(WCMAppModel.PROP_PRIMARY_FORM_INSTANCE_DATA, path); - nodeService.addAspect(renditionNodeRef, WCMAppModel.ASPECT_RENDITION, props); + nodeService.addAspect(rendition.getNodeRef(), WCMAppModel.ASPECT_RENDITION, props); } private ServiceRegistry getServiceRegistry() diff --git a/source/java/org/alfresco/web/forms/Rendition.java b/source/java/org/alfresco/web/forms/Rendition.java index 3553bf373e..fd75bdc62e 100644 --- a/source/java/org/alfresco/web/forms/Rendition.java +++ b/source/java/org/alfresco/web/forms/Rendition.java @@ -27,12 +27,18 @@ import java.io.Serializable; public interface Rendition extends Serializable { - /** the name of this instance data */ + /** the name of this rendition */ public String getName(); + /** the description of this rendition */ + public String getDescription(); + /** the path relative to the containing webapp */ public String getWebappRelativePath(); + /** the path relative to the sandbox */ + public String getSandboxRelativePath(); + /** the primary form instance data used to generate this rendition */ public FormInstanceData getPrimaryFormInstanceData(); diff --git a/source/java/org/alfresco/web/forms/RenditionImpl.java b/source/java/org/alfresco/web/forms/RenditionImpl.java index 49cfb7c652..b2ba98e7b0 100644 --- a/source/java/org/alfresco/web/forms/RenditionImpl.java +++ b/source/java/org/alfresco/web/forms/RenditionImpl.java @@ -16,8 +16,6 @@ */ package org.alfresco.web.forms; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import javax.faces.context.FacesContext; import org.alfresco.model.ContentModel; import org.alfresco.model.WCMAppModel; @@ -64,15 +62,22 @@ public class RenditionImpl nodeService.getProperty(this.nodeRef, ContentModel.PROP_NAME); } - /** the path relative to the containing webapp */ + /** the description of this rendition */ + public String getDescription() + { + final NodeService nodeService = this.getServiceRegistry().getNodeService(); + return (String) + nodeService.getProperty(this.nodeRef, ContentModel.PROP_DESCRIPTION); + } + public String getWebappRelativePath() { - final String path = AVMNodeConverter.ToAVMVersionPath(this.nodeRef).getSecond(); - final String p = ("[^:]+:/" + AVMConstants.DIR_APPBASE + - "/" + AVMConstants.DIR_WEBAPPS + - "/[^/]+(.*)/" + this.getName()); - final Matcher m = Pattern.compile(p).matcher(path); - return m.matches() && m.group(1).length() != 0 ? m.group(1) : "/"; + return AVMConstants.getWebappRelativePath(this.getPath()); + } + + public String getSandboxRelativePath() + { + return AVMConstants.getSandboxRelativePath(this.getPath()); } public FormInstanceData getPrimaryFormInstanceData() @@ -115,7 +120,7 @@ public class RenditionImpl public String getUrl() { - return AVMConstants.buildAVMAssetUrl(AVMNodeConverter.ToAVMVersionPath(this.nodeRef).getSecond()); + return AVMConstants.buildAVMAssetUrl(this.getPath()); } public String getFileTypeImage() diff --git a/source/java/org/alfresco/web/forms/XSLTRenderingEngine.java b/source/java/org/alfresco/web/forms/XSLTRenderingEngine.java index 11a07dbb22..947eb8f342 100644 --- a/source/java/org/alfresco/web/forms/XSLTRenderingEngine.java +++ b/source/java/org/alfresco/web/forms/XSLTRenderingEngine.java @@ -79,7 +79,9 @@ public class XSLTRenderingEngine throws TransformerException { final XObject o = ec.getVariableOrParam(new QName(ALFRESCO_NS, ALFRESCO_NS_PREFIX, "parent_path")); - return o == null ? null : AVMConstants.buildAbsoluteAVMPath(o.toString(), path); + return o == null ? null : AVMConstants.buildAVMPath(o.toString(), + path, + AVMConstants.PathRelation.WEBAPP_RELATIVE); } /** diff --git a/source/java/org/alfresco/web/forms/xforms/XFormsBean.java b/source/java/org/alfresco/web/forms/xforms/XFormsBean.java index 9cb5f40325..7ba0b9cb00 100644 --- a/source/java/org/alfresco/web/forms/xforms/XFormsBean.java +++ b/source/java/org/alfresco/web/forms/xforms/XFormsBean.java @@ -434,8 +434,9 @@ public class XFormsBean final String previewStorePath = this.avmBrowseBean.getCurrentPath().replaceFirst(AVMConstants.STORE_MAIN, AVMConstants.STORE_PREVIEW); - currentPath = AVMConstants.buildAbsoluteAVMPath(previewStorePath, - currentPath); + currentPath = AVMConstants.buildAVMPath(previewStorePath, + currentPath, + AVMConstants.PathRelation.WEBAPP_RELATIVE); } LOGGER.debug(this + ".getFilePickerData(" + currentPath + ")"); @@ -519,8 +520,9 @@ public class XFormsBean final String previewStorePath = this.avmBrowseBean.getCurrentPath().replaceFirst(AVMConstants.STORE_MAIN, AVMConstants.STORE_PREVIEW); - currentPath = AVMConstants.buildAbsoluteAVMPath(previewStorePath, - item.getString()); + currentPath = AVMConstants.buildAVMPath(previewStorePath, + item.getString(), + AVMConstants.PathRelation.WEBAPP_RELATIVE); LOGGER.debug("currentPath is " + currentPath); } else diff --git a/source/java/org/alfresco/web/ui/repo/renderer/NodePathLinkRenderer.java b/source/java/org/alfresco/web/ui/repo/renderer/NodePathLinkRenderer.java index 25a1fbda17..9725f81444 100644 --- a/source/java/org/alfresco/web/ui/repo/renderer/NodePathLinkRenderer.java +++ b/source/java/org/alfresco/web/ui/repo/renderer/NodePathLinkRenderer.java @@ -73,7 +73,7 @@ public class NodePathLinkRenderer extends BaseRenderer public void encodeEnd(FacesContext context, UIComponent component) throws IOException { // always check for this flag - as per the spec - if (component.isRendered() == false) + if (!component.isRendered()) { return; } @@ -84,17 +84,19 @@ public class NodePathLinkRenderer extends BaseRenderer Path path = null; NodeRef nodeRef = null; Object val = ((UINodePath)component).getValue(); - if (val instanceof NodeRef == true) + if (val instanceof NodeRef) { nodeRef = (NodeRef)val; } - else if (val instanceof Path == true) + else if (val instanceof Path) { path = (Path)val; } else if (val != null) { - throw new IllegalArgumentException("UINodePath component 'value' property must resolve to a NodeRef or Path!"); + throw new IllegalArgumentException("UINodePath component 'value' " + + "property must resolve to a NodeRef " + + "or Path. Got a " + val.getClass().getName()); } if (val != null) diff --git a/source/web/WEB-INF/faces-config-beans.xml b/source/web/WEB-INF/faces-config-beans.xml index c93aba5431..bb1cde5951 100644 --- a/source/web/WEB-INF/faces-config-beans.xml +++ b/source/web/WEB-INF/faces-config-beans.xml @@ -1782,6 +1782,15 @@ workflowService #{WorkflowService} + + avmService + #{AVMService} + + + avmSyncService + #{AVMSyncService} + + diff --git a/source/web/jsp/wcm/create-web-content-wizard/summary.jsp b/source/web/jsp/wcm/create-web-content-wizard/summary.jsp index 3e78444fc1..ebea252f31 100644 --- a/source/web/jsp/wcm/create-web-content-wizard/summary.jsp +++ b/source/web/jsp/wcm/create-web-content-wizard/summary.jsp @@ -24,13 +24,12 @@ window.onload = function() { document.getElementById("wizard:finish-button").focus(); } - - +
${msg.form}: ${WizardManager.bean.formInstanceData.form.name}
-
${msg.location}: ${WizardManager.bean.formInstanceData.webappRelativePath}
+
${msg.location}: ${WizardManager.bean.formInstanceData.sandboxRelativePath}
+ width="100%" rowClasses="wizardSectionHeading" + rendered="#{!empty WizardManager.bean.renditions}"> - + - Rendered by ${rendition.renderingEngineTemplate.name} into ${rendition.webappRelativePath} + ${rendition.description} @@ -89,11 +90,13 @@ + width="100%" rowClasses="wizardSectionHeading" + rendered="#{!empty WizardManager.bean.uploadedFiles}"> - + - + + + +