diff --git a/config/alfresco/messages/webclient.properties b/config/alfresco/messages/webclient.properties index b31aa088ba..d18915e27e 100644 --- a/config/alfresco/messages/webclient.properties +++ b/config/alfresco/messages/webclient.properties @@ -646,13 +646,14 @@ create_form_title=Create Form Wizard create_form_desc=Create an XML Form definition from XML Schema and Rendering Engines create_form_step1_title=Upload an XML Schema create_form_step1_desc=Upload an XML Schema -create_form_step2_title=Edit the XML Schema -create_form_step2_desc=This is the generated XForm based on the schema provided. +create_form_step2_title=Configure Rendering Engines +create_form_step2_desc=Select rendering engines and rendering engine template to render form instance data processed by the form. selected_rendering_engines=Selected Rendering Engines configure_rendering_engines_step1_desc=Upload rendering engine template and specify the extension to use for its generated assets. rendering_engine_file=Rendering Engine Template File rendering_engine_type=Rendering Engine Type extension_for_generated_assets=Extension For Generated Assets +mimetype_for_generated_assets=Mimetype For Generated Assets file_extension=Extension schema=Schema schema_root_element_name=Root Element diff --git a/source/java/org/alfresco/web/bean/wcm/CreateFormWizard.java b/source/java/org/alfresco/web/bean/wcm/CreateFormWizard.java index 0528ff8047..5ff9df5f11 100644 --- a/source/java/org/alfresco/web/bean/wcm/CreateFormWizard.java +++ b/source/java/org/alfresco/web/bean/wcm/CreateFormWizard.java @@ -36,11 +36,14 @@ import org.alfresco.model.WCMModel; import org.alfresco.service.cmr.model.FileInfo; import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.repository.MimetypeService; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.namespace.QName; import org.alfresco.web.app.Application; import org.alfresco.web.bean.FileUploadBean; import org.alfresco.web.bean.wizard.BaseWizardBean; +import org.alfresco.web.data.IDataContainer; +import org.alfresco.web.data.QuickSort; import org.alfresco.web.forms.*; import org.alfresco.web.forms.xforms.SchemaFormBuilder; import org.apache.commons.logging.Log; @@ -66,16 +69,19 @@ public class CreateFormWizard extends BaseWizardBean private final String fileName; private final File file; private final String fileExtension; + private final String mimetype; private final Class renderingEngineType; public RenderingEngineData(final String fileName, - final File file, - final String fileExtension, - final Class renderingEngineType) + final File file, + final String fileExtension, + final String mimetype, + final Class renderingEngineType) { this.fileName = fileName; this.file = file; this.fileExtension = fileExtension; + this.mimetype = mimetype; this.renderingEngineType = renderingEngineType; } @@ -83,6 +89,11 @@ public class CreateFormWizard extends BaseWizardBean { return this.fileExtension; } + + public String getMimetype() + { + return this.mimetype; + } public String getFileName() { @@ -118,9 +129,12 @@ public class CreateFormWizard extends BaseWizardBean private String formDescription; private Class renderingEngineType = null; protected ContentService contentService; + protected MimetypeService mimetypeService; private DataModel renderingEnginesDataModel; private List renderingEngines = null; private String fileExtension = null; + private String mimetype = null; + private List mimetypeChoices = null; // ------------------------------------------------------------------------------ // Wizard implementation @@ -195,6 +209,8 @@ public class CreateFormWizard extends BaseWizardBean props.put(WCMModel.PROP_FORM_SOURCE, schemaNodeRef); props.put(WCMModel.PROP_FILE_EXTENSION_FOR_RENDITION, tomd.getFileExtension()); + props.put(WCMModel.PROP_MIMETYPE_FOR_RENDITION, + tomd.getMimetype()); this.nodeService.addAspect(renderingEngineNodeRef, WCMModel.ASPECT_RENDERING_ENGINE, props); @@ -216,6 +232,7 @@ public class CreateFormWizard extends BaseWizardBean this.renderingEngineType = null; this.renderingEngines = new ArrayList(); this.fileExtension = null; + this.mimetype = null; } @Override @@ -262,6 +279,10 @@ public class CreateFormWizard extends BaseWizardBean */ public String getFileExtension() { + if (this.fileExtension == null && this.mimetype != null) + { + this.fileExtension = this.mimetypeService.getExtension(this.mimetype); + } return this.fileExtension; } @@ -273,6 +294,26 @@ public class CreateFormWizard extends BaseWizardBean this.fileExtension = fileExtension; } + /** + * @return Returns the mimetype. + */ + public String getMimetype() + { + if (this.mimetype == null && this.fileExtension != null) + { + this.mimetype = this.mimetypeService.guessMimetype(this.fileExtension); + } + return this.mimetype; + } + + /** + * @param mimetype The mimetype to set. + */ + public void setMimetype(String mimetype) + { + this.mimetype = mimetype; + } + /** * Add the selected rendering engine to the list */ @@ -289,13 +330,15 @@ public class CreateFormWizard extends BaseWizardBean final RenderingEngineData data = this.new RenderingEngineData(this.getRenderingEngineFileName(), - this.getRenderingEngineFile(), - this.fileExtension, - this.renderingEngineType); + this.getRenderingEngineFile(), + this.getFileExtension(), + this.getMimetype(), + this.renderingEngineType); this.renderingEngines.add(data); this.removeUploadedRenderingEngineFile(); this.renderingEngineType = null; this.fileExtension = null; + this.mimetype = null; } /** @@ -368,7 +411,9 @@ public class CreateFormWizard extends BaseWizardBean ? XSLTRenderingEngine.class : (this.getRenderingEngineFileName().endsWith(".ftl") ? FreeMarkerRenderingEngine.class - : null)); + : (this.getRenderingEngineFileName().endsWith(".fo") + ? XSLFORenderingEngine.class + : null))); } return (this.renderingEngineType == null ? null @@ -396,9 +441,40 @@ public class CreateFormWizard extends BaseWizardBean new SelectItem(FreeMarkerRenderingEngine.class.getName(), getRenderingEngineTypeName(FreeMarkerRenderingEngine.class)), new SelectItem(XSLTRenderingEngine.class.getName(), - getRenderingEngineTypeName(XSLTRenderingEngine.class)) + getRenderingEngineTypeName(XSLTRenderingEngine.class)), + new SelectItem(XSLFORenderingEngine.class.getName(), + getRenderingEngineTypeName(XSLFORenderingEngine.class)) }); } + + /** + * Returns a list of mime types in the system + * + * @return List of mime types + */ + public List getMimeTypeChoices() + { + if (this.mimetypeChoices == null) + { + this.mimetypeChoices = new ArrayList(50); + + final Map mimetypes = this.mimetypeService.getDisplaysByMimetype(); + for (String mimetype : mimetypes.keySet()) + { + this.mimetypeChoices.add(new SelectItem(mimetype, + mimetypes.get(mimetype))); + } + + // make sure the list is sorted by the values + final QuickSort sorter = new QuickSort(this.mimetypeChoices, + "label", + true, + IDataContainer.SORT_CASEINSENSITIVE); + sorter.sort(); + } + + return this.mimetypeChoices; + } private String getRenderingEngineTypeName(Class type) { @@ -406,7 +482,9 @@ public class CreateFormWizard extends BaseWizardBean ? "FreeMarker" : (XSLTRenderingEngine.class.equals(type) ? "XSLT" - : null)); + : (XSLFORenderingEngine.class.equals(type) + ? "XSL-FO" + : null))); } private FileUploadBean getFileUploadBean(final String id) @@ -566,7 +644,8 @@ public class CreateFormWizard extends BaseWizardBean for (int i = 0; i < this.renderingEngines.size(); i++) { final RenderingEngineData tomd = this.renderingEngines.get(i); - labels[1 + i] = "Form Data Renderer for " + tomd.getFileExtension(); + labels[1 + i] = ("RenderingEngine for " + tomd.getFileExtension() + + " mimetype " + tomd.getMimetype()); values[1 + i] = tomd.getFileName(); } @@ -584,7 +663,14 @@ public class CreateFormWizard extends BaseWizardBean { this.contentService = contentService; } - + + /** + * @param mimetypeService The mimetypeService to set. + */ + public void setMimetypeService(MimetypeService mimetypeService) + { + this.mimetypeService = mimetypeService; + } // ------------------------------------------------------------------------------ // Helper Methods diff --git a/source/java/org/alfresco/web/forms/AbstractRenderingEngine.java b/source/java/org/alfresco/web/forms/AbstractRenderingEngine.java index 22d3399702..8afa6a6452 100644 --- a/source/java/org/alfresco/web/forms/AbstractRenderingEngine.java +++ b/source/java/org/alfresco/web/forms/AbstractRenderingEngine.java @@ -69,13 +69,25 @@ public abstract class AbstractRenderingEngine * * @return the file extension to use for generated assets. */ - public String getFileExtension() + public String getFileExtensionForRendition() { return (String) this.nodeService.getProperty(this.nodeRef, WCMModel.PROP_FILE_EXTENSION_FOR_RENDITION); } + /** + * Returns the file extension to use for generated assets. + * + * @return the file extension to use for generated assets. + */ + public String getMimetypeForRendition() + { + return (String) + this.nodeService.getProperty(this.nodeRef, + WCMModel.PROP_MIMETYPE_FOR_RENDITION); + } + protected static AVMRemote getAVMRemote() { final FacesContext fc = diff --git a/source/java/org/alfresco/web/forms/FormProcessor.java b/source/java/org/alfresco/web/forms/FormProcessor.java index 7d5ecc0f0d..25861d2c14 100644 --- a/source/java/org/alfresco/web/forms/FormProcessor.java +++ b/source/java/org/alfresco/web/forms/FormProcessor.java @@ -43,13 +43,13 @@ public interface FormProcessor ///////////////////////////////////////////////////////////////////////////// /** - * Generates a user interface for inputing data into a form. + * Processes a user interface for inputing data into a form. * * @param instanceData provides the xml instance data if available. * @param form the form to generate for * @param out the writer to write the output to. */ - public void generate(final FormProcessor.InstanceData instanceData, - final Form form, - final Writer out); + public void process(final FormProcessor.InstanceData instanceData, + final Form form, + final Writer out); } diff --git a/source/java/org/alfresco/web/forms/FormsService.java b/source/java/org/alfresco/web/forms/FormsService.java index 9d35e4f5d2..120903f06b 100644 --- a/source/java/org/alfresco/web/forms/FormsService.java +++ b/source/java/org/alfresco/web/forms/FormsService.java @@ -238,7 +238,8 @@ public final class FormsService final RenderingEngine tom = (RenderingEngine) c.newInstance(tomNodeRef, this.nodeService, this.contentService); LOGGER.debug("loaded form data renderer type " + tom.getClass().getName() + - " for extension " + tom.getFileExtension() + ", " + tomNodeRef); + " for extension " + tom.getFileExtensionForRendition() + + ", " + tomNodeRef); tt.addRenderingEngine(tom); } catch (Exception e) @@ -271,19 +272,19 @@ public final class FormsService { // get the node ref of the node that will contain the content final String renditionFileName = - this.stripExtension(formInstanceDataFileName) + "." + re.getFileExtension(); - final OutputStream fileOut = this.avmService.createFile(parentPath, renditionFileName); + (this.stripExtension(formInstanceDataFileName) + + "." + re.getFileExtensionForRendition()); + final OutputStream out = this.avmService.createFile(parentPath, renditionFileName); final String renditionAvmPath = parentPath + '/' + renditionFileName; if (LOGGER.isDebugEnabled()) LOGGER.debug("Created file node for file: " + renditionAvmPath); - final OutputStreamWriter out = new OutputStreamWriter(fileOut); final HashMap parameters = this.getRenderingEngineParameters(formInstanceDataFileName, - renditionFileName, - parentPath); - re.generate(formInstanceData, parameters, out); + renditionFileName, + parentPath); + re.render(formInstanceData, parameters, out); out.close(); final NodeRef renditionNodeRef = @@ -335,7 +336,8 @@ public final class FormsService for (RenderingEngine re : form.getRenderingEngines()) { final String renditionFileName = - this.stripExtension(formInstanceDataFileName) + "." + re.getFileExtension(); + (this.stripExtension(formInstanceDataFileName) + "." + + re.getFileExtensionForRendition()); if (LOGGER.isDebugEnabled()) LOGGER.debug("regenerating file node for : " + formInstanceDataFileName + @@ -354,13 +356,12 @@ public final class FormsService out = this.avmService.createFile(parentPath, renditionFileName); } - final OutputStreamWriter writer = new OutputStreamWriter(out); final HashMap parameters = this.getRenderingEngineParameters(formInstanceDataFileName, renditionFileName, parentPath); - re.generate(formInstanceData, parameters, writer); - writer.close(); + re.render(formInstanceData, parameters, out); + out.close(); LOGGER.debug("generated " + renditionFileName + " using " + re); } diff --git a/source/java/org/alfresco/web/forms/FreeMarkerRenderingEngine.java b/source/java/org/alfresco/web/forms/FreeMarkerRenderingEngine.java index f03dbf5f61..567ce7ae0c 100644 --- a/source/java/org/alfresco/web/forms/FreeMarkerRenderingEngine.java +++ b/source/java/org/alfresco/web/forms/FreeMarkerRenderingEngine.java @@ -56,14 +56,14 @@ public class FreeMarkerRenderingEngine } /** - * Generates the rendition using the configured freemarker template. This + * Renders the rendition using the configured freemarker template. This * provides a root map to the freemarker template which places the xml document, and * a variable named alfresco at the root. the alfresco variable contains a hash of * all parameters and all extension functions. */ - public void generate(final Document xmlContent, - final Map parameters, - final Writer out) + public void render(final Document xmlContent, + final Map parameters, + final OutputStream out) throws IOException, RenderingEngine.RenderingException { @@ -200,9 +200,10 @@ public class FreeMarkerRenderingEngine }; // process the form + final Writer writer = new OutputStreamWriter(out); try { - t.process(rootModel, out); + t.process(rootModel, writer); } catch (final TemplateException te) { @@ -211,7 +212,7 @@ public class FreeMarkerRenderingEngine } finally { - out.flush(); + writer.flush(); } } } diff --git a/source/java/org/alfresco/web/forms/RenderingEngine.java b/source/java/org/alfresco/web/forms/RenderingEngine.java index 88a428abb7..083fc7fb30 100644 --- a/source/java/org/alfresco/web/forms/RenderingEngine.java +++ b/source/java/org/alfresco/web/forms/RenderingEngine.java @@ -18,8 +18,8 @@ package org.alfresco.web.forms; import org.alfresco.service.cmr.repository.NodeRef; import java.io.IOException; +import java.io.OutputStream; import java.io.Serializable; -import java.io.Writer; import java.util.Map; import org.w3c.dom.Document; @@ -50,20 +50,25 @@ public interface RenderingEngine ///////////////////////////////////////////////////////////////////////////// - /** the noderef associated with this output method */ + /** + * XXXarielb this shouldn't be in the interface... i'll figure out a + * different id scheme once i make rendering engines configurable. + * + * the noderef associated with this output method + */ public NodeRef getNodeRef(); /** - * Serializes the xml data in to a presentation format. + * Renders the xml data in to a presentation format. * - * @param xmlContent the xml content to serialize + * @param formInstanceData the xml content to serialize * @param form the form that collected the xml content. - * @param sandBoxUrl the url of the current sandbox - * @param out the writer to serialize to. + * @param parameters the set of parameters to the rendering engine + * @param out the output stream to serialize to. */ - public void generate(final Document xmlContent, - final Map parameters, - final Writer out) + public void render(final Document formInstanceData, + final Map parameters, + final OutputStream out) throws IOException, RenderingException; /** @@ -71,7 +76,16 @@ public interface RenderingEngine * output method. * * @return the file extension to use when generating content for this - * output method, such as html, rss, pdf. + * output method, such as html, xml, pdf. */ - public String getFileExtension(); + public String getFileExtensionForRendition(); + + /** + * Returns the mimetype to use when generating content for this + * output method. + * + * @return the mimetype to use when generating content for this + * output method, such as text/html, text/xml, application/pdf. + */ + public String getMimetypeForRendition(); } diff --git a/source/java/org/alfresco/web/forms/XSLFORenderingEngine.java b/source/java/org/alfresco/web/forms/XSLFORenderingEngine.java new file mode 100644 index 0000000000..c4b1926e29 --- /dev/null +++ b/source/java/org/alfresco/web/forms/XSLFORenderingEngine.java @@ -0,0 +1,93 @@ +/* + * 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.io.*; +import java.util.*; +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.cmr.repository.ContentService; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.w3c.dom.*; +import org.xml.sax.SAXException; +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.Fop; +import org.apache.fop.apps.FOPException; +import org.apache.fop.apps.FopFactory; +import org.apache.fop.apps.FormattingResults; +import org.apache.fop.apps.MimeConstants; +import org.apache.fop.apps.PageSequenceResults; + +/** + * A rendering engine which uses xsl-fo templates to generate renditions of + * form instance data. + * + * @author Ariel Backenroth + */ +public class XSLFORenderingEngine + extends XSLTRenderingEngine +{ + + private static final Log LOGGER = LogFactory.getLog(XSLFORenderingEngine.class); + + public XSLFORenderingEngine(final NodeRef nodeRef, + final NodeService nodeService, + final ContentService contentService) + { + super(nodeRef, nodeService, contentService); + } + + public void generate(final Document xmlContent, + final Map parameters, + final OutputStream out) + throws IOException, + RenderingEngine.RenderingException + { + try + { + final FopFactory fopFactory = FopFactory.newInstance(); + final FOUserAgent foUserAgent = fopFactory.newFOUserAgent(); + final Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out); + + // Resulting SAX events (the generated FO) must be piped through to FOP + final Result result = new SAXResult(fop.getDefaultHandler()); + + super.render(new DOMSource(xmlContent), parameters, result); + + // Result processing + FormattingResults foResults = fop.getResults(); + java.util.List pageSequences = foResults.getPageSequences(); + for (java.util.Iterator it = pageSequences.iterator(); it.hasNext();) + { + PageSequenceResults pageSequenceResults = (PageSequenceResults)it.next(); + System.out.println("PageSequence " + + (String.valueOf(pageSequenceResults.getID()).length() > 0 + ? pageSequenceResults.getID() : "") + + " generated " + pageSequenceResults.getPageCount() + " pages."); + } + System.out.println("Generated " + foResults.getPageCount() + " pages in total."); + } + catch (FOPException fope) + { + } + } +} \ No newline at end of file diff --git a/source/java/org/alfresco/web/forms/xforms/XFormsProcessor.java b/source/java/org/alfresco/web/forms/xforms/XFormsProcessor.java index 9aa316073f..01c83c8766 100644 --- a/source/java/org/alfresco/web/forms/xforms/XFormsProcessor.java +++ b/source/java/org/alfresco/web/forms/xforms/XFormsProcessor.java @@ -45,9 +45,9 @@ public class XFormsProcessor * Generates html text which bootstraps the JavaScript code that will * call back into the XFormsBean and get the xform and build the ui. */ - public void generate(final InstanceData instanceData, - final Form tt, - final Writer out) + public void process(final InstanceData instanceData, + final Form tt, + final Writer out) { final FormsService ts = FormsService.getInstance(); final FacesContext fc = FacesContext.getCurrentInstance(); 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 f94ddc9048..bb462e7b2c 100644 --- a/source/java/org/alfresco/web/ui/wcm/component/UIFormProcessor.java +++ b/source/java/org/alfresco/web/ui/wcm/component/UIFormProcessor.java @@ -88,7 +88,7 @@ public class UIFormProcessor extends SelfRenderingComponent final Form form = this.getForm(); final FormProcessor.InstanceData formInstanceData = this.getFormInstanceData(); final FormProcessor tim = form.getFormProcessors().get(0); - tim.generate(formInstanceData, form, out); + tim.process(formInstanceData, form, out); } // ------------------------------------------------------------------------------ diff --git a/source/test-resources/xforms/demos/press-release/press-release.xsd b/source/test-resources/xforms/demos/press-release/press-release.xsd index 089a15044f..4598c39124 100644 --- a/source/test-resources/xforms/demos/press-release/press-release.xsd +++ b/source/test-resources/xforms/demos/press-release/press-release.xsd @@ -35,16 +35,6 @@ Describes a press release and related assets. - - - - - - - - - - diff --git a/source/web/WEB-INF/faces-config-beans.xml b/source/web/WEB-INF/faces-config-beans.xml index 8016ae473a..f7a40c5104 100644 --- a/source/web/WEB-INF/faces-config-beans.xml +++ b/source/web/WEB-INF/faces-config-beans.xml @@ -2054,6 +2054,10 @@ contentService #{ContentService} + + mimetypeService + #{MimetypeService} + 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 7d0c387574..1f76054d8c 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 @@ -84,19 +84,32 @@ else value="#{WizardManager.bean.renderingEngineTypeChoices}"/> + + + + + + - - + styleClass="wizardButton" + disabled="#{WizardManager.bean.addToListDisabled}" /> + + + + + +