diff --git a/source/java/org/alfresco/web/bean/wcm/AVMEditBean.java b/source/java/org/alfresco/web/bean/wcm/AVMEditBean.java index 17b281420c..85e41d28e8 100644 --- a/source/java/org/alfresco/web/bean/wcm/AVMEditBean.java +++ b/source/java/org/alfresco/web/bean/wcm/AVMEditBean.java @@ -240,11 +240,17 @@ public class AVMEditBean { if (this.form == null) { - final String formName = (String) - this.nodeService.getProperty(this.getAvmNode().getNodeRef(), - WCMAppModel.PROP_PARENT_FORM_NAME); + 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); + LOGGER.debug("loaded form " + this.form + + ", form name " + formName + + ", for " + this.getAvmNode().getPath()); } return this.form; } @@ -441,7 +447,10 @@ public class AVMEditBean } catch (Throwable t) { - LOGGER.error(t, t); + LOGGER.error("error regenerating " + rendition.getName() + + ": " + t.getMessage(), t); + Utils.addErrorMessage("error regenerating " + rendition.getName() + + ": " + t.getMessage(), t); } } final NodeRef[] uploadedFiles = this.formProcessorSession.getUploadedFiles(); @@ -539,6 +548,7 @@ public class AVMEditBean setEditorOutput(null); this.instanceDataDocument = null; this.formProcessorSession = null; + this.form = null; } /** diff --git a/source/java/org/alfresco/web/bean/wcm/CreateFormWizard.java b/source/java/org/alfresco/web/bean/wcm/CreateFormWizard.java index afd471c2d8..9b1a0454ee 100644 --- a/source/java/org/alfresco/web/bean/wcm/CreateFormWizard.java +++ b/source/java/org/alfresco/web/bean/wcm/CreateFormWizard.java @@ -501,6 +501,11 @@ public class CreateFormWizard public void addSelectedRenderingEngineTemplate(final ActionEvent event) { final String name = this.getRenderingEngineTemplateName(); + if (name == null || name.length() == 0) + { + Utils.addErrorMessage("Please provide a name for the rendering engine template"); + return; + } final String opp = this.getOutputPathPatternForRendition(); final String mimetype = this.getMimetypeForRendition(); for (RenderingEngineTemplateData retd : this.renderingEngineTemplates) diff --git a/source/java/org/alfresco/web/forms/AbstractRenderingEngine.java b/source/java/org/alfresco/web/forms/AbstractRenderingEngine.java deleted file mode 100644 index ced4a85c0a..0000000000 --- a/source/java/org/alfresco/web/forms/AbstractRenderingEngine.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2005 Alfresco, Inc. - * - * Licensed under the Mozilla Public License version 1.1 - * with a permitted attribution clause. You may obtain a - * copy of the License at - * - * http://www.alfresco.org/legal/license.txt - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific - * language governing permissions and limitations under the - * License. - */ -package org.alfresco.web.forms; - -import java.util.HashMap; -import java.util.Map; -import javax.faces.context.FacesContext; -import org.alfresco.model.WCMModel; -import org.alfresco.repo.avm.AVMNodeConverter; -import org.alfresco.service.cmr.remote.AVMRemote; -import org.alfresco.service.cmr.repository.ContentService; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.web.bean.wcm.AVMConstants; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.web.context.WebApplicationContext; -import org.springframework.web.jsf.FacesContextUtils; - -/** - * Provides helper functions for form data renderers. - */ -public abstract class AbstractRenderingEngine - implements RenderingEngine -{ - private static final Log LOGGER = LogFactory.getLog(AbstractRenderingEngine.class); - - protected static final String ALFRESCO_NS = "http://www.alfresco.org/alfresco"; - protected static final String ALFRESCO_NS_PREFIX = "alfresco"; - - protected AbstractRenderingEngine() - { - } - - protected static AVMRemote getAVMRemote() - { - final FacesContext fc = - FacesContext.getCurrentInstance(); - final WebApplicationContext wac = - FacesContextUtils.getRequiredWebApplicationContext(fc); - return (AVMRemote)wac.getBean("avmRemote"); - } - - protected static FormDataFunctions getFormDataFunctions() - { - return new FormDataFunctions(AbstractRenderingEngine.getAVMRemote()); - } - - protected HashMap getStandardParameters(final FormInstanceData formInstanceData, - final Rendition rendition) - { - final String formInstanceDataAvmPath = formInstanceData.getPath(); - final String renditionAvmPath = rendition.getPath(); - final HashMap parameters = new HashMap(); - parameters.put("avm_sandbox_url", AVMConstants.buildStoreUrl(formInstanceDataAvmPath)); - parameters.put("form_instance_data_file_name", AVMNodeConverter.SplitBase(formInstanceDataAvmPath)[1]); - parameters.put("rendition_file_name", AVMNodeConverter.SplitBase(renditionAvmPath)[1]); - parameters.put("parent_path", AVMNodeConverter.SplitBase(formInstanceDataAvmPath)[0]); - final FacesContext fc = FacesContext.getCurrentInstance(); - parameters.put("request_context_path", fc.getExternalContext().getRequestContextPath()); - return parameters; - } -} \ No newline at end of file diff --git a/source/java/org/alfresco/web/forms/FormInstanceDataImpl.java b/source/java/org/alfresco/web/forms/FormInstanceDataImpl.java index 0ddc676fce..ac6be50063 100644 --- a/source/java/org/alfresco/web/forms/FormInstanceDataImpl.java +++ b/source/java/org/alfresco/web/forms/FormInstanceDataImpl.java @@ -114,8 +114,8 @@ public class FormInstanceDataImpl final PropertyValue pv = avmService.getNodeProperty(-1, this.getPath(), WCMAppModel.PROP_RENDITIONS); final Collection renditionPaths = (pv == null - ? Collections.EMPTY_LIST - : pv.getCollection(DataTypeDefinition.TEXT)); + ? Collections.EMPTY_LIST + : pv.getCollection(DataTypeDefinition.TEXT)); final String storeName = AVMConstants.getStoreName(this.getPath()); final List result = new ArrayList(renditionPaths.size()); for (Serializable path : renditionPaths) diff --git a/source/java/org/alfresco/web/forms/FreeMarkerRenderingEngine.java b/source/java/org/alfresco/web/forms/FreeMarkerRenderingEngine.java index 2eb37acb48..f6687d7de6 100644 --- a/source/java/org/alfresco/web/forms/FreeMarkerRenderingEngine.java +++ b/source/java/org/alfresco/web/forms/FreeMarkerRenderingEngine.java @@ -19,16 +19,15 @@ package org.alfresco.web.forms; import freemarker.ext.dom.NodeModel; import freemarker.template.*; import java.io.*; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import javax.xml.parsers.DocumentBuilder; import org.alfresco.model.ContentModel; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentService; 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.web.bean.wcm.AVMConstants; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -44,25 +43,16 @@ import org.xml.sax.SAXException; * @author Ariel Backenroth */ public class FreeMarkerRenderingEngine - extends AbstractRenderingEngine + implements RenderingEngine { private static final Log LOGGER = LogFactory.getLog(FreeMarkerRenderingEngine.class); - public FreeMarkerRenderingEngine() - { - super(); - } + public FreeMarkerRenderingEngine() { } - public String getName() - { - return "FreeMarker"; - } + public String getName() { return "FreeMarker"; } - public String getDefaultTemplateFileExtension() - { - return "ftl"; - } + public String getDefaultTemplateFileExtension() { return "ftl"; } /** * Renders the rendition using the configured freemarker template. This @@ -70,15 +60,13 @@ public class FreeMarkerRenderingEngine * a variable named alfresco at the root. the alfresco variable contains a hash of * all parameters and all extension functions. */ - public void render(final FormInstanceData formInstanceData, + public void render(final Map model, final RenderingEngineTemplate ret, - final Rendition rendition) + final OutputStream out) throws IOException, RenderingEngine.RenderingException, SAXException { - final Map parameters = - this.getStandardParameters(formInstanceData, rendition); final Configuration cfg = new Configuration(); cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); @@ -86,139 +74,12 @@ public class FreeMarkerRenderingEngine final Template t = new Template("freemarker_template", new InputStreamReader(ret.getInputStream()), cfg); + final TemplateHashModel rootModel = this.convertModel(model); - // wrap the xml instance in a model - final TemplateHashModel instanceDataModel = NodeModel.wrap(formInstanceData.getDocument()); - - // build models for each of the extension functions - final HashMap methodModels = - new HashMap(3, 1.0f); - - methodModels.put("parseXMLDocument", new TemplateMethodModel() - { - public Object exec(final List args) - throws TemplateModelException - { - try - { - final FormDataFunctions ef = FreeMarkerRenderingEngine.getFormDataFunctions(); - final String path = - AVMConstants.buildPath(parameters.get("parent_path"), - (String)args.get(0), - AVMConstants.PathRelation.WEBAPP_RELATIVE); - final Document d = ef.parseXMLDocument(path); - return d != null ? d.getDocumentElement() : null; - } - catch (Exception e) - { - throw new TemplateModelException(e); - } - } - }); - - methodModels.put("parseXMLDocuments", new TemplateMethodModel() - { - public Object exec(final List args) - throws TemplateModelException - { - try - { - final FormDataFunctions ef = FreeMarkerRenderingEngine.getFormDataFunctions(); - final String path = - AVMConstants.buildPath(parameters.get("parent_path"), - args.size() == 1 ? "" : (String)args.get(1), - AVMConstants.PathRelation.WEBAPP_RELATIVE); - final Map resultMap = ef.parseXMLDocuments((String)args.get(0), path); - LOGGER.debug("received " + resultMap.size() + " documents in " + path); - - // create a root document for rooting all the results. we do this - // so that each document root element has a common parent node - // and so that xpath axes work properly - final Document rootNodeDocument = XMLUtil.newDocument(); - final Element rootNodeDocumentEl = - rootNodeDocument.createElementNS(ALFRESCO_NS, - ALFRESCO_NS_PREFIX + ":file_list"); - rootNodeDocumentEl.setAttribute("xmlns:" + ALFRESCO_NS_PREFIX, ALFRESCO_NS); - rootNodeDocument.appendChild(rootNodeDocumentEl); - - final List result = new ArrayList(resultMap.size()); - for (Map.Entry e : resultMap.entrySet()) - { - final Element documentEl = e.getValue().getDocumentElement(); - documentEl.setAttribute("xmlns:" + ALFRESCO_NS_PREFIX, ALFRESCO_NS); - documentEl.setAttributeNS(ALFRESCO_NS, - ALFRESCO_NS_PREFIX + ":file_name", - e.getKey()); - final Node n = rootNodeDocument.importNode(documentEl, true); - rootNodeDocumentEl.appendChild(n); - result.add(NodeModel.wrap(n)); - } - return result; - } - catch (Exception e) - { - throw new TemplateModelException(e); - } - } - }); - - // for debugging - methodModels.put("_getAVMPath", new TemplateMethodModel() - { - public Object exec(final List args) - throws TemplateModelException - { - try - { - return AVMConstants.buildPath(parameters.get("parent_path"), - (String)args.get(0), - AVMConstants.PathRelation.WEBAPP_RELATIVE); - } - catch (Exception e) - { - throw new TemplateModelException(e); - } - } - }); - - // build a wrapper for the parameters. this also wraps the extension functions - // so they appear in the namespace alfresco. - final TemplateHashModel parameterModel = new SimpleHash(parameters) - { - - public TemplateModel get(final String key) - throws TemplateModelException - { - return (methodModels.containsKey(key) - ? methodModels.get(key) - : super.get(key)); - } - }; - - // build the root model. anything not in the falsey alfresco namespace will be - // retrieved from the xml file in order to make it behave as close as possible to - // the xsl environment - final TemplateHashModel rootModel = new TemplateHashModel() - { - public TemplateModel get(final String key) - throws TemplateModelException - { - return (ALFRESCO_NS_PREFIX.equals(key) - ? parameterModel - : instanceDataModel.get(key)); - } - - public boolean isEmpty() - { - return false; - } - }; - // process the form - final Writer writer = new OutputStreamWriter(rendition.getOutputStream()); try { - t.process(rootModel, writer); + t.process(rootModel, new OutputStreamWriter(out)); } catch (final TemplateException te) { @@ -227,8 +88,158 @@ public class FreeMarkerRenderingEngine } finally { - writer.flush(); - writer.close(); + out.flush(); + out.close(); + } + } + + private TemplateHashModel convertModel(final Map model) + { + final List rootModelObjects = new LinkedList(); + final SimpleHash result = new SimpleHash() + { + public TemplateModel get(final String key) + throws TemplateModelException + { + TemplateModel result = super.get(key); + if (result == null) + { + for (TemplateHashModel m : rootModelObjects) + { + result = m.get(key); + if (result != null) + { + break; + } + } + } + return result; + } + }; + for (final Map.Entry entry : model.entrySet()) + { + final QName qn = entry.getKey(); + if (qn.equals(RenderingEngine.ROOT_NAMESPACE)) + { + final TemplateModel m = this.convertValue(entry.getValue()); + if (m instanceof TemplateHashModel) + { + rootModelObjects.add((TemplateHashModel)m); + } + else + { + throw new IllegalArgumentException("root namespace values must be convertable to " + TemplateHashModel.class.getName() + + ". converted " + entry.getValue().getClass().getName() + + " to " + m.getClass().getName() + "."); + } + } + else + { + final String[] splitQName = QName.splitPrefixedQName(qn.toPrefixString()); + final String variableName = splitQName[1]; + + //insert + if (NamespaceService.DEFAULT_PREFIX.equals(splitQName[0])) + { + result.put(variableName, this.convertValue(entry.getValue())); + } + else + { + SimpleHash prefixModel = null; + final String prefix = splitQName[0]; + try + { + try + { + prefixModel = (SimpleHash)result.get(prefix); + } + catch (ClassCastException cce) + { + throw new ClassCastException("expected value of " + prefix + + " to be a " + SimpleHash.class.getName() + + ". found a " + result.get(prefix).getClass().getName()); + } + } + catch (TemplateModelException tme) + { + } + if (prefixModel == null) + { + prefixModel = new SimpleHash(); + result.put(prefix, prefixModel); + } + + prefixModel.put(variableName, + this.convertValue(entry.getValue())); + } + } + } + return result; + } + + private TemplateModel convertValue(final Object value) + { + LOGGER.debug("converting value " + value); + if (value == null) + { + return null; + } + else if (value.getClass().isArray()) + { + final Object[] array = (Object[])value; + LOGGER.debug("converting array of " + array.getClass().getComponentType() + + " size " + array.length); + final SimpleSequence result = new SimpleSequence(); + for (int i = 0; i < array.length; i++) + { + result.add(this.convertValue(array[i])); + } + return result; + } + else if (value instanceof String) + { + return new SimpleScalar((String)value); + } + else if (value instanceof Number) + { + return new SimpleNumber((Number)value); + } + else if (value instanceof Boolean) + { + return (Boolean)value ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE; + } + else if (value instanceof Document) + { + return NodeModel.wrap((Document)value); + } + else if (value instanceof Node) + { + return NodeModel.wrap((Node)value); + } + else if (value instanceof RenderingEngine.TemplateProcessorMethod) + { + return new TemplateMethodModel() + { + public Object exec(final List args) + throws TemplateModelException + { + try + { + LOGGER.debug("invoking template processor method " + value + + " with " + args.size() + " arguments"); + final Object result = ((TemplateProcessorMethod)value).exec(args.toArray(new Object[args.size()])); + return FreeMarkerRenderingEngine.this.convertValue(result); + } + catch (Exception e) + { + throw new TemplateModelException(e); + } + } + }; + } + else + { + throw new IllegalArgumentException("unable to convert value " + value.getClass().getName()); } } } diff --git a/source/java/org/alfresco/web/forms/RenderingEngine.java b/source/java/org/alfresco/web/forms/RenderingEngine.java index dccc8329a0..3638f7451a 100644 --- a/source/java/org/alfresco/web/forms/RenderingEngine.java +++ b/source/java/org/alfresco/web/forms/RenderingEngine.java @@ -17,6 +17,7 @@ package org.alfresco.web.forms; import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.QName; import java.io.IOException; import java.io.OutputStream; import java.io.Serializable; @@ -56,6 +57,18 @@ public interface RenderingEngine ///////////////////////////////////////////////////////////////////////////// + public interface TemplateProcessorMethod + extends Serializable + { + public Object exec(final Object[] arguments) + throws Exception; + } + + ///////////////////////////////////////////////////////////////////////////// + + public final static QName ROOT_NAMESPACE = + QName.createQName(null, "root_namespace"); + /** * Returns the rendering engines name. * @@ -81,8 +94,8 @@ public interface RenderingEngine * @param form the form that collected the xml content. * @param rendition the rendition to serialize to. */ - public void render(final FormInstanceData formInstanceData, + public void render(final Map model, final RenderingEngineTemplate ret, - final Rendition rendition) + final OutputStream out) throws IOException, RenderingException, SAXException; } diff --git a/source/java/org/alfresco/web/forms/RenderingEngineTemplate.java b/source/java/org/alfresco/web/forms/RenderingEngineTemplate.java index 3aa26d2fd9..0a8351108e 100644 --- a/source/java/org/alfresco/web/forms/RenderingEngineTemplate.java +++ b/source/java/org/alfresco/web/forms/RenderingEngineTemplate.java @@ -78,9 +78,26 @@ public interface RenderingEngineTemplate /** * Produces a rendition of the provided formInstanceData. + * + * @param formInstanceData the form instance data for which to produce + * the rendition. */ public Rendition render(final FormInstanceData formInstanceData) throws IOException, SAXException, RenderingEngine.RenderingException; + + /** + * Produces a rendition of the provided formInstanceData to an existing + * rendition. + * + * @param formInstanceData the form instance data for which to produce + * the rendition. + * @param rendition the rendition to rerender + */ + public void render(final FormInstanceData formInstanceData, + final Rendition rendition) + throws IOException, + SAXException, + RenderingEngine.RenderingException; } diff --git a/source/java/org/alfresco/web/forms/RenderingEngineTemplateImpl.java b/source/java/org/alfresco/web/forms/RenderingEngineTemplateImpl.java index 25eb589887..627df2917d 100644 --- a/source/java/org/alfresco/web/forms/RenderingEngineTemplateImpl.java +++ b/source/java/org/alfresco/web/forms/RenderingEngineTemplateImpl.java @@ -30,15 +30,19 @@ import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.avm.AVMService; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.repository.*; -import org.alfresco.service.namespace.QName; +import org.alfresco.service.namespace.*; +import org.alfresco.service.cmr.remote.AVMRemote; import org.alfresco.web.app.Application; import org.alfresco.web.bean.repository.Repository; import org.alfresco.web.bean.wcm.AVMConstants; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.w3c.dom.Document; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.jsf.FacesContextUtils; +import org.w3c.dom.*; import org.xml.sax.SAXException; + /** * Implementation of a rendering engine template */ @@ -101,11 +105,6 @@ public class RenderingEngineTemplateImpl return this.renditionPropertiesNodeRef; } - /** - * Provides an input stream to the rendering engine template. - * - * @return the input stream to the rendering engine template. - */ public InputStream getInputStream() throws IOException { @@ -131,7 +130,8 @@ public class RenderingEngineTemplateImpl } /** - * Returns the output path to use for renditions. + * Generates an output path for the rendition by compiling the output path pattern + * as a freemarker template. * * @return the output path to use for renditions. */ @@ -183,11 +183,6 @@ public class RenderingEngineTemplateImpl return result; } - /** - * Returns the mime type to use for generated assets. - * - * @return the mime type to use for generated assets. - */ public String getMimetypeForRendition() { final NodeService nodeService = this.getServiceRegistry().getNodeService(); @@ -195,9 +190,6 @@ public class RenderingEngineTemplateImpl WCMAppModel.PROP_MIMETYPE_FOR_RENDITION); } - /** - * Produces a rendition of the provided formInstanceData. - */ public Rendition render(final FormInstanceData formInstanceData) throws IOException, SAXException, @@ -213,14 +205,44 @@ public class RenderingEngineTemplateImpl AVMNodeConverter.SplitBase(renditionAvmPath)[1]); if (LOGGER.isDebugEnabled()) LOGGER.debug("Created file node for file: " + renditionAvmPath); + avmService.addAspect(renditionAvmPath, WCMAppModel.ASPECT_FORM_INSTANCE_DATA); + avmService.addAspect(renditionAvmPath, ContentModel.ASPECT_TITLED); + avmService.addAspect(renditionAvmPath, WCMAppModel.ASPECT_RENDITION); + + final PropertyValue pv = + avmService.getNodeProperty(-1, formInstanceData.getPath(), WCMAppModel.PROP_RENDITIONS); + final Collection renditions = (pv == null + ? new HashSet() + : pv.getCollection(DataTypeDefinition.TEXT)); + renditions.add(AVMConstants.getStoreRelativePath(renditionAvmPath)); + avmService.setNodeProperty(formInstanceData.getPath(), + WCMAppModel.PROP_RENDITIONS, + new PropertyValue(DataTypeDefinition.TEXT, + (Serializable)renditions)); } final Rendition result = new RenditionImpl(AVMNodeConverter.ToNodeRef(-1, renditionAvmPath)); - this.getRenderingEngine().render(formInstanceData, this, result); + this.render(formInstanceData, result); + return result; + } - avmService.addAspect(renditionAvmPath, WCMAppModel.ASPECT_FORM_INSTANCE_DATA); - avmService.addAspect(renditionAvmPath, ContentModel.ASPECT_TITLED); - avmService.addAspect(renditionAvmPath, WCMAppModel.ASPECT_RENDITION); + public void render(final FormInstanceData formInstanceData, + final Rendition rendition) + throws IOException, + SAXException, + RenderingEngine.RenderingException + { + final OutputStream out = rendition.getOutputStream(); + try + { + this.getRenderingEngine().render(this.buildModel(formInstanceData, rendition), + this, + out); + } + finally + { + out.close(); + } final Map props = new HashMap(5, 1.0f); props.put(WCMAppModel.PROP_PARENT_FORM_NAME, @@ -228,13 +250,13 @@ public class RenderingEngineTemplateImpl formInstanceData.getForm().getName())); props.put(ContentModel.PROP_TITLE, new PropertyValue(DataTypeDefinition.TEXT, - AVMNodeConverter.SplitBase(renditionAvmPath)[1])); + AVMNodeConverter.SplitBase(rendition.getPath())[1])); final ResourceBundle bundle = Application.getBundle(FacesContext.getCurrentInstance()); props.put(ContentModel.PROP_DESCRIPTION, new PropertyValue(DataTypeDefinition.TEXT, MessageFormat.format(bundle.getString("default_rendition_description"), this.getTitle(), - AVMConstants.getSandboxRelativePath(renditionAvmPath)))); + AVMConstants.getSandboxRelativePath(rendition.getPath())))); props.put(WCMAppModel.PROP_PARENT_RENDERING_ENGINE_TEMPLATE, new PropertyValue(DataTypeDefinition.NODE_REF, this.nodeRef)); @@ -246,19 +268,187 @@ public class RenderingEngineTemplateImpl new PropertyValue(DataTypeDefinition.TEXT, AVMConstants.getStoreRelativePath(formInstanceData.getPath()))); - avmService.setNodeProperties(renditionAvmPath, props); - - final PropertyValue pv = - avmService.getNodeProperty(-1, formInstanceData.getPath(), WCMAppModel.PROP_RENDITIONS); - Collection renditions = (pv == null - ? new LinkedList() - : pv.getCollection(DataTypeDefinition.TEXT)); - renditions.add(AVMConstants.getStoreRelativePath(renditionAvmPath)); - avmService.setNodeProperty(formInstanceData.getPath(), - WCMAppModel.PROP_RENDITIONS, - new PropertyValue(DataTypeDefinition.TEXT, - (Serializable)renditions)); - return result; + final AVMService avmService = this.getServiceRegistry().getAVMService(); + avmService.setNodeProperties(rendition.getPath(), props); + } + + /** + * Builds the model to pass to the rendering engine. + */ + protected Map buildModel(final FormInstanceData formInstanceData, + final Rendition rendition) + throws IOException, + SAXException + { + final DynamicNamespacePrefixResolver namespacePrefixResolver = + new DynamicNamespacePrefixResolver(); + namespacePrefixResolver.registerNamespace(NamespaceService.ALFRESCO_PREFIX, + NamespaceService.ALFRESCO_URI); + + final String formInstanceDataAvmPath = formInstanceData.getPath(); + final String renditionAvmPath = rendition.getPath(); + final String parentPath = AVMNodeConverter.SplitBase(formInstanceDataAvmPath)[0]; + final String sandboxUrl = AVMConstants.buildStoreUrl(formInstanceDataAvmPath); + final HashMap model = new HashMap(); + // add simple scalar parameters + model.put(QName.createQName(NamespaceService.ALFRESCO_PREFIX, + "avm_sandbox_url", + namespacePrefixResolver), + sandboxUrl); + model.put(XSLTRenderingEngine.PROP_URI_RESOLVER_BASE_URI, + sandboxUrl); + model.put(QName.createQName(NamespaceService.ALFRESCO_PREFIX, + "form_instance_data_file_name", + namespacePrefixResolver), + AVMNodeConverter.SplitBase(formInstanceDataAvmPath)[1]); + model.put(QName.createQName(NamespaceService.ALFRESCO_PREFIX, + "rendition_file_name", + namespacePrefixResolver), + AVMNodeConverter.SplitBase(renditionAvmPath)[1]); + model.put(QName.createQName(NamespaceService.ALFRESCO_PREFIX, + "parent_path", + namespacePrefixResolver), + parentPath); + final FacesContext fc = FacesContext.getCurrentInstance(); + model.put(QName.createQName(NamespaceService.ALFRESCO_PREFIX, + "request_context_path", + namespacePrefixResolver), + fc.getExternalContext().getRequestContextPath()); + + // add methods + final FormDataFunctions fdf = this.getFormDataFunctions(); + model.put(QName.createQName(NamespaceService.ALFRESCO_PREFIX, + "parseXMLDocument", + namespacePrefixResolver), + new RenderingEngine.TemplateProcessorMethod() + { + public Object exec(final Object[] arguments) + throws IOException, + SAXException + { + if (arguments.length != 1) + { + throw new IllegalArgumentException("expected 1 argument to parseXMLDocument. got " + + arguments.length); + + } + if (! (arguments[0] instanceof String)) + { + throw new ClassCastException("expected arguments[0] to be a " + String.class.getName() + + ". got a " + arguments[0].getClass().getName() + "."); + } + String path = (String)arguments[0]; + path = AVMConstants.buildPath(parentPath, + path, + AVMConstants.PathRelation.WEBAPP_RELATIVE); + LOGGER.debug("tpm_parseXMLDocument('" + path + + "'), parentPath = " + parentPath); + final Document d = fdf.parseXMLDocument(path); + return d != null ? d.getDocumentElement() : null; + } + }); + model.put(QName.createQName(NamespaceService.ALFRESCO_PREFIX, + "parseXMLDocuments", + namespacePrefixResolver), + new RenderingEngine.TemplateProcessorMethod() + { + public Object exec(final Object[] arguments) + throws IOException, + SAXException + { + if (arguments.length > 1) + { + throw new IllegalArgumentException("expected zero or one arguments to parseXMLDocuments. got " + + arguments.length); + } + if (! (arguments[0] instanceof String)) + { + throw new ClassCastException("expected arguments[0] to be a " + String.class.getName() + + ". got a " + arguments[0].getClass().getName() + "."); + } + + if (arguments.length == 2 && ! (arguments[1] instanceof String)) + { + throw new ClassCastException("expected arguments[1] to be a " + String.class.getName() + + ". got a " + arguments[1].getClass().getName() + "."); + } + + String path = arguments.length == 2 ? (String)arguments[1] : ""; + path = AVMConstants.buildPath(parentPath, + path, + AVMConstants.PathRelation.WEBAPP_RELATIVE); + final String formName = (String)arguments[0]; + LOGGER.debug("tpm_parseXMLDocuments('" + formName + "','" + path + + "'), parentPath = " + parentPath); + final Map resultMap = fdf.parseXMLDocuments(formName, path); + LOGGER.debug("received " + resultMap.size() + + " documents in " + path + + " with form name " + formName); + + // create a root document for rooting all the results. we do this + // so that each document root element has a common parent node + // and so that xpath axes work properly + final Document rootNodeDocument = XMLUtil.newDocument(); + final Element rootNodeDocumentEl = + rootNodeDocument.createElementNS(NamespaceService.ALFRESCO_URI, + NamespaceService.ALFRESCO_PREFIX + ":file_list"); + rootNodeDocumentEl.setAttribute("xmlns:" + NamespaceService.ALFRESCO_PREFIX, + NamespaceService.ALFRESCO_URI); + rootNodeDocument.appendChild(rootNodeDocumentEl); + + final List result = new ArrayList(resultMap.size()); + for (Map.Entry e : resultMap.entrySet()) + { + final Element documentEl = e.getValue().getDocumentElement(); + documentEl.setAttribute("xmlns:" + NamespaceService.ALFRESCO_PREFIX, + NamespaceService.ALFRESCO_URI); + documentEl.setAttributeNS(NamespaceService.ALFRESCO_URI, + NamespaceService.ALFRESCO_PREFIX + ":file_name", + e.getKey()); + final Node n = rootNodeDocument.importNode(documentEl, true); + rootNodeDocumentEl.appendChild(n); + result.add(n); + } + return result.toArray(new Node[result.size()]); + } + }); + model.put(QName.createQName(NamespaceService.ALFRESCO_PREFIX, + "_getAVMPath", + namespacePrefixResolver), + new RenderingEngine.TemplateProcessorMethod() + { + public Object exec(final Object[] arguments) + { + if (arguments.length != 1) + { + throw new IllegalArgumentException("expected one argument to _getAVMPath. got " + + arguments.length); + } + if (! (arguments[0] instanceof String)) + { + throw new ClassCastException("expected arguments[0] to be a " + String.class.getName() + + ". got a " + arguments[0].getClass().getName() + "."); + } + + final String path = (String)arguments[0]; + LOGGER.debug("tpm_getAVMPAth('" + path + "'), parentPath = " + parentPath); + return AVMConstants.buildPath(parentPath, + path, + AVMConstants.PathRelation.WEBAPP_RELATIVE); + } + }); + + // add the xml document + model.put(RenderingEngine.ROOT_NAMESPACE, formInstanceData.getDocument()); + return model; + } + + protected static FormDataFunctions getFormDataFunctions() + { + final FacesContext fc = FacesContext.getCurrentInstance(); + final WebApplicationContext wac = + FacesContextUtils.getRequiredWebApplicationContext(fc); + return new FormDataFunctions((AVMRemote)wac.getBean("avmRemote")); } private ServiceRegistry getServiceRegistry() diff --git a/source/java/org/alfresco/web/forms/RenditionImpl.java b/source/java/org/alfresco/web/forms/RenditionImpl.java index aafe4c4208..a0ba020bab 100644 --- a/source/java/org/alfresco/web/forms/RenditionImpl.java +++ b/source/java/org/alfresco/web/forms/RenditionImpl.java @@ -161,14 +161,13 @@ public class RenditionImpl this.regenerate(this.getPrimaryFormInstanceData()); } + @Deprecated public void regenerate(final FormInstanceData formInstanceData) throws IOException, RenderingEngine.RenderingException, SAXException { - final RenderingEngineTemplate ret = this.getRenderingEngineTemplate(); - final RenderingEngine engine = ret.getRenderingEngine(); - engine.render(formInstanceData, ret, this); + this.getRenderingEngineTemplate().render(formInstanceData, this); } private ServiceRegistry getServiceRegistry() diff --git a/source/java/org/alfresco/web/forms/XMLUtil.java b/source/java/org/alfresco/web/forms/XMLUtil.java index 4d15a45d03..71f326c0cf 100644 --- a/source/java/org/alfresco/web/forms/XMLUtil.java +++ b/source/java/org/alfresco/web/forms/XMLUtil.java @@ -43,6 +43,7 @@ import org.xml.sax.SAXException; */ public class XMLUtil { + private static final Log LOGGER = LogFactory.getLog(XMLUtil.class); private static DocumentBuilder documentBuilder; diff --git a/source/java/org/alfresco/web/forms/XSLFORenderingEngine.java b/source/java/org/alfresco/web/forms/XSLFORenderingEngine.java index cd0677e0a5..7d0ec6e410 100644 --- a/source/java/org/alfresco/web/forms/XSLFORenderingEngine.java +++ b/source/java/org/alfresco/web/forms/XSLFORenderingEngine.java @@ -22,6 +22,7 @@ import javax.xml.transform.Result; import javax.xml.transform.Source; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.sax.SAXResult; +import org.alfresco.service.namespace.QName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.fop.apps.FOPException; @@ -86,9 +87,10 @@ public class XSLFORenderingEngine return "fo"; } - public void render(final FormInstanceData formInstanceData, + @Override + public void render(final Map model, final RenderingEngineTemplate ret, - final Rendition rendition) + final OutputStream out) throws IOException, RenderingEngine.RenderingException, SAXException @@ -100,16 +102,14 @@ public class XSLFORenderingEngine throw new RenderingEngine.RenderingException("mimetype " + ret.getMimetypeForRendition() + " is not supported by " + this.getName()); } - final OutputStream out = rendition.getOutputStream(); try { final FopFactory fopFactory = FopFactory.newInstance(); final FOUserAgent foUserAgent = fopFactory.newFOUserAgent(); final Fop fop = fopFactory.newFop(mimetype, foUserAgent, out); // Resulting SAX events (the generated FO) must be piped through to FOP - super.render(new DOMSource(formInstanceData.getDocument()), + super.render(model, ret, - this.getStandardParameters(formInstanceData, rendition), new SAXResult(fop.getDefaultHandler())); } diff --git a/source/java/org/alfresco/web/forms/XSLTRenderingEngine.java b/source/java/org/alfresco/web/forms/XSLTRenderingEngine.java index a1dee73dbb..1a5693adc1 100644 --- a/source/java/org/alfresco/web/forms/XSLTRenderingEngine.java +++ b/source/java/org/alfresco/web/forms/XSLTRenderingEngine.java @@ -35,13 +35,17 @@ import javax.xml.transform.stream.StreamSource; import org.alfresco.service.cmr.repository.ContentService; 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.web.bean.wcm.AVMConstants; import org.alfresco.web.forms.XMLUtil; 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.utils.QName; +import org.apache.xml.dtm.ref.DTMNodeProxy; +import org.apache.xml.utils.Constants; +//import org.apache.xml.utils.QName; import org.w3c.dom.*; import org.w3c.dom.traversal.NodeFilter; import org.w3c.dom.traversal.NodeIterator; @@ -55,187 +59,176 @@ import org.apache.bsf.BSFManager; * @author Ariel Backenroth */ public class XSLTRenderingEngine - extends AbstractRenderingEngine + implements RenderingEngine { - private static final Log LOGGER = LogFactory.getLog(XSLTRenderingEngine.class); + ///////////////////////////////////////////////////////////////////////////// - public XSLTRenderingEngine() + public static class ProcessorMethodInvoker { - super(); - } + private final static HashMap PROCESSOR_METHODS = + new HashMap(); + + public ProcessorMethodInvoker() { } - public String getName() - { - return "XSLT"; - } - - public String getDefaultTemplateFileExtension() - { - return "xsl"; - } - - protected static String toAVMPath(final ExpressionContext ec, String path) - throws TransformerException - { - final XObject o = ec.getVariableOrParam(new QName(ALFRESCO_NS, ALFRESCO_NS_PREFIX, "parent_path")); - return o == null ? null : AVMConstants.buildPath(o.toString(), - path, - AVMConstants.PathRelation.WEBAPP_RELATIVE); - } - - /** - * Adapter function used by the xsl tempalte to retrieve an xml asset at the given - * path. - * - * @return the document element for the xml asset at the given path. - */ - public static Node parseXMLDocument(final ExpressionContext ec, final String path) - throws TransformerException, - IOException, - SAXException - { - final FormDataFunctions ef = XSLTRenderingEngine.getFormDataFunctions(); - final Document d = ef.parseXMLDocument(XSLTRenderingEngine.toAVMPath(ec, path)); - return d != null ? d.getDocumentElement() : null; - } - - /** - * Adapter function used by the xsl tempalte to retrieve a xml assets in the - * current directory. - */ - public static NodeIterator parseXMLDocuments(final ExpressionContext ec, - final String formName) - throws TransformerException, - IOException, - SAXException - { - return XSLTRenderingEngine.parseXMLDocuments(ec, formName, ""); - } - - /** - * Adapter function used by the xsl tempalte to retrieve a xml assets at - * the given path. - * - * @return an iterator of the document elements for each of the xml - * assets at the given path. In order to enable xpath expressions to - * properly access siblings, each root element is rooted at a node named - * file-list in the alfresco namespace. - */ - public static NodeIterator parseXMLDocuments(final ExpressionContext ec, - final String formName, - String path) - throws TransformerException, - IOException, - SAXException - { - final FormDataFunctions ef = XSLTRenderingEngine.getFormDataFunctions(); - path = XSLTRenderingEngine.toAVMPath(ec, path); - final Map resultMap = ef.parseXMLDocuments(formName, path); - if (LOGGER.isDebugEnabled()) - LOGGER.debug("received " + resultMap.size() + " documents in " + path); - - // create a root document for rooting all the results. we do this - // so that each document root element has a common parent node - // and so that xpath axes work properly - final Document rootNodeDocument = XMLUtil.newDocument(); - final Element rootNodeDocumentEl = - rootNodeDocument.createElementNS(ALFRESCO_NS, - ALFRESCO_NS_PREFIX + ":file_list"); - rootNodeDocumentEl.setAttribute("xmlns:" + ALFRESCO_NS_PREFIX, ALFRESCO_NS); - rootNodeDocument.appendChild(rootNodeDocumentEl); - - final List documents = new ArrayList(resultMap.size()); - for (Map.Entry mapEntry : resultMap.entrySet()) + private Object[] convertArguments(final Object[] arguments) { - final Element documentEl = mapEntry.getValue().getDocumentElement(); - documentEl.setAttributeNS(ALFRESCO_NS, - ALFRESCO_NS_PREFIX + ":file_name", - mapEntry.getKey()); - final Node n = rootNodeDocument.importNode(documentEl, true); - documents.add(n); - rootNodeDocumentEl.appendChild(n); + final List result = new LinkedList(); + for (int i = 0; i < arguments.length; i++) + { + LOGGER.debug("args[" + i + "] = " + arguments[i] + + "(" + (arguments[i] != null + ? arguments[i].getClass().getName() + : "null") + ")"); + if (arguments[i] == null || + arguments[i] instanceof String || + arguments[i] instanceof Number) + { + result.add(arguments[i]); + } + else if (arguments[i] instanceof DTMNodeProxy) + { + result.add(((DTMNodeProxy)arguments[i]).getStringValue()); + } + else if (arguments[i] instanceof Node) + { + LOGGER.debug("node type is " + ((Node)arguments[i]).getNodeType() + + " content " + ((Node)arguments[i]).getTextContent()); + result.add(((Node)arguments[i]).getNodeValue()); + } + else if (arguments[i] instanceof NodeIterator) + { + Node n = ((NodeIterator)arguments[i]).nextNode(); + while (n != null) + { + LOGGER.debug("iterated to node " + n + " type " + n.getNodeType() + + " value " + n.getNodeValue() + + " tc " + n.getTextContent() + + " nn " + n.getNodeName() + + " sv " + ((org.apache.xml.dtm.ref.DTMNodeProxy)n).getStringValue()); + if (n instanceof DTMNodeProxy) + { + result.add(((DTMNodeProxy)n).getStringValue()); + } + else + { + result.add(n); + } + n = ((NodeIterator)arguments[i]).nextNode(); + } + } + else + { + throw new IllegalArgumentException("unable to convert argument " + arguments[i]); + } + } + + return result.toArray(new Object[result.size()]); } - return new NodeIterator() + public Object invokeMethod(final String id, Object[] arguments) + throws Exception { - private int index = 0; - private boolean detached = false; - - public void detach() - { - if (LOGGER.isDebugEnabled()) - LOGGER.debug("detaching NodeIterator"); - resultMap.clear(); - documents.clear(); - this.detached = true; - } - - public boolean getExpandEntityReferences() - { - return true; + if (!PROCESSOR_METHODS.containsKey(id)) + { + throw new NullPointerException("unable to find method " + id); } - public NodeFilter getFilter() - { - return new NodeFilter() + final TemplateProcessorMethod method = PROCESSOR_METHODS.get(id); + arguments = this.convertArguments(arguments); + LOGGER.debug("invoking " + id + " with " + arguments.length); + + Object result = method.exec(arguments); + LOGGER.debug(id + " returned a " + result); + if (result == null) + { + return null; + } + else if (result.getClass().isArray() && + Node.class.isAssignableFrom(result.getClass().getComponentType())) + { + LOGGER.debug("converting " + result + " to a node iterator"); + final Node[] array = (Node[])result; + return new NodeIterator() { - public short acceptNode(final Node n) + private int index = 0; + private boolean detached = false; + + public void detach() + { + if (LOGGER.isDebugEnabled()) + LOGGER.debug("detaching NodeIterator"); + this.detached = true; + } + + public boolean getExpandEntityReferences() { return true; } + public int getWhatToShow() { return NodeFilter.SHOW_ALL; } + + public Node getRoot() { - return NodeFilter.FILTER_ACCEPT; + return (array.length == 0 + ? null + : array[0].getOwnerDocument().getDocumentElement()); + } + + public NodeFilter getFilter() + { + return new NodeFilter() + { + public short acceptNode(final Node n) + { + return NodeFilter.FILTER_ACCEPT; + } + }; + } + + public Node nextNode() + throws DOMException + { + if (LOGGER.isDebugEnabled()) + LOGGER.debug("NodeIterator.nextNode(" + index + ")"); + if (this.detached) + throw new DOMException(DOMException.INVALID_STATE_ERR, null); + return index == array.length ? null : array[index++]; + } + + public Node previousNode() + throws DOMException + { + if (LOGGER.isDebugEnabled()) + LOGGER.debug("NodeIterator.previousNode(" + index + ")"); + if (this.detached) + throw new DOMException(DOMException.INVALID_STATE_ERR, null); + return index == -1 ? null : array[index--]; } }; } - - public Node getRoot() + else if (result instanceof String || + result instanceof Number || + result instanceof Node) { - return rootNodeDocumentEl; + LOGGER.debug("returning " + result + " as is"); + return result; } - - public int getWhatToShow() + else { - return NodeFilter.SHOW_ALL; + throw new IllegalArgumentException("unable to convert " + result.getClass().getName()); } - - public Node nextNode() - throws DOMException - { - if (LOGGER.isDebugEnabled()) - LOGGER.debug("NodeIterator.nextNode(" + index + ")"); - if (this.detached) - throw new DOMException(DOMException.INVALID_STATE_ERR, null); - if (index == documents.size()) - return null; - return documents.get(index++); - } - - public Node previousNode() - throws DOMException - { - if (LOGGER.isDebugEnabled()) - LOGGER.debug("NodeIterator.previousNode(" + index + ")"); - if (this.detached) - throw new DOMException(DOMException.INVALID_STATE_ERR, null); - if (index == -1) - return null; - return documents.get(index--); - } - }; + } } - /** - * for debugging only. provides the absolute avm path for the given - * path. - */ - public static String _getAVMPath(final ExpressionContext ec, - final String path) - throws TransformerException, - IOException, - SAXException - { - final FormDataFunctions ef = XSLTRenderingEngine.getFormDataFunctions(); - return XSLTRenderingEngine.toAVMPath(ec, path); - } + ///////////////////////////////////////////////////////////////////////////// + + private static final Log LOGGER = LogFactory.getLog(XSLTRenderingEngine.class); + + public static final QName PROP_URI_RESOLVER_BASE_URI = + QName.createQName(NamespaceService.ALFRESCO_URI, "xslt_resolver_base_uri"); + + public XSLTRenderingEngine() { } + + public String getName() { return "XSLT"; } + + public String getDefaultTemplateFileExtension() { return "xsl"; } /** * Adds a script element to the xsl which makes static methods on this @@ -243,22 +236,75 @@ public class XSLTRenderingEngine * * @param xslTemplate the xsl template */ - protected void addScript(final Document xslTemplate) + protected List addScripts(final Map model, + final Document xslTemplate) { + final Map>> methods = + new HashMap>>(); + for (final Map.Entry entry : model.entrySet()) + { + if (entry.getValue() instanceof TemplateProcessorMethod) + { + final String prefix = QName.splitPrefixedQName(entry.getKey().toPrefixString())[0]; + final QName qn = QName.createQName(entry.getKey().getNamespaceURI(), + prefix); + if (!methods.containsKey(qn)) + { + methods.put(qn, new LinkedList()); + } + methods.get(qn).add(entry); + } + } + final Element docEl = xslTemplate.getDocumentElement(); - final String XALAN_NS = "http://xml.apache.org/xalan"; + final String XALAN_NS = Constants.S_BUILTIN_EXTENSIONS_URL; final String XALAN_NS_PREFIX = "xalan"; docEl.setAttribute("xmlns:" + XALAN_NS_PREFIX, XALAN_NS); - docEl.setAttribute("xmlns:" + ALFRESCO_NS_PREFIX, ALFRESCO_NS); - - final Element compEl = xslTemplate.createElementNS(XALAN_NS, XALAN_NS_PREFIX + ":component"); - compEl.setAttribute("prefix", "alfresco"); - docEl.appendChild(compEl); - final Element scriptEl = xslTemplate.createElementNS(XALAN_NS, XALAN_NS_PREFIX + ":script"); - scriptEl.setAttribute("lang", "javaclass"); - scriptEl.setAttribute("src", XALAN_NS_PREFIX + "://" + this.getClass().getName()); - compEl.appendChild(scriptEl); + final List result = new LinkedList(); + for (QName ns : methods.keySet()) + { + final String prefix = ns.getLocalName(); + docEl.setAttribute("xmlns:" + prefix, ns.getNamespaceURI()); + + final Element compEl = xslTemplate.createElementNS(XALAN_NS, + XALAN_NS_PREFIX + ":component"); + compEl.setAttribute("prefix", prefix); + docEl.appendChild(compEl); + String functionNames = null; + final Element scriptEl = xslTemplate.createElementNS(XALAN_NS, + XALAN_NS_PREFIX + ":script"); + scriptEl.setAttribute("lang", "javascript"); + final StringBuilder js = + new StringBuilder("var _xsltp_invoke = java.lang.Class.forName('" + ProcessorMethodInvoker.class.getName() + + "').newInstance();\n" + + "function _xsltp_to_java_array(js_array) {\n" + + "var java_array = java.lang.reflect.Array.newInstance(java.lang.Object, js_array.length);\n" + + "for (var i = 0; i < js_array.length; i++) { java_array[i] = js_array[i]; }\n" + + "return java_array; }\n"); + for (final Map.Entry entry : methods.get(ns)) + { + if (functionNames == null) + { + functionNames = entry.getKey().getLocalName(); + } + else + { + functionNames += " " + entry.getKey().getLocalName(); + } + final String id = entry.getKey().getLocalName() + entry.getValue().hashCode(); + js.append("function " + entry.getKey().getLocalName() + + "() { return _xsltp_invoke.invokeMethod('" + id + + "', _xsltp_to_java_array(arguments)); }\n"); + ProcessorMethodInvoker.PROCESSOR_METHODS.put(id, (TemplateProcessorMethod)entry.getValue()); + result.add(id); + } + LOGGER.debug("generated JavaScript bindings:\n" + js); + scriptEl.appendChild(xslTemplate.createTextNode(js.toString())); + compEl.setAttribute("functions", functionNames); + compEl.appendChild(scriptEl); + } + return result; } /** @@ -268,47 +314,58 @@ public class XSLTRenderingEngine * @param parameters the variables to place within the xsl template * @param xslTemplate the xsl template */ - protected void addParameters(final Map parameters, - final Document xslTemplate) + protected void addParameters(final Map model, + final Document xslTemplate) { final Element docEl = xslTemplate.getDocumentElement(); final String XSL_NS = docEl.getNamespaceURI(); final String XSL_NS_PREFIX = docEl.getPrefix(); - for (Map.Entry e : parameters.entrySet()) + for (Map.Entry e : model.entrySet()) { + if (RenderingEngine.ROOT_NAMESPACE.equals(e.getKey())) + { + continue; + } final Element el = xslTemplate.createElementNS(XSL_NS, XSL_NS_PREFIX + ":variable"); - el.setAttribute("name", ALFRESCO_NS_PREFIX + ':' + e.getKey()); - el.appendChild(xslTemplate.createTextNode(e.getValue())); - docEl.insertBefore(el, docEl.getFirstChild()); + el.setAttribute("name", e.getKey().toPrefixString()); + final Object o = e.getValue(); + if (o instanceof String || o instanceof Number || o instanceof Boolean) + { + el.appendChild(xslTemplate.createTextNode(o.toString())); + docEl.insertBefore(el, docEl.getFirstChild()); + } } } + + protected Source getXMLSource(final Map model) + { + if (!model.containsKey(RenderingEngine.ROOT_NAMESPACE)) + { + return null; + } + final Object o = model.get(RenderingEngine.ROOT_NAMESPACE); + if (!(o instanceof Document)) + { + throw new IllegalArgumentException("expected root namespace object to be a " + Document.class.getName() + + ". found a " + o.getClass().getName()); + } + return new DOMSource((Document)o); + } - public void render(final FormInstanceData formInstanceData, + public void render(final Map model, final RenderingEngineTemplate ret, - final Rendition rendition) + final OutputStream out) throws IOException, RenderingEngine.RenderingException, SAXException { - final OutputStream out = rendition.getOutputStream(); - try - { - this.render(new DOMSource(formInstanceData.getDocument()), - ret, - this.getStandardParameters(formInstanceData, rendition), - new StreamResult(out)); - } - finally - { - out.close(); - } + this.render(model, ret, new StreamResult(out)); } - protected void render(final Source formInstanceDataSource, - final RenderingEngineTemplate ret, - final Map parameters, - final Result result) + public void render(final Map model, + final RenderingEngineTemplate ret, + final Result result) throws IOException, RenderingEngine.RenderingException, SAXException @@ -324,8 +381,10 @@ public class XSLTRenderingEngine { throw new RenderingEngine.RenderingException(sax); } - this.addScript(xslTemplate); - this.addParameters(parameters, xslTemplate); + this.addScripts(model, xslTemplate); + this.addParameters(model, xslTemplate); + + Source xmlSource = this.getXMLSource(model); Transformer t = null; try @@ -344,21 +403,25 @@ public class XSLTRenderingEngine // web application t.setURIResolver(new URIResolver() { - public Source resolve(final String href, final String base) + public Source resolve(final String href, String base) throws TransformerException { - // XXXarielb - dirty - fix this - final String sandBoxUrl = (String)parameters.get("avm_sandbox_url"); - + LOGGER.debug("request to resolve href " + href + + " using base " + base); + if (model.containsKey(PROP_URI_RESOLVER_BASE_URI)) + { + base = (String)model.get(PROP_URI_RESOLVER_BASE_URI); + LOGGER.debug("overriding base with " + base); + } + URI uri = null; try { - uri = new URI(sandBoxUrl + href); + uri = new URI(base + href); } catch (URISyntaxException e) { - throw new TransformerException("unable to create uri " + - sandBoxUrl + href, + throw new TransformerException("unable to create uri " + base + href, e); } try @@ -379,11 +442,16 @@ public class XSLTRenderingEngine try { - t.transform(formInstanceDataSource, result); + t.transform(xmlSource, result); } - catch (TransformerException e) + catch (TransformerException te) { - LOGGER.error(e.getMessageAndLocation()); + LOGGER.error(te.getMessageAndLocation()); + throw new RenderingEngine.RenderingException(te); + } + catch (Exception e) + { + LOGGER.error("unexpected error " + e); throw new RenderingEngine.RenderingException(e); } } diff --git a/source/java/org/alfresco/web/forms/xforms/SchemaFormBuilder.java b/source/java/org/alfresco/web/forms/xforms/SchemaFormBuilder.java index cf31507371..1698ce73b9 100644 --- a/source/java/org/alfresco/web/forms/xforms/SchemaFormBuilder.java +++ b/source/java/org/alfresco/web/forms/xforms/SchemaFormBuilder.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.io.StringWriter; import java.util.*; import javax.xml.transform.*; +import org.alfresco.service.namespace.NamespaceService; import org.alfresco.web.forms.XMLUtil; import org.apache.commons.jxpath.JXPathContext; import org.apache.commons.jxpath.Pointer; @@ -70,16 +71,7 @@ public class SchemaFormBuilder ///////////////////////////////////////////////////////////////////////////// - public final static Log LOGGER = - LogFactory.getLog(SchemaFormBuilder.class); - - - /** Alfresco namespace declaration. */ - private static final String ALFRESCO_NS = - "http://www.alfresco.org/alfresco"; - - /** Alfresco prefix */ - private static final String ALFRESCO_PREFIX = "alfresco"; + private final static Log LOGGER = LogFactory.getLog(SchemaFormBuilder.class); private static final String PROPERTY_PREFIX = "http://www.chiba.org/properties/schemaFormBuilder/"; @@ -433,10 +425,12 @@ public class SchemaFormBuilder { final JXPathContext prototypeContext = JXPathContext.newContext(prototypeDocumentElement); - prototypeContext.registerNamespace("alfresco", SchemaFormBuilder.ALFRESCO_NS); + prototypeContext.registerNamespace(NamespaceService.ALFRESCO_PREFIX, + NamespaceService.ALFRESCO_URI); final JXPathContext instanceContext = JXPathContext.newContext(instanceDocumentElement); - instanceContext.registerNamespace("alfresco", SchemaFormBuilder.ALFRESCO_NS); + instanceContext.registerNamespace(NamespaceService.ALFRESCO_PREFIX, + NamespaceService.ALFRESCO_URI); class PrototypeInsertionData { @@ -457,7 +451,7 @@ public class SchemaFormBuilder new LinkedList(); final Iterator it = - prototypeContext.iteratePointers("//*[@" + SchemaFormBuilder.ALFRESCO_PREFIX + + prototypeContext.iteratePointers("//*[@" + NamespaceService.ALFRESCO_PREFIX + ":prototype='true']"); while (it.hasNext()) { @@ -528,11 +522,11 @@ public class SchemaFormBuilder { for (Element e : l) { - if (e.hasAttributeNS(SchemaFormBuilder.ALFRESCO_NS, "prototype")) + if (e.hasAttributeNS(NamespaceService.ALFRESCO_URI, "prototype")) { - assert "true".equals(e.getAttributeNS(SchemaFormBuilder.ALFRESCO_NS, + assert "true".equals(e.getAttributeNS(NamespaceService.ALFRESCO_URI, "prototype")); - e.removeAttributeNS(SchemaFormBuilder.ALFRESCO_NS, "prototype"); + e.removeAttributeNS(NamespaceService.ALFRESCO_URI, "prototype"); if (l.getLast().equals(e)) { @@ -1687,8 +1681,8 @@ public class SchemaFormBuilder final Element e = (Element)newDefaultInstanceElement.cloneNode(true); if (i == elementOccurs.minimum) { - e.setAttributeNS(SchemaFormBuilder.ALFRESCO_NS, - SchemaFormBuilder.ALFRESCO_PREFIX + ":prototype", + e.setAttributeNS(NamespaceService.ALFRESCO_URI, + NamespaceService.ALFRESCO_PREFIX + ":prototype", "true"); } defaultInstanceElement.appendChild(e); @@ -1990,7 +1984,7 @@ public class SchemaFormBuilder formControl.appendChild(alertElement); this.setXFormsId(alertElement); - String alert = SchemaFormBuilder.extractPropertyFromAnnotation(ALFRESCO_NS, + String alert = SchemaFormBuilder.extractPropertyFromAnnotation(NamespaceService.ALFRESCO_URI, "alert", this.getAnnotation(owner), resourceBundle); @@ -2082,8 +2076,8 @@ public class SchemaFormBuilder NamespaceConstants.XMLSCHEMA_INSTANCE_PREFIX, NamespaceConstants.XMLSCHEMA_INSTANCE_NS); this.addNamespace(envelopeElement, - SchemaFormBuilder.ALFRESCO_PREFIX, - SchemaFormBuilder.ALFRESCO_NS); + NamespaceService.ALFRESCO_PREFIX, + NamespaceService.ALFRESCO_URI); //base if (this.base != null && this.base.length() != 0) @@ -2150,7 +2144,7 @@ public class SchemaFormBuilder final XSAnnotation annotation, final ResourceBundle resourceBundle) { - final String s = SchemaFormBuilder.extractPropertyFromAnnotation(ALFRESCO_NS, + final String s = SchemaFormBuilder.extractPropertyFromAnnotation(NamespaceService.ALFRESCO_URI, "label", annotation, resourceBundle); @@ -2540,7 +2534,7 @@ public class SchemaFormBuilder final XSAnnotation annotation = this.getAnnotation(node); if (annotation == null) return null; - final String s = this.extractPropertyFromAnnotation(ALFRESCO_NS, + final String s = this.extractPropertyFromAnnotation(NamespaceService.ALFRESCO_URI, "hint", annotation, resourceBundle); @@ -2666,16 +2660,16 @@ public class SchemaFormBuilder { //if 0 or 1 -> no constraint (managed by "required") minConstraint = "count(.) >= " + o.minimum; - bindElement.setAttributeNS(ALFRESCO_NS, - ALFRESCO_PREFIX + ":minimum", + bindElement.setAttributeNS(NamespaceService.ALFRESCO_URI, + NamespaceService.ALFRESCO_PREFIX + ":minimum", String.valueOf(o.minimum)); } if (o.maximum > 1) { //if 1 or unbounded -> no constraint maxConstraint = "count(.) <= " + o.maximum; - bindElement.setAttributeNS(ALFRESCO_NS, - ALFRESCO_PREFIX + ":maximum", + bindElement.setAttributeNS(NamespaceService.ALFRESCO_URI, + NamespaceService.ALFRESCO_PREFIX + ":maximum", String.valueOf(o.maximum)); } diff --git a/source/java/org/alfresco/web/forms/xforms/XFormsProcessor.java b/source/java/org/alfresco/web/forms/xforms/XFormsProcessor.java index 8fc179abf6..ff41aa9b1e 100644 --- a/source/java/org/alfresco/web/forms/xforms/XFormsProcessor.java +++ b/source/java/org/alfresco/web/forms/xforms/XFormsProcessor.java @@ -20,6 +20,7 @@ import java.io.*; import javax.faces.context.FacesContext; import javax.servlet.http.HttpServletRequest; +import org.alfresco.service.namespace.NamespaceService; import org.alfresco.web.forms.*; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -28,6 +29,7 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.alfresco.web.app.servlet.FacesHelper; +import org.chiba.xml.ns.NamespaceConstants; import org.chiba.xml.xforms.exception.XFormsException; public class XFormsProcessor @@ -36,6 +38,26 @@ public class XFormsProcessor private static final Log LOGGER = LogFactory.getLog(XFormsProcessor.class); + private final static String[][] JS_NAMESPACES = + { + { "xforms", NamespaceConstants.XFORMS_NS, NamespaceConstants.XFORMS_PREFIX }, + { "xhtml", NamespaceConstants.XHTML_NS, NamespaceConstants.XHTML_PREFIX }, + { "chiba", NamespaceConstants.CHIBA_NS, NamespaceConstants.CHIBA_PREFIX }, + { "alfresco", NamespaceService.ALFRESCO_URI, NamespaceService.ALFRESCO_PREFIX } + }; + + private final String[] JS_SCRIPTS = + { + "/scripts/tiny_mce/" + (LOGGER.isDebugEnabled() + ? "tiny_mce_src.js" + : "tiny_mce.js"), + "/scripts/ajax/dojo/" + (LOGGER.isDebugEnabled() + ? "dojo.js.uncompressed.js" + : "dojo.js"), + "/scripts/ajax/xforms.js" + }; + + public XFormsProcessor() { } @@ -77,44 +99,51 @@ public class XFormsProcessor throw new ProcessingException(xfe); } - final String cp = fc.getExternalContext().getRequestContextPath(); + final String contextPath = fc.getExternalContext().getRequestContextPath(); final Document result = XMLUtil.newDocument(); + final String xformsUIDivId = "alfresco-xforms-ui"; // this div is where the ui will write to final Element div = result.createElement("div"); - div.setAttribute("id", "alfresco-xforms-ui"); + div.setAttribute("id", xformsUIDivId); result.appendChild(div); Element e = result.createElement("link"); e.setAttribute("rel", "stylesheet"); e.setAttribute("type", "text/css"); - e.setAttribute("href", cp + "/css/xforms.css"); + e.setAttribute("href", contextPath + "/css/xforms.css"); div.appendChild(e); // a script with config information and globals. e = result.createElement("script"); e.setAttribute("type", "text/javascript"); - e.appendChild(result.createTextNode("\ndjConfig = { isDebug: " + LOGGER.isDebugEnabled() + - " };\n" + - "var WEBAPP_CONTEXT = \"" + cp + "\";\n")); + final StringBuilder js = new StringBuilder("\ndjConfig = {isDebug:" + LOGGER.isDebugEnabled() + "};\n"); + js.append("var alfresco_xforms_constants = {};\n"); + js.append("alfresco_xforms_constants.WEBAPP_CONTEXT = '"). + append(contextPath). + append("';\n"); + js.append("alfresco_xforms_constants.XFORMS_UI_DIV_ID = '"). + append(xformsUIDivId). + append("';\n"); + for (String[] ns : JS_NAMESPACES) + { + js.append("alfresco_xforms_constants."). + append(ns[0].toUpperCase()). + append("_NS = '").append(ns[1]).append("';\n"); + js.append("alfresco_xforms_constants."). + append(ns[0].toUpperCase()). + append("_PREFIX = '").append(ns[2]).append("';\n"); + } + e.appendChild(result.createTextNode(js.toString())); + div.appendChild(e); - final String[] scripts = - { - "/scripts/tiny_mce/" + (LOGGER.isDebugEnabled() - ? "tiny_mce_src.js" - : "tiny_mce.js"), - "/scripts/ajax/dojo/" + (LOGGER.isDebugEnabled() - ? "dojo.js.uncompressed.js" - : "dojo.js"), - "/scripts/ajax/xforms.js" - }; // include all our scripts, order is significant - for (int i = 0; i < scripts.length; i++) + for (final String script : JS_SCRIPTS) { e = result.createElement("script"); e.setAttribute("type", "text/javascript"); - e.setAttribute("src", cp + scripts[i]); + e.setAttribute("src", contextPath + script); e.appendChild(result.createTextNode("\n")); div.appendChild(e); } diff --git a/source/java/org/alfresco/web/ui/wcm/component/UIFormProcessor.java b/source/java/org/alfresco/web/ui/wcm/component/UIFormProcessor.java index 5e678fd3e2..990b776fde 100644 --- a/source/java/org/alfresco/web/ui/wcm/component/UIFormProcessor.java +++ b/source/java/org/alfresco/web/ui/wcm/component/UIFormProcessor.java @@ -25,8 +25,6 @@ import javax.faces.el.ValueBinding; import org.alfresco.web.forms.*; import org.alfresco.web.ui.common.Utils; import org.alfresco.web.ui.common.component.SelfRenderingComponent; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.w3c.dom.Document; /** @@ -34,8 +32,6 @@ import org.w3c.dom.Document; */ public class UIFormProcessor extends SelfRenderingComponent { - private static final Log LOGGER = LogFactory.getLog(UIFormProcessor.class); - private Document formInstanceData = null; private Form form = null; diff --git a/source/java/org/alfresco/web/ui/wcm/tag/FormProcessorTag.java b/source/java/org/alfresco/web/ui/wcm/tag/FormProcessorTag.java index 2c5ae44f2a..d5e5db2f52 100644 --- a/source/java/org/alfresco/web/ui/wcm/tag/FormProcessorTag.java +++ b/source/java/org/alfresco/web/ui/wcm/tag/FormProcessorTag.java @@ -29,7 +29,7 @@ public class FormProcessorTag extends BaseComponentTag { private String formInstanceData; - private String templateType; + private String form; private String formProcessorSession; /** @@ -61,10 +61,10 @@ public class FormProcessorTag extends BaseComponentTag final ValueBinding vb = app.createValueBinding(this.formInstanceData); component.setValueBinding("formInstanceData", vb); } - if (this.templateType != null) + if (this.form != null) { - assert this.isValueReference(this.templateType); - final ValueBinding vb = app.createValueBinding(this.templateType); + assert this.isValueReference(this.form); + final ValueBinding vb = app.createValueBinding(this.form); component.setValueBinding("form", vb); } if (this.formProcessorSession != null) @@ -82,7 +82,7 @@ public class FormProcessorTag extends BaseComponentTag { super.release(); this.formInstanceData = null; - this.templateType = null; + this.form = null; this.formProcessorSession = null; } @@ -99,11 +99,11 @@ public class FormProcessorTag extends BaseComponentTag /** * Sets the tempalte type * - * @param templateType the tempalteType for the processor. + * @param form the tempalteType for the processor. */ - public void setForm(final String templateType) + public void setForm(final String form) { - this.templateType = templateType; + this.form = form; } /** diff --git a/source/test-resources/websites/alfresco/ROOT/media/releases/get_company_footer_choices_simple_type.jsp b/source/test-resources/websites/alfresco/ROOT/media/releases/get_company_footer_choices_simple_type.jsp index bfd325a692..de56060252 100644 --- a/source/test-resources/websites/alfresco/ROOT/media/releases/get_company_footer_choices_simple_type.jsp +++ b/source/test-resources/websites/alfresco/ROOT/media/releases/get_company_footer_choices_simple_type.jsp @@ -52,7 +52,7 @@ which wants to update the list of available company footers dynamically. --> @@ -65,7 +65,7 @@ which wants to update the list of available company footers dynamically. - + diff --git a/source/test-resources/xforms/unit-tests/output-method-callout-test/output-method-callout.ftl b/source/test-resources/xforms/unit-tests/output-method-callout-test/output-method-callout.ftl index 0ae0cde40d..3e20f0bf11 100644 --- a/source/test-resources/xforms/unit-tests/output-method-callout-test/output-method-callout.ftl +++ b/source/test-resources/xforms/unit-tests/output-method-callout-test/output-method-callout.ftl @@ -1,4 +1,4 @@ -<#ftl ns_prefixes={"alfresco", "http://www.alfresco.org/alfresco"}> +<#ftl ns_prefixes={"alf", "http://www.alfresco.org"}> Simple Test - +
Generated by output-method-callout.xsl
+ +
+ <xsl:value-of select="$alf:avm_sandbox_url"/> +
+
- <xsl:value-of select="$alfresco:avm_sandbox_url"/> + <xsl:value-of select="$alf:form_instance_data_file_name"/>
- +
- <xsl:value-of select="$alfresco:form_instance_data_file_name"/> + <xsl:value-of select="$alf:rendition_file_name"/>
- +
- <xsl:value-of select="$alfresco:rendition_file_name"/> + <xsl:value-of select="$alf:parent_path"/>
- +
- <xsl:value-of select="$alfresco:parent_path"/> + <xsl:value-of select="$alf:request_context_path"/>
- +
- <xsl:value-of select="$alfresco:request_context_path"/> + <xsl:value-of select="$alf:request_context_path"/><xsl:value-of select="/simple/uri"/>
- +
- <xsl:value-of select="$alfresco:request_context_path"/><xsl:value-of select="/simple/uri"/> + <xsl:value-of select="alf:_getAVMPath('foo')"/>
- +
- <xsl:value-of select="alfresco:_getAVMPath('foo')"/> + <xsl:value-of select="alf:_getAVMPath('/foo')"/>
- - -
- <xsl:value-of select="alfresco:_getAVMPath('/foo')"/> -
- +
My value accessed using /simple/string:
-
My value accessed using alfresco:parseXMLDocument($alfresco:form_instance_data_file_name):
- -
Values from xml files generated by in :
+ +
My value accessed using alf:parseXMLDocument($alf:form_instance_data_file_name):
+ + +
My value accessed using document(concat('/', $alf:form_instance_data_file_name)):
+ + +
Values from xml files generated by in :
    - +
  • - <xsl:value-of select="@alfresco:file_name"/> = <xsl:value-of select="string"/> + <xsl:value-of select="@alf:file_name"/> = <xsl:value-of select="string"/>
    - = + =
  • diff --git a/source/web/css/main.css b/source/web/css/main.css index f2228ebe6b..9f6d5d1399 100644 --- a/source/web/css/main.css +++ b/source/web/css/main.css @@ -628,4 +628,20 @@ a.topToolbarLinkHighlight, a.topToolbarLinkHighlight:link, a.topToolbarLinkHighl height: 330px; width: 220px; overflow: auto; -} \ No newline at end of file +} + +.panelGridRequiredImageColumn +{ + width: 20px; +} + +.panelGridLabelColumn +{ + white-space: nowrap; + width: 25%; +} + +.panelGridValueColumn +{ + width: 100%; +} diff --git a/source/web/jsp/wcm/create-form-wizard/configure-rendering-engines.jsp b/source/web/jsp/wcm/create-form-wizard/configure-rendering-engines.jsp index ee7ba34446..4c9180d8d2 100644 --- a/source/web/jsp/wcm/create-form-wizard/configure-rendering-engines.jsp +++ b/source/web/jsp/wcm/create-form-wizard/configure-rendering-engines.jsp @@ -48,6 +48,7 @@ escape="false" /> width="100%"> @@ -93,6 +94,7 @@ escape="false" /> width="100%"> - - - + columns="2" cellspacing="1" border="0"> + + + - + diff --git a/source/web/jsp/wcm/create-form-wizard/details.jsp b/source/web/jsp/wcm/create-form-wizard/details.jsp index bc1423717d..c82afe71ab 100644 --- a/source/web/jsp/wcm/create-form-wizard/details.jsp +++ b/source/web/jsp/wcm/create-form-wizard/details.jsp @@ -94,8 +94,12 @@ escape="false" /> - + columns="3" + cellpadding="3" + cellspacing="3" + border="0" + width="100%" + columnClasses="panelGridRequiredImageColumn,panelGridLabelColumn,panelGridValueColumn"> + columns="3" + cellpadding="3" + cellspacing="3" + border="0" + columnClasses="panelGridRequiredImageColumn,panelGridLabelColumn,panelGridValueColumn"> + width="100%"> function apply_default_workflow_changed(value) { -document.getElementById("wizard:wizard-body:sdw-pg-2").style.display = value == 'true' ? "block" : "none"; + document.getElementById("wizard:wizard-body:sdw-pg-2").style.display = value == 'true' ? "block" : "none"; } @@ -37,12 +37,13 @@ document.getElementById("wizard:wizard-body:sdw-pg-2").style.display = value == +
     
    + style="margin:5px 0px;height:108px;*height:112px;width:100%;overflow:auto" class="selectListTable"> ${msg.description}: - <${msg.value_not_set}> + ${msg.description_not_set} ${WizardManager.bean.formDescription} @@ -76,7 +76,7 @@
    ${msg.description}: - <${msg.value_not_set}> + ${msg.description_not_set} ${ret.description} diff --git a/source/web/jsp/workflow/manage-task-dialog.jsp b/source/web/jsp/workflow/manage-task-dialog.jsp index 381473fa95..784032f721 100644 --- a/source/web/jsp/workflow/manage-task-dialog.jsp +++ b/source/web/jsp/workflow/manage-task-dialog.jsp @@ -98,6 +98,7 @@ + diff --git a/source/web/scripts/ajax/xforms.js b/source/web/scripts/ajax/xforms.js index f2505e5b7b..03c7885c13 100644 --- a/source/web/scripts/ajax/xforms.js +++ b/source/web/scripts/ajax/xforms.js @@ -4,19 +4,16 @@ dojo.require("dojo.widget.Button"); dojo.require("dojo.lfx.html"); dojo.hostenv.writeIncludes(); -var XFORMS_NS = "http://www.w3.org/2002/xforms"; -var XFORMS_PREFIX = "xf"; -var XHTML_NS = "http://www.w3.org/1999/xhtml"; -var XHTML_NS_PREFIX = "xhtml"; -var CHIBA_NS = "http://chiba.sourceforge.net/xforms"; -var CHIBA_NS_PREFIX = "chiba"; -var ALFRESCO_NS = "http://www.alfresco.org/alfresco"; -var ALFRESCO_NS_PREFIX = "alfresco"; +alfresco_xforms_constants.XFORMS_ERROR_DIV_ID = "alfresco-xforms-error"; +alfresco_xforms_constants.AJAX_LOADER_DIV_ID = "alfresco-ajax-loader"; -var EXPANDED_IMAGE = new Image(); -EXPANDED_IMAGE.src = WEBAPP_CONTEXT + "/images/icons/expanded.gif"; -var COLLAPSED_IMAGE = new Image(); -COLLAPSED_IMAGE.src = WEBAPP_CONTEXT + "/images/icons/collapsed.gif"; +alfresco_xforms_constants.EXPANDED_IMAGE = new Image(); +alfresco_xforms_constants.EXPANDED_IMAGE.src = + alfresco_xforms_constants.WEBAPP_CONTEXT + "/images/icons/expanded.gif"; + +alfresco_xforms_constants.COLLAPSED_IMAGE = new Image(); +alfresco_xforms_constants.COLLAPSED_IMAGE.src = + alfresco_xforms_constants.WEBAPP_CONTEXT + "/images/icons/collapsed.gif"; function _xforms_init() { @@ -146,7 +143,10 @@ dojo.declare("alfresco.xforms.Widget", this.xform.getInstance(), XPathResult.FIRST_ORDERED_NODE_TYPE); if (!result) - throw new Error("unable to resolve xpath /" + xpath + " for " + this.id); + { + dojo.debug("unable to resolve xpath /" + xpath + " for " + this.id); + return null; + } result = (result.nodeType == dojo.dom.ELEMENT_NODE ? dojo.dom.textContent(result) : result.nodeValue); @@ -157,15 +157,18 @@ dojo.declare("alfresco.xforms.Widget", { var binding = this.xform.getBinding(this.xformsNode); var xpath = ''; + var repeatIndices = this.getRepeatIndices(); do { var s = binding.nodeset; if (binding.nodeset == '.') { binding = binding.parent; - var repeatIndices = this.getRepeatIndices(); + } + if (binding.nodeset.match(/.+\[.+\]/)) + { s = binding.nodeset.replace(/([^\[]+)\[.*/, "$1"); - s += '[' + (repeatIndices.pop().index + 1) + ']'; + s += '[' + (repeatIndices.shift().index + 1) + ']'; } xpath = s + (xpath.length != 0 ? '/' + xpath : ""); binding = binding.parent; @@ -175,7 +178,10 @@ dojo.declare("alfresco.xforms.Widget", }, _getLabelNode: function() { - var labels = _getElementsByTagNameNS(this.xformsNode, XFORMS_NS, XFORMS_PREFIX, "label"); + var labels = _getElementsByTagNameNS(this.xformsNode, + alfresco_xforms_constants.XFORMS_NS, + alfresco_xforms_constants.XFORMS_PREFIX, + "label"); for (var i = 0; i < labels.length; i++) { if (labels[i].parentNode == this.xformsNode) @@ -185,7 +191,10 @@ dojo.declare("alfresco.xforms.Widget", }, _getAlertNode: function() { - var labels = _getElementsByTagNameNS(this.xformsNode, XFORMS_NS, XFORMS_PREFIX, "alert"); + var labels = _getElementsByTagNameNS(this.xformsNode, + alfresco_xforms_constants.XFORMS_NS, + alfresco_xforms_constants.XFORMS_PREFIX, + "alert"); for (var i = 0; i < labels.length; i++) { if (labels[i].parentNode == this.xformsNode) @@ -461,12 +470,21 @@ dojo.declare("alfresco.xforms.AbstractSelectWidget", getValues: function() { var binding = this.xform.getBinding(this.xformsNode); - var values = _getElementsByTagNameNS(this.xformsNode, XFORMS_NS, XFORMS_PREFIX, "item"); + var values = _getElementsByTagNameNS(this.xformsNode, + alfresco_xforms_constants.XFORMS_NS, + alfresco_xforms_constants.XFORMS_PREFIX, + "item"); var result = []; for (var v = 0; v < values.length; v++) { - var label = _getElementsByTagNameNS(values[v], XFORMS_NS, XFORMS_PREFIX, "label")[0]; - var value = _getElementsByTagNameNS(values[v], XFORMS_NS, XFORMS_PREFIX, "value")[0]; + var label = _getElementsByTagNameNS(values[v], + alfresco_xforms_constants.XFORMS_NS, + alfresco_xforms_constants.XFORMS_PREFIX, + "label")[0]; + var value = _getElementsByTagNameNS(values[v], + alfresco_xforms_constants.XFORMS_NS, + alfresco_xforms_constants.XFORMS_PREFIX, + "value")[0]; var valid = true; if (binding.constraint) { @@ -721,13 +739,19 @@ dojo.declare("alfresco.xforms.Group", setShowHeader: function(showHeader) { if (showHeader == this.showHeader) + { return; + } this.showHeader = showHeader; if (this.showHeader && this.groupHeaderNode.style.display == "none") + { this.groupHeaderNode.style.display = "block"; + } if (!this.showHeader && this.groupHeaderNode.style.display == "block") + { this.groupHeaderNode.style.display = "none"; + } }, getWidgetsInvalidForSubmit: function() { @@ -753,7 +777,9 @@ dojo.declare("alfresco.xforms.Group", " is " + this.children[i].id + " the same as " + child.id + "?"); if (this.children[i] == child) + { return i; + } } return -1; }, @@ -775,7 +801,9 @@ dojo.declare("alfresco.xforms.Group", child.domContainer.style.top = "0px"; if (this.parent && this.parent.domNode) + { child.domContainer.style.top = this.parent.domNode.style.bottom; + } if (position == this.children.length) { @@ -792,7 +820,8 @@ dojo.declare("alfresco.xforms.Group", if (!(child instanceof alfresco.xforms.Group)) { var requiredImage = document.createElement("img"); - requiredImage.setAttribute("src", WEBAPP_CONTEXT + "/images/icons/required_field.gif"); + requiredImage.setAttribute("src", + alfresco_xforms_constants.WEBAPP_CONTEXT + "/images/icons/required_field.gif"); requiredImage.style.marginLeft = "5px"; requiredImage.style.marginRight = "5px"; child.domContainer.appendChild(requiredImage); @@ -893,12 +922,15 @@ dojo.declare("alfresco.xforms.Group", this.toggleExpandedImage = document.createElement("img"); this.groupHeaderNode.appendChild(this.toggleExpandedImage); - this.toggleExpandedImage.setAttribute("src", EXPANDED_IMAGE.src); + this.toggleExpandedImage.setAttribute("src", alfresco_xforms_constants.EXPANDED_IMAGE.src); this.toggleExpandedImage.align = "absmiddle"; this.toggleExpandedImage.style.marginLeft = "5px"; this.toggleExpandedImage.style.marginRight = "5px"; - dojo.event.connect(this.toggleExpandedImage, "onclick", this, this._toggleExpanded_clickHandler); + dojo.event.connect(this.toggleExpandedImage, + "onclick", + this, + this._toggleExpanded_clickHandler); this.groupHeaderNode.appendChild(document.createTextNode(this.getLabel())); @@ -910,14 +942,18 @@ dojo.declare("alfresco.xforms.Group", }, isExpanded: function() { - return this.toggleExpandedImage.getAttribute("src") == EXPANDED_IMAGE.src; + return this.toggleExpandedImage.getAttribute("src") == alfresco_xforms_constants.EXPANDED_IMAGE.src; }, setExpanded: function(expanded) { - if (expanded == this.isExpanded()) - return; - this.toggleExpandedImage.src = expanded ? EXPANDED_IMAGE.src : COLLAPSED_IMAGE.src; - this.domNode.childContainerNode.style.display = expanded ? "block" : "none"; + if (expanded != this.isExpanded()) + { + this.toggleExpandedImage.src = + (expanded + ? alfresco_xforms_constants.EXPANDED_IMAGE.src + : alfresco_xforms_constants.COLLAPSED_IMAGE.src); + this.domNode.childContainerNode.style.display = expanded ? "block" : "none"; + } }, _toggleExpanded_clickHandler: function(event) { @@ -995,18 +1031,19 @@ dojo.declare("alfresco.xforms.Repeat", insertChildAt: function(child, position) { this.repeatControls.splice(position, 0, document.createElement("div")); - var images = [ - { name: "insertRepeatItemImage", src: "plus", action: this._insertRepeatItemAfter_handler }, - { name: "moveRepeatItemUpImage", src: "arrow_up", action: this._moveRepeatItemUp_handler }, - { name: "moveRepeatItemDownImage", src: "arrow_down", action: this._moveRepeatItemDown_handler }, - { name: "removeRepeatItemImage", src: "minus", action: this._removeRepeatItem_handler } + var images = + [ + { name: "insertRepeatItemImage", src: "plus", action: this._insertRepeatItemAfter_handler }, + { name: "moveRepeatItemUpImage", src: "arrow_up", action: this._moveRepeatItemUp_handler }, + { name: "moveRepeatItemDownImage", src: "arrow_down", action: this._moveRepeatItemDown_handler }, + { name: "removeRepeatItemImage", src: "minus", action: this._removeRepeatItem_handler } ]; var repeatControlsWidth = 0; for (var i = 0; i < images.length; i++) { var img = document.createElement("img"); this.repeatControls[position][images[i].name] = img; - img.setAttribute("src", (WEBAPP_CONTEXT + "/images/icons/" + + img.setAttribute("src", (alfresco_xforms_constants.WEBAPP_CONTEXT + "/images/icons/" + images[i].src + ".gif")); img.style.width = "16px"; img.style.height = "16px"; @@ -1028,9 +1065,14 @@ dojo.declare("alfresco.xforms.Repeat", result.style.border = "1px solid black"; if (result.nextSibling) - result.parentNode.insertBefore(this.repeatControls[position], result.nextSibling); + { + result.parentNode.insertBefore(this.repeatControls[position], + result.nextSibling); + } else + { result.parentNode.appendChild(this.repeatControls[position]); + } dojo.html.setClass(this.repeatControls[position], "xformsRepeatControls"); this.repeatControls[position].style.width = repeatControlsWidth + "px"; @@ -1062,7 +1104,9 @@ dojo.declare("alfresco.xforms.Repeat", { this._selectedIndex = Math.min(this.children.length - 1, this._selectedIndex); if (this.children.length == 0) + { this._selectedIndex = -1; + } return this._selectedIndex; }, _updateDisplay: function() @@ -1080,10 +1124,16 @@ dojo.declare("alfresco.xforms.Repeat", for (var i in bw) { if (! (bw[i] instanceof alfresco.xforms.Trigger)) + { continue; + } + var action = bw[i].getAction(); if (action.getType() != type) + { continue; + } + var propertiesEqual = true; for (var p in properties) { @@ -1095,7 +1145,9 @@ dojo.declare("alfresco.xforms.Repeat", } } if (propertiesEqual) + { return bw[i]; + } } throw new Error("unable to find trigger " + type + ", properties " + properties + @@ -1106,14 +1158,14 @@ dojo.declare("alfresco.xforms.Repeat", { dojo.event.browser.stopEvent(event); var repeat = event.target.repeat; - if (!repeat.isInsertRepeatItemEnabled()) - return; - - var index = repeat.repeatControls.indexOf(event.target.parentNode); - var repeatItem = repeat.getChildAt(index); - this.setFocusedChild(repeatItem); - var trigger = this._getRepeatItemTrigger("insert", { position: "after" }); - this.xform.fireAction(trigger.id); + if (repeat.isInsertRepeatItemEnabled()) + { + var index = repeat.repeatControls.indexOf(event.target.parentNode); + var repeatItem = repeat.getChildAt(index); + this.setFocusedChild(repeatItem); + var trigger = this._getRepeatItemTrigger("insert", { position: "after" }); + this.xform.fireAction(trigger.id); + } }, _headerInsertRepeatItemBefore_handler: function(event) { @@ -1121,11 +1173,12 @@ dojo.declare("alfresco.xforms.Repeat", { dojo.event.browser.stopEvent(event); var repeat = event.target.repeat; - if (!repeat.isInsertRepeatItemEnabled()) - return; - this.setFocusedChild(null); - var trigger = this._getRepeatItemTrigger("insert", { position: "before" }); - this.xform.fireAction(trigger.id); + if (repeat.isInsertRepeatItemEnabled()) + { + this.setFocusedChild(null); + var trigger = this._getRepeatItemTrigger("insert", { position: "before" }); + this.xform.fireAction(trigger.id); + } } }, _removeRepeatItem_handler: function(event) @@ -1231,7 +1284,9 @@ dojo.declare("alfresco.xforms.Repeat", this.headerInsertRepeatItemImage = document.createElement("img"); this.headerInsertRepeatItemImage.repeat = this; this.groupHeaderNode.appendChild(this.headerInsertRepeatItemImage); - this.headerInsertRepeatItemImage.setAttribute("src", WEBAPP_CONTEXT + "/images/icons/plus.gif"); + this.headerInsertRepeatItemImage.setAttribute("src", + alfresco_xforms_constants.WEBAPP_CONTEXT + + "/images/icons/plus.gif"); this.headerInsertRepeatItemImage.style.width = "16px"; this.headerInsertRepeatItemImage.style.height = "16px"; this.headerInsertRepeatItemImage.align = "absmiddle"; @@ -1253,9 +1308,12 @@ dojo.declare("alfresco.xforms.Repeat", handlePrototypeCloned: function(prototypeId) { dojo.debug(this.id + ".handlePrototypeCloned("+ prototypeId +")"); - var chibaData = _getElementsByTagNameNS(this.xformsNode, CHIBA_NS, CHIBA_NS_PREFIX, "data"); + var chibaData = _getElementsByTagNameNS(this.xformsNode, + alfresco_xforms_constants.CHIBA_NS, + alfresco_xforms_constants.CHIBA_PREFIX, + "data"); chibaData = chibaData[chibaData.length - 1]; - dojo.debug(CHIBA_NS_PREFIX + ":data == " + dojo.dom.innerXML(chibaData)); + dojo.debug(alfresco_xforms_constants.CHIBA_PREFIX + ":data == " + dojo.dom.innerXML(chibaData)); var prototypeToClone = dojo.dom.firstElement(chibaData); if (prototypeToClone.getAttribute("id") != prototypeId) throw new Error("unable to locate " + prototypeId + @@ -1308,7 +1366,7 @@ dojo.declare("alfresco.xforms.Repeat", dojo.declare("alfresco.xforms.Trigger", alfresco.xforms.Widget, { - initializer: function(xform, xformsNode) + initializer: function(xform, xformsNode) { // this.inherited("initializer", [ xform, xformsNode ]); }, @@ -1336,8 +1394,8 @@ dojo.declare("alfresco.xforms.Trigger", var c = this.xformsNode.childNodes[i]; if (c.nodeType != dojo.dom.ELEMENT_NODE) continue; - if (c.nodeName == XFORMS_PREFIX + ":label" || - c.nodeName == XFORMS_PREFIX + ":alert") + if (c.nodeName == alfresco_xforms_constants.XFORMS_PREFIX + ":label" || + c.nodeName == alfresco_xforms_constants.XFORMS_PREFIX + ":alert") continue; return new alfresco.xforms.XFormsAction(this.xform, c); } @@ -1352,7 +1410,7 @@ dojo.declare("alfresco.xforms.Trigger", dojo.declare("alfresco.xforms.Submit", alfresco.xforms.Trigger, { - initializer: function(xform, xformsNode) + initializer: function(xform, xformsNode) { // this.inherited("initializer", [ xform, xformsNode ]); var submit_buttons = _xforms_getSubmitButtons(); @@ -1400,7 +1458,7 @@ dojo.declare("alfresco.xforms.Submit", dojo.declare("alfresco.xforms.XFormsAction", null, { - initializer: function(xform, xformsNode) + initializer: function(xform, xformsNode) { this.xform = xform; this.xformsNode = xformsNode; @@ -1408,23 +1466,23 @@ dojo.declare("alfresco.xforms.XFormsAction", for (var i = 0; i < this.xformsNode.attributes.length; i++) { var attr = this.xformsNode.attributes[i]; - if (attr.nodeName.match(new RegExp("^" + XFORMS_PREFIX + ":"))) + if (attr.nodeName.match(new RegExp("^" + alfresco_xforms_constants.XFORMS_PREFIX + ":"))) { - this.properties[attr.nodeName.substring((XFORMS_PREFIX + ":").length)] = + this.properties[attr.nodeName.substring((alfresco_xforms_constants.XFORMS_PREFIX + ":").length)] = attr.nodeValue; } } }, getType: function() { - return this.xformsNode.nodeName.substring((XFORMS_PREFIX + ":").length); + return this.xformsNode.nodeName.substring((alfresco_xforms_constants.XFORMS_PREFIX + ":").length); } }); dojo.declare("alfresco.xforms.XFormsEvent", null, { - initializer: function(node) + initializer: function(node) { this.type = node.nodeName; this.targetId = node.getAttribute("targetId"); @@ -1452,17 +1510,17 @@ dojo.declare("alfresco.xforms.Binding", { this.xformsNode = xformsNode; this.id = this.xformsNode.getAttribute("id"); - this.readonly = this.xformsNode.getAttribute(XFORMS_PREFIX + ":readonly"); - this.required = this.xformsNode.getAttribute(XFORMS_PREFIX + ":required"); - this.nodeset = this.xformsNode.getAttribute(XFORMS_PREFIX + ":nodeset"); - this._type = (this.xformsNode.hasAttribute(XFORMS_PREFIX + ":type") - ? this.xformsNode.getAttribute(XFORMS_PREFIX + ":type") + this.readonly = this.xformsNode.getAttribute(alfresco_xforms_constants.XFORMS_PREFIX + ":readonly"); + this.required = this.xformsNode.getAttribute(alfresco_xforms_constants.XFORMS_PREFIX + ":required"); + this.nodeset = this.xformsNode.getAttribute(alfresco_xforms_constants.XFORMS_PREFIX + ":nodeset"); + this._type = (this.xformsNode.hasAttribute(alfresco_xforms_constants.XFORMS_PREFIX + ":type") + ? this.xformsNode.getAttribute(alfresco_xforms_constants.XFORMS_PREFIX + ":type") : null); - this.constraint = (this.xformsNode.hasAttribute(XFORMS_PREFIX + ":constraint") - ? this.xformsNode.getAttribute(XFORMS_PREFIX + ":constraint") + this.constraint = (this.xformsNode.hasAttribute(alfresco_xforms_constants.XFORMS_PREFIX + ":constraint") + ? this.xformsNode.getAttribute(alfresco_xforms_constants.XFORMS_PREFIX + ":constraint") : null); - this.maximum = parseInt(this.xformsNode.getAttribute(ALFRESCO_NS_PREFIX + ":maximum")); - this.minimum = parseInt(this.xformsNode.getAttribute(ALFRESCO_NS_PREFIX + ":minimum")); + this.maximum = parseInt(this.xformsNode.getAttribute(alfresco_xforms_constants.ALFRESCO_PREFIX + ":maximum")); + this.minimum = parseInt(this.xformsNode.getAttribute(alfresco_xforms_constants.ALFRESCO_PREFIX + ":minimum")); this.parent = parent; this.widgets = {}; }, @@ -1507,7 +1565,7 @@ dojo.declare("alfresco.xforms.XForm", ? bindings[i].parent.id : 'null')); } - var alfUI = document.getElementById("alfresco-xforms-ui"); + var alfUI = document.getElementById(alfresco_xforms_constants.XFORMS_UI_DIV_ID); alfUI.style.width = "100%"; this.rootWidget = new alfresco.xforms.Group(this, alfUI); this.rootWidget.render(alfUI); @@ -1519,15 +1577,15 @@ dojo.declare("alfresco.xforms.XForm", dojo.debug("creating node for " + node.nodeName.toLowerCase()); switch (node.nodeName.toLowerCase()) { - case XFORMS_PREFIX + ":group": + case alfresco_xforms_constants.XFORMS_PREFIX + ":group": return new alfresco.xforms.Group(this, node); - case XFORMS_PREFIX + ":repeat": + case alfresco_xforms_constants.XFORMS_PREFIX + ":repeat": return new alfresco.xforms.Repeat(this, node); - case XFORMS_PREFIX + ":textarea": + case alfresco_xforms_constants.XFORMS_PREFIX + ":textarea": return new alfresco.xforms.TextArea(this, node); - case XFORMS_PREFIX + ":upload": + case alfresco_xforms_constants.XFORMS_PREFIX + ":upload": return new alfresco.xforms.FilePicker(this, node); - case XFORMS_PREFIX + ":input": + case alfresco_xforms_constants.XFORMS_PREFIX + ":input": { var type = this.getBinding(node).getType(); switch (type) @@ -1554,19 +1612,19 @@ dojo.declare("alfresco.xforms.XForm", return new alfresco.xforms.TextField(this, node); } } - case XFORMS_PREFIX + ":select": + case alfresco_xforms_constants.XFORMS_PREFIX + ":select": return new alfresco.xforms.Select(this, node); - case XFORMS_PREFIX + ":select1": + case alfresco_xforms_constants.XFORMS_PREFIX + ":select1": return (this.getBinding(node).getType() == "boolean" ? new alfresco.xforms.Checkbox(this, node) : new alfresco.xforms.Select1(this, node)); - case XFORMS_PREFIX + ":submit": + case alfresco_xforms_constants.XFORMS_PREFIX + ":submit": return new alfresco.xforms.Submit(this, node); - case XFORMS_PREFIX + ":trigger": + case alfresco_xforms_constants.XFORMS_PREFIX + ":trigger": return new alfresco.xforms.Trigger(this, node); - case CHIBA_NS_PREFIX + ":data": - case XFORMS_PREFIX + ":label": - case XFORMS_PREFIX + ":alert": + case alfresco_xforms_constants.CHIBA_PREFIX + ":data": + case alfresco_xforms_constants.XFORMS_PREFIX + ":label": + case alfresco_xforms_constants.XFORMS_PREFIX + ":alert": dojo.debug("ignoring " + node.nodeName); return null; default: @@ -1581,7 +1639,7 @@ dojo.declare("alfresco.xforms.XForm", { dojo.debug("loading " + xformsNode.childNodes[i].nodeName + " into " + parentWidget.id); - if (xformsNode.childNodes[i].getAttribute(ALFRESCO_NS_PREFIX + ":prototype") == "true") + if (xformsNode.childNodes[i].getAttribute(alfresco_xforms_constants.ALFRESCO_PREFIX + ":prototype") == "true") { dojo.debug(xformsNode.childNodes[i].getAttribute("id") + " is a prototype, ignoring"); @@ -1593,7 +1651,9 @@ dojo.declare("alfresco.xforms.XForm", dojo.debug("created " + w.id + " for " + xformsNode.childNodes[i].nodeName); parentWidget.addChild(w); if (w instanceof alfresco.xforms.Group) + { this.loadWidgets(xformsNode.childNodes[i], w); + } } } } @@ -1601,29 +1661,29 @@ dojo.declare("alfresco.xforms.XForm", getModel: function() { return _getElementsByTagNameNS(this.xformsNode, - XFORMS_NS, - XFORMS_PREFIX, + alfresco_xforms_constants.XFORMS_NS, + alfresco_xforms_constants.XFORMS_PREFIX, "model")[0]; }, getInstance: function() { var model = this.getModel(); return _getElementsByTagNameNS(model, - XFORMS_NS, - XFORMS_PREFIX, + alfresco_xforms_constants.XFORMS_NS, + alfresco_xforms_constants.XFORMS_PREFIX, "instance")[0]; }, getBody: function() { var b = _getElementsByTagNameNS(this.xformsNode, - XHTML_NS, - XHTML_NS_PREFIX, + alfresco_xforms_constants.XHTML_NS, + alfresco_xforms_constants.XHTML_PREFIX, "body"); return b[b.length - 1]; }, getBinding: function(node) { - return this._bindings[node.getAttribute(XFORMS_PREFIX + ":bind")]; + return this._bindings[node.getAttribute(alfresco_xforms_constants.XFORMS_PREFIX + ":bind")]; }, getBindings: function() { @@ -1635,7 +1695,7 @@ dojo.declare("alfresco.xforms.XForm", dojo.debug("loading bindings for " + bind.nodeName); for (var i = 0; i < bind.childNodes.length; i++) { - if (bind.childNodes[i].nodeName.toLowerCase() == XFORMS_PREFIX + ":bind") + if (bind.childNodes[i].nodeName.toLowerCase() == alfresco_xforms_constants.XFORMS_PREFIX + ":bind") { var b = new alfresco.xforms.Binding(bind.childNodes[i], parent); result[b.id] = b; @@ -1743,22 +1803,14 @@ dojo.declare("alfresco.xforms.XForm", dojo.debug("cloning prototype " + originalId); var prototypeNode = _findElementById(this.xformsNode, originalId); clone = prototypeNode.cloneNode(true); - var clone = prototypeNode.ownerDocument.createElement(XFORMS_PREFIX + ":group"); - clone.setAttribute(XFORMS_PREFIX + ":appearance", "repeated"); + var clone = prototypeNode.ownerDocument.createElement(alfresco_xforms_constants.XFORMS_PREFIX + ":group"); + clone.setAttribute(alfresco_xforms_constants.XFORMS_PREFIX + ":appearance", "repeated"); for (var j = 0; j < prototypeNode.childNodes.length; j++) { clone.appendChild(prototypeNode.childNodes[j].cloneNode(true)); } clone.setAttribute("id", prototypeId); } -// if (true || originalId == xfe.targetId) -// var clone = xfe.getTarget().handlePrototypeCloned(prototypeId); -// else -// { -// var parentClone = prototypeClones[prototypeClones.length - 1]; - -// var clone = originalWidget.widget.handlePrototypeCloned(prototypeId); -// } clone.parentClone = prototypeClone; prototypeClone = clone; break; @@ -1780,7 +1832,7 @@ dojo.declare("alfresco.xforms.XForm", var e = _findElementById(prototypeClone.parentClone, originalId); if (e) { - e.setAttribute(ALFRESCO_NS_PREFIX + ":prototype", "true"); + e.setAttribute(alfresco_xforms_constants.ALFRESCO_PREFIX + ":prototype", "true"); } } break; @@ -1888,7 +1940,9 @@ function _findElementById(node, id) function create_ajax_request(target, serverMethod, methodArgs, load, error) { - var result = new dojo.io.Request(WEBAPP_CONTEXT + "/ajax/invoke/XFormsBean." + serverMethod, "text/xml"); + var result = new dojo.io.Request(alfresco_xforms_constants.WEBAPP_CONTEXT + + "/ajax/invoke/XFormsBean." + serverMethod, + "text/xml"); result.target = target; result.content = methodArgs; @@ -1908,7 +1962,7 @@ function create_ajax_request(target, serverMethod, methodArgs, load, error) function _hide_errors() { - var errorDiv = document.getElementById("alfresco-xforms-error"); + var errorDiv = document.getElementById(alfresco_xforms_constants.XFORMS_ERROR_DIV_ID); if (errorDiv) { dojo.dom.removeChildren(errorDiv); @@ -1918,19 +1972,24 @@ function _hide_errors() function _show_error(msg) { - var errorDiv = document.getElementById("alfresco-xforms-error"); + var errorDiv = document.getElementById(alfresco_xforms_constants.XFORMS_ERROR_DIV_ID); if (!errorDiv) { errorDiv = document.createElement("div"); - errorDiv.setAttribute("id", "alfresco-xforms-error"); + errorDiv.setAttribute("id", alfresco_xforms_constants.XFORMS_ERROR_DIV_ID); dojo.html.setClass(errorDiv, "infoText statusErrorText xformsError"); - var alfUI = document.getElementById("alfresco-xforms-ui"); + var alfUI = document.getElementById(alfresco_xforms_constants.XFORMS_UI_DIV_ID); dojo.dom.prependChild(errorDiv, alfUI); } + if (errorDiv.style.display == "block") + { errorDiv.appendChild(document.createElement("br")); + } else + { errorDiv.style.display = "block"; + } errorDiv.appendChild(msg); } @@ -1942,11 +2001,11 @@ function send_ajax_request(req) function _get_ajax_loader_element() { - var result = document.getElementById("alfresco-ajax-loader"); + var result = document.getElementById(alfresco_xforms_constants.AJAX_LOADER_DIV_ID); if (result) return result; result = document.createElement("div"); - result.setAttribute("id", "alfresco-ajax-loader"); + result.setAttribute("id", alfresco_xforms_constants.AJAX_LOADER_DIV_ID); dojo.html.setClass(result, "xformsAjaxLoader"); dojo.style.hide(result); document.body.appendChild(result); @@ -2008,7 +2067,8 @@ function _getElementsByTagNameNS(parentNode, ns, nsPrefix, tagName) function _evaluateXPath(xpath, contextNode, result_type) { var xmlDocument = contextNode.ownerDocument; - dojo.debug("evaluating xpath " + xpath + " on node " + contextNode.nodeName + + dojo.debug("evaluating xpath " + xpath + + " on node " + contextNode.nodeName + " in document " + xmlDocument); var result = null; if (xmlDocument.evaluate) @@ -2120,7 +2180,7 @@ FilePickerWidget._handleUpload = function(id, fileInput, webappRelativePath, wid form.encoding = "multipart/form-data"; form.enctype = "multipart/form-data"; form.target = iframe.name; - form.action = WEBAPP_CONTEXT + "/ajax/invoke/XFormsBean.uploadFile"; + form.action = alfresco_xforms_constants.WEBAPP_CONTEXT + "/ajax/invoke/XFormsBean.uploadFile"; form.appendChild(fileInput.cloneNode(true)); var rp = d.createElement("input"); @@ -2164,9 +2224,13 @@ setReadonly: function(r) { this.readonly = r; if (this.selectButton) + { this.selectButton.disabled = this.readonly; + } else if (this.readonly) + { this._showSelectedValue(); + } }, render: function() { @@ -2328,7 +2392,7 @@ _showPicker: function(data) headerMenuTriggerImage = d.createElement("img"); this.headerMenuTriggerLink.appendChild(headerMenuTriggerImage); this.headerMenuTriggerLink.image = headerMenuTriggerImage; - headerMenuTriggerImage.setAttribute("src", WEBAPP_CONTEXT + "/images/icons/menu.gif"); + headerMenuTriggerImage.setAttribute("src", alfresco_xforms_constants.WEBAPP_CONTEXT + "/images/icons/menu.gif"); headerMenuTriggerImage.style.borderWidth = "0px"; headerMenuTriggerImage.style.marginLeft = "4px"; headerMenuTriggerImage.align = "absmiddle"; @@ -2352,7 +2416,7 @@ _showPicker: function(data) addContentImage.style.borderWidth = "0px"; addContentImage.style.margin = "0px 2px 0px 2px"; addContentImage.align = "absmiddle"; - addContentImage.setAttribute("src", WEBAPP_CONTEXT + "/images/icons/add.gif"); + addContentImage.setAttribute("src", alfresco_xforms_constants.WEBAPP_CONTEXT + "/images/icons/add.gif"); addContentLink.appendChild(addContentImage); addContentLink.appendChild(d.createTextNode("Add Content")); @@ -2381,7 +2445,7 @@ _showPicker: function(data) navigateToParentNodeImage.style.opacity = (currentPathName == "/" ? .3 : 1); navigateToParentNodeImage.style.margin = "0px 2px 0px 2px"; navigateToParentNodeImage.align = "absmiddle"; - navigateToParentNodeImage.setAttribute("src", WEBAPP_CONTEXT + "/images/icons/up.gif"); + navigateToParentNodeImage.setAttribute("src", alfresco_xforms_constants.WEBAPP_CONTEXT + "/images/icons/up.gif"); navigateToParentLink.appendChild(navigateToParentNodeImage); navigateToParentLink.appendChild(d.createTextNode("Go up")); @@ -2462,7 +2526,7 @@ _showPicker: function(data) var e = d.createElement("img"); e.align = "absmiddle"; e.style.margin = "0px 4px 0px 4px"; - e.setAttribute("src", WEBAPP_CONTEXT + childNodes[i].getAttribute("image")); + e.setAttribute("src", alfresco_xforms_constants.WEBAPP_CONTEXT + childNodes[i].getAttribute("image")); row.appendChild(e); if (childNodes[i].getAttribute("type") == "directory") @@ -2638,7 +2702,7 @@ _openParentPathMenu: function(target, path) parentNodeImage.align = "absmiddle"; parentNodeImage.style.marginRight = "4px"; parentNodeDiv.appendChild(parentNodeImage); - parentNodeImage.setAttribute("src", WEBAPP_CONTEXT + "/images/icons/space_small.gif"); + parentNodeImage.setAttribute("src", alfresco_xforms_constants.WEBAPP_CONTEXT + "/images/icons/space_small.gif"); parentNodeDiv.appendChild(parentNodeImage); parentNodeDiv.appendChild(d.createTextNode(path)); dojo.event.connect(parentNodeDiv,