From 10236f165ad11e56ff7830aba6616165be1586e4 Mon Sep 17 00:00:00 2001 From: Derek Hulley Date: Mon, 10 Sep 2007 12:26:25 +0000 Subject: [PATCH] Merged V2.1 to HEAD 6293: WCM fixes by Ariel (no details) 6294: Fogotten file for above git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@6717 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/messages/webclient.properties | 16 +- config/alfresco/web-client-config-dialogs.xml | 4 - config/alfresco/web-client-config-wcm.xml | 41 +++- config/alfresco/web-client-config-wizards.xml | 44 +++- .../action/evaluator/WCMLockEvaluator.java | 22 +- .../alfresco/web/bean/wcm/AVMBrowseBean.java | 119 ++++++---- .../alfresco/web/bean/wcm/AVMEditBean.java | 162 +++----------- .../web/bean/wcm/CreateFormWizard.java | 9 + .../web/bean/wcm/CreateWebContentWizard.java | 48 +++-- .../web/bean/wcm/DeleteFileDialog.java | 87 ++++++-- .../alfresco/web/bean/wcm/EditFormWizard.java | 3 - .../web/bean/wcm/EditWebContentWizard.java | 203 ++++++++++++++++++ .../web/bean/wcm/EditWebsiteWizard.java | 9 +- .../web/bean/wcm/EditXmlInlineDialog.java | 190 ---------------- .../alfresco/web/bean/wcm/FilePickerBean.java | 135 ++++++++++-- .../bean/wcm/RegenerateRenditionsWizard.java | 78 +++++-- .../org/alfresco/web/bean/wcm/WebProject.java | 45 +++- .../alfresco/web/forms/FormInstanceData.java | 9 +- .../web/forms/FormInstanceDataImpl.java | 39 +++- .../web/forms/FormNotFoundException.java | 110 ++++++++++ .../org/alfresco/web/forms/FormsService.java | 17 +- .../web/forms/XSLTRenderingEngine.java | 5 +- .../web/forms/xforms/Schema2XForms.java | 101 +++++---- .../forms/xforms/Schema2XFormsProperties.java | 7 +- .../web/forms/xforms/Schema2XFormsTest.java | 97 ++++++--- .../alfresco/web/forms/xforms/SchemaUtil.java | 18 +- .../alfresco/web/forms/xforms/XFormsBean.java | 102 ++++++--- .../evaluator/ActionInstanceEvaluator.java | 13 +- .../customer-tests/monks-switch-test.xsd | 58 +++++ .../unit-tests/automated/number-test.xsd | 41 ++++ .../root-element-with-extension-test.xsd | 37 ++++ .../unit-tests/automated/switch-test.xsd | 50 +++++ .../unit-tests/simple-test/textarea-test.xsd | 7 + .../simple-test/upload-simple-test.xsd | 35 ++- source/web/WEB-INF/chiba.xml | 1 + source/web/WEB-INF/faces-config-beans.xml | 98 ++++++--- source/web/images/filetypes/xsd.gif | Bin 0 -> 632 bytes source/web/images/filetypes/xsl.gif | Bin 0 -> 639 bytes source/web/images/filetypes32/xsd.gif | Bin 0 -> 966 bytes source/web/images/filetypes32/xsl.gif | Bin 0 -> 979 bytes .../create-web-content-wizard/create-xml.jsp | 48 ++--- .../wcm/create-web-content-wizard/summary.jsp | 3 +- source/web/jsp/wcm/tiny_mce_image_dialog.jsp | 9 +- source/web/scripts/ajax/ajax_helper.js | 27 ++- source/web/scripts/ajax/common.js | 1 + source/web/scripts/ajax/file_picker_widget.js | 58 +++-- source/web/scripts/ajax/xforms.js | 108 ++++++---- 47 files changed, 1596 insertions(+), 718 deletions(-) create mode 100644 source/java/org/alfresco/web/bean/wcm/EditWebContentWizard.java delete mode 100644 source/java/org/alfresco/web/bean/wcm/EditXmlInlineDialog.java create mode 100644 source/java/org/alfresco/web/forms/FormNotFoundException.java create mode 100644 source/test-resources/xforms/customer-tests/monks-switch-test.xsd create mode 100644 source/test-resources/xforms/unit-tests/automated/number-test.xsd create mode 100644 source/test-resources/xforms/unit-tests/automated/root-element-with-extension-test.xsd create mode 100644 source/test-resources/xforms/unit-tests/automated/switch-test.xsd create mode 100755 source/web/images/filetypes/xsd.gif create mode 100755 source/web/images/filetypes/xsl.gif create mode 100755 source/web/images/filetypes32/xsd.gif create mode 100755 source/web/images/filetypes32/xsl.gif diff --git a/config/alfresco/messages/webclient.properties b/config/alfresco/messages/webclient.properties index df6cc54427..c7aed6ae27 100644 --- a/config/alfresco/messages/webclient.properties +++ b/config/alfresco/messages/webclient.properties @@ -797,6 +797,7 @@ create_web_content_details_title=Web Content Details create_web_content_details_step_title=Step One - Web Content Details create_web_content_enter_content_title=Author Web Content create_web_content_enter_content_step_title=Step Two - Author Web Content +edit_web_content_enter_content_step_title=Step One - Author Web Content 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 @@ -817,6 +818,14 @@ schema_root_element_name=Root element form=Web Form web_project=Web Project +# Form Not Found Exception messages +form_not_found=Unable to find form {0}. +form_not_found_for_form_instance_data=Unable to find form {0} associated with {1}. +form_not_found_in_web_project=Unable to find form {0} in web project {1}. +form_not_found_for_form_instance_data_in_web_project=Unable to find form {0} in web project {1} associated with {2}. +form_not_configured_for_web_project=Form {0} is not configured for web project {1}. +form_associated_with_form_instance_data_not_configured_for_web_project=Form {0} associated with {1} is not configured for web project {2}. + # Rule and Action Wizard messages run_action_title=Run Action Wizard run_action_desc=This wizard helps you run an action @@ -1060,7 +1069,7 @@ store_created_by=Created By store_working_users=There {0,choice,0#are no users|1#is one user|1 - - diff --git a/config/alfresco/web-client-config-wcm.xml b/config/alfresco/web-client-config-wcm.xml index fe932a902e..a50dbd8c76 100644 --- a/config/alfresco/web-client-config-wcm.xml +++ b/config/alfresco/web-client-config-wcm.xml @@ -56,7 +56,46 @@ link,unlink,image,separator,justifyleft,justifycenter,justifyright,justifyfull,separator,bullist,numlist,separator,undo,redo,separator,forecolor,backcolor 400 - + + bold,italic,underline,strikethrough,separator,fontselect,fontsizeselect + link,unlink,image,separator,justifyleft,justifycenter,justifyright,justifyfull,separator,bullist,numlist,separator,undo,redo,separator,forecolor,backcolor + 600 + exact + true + true + table + tablecontrols + + + wcm:avmcontent,wcm:avmfolder + + + wcm:avmcontent + image/* + + + + wcm:avmcontent,wcm:avmfolder + text/html + + + wcm:avmfolder + * + + + wcm:avmcontent + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file + + diff --git a/source/java/org/alfresco/web/action/evaluator/WCMLockEvaluator.java b/source/java/org/alfresco/web/action/evaluator/WCMLockEvaluator.java index 364522b110..60470cf705 100644 --- a/source/java/org/alfresco/web/action/evaluator/WCMLockEvaluator.java +++ b/source/java/org/alfresco/web/action/evaluator/WCMLockEvaluator.java @@ -34,6 +34,7 @@ import org.alfresco.web.app.servlet.FacesHelper; import org.alfresco.web.bean.repository.Node; import org.alfresco.web.bean.repository.Repository; import org.alfresco.web.bean.wcm.AVMBrowseBean; +import org.alfresco.web.bean.wcm.WebProject; /** * Evaluator to return if a item is accessable due to a WCM user level lock. @@ -45,15 +46,22 @@ public class WCMLockEvaluator implements ActionEvaluator /** * @return true if the item is not locked by another user */ - public boolean evaluate(Node node) + public boolean evaluate(final Node node) { - FacesContext fc = FacesContext.getCurrentInstance(); - AVMLockingService avmLockService = Repository.getServiceRegistry(fc).getAVMLockingService(); - AVMBrowseBean avmBrowseBean = (AVMBrowseBean)FacesHelper.getManagedBean(fc, AVMBrowseBean.BEAN_NAME); + final FacesContext fc = FacesContext.getCurrentInstance(); + final AVMLockingService avmLockService = Repository.getServiceRegistry(fc).getAVMLockingService(); + final AVMBrowseBean avmBrowseBean = (AVMBrowseBean)FacesHelper.getManagedBean(fc, AVMBrowseBean.BEAN_NAME); - String path = AVMNodeConverter.ToAVMVersionPath(node.getNodeRef()).getSecond(); - String username = Application.getCurrentUser(fc).getUserName(); + final String path = AVMNodeConverter.ToAVMVersionPath(node.getNodeRef()).getSecond(); + final String username = Application.getCurrentUser(fc).getUserName(); - return avmLockService.hasAccess(avmBrowseBean.getWebProject().getNodeRef(), path, username); + WebProject webProject = avmBrowseBean.getWebProject(); + if (webProject == null) + { + // when in a workflow context, the WebProject may not be accurate on the browsebean + // so get the web project associated with the path + webProject = new WebProject(path); + } + return avmLockService.hasAccess(webProject.getNodeRef(), path, username); } } diff --git a/source/java/org/alfresco/web/bean/wcm/AVMBrowseBean.java b/source/java/org/alfresco/web/bean/wcm/AVMBrowseBean.java index 3730ddf86a..583764865a 100644 --- a/source/java/org/alfresco/web/bean/wcm/AVMBrowseBean.java +++ b/source/java/org/alfresco/web/bean/wcm/AVMBrowseBean.java @@ -74,6 +74,7 @@ import org.alfresco.web.bean.repository.Node; import org.alfresco.web.bean.repository.Repository; import org.alfresco.web.bean.repository.User; import org.alfresco.web.bean.wizard.WizardManager; +import org.alfresco.web.forms.*; import org.alfresco.web.ui.common.Utils; import org.alfresco.web.ui.common.component.IBreadcrumbHandler; import org.alfresco.web.ui.common.component.UIActionLink; @@ -85,6 +86,7 @@ import org.alfresco.web.ui.wcm.component.UISandboxSnapshots; import org.alfresco.web.ui.wcm.component.UIUserSandboxes; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.commons.lang.StringUtils; /** * Bean backing up the AVM specific browse screens @@ -601,7 +603,9 @@ public class AVMBrowseBean implements IContextListener public Node getWebsite() { // check to see if the website we are browsing has changed since the last time - if (!this.navigator.getCurrentNodeId().equals(this.lastWebsiteId)) + final Node currentNode = this.navigator.getCurrentNode(); + if (!this.navigator.getCurrentNodeId().equals(this.lastWebsiteId) || + !WCMAppModel.TYPE_AVMWEBFOLDER.equals(currentNode.getType())) { // clear context when we are browsing a new website this.lastWebsiteId = this.navigator.getCurrentNodeId(); @@ -609,7 +613,7 @@ public class AVMBrowseBean implements IContextListener this.webapps = null; this.webProject = null; } - return this.navigator.getCurrentNode(); + return WCMAppModel.TYPE_AVMWEBFOLDER.equals(currentNode.getType()) ? currentNode : null; } /** @@ -617,9 +621,10 @@ public class AVMBrowseBean implements IContextListener */ public WebProject getWebProject() { - if (this.webProject == null) + Node website = this.getWebsite(); + if (this.webProject == null && website != null) { - this.webProject = new WebProject(this.getWebsite().getNodeRef()); + this.webProject = new WebProject(website.getNodeRef()); } return this.webProject; } @@ -882,14 +887,11 @@ public class AVMBrowseBean implements IContextListener /** * Setup the context for a sandbox browse action */ - public void setupSandboxAction(ActionEvent event) + public void setupSandboxAction(final ActionEvent event) { - UIActionLink link = (UIActionLink)event.getComponent(); - Map params = link.getParameterMap(); - String store = params.get("store"); - String username = params.get("username"); - - setupSandboxActionImpl(store, username, true); + final UIActionLink link = (UIActionLink)event.getComponent(); + final Map params = link.getParameterMap(); + this.setupSandboxAction(params.get("store"), params.get("username")); } /** @@ -900,7 +902,7 @@ public class AVMBrowseBean implements IContextListener */ public void setupSandboxAction(String store, String username) { - setupSandboxActionImpl(store, username, true); + this.setupSandboxActionImpl(store, null, username, true); } /** @@ -910,20 +912,21 @@ public class AVMBrowseBean implements IContextListener * @param username The authority pertinent to the action (null for staging store actions) * @param reset True to reset the current path and AVM action node context */ - private void setupSandboxActionImpl(String store, String username, boolean reset) + private void setupSandboxActionImpl(final String store, + final String webapp, + final String username, + final boolean reset) { // can be null if it's the staging store - i.e. not a user specific store setUsername(username); // the store can be either a user store or the staging store if this is null - if (store != null) + // get the staging store from the current website node + this.setSandbox(store != null ? store : this.getStagingStore()); + + if (webapp != null) { - setSandbox(store); - } - else - { - // get the staging store from the current website node - setSandbox(this.getStagingStore()); + this.setWebapp(webapp); } // update UI state ready for return to the previous screen @@ -944,12 +947,11 @@ public class AVMBrowseBean implements IContextListener * * @param event ActionEvent */ - public void setupContentAction(ActionEvent event) + public void setupContentAction(final ActionEvent event) { - UIActionLink link = (UIActionLink)event.getComponent(); - Map params = link.getParameterMap(); - String path = params.get("id"); - setupContentAction(path, true); + final UIActionLink link = (UIActionLink)event.getComponent(); + final Map params = link.getParameterMap(); + this.setupContentAction(params.get("id"), true); } /*package*/ void setupContentAction(final String path, final boolean refresh) @@ -966,24 +968,30 @@ public class AVMBrowseBean implements IContextListener // calculate username and store name from specified path String storeName = AVMUtil.getStoreName(path); final String storeId = AVMUtil.getStoreId(storeName); + final String webapp = AVMUtil.getWebapp(path); final String username = AVMUtil.getUserName(storeName); if (username == null) { storeName = (AVMUtil.isPreviewStore(storeName) ? AVMUtil.buildStagingPreviewStoreName(storeId) : AVMUtil.buildStagingStoreName(storeId)); - setupSandboxActionImpl(storeName, null, false); + this.setupSandboxActionImpl(storeName, webapp, null, false); } else { storeName = (AVMUtil.isPreviewStore(storeName) ? AVMUtil.buildUserPreviewStoreName(storeId, username) : AVMUtil.buildUserMainStoreName(storeId, username)); - setupSandboxActionImpl(storeName, username, false); + this.setupSandboxActionImpl(storeName, webapp, username, false); + } + + if (this.webProject == null) + { + this.webProject = new WebProject(path); } // setup the action node - setAVMActionNodeDescriptor(avmService.lookup(-1, path, true)); + this.setAVMActionNodeDescriptor(avmService.lookup(-1, path, true)); } // update UI state ready for return after dialog close @@ -1026,21 +1034,44 @@ public class AVMBrowseBean implements IContextListener */ public void revertNode(ActionEvent event) { - String path = getPathFromEventArgs(event); - + final String path = getPathFromEventArgs(event); + final List namesForDisplayMsg = new LinkedList(); UserTransaction tx = null; + final FacesContext context = FacesContext.getCurrentInstance(); try { - FacesContext context = FacesContext.getCurrentInstance(); tx = Repository.getUserTransaction(context, false); tx.begin(); AVMNodeDescriptor node = this.avmService.lookup(-1, path, true); if (node != null) { - Map args = new HashMap(1, 1.0f); + FormInstanceData fid = null; + if (this.avmService.hasAspect(-1, path, WCMAppModel.ASPECT_RENDITION)) + { + fid = new RenditionImpl(-1, path).getPrimaryFormInstanceData(); + } + else if (this.avmService.hasAspect(-1, path, WCMAppModel.ASPECT_FORM_INSTANCE_DATA)) + { + fid = new FormInstanceDataImpl(-1, path); + } List> versionPaths = new ArrayList>(); - versionPaths.add(new Pair(-1, path)); + if (fid != null) + { + versionPaths.add(new Pair(-1, fid.getPath())); + namesForDisplayMsg.add(fid.getName()); + for (Rendition r : fid.getRenditions()) + { + versionPaths.add(new Pair(-1, r.getPath())); + namesForDisplayMsg.add(r.getName()); + } + } + else + { + versionPaths.add(new Pair(-1, path)); + namesForDisplayMsg.add(node.getName()); + } + final Map args = new HashMap(1, 1.0f); args.put(AVMUndoSandboxListAction.PARAM_NODE_LIST, (Serializable)versionPaths); Action action = this.actionService.createAction(AVMUndoSandboxListAction.NAME, args); this.actionService.executeAction(action, null); // dummy action ref @@ -1051,22 +1082,23 @@ public class AVMBrowseBean implements IContextListener // possibly update webapp after commit - if ( VirtServerUtils.requiresUpdateNotification( path ) ) + if (VirtServerUtils.requiresUpdateNotification(path)) { AVMUtil.updateVServerWebapp(path, true); } - // if we get here, all was well - output friendly status message to the user - String msg = MessageFormat.format(Application.getMessage( - context, MSG_REVERT_SUCCESS), node.getName()); - displayStatusMessage(context, msg); + this.displayStatusMessage(context, + MessageFormat.format(Application.getMessage(context, MSG_REVERT_SUCCESS), + StringUtils.join(namesForDisplayMsg.toArray(), ", "), + namesForDisplayMsg.size())); } catch (Throwable err) { err.printStackTrace(System.err); - Utils.addErrorMessage(MessageFormat.format(Application.getMessage( - FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err); + Utils.addErrorMessage(MessageFormat.format(Application.getMessage(context, Repository.ERROR_GENERIC), + err.getMessage()), + err); try { if (tx != null) {tx.rollback();} } catch (Exception tex) {} } } @@ -1116,9 +1148,10 @@ public class AVMBrowseBean implements IContextListener } // if we get here, all was well - output friendly status message to the user - String msg = MessageFormat.format(Application.getMessage( - context, MSG_REVERT_SANDBOX), sandbox, strVersion); - displayStatusMessage(context, msg); + this.displayStatusMessage(context, + MessageFormat.format(Application.getMessage(context, MSG_REVERT_SANDBOX), + sandbox, + strVersion)); } catch (Throwable err) { diff --git a/source/java/org/alfresco/web/bean/wcm/AVMEditBean.java b/source/java/org/alfresco/web/bean/wcm/AVMEditBean.java index 3516b42a0c..ef61ed54d3 100644 --- a/source/java/org/alfresco/web/bean/wcm/AVMEditBean.java +++ b/source/java/org/alfresco/web/bean/wcm/AVMEditBean.java @@ -37,7 +37,6 @@ import org.alfresco.service.cmr.avm.AVMService; import org.alfresco.service.cmr.avmsync.AVMSyncService; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.repository.ContentReader; -import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.web.app.AlfrescoNavigationHandler; import org.alfresco.web.app.Application; @@ -47,6 +46,7 @@ import org.alfresco.web.bean.repository.Repository; import org.alfresco.web.forms.Form; import org.alfresco.web.forms.FormInstanceData; import org.alfresco.web.forms.FormInstanceDataImpl; +import org.alfresco.web.forms.FormNotFoundException; import org.alfresco.web.forms.FormProcessor; import org.alfresco.web.forms.RenderingEngineTemplate; import org.alfresco.web.forms.Rendition; @@ -79,8 +79,6 @@ public class AVMEditBean private File file = null; private String fileName = null; - protected FormProcessor.Session formProcessorSession = null; - private Form form = null; /** AVM service bean reference */ protected AVMService avmService; @@ -91,13 +89,6 @@ public class AVMEditBean /** AVM Browse Bean reference */ protected AVMBrowseBean avmBrowseBean; - /** The ContentService bean reference */ - protected ContentService contentService; - - /** The FilePickerBean reference */ - protected FilePickerBean filePickerBean; - - // ------------------------------------------------------------------------------ // Bean property getters and setters @@ -125,22 +116,6 @@ public class AVMEditBean this.avmBrowseBean = avmBrowseBean; } - /** - * @param filePickerBean The FilePickerBean to set. - */ - public void setFilePickerBean(final FilePickerBean filePickerBean) - { - this.filePickerBean = filePickerBean; - } - - /** - * @param contentService The ContentService to set. - */ - public void setContentService(final ContentService contentService) - { - this.contentService = contentService; - } - /** * @return Returns the current AVM node context. */ @@ -213,9 +188,9 @@ public class AVMEditBean { // try and retrieve the file and filename from the file upload bean // representing the file we previously uploaded. - FacesContext ctx = FacesContext.getCurrentInstance(); - FileUploadBean fileBean = (FileUploadBean)ctx.getExternalContext().getSessionMap(). - get(FileUploadBean.FILE_UPLOAD_BEAN_NAME); + final FacesContext ctx = FacesContext.getCurrentInstance(); + final FileUploadBean fileBean = (FileUploadBean) + ctx.getExternalContext().getSessionMap().get(FileUploadBean.FILE_UPLOAD_BEAN_NAME); if (fileBean != null) { this.file = fileBean.getFile(); @@ -230,86 +205,8 @@ public class AVMEditBean */ public String getFileUploadSuccessMsg() { - String msg = Application.getMessage(FacesContext.getCurrentInstance(), MSG_UPLOAD_SUCCESS); - return MessageFormat.format(msg, new Object[] {getFileName()}); - } - - /** - * @return Returns the form when in the context of editing an xml asset. - */ - public Form getForm() - { - if (this.form == null) - { - final PropertyValue pv = - this.avmService.getNodeProperty(-1, - this.getAvmNode().getPath(), - WCMAppModel.PROP_PARENT_FORM_NAME); - - final String formName = (String)pv.getValue(DataTypeDefinition.TEXT); - final WebProject wp = new WebProject(this.getAvmNode().getPath()); - this.form = wp.getForm(formName); - - if (LOGGER.isDebugEnabled()) - LOGGER.debug("loaded form " + this.form + - ", form name " + formName + - ", for " + this.getAvmNode().getPath()); - } - return this.form; - } - - /** - * @return Returns the wrapper instance data for feeding the xml - * content to the form processor. - */ - public Document getInstanceDataDocument() - { - if (this.instanceDataDocument == null) - { - final String content = this.getEditorOutput(); - try - { - this.instanceDataDocument = (content != null - ? XMLUtil.parse(content) - : XMLUtil.newDocument()); - } - catch (Exception e) - { - Utils.addErrorMessage("error parsing document", e); - return XMLUtil.newDocument(); - } - } - return this.instanceDataDocument; - } - - /** - * Returns the name of the form instance data for display purposes. - */ - public String getFormInstanceDataName() - { - final FormInstanceData fid = new FormInstanceDataImpl(-1, this.getAvmNode().getPath()); - return fid.getName().replaceAll("(.+)\\..*", "$1"); - } - - /** - * Returns the form processor session. - */ - public FormProcessor.Session getFormProcessorSession() - { - return this.formProcessorSession; - } - - /** - * Sets the form processor session. - */ - public void setFormProcessorSession(final FormProcessor.Session formProcessorSession) - { - if (this.formProcessorSession != null && - this.formProcessorSession != formProcessorSession) - { - this.formProcessorSession.destroy(); - } - this.formProcessorSession = formProcessorSession; + final String msg = Application.getMessage(FacesContext.getCurrentInstance(), MSG_UPLOAD_SUCCESS); + return MessageFormat.format(msg, new Object[] { this.getFileName() }); } // ------------------------------------------------------------------------------ @@ -319,12 +216,11 @@ public class AVMEditBean * Action handler called to calculate which editing screen to display based on the mimetype * of a document. If appropriate, the in-line editing screen will be shown. */ - public void setupEditAction(ActionEvent event) + public void setupEditAction(final ActionEvent event) { - UIActionLink link = (UIActionLink)event.getComponent(); - Map params = link.getParameterMap(); - String path = params.get("id"); - setupEditAction(path); + final UIActionLink link = (UIActionLink)event.getComponent(); + final Map params = link.getParameterMap(); + this.setupEditAction(params.get("id")); } /** @@ -374,8 +270,6 @@ public class AVMEditBean this.avmSyncService.resetLayer(rootPath); } - this.filePickerBean.clearUploadedFiles(); - if (LOGGER.isDebugEnabled()) LOGGER.debug("Editing AVM node: " + avmPath); @@ -390,12 +284,9 @@ public class AVMEditBean { // make content available to the editing screen this.setEditorOutput(reader.getContentString()); - this.setFormProcessorSession(null); - this.instanceDataDocument = null; - this.form = null; // navigate to appropriate screen - outcome = "dialog:editXmlInline"; + outcome = "wizard:editWebContent"; } else { @@ -447,12 +338,11 @@ public class AVMEditBean tx.begin(); // get an updating writer that we can use to modify the content on the current node - ContentWriter writer = this.contentService.getWriter(node.getNodeRef(), ContentModel.PROP_CONTENT, true); + final ContentWriter writer = this.avmService.getContentWriter(node.getPath()); // also update the mime type in case a different type of file is uploaded String mimeType = Repository.getMimeTypeForFileName(context, this.fileName); writer.setMimetype(mimeType); - writer.putContent(this.file); // commit the transaction @@ -487,21 +377,17 @@ public class AVMEditBean public String cancel() { // reset the state - resetState(); + this.resetState(); return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; } - /*package*/ void resetState() + private void resetState() { // clean up and clear action context clearUpload(); setDocumentContent(null); setEditorOutput(null); - this.setFormProcessorSession(null); - this.instanceDataDocument = null; - this.form = null; - this.filePickerBean.clearUploadedFiles(); } /** @@ -523,13 +409,27 @@ public class AVMEditBean ctx.getExternalContext().getSessionMap().remove(FileUploadBean.FILE_UPLOAD_BEAN_NAME); } - /*package*/ void regenerateRenditions() + private void regenerateRenditions() + throws FormNotFoundException { final String avmPath = this.getAvmNode().getPath(); - final FormInstanceData fid = new FormInstanceDataImpl(AVMNodeConverter.ToNodeRef(-1, avmPath)) + final FormInstanceData fid = new FormInstanceDataImpl(-1, avmPath) { @Override - public Form getForm() { return AVMEditBean.this.getForm(); } + public Form getForm() + throws FormNotFoundException + { + final WebProject wp = new WebProject(this.getPath()); + Form f = super.getForm(); + try + { + return wp.getForm(f.getName()); + } + catch (FormNotFoundException fnfe) + { + throw new FormNotFoundException(f, wp, this); + } + } }; final List result = fid.regenerateRenditions(); for (FormInstanceData.RegenerateResult rr : result) diff --git a/source/java/org/alfresco/web/bean/wcm/CreateFormWizard.java b/source/java/org/alfresco/web/bean/wcm/CreateFormWizard.java index 0545dc1777..f6a7a1ac8e 100644 --- a/source/java/org/alfresco/web/bean/wcm/CreateFormWizard.java +++ b/source/java/org/alfresco/web/bean/wcm/CreateFormWizard.java @@ -590,6 +590,10 @@ public class CreateFormWizard LOGGER.debug("removing uploaded rendering engine template file " + this.getRenderingEngineTemplateFileName()); this.clearUpload(FILE_SCHEMA); + this.formName = null; + this.formTitle = null; + this.formDescription = null; + this.outputPathPatternForFormInstanceData = null; this.schemaRootElementNameChoices = null; this.schema = null; this.schemaFileName = null; @@ -607,6 +611,11 @@ public class CreateFormWizard this.getRenderingEngineTemplateFileName()); this.clearUpload(FILE_RENDERING_ENGINE_TEMPLATE); this.renderingEngineTemplateFileName = null; + this.renderingEngineTemplateName = null; + this.renderingEngineTemplateTitle = null; + this.renderingEngineTemplateDescription = null; + this.outputPathPatternForRendition = null; + this.mimetypeForRendition = null; assert this.getRenderingEngineTemplateFileName() == null; // refresh the current page return null; diff --git a/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java b/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java index ed86c5324c..8e500b9ffa 100644 --- a/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java +++ b/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java @@ -73,6 +73,7 @@ import org.alfresco.web.data.QuickSort; import org.alfresco.web.forms.Form; import org.alfresco.web.forms.FormInstanceData; import org.alfresco.web.forms.FormInstanceDataImpl; +import org.alfresco.web.forms.FormNotFoundException; import org.alfresco.web.forms.FormProcessor; import org.alfresco.web.forms.FormsService; import org.alfresco.web.forms.RenderingEngineTemplate; @@ -101,7 +102,7 @@ public class CreateWebContentWizard extends BaseContentWizard protected List renditions = null; protected FormInstanceData formInstanceData = null; protected FormProcessor.Session formProcessorSession = null; - private Document instanceDataDocument = null; + protected Document instanceDataDocument = null; protected boolean formSelectDisabled = false; protected boolean startWorkflow = false; @@ -204,11 +205,18 @@ public class CreateWebContentWizard extends BaseContentWizard { // it is used to init the dialog to a specific template final String formName = parameters.get(UIUserSandboxes.PARAM_FORM_NAME); - final Form form = this.avmBrowseBean.getWebProject().getForm(formName); - if (form != null) + try { - this.formName = form.getName(); - this.formSelectDisabled = true; + final Form form = this.avmBrowseBean.getWebProject().getForm(formName); + if (form != null) + { + this.formName = form.getName(); + this.formSelectDisabled = true; + } + } + catch (FormNotFoundException fnfe) + { + Utils.addErrorMessage(fnfe.getMessage(), fnfe); } } @@ -224,8 +232,7 @@ public class CreateWebContentWizard extends BaseContentWizard @Override public String next() { - final int step = Application.getWizardManager().getCurrentStep(); - if (step == 3) + if ("summary".equals(Application.getWizardManager().getCurrentStepName())) { // if rendering a form, then save the content now to generate the renditions if (MimetypeMap.MIMETYPE_XML.equals(this.mimeType)) @@ -236,7 +243,7 @@ public class CreateWebContentWizard extends BaseContentWizard } catch (Exception e) { - Application.getWizardManager().getState().setCurrentStep(step - 1); + Application.getWizardManager().getState().setCurrentStep(Application.getWizardManager().getCurrentStep() - 1); Utils.addErrorMessage(e.getMessage(), e); } } @@ -247,13 +254,12 @@ public class CreateWebContentWizard extends BaseContentWizard @Override public String back() { - final int step = Application.getWizardManager().getCurrentStep(); - if (step == 2) + if ("content".equals(Application.getWizardManager().getCurrentStepName())) { - if (LOGGER.isDebugEnabled()) - LOGGER.debug("clearing form instance data"); if (this.formInstanceData != null) { + if (LOGGER.isDebugEnabled()) + LOGGER.debug("clearing form instance data: " + this.formInstanceData.getPath()); this.avmService.removeNode(this.formInstanceData.getPath()); } if (this.renditions != null) @@ -444,7 +450,7 @@ public class CreateWebContentWizard extends BaseContentWizard if (MimetypeMap.MIMETYPE_XML.equals(this.mimeType) && this.formName != null) { - this.formInstanceData = new FormInstanceDataImpl(AVMNodeConverter.ToNodeRef(-1, this.createdPath)); + this.formInstanceData = new FormInstanceDataImpl(-1, this.createdPath); this.renditions = this.formInstanceData.getRenditions(); if (LOGGER.isDebugEnabled()) LOGGER.debug("reset form instance data " + this.formInstanceData.getName() + @@ -461,8 +467,7 @@ public class CreateWebContentWizard extends BaseContentWizard // checking step numbers boolean disabled = false; - int step = Application.getWizardManager().getCurrentStep(); - if (step == 1) + if ("details".equals(Application.getWizardManager().getCurrentStepName())) { disabled = (this.fileName == null || this.fileName.length() == 0); } @@ -675,6 +680,7 @@ public class CreateWebContentWizard extends BaseContentWizard } public Form getForm() + throws FormNotFoundException { return (this.getFormName() != null ? this.avmBrowseBean.getWebProject().getForm(this.getFormName()) @@ -802,6 +808,11 @@ public class CreateWebContentWizard extends BaseContentWizard return this.startWorkflow; } + public boolean getSubmittable() + { + return true; + } + /** * Provides the url to the preview sandbox containing the asset currently * being edited. @@ -809,7 +820,7 @@ public class CreateWebContentWizard extends BaseContentWizard public String getPreviewSandboxUrl() { return AVMUtil.buildWebappUrl(AVMUtil.getCorrespondingPreviewStoreName(this.avmBrowseBean.getSandbox()), - this.avmBrowseBean.getWebapp()); + this.avmBrowseBean.getWebapp()); } public String getSummary() @@ -831,6 +842,11 @@ public class CreateWebContentWizard extends BaseContentWizard this.getSummaryMimeType(this.mimeType) }); } + + public boolean getEditMode() + { + return false; + } // ------------------------------------------------------------------------------ // Action event handlers diff --git a/source/java/org/alfresco/web/bean/wcm/DeleteFileDialog.java b/source/java/org/alfresco/web/bean/wcm/DeleteFileDialog.java index f6139c1199..a60eba05aa 100644 --- a/source/java/org/alfresco/web/bean/wcm/DeleteFileDialog.java +++ b/source/java/org/alfresco/web/bean/wcm/DeleteFileDialog.java @@ -24,14 +24,19 @@ */ package org.alfresco.web.bean.wcm; +import java.io.FileNotFoundException; +import java.util.List; import java.text.MessageFormat; import javax.faces.context.FacesContext; +import org.alfresco.model.WCMAppModel; +import org.alfresco.repo.avm.AVMNodeConverter; import org.alfresco.service.cmr.avm.AVMService; import org.alfresco.web.app.AlfrescoNavigationHandler; import org.alfresco.web.app.Application; import org.alfresco.web.bean.dialog.BaseDialogBean; +import org.alfresco.web.forms.*; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -69,20 +74,48 @@ public class DeleteFileDialog extends BaseDialogBean // Dialog implementation @Override - protected String finishImpl(FacesContext context, String outcome) - throws Exception + protected String finishImpl(final FacesContext context, final String outcome) + throws Exception { // get the content to delete - AVMNode node = this.avmBrowseBean.getAvmActionNode(); + final AVMNode node = this.avmBrowseBean.getAvmActionNode(); if (node != null) { if (logger.isDebugEnabled()) logger.debug("Trying to delete AVM node: " + node.getPath()); - - // delete the node - this.avmService.removeNode( - node.getPath().substring(0, node.getPath().lastIndexOf('/')), - node.getPath().substring(node.getPath().lastIndexOf('/') + 1)); + FormInstanceData fid = null; + if (node.hasAspect(WCMAppModel.ASPECT_RENDITION)) + { + try + { + fid = new RenditionImpl(node.getNodeRef()).getPrimaryFormInstanceData(); + } + catch (FileNotFoundException fnfe) + { + //ignore + } + } + else if (node.hasAspect(WCMAppModel.ASPECT_FORM_INSTANCE_DATA)) + { + fid = new FormInstanceDataImpl(node.getNodeRef()); + } + if (fid != null) + { + final List renditions = fid.getRenditions(); + for (final Rendition r : renditions) + { + this.avmService.removeNode(AVMNodeConverter.SplitBase(r.getPath())[0], + AVMNodeConverter.SplitBase(r.getPath())[1]); + } + this.avmService.removeNode(AVMNodeConverter.SplitBase(fid.getPath())[0], + AVMNodeConverter.SplitBase(fid.getPath())[1]); + } + else + { + // delete the node + this.avmService.removeNode(AVMNodeConverter.SplitBase(node.getPath())[0], + AVMNodeConverter.SplitBase(node.getPath())[1]); + } } else { @@ -93,7 +126,8 @@ public class DeleteFileDialog extends BaseDialogBean } @Override - protected String doPostCommitProcessing(FacesContext context, String outcome) + protected String doPostCommitProcessing(final FacesContext context, + final String outcome) { return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; } @@ -121,10 +155,35 @@ public class DeleteFileDialog extends BaseDialogBean */ public String getConfirmMessage() { - String fileConfirmMsg = Application.getMessage(FacesContext.getCurrentInstance(), - "delete_avm_file_confirm"); - - return MessageFormat.format(fileConfirmMsg, - new Object[] {this.avmBrowseBean.getAvmActionNode().getName()}); + final AVMNode node = this.avmBrowseBean.getAvmActionNode(); + if (node.hasAspect(WCMAppModel.ASPECT_RENDITION)) + { + try + { + final FormInstanceData fid = new RenditionImpl(node.getNodeRef()).getPrimaryFormInstanceData(); + return MessageFormat.format(Application.getMessage(FacesContext.getCurrentInstance(), + "delete_rendition_confirm"), + node.getName(), + fid.getName(), + fid.getRenditions().size() - 1); + + } + catch (FileNotFoundException fnfe) + { + //ignore + } + } + else if (node.hasAspect(WCMAppModel.ASPECT_FORM_INSTANCE_DATA)) + { + final FormInstanceData fid = new FormInstanceDataImpl(node.getNodeRef()); + return MessageFormat.format(Application.getMessage(FacesContext.getCurrentInstance(), + "delete_form_instance_data_confirm"), + fid.getName(), + fid.getRenditions().size()); + + } + return MessageFormat.format(Application.getMessage(FacesContext.getCurrentInstance(), + "delete_avm_file_confirm"), + node.getName()); } } diff --git a/source/java/org/alfresco/web/bean/wcm/EditFormWizard.java b/source/java/org/alfresco/web/bean/wcm/EditFormWizard.java index 7defb102d0..edae99cf3e 100644 --- a/source/java/org/alfresco/web/bean/wcm/EditFormWizard.java +++ b/source/java/org/alfresco/web/bean/wcm/EditFormWizard.java @@ -74,9 +74,6 @@ public class EditFormWizard { super.init(parameters); - // the editMode flag is used to disabled some wizard fields - // this.editMode = true; - final NodeRef formNodeRef = this.browseBean.getActionSpace().getNodeRef(); if (formNodeRef == null) { diff --git a/source/java/org/alfresco/web/bean/wcm/EditWebContentWizard.java b/source/java/org/alfresco/web/bean/wcm/EditWebContentWizard.java new file mode 100644 index 0000000000..51004b7123 --- /dev/null +++ b/source/java/org/alfresco/web/bean/wcm/EditWebContentWizard.java @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing + */ +package org.alfresco.web.bean.wcm; + +import java.io.ByteArrayInputStream; +import java.io.Serializable; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.ResourceBundle; + +import javax.faces.context.FacesContext; +import javax.faces.event.ValueChangeEvent; +import javax.faces.model.SelectItem; + +import org.alfresco.config.Config; +import org.alfresco.config.ConfigElement; +import org.alfresco.config.ConfigService; +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.model.ContentModel; +import org.alfresco.model.WCMAppModel; +import org.alfresco.model.WCMWorkflowModel; +import org.alfresco.repo.avm.AVMNodeConverter; +import org.alfresco.repo.avm.wf.AVMSubmittedAspect; +import org.alfresco.repo.content.MimetypeMap; +import org.alfresco.repo.workflow.WorkflowModel; +import org.alfresco.service.cmr.avm.AVMExistsException; +import org.alfresco.service.cmr.avm.AVMNodeDescriptor; +import org.alfresco.service.cmr.avm.AVMService; +import org.alfresco.service.cmr.avmsync.AVMDifference; +import org.alfresco.service.cmr.avmsync.AVMSyncService; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.workflow.WorkflowDefinition; +import org.alfresco.service.cmr.workflow.WorkflowPath; +import org.alfresco.service.cmr.workflow.WorkflowService; +import org.alfresco.service.cmr.workflow.WorkflowTask; +import org.alfresco.service.cmr.workflow.WorkflowTaskState; +import org.alfresco.service.namespace.QName; +import org.alfresco.service.namespace.RegexQNamePattern; +import org.alfresco.web.app.Application; +import org.alfresco.web.bean.content.BaseContentWizard; +import org.alfresco.web.bean.repository.Node; +import org.alfresco.web.bean.repository.Repository; +import org.alfresco.web.data.IDataContainer; +import org.alfresco.web.data.QuickSort; +import org.alfresco.web.forms.Form; +import org.alfresco.web.forms.FormInstanceData; +import org.alfresco.web.forms.FormInstanceDataImpl; +import org.alfresco.web.forms.FormNotFoundException; +import org.alfresco.web.forms.FormProcessor; +import org.alfresco.web.forms.FormsService; +import org.alfresco.web.forms.RenderingEngineTemplate; +import org.alfresco.web.forms.Rendition; +import org.alfresco.web.forms.XMLUtil; +import org.alfresco.web.ui.common.Utils; +import org.alfresco.web.ui.common.component.UIListItem; +import org.alfresco.web.ui.wcm.component.UIUserSandboxes; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.w3c.dom.Document; + +/** + * Bean implementation for the "Edit Web Content Wizard" dialog + */ +public class EditWebContentWizard extends CreateWebContentWizard +{ + private static final Log LOGGER = LogFactory.getLog(EditWebContentWizard.class); + + private AVMNode avmNode; + private Form form; + + // ------------------------------------------------------------------------------ + // Wizard implementation + + @Override + public void init(final Map parameters) + { + super.init(parameters); + this.avmNode = this.avmBrowseBean.getAvmActionNode(); + if (this.avmNode == null) + { + throw new IllegalArgumentException("Edit Form wizard requires action node context."); + } + LOGGER.debug("path is " + this.avmNode.getPath()); + this.createdPath = AVMUtil.getCorrespondingPathInPreviewStore(this.avmNode.getPath()); + this.formInstanceData = new FormInstanceDataImpl(-1, this.createdPath); + final WebProject webProject = new WebProject(this.createdPath); + try + { + this.formName = this.formInstanceData.getForm().getName(); + this.form = webProject.getForm(this.formName); + } + catch (FormNotFoundException fnfe) + { + Utils.addErrorMessage(fnfe.getMessage(), fnfe); + } + this.content = this.avmService.getContentReader(-1, this.createdPath).getContentString(); + this.fileName = this.formInstanceData.getName(); + this.mimeType = MimetypeMap.MIMETYPE_XML; + } + + @Override + public String back() + { + if ("content".equals(Application.getWizardManager().getCurrentStepName())) + { + //override in order not to delete these items + this.formInstanceData = null; + this.renditions = null; + } + return super.back(); + } + + @Override + protected void saveContent() + throws Exception + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("saving " + this.createdPath); + } + final ContentWriter writer = this.avmService.getContentWriter(this.createdPath); + this.content = XMLUtil.toString(this.instanceDataDocument, false); + writer.putContent(this.content); + this.formInstanceData = new FormInstanceDataImpl(-1, this.createdPath) + { + @Override + public Form getForm() + throws FormNotFoundException + { + return EditWebContentWizard.this.getForm(); + } + }; + final List result = this.formInstanceData.regenerateRenditions(); + this.renditions = new LinkedList(); + for (FormInstanceData.RegenerateResult rr : result) + { + if (rr.getException() != null) + { + Utils.addErrorMessage("error regenerating rendition using " + rr.getRenderingEngineTemplate().getName() + + ": " + rr.getException().getMessage(), + rr.getException()); + } + else + { + this.renditions.add(rr.getRendition()); + } + } + } + + /** Indicates whether or not the wizard is currently in edit mode */ + @Override + public boolean getEditMode() + { + return true; + } + + @Override + public boolean getSubmittable() + { + return !AVMUtil.isWorkflowStore(AVMUtil.getStoreName(this.createdPath)); + } + + /** + * Overridden to avoid calling getWebProject since potentially there is no web project + * context in workflow scenario. + */ + @Override + public Form getForm() + { + return this.form; + } +} diff --git a/source/java/org/alfresco/web/bean/wcm/EditWebsiteWizard.java b/source/java/org/alfresco/web/bean/wcm/EditWebsiteWizard.java index 7bdf5fef41..b74469a635 100644 --- a/source/java/org/alfresco/web/bean/wcm/EditWebsiteWizard.java +++ b/source/java/org/alfresco/web/bean/wcm/EditWebsiteWizard.java @@ -39,6 +39,7 @@ import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.RegexQNamePattern; import org.alfresco.web.app.AlfrescoNavigationHandler; import org.alfresco.web.forms.Form; +import org.alfresco.web.forms.FormNotFoundException; import org.alfresco.web.forms.FormsService; import org.alfresco.web.forms.RenderingEngineTemplate; @@ -95,9 +96,9 @@ public class EditWebsiteWizard extends CreateWebsiteWizard NodeRef formRef = ref.getChildRef(); String name = (String)this.nodeService.getProperty(formRef, WCMAppModel.PROP_FORMNAME); - Form formImpl = FormsService.getInstance().getForm(name); - if (formImpl != null) + try { + final Form formImpl = FormsService.getInstance().getForm(name); FormWrapper form = new FormWrapper(formImpl); form.setTitle((String)this.nodeService.getProperty(formRef, ContentModel.PROP_TITLE)); form.setDescription((String)this.nodeService.getProperty(formRef, ContentModel.PROP_DESCRIPTION)); @@ -143,6 +144,10 @@ public class EditWebsiteWizard extends CreateWebsiteWizard this.forms.add(form); } + catch (FormNotFoundException fnfe) + { + //ignore + } } // load the workflows associated with the website diff --git a/source/java/org/alfresco/web/bean/wcm/EditXmlInlineDialog.java b/source/java/org/alfresco/web/bean/wcm/EditXmlInlineDialog.java deleted file mode 100644 index 7be02d7f95..0000000000 --- a/source/java/org/alfresco/web/bean/wcm/EditXmlInlineDialog.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (C) 2005-2007 Alfresco Software Limited. - * - * 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 2 - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - * As a special exception to the terms and conditions of version 2.0 of - * the GPL, you may redistribute this Program in connection with Free/Libre - * and Open Source Software ("FLOSS") applications as described in Alfresco's - * FLOSS exception. You should have recieved a copy of the text describing - * the FLOSS exception, and it is also available here: - * http://www.alfresco.com/legal/licensing - */ -package org.alfresco.web.bean.wcm; - -import java.util.ArrayList; -import java.util.List; - -import javax.faces.context.FacesContext; - -import org.alfresco.model.WCMAppModel; -import org.alfresco.repo.avm.AVMNodeConverter; -import org.alfresco.service.cmr.avm.AVMService; -import org.alfresco.service.cmr.avmsync.AVMDifference; -import org.alfresco.service.cmr.avmsync.AVMSyncService; -import org.alfresco.service.cmr.repository.ContentWriter; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.web.app.AlfrescoNavigationHandler; -import org.alfresco.web.app.Application; -import org.alfresco.web.bean.dialog.BaseDialogBean; -import org.alfresco.web.forms.XMLUtil; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * @author Kevin Roast - */ -public class EditXmlInlineDialog extends BaseDialogBean -{ - private static final Log logger = LogFactory.getLog(EditXmlInlineDialog.class); - - /** AVM Edit Bean reference */ - private AVMEditBean avmEditBean; - - /** AVM service bean reference */ - protected AVMService avmService; - - /** AVM sync service bean reference */ - protected AVMSyncService avmSyncService; - - /** The FilePickerBean reference */ - protected FilePickerBean filePickerBean; - - - /** - * @param avmEditBean The AVMEditBean to set. - */ - public void setAvmEditBean(AVMEditBean avmEditBean) - { - this.avmEditBean = avmEditBean; - } - - /** - * @param avmService The AVMService to set. - */ - public void setAvmService(final AVMService avmService) - { - this.avmService = avmService; - } - - /** - * @param avmSyncService The AVMSyncService to set. - */ - public void setAvmSyncService(final AVMSyncService avmSyncService) - { - this.avmSyncService = avmSyncService; - } - - /** - * @param filePickerBean The FilePickerBean to set. - */ - public void setFilePickerBean(final FilePickerBean filePickerBean) - { - this.filePickerBean = filePickerBean; - } - - @Override - public String getContainerTitle() - { - return this.avmEditBean.getAvmNode().getName(); - } - - /** - * @see org.alfresco.web.bean.dialog.BaseDialogBean#finishImpl(javax.faces.context.FacesContext, java.lang.String) - */ - @Override - protected String finishImpl(FacesContext context, String outcome) throws Exception - { - AVMNode avmNode = this.avmEditBean.getAvmNode(); - if (avmNode == null) - { - return null; - } - - String avmPath = avmNode.getPath(); - - if (logger.isDebugEnabled()) - logger.debug("saving " + avmPath); - - // get an updating writer that we can use to modify the content on the current node - final ContentWriter writer = this.avmService.getContentWriter(avmPath); - String editorOutput = this.avmEditBean.getEditorOutput(); - if (this.avmService.hasAspect(-1, avmPath, WCMAppModel.ASPECT_FORM_INSTANCE_DATA)) - { - editorOutput = XMLUtil.toString(this.avmEditBean.getInstanceDataDocument(), false); - this.avmEditBean.setEditorOutput(editorOutput); - } - writer.putContent(editorOutput); - - return outcome; - } - - @Override - protected String doPostCommitProcessing(FacesContext context, String outcome) - { - AVMNode avmNode = this.avmEditBean.getAvmNode(); - String avmPath = avmNode.getPath(); - - // regenerate form content - if (this.avmService.hasAspect(-1, avmPath, WCMAppModel.ASPECT_FORM_INSTANCE_DATA)) - { - this.avmEditBean.regenerateRenditions(); - } - final NodeRef[] uploadedFiles = this.filePickerBean.getUploadedFiles(); - - if (logger.isDebugEnabled()) - logger.debug("updating " + uploadedFiles.length + " uploaded files"); - - final List diffList = new ArrayList(uploadedFiles.length); - for (NodeRef uploadedFile : uploadedFiles) - { - final String path = AVMNodeConverter.ToAVMVersionPath(uploadedFile).getSecond(); - diffList.add(new AVMDifference(-1, path, - -1, AVMUtil.getCorrespondingPathInMainStore(path), - AVMDifference.NEWER)); - } - this.avmSyncService.update(diffList, null, true, true, true, true, null, null); - - // Possibly notify virt server - AVMUtil.updateVServerWebapp(avmNode.getPath(), false); - - this.avmEditBean.resetState(); - - return outcome; - } - - @Override - public String cancel() - { - super.cancel(); - - // reset the state - this.avmEditBean.resetState(); - - return AlfrescoNavigationHandler.CLOSE_DIALOG_OUTCOME; - } - - @Override - public boolean getFinishButtonDisabled() - { - return false; - } - - @Override - public String getFinishButtonLabel() - { - return Application.getMessage(FacesContext.getCurrentInstance(), "save"); - } -} diff --git a/source/java/org/alfresco/web/bean/wcm/FilePickerBean.java b/source/java/org/alfresco/web/bean/wcm/FilePickerBean.java index ddaed5c29f..a2ec6549f0 100644 --- a/source/java/org/alfresco/web/bean/wcm/FilePickerBean.java +++ b/source/java/org/alfresco/web/bean/wcm/FilePickerBean.java @@ -24,6 +24,7 @@ package org.alfresco.web.bean.wcm; import java.io.*; +import java.util.regex.Pattern; import java.text.MessageFormat; import java.util.*; @@ -35,6 +36,7 @@ import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import org.alfresco.model.ContentModel; +import org.alfresco.model.WCMModel; import org.alfresco.repo.avm.AVMNodeConverter; import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.domain.PropertyValue; @@ -43,6 +45,7 @@ import org.alfresco.service.cmr.avm.AVMService; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.alfresco.util.TempFileProvider; import org.alfresco.web.app.Application; @@ -58,6 +61,7 @@ import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.fileupload.servlet.ServletRequestContext; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.util.FileCopyUtils; @@ -80,6 +84,7 @@ public class FilePickerBean private AVMBrowseBean avmBrowseBean; private AVMService avmService; + private NamespaceService namespaceService; public FilePickerBean() { @@ -111,6 +116,14 @@ public class FilePickerBean this.avmService = avmService; } + /** + * @param namespaceService the namespaceService to set. + */ + public void setNamespaceService(final NamespaceService namespaceService) + { + this.namespaceService = namespaceService; + } + /** * Provides data for a file picker widget. */ @@ -121,8 +134,7 @@ public class FilePickerBean final FacesContext facesContext = FacesContext.getCurrentInstance(); final ExternalContext externalContext = facesContext.getExternalContext(); - final Map requestParameters = externalContext.getRequestParameterMap(); - String currentPath = (String)requestParameters.get("currentPath"); + String currentPath = (String)externalContext.getRequestParameterMap().get("currentPath"); if (currentPath == null) { currentPath = this.getCurrentAVMPath(); @@ -135,7 +147,18 @@ public class FilePickerBean currentPath, AVMUtil.PathRelation.WEBAPP_RELATIVE); } - LOGGER.debug(this + ".getFilePickerData(" + currentPath + ")"); + + final QName[] selectableTypes = + this.getSelectableTypes((String[])externalContext.getRequestParameterValuesMap().get("selectableTypes")); + final Pattern[] filterMimetypes = + this.getFilterMimetypes((String[])externalContext.getRequestParameterValuesMap().get("filterMimetypes")); + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug(this + ".getFilePickerData(path = " + currentPath + + ", selectableTypes = [" + StringUtils.join(selectableTypes, ",") + + "], filterMimetypes = [" + StringUtils.join(filterMimetypes, ",") + + "])"); + } final Document result = XMLUtil.newDocument(); final Element filePickerDataElement = result.createElement("file-picker-data"); @@ -149,8 +172,11 @@ public class FilePickerBean filePickerDataElement.setAttribute("error", MessageFormat.format(Application.getMessage(facesContext, "error_not_found"), - currentPath.substring(currentPath.lastIndexOf("/") + 1, currentPath.length()), - currentPath.lastIndexOf("/") == 0 ? "/" : currentPath.substring(0, currentPath.lastIndexOf("/")))); + currentPath.substring(currentPath.lastIndexOf("/") + 1, + currentPath.length()), + (currentPath.lastIndexOf("/") == 0 + ? "/" + : currentPath.substring(0, currentPath.lastIndexOf("/"))))); currentPath = this.getCurrentAVMPath(); } else if (! currentNode.isDirectory()) @@ -166,9 +192,30 @@ public class FilePickerBean e.setAttribute("image", "/images/icons/space_small.gif"); filePickerDataElement.appendChild(e); - for (Map.Entry entry : + for (final Map.Entry entry : this.avmService.getDirectoryListing(-1, currentPath).entrySet()) { + if (!entry.getValue().isDirectory() && filterMimetypes.length != 0) + { + final String contentMimetype = this.avmService.getContentDataForRead(entry.getValue()).getMimetype(); + boolean matched = false; + for (final Pattern p : filterMimetypes) + { + matched = p.matcher(contentMimetype).matches(); + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug(p + ".matches(" + contentMimetype + ") = " + matched); + } + if (matched) + { + break; + } + } + if (!matched) + { + continue; + } + } e = result.createElement("child-node"); e.setAttribute("avmPath", entry.getValue().getPath()); e.setAttribute("webappRelativePath", @@ -179,6 +226,18 @@ public class FilePickerBean : Utils.getFileTypeImage(facesContext, entry.getValue().getName(), true))); + + boolean selectable = false; + // faking this for now since i can't figure out how to efficiently get the type + // qname from the avmservice + for (final QName typeQName : selectableTypes) + { + selectable = selectable || (WCMModel.TYPE_AVM_FOLDER.equals(typeQName) && + entry.getValue().isDirectory()); + selectable = selectable || (WCMModel.TYPE_AVM_CONTENT.equals(typeQName) && + !entry.getValue().isDirectory()); + } + e.setAttribute("selectable", Boolean.toString(selectable)); filePickerDataElement.appendChild(e); } @@ -208,16 +267,25 @@ public class FilePickerBean InputStream fileInputStream = null; for (FileItem item : fileItems) { - LOGGER.debug("item = " + item); + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("item = " + item); + } if (item.isFormField() && item.getFieldName().equals("upload-id")) { uploadId = item.getString(); - LOGGER.debug("uploadId is " + uploadId); + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("uploadId is " + uploadId); + } } if (item.isFormField() && item.getFieldName().equals("return-page")) { returnPage = item.getString(); - LOGGER.debug("returnPage is " + returnPage); + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("returnPage is " + returnPage); + } } else if (item.isFormField() && item.getFieldName().equals("currentPath")) { @@ -226,17 +294,27 @@ public class FilePickerBean currentPath = AVMUtil.buildPath(previewStorePath, item.getString(), AVMUtil.PathRelation.WEBAPP_RELATIVE); - LOGGER.debug("currentPath is " + currentPath); + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("currentPath is " + currentPath); + } } else { filename = FilenameUtils.getName(item.getName()); fileInputStream = item.getInputStream(); - LOGGER.debug("uploading file " + filename); + + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("uploading file " + filename); + } } } - LOGGER.debug("saving file " + filename + " to " + currentPath); + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("saving file " + filename + " to " + currentPath); + } try { @@ -279,7 +357,7 @@ public class FilePickerBean private String getCurrentAVMPath() { - AVMNode node = this.avmBrowseBean.getAvmActionNode(); + final AVMNode node = this.avmBrowseBean.getAvmActionNode(); if (node == null) { return this.avmBrowseBean.getCurrentPath(); @@ -288,4 +366,33 @@ public class FilePickerBean final String result = node.getPath(); return node.isDirectory() ? result : AVMNodeConverter.SplitBase(result)[0]; } -} \ No newline at end of file + + private QName[] getSelectableTypes(final String[] selectableTypes) + { + final QName[] result = (selectableTypes == null + ? new QName[] { WCMModel.TYPE_AVM_CONTENT, WCMModel.TYPE_AVM_FOLDER } + : new QName[selectableTypes.length]); + + if (selectableTypes != null) + { + for (int i = 0; i < selectableTypes.length; i++) + { + result[i] = QName.resolveToQName(this.namespaceService, selectableTypes[i]); + } + } + return result; + } + + private Pattern[] getFilterMimetypes(final String[] filterMimetypes) + { + final Pattern[] result = filterMimetypes == null ? new Pattern[0] : new Pattern[filterMimetypes.length]; + if (filterMimetypes != null) + { + for (int i = 0; i < filterMimetypes.length; i++) + { + result[i] = Pattern.compile(filterMimetypes[i].replaceAll("\\*", "\\.*").replaceAll("\\/", "\\\\/")); + } + } + return result; + } +} diff --git a/source/java/org/alfresco/web/bean/wcm/RegenerateRenditionsWizard.java b/source/java/org/alfresco/web/bean/wcm/RegenerateRenditionsWizard.java index 3f97cb1a3b..1961e926a8 100644 --- a/source/java/org/alfresco/web/bean/wcm/RegenerateRenditionsWizard.java +++ b/source/java/org/alfresco/web/bean/wcm/RegenerateRenditionsWizard.java @@ -67,9 +67,9 @@ import org.alfresco.web.ui.common.Utils; import org.alfresco.web.ui.common.component.UIListItem; import org.alfresco.web.ui.wcm.WebResources; import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.util.StringUtils; import org.w3c.dom.Document; /** @@ -119,12 +119,12 @@ public class RegenerateRenditionsWizard if (this.regenerateScope.equals(REGENERATE_SCOPE_FORM)) { description = MessageFormat.format("regenerate_renditions_snapshot_description_scope_form", - StringUtils.arrayToDelimitedString(this.selectedForms, ", ")); + StringUtils.join(this.selectedForms, ", ")); } else if (this.regenerateScope.equals(REGENERATE_SCOPE_RENDERING_ENGINE_TEMPLATE)) { description = MessageFormat.format("regenerate_renditions_snapshot_description_scope_rendering_engine_template", - StringUtils.arrayToDelimitedString(this.selectedRenderingEngineTemplates, ", ")); + StringUtils.join(this.selectedRenderingEngineTemplates, ", ")); } else { @@ -422,8 +422,17 @@ public class RegenerateRenditionsWizard { @Override public Form getForm() + throws FormNotFoundException { - return RegenerateRenditionsWizard.this.selectedWebProject.getForm(super.getForm().getName()); + final Form f = super.getForm(); + try + { + return RegenerateRenditionsWizard.this.selectedWebProject.getForm(f.getName()); + } + catch (FormNotFoundException fnfe) + { + throw new FormNotFoundException(f, RegenerateRenditionsWizard.this.selectedWebProject, this); + } } }; result.add(fid); @@ -497,14 +506,21 @@ public class RegenerateRenditionsWizard query.append(" +("); for (int i = 0; i < this.selectedRenderingEngineTemplates.length; i++) { - - final Form f = this.selectedWebProject.getForm(this.selectedRenderingEngineTemplates[i].split(":")[0]); - final RenderingEngineTemplate ret = f.getRenderingEngineTemplate((String)this.selectedRenderingEngineTemplates[i].split(":")[1]); - query.append("@" + Repository.escapeQName(WCMAppModel.PROP_PARENT_RENDERING_ENGINE_TEMPLATE) + - ":\"" + ((RenderingEngineTemplateImpl)ret).getNodeRef() + "\""); - if (i != this.selectedRenderingEngineTemplates.length - 1) + try { - query.append(" OR "); + final String formName = this.selectedRenderingEngineTemplates[i].split(":")[0]; + final Form f = this.selectedWebProject.getForm(formName); + final RenderingEngineTemplate ret = f.getRenderingEngineTemplate((String)this.selectedRenderingEngineTemplates[i].split(":")[1]); + query.append("@" + Repository.escapeQName(WCMAppModel.PROP_PARENT_RENDERING_ENGINE_TEMPLATE) + + ":\"" + ((RenderingEngineTemplateImpl)ret).getNodeRef() + "\""); + if (i != this.selectedRenderingEngineTemplates.length - 1) + { + query.append(" OR "); + } + } + catch (FormNotFoundException fnfe) + { + LOGGER.debug(fnfe); } } query.append(") "); @@ -528,25 +544,41 @@ public class RegenerateRenditionsWizard { @Override public Form getForm() + throws FormNotFoundException { - return RegenerateRenditionsWizard.this.selectedWebProject.getForm(super.getForm().getName()); + final Form f = super.getForm(); + try + { + return RegenerateRenditionsWizard.this.selectedWebProject.getForm(f.getName()); + } + catch (FormNotFoundException fnfe) + { + throw new FormNotFoundException(f, RegenerateRenditionsWizard.this.selectedWebProject, this); + } } }; - - final List regenResults = fid.regenerateRenditions(); - for (final FormInstanceData.RegenerateResult rr : regenResults) + + try { - if (rr.getException() != null) + final List regenResults = fid.regenerateRenditions(); + for (final FormInstanceData.RegenerateResult rr : regenResults) { - Utils.addErrorMessage("error regenerating rendition using " + rr.getRenderingEngineTemplate().getName() + - ": " + rr.getException().getMessage(), - rr.getException()); - } - else - { - result.add(rr.getRendition()); + if (rr.getException() != null) + { + Utils.addErrorMessage("error regenerating rendition using " + rr.getRenderingEngineTemplate().getName() + + ": " + rr.getException().getMessage(), + rr.getException()); + } + else + { + result.add(rr.getRendition()); + } } } + catch (FormNotFoundException fnfe) + { + Utils.addErrorMessage("error regenerating renditions of " + fid.getPath() + ": " + fnfe.getMessage(), fnfe); + } } else { diff --git a/source/java/org/alfresco/web/bean/wcm/WebProject.java b/source/java/org/alfresco/web/bean/wcm/WebProject.java index 04ddc1af10..7829c7bd41 100644 --- a/source/java/org/alfresco/web/bean/wcm/WebProject.java +++ b/source/java/org/alfresco/web/bean/wcm/WebProject.java @@ -57,6 +57,7 @@ import org.alfresco.web.data.IDataContainer; import org.alfresco.web.data.QuickSort; import org.alfresco.web.forms.Form; import org.alfresco.web.forms.FormImpl; +import org.alfresco.web.forms.FormNotFoundException; import org.alfresco.web.forms.FormsService; import org.alfresco.web.forms.RenderingEngineTemplate; import org.alfresco.web.forms.RenderingEngineTemplateImpl; @@ -182,15 +183,33 @@ public class WebProject public WebProject(final NodeRef nodeRef) { + if (nodeRef == null) + { + throw new NullPointerException(); + } + + final ServiceRegistry serviceRegistry = this.getServiceRegistry(); + final NodeService nodeService = serviceRegistry.getNodeService(); + if (!WCMAppModel.TYPE_AVMWEBFOLDER.equals(nodeService.getType(nodeRef))) + { + throw new IllegalArgumentException(nodeRef + " is not a " + WCMAppModel.TYPE_AVMWEBFOLDER); + } + this.nodeRef = nodeRef; } public WebProject(final String avmPath) { - String stagingStore = AVMUtil.buildStagingStoreName(AVMUtil.getStoreId(AVMUtil.getStoreName(avmPath))); + if (avmPath == null) + { + throw new NullPointerException(); + } + + final String stagingStore = AVMUtil.buildStagingStoreName(AVMUtil.getStoreId(AVMUtil.getStoreName(avmPath))); final AVMService avmService = this.getServiceRegistry().getAVMService(); - this.nodeRef = (NodeRef)avmService.getStoreProperty(stagingStore, - SandboxConstants.PROP_WEB_PROJECT_NODE_REF).getValue(DataTypeDefinition.NODE_REF); + this.nodeRef = (NodeRef) + avmService.getStoreProperty(stagingStore, + SandboxConstants.PROP_WEB_PROJECT_NODE_REF).getValue(DataTypeDefinition.NODE_REF); } /** @@ -282,12 +301,18 @@ public class WebProject * @exception NullPointerException if the name is null. */ public Form getForm(final String name) + throws FormNotFoundException { if (name == null) { throw new NullPointerException(); } - return this.getFormsImpl().get(name); + final Form result = this.getFormsImpl().get(name); + if (result == null) + { + throw new FormNotFoundException(name, this); + } + return result; } /** @@ -395,6 +420,7 @@ public class WebProject { final ServiceRegistry serviceRegistry = this.getServiceRegistry(); final NodeService nodeService = serviceRegistry.getNodeService(); + final FormsService formsService = FormsService.getInstance(); final List formRefs = nodeService.getChildAssocs(this.nodeRef, WCMAppModel.ASSOC_WEBFORM, @@ -404,8 +430,15 @@ public class WebProject { final String formName = (String) nodeService.getProperty(ref.getChildRef(), WCMAppModel.PROP_FORMNAME); - final Form baseForm = FormsService.getInstance().getForm(formName); - result.put(formName, new FormWrapper(baseForm, ref.getChildRef())); + try + { + final Form baseForm = formsService.getForm(formName); + result.put(formName, new FormWrapper(baseForm, ref.getChildRef())); + } + catch (FormNotFoundException fnfe) + { + LOGGER.debug(fnfe); + } } return result; } diff --git a/source/java/org/alfresco/web/forms/FormInstanceData.java b/source/java/org/alfresco/web/forms/FormInstanceData.java index 5fb0fada57..f37e030363 100644 --- a/source/java/org/alfresco/web/forms/FormInstanceData.java +++ b/source/java/org/alfresco/web/forms/FormInstanceData.java @@ -19,7 +19,8 @@ * and Open Source Software ("FLOSS") applications as described in Alfresco's * FLOSS exception. You should have recieved a copy of the text describing * the FLOSS exception, and it is also available here: - * http://www.alfresco.com/legal/licensing" */ + * http://www.alfresco.com/legal/licensing" + */ package org.alfresco.web.forms; import java.io.IOException; @@ -82,7 +83,8 @@ public interface FormInstanceData ///////////////////////////////////////////////////////////////////////////// /** the form generate this form instance data */ - public Form getForm(); + public Form getForm() + throws FormNotFoundException; /** the name of this instance data */ public String getName(); @@ -104,7 +106,8 @@ public interface FormInstanceData throws IOException, SAXException; /** Regenerates all renditions of this form instance data */ - public List regenerateRenditions(); + public List regenerateRenditions() + throws FormNotFoundException; /** returns all renditions of this form instance data */ public List getRenditions(); diff --git a/source/java/org/alfresco/web/forms/FormInstanceDataImpl.java b/source/java/org/alfresco/web/forms/FormInstanceDataImpl.java index 27534dc5c8..d6eb849f0a 100644 --- a/source/java/org/alfresco/web/forms/FormInstanceDataImpl.java +++ b/source/java/org/alfresco/web/forms/FormInstanceDataImpl.java @@ -101,12 +101,17 @@ public class FormInstanceDataImpl } public Form getForm() + throws FormNotFoundException { - final NodeService nodeService = this.getServiceRegistry().getNodeService(); - final String parentFormName = (String) - nodeService.getProperty(this.nodeRef, - WCMAppModel.PROP_PARENT_FORM_NAME); - return FormsService.getInstance().getForm(parentFormName); + final String parentFormName = this.getParentFormName(); + try + { + return FormsService.getInstance().getForm(parentFormName); + } + catch (FormNotFoundException fnfe) + { + throw new FormNotFoundException(parentFormName, this); + } } /** the node ref containing the contents of this rendition */ @@ -121,8 +126,8 @@ public class FormInstanceDataImpl } public List regenerateRenditions() + throws FormNotFoundException { - if (LOGGER.isDebugEnabled()) LOGGER.debug("regenerating renditions of " + this); String originalParentAvmPath = (String) @@ -211,12 +216,28 @@ public class FormInstanceDataImpl public int hashCode() { - return this.getPath().hashCode() ^ this.getForm().hashCode(); + return this.getPath().hashCode(); } public String toString() { - return (this.getClass().getName() + "{path : " + this.getPath() + - ", form : " + this.getForm().getName() + "}"); + try + { + return (this.getClass().getName() + "{path : " + this.getPath() + + ", form : " + this.getForm().getName() + "}"); + } + catch (FormNotFoundException fnfe) + { + return (this.getClass().getName() + "{path : " + this.getPath() + + ", form : " + this.getParentFormName() + " NOT_FOUND! }"); + + } + } + + protected String getParentFormName() + { + final NodeService nodeService = this.getServiceRegistry().getNodeService(); + return (String) nodeService.getProperty(this.nodeRef, + WCMAppModel.PROP_PARENT_FORM_NAME); } } diff --git a/source/java/org/alfresco/web/forms/FormNotFoundException.java b/source/java/org/alfresco/web/forms/FormNotFoundException.java new file mode 100644 index 0000000000..68b5735060 --- /dev/null +++ b/source/java/org/alfresco/web/forms/FormNotFoundException.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.web.forms; + +import java.io.FileNotFoundException; +import java.text.MessageFormat; +import javax.faces.context.FacesContext; +import org.alfresco.web.app.Application; +import org.alfresco.web.bean.wcm.WebProject; + +/** + * Error when a form cannot be resolved. + * + * @author Ariel Backenroth + */ +public class FormNotFoundException + extends FileNotFoundException +{ + private final String formName; + private final WebProject webProject; + private final FormInstanceData fid; + + public FormNotFoundException(final String formName) + { + super(MessageFormat.format(Application.getMessage(FacesContext.getCurrentInstance(), + "form_not_found"), + formName)); + this.formName = formName; + this.webProject = null; + this.fid = null; + } + + public FormNotFoundException(final String formName, final FormInstanceData fid) + { + super(MessageFormat.format(Application.getMessage(FacesContext.getCurrentInstance(), + "form_not_found_for_form_instance_data"), + formName, + fid.getPath())); + this.formName = formName; + this.fid = fid; + this.webProject = null; + } + + public FormNotFoundException(final String formName, final WebProject webProject) + { + super(MessageFormat.format(Application.getMessage(FacesContext.getCurrentInstance(), + "form_not_found_in_web_project"), + formName, + webProject.getName())); + this.formName = formName; + this.webProject = webProject; + this.fid = null; + } + + public FormNotFoundException(final String formName, final WebProject webProject, final FormInstanceData fid) + { + super(MessageFormat.format(Application.getMessage(FacesContext.getCurrentInstance(), + "form_not_found_for_form_instance_data_in_web_project"), + formName, + webProject.getName(), + fid.getPath())); + this.formName = formName; + this.webProject = webProject; + this.fid = fid; + } + + public FormNotFoundException(final Form form, final WebProject webProject) + { + super(MessageFormat.format(Application.getMessage(FacesContext.getCurrentInstance(), + "form_not_configured_for_web_project"), + form.getName(), + webProject.getName())); + this.formName = form.getName(); + this.webProject = webProject; + this.fid = null; + } + + public FormNotFoundException(final Form form, final WebProject webProject, final FormInstanceData fid) + { + super(MessageFormat.format(Application.getMessage(FacesContext.getCurrentInstance(), + "form_associated_with_form_instance_data_not_configured_for_web_project"), + form.getName(), + fid.getPath(), + webProject.getName())); + this.formName = form.getName(); + this.webProject = webProject; + this.fid = fid; + } +} diff --git a/source/java/org/alfresco/web/forms/FormsService.java b/source/java/org/alfresco/web/forms/FormsService.java index 5da3d1ac41..9dbed72eb7 100644 --- a/source/java/org/alfresco/web/forms/FormsService.java +++ b/source/java/org/alfresco/web/forms/FormsService.java @@ -211,6 +211,7 @@ public final class FormsService * @return the form by name or null if not found */ public Form getForm(final String name) + throws FormNotFoundException { final SearchParameters sp = new SearchParameters(); sp.addStore(Repository.getStoreRef()); @@ -230,9 +231,11 @@ public final class FormsService break; } } - if (result == null && LOGGER.isDebugEnabled()) - LOGGER.debug("unable to find template type " + name); - return result != null ? this.getForm(result) : null; + if (result == null) + { + throw new FormNotFoundException(name); + } + return this.getForm(result); } /** @@ -244,11 +247,13 @@ public final class FormsService */ public Form getForm(final NodeRef nodeRef) { - if (LOGGER.isDebugEnabled()) - LOGGER.debug("loading form for " + nodeRef); + if (!this.nodeService.hasAspect(nodeRef, WCMAppModel.ASPECT_FORM)) + { + throw new IllegalArgumentException("node " + nodeRef + " is not a form"); + } final Form result = new FormImpl(nodeRef); if (LOGGER.isDebugEnabled()) - LOGGER.debug("loaded form " + result); + LOGGER.debug("loaded form " + result + " for noderef " + nodeRef); return result; } } diff --git a/source/java/org/alfresco/web/forms/XSLTRenderingEngine.java b/source/java/org/alfresco/web/forms/XSLTRenderingEngine.java index 50521cdaaa..7e1e9db02c 100644 --- a/source/java/org/alfresco/web/forms/XSLTRenderingEngine.java +++ b/source/java/org/alfresco/web/forms/XSLTRenderingEngine.java @@ -46,13 +46,14 @@ import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.alfresco.web.bean.wcm.AVMUtil; import org.alfresco.web.forms.XMLUtil; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.xalan.extensions.ExpressionContext; import org.apache.xpath.objects.XObject; import org.apache.xml.dtm.ref.DTMNodeProxy; import org.apache.xml.utils.Constants; -import org.springframework.util.StringUtils; + //import org.apache.xml.utils.QName; import org.w3c.dom.*; import org.w3c.dom.traversal.NodeFilter; @@ -318,7 +319,7 @@ public class XSLTRenderingEngine compEl.appendChild(scriptEl); } docEl.setAttribute("exclude-result-prefixes", - StringUtils.arrayToDelimitedString(excludePrefixes.toArray(new String[excludePrefixes.size()]), " ")); + StringUtils.join(excludePrefixes.toArray(new String[excludePrefixes.size()]), " ")); return result; } diff --git a/source/java/org/alfresco/web/forms/xforms/Schema2XForms.java b/source/java/org/alfresco/web/forms/xforms/Schema2XForms.java index cab7438992..a0cfbe0f23 100644 --- a/source/java/org/alfresco/web/forms/xforms/Schema2XForms.java +++ b/source/java/org/alfresco/web/forms/xforms/Schema2XForms.java @@ -19,7 +19,8 @@ * and Open Source Software ("FLOSS") applications as described in Alfresco's * FLOSS exception. You should have recieved a copy of the text describing * the FLOSS exception, and it is also available here: - * http://www.alfresco.com/legal/licensing" */ + * http://www.alfresco.com/legal/licensing" + */ package org.alfresco.web.forms.xforms; import java.io.File; @@ -273,23 +274,27 @@ public class Schema2XForms schema, rootElementDecl, "/" + this.getElementName(rootElementDecl, xformsDocument), - new SchemaUtil.Occurance(1, 1), + new SchemaUtil.Occurrence(1, 1), resourceBundle); if (rootGroup.getNodeName() != NamespaceConstants.XFORMS_PREFIX + ":group") { - throw new FormBuilderException("Expected root form element to be a group. Generated a " + - rootGroup.getNodeName() + " instead"); + throw new FormBuilderException("Expected root form element to be a " + NamespaceConstants.XFORMS_PREFIX + + ":group, not a " + rootGroup.getNodeName() + + ". Ensure that " + this.getElementName(rootElementDecl, xformsDocument) + + " is a concrete type that has no extensions. " + + "Types with extensions are not supported for " + + "the root element of a form."); } this.setXFormsId(rootGroup, "alfresco-xforms-root-group"); if (importedInstanceDocumentElement != null) { - this.insertUpdatedNodes(importedInstanceDocumentElement, - defaultInstanceDocumentElement, - schemaNamespacesMap); - this.insertPrototypeNodes(importedInstanceDocumentElement, - defaultInstanceDocumentElement, - schemaNamespacesMap); + Schema2XForms.insertUpdatedNodes(importedInstanceDocumentElement, + defaultInstanceDocumentElement, + schemaNamespacesMap); + Schema2XForms.insertPrototypeNodes(importedInstanceDocumentElement, + defaultInstanceDocumentElement, + schemaNamespacesMap); } @@ -324,9 +329,9 @@ public class Schema2XForms * @param schemaNamespaces the namespaces used by the instance document needed for * initializing the xpath context. */ - private void insertUpdatedNodes(final Element instanceDocumentElement, - final Element prototypeDocumentElement, - final HashMap schemaNamespaces) + public static void insertUpdatedNodes(final Element instanceDocumentElement, + final Element prototypeDocumentElement, + final HashMap schemaNamespaces) { LOGGER.debug("updating imported instance document"); final JXPathContext prototypeContext = @@ -434,9 +439,9 @@ public class Schema2XForms * @param schemaNamespaces the namespaces used by the instance document needed for * initializing the xpath context. */ - private void insertPrototypeNodes(final Element instanceDocumentElement, - final Element prototypeDocumentElement, - final HashMap schemaNamespaces) + public static void insertPrototypeNodes(final Element instanceDocumentElement, + final Element prototypeDocumentElement, + final HashMap schemaNamespaces) { final JXPathContext prototypeContext = JXPathContext.newContext(prototypeDocumentElement); @@ -605,7 +610,7 @@ public class Schema2XForms } } - public void removePrototypeNodes(final Element instanceDocumentElement) + public static void removePrototypeNodes(final Node instanceDocumentElement) { final Map> prototypes = new HashMap>(); @@ -641,7 +646,7 @@ public class Schema2XForms } if (e.getParentNode() != null) { - this.removePrototypeNodes(e); + Schema2XForms.removePrototypeNodes(e); } } } @@ -953,7 +958,7 @@ public class Schema2XForms final XSComplexTypeDefinition controlType, final XSElementDeclaration owner, String pathToRoot, - final SchemaUtil.Occurance occurs, + final SchemaUtil.Occurrence occurs, boolean relative, final boolean checkIfExtension, final ResourceBundle resourceBundle) @@ -981,7 +986,7 @@ public class Schema2XForms formSection, owner, resourceBundle); -// final SchemaUtil.Occurance o = SchemaUtil.getOccurance(owner); +// final SchemaUtil.Occurrence o = SchemaUtil.getOccurrence(owner); final Element repeatSection = this.addRepeatIfNecessary(xformsDocument, modelSection, groupElement, @@ -1000,7 +1005,7 @@ public class Schema2XForms if (LOGGER.isDebugEnabled()) { - LOGGER.debug("addComplexTypeChildren for " + controlType.getName() + + LOGGER.debug("addComplexType for " + controlType.getName() + "(" + pathToRoot + ")" + " owner = " + (owner == null ? "null" : owner.getName())); } @@ -1081,6 +1086,26 @@ public class Schema2XForms if (term instanceof XSModelGroup) { + + switch (((XSModelGroup)term).getCompositor()) + { + case XSModelGroup.COMPOSITOR_CHOICE: + LOGGER.warn("term " + term.getName() + " of particle " + particle.getName() + + " of type " + controlType.getName() + " in " + owner.getName() + + " describes a " + NamespaceConstants.XMLSCHEMA_PREFIX + + ":choice which is not yet supported, adding it as a " + + NamespaceConstants.XMLSCHEMA_PREFIX + ":sequence"); + break; + case XSModelGroup.COMPOSITOR_ALL: + LOGGER.warn("term " + term.getName() + " of particle " + particle.getName() + + " of type " + controlType.getName() + " in " + owner.getName() + + " describes a " + NamespaceConstants.XMLSCHEMA_PREFIX + + ":all which is not yet supported, adding it as a " + + NamespaceConstants.XMLSCHEMA_PREFIX + ":sequence"); + break; + case XSModelGroup.COMPOSITOR_SEQUENCE: + break; + } //call addGroup on this group this.addGroup(xformsDocument, modelSection, @@ -1091,7 +1116,7 @@ public class Schema2XForms controlType, owner, pathToRoot, - new SchemaUtil.Occurance(particle), + new SchemaUtil.Occurrence(particle), checkIfExtension, resourceBundle); } @@ -1115,7 +1140,7 @@ public class Schema2XForms final XSModel schema, final XSElementDeclaration elementDecl, final String pathToRoot, - final SchemaUtil.Occurance occurs, + final SchemaUtil.Occurrence occurs, final ResourceBundle resourceBundle) throws FormBuilderException { @@ -1229,7 +1254,7 @@ public class Schema2XForms } else { -// final SchemaUtil.Occurance occurs = SchemaUtil.getOccurance(elementDecl); +// final SchemaUtil.Occurrence occurs = SchemaUtil.getOccurrence(elementDecl); //create the bind in case it is a repeat LOGGER.debug("Adding empty bind for control " + controlType + " type " + typeName + @@ -1331,7 +1356,7 @@ public class Schema2XForms (XSComplexTypeDefinition)controlType, elementDecl, pathToRoot, - SchemaUtil.getOccurance(elementDecl), + SchemaUtil.getOccurrence(elementDecl), true, false, resourceBundle); @@ -1379,7 +1404,7 @@ public class Schema2XForms (XSComplexTypeDefinition) type, elementDecl, pathToRoot, - SchemaUtil.getOccurance(elementDecl), + SchemaUtil.getOccurrence(elementDecl), true, true, resourceBundle); @@ -1454,7 +1479,7 @@ public class Schema2XForms final XSComplexTypeDefinition controlType, final XSElementDeclaration owner, final String pathToRoot, - final SchemaUtil.Occurance occurs, + final SchemaUtil.Occurrence occurs, final boolean checkIfExtension, final ResourceBundle resourceBundle) throws FormBuilderException @@ -1482,7 +1507,7 @@ public class Schema2XForms { final XSParticle currentNode = (XSParticle)particles.item(counter); XSTerm term = currentNode.getTerm(); - final SchemaUtil.Occurance childOccurs = new SchemaUtil.Occurance(currentNode); + final SchemaUtil.Occurrence childOccurs = new SchemaUtil.Occurrence(currentNode); if (LOGGER.isDebugEnabled()) { LOGGER.debug(" : next term = " + term.getName() + @@ -1625,16 +1650,16 @@ public class Schema2XForms final XSModel schema, final XSElementDeclaration element, final String pathToRoot, - final SchemaUtil.Occurance occurs, + final SchemaUtil.Occurrence occurs, final ResourceBundle resourceBundle) throws FormBuilderException { - LOGGER.debug("addElement to group " + element + " at " + pathToRoot); //add it normally final String elementName = this.getElementName(element, xformsDocument); final String path = (pathToRoot.length() == 0 ? elementName : pathToRoot + "/" + elementName); + LOGGER.debug("addElement to group " + elementName + " at " + path); final Element newDefaultInstanceElement = xformsDocument.createElement(elementName); if (element.getConstraintType() != XSConstants.VC_NONE) @@ -1653,7 +1678,7 @@ public class Schema2XForms occurs, resourceBundle); -// final SchemaUtil.Occurance occurs = SchemaUtil.getOccurance(element); +// final SchemaUtil.Occurrence occurs = SchemaUtil.getOccurrence(element); LOGGER.debug("adding " + (occurs.maximum == 1 ? 1 : occurs.minimum + 1) + @@ -1699,7 +1724,7 @@ public class Schema2XForms final Element formSection, final XSTypeDefinition controlType, final String pathToRoot, - final SchemaUtil.Occurance o) + final SchemaUtil.Occurrence o) { // add xforms:repeat section if this element re-occurs @@ -1783,7 +1808,7 @@ public class Schema2XForms final String owningElementName, final XSObject owner, final String pathToRoot, - final SchemaUtil.Occurance occurs, + final SchemaUtil.Occurrence occurs, final ResourceBundle resourceBundle) { if (LOGGER.isDebugEnabled()) @@ -1887,7 +1912,7 @@ public class Schema2XForms owningAttribute.getAttrDeclaration().getName(), owningAttribute, pathToRoot, - new SchemaUtil.Occurance(owningAttribute.getRequired() ? 1 : 0, 1), + new SchemaUtil.Occurrence(owningAttribute.getRequired() ? 1 : 0, 1), resourceBundle); } @@ -1898,7 +1923,7 @@ public class Schema2XForms final XSObject owner, final String bindId, final Element bindElement, - final SchemaUtil.Occurance o, + final SchemaUtil.Occurrence o, final ResourceBundle resourceBundle) { Element formControl = null; @@ -2123,6 +2148,10 @@ public class Schema2XForms formSection.appendChild(result); result.appendChild(this.createLabel(xformsDocument, this.createCaption(owner, resourceBundle))); + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("created group " + XMLUtil.toString(result)); + } return result; } @@ -2718,7 +2747,7 @@ public class Schema2XForms final XSModel schema, final XSTypeDefinition controlType, final XSObject owner, - final SchemaUtil.Occurance o) + final SchemaUtil.Occurrence o) { // START WORKAROUND // Due to a Chiba bug, anyType is not a recognized type name. diff --git a/source/java/org/alfresco/web/forms/xforms/Schema2XFormsProperties.java b/source/java/org/alfresco/web/forms/xforms/Schema2XFormsProperties.java index 212bafa321..6227873f60 100644 --- a/source/java/org/alfresco/web/forms/xforms/Schema2XFormsProperties.java +++ b/source/java/org/alfresco/web/forms/xforms/Schema2XFormsProperties.java @@ -35,7 +35,7 @@ import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.web.bean.repository.Repository; import org.alfresco.web.forms.Form; -import org.springframework.util.StringUtils; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -198,7 +198,8 @@ public class Schema2XFormsProperties public String toString() { return (this.getClass().getName() + "{" + - StringUtils.arrayToCommaDelimitedString(this.locations) + + StringUtils.join(this.locations, ",") + "}"); } -} \ No newline at end of file +} + diff --git a/source/java/org/alfresco/web/forms/xforms/Schema2XFormsTest.java b/source/java/org/alfresco/web/forms/xforms/Schema2XFormsTest.java index 2651cb1f6c..4c6cc220a5 100644 --- a/source/java/org/alfresco/web/forms/xforms/Schema2XFormsTest.java +++ b/source/java/org/alfresco/web/forms/xforms/Schema2XFormsTest.java @@ -35,6 +35,8 @@ import org.apache.commons.jxpath.Pointer; import org.chiba.xml.ns.NamespaceConstants; import org.w3c.dom.*; import org.xml.sax.*; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; /** * JUnit tests to exercise the the schema to xforms converter @@ -45,6 +47,8 @@ public class Schema2XFormsTest extends BaseTest { + private final static Log LOGGER = LogFactory.getLog(Schema2XFormsTest.class); + public void testOneStringTestWithEmptyInstanceDocument() throws Exception { @@ -88,61 +92,96 @@ public class Schema2XFormsTest final Document xformsDocument = this.buildXForm(null, schemaDocument, "repeat-constraints-test"); this.assertRepeatProperties(xformsDocument, "/repeat-constraints-test/one-to-inf", - new SchemaUtil.Occurance(1, SchemaUtil.Occurance.UNBOUNDED)); + new SchemaUtil.Occurrence(1, SchemaUtil.Occurrence.UNBOUNDED)); this.assertRepeatProperties(xformsDocument, "/repeat-constraints-test/zero-to-inf", - new SchemaUtil.Occurance(0, SchemaUtil.Occurance.UNBOUNDED)); + new SchemaUtil.Occurrence(0, SchemaUtil.Occurrence.UNBOUNDED)); this.assertRepeatProperties(xformsDocument, "/repeat-constraints-test/one-to-five", - new SchemaUtil.Occurance(1, 5)); + new SchemaUtil.Occurrence(1, 5)); this.assertRepeatProperties(xformsDocument, "/repeat-constraints-test/three-to-five", - new SchemaUtil.Occurance(3, 5)); + new SchemaUtil.Occurrence(3, 5)); this.assertRepeatProperties(xformsDocument, "/repeat-constraints-test/zero-to-five", - new SchemaUtil.Occurance(0, 5)); + new SchemaUtil.Occurrence(0, 5)); this.assertRepeatProperties(xformsDocument, "/repeat-constraints-test/referenced-string", - new SchemaUtil.Occurance(1, SchemaUtil.Occurance.UNBOUNDED)); + new SchemaUtil.Occurrence(1, SchemaUtil.Occurrence.UNBOUNDED)); this.assertRepeatProperties(xformsDocument, "/repeat-constraints-test/nested-outer-zero-to-inf", - new SchemaUtil.Occurance(0, SchemaUtil.Occurance.UNBOUNDED)); + new SchemaUtil.Occurrence(0, SchemaUtil.Occurrence.UNBOUNDED)); this.assertRepeatProperties(xformsDocument, "/repeat-constraints-test/nested-outer-zero-to-inf/nested-zero-to-inf-inner-zero-to-inf", - new SchemaUtil.Occurance(0, SchemaUtil.Occurance.UNBOUNDED)); + new SchemaUtil.Occurrence(0, SchemaUtil.Occurrence.UNBOUNDED)); this.assertRepeatProperties(xformsDocument, "/repeat-constraints-test/nested-outer-zero-to-inf/nested-zero-to-inf-inner-one-to-inf", - new SchemaUtil.Occurance(1, SchemaUtil.Occurance.UNBOUNDED)); + new SchemaUtil.Occurrence(1, SchemaUtil.Occurrence.UNBOUNDED)); this.assertRepeatProperties(xformsDocument, "/repeat-constraints-test/nested-outer-one-to-inf", - new SchemaUtil.Occurance(1, SchemaUtil.Occurance.UNBOUNDED)); + new SchemaUtil.Occurrence(1, SchemaUtil.Occurrence.UNBOUNDED)); this.assertRepeatProperties(xformsDocument, "/repeat-constraints-test/nested-outer-one-to-inf/nested-one-to-inf-inner-zero-to-inf", - new SchemaUtil.Occurance(0, SchemaUtil.Occurance.UNBOUNDED)); + new SchemaUtil.Occurrence(0, SchemaUtil.Occurrence.UNBOUNDED)); this.assertRepeatProperties(xformsDocument, "/repeat-constraints-test/nested-outer-one-to-inf/nested-one-to-inf-inner-one-to-inf", - new SchemaUtil.Occurance(1, SchemaUtil.Occurance.UNBOUNDED)); + new SchemaUtil.Occurrence(1, SchemaUtil.Occurrence.UNBOUNDED)); this.assertRepeatProperties(xformsDocument, "/repeat-constraints-test/nested-outer-three-to-five", - new SchemaUtil.Occurance(3, 5)); + new SchemaUtil.Occurrence(3, 5)); this.assertRepeatProperties(xformsDocument, "/repeat-constraints-test/nested-outer-three-to-five/nested-three-to-five-inner-zero-to-inf", - new SchemaUtil.Occurance(0, SchemaUtil.Occurance.UNBOUNDED)); + new SchemaUtil.Occurrence(0, SchemaUtil.Occurrence.UNBOUNDED)); this.assertRepeatProperties(xformsDocument, "/repeat-constraints-test/nested-outer-three-to-five/nested-three-to-five-inner-one-to-inf", - new SchemaUtil.Occurance(1, SchemaUtil.Occurance.UNBOUNDED)); + new SchemaUtil.Occurrence(1, SchemaUtil.Occurrence.UNBOUNDED)); this.assertRepeatProperties(xformsDocument, "/repeat-constraints-test/nested-outer-outer-three-to-inf", - new SchemaUtil.Occurance(3, SchemaUtil.Occurance.UNBOUNDED)); + new SchemaUtil.Occurrence(3, SchemaUtil.Occurrence.UNBOUNDED)); this.assertRepeatProperties(xformsDocument, "/repeat-constraints-test/nested-outer-outer-three-to-inf/nested-outer-inner-five-to-inf", - new SchemaUtil.Occurance(5, SchemaUtil.Occurance.UNBOUNDED)); + new SchemaUtil.Occurrence(5, SchemaUtil.Occurrence.UNBOUNDED)); this.assertRepeatProperties(xformsDocument, "/repeat-constraints-test/nested-outer-outer-three-to-inf/nested-outer-inner-five-to-inf/nested-inner-inner-seven-to-inf", - new SchemaUtil.Occurance(7, SchemaUtil.Occurance.UNBOUNDED)); + new SchemaUtil.Occurrence(7, SchemaUtil.Occurrence.UNBOUNDED)); } - private void assertRepeatProperties(final Document xformsDocument, final String nodeset, final SchemaUtil.Occurance o) + public void testRootElementWithExtension() + throws Exception + { + final Document schemaDocument = this.loadTestResourceDocument("xforms/unit-tests/automated/root-element-with-extension-test.xsd"); + Document xformsDocument = this.buildXForm(null, schemaDocument, "without-extension-test"); + assertEquals(3, xformsDocument.getElementsByTagNameNS(NamespaceConstants.XFORMS_NS, "input").getLength()); + + try + { + xformsDocument = this.buildXForm(null, schemaDocument, "with-extension-test"); + fail("expected failure creating xform with root element with-extension-test in schema " + XMLUtil.toString(schemaDocument)); + } + catch (FormBuilderException fbe) + { + } + } + + public void testSwitch() + throws Exception + { + final Document schemaDocument = this.loadTestResourceDocument("xforms/unit-tests/automated/switch-test.xsd"); + final Document xformsDocument = this.buildXForm(null, schemaDocument, "switch-test"); + LOGGER.debug("generated xforms " + XMLUtil.toString(xformsDocument)); +// assertEquals(3, xformsDocument.getElementsByTagNameNS(NamespaceConstants.XFORMS_NS, "input").getLength()); +// +// try +// { +// xformsDocument = this.buildXForm(null, schemaDocument, "with-extension-test"); +// fail("expected failure creating xform with root element with-extension-test in schema " + XMLUtil.toString(schemaDocument)); +// } +// catch (FormBuilderException fbe) +// { +// } + } + + private void assertRepeatProperties(final Document xformsDocument, final String nodeset, final SchemaUtil.Occurrence o) { final Element[] bindElements = this.resolveBind(xformsDocument, nodeset); assertNotNull("unable to resolve bind for nodeset " + nodeset, bindElements); @@ -182,7 +221,7 @@ public class Schema2XFormsTest int nestingFactor = 1; for (int i = 0; i < bindElements.length - 1; i++) { - final SchemaUtil.Occurance parentO = this.occuranceFromBind(bindElements[i]); + final SchemaUtil.Occurrence parentO = this.occuranceFromBind(bindElements[i]); if (parentO.isRepeated()) { nestingFactor = nestingFactor * (1 + parentO.minimum); @@ -283,15 +322,15 @@ public class Schema2XFormsTest } - private SchemaUtil.Occurance occuranceFromBind(final Element bindElement) + private SchemaUtil.Occurrence occuranceFromBind(final Element bindElement) { - return new SchemaUtil.Occurance(bindElement.hasAttributeNS(NamespaceConstants.XFORMS_NS, "minOccurs") - ? Integer.parseInt(bindElement.getAttributeNS(NamespaceConstants.XFORMS_NS, "minOccurs")) - : 1, - bindElement.hasAttributeNS(NamespaceConstants.XFORMS_NS, "maxOccurs") - ? ("unbounded".equals(bindElement.getAttributeNS(NamespaceConstants.XFORMS_NS, "maxOccurs")) - ? SchemaUtil.Occurance.UNBOUNDED - : Integer.parseInt(bindElement.getAttributeNS(NamespaceConstants.XFORMS_NS, "maxOccurs"))) - : 1); + return new SchemaUtil.Occurrence(bindElement.hasAttributeNS(NamespaceConstants.XFORMS_NS, "minOccurs") + ? Integer.parseInt(bindElement.getAttributeNS(NamespaceConstants.XFORMS_NS, "minOccurs")) + : 1, + bindElement.hasAttributeNS(NamespaceConstants.XFORMS_NS, "maxOccurs") + ? ("unbounded".equals(bindElement.getAttributeNS(NamespaceConstants.XFORMS_NS, "maxOccurs")) + ? SchemaUtil.Occurrence.UNBOUNDED + : Integer.parseInt(bindElement.getAttributeNS(NamespaceConstants.XFORMS_NS, "maxOccurs"))) + : 1); } } \ No newline at end of file diff --git a/source/java/org/alfresco/web/forms/xforms/SchemaUtil.java b/source/java/org/alfresco/web/forms/xforms/SchemaUtil.java index 1e89a256e6..0da62730c6 100644 --- a/source/java/org/alfresco/web/forms/xforms/SchemaUtil.java +++ b/source/java/org/alfresco/web/forms/xforms/SchemaUtil.java @@ -42,26 +42,26 @@ public class SchemaUtil //////////////////////////////////////////////////////////////////////////// - public static class Occurance + public static class Occurrence { public final static int UNBOUNDED = -1; public final int minimum; public final int maximum; - public Occurance(final XSParticle particle) + public Occurrence(final XSParticle particle) { this(particle.getMinOccurs(), (particle.getMaxOccursUnbounded() - ? Occurance.UNBOUNDED + ? Occurrence.UNBOUNDED : particle.getMaxOccurs())); } - public Occurance(final int minimum) + public Occurrence(final int minimum) { - this(minimum, Occurance.UNBOUNDED); + this(minimum, Occurrence.UNBOUNDED); } - public Occurance(final int minimum, final int maximum) + public Occurrence(final int minimum, final int maximum) { this.minimum = minimum; this.maximum = maximum; @@ -723,15 +723,15 @@ public class SchemaUtil * * @return a table containing minOccurs and MaxOccurs */ - public static Occurance getOccurance(final XSElementDeclaration elDecl) + public static Occurrence getOccurrence(final XSElementDeclaration elDecl) { //get occurance on encosing element declaration final XSParticle particle = SchemaUtil.findCorrespondingParticleInComplexType(elDecl); - final Occurance result = particle == null ? new Occurance(1, 1) : new Occurance(particle); + final Occurrence result = particle == null ? new Occurrence(1, 1) : new Occurrence(particle); if (LOGGER.isDebugEnabled()) { - LOGGER.debug("getOccurance for " + elDecl.getName() + + LOGGER.debug("getOccurrence for " + elDecl.getName() + ", " + result); } return result; diff --git a/source/java/org/alfresco/web/forms/xforms/XFormsBean.java b/source/java/org/alfresco/web/forms/xforms/XFormsBean.java index 2653d5e27e..b54aa09666 100644 --- a/source/java/org/alfresco/web/forms/xforms/XFormsBean.java +++ b/source/java/org/alfresco/web/forms/xforms/XFormsBean.java @@ -69,10 +69,12 @@ import org.chiba.xml.events.XFormsEventNames; import org.chiba.xml.events.XMLEvent; import org.chiba.xml.xforms.ChibaBean; import org.chiba.xml.xforms.XFormsElement; -import org.chiba.xml.xforms.connector.http.AbstractHTTPConnector; +import org.chiba.xml.xforms.connector.SubmissionHandler; +import org.chiba.xml.xforms.connector.AbstractConnector; import org.chiba.xml.xforms.core.Instance; import org.chiba.xml.xforms.core.ModelItem; import org.chiba.xml.xforms.core.Model; +import org.chiba.xml.xforms.core.Submission; import org.chiba.xml.xforms.core.UpdateHandler; import org.chiba.xml.xforms.core.impl.DefaultValidatorMode; import org.chiba.xml.xforms.exception.XFormsException; @@ -96,6 +98,30 @@ import org.xml.sax.SAXException; public class XFormsBean { + ///////////////////////////////////////////////////////////////////////////// + + public static class AlfrescoSubmissionHandler + extends AbstractConnector + implements SubmissionHandler + { + + public Map submit(final Submission submission, + final Node instance) + throws XFormsException + { + if (XFormsBean.LOGGER.isDebugEnabled()) + { + XFormsBean.LOGGER.debug(this.getClass().getName() + + " recieved submission " + XMLUtil.toString(instance, true)); + } + final FacesContext fc = FacesContext.getCurrentInstance(); + //make the XFormsBean available for this session + final XFormsBean xforms = (XFormsBean)FacesHelper.getManagedBean(fc, "XFormsBean"); + xforms.handleSubmit(instance); + return Collections.EMPTY_MAP; + } + } + ///////////////////////////////////////////////////////////////////////////// /** @@ -120,9 +146,9 @@ public class XFormsBean this.formInstanceData = formInstanceData; this.formInstanceDataName = formInstanceDataName; this.form = form; - this.schema2XForms = new Schema2XForms("/ajax/invoke/XFormsBean.handleAction", + this.schema2XForms = new Schema2XForms(/* "/ajax/invoke/XFormsBean.handleAction" */ null, Schema2XForms.SubmitMethod.POST, - baseUrl); + /* baseUrl */ "alfresco:" + XFormsBean.class.getName()); } public void destroy() @@ -206,7 +232,7 @@ public class XFormsBean final ChibaBean chibaBean = new ChibaBean(); chibaBean.setConfig(servletContext.getRealPath("/WEB-INF/chiba.xml")); - XFormsBean.storeCookies(request.getCookies(), chibaBean); +// XFormsBean.storeCookies(request.getCookies(), chibaBean); chibaBean.setXMLContainer(this.getXFormsDocument()); final EventTarget et = (EventTarget) @@ -380,18 +406,8 @@ public class XFormsBean final HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest(); final Document result = XMLUtil.parse(request.getInputStream()); + this.handleSubmit(result); final Document instanceData = this.xformsSession.getFormInstanceData(); - Element documentElement = instanceData.getDocumentElement(); - if (documentElement != null) - { - instanceData.removeChild(documentElement); - } - - documentElement = result.getDocumentElement(); - this.xformsSession.schema2XForms.removePrototypeNodes(documentElement); - documentElement = (Element)instanceData.importNode(documentElement, true); - instanceData.appendChild(documentElement); - instanceData.normalizeDocument(); final ResponseWriter out = context.getResponseWriter(); XMLUtil.print(instanceData, out, false); out.close(); @@ -402,6 +418,24 @@ public class XFormsBean } } + public void handleSubmit(Node result) + { + final Document instanceData = this.xformsSession.getFormInstanceData(); + Element documentElement = instanceData.getDocumentElement(); + if (documentElement != null) + { + instanceData.removeChild(documentElement); + } + if (result instanceof Document) + { + result = ((Document)result).getDocumentElement(); + } + documentElement = (Element)instanceData.importNode(result.cloneNode(true), true); + Schema2XForms.removePrototypeNodes(documentElement); + instanceData.appendChild(documentElement); + instanceData.normalizeDocument(); + } + /** * Swaps model nodes to implement reordering within repeats. */ @@ -608,25 +642,25 @@ public class XFormsBean * HTTPConnectors. Instance loading and submission then uses these cookies. Important for * applications using auth. */ - @SuppressWarnings("unchecked") - private static void storeCookies(final javax.servlet.http.Cookie[] cookiesIn, - final ChibaBean chibaBean){ - if (cookiesIn != null) { - org.apache.commons.httpclient.Cookie[] commonsCookies = - new org.apache.commons.httpclient.Cookie[cookiesIn.length]; - for (int i = 0; i < cookiesIn.length; i += 1) { - commonsCookies[i] = - new org.apache.commons.httpclient.Cookie(cookiesIn[i].getDomain(), - cookiesIn[i].getName(), - cookiesIn[i].getValue(), - cookiesIn[i].getPath(), - cookiesIn[i].getMaxAge(), - cookiesIn[i].getSecure()); - } - chibaBean.getContext().put(AbstractHTTPConnector.REQUEST_COOKIE, - commonsCookies); - } - } +// @SuppressWarnings("unchecked") +// private static void storeCookies(final javax.servlet.http.Cookie[] cookiesIn, +// final ChibaBean chibaBean){ +// if (cookiesIn != null) { +// org.apache.commons.httpclient.Cookie[] commonsCookies = +// new org.apache.commons.httpclient.Cookie[cookiesIn.length]; +// for (int i = 0; i < cookiesIn.length; i += 1) { +// commonsCookies[i] = +// new org.apache.commons.httpclient.Cookie(cookiesIn[i].getDomain(), +// cookiesIn[i].getName(), +// cookiesIn[i].getValue(), +// cookiesIn[i].getPath(), +// cookiesIn[i].getMaxAge(), +// cookiesIn[i].getSecure()); +// } +// chibaBean.getContext().put(AbstractHTTPConnector.REQUEST_COOKIE, +// commonsCookies); +// } +// } private Document getXFormsDocument() throws FormBuilderException diff --git a/source/java/org/alfresco/web/ui/repo/component/evaluator/ActionInstanceEvaluator.java b/source/java/org/alfresco/web/ui/repo/component/evaluator/ActionInstanceEvaluator.java index a4e265aec2..9e38409192 100644 --- a/source/java/org/alfresco/web/ui/repo/component/evaluator/ActionInstanceEvaluator.java +++ b/source/java/org/alfresco/web/ui/repo/component/evaluator/ActionInstanceEvaluator.java @@ -51,16 +51,17 @@ public class ActionInstanceEvaluator extends BaseEvaluator try { - Object obj = getValue(); + final Object obj = this.getValue(); if (obj instanceof Node) { - result = getEvaluator().evaluate((Node)obj); + result = this.getEvaluator().evaluate((Node)obj); } } catch (Exception err) { // return default value on error - s_logger.debug("Error during ActionInstanceEvaluator evaluation: " + err.getMessage()); + s_logger.warn("Error during ActionInstanceEvaluator evaluation of " + this.getEvaluator() + + ": " + err.getMessage()); } return result; @@ -83,12 +84,12 @@ public class ActionInstanceEvaluator extends BaseEvaluator */ public Object saveState(FacesContext context) { - Object values[] = new Object[] { + return new Object[] { // standard component attributes are saved by the super class super.saveState(context), this.evaluator, - this.evaluatorClassName }; - return (values); + this.evaluatorClassName + }; } /** diff --git a/source/test-resources/xforms/customer-tests/monks-switch-test.xsd b/source/test-resources/xforms/customer-tests/monks-switch-test.xsd new file mode 100644 index 0000000000..cd5a8674a6 --- /dev/null +++ b/source/test-resources/xforms/customer-tests/monks-switch-test.xsd @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/test-resources/xforms/unit-tests/automated/number-test.xsd b/source/test-resources/xforms/unit-tests/automated/number-test.xsd new file mode 100644 index 0000000000..6ba215686a --- /dev/null +++ b/source/test-resources/xforms/unit-tests/automated/number-test.xsd @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/test-resources/xforms/unit-tests/automated/root-element-with-extension-test.xsd b/source/test-resources/xforms/unit-tests/automated/root-element-with-extension-test.xsd new file mode 100644 index 0000000000..5226d1b323 --- /dev/null +++ b/source/test-resources/xforms/unit-tests/automated/root-element-with-extension-test.xsd @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/test-resources/xforms/unit-tests/automated/switch-test.xsd b/source/test-resources/xforms/unit-tests/automated/switch-test.xsd new file mode 100644 index 0000000000..42b039f811 --- /dev/null +++ b/source/test-resources/xforms/unit-tests/automated/switch-test.xsd @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/test-resources/xforms/unit-tests/simple-test/textarea-test.xsd b/source/test-resources/xforms/unit-tests/simple-test/textarea-test.xsd index 20733c5430..b8b301bdd5 100644 --- a/source/test-resources/xforms/unit-tests/simple-test/textarea-test.xsd +++ b/source/test-resources/xforms/unit-tests/simple-test/textarea-test.xsd @@ -20,6 +20,13 @@ + + + + custom + + + diff --git a/source/test-resources/xforms/unit-tests/simple-test/upload-simple-test.xsd b/source/test-resources/xforms/unit-tests/simple-test/upload-simple-test.xsd index 5814514633..79835c1f3a 100644 --- a/source/test-resources/xforms/unit-tests/simple-test/upload-simple-test.xsd +++ b/source/test-resources/xforms/unit-tests/simple-test/upload-simple-test.xsd @@ -1,15 +1,40 @@ - - - + + + + + + + + + + + + + + + + image_file_picker + + + html_file_picker + + + folder_picker + + + file_picker + + + + - - diff --git a/source/web/WEB-INF/chiba.xml b/source/web/WEB-INF/chiba.xml index 3dca1b8949..21f10a7d8a 100644 --- a/source/web/WEB-INF/chiba.xml +++ b/source/web/WEB-INF/chiba.xml @@ -25,6 +25,7 @@ + + + - + function _xforms_getSaveDraftButtons() + { + return [ document.getElementById("wizard:back-button") ]; + } + + + 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 13b8b76286..29adc300bd 100644 --- a/source/web/jsp/wcm/create-web-content-wizard/summary.jsp +++ b/source/web/jsp/wcm/create-web-content-wizard/summary.jsp @@ -142,7 +142,8 @@ + width="100%" + rendered="#{WizardManager.bean.submittable}"> diff --git a/source/web/jsp/wcm/tiny_mce_image_dialog.jsp b/source/web/jsp/wcm/tiny_mce_image_dialog.jsp index 5739a72549..853d4490a7 100644 --- a/source/web/jsp/wcm/tiny_mce_image_dialog.jsp +++ b/source/web/jsp/wcm/tiny_mce_image_dialog.jsp @@ -91,7 +91,14 @@ { document.getElementById("src").value = picker.getValue(); }; - alfFilePickerWidgetInstance = new alfresco.FilePickerWidget("alfFilePicker", d, "", false, changeHandler, resizeHandler) + alfFilePickerWidgetInstance = new alfresco.FilePickerWidget("alfFilePicker", + d, + "", + false, + changeHandler, + resizeHandler, + ["wcm:avmcontent"], + ["image/*"]); alfFilePickerWidgetInstance.setValue(document.getElementById("src").value); alfFilePickerWidgetInstance.render(); } diff --git a/source/web/scripts/ajax/ajax_helper.js b/source/web/scripts/ajax/ajax_helper.js index 05bb82f8d8..0dd5c70293 100644 --- a/source/web/scripts/ajax/ajax_helper.js +++ b/source/web/scripts/ajax/ajax_helper.js @@ -28,6 +28,8 @@ // AJAX helper //////////////////////////////////////////////////////////////////////////////// +djConfig.bindEncoding = "UTF-8"; + alfresco = typeof alfresco == "undefined" ? {} : alfresco; alfresco.constants = typeof alfresco.constants == "undefined" ? {} : alfresco.constants; alfresco.constants.AJAX_LOADER_DIV_ID = "alfresco-ajax-loader"; @@ -39,15 +41,25 @@ alfresco.AjaxHelper = function() /** All pending ajax requests. */ alfresco.AjaxHelper._requests = []; +/** A counter for numbering requests - for debugging */ +alfresco.AjaxHelper._requestCounter = 0; + /** Creates an ajax request object. */ alfresco.AjaxHelper.createRequest = function(target, serverMethod, methodArgs, load, error) { var result = new dojo.io.Request(alfresco.constants.WEBAPP_CONTEXT + "/ajax/invoke/" + serverMethod, "text/xml"); + dojo.io.XMLHTTPTransport.useCache = false; + dojo.io.XMLHTTPTransport.preventCache = true; result.target = target; + methodArgs._alfresco_AjaxHelper_request_counter = alfresco.AjaxHelper._requestCounter++; + result.content = methodArgs; result.method = "POST"; + result.encoding = "UTF-8"; + result.preventCache = true; + result.useCache = false; result._baseLoadHandler = load; result.load = function(type, data, event, kwArgs) { @@ -60,14 +72,24 @@ alfresco.AjaxHelper.createRequest = function(target, serverMethod, methodArgs, l }); result.error = error || function(type, e, impl) { - dojo.debug("error [" + type + "] " + e.message); + dojo.debug("error [type:" + type + + ", number: " + e.number + + ", status: " + impl.status + + ", responseText: " + impl.responseText + + ", readyState : " + impl.readyState + + ", message: '" + e.message + + "'] while invoking [url: " + this.url + + ", content: " + methodArgs + "]"); if (impl.status == 401) { document.getElementById("logout").onclick(); } else { - _show_error(document.createTextNode(e.message)); + if (impl.status != 0) + { + _show_error(document.createTextNode(e.message)); + } alfresco.AjaxHelper._loadHandler(this); } }; @@ -78,7 +100,6 @@ alfresco.AjaxHelper.createRequest = function(target, serverMethod, methodArgs, l alfresco.AjaxHelper.sendRequest = function(req) { alfresco.AjaxHelper._sendHandler(req); - req.encoding = "utf-8"; dojo.io.queueBind(req); } diff --git a/source/web/scripts/ajax/common.js b/source/web/scripts/ajax/common.js index ea40e0c607..b7f50df824 100644 --- a/source/web/scripts/ajax/common.js +++ b/source/web/scripts/ajax/common.js @@ -435,6 +435,7 @@ if (!Array.prototype.peek) } } +// this is an exact copy of ../upload_helper.js - needs refactoring var _fileUploads = []; function handleUploadHelper(fileInputElement, diff --git a/source/web/scripts/ajax/file_picker_widget.js b/source/web/scripts/ajax/file_picker_widget.js index 938889198a..fbc8ac1009 100644 --- a/source/web/scripts/ajax/file_picker_widget.js +++ b/source/web/scripts/ajax/file_picker_widget.js @@ -42,7 +42,14 @@ if (typeof alfresco.resources == "undefined") /** * The file picker widget. */ -alfresco.FilePickerWidget = function(uploadId, node, value, readonly, change_callback, resize_callback) +alfresco.FilePickerWidget = function(uploadId, + node, + value, + readonly, + change_callback, + resize_callback, + selectableTypes, + filterMimetypes) { this.uploadId = uploadId; this.node = node; @@ -50,6 +57,8 @@ alfresco.FilePickerWidget = function(uploadId, node, value, readonly, change_cal this.readonly = readonly || false; this.change_callback = change_callback; this.resize_callback = resize_callback; + this.selectableTypes = selectableTypes; + this.filterMimetypes = filterMimetypes; } // static methods and properties @@ -234,6 +243,14 @@ _navigateToNode: function(path) this.target._showPicker(data.documentElement); }); req.content.currentPath = path; + if (this.selectableTypes) + { + req.content.selectableTypes = this.selectableTypes; + } + if (this.filterMimetypes) + { + req.content.filterMimetypes = this.filterMimetypes; + } alfresco.AjaxHelper.sendRequest(req); }, @@ -423,6 +440,7 @@ _showPicker: function(data) var row = this._createRow(fileName, webappRelativePath, childNodes[i].getAttribute("type") == "directory", + eval(childNodes[i].getAttribute("selectable")), childNodes[i].getAttribute("image"), "xformsRow" + (i % 2 ? "Even" : "Odd")); this.contentDiv.appendChild(row); @@ -434,7 +452,7 @@ _showPicker: function(data) } }, -_createRow: function(fileName, webappRelativePath, isDirectory, fileTypeImage, rowClass) +_createRow: function(fileName, webappRelativePath, isDirectory, isSelectable, fileTypeImage, rowClass) { var d = this.contentDiv.ownerDocument; var result = d.createElement("div"); @@ -492,23 +510,25 @@ _createRow: function(fileName, webappRelativePath, isDirectory, fileTypeImage, { result.appendChild(d.createTextNode(fileName)); } - - e = d.createElement("input"); - e.filePickerWidget = this; - e.type = "button"; - e.name = webappRelativePath; - e.value = "Select"; - result.appendChild(e); - - e.style.position = "absolute"; - e.style.right = "10px"; - e.style.top = (.5 * result.offsetHeight) - (.5 * e.offsetHeight) + "px"; - dojo.event.connect(e, "onclick", function(event) - { - var w = event.target.filePickerWidget; - w.setValue(event.target.name); - w._showSelectedValue(); - }); + if (isSelectable) + { + e = d.createElement("input"); + e.filePickerWidget = this; + e.type = "button"; + e.name = webappRelativePath; + e.value = "Select"; + result.appendChild(e); + + e.style.position = "absolute"; + e.style.right = "10px"; + e.style.top = (.5 * result.offsetHeight) - (.5 * e.offsetHeight) + "px"; + dojo.event.connect(e, "onclick", function(event) + { + var w = event.target.filePickerWidget; + w.setValue(event.target.name); + w._showSelectedValue(); + }); + } return result; }, diff --git a/source/web/scripts/ajax/xforms.js b/source/web/scripts/ajax/xforms.js index 0e3e796b5a..4be9ada61e 100644 --- a/source/web/scripts/ajax/xforms.js +++ b/source/web/scripts/ajax/xforms.js @@ -30,7 +30,6 @@ // Initiliaze dojo requirements, tinymce, and add a hook to load the xform. //////////////////////////////////////////////////////////////////////////////// -djConfig.bindEncoding = "UTF-8"; djConfig.parseWidgets = false; dojo.require("dojo.date.common"); dojo.require("dojo.debug.console"); @@ -286,15 +285,15 @@ dojo.declare("alfresco.xforms.Widget", }, /** Commits the changed value to the server */ - _commitValueChange: function() + _commitValueChange: function(value) { if (this._compositeParent) { - this._compositeParent._commitValueChange(); + this._compositeParent._commitValueChange(value); } else { - this.xform.setXFormsValue(this.id, this.getValue()); + this.xform.setXFormsValue(this.id, value || this.getValue()); } }, @@ -514,8 +513,10 @@ dojo.declare("alfresco.xforms.Widget", /** The file picker widget which handles xforms widget xf:upload. */ dojo.declare("alfresco.xforms.FilePicker", alfresco.xforms.Widget, - function(xform, xformsNode) + function(xform, xformsNode, params) { + this._selectableTypes = "selectable_types" in params ? params["selectable_types"].split(",") : null; + this._filterMimetypes = "filter_mimetypes" in params ? params["filter_mimetypes"].split(",") : []; }, { @@ -533,7 +534,9 @@ dojo.declare("alfresco.xforms.FilePicker", this.getInitialValue(), false, this._filePicker_changeHandler, - this._filePicker_resizeHandler); + this._filePicker_resizeHandler, + this._selectableTypes, + this._filterMimetypes); this.widget.render(); }, @@ -815,10 +818,7 @@ dojo.declare("alfresco.xforms.RichTextEditor", { this._focused = false; this._params = params; - if (!this.statics.tinyMCEInitialized) - { - this.statics.tinyMCEInitialized = true; - } + this._oldValue = null; }, { @@ -826,12 +826,17 @@ dojo.declare("alfresco.xforms.RichTextEditor", // methods & properties ///////////////////////////////////////////////////////////////// - statics: { currentInstance: null, tinyMCEInitialized: false }, + statics: { currentInstance: null }, _removeTinyMCE: function() { - var value = tinyMCE.getContent(this.id); - this._commitValueChange(); + var value = this.getValue(); //tinyMCE.getContent(this.id); + if (value != this._oldValue) + { + dojo.debug("commitValueChange from _removeTinyMCE [" + value + "]"); + this._commitValueChange(value); + this._oldValue = value; + } tinyMCE.removeMCEControl(this.id); this._focused = false; }, @@ -846,15 +851,26 @@ dojo.declare("alfresco.xforms.RichTextEditor", this.statics.currentInstance = this; - tinyMCE.settings.theme_advanced_buttons1 = this._params["theme_advanced_buttons1"] || ""; - tinyMCE.settings.theme_advanced_buttons2 = this._params["theme_advanced_buttons2"] || ""; - tinyMCE.settings.theme_advanced_buttons3 = this._params["theme_advanced_buttons3"] || ""; - if (this._params["height"]) + for (var i in alfresco.constants.TINY_MCE_DEFAULT_SETTINGS) { - tinyMCE.settings.height = parseInt(this._params["height"]); + if (!(i in this._params)) + { + this._params[i] = alfresco.constants.TINY_MCE_DEFAULT_SETTINGS[i]; + } } + for (var i in this._params) + { + if (i in tinyMCE.settings) + { + dojo.debug("setting tinyMCE.settings[" + i + "] = " + this._params[i]); + tinyMCE.settings[i] = this._params[i]; + } + } + tinyMCE.settings.height = this._params["height"] ? parseInt(this._params["height"]) : -1; + tinyMCE.settings.auto_focus = this.id; tinyMCE.addMCEControl(this.widget, this.id); + tinyMCE.getInstanceById(this.id).getWin().focus(); var editorDocument = tinyMCE.getInstanceById(this.id).getDoc(); editorDocument.widget = this; @@ -885,7 +901,8 @@ dojo.declare("alfresco.xforms.RichTextEditor", } this.widget.style.border = "1px solid black"; this.widget.style.overflow = "auto"; - this.widget.innerHTML = this.getInitialValue() || ""; + this._oldValue = this.getInitialValue() || ""; + this.widget.innerHTML = this._oldValue; var images = this.widget.getElementsByTagName("img"); for (var i = 0; i < images.length; i++) { @@ -906,25 +923,29 @@ dojo.declare("alfresco.xforms.RichTextEditor", } }, - setValue: function(value) + setValue: function(value, forceCommit) { - if (this.statics.currentInstance == this) + if (value != this._oldValue || forceCommit) { - tinyMCE.selectedInstance = tinyMCE.getInstanceById(this.id); - try + if (this.statics.currentInstance == this) { - tinyMCE.setContent(value); + tinyMCE.selectedInstance = tinyMCE.getInstanceById(this.id); + try + { + tinyMCE.setContent(value); + } + catch (e) + { + //XXXarielb figure this out - getting intermittent errors in IE. + dojo.debug(e); + } } - catch (e) + else { - //XXXarielb figure this out - getting intermittent errors in IE. - dojo.debug(e); + this.widget.innerHTML = value; } } - else - { - this.widget.innerHTML = value; - } + alfresco.xforms.RichTextEditor.superclass.setValue.call(this, value, forceCommit); }, getValue: function() @@ -964,15 +985,21 @@ dojo.declare("alfresco.xforms.RichTextEditor", event.target = event.srcElement.ownerDocument; } var widget = event.target.widget; - widget._commitValueChange(); - this._focused = false; + var value = widget.getValue(); + if (value != widget._oldValue) + { + dojo.debug("commitValueChange from _tinyMCE_blurHandler [" + value + "]"); + widget._commitValueChange(value); + widget._oldValue = value; + } + widget._focused = false; }, _tinyMCE_focusHandler: function(event) { var widget = event.target.widget; var repeatIndices = widget.getRepeatIndices(); - if (repeatIndices.length != 0 && !this._focused) + if (repeatIndices.length != 0 && !widget._focused) { var r = repeatIndices[repeatIndices.length - 1].repeat; var p = widget; @@ -991,7 +1018,7 @@ dojo.declare("alfresco.xforms.RichTextEditor", } repeatIndices[repeatIndices.length - 1].repeat.setFocusedChild(p); } - this._focused = true; + widget._focused = true; }, _div_mouseoverHandler: function(event) @@ -4206,7 +4233,7 @@ dojo.declare("alfresco.xforms.XForm", dojo.debug("setting value " + id + " = " + value); var req = alfresco.AjaxHelper.createRequest(this, "XFormsBean.setXFormsValue", - { id: id, value: value }, + { id: id, value: new String(value) }, function(type, data, evt) { this.target._handleEventLog(data.documentElement); @@ -4626,10 +4653,13 @@ dojo.html.toCamelCase = function(str) // tiny mce integration //////////////////////////////////////////////////////////////////////////////// -tinyMCE.init({ +alfresco.constants.TINY_MCE_DEFAULT_SETTINGS = +{ theme: "advanced", mode: "exact", + plugins: "table", width: -1, + height: -1, auto_resize: false, force_p_newlines: false, encoding: "UTF-8", @@ -4643,4 +4673,6 @@ tinyMCE.init({ theme_advanced_buttons2: "", theme_advanced_buttons3: "", urlconverter_callback: "alfresco_TinyMCE_urlconverter_callback" -}); +}; + +tinyMCE.init(dojo.lang.mixin(new Object(), alfresco.constants.TINY_MCE_DEFAULT_SETTINGS));