From 272549851570c24662ceb2c987e43f4abefca0da Mon Sep 17 00:00:00 2001 From: Derek Hulley Date: Wed, 7 Mar 2007 15:04:21 +0000 Subject: [PATCH] Merged V2.0 to HEAD 5178: WCM-336, checkin performance 5182: Missing OpenSearch strings 5183: AR-1126 5185: OpenSearch externalized strings 5190: Schema and xforms 5191: WCM-343 5205: NTML using incorrect auth component 5210: No virtual server start 5211: WCM-352, WCM-353 5212: Manage Task Dialog issues git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5332 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/messages/webclient.properties | 4 + .../web-client-config-wcm-actions.xml | 4 +- .../web-client-config-workflow-actions.xml | 91 ++++++++++--- .../WCMWorkflowDeletedEvaluator.java | 62 +++++++++ .../evaluator/WCMWorkflowEvaluator.java | 14 +- .../app/servlet/NTLMAuthenticationFilter.java | 4 +- .../org/alfresco/web/bean/wcm/AVMNode.java | 17 +-- .../web/bean/wcm/CreateFormWizard.java | 13 +- .../web/bean/wcm/CreateWebContentWizard.java | 59 ++++++--- .../alfresco/web/bean/wcm/EditFormWizard.java | 3 +- .../web/bean/workflow/ManageTaskDialog.java | 6 +- .../web/forms/xforms/Schema2XForms.java | 117 ++++++++++++++++- .../alfresco/web/forms/xforms/SchemaUtil.java | 51 +++++++- .../web/ui/repo/component/UIOpenSearch.java | 83 ++++++------ .../web/ui/wcm/component/UIUserSandboxes.java | 2 +- .../select-default-workflow.jsp | 2 +- source/web/scripts/ajax/xforms.js | 120 ++++++++++-------- 17 files changed, 487 insertions(+), 165 deletions(-) create mode 100644 source/java/org/alfresco/web/action/evaluator/WCMWorkflowDeletedEvaluator.java diff --git a/config/alfresco/messages/webclient.properties b/config/alfresco/messages/webclient.properties index 9f46c8ce38..69ad822f21 100644 --- a/config/alfresco/messages/webclient.properties +++ b/config/alfresco/messages/webclient.properties @@ -1310,6 +1310,10 @@ search_in=Search In no_engines_registered=Failed to find any registered OpenSearch engines! current_repo=Current Alfresco Repository toggle_options=Toggle Options +no_results=No results +of=of +failed_gen_url=Failed to generate url for search engine '{0}'.\\n\\nThis is probably caused by missing required parameters, check the template url for the search engine. +failed_search=Failed to retrieve search results for '{0}' # UI Page Titles title_about=About Alfresco diff --git a/config/alfresco/web-client-config-wcm-actions.xml b/config/alfresco/web-client-config-wcm-actions.xml index 3820fe19a4..e16145e079 100644 --- a/config/alfresco/web-client-config-wcm-actions.xml +++ b/config/alfresco/web-client-config-wcm-actions.xml @@ -82,7 +82,7 @@ Write - org.alfresco.web.action.evaluator.WCMWorkflowEvaluator + org.alfresco.web.action.evaluator.WCMWorkflowDeletedEvaluator submit /images/icons/submit.gif #{AVMBrowseBean.setupContentAction} @@ -97,7 +97,7 @@ Write - org.alfresco.web.action.evaluator.WCMWorkflowEvaluator + org.alfresco.web.action.evaluator.WCMWorkflowDeletedEvaluator revert /images/icons/revert.gif #{AVMBrowseBean.revertNode} diff --git a/config/alfresco/web-client-config-workflow-actions.xml b/config/alfresco/web-client-config-workflow-actions.xml index e26534aa21..d924c1a3d4 100644 --- a/config/alfresco/web-client-config-workflow-actions.xml +++ b/config/alfresco/web-client-config-workflow-actions.xml @@ -135,6 +135,67 @@ + + + + Write + + revert + /images/icons/revert.gif + #{AVMBrowseBean.revertNode} + + #{actionContext.id} + + + + + + org.alfresco.web.action.evaluator.WCMWorkflowEvaluator + folder_preview + /images/icons/preview_website.gif + #{actionContext.previewUrl} + new + + + + + org.alfresco.web.action.evaluator.WCMWorkflowEvaluator + file_preview + /images/icons/preview_website.gif + #{actionContext.previewUrl} + new + + + + + + Read + + org.alfresco.web.action.evaluator.WCMWorkflowEvaluator + view_details + /images/icons/View_details.gif + #{AVMBrowseBean.setupContentAction} + dialog:showFileDetails + + #{actionContext.id} + + + + + + + Read + + org.alfresco.web.action.evaluator.WCMWorkflowEvaluator + view_details + /images/icons/View_details.gif + #{AVMBrowseBean.setupContentAction} + dialog:showFolderDetails + + #{actionContext.id} + + + @@ -185,9 +246,9 @@ - - - + + + @@ -226,9 +287,9 @@ - - - + + + @@ -245,12 +306,11 @@ - - + + - - - + + @@ -263,12 +323,11 @@ - - + + - - - + + diff --git a/source/java/org/alfresco/web/action/evaluator/WCMWorkflowDeletedEvaluator.java b/source/java/org/alfresco/web/action/evaluator/WCMWorkflowDeletedEvaluator.java new file mode 100644 index 0000000000..20a2bbd9b1 --- /dev/null +++ b/source/java/org/alfresco/web/action/evaluator/WCMWorkflowDeletedEvaluator.java @@ -0,0 +1,62 @@ +/* + * 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.action.evaluator; + +import javax.faces.context.FacesContext; + +import org.alfresco.repo.avm.AVMNodeConverter; +import org.alfresco.repo.avm.wf.AVMSubmittedAspect; +import org.alfresco.service.cmr.avm.AVMService; +import org.alfresco.util.Pair; +import org.alfresco.web.action.ActionEvaluator; +import org.alfresco.web.bean.repository.Node; +import org.alfresco.web.bean.repository.Repository; +import org.alfresco.web.bean.wcm.AVMConstants; + +/** + * UI Action Evaluator - return true if the node is not part of an in-progress WCM workflow. + * No check for deleted items is made in this evaluator. @see WCMWorkflowEvaluator + * + * @author Kevin Roast + */ +public class WCMWorkflowDeletedEvaluator implements ActionEvaluator +{ + /** + * @see org.alfresco.web.action.ActionEvaluator#evaluate(org.alfresco.web.bean.repository.Node) + */ + public boolean evaluate(final Node node) + { + final FacesContext facesContext = FacesContext.getCurrentInstance(); + final AVMService avmService = Repository.getServiceRegistry(facesContext).getAVMService(); + final Pair p = AVMNodeConverter.ToAVMVersionPath(node.getNodeRef()); + final int version = p.getFirst(); + final String path = p.getSecond(); + + // evaluate to true if we are within a workflow store (i.e. list of resources in the task + // dialog) or not part of an already in-progress workflow + return (AVMConstants.isWorkflowStore(AVMConstants.getStoreName(path)) || + avmService.hasAspect(version, path, AVMSubmittedAspect.ASPECT) == false); + } +} diff --git a/source/java/org/alfresco/web/action/evaluator/WCMWorkflowEvaluator.java b/source/java/org/alfresco/web/action/evaluator/WCMWorkflowEvaluator.java index 7a7a3f7a6e..a091f23c10 100644 --- a/source/java/org/alfresco/web/action/evaluator/WCMWorkflowEvaluator.java +++ b/source/java/org/alfresco/web/action/evaluator/WCMWorkflowEvaluator.java @@ -26,10 +26,10 @@ package org.alfresco.web.action.evaluator; import javax.faces.context.FacesContext; -import org.alfresco.util.Pair; import org.alfresco.repo.avm.AVMNodeConverter; import org.alfresco.repo.avm.wf.AVMSubmittedAspect; import org.alfresco.service.cmr.avm.AVMService; +import org.alfresco.util.Pair; import org.alfresco.web.action.ActionEvaluator; import org.alfresco.web.bean.repository.Node; import org.alfresco.web.bean.repository.Repository; @@ -48,11 +48,15 @@ public class WCMWorkflowEvaluator implements ActionEvaluator public boolean evaluate(final Node node) { final FacesContext facesContext = FacesContext.getCurrentInstance(); - final AVMService avmService = - Repository.getServiceRegistry(facesContext).getAVMService(); + final AVMService avmService = Repository.getServiceRegistry(facesContext).getAVMService(); final Pair p = AVMNodeConverter.ToAVMVersionPath(node.getNodeRef()); + final int version = p.getFirst(); final String path = p.getSecond(); - return (!avmService.hasAspect(p.getFirst(), path, AVMSubmittedAspect.ASPECT) || - AVMConstants.isWorkflowStore(AVMConstants.getStoreName(path))); + + // evaluate to true if we are not deleted and within a workflow store (i.e. list of resources + // in the task dialog) or not part of an already in-progress workflow + return ((AVMConstants.isWorkflowStore(AVMConstants.getStoreName(path)) || + avmService.hasAspect(version, path, AVMSubmittedAspect.ASPECT) == false) && + avmService.lookup(version, path) != null); } } diff --git a/source/java/org/alfresco/web/app/servlet/NTLMAuthenticationFilter.java b/source/java/org/alfresco/web/app/servlet/NTLMAuthenticationFilter.java index 4456526c4b..7a17b7a1dc 100644 --- a/source/java/org/alfresco/web/app/servlet/NTLMAuthenticationFilter.java +++ b/source/java/org/alfresco/web/app/servlet/NTLMAuthenticationFilter.java @@ -173,8 +173,8 @@ public class NTLMAuthenticationFilter extends AbstractAuthenticationFilter imple m_nodeService = serviceRegistry.getNodeService(); m_transactionService = serviceRegistry.getTransactionService(); - m_authService = (AuthenticationService) ctx.getBean("authenticationService"); - m_authComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent"); + m_authService = (AuthenticationService) ctx.getBean("AuthenticationService"); + m_authComponent = (AuthenticationComponent) ctx.getBean("AuthenticationComponent"); m_personService = (PersonService) ctx.getBean("personService"); m_configService = (ConfigService) ctx.getBean("webClientConfigService"); diff --git a/source/java/org/alfresco/web/bean/wcm/AVMNode.java b/source/java/org/alfresco/web/bean/wcm/AVMNode.java index d27c5db8ce..492a31a53d 100644 --- a/source/java/org/alfresco/web/bean/wcm/AVMNode.java +++ b/source/java/org/alfresco/web/bean/wcm/AVMNode.java @@ -140,18 +140,7 @@ public class AVMNode extends Node implements Map this.avmRef = avmRef; this.version = -1; // TODO: always -1 for now... this.id = avmRef.getPath(); - } - - /** - * Constructor - * - * @param avmRef The AVMNodeDescriptor that describes this node - * @param deleted True if the node represents a ghosted deleted node - */ - public AVMNode(AVMNodeDescriptor avmRef, boolean deleted) - { - this(avmRef); - this.deleted = deleted; + this.deleted = avmRef.isDeleted(); } @Override @@ -196,12 +185,12 @@ public class AVMNode extends Node implements Map public final boolean isDirectory() { - return this.avmRef.isDirectory(); + return this.avmRef.isDirectory() || this.avmRef.isDeletedDirectory(); } public final boolean isFile() { - return this.avmRef.isFile(); + return this.avmRef.isFile() || this.avmRef.isDeletedFile(); } /** diff --git a/source/java/org/alfresco/web/bean/wcm/CreateFormWizard.java b/source/java/org/alfresco/web/bean/wcm/CreateFormWizard.java index 648164a695..88a34b8a15 100644 --- a/source/java/org/alfresco/web/bean/wcm/CreateFormWizard.java +++ b/source/java/org/alfresco/web/bean/wcm/CreateFormWizard.java @@ -33,6 +33,7 @@ import java.util.List; import java.util.Map; import java.util.ResourceBundle; +import javax.faces.application.FacesMessage; import javax.faces.context.FacesContext; import javax.faces.event.ActionEvent; import javax.faces.event.ValueChangeEvent; @@ -62,6 +63,7 @@ import org.alfresco.web.forms.RenderingEngine; import org.alfresco.web.forms.RenderingEngineTemplate; import org.alfresco.web.forms.RenderingEngineTemplateImpl; import org.alfresco.web.forms.XMLUtil; +import org.alfresco.web.forms.xforms.FormBuilderException; import org.alfresco.web.forms.xforms.SchemaUtil; import org.alfresco.web.ui.common.Utils; import org.alfresco.web.ui.common.component.UIListItem; @@ -615,7 +617,16 @@ public class CreateFormWizard try { final Document d = XMLUtil.parse(this.getSchemaFile()); - this.schema = SchemaUtil.parseSchema(d); + try + { + this.schema = SchemaUtil.parseSchema(d, true); + } + catch (FormBuilderException fbe) + { + this.schema = SchemaUtil.parseSchema(d, false); + LOGGER.warn("non fatal errors encountered parsing schema " + this.getFileName(FILE_SCHEMA) + + "\n " + fbe.getMessage()); + } } catch (Exception e) { diff --git a/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java b/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java index b61615ee4a..95a45343be 100644 --- a/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java +++ b/source/java/org/alfresco/web/bean/wcm/CreateWebContentWizard.java @@ -309,24 +309,15 @@ public class CreateWebContentWizard extends BaseContentWizard } } this.avmSyncService.update(diffList, null, true, true, true, true, null, null); - - // reset all paths and structures to the main store - this.createdPath = AVMConstants.getCorrespondingPathInMainStore(this.createdPath); - if (LOGGER.isDebugEnabled()) - LOGGER.debug("reset path " + this.createdPath + " to main store"); - boolean form = (MimetypeMap.MIMETYPE_XML.equals(this.mimeType) && this.formName != null); - if (form) - { - this.formInstanceData = new FormInstanceDataImpl(AVMNodeConverter.ToNodeRef(-1, this.createdPath)); - this.renditions = this.formInstanceData.getRenditions(); - if (LOGGER.isDebugEnabled()) - LOGGER.debug("reset form instance data " + this.formInstanceData.getName() + - " and " + this.renditions.size() + " to main store"); - } if (this.startWorkflow) { final WorkflowDefinition wd = this.getForm().getDefaultWorkflow(); + if (wd == null) + { + throw new AlfrescoRuntimeException(Application.getMessage(context, "submit_no_workflow_warning")); + } + final Map parameters = this.getForm().getDefaultWorkflowParameters(); if (LOGGER.isDebugEnabled()) @@ -334,8 +325,7 @@ public class CreateWebContentWizard extends BaseContentWizard if (parameters == null) { - Utils.addErrorMessage(Application.getMessage(context, "submit_workflow_config_error")); - return null; + throw new AlfrescoRuntimeException(Application.getMessage(context, "submit_workflow_config_error")); } // start the workflow to get access to the start task @@ -357,7 +347,7 @@ public class CreateWebContentWizard extends BaseContentWizard final List srcPaths = new ArrayList(); // construct diffs for selected items for submission final String sandboxName = this.avmBrowseBean.getSandbox(); - if (form) + if (MimetypeMap.MIMETYPE_XML.equals(this.mimeType) && this.formName != null) { // collect diffs for form data instance and all renditions for (Rendition rendition : this.getRenditions()) @@ -379,10 +369,17 @@ public class CreateWebContentWizard extends BaseContentWizard } if (LOGGER.isDebugEnabled()) - LOGGER.debug("creating workflow package with " + srcPaths.size() + " files"); + { + LOGGER.debug("creating workflow package with " + srcPaths.size() + " files: {"); + for (final String srcPath : srcPaths) + { + LOGGER.debug("-- " + srcPath + ","); + } + LOGGER.debug("}"); + } // Create workflow sandbox for workflow package - SandboxInfo sandboxInfo = SandboxFactory.createWorkflowSandbox(storeId); + final SandboxInfo sandboxInfo = SandboxFactory.createWorkflowSandbox(storeId); final NodeRef packageNodeRef = AVMWorkflowUtil.createWorkflowPackage(srcPaths, @@ -396,7 +393,10 @@ public class CreateWebContentWizard extends BaseContentWizard parameters.put(WorkflowModel.ASSOC_PACKAGE, packageNodeRef); // TODO: capture label and comment? - parameters.put(AVMWorkflowUtil.PROP_LABEL, form ? this.formInstanceData.getName() : this.getFileName()); + parameters.put(AVMWorkflowUtil.PROP_LABEL, + MimetypeMap.MIMETYPE_XML.equals(this.mimeType) && this.formName != null + ? this.formInstanceData.getName() + : this.getFileName()); parameters.put(AVMWorkflowUtil.PROP_FROM_PATH, AVMConstants.buildStoreRootPath(sandboxName)); // update start task with submit parameters @@ -417,6 +417,25 @@ public class CreateWebContentWizard extends BaseContentWizard // return the default outcome return outcome; } + + @Override + protected String doPostCommitProcessing(final FacesContext facesContext, final String outcome) + { + // reset all paths and structures to the main store + this.createdPath = AVMConstants.getCorrespondingPathInMainStore(this.createdPath); + if (LOGGER.isDebugEnabled()) + LOGGER.debug("reset path " + this.createdPath + " to main store"); + + if (MimetypeMap.MIMETYPE_XML.equals(this.mimeType) && this.formName != null) + { + this.formInstanceData = new FormInstanceDataImpl(AVMNodeConverter.ToNodeRef(-1, this.createdPath)); + this.renditions = this.formInstanceData.getRenditions(); + if (LOGGER.isDebugEnabled()) + LOGGER.debug("reset form instance data " + this.formInstanceData.getName() + + " and " + this.renditions.size() + " to main store"); + } + return super.doPostCommitProcessing(facesContext, outcome); + } @Override public boolean getNextButtonDisabled() diff --git a/source/java/org/alfresco/web/bean/wcm/EditFormWizard.java b/source/java/org/alfresco/web/bean/wcm/EditFormWizard.java index 747c9030a4..8635c61d41 100644 --- a/source/java/org/alfresco/web/bean/wcm/EditFormWizard.java +++ b/source/java/org/alfresco/web/bean/wcm/EditFormWizard.java @@ -42,6 +42,7 @@ import org.alfresco.service.cmr.workflow.WorkflowDefinition; import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.RegexQNamePattern; import org.alfresco.web.app.AlfrescoNavigationHandler; +import org.alfresco.web.forms.xforms.FormBuilderException; import org.alfresco.web.forms.xforms.SchemaUtil; import org.alfresco.web.forms.Form; import org.alfresco.web.forms.FormsService; @@ -94,7 +95,7 @@ public class EditFormWizard ContentModel.PROP_NAME)); try { - this.schema = SchemaUtil.parseSchema(form.getSchema()); + this.schema = SchemaUtil.parseSchema(form.getSchema(), false); } catch (Throwable t) { diff --git a/source/java/org/alfresco/web/bean/workflow/ManageTaskDialog.java b/source/java/org/alfresco/web/bean/workflow/ManageTaskDialog.java index 94882167fd..8e054ede8a 100644 --- a/source/java/org/alfresco/web/bean/workflow/ManageTaskDialog.java +++ b/source/java/org/alfresco/web/bean/workflow/ManageTaskDialog.java @@ -658,12 +658,14 @@ public class ManageTaskDialog extends BaseDialogBean WCMModel.PROP_AVM_DIR_INDIRECTION); final String stagingAvmPath = AVMNodeConverter.ToAVMVersionPath(stagingNodeRef).getSecond(); final String packageAvmPath = AVMNodeConverter.ToAVMVersionPath(this.workflowPackage).getSecond(); - LOGGER.debug("comparing " + packageAvmPath + " with " + stagingAvmPath); + if (LOGGER.isDebugEnabled()) + LOGGER.debug("comparing " + packageAvmPath + " with " + stagingAvmPath); for (AVMDifference d : this.avmSyncService.compare(-1, packageAvmPath, -1, stagingAvmPath, null)) { - LOGGER.debug("got difference " + d); + if (LOGGER.isDebugEnabled()) + LOGGER.debug("got difference " + d); if (d.getDifferenceCode() == AVMDifference.NEWER || d.getDifferenceCode() == AVMDifference.CONFLICT) { diff --git a/source/java/org/alfresco/web/forms/xforms/Schema2XForms.java b/source/java/org/alfresco/web/forms/xforms/Schema2XForms.java index 50cd5285c5..228487cfb7 100644 --- a/source/java/org/alfresco/web/forms/xforms/Schema2XForms.java +++ b/source/java/org/alfresco/web/forms/xforms/Schema2XForms.java @@ -135,7 +135,7 @@ public class Schema2XForms final ResourceBundle resourceBundle) throws FormBuilderException { - final XSModel schema = SchemaUtil.parseSchema(schemaDocument); + final XSModel schema = SchemaUtil.parseSchema(schemaDocument, true); this.typeTree = SchemaUtil.buildTypeTree(schema); //refCounter = 0; @@ -278,9 +278,13 @@ public class Schema2XForms if (importedInstanceDocumentElement != null) { + this.insertUpdatedNodes(importedInstanceDocumentElement, + defaultInstanceDocumentElement, + schemaNamespacesMap); this.insertPrototypeNodes(importedInstanceDocumentElement, defaultInstanceDocumentElement, schemaNamespacesMap); + } this.createSubmitElements(xformsDocument, modelSection, rootGroup); @@ -303,6 +307,117 @@ public class Schema2XForms this.counter.clear(); } + /** + * Inserts nodes that exist in the prototype document that are absent in the imported instance. + * This is to handle the case where a schema has been updated since the last time the + * imported document was modified. + * + * @param instanceDocumentElement the user provided instance document + * @param prototypeInstanceElement the generated prototype instance document + * @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) + { + LOGGER.debug("updating imported instance document"); + final JXPathContext prototypeContext = + JXPathContext.newContext(prototypeDocumentElement); + prototypeContext.registerNamespace(NamespaceService.ALFRESCO_PREFIX, + NamespaceService.ALFRESCO_URI); + final JXPathContext instanceContext = + JXPathContext.newContext(instanceDocumentElement); + instanceContext.registerNamespace(NamespaceService.ALFRESCO_PREFIX, + NamespaceService.ALFRESCO_URI); + + // identify all non prototype elements in the prototypeDocument + for (final String prefix : schemaNamespaces.keySet()) + { + prototypeContext.registerNamespace(prefix, schemaNamespaces.get(prefix)); + instanceContext.registerNamespace(prefix, schemaNamespaces.get(prefix)); + } + + final Iterator it = + prototypeContext.iteratePointers("//*[not(@" + NamespaceService.ALFRESCO_PREFIX + + ":prototype='true')] | //@*[name()!='" + NamespaceService.ALFRESCO_PREFIX + + ":prototype']"); + while (it.hasNext()) + { + final Pointer p = (Pointer)it.next(); + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("evaluating prototype node " + p.asPath() + + " normalized " + p.asPath().replaceAll("\\[\\d+\\]", "")); + } + + String path = p.asPath().replaceAll("\\[\\d+\\]", ""); + if (path.lastIndexOf("/") == 0) + { + if (instanceContext.selectNodes(path).size() == 0) + { + LOGGER.debug("copying " + path + " into imported instance"); + // remove child elements - we want attributes but don't want to + // copy any potential prototyp nodes + final Node clone = ((Node)p.getNode()).cloneNode(true); + if (clone instanceof Attr) + { + instanceDocumentElement.setAttributeNode((Attr)clone); + } + else + { + final NodeList children = clone.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) + { + if (children.item(i) instanceof Element) + { + clone.removeChild(children.item(i)); + } + } + instanceDocumentElement.appendChild(clone); + } + } + } + else + { + // change path /foo/bar into /foo[not(child::bar)] + if (path.indexOf("@") >= 0) + { + path = path.replaceAll("\\/(@.+)$", "[not($1)]"); + } + else + { + path = path.replaceAll("\\/([^/]+)$", "[not(child::$1)]"); + } + final List l = (List)instanceContext.selectNodes(path); + LOGGER.debug("appending node " + ((Node)p.getNode()).getNodeName() + + " to the " + l.size() + " selected nodes matching path " + path); + for (Node n : l) + { + // remove child elements - we want attributes but don't want to + // copy any potential prototyp nodes + final Node clone = ((Node)p.getNode()).cloneNode(true); + if (clone instanceof Attr) + { + ((Element)n).setAttributeNode((Attr)clone); + } + else + { + final NodeList children = clone.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) + { + if (children.item(i) instanceof Element) + { + clone.removeChild(children.item(i)); + } + } + n.appendChild(clone); + } + } + } + } + } + /** * Inserts prototype nodes into the provided instance document by aggregating insertion * points from the generated prototype instance docment. diff --git a/source/java/org/alfresco/web/forms/xforms/SchemaUtil.java b/source/java/org/alfresco/web/forms/xforms/SchemaUtil.java index c0c227f70e..fca3ae92fc 100644 --- a/source/java/org/alfresco/web/forms/xforms/SchemaUtil.java +++ b/source/java/org/alfresco/web/forms/xforms/SchemaUtil.java @@ -32,7 +32,7 @@ import org.apache.commons.logging.LogFactory; import org.apache.xerces.xs.*; import org.w3c.dom.bootstrap.DOMImplementationRegistry; import org.w3c.dom.ls.*; -import org.w3c.dom.Document; +import org.w3c.dom.*; /** * Provides utility functions for xml schema parsing. @@ -208,7 +208,8 @@ public class SchemaUtil return SchemaUtil.DATA_TYPE_TO_NAME.get(type); } - public static XSModel parseSchema(final Document schemaDocument) + public static XSModel parseSchema(final Document schemaDocument, + final boolean failOnError) throws FormBuilderException { try @@ -222,13 +223,59 @@ public class SchemaUtil final DOMImplementationLS lsImpl = (DOMImplementationLS) registry.getDOMImplementation("XML 1.0 LS 3.0"); + if (lsImpl == null) + { + throw new FormBuilderException("unable to create DOMImplementationLS using " + registry); + } final LSInput in = lsImpl.createLSInput(); in.setStringData(XMLUtil.toString(schemaDocument)); final XSImplementation xsImpl = (XSImplementation) registry.getDOMImplementation("XS-Loader"); final XSLoader schemaLoader = xsImpl.createXSLoader(null); + final DOMConfiguration config = schemaLoader.getConfig(); + final LinkedList errors = new LinkedList(); + config.setParameter("error-handler", new DOMErrorHandler() + { + public boolean handleError(final DOMError domError) + { + errors.add(domError); + return true; + } + }); + final XSModel result = schemaLoader.load(in); + if (failOnError && errors.size() != 0) + { + final HashSet messages = new HashSet(); + StringBuilder message = null; + for (DOMError e : errors) + { + message = new StringBuilder(); + final DOMLocator dl = e.getLocation(); + if (dl != null) + { + message.append("at line ").append(dl.getLineNumber()) + .append(" column ").append(dl.getColumnNumber()); + if (dl.getRelatedNode() != null) + { + message.append(" node ").append(dl.getRelatedNode().getNodeName()); + } + message.append(": ").append(e.getMessage()); + } + messages.add(message.toString()); + } + + message = new StringBuilder(); + message.append(messages.size() > 1 ? "errors" : "error").append(" parsing schema: \n"); + for (final String s : messages) + { + message.append(s).append("\n"); + } + + throw new FormBuilderException(message.toString()); + } + if (result == null) { throw new FormBuilderException("invalid schema"); diff --git a/source/java/org/alfresco/web/ui/repo/component/UIOpenSearch.java b/source/java/org/alfresco/web/ui/repo/component/UIOpenSearch.java index 99d9402623..97432d8570 100644 --- a/source/java/org/alfresco/web/ui/repo/component/UIOpenSearch.java +++ b/source/java/org/alfresco/web/ui/repo/component/UIOpenSearch.java @@ -115,48 +115,49 @@ public class UIOpenSearch extends SelfRenderingComponent out.write("', '"); out.write(engine.getUrl()); out.write("');\n"); - - // pass in NLS strings - out.write(clientId); - out.write(".setMsgNoResults(\""); - out.write(Application.getMessage(context, "no_results")); - out.write("\");\n"); - - out.write(clientId); - out.write(".setMsgOf(\""); - out.write(Application.getMessage(context, "of")); - out.write("\");\n"); - - out.write(clientId); - out.write(".setMsgFailedGenerateUrl(\""); - out.write(Application.getMessage(context, "failed_gen_url")); - out.write("\");\n"); - - out.write(clientId); - out.write(".setMsgFailedSearch(\""); - out.write(Application.getMessage(context, "failed_search")); - out.write("\");\n"); - - out.write(clientId); - out.write(".setMsgFirstPage(\""); - out.write(Application.getMessage(context, "first_page")); - out.write("\");\n"); - - out.write(clientId); - out.write(".setMsgPreviousPage(\""); - out.write(Application.getMessage(context, "prev_page")); - out.write("\");\n"); - - out.write(clientId); - out.write(".setMsgNextPage(\""); - out.write(Application.getMessage(context, "next_page")); - out.write("\");\n"); - - out.write(clientId); - out.write(".setMsgLastPage(\""); - out.write(Application.getMessage(context, "last_page")); - out.write("\");\n"); } + + // pass in NLS strings + out.write(clientId); + out.write(".setMsgNoResults(\""); + out.write(Application.getMessage(context, "no_results")); + out.write("\");\n"); + + out.write(clientId); + out.write(".setMsgOf(\""); + out.write(Application.getMessage(context, "of")); + out.write("\");\n"); + + out.write(clientId); + out.write(".setMsgFailedGenerateUrl(\""); + out.write(Application.getMessage(context, "failed_gen_url")); + out.write("\");\n"); + + out.write(clientId); + out.write(".setMsgFailedSearch(\""); + out.write(Application.getMessage(context, "failed_search")); + out.write("\");\n"); + + out.write(clientId); + out.write(".setMsgFirstPage(\""); + out.write(Application.getMessage(context, "first_page")); + out.write("\");\n"); + + out.write(clientId); + out.write(".setMsgPreviousPage(\""); + out.write(Application.getMessage(context, "prev_page")); + out.write("\");\n"); + + out.write(clientId); + out.write(".setMsgNextPage(\""); + out.write(Application.getMessage(context, "next_page")); + out.write("\");\n"); + + out.write(clientId); + out.write(".setMsgLastPage(\""); + out.write(Application.getMessage(context, "last_page")); + out.write("\");\n"); + out.write("\n"); // write out the HTML diff --git a/source/java/org/alfresco/web/ui/wcm/component/UIUserSandboxes.java b/source/java/org/alfresco/web/ui/wcm/component/UIUserSandboxes.java index eb30ad69d9..e01e2cbca8 100644 --- a/source/java/org/alfresco/web/ui/wcm/component/UIUserSandboxes.java +++ b/source/java/org/alfresco/web/ui/wcm/component/UIUserSandboxes.java @@ -787,7 +787,7 @@ public class UIUserSandboxes extends SelfRenderingComponent out.write(""); // deleted UI actions for this item - uiDeletedActions.setContext(new AVMNode(node, true)); + uiDeletedActions.setContext(new AVMNode(node)); Utils.encodeRecursive(fc, uiDeletedActions); } out.write(""); diff --git a/source/web/jsp/wcm/create-form-wizard/select-default-workflow.jsp b/source/web/jsp/wcm/create-form-wizard/select-default-workflow.jsp index 9baeb43a06..1c4f99dba5 100644 --- a/source/web/jsp/wcm/create-form-wizard/select-default-workflow.jsp +++ b/source/web/jsp/wcm/create-form-wizard/select-default-workflow.jsp @@ -41,7 +41,7 @@ function apply_default_workflow_changed(value) + itemLabel="#{msg.no_not_now}" itemValue="false"/>
 
diff --git a/source/web/scripts/ajax/xforms.js b/source/web/scripts/ajax/xforms.js index e8085b0897..81790815d8 100644 --- a/source/web/scripts/ajax/xforms.js +++ b/source/web/scripts/ajax/xforms.js @@ -35,12 +35,7 @@ dojo.require("dojo.date.common"); dojo.require("dojo.debug.console"); dojo.require("dojo.lang.assert"); dojo.require("dojo.lfx.html"); -dojo.require("dojo.widget.Button"); -dojo.require("dojo.widget.DatePicker"); -dojo.require("dojo.widget.DebugConsole"); -dojo.require("dojo.widget.Slider"); -dojo.require("dojo.widget.TimePicker"); -dojo.hostenv.writeIncludes(); +//dojo.hostenv.writeIncludes(); function _xforms_init() { @@ -149,26 +144,32 @@ dojo.declare("alfresco.xforms.Widget", /** Sets the widget's modified state, as indicated by an XFormsEvent. */ setModified: function(b) { - this._modified = b; - this._updateDisplay(); - if (this.isValidForSubmit()) + if (this._modified != b) { - this.hideAlert(); + this._modified = b; + this._updateDisplay(false); + if (this.isValidForSubmit()) + { + this.hideAlert(); + } } }, /** Sets the widget's valid state, as indicated by an XFormsEvent */ setValid: function(b) { - this._valid = b; - this._updateDisplay(); - if (this.isValidForSubmit()) + if (this._valid != b) { - this.hideAlert(); - } - else - { - this.showAlert(); + this._valid = b; + this._updateDisplay(false); + if (this.isValidForSubmit()) + { + this.hideAlert(); + } + else + { + this.showAlert(); + } } }, @@ -260,8 +261,11 @@ dojo.declare("alfresco.xforms.Widget", /** Sets the widget's required state, as indicated by an XFormsEvent */ setRequired: function(b) { - this._required = b; - this._updateDisplay(); + if (this._required != b) + { + this._required = b; + this._updateDisplay(false); + } }, /** Indicates if a value is required for the widget. */ @@ -473,10 +477,8 @@ dojo.declare("alfresco.xforms.Widget", }, /** Updates the display of the widget. This is intended to be overridden. */ - _updateDisplay: function() + _updateDisplay: function(recursively) { -// this.domContainer.style.backgroundColor = -// (!this._valid ? "yellow" : this._modified ? "lightgreen" : "white"); }, /** Destroy the widget and any resources no longer needed. */ @@ -666,6 +668,7 @@ dojo.declare("alfresco.xforms.NumericalRange", alfresco.xforms.Widget, function(xform, xformsNode) { + dojo.require("dojo.widget.Slider"); this.fractionDigits = (_hasAttribute(this.xformsNode, alfresco_xforms_constants.ALFRESCO_PREFIX + ":fractionDigits") ? Number(this.xformsNode.getAttribute(alfresco_xforms_constants.ALFRESCO_PREFIX + ":fractionDigits")) : -1); @@ -1366,6 +1369,7 @@ dojo.declare("alfresco.xforms.DatePicker", alfresco.xforms.Widget, function(xform, xformsNode) { + dojo.require("dojo.widget.DatePicker"); this._noValueSet = (alfresco_xforms_constants.resources["eg"] + " " + dojo.date.format(new Date(), {datePattern: alfresco_xforms_constants.DATE_FORMAT, @@ -1520,6 +1524,7 @@ dojo.declare("alfresco.xforms.TimePicker", alfresco.xforms.Widget, function(xform, xformsNode) { + dojo.require("dojo.widget.TimePicker"); this._noValueSet = (alfresco_xforms_constants.resources["eg"] + " " + dojo.date.format(new Date(), {timePattern: alfresco_xforms_constants.TIME_FORMAT, @@ -1682,6 +1687,9 @@ dojo.declare("alfresco.xforms.DateTimePicker", alfresco.xforms.Widget, function(xform, xformsNode) { + dojo.require("dojo.widget.DatePicker"); + dojo.require("dojo.widget.TimePicker"); + this._noValueSet = (alfresco_xforms_constants.resources["eg"] + " " + dojo.date.format(new Date(), {datePattern: alfresco_xforms_constants.DATE_TIME_FORMAT, @@ -1716,10 +1724,10 @@ dojo.declare("alfresco.xforms.DateTimePicker", var jsDate = this.getValue() ? dojo.date.fromRfc3339(this.getValue()) : new Date(); this.widget.timePicker = dojo.widget.createWidget("TimePicker", - { - value: jsDate - }, - timePickerDiv); + { + value: jsDate + }, + timePickerDiv); this.widget.timePicker.anyTimeContainerNode.innerHTML = ""; // don't let it float - it screws up layout somehow @@ -2247,7 +2255,7 @@ dojo.declare("alfresco.xforms.Group", } contentDiv.widget = child; - this._updateDisplay(); + this._updateDisplay(false); this._childAdded(child); return child.domContainer; }, @@ -2272,7 +2280,7 @@ dojo.declare("alfresco.xforms.Group", dojo.dom.removeChildren(child.domContainer); dojo.dom.removeNode(child.domContainer); - child.domContainer.group._updateDisplay(); + child.domContainer.group._updateDisplay(false); }; anim.play(); @@ -2414,7 +2422,7 @@ dojo.declare("alfresco.xforms.Group", } }, - _updateDisplay: function() + _updateDisplay: function(recursively) { if (dojo.render.html.ie) { @@ -2445,7 +2453,10 @@ dojo.declare("alfresco.xforms.Group", : (1 - (contentDiv.offsetLeft / this._children[i].domContainer.parentNode.offsetWidth)) * 100 + "%"); - this._children[i]._updateDisplay(); + if (recursively) + { + this._children[i]._updateDisplay(recursively); + } if (!(this._children[i] instanceof alfresco.xforms.Group)) { @@ -2648,7 +2659,7 @@ dojo.declare("alfresco.xforms.SwitchGroup", this._children[i].domContainer.style.display = "none"; } } - this._updateDisplay(); + this._updateDisplay(false); } }); @@ -2836,7 +2847,7 @@ dojo.declare("alfresco.xforms.Repeat", { oldFocusedRepeat._selectedIndex = -1; } - oldFocusedRepeat._updateDisplay(); + oldFocusedRepeat._updateDisplay(false); } var repeatIndices = this.getRepeatIndices(); @@ -2888,13 +2899,13 @@ dojo.declare("alfresco.xforms.Repeat", for (var i = 0; i < this.repeatControls.length; i++) { dojo.html.setOpacity(this.repeatControls[i].moveRepeatItemUpImage, - i == 0 ? .3 : 1); + i == 0 ? .3 : 1); dojo.html.setOpacity(this.repeatControls[i].moveRepeatItemDownImage, - i == this.repeatControls.length - 1 ? .3 : 1); + i == this.repeatControls.length - 1 ? .3 : 1); dojo.html.setOpacity(this.repeatControls[i].insertRepeatItemImage, - insertEnabled ? 1 : .3); + insertEnabled ? 1 : .3); dojo.html.setOpacity(this.repeatControls[i].removeRepeatItemImage, - removeEnabled ? 1 : .3); + removeEnabled ? 1 : .3); } }, @@ -3046,9 +3057,9 @@ dojo.declare("alfresco.xforms.Repeat", return this.domNode; }, - _updateDisplay: function() + _updateDisplay: function(recursively) { - alfresco.xforms.Repeat.superclass._updateDisplay.call(this); + alfresco.xforms.Repeat.superclass._updateDisplay.call(this, recursively); if (this.getViewRoot().focusedRepeat != null && (this.getViewRoot().focusedRepeat == this || this.getViewRoot().focusedRepeat.isAncestorOf(this))) @@ -3065,28 +3076,29 @@ dojo.declare("alfresco.xforms.Repeat", for (var i = 0; i < this._children.length; i++) { + var domContainerClasses = dojo.html.getClasses(this._children[i].domContainer); if (i + 1 == this.getSelectedIndex() && this.getViewRoot().focusedRepeat == this) { - if (dojo.html.hasClass(this._children[i].domContainer, "xformsRowOdd")) + if (domContainerClasses.indexOf("xformsRowOdd") >= 0) { dojo.html.removeClass(this._children[i].domContainer, "xformsRowOdd"); } - if (dojo.html.hasClass(this._children[i].domContainer, "xformsRowEven")) + if (domContainerClasses.indexOf("xformsRowEven") >= 0) { dojo.html.removeClass(this._children[i].domContainer, "xformsRowEven"); } - if (!dojo.html.hasClass(this._children[i].domContainer,"xformsRepeatItemSelected")) + if (domContainerClasses.indexOf("xformsRepeatItemSelected") < 0) { dojo.html.addClass(this._children[i].domContainer, "xformsRepeatItemSelected"); } } else { - if (dojo.html.hasClass(this._children[i].domContainer, "xformsRepeatItemSelected")) + if (domContainerClasses.indexOf("xformsRepeatItemSelected") >= 0) { dojo.html.removeClass(this._children[i].domContainer, "xformsRepeatItemSelected"); } - if (dojo.html.hasClass(this._children[i].domContainer, "xformsRow" + (i % 2 ? "Odd" : "Even"))) + if (domContainerClasses.indexOf("xformsRow" + (i % 2 ? "Odd" : "Even")) >= 0) { dojo.html.removeClass(this._children[i].domContainer, "xformsRow" + (i % 2 ? "Odd" : "Even")); } @@ -3206,7 +3218,7 @@ dojo.declare("alfresco.xforms.Repeat", { dojo.debug(this.id + ".handleIndexChanged(" + index + ")"); this._selectedIndex = index; - this._updateDisplay(); + this._updateDisplay(false); }, /** Returns a clone of the specified prototype id. */ @@ -3311,15 +3323,12 @@ dojo.declare("alfresco.xforms.Trigger", render: function(attach_point) { - var nodeRef = document.createElement("div"); - attach_point.appendChild(nodeRef); - this.widget = dojo.widget.createWidget("Button", - { - widgetId: this.id + "-widget", - caption: this.getLabel() + " " + this.id - }, - nodeRef); - dojo.event.connect(this.widget, "onClick", this, this._clickHandler); + attach_point.appendChild(this.domNode); + this.widget = document.createElement("input"); + this.widget.setAttribute("type", "submit"); + this.widget.setAttribute("id", this.id + "-widget"); + this.widget.setAttribute("value", this.getLabel() + " " + this.id); + dojo.event.connect(this.widget, "onclick", this, this._clickHandler); this.domContainer.style.display = "none"; }, @@ -3394,7 +3403,7 @@ dojo.declare("alfresco.xforms.Submit", _hide_errors(); xform.submitWidget = event.target.widget; xform.submitWidget.currentButton = event.target; - xform.submitWidget.widget.buttonClick(); + xform.submitWidget.fire(); return false; } } @@ -3582,7 +3591,6 @@ dojo.declare("alfresco.xforms.XForm", this.rootWidget = new alfresco.xforms.ViewRoot(this, rootGroup); this.rootWidget.render(alfUI); this.loadWidgets(rootGroup, this.rootWidget); -// this.rootWidget._updateDisplay(); }, /** Creates the widget for the provided xforms node. */