diff --git a/config/alfresco/messages/webclient.properties b/config/alfresco/messages/webclient.properties index 6266c85a09..637dcf81b0 100644 --- a/config/alfresco/messages/webclient.properties +++ b/config/alfresco/messages/webclient.properties @@ -233,6 +233,7 @@ remove_user=Remove User create_space=Create Space add_content=Add Content create_content=Create Content +create_xml_content_type=Create XML Content Type add_multiple_files=Add Multiple Files import_directory=Import Directory advanced_space_wizard=Advanced Space Wizard @@ -634,6 +635,16 @@ select_type=Select Type content=Content text_content=Plain Text Content html_content=HTML Content +xml_content=XML Content +create_xml_content_type_title=Create XML Content Type Wizard +create_xml_content_type_desc=Create XML Content Type +create_xml_content_type_step1_title=Upload an XML Schema +create_xml_content_type_step1_desc=Upload an XML Schema +create_xml_content_type_step2_title=Edit the XML Schema +create_xml_content_type_step2_desc=This is the generated XForm based on the schema provided. +edit_xml_schema=Edit XML Schema +template_type=Template Type +configure_presentation_templates=Configure Presentation Templates # Rule and Action Wizard messages run_action_title=Run Action Wizard diff --git a/source/java/org/alfresco/web/bean/CheckinCheckoutBean.java b/source/java/org/alfresco/web/bean/CheckinCheckoutBean.java index 3359683f70..365bc43134 100644 --- a/source/java/org/alfresco/web/bean/CheckinCheckoutBean.java +++ b/source/java/org/alfresco/web/bean/CheckinCheckoutBean.java @@ -46,6 +46,8 @@ import org.alfresco.web.app.context.UIContextService; import org.alfresco.web.app.servlet.DownloadContentServlet; import org.alfresco.web.bean.repository.Node; import org.alfresco.web.bean.repository.Repository; +import org.alfresco.web.templating.OutputUtil; +import org.alfresco.web.templating.TemplatingService; import org.alfresco.web.ui.common.Utils; import org.alfresco.web.ui.common.component.UIActionLink; import org.apache.commons.logging.Log; @@ -375,8 +377,8 @@ public class CheckinCheckoutBean */ private Node setupContentDocument(String id) { - if (logger.isDebugEnabled()) - logger.debug("Setup for action, setting current document to: " + id); + if (LOGGER.isDebugEnabled()) + LOGGER.debug("Setup for action, setting current document to: " + id); Node node = null; @@ -426,14 +428,14 @@ public class CheckinCheckoutBean tx = Repository.getUserTransaction(FacesContext.getCurrentInstance()); tx.begin(); - if (logger.isDebugEnabled()) - logger.debug("Trying to checkout content node Id: " + node.getId()); + if (LOGGER.isDebugEnabled()) + LOGGER.debug("Trying to checkout content node Id: " + node.getId()); // checkout the node content to create a working copy - if (logger.isDebugEnabled()) + if (LOGGER.isDebugEnabled()) { - logger.debug("Checkout copy location: " + getCopyLocation()); - logger.debug("Selected Space Id: " + this.selectedSpaceId); + LOGGER.debug("Checkout copy location: " + getCopyLocation()); + LOGGER.debug("Selected Space Id: " + this.selectedSpaceId); } NodeRef workingCopyRef; if (getCopyLocation().equals(COPYLOCATION_OTHER) && this.selectedSpaceId != null) @@ -477,7 +479,7 @@ public class CheckinCheckoutBean } else { - logger.warn("WARNING: checkoutFile called without a current Document!"); + LOGGER.warn("WARNING: checkoutFile called without a current Document!"); } return outcome; @@ -508,7 +510,7 @@ public class CheckinCheckoutBean } else { - logger.warn("WARNING: checkoutFileOK called without a current WorkingDocument!"); + LOGGER.warn("WARNING: checkoutFileOK called without a current WorkingDocument!"); } return outcome; @@ -533,7 +535,7 @@ public class CheckinCheckoutBean } else { - logger.warn("WARNING: editFileOK called without a current Document!"); + LOGGER.warn("WARNING: editFileOK called without a current Document!"); } return outcome; @@ -572,12 +574,18 @@ public class CheckinCheckoutBean MimetypeMap.MIMETYPE_JAVASCRIPT.equals(mimetype)) { // make content available to the editing screen - setEditorOutput(reader.getContentString()); + String contentString = reader.getContentString(); + setDocumentContent(contentString); + setEditorOutput(contentString); + + // navigate to appropriate screen + FacesContext fc = FacesContext.getCurrentInstance(); + this.navigator.setupDispatchContext(node); + String s = (MimetypeMap.MIMETYPE_XML.equals(mimetype) + ? "dialog:editXmlInline" + : "dialog:editTextInline"); + fc.getApplication().getNavigationHandler().handleNavigation(fc, null, s); - // navigate to appropriate screen - FacesContext fc = FacesContext.getCurrentInstance(); - this.navigator.setupDispatchContext(node); - fc.getApplication().getNavigationHandler().handleNavigation(fc, null, "dialog:editTextInline"); } else { @@ -620,15 +628,23 @@ public class CheckinCheckoutBean tx = Repository.getUserTransaction(FacesContext.getCurrentInstance()); tx.begin(); - if (logger.isDebugEnabled()) - logger.debug("Trying to update content node Id: " + node.getId()); + if (LOGGER.isDebugEnabled()) + LOGGER.debug("Trying to update content node Id: " + node.getId()); // get an updating writer that we can use to modify the content on the current node ContentWriter writer = this.contentService.getWriter(node.getNodeRef(), ContentModel.PROP_CONTENT, true); writer.putContent(this.editorOutput); - + // commit the transaction tx.commit(); + + if (nodeService.getProperty(node.getNodeRef(), + TemplatingService.TT_QNAME) != null) + { + OutputUtil.regenerate(node.getNodeRef(), + this.contentService, + this.nodeService); + } // clean up and clear action context clearUpload(); @@ -648,7 +664,7 @@ public class CheckinCheckoutBean } else { - logger.warn("WARNING: editInlineOK called without a current Document!"); + LOGGER.warn("WARNING: editInlineOK called without a current Document!"); } return outcome; @@ -681,7 +697,7 @@ public class CheckinCheckoutBean } else { - logger.warn("WARNING: undoCheckout called without a current WorkingDocument!"); + LOGGER.warn("WARNING: undoCheckout called without a current WorkingDocument!"); } return outcome; @@ -730,7 +746,7 @@ public class CheckinCheckoutBean } else { - logger.warn("WARNING: undoCheckout called without a current WorkingDocument!"); + LOGGER.warn("WARNING: undoCheckout called without a current WorkingDocument!"); } return outcome; @@ -755,8 +771,8 @@ public class CheckinCheckoutBean tx = Repository.getUserTransaction(context); tx.begin(); - if (logger.isDebugEnabled()) - logger.debug("Trying to checkin content node Id: " + node.getId()); + if (LOGGER.isDebugEnabled()) + LOGGER.debug("Trying to checkin content node Id: " + node.getId()); // we can either checkin the content from the current working copy node // which would have been previously updated by the user @@ -821,7 +837,7 @@ public class CheckinCheckoutBean } else { - logger.warn("WARNING: checkinFileOK called without a current Document!"); + LOGGER.warn("WARNING: checkinFileOK called without a current Document!"); } return outcome; @@ -846,8 +862,8 @@ public class CheckinCheckoutBean tx = Repository.getUserTransaction(context); tx.begin(); - if (logger.isDebugEnabled()) - logger.debug("Trying to update content node Id: " + node.getId()); + if (LOGGER.isDebugEnabled()) + LOGGER.debug("Trying to update content node Id: " + node.getId()); // get an updating writer that we can use to modify the content on the current node ContentWriter writer = this.contentService.getWriter(node.getNodeRef(), ContentModel.PROP_CONTENT, true); @@ -877,7 +893,7 @@ public class CheckinCheckoutBean } else { - logger.warn("WARNING: updateFileOK called without a current Document!"); + LOGGER.warn("WARNING: updateFileOK called without a current Document!"); } return outcome; @@ -922,7 +938,7 @@ public class CheckinCheckoutBean // ------------------------------------------------------------------------------ // Private data - private static Log logger = LogFactory.getLog(CheckinCheckoutBean.class); + private static final Log LOGGER = LogFactory.getLog(CheckinCheckoutBean.class); /** I18N messages */ private static final String MSG_ERROR_CHECKIN = "error_checkin"; diff --git a/source/java/org/alfresco/web/bean/content/CreateContentWizard.java b/source/java/org/alfresco/web/bean/content/CreateContentWizard.java index 881facb299..dd11533c0d 100644 --- a/source/java/org/alfresco/web/bean/content/CreateContentWizard.java +++ b/source/java/org/alfresco/web/bean/content/CreateContentWizard.java @@ -1,6 +1,23 @@ +/* + * 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.bean.content; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.ResourceBundle; @@ -18,9 +35,17 @@ import org.alfresco.web.app.Application; import org.alfresco.web.bean.repository.Node; import org.alfresco.web.data.IDataContainer; import org.alfresco.web.data.QuickSort; +import org.alfresco.web.templating.*; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.alfresco.model.ContentModel; +import org.alfresco.service.cmr.model.FileInfo; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.ContentWriter; +import java.io.OutputStreamWriter; +import org.alfresco.web.app.servlet.FacesHelper; + /** * Bean implementation for the "Create Content Wizard" dialog * @@ -28,12 +53,14 @@ import org.apache.commons.logging.LogFactory; */ public class CreateContentWizard extends BaseContentWizard { - protected String content = null; - - protected List createMimeTypes; - - private static Log logger = LogFactory.getLog(CreateContentWizard.class); - + protected String content = null; + protected String templateTypeName; + protected List createMimeTypes; + + private static final Log LOGGER = + LogFactory.getLog(CreateContentWizard.class); + + // ------------------------------------------------------------------------------ // Wizard implementation @@ -41,10 +68,28 @@ public class CreateContentWizard extends BaseContentWizard protected String finishImpl(FacesContext context, String outcome) throws Exception { - saveContent(null, this.content); - - // return the default outcome - return outcome; + LOGGER.debug("saving file content to " + this.fileName); + saveContent(null, this.content); + if (this.templateTypeName != null) + { + LOGGER.debug("generating template output for " + this.templateTypeName); + this.nodeService.setProperty(this.createdNode, + TemplatingService.TT_QNAME, + this.templateTypeName); + TemplatingService ts = TemplatingService.getInstance(); + TemplateType tt = this.getTemplateType(); + OutputUtil.generate(this.createdNode, + ts.parseXML(this.content), + tt, + this.fileName, + this.getContainerNodeRef(), + this.fileFolderService, + this.contentService, + this.nodeService); + } + + // return the default outcome + return outcome; } @Override @@ -54,6 +99,7 @@ public class CreateContentWizard extends BaseContentWizard this.content = null; this.inlineEdit = true; + this.templateTypeName = null; this.mimeType = MimetypeMap.MIMETYPE_HTML; } @@ -116,6 +162,20 @@ public class CreateContentWizard extends BaseContentWizard { this.content = content; } + + public List getCreateTemplateTypes() + { + Collection ttl = TemplatingService.getInstance().getTemplateTypes(); + List sil = new ArrayList(ttl.size()); + for (TemplateType tt : ttl) + { + sil.add(new SelectItem(tt.getName(), tt.getName())); + } + + QuickSort sorter = new QuickSort(sil, "label", true, IDataContainer.SORT_CASEINSENSITIVE); + sorter.sort(); + return sil; + } /** * @return Returns a list of mime types to allow the user to select from @@ -153,18 +213,37 @@ public class CreateContentWizard extends BaseContentWizard } else { - logger.warn("Could not find 'create-mime-types' configuration element"); + LOGGER.warn("Could not find 'create-mime-types' configuration element"); } } else { - logger.warn("Could not find 'Content Wizards' configuration section"); + LOGGER.warn("Could not find 'Content Wizards' configuration section"); } } return this.createMimeTypes; } + + public String getTemplateTypeName() + { + return this.templateTypeName; + } + + public TemplateType getTemplateType() + { + final TemplatingService ts = TemplatingService.getInstance(); + return ts.getTemplateType(this.getTemplateTypeName()); + } + + /** + * @param templateType Sets the currently selected template type + */ + public void setTemplateTypeName(final String templateTypeName) + { + this.templateTypeName = templateTypeName; + } /** * @return Returns the summary data for the wizard. diff --git a/source/java/org/alfresco/web/templating/TemplatingService.java b/source/java/org/alfresco/web/templating/TemplatingService.java index ad498580a3..e3fdb432fe 100644 --- a/source/java/org/alfresco/web/templating/TemplatingService.java +++ b/source/java/org/alfresco/web/templating/TemplatingService.java @@ -64,6 +64,7 @@ public final class TemplatingService /** indicates whether or not the configuration file has been loaded */ public static boolean loaded = false; + private static NodeRef configFileNodeRef = null; /** * locate the configuration file. currently it is stored as @@ -74,40 +75,36 @@ public final class TemplatingService */ private static NodeRef getConfigFile() { - final TemplatingService ts = TemplatingService.INSTANCE; - LOGGER.debug("loading config file"); - // get the template from the special Email Templates folder - FacesContext fc = FacesContext.getCurrentInstance(); - String xpath = (Application.getRootPath(fc) + "/" + - Application.getGlossaryFolderName(fc)); - NodeRef rootNodeRef = ts.nodeService.getRootNode(Repository.getStoreRef()); - List results = ts.searchService.selectNodes(rootNodeRef, xpath, null, ts.namespaceService, false); - if (results.size() != 1) - throw new RuntimeException("expected one result for " + xpath); - NodeRef dataDictionaryNodeRef = results.get(0); - LOGGER.debug("loaded data dictionary " + dataDictionaryNodeRef); - NodeRef configFileNodeRef = null; - try + if (configFileNodeRef == null) { - configFileNodeRef = ts.fileFolderService.create(dataDictionaryNodeRef, - "templating_configuration.xml", - ContentModel.TYPE_CONTENT).getNodeRef(); - } - catch (FileExistsException fee) - { - List l = ts.fileFolderService.search(dataDictionaryNodeRef, - "templating_configuration.xml", - true, - false, - false); - if (l.size() != 1) + final TemplatingService ts = TemplatingService.INSTANCE; + LOGGER.debug("loading config file"); + // get the template from the special Email Templates folder + FacesContext fc = FacesContext.getCurrentInstance(); + String xpath = (Application.getRootPath(fc) + "/" + + Application.getGlossaryFolderName(fc)); + NodeRef rootNodeRef = ts.nodeService.getRootNode(Repository.getStoreRef()); + List results = ts.searchService.selectNodes(rootNodeRef, xpath, null, ts.namespaceService, false); + if (results.size() != 1) + throw new RuntimeException("expected one result for " + xpath); + NodeRef dataDictionaryNodeRef = results.get(0); + LOGGER.debug("loaded data dictionary " + dataDictionaryNodeRef); + try { - throw new RuntimeException("expected one templating_configuration.xml in " + dataDictionaryNodeRef); + Configuration.configFileNodeRef = + ts.fileFolderService.create(dataDictionaryNodeRef, + "templating_configuration.xml", + ContentModel.TYPE_CONTENT).getNodeRef(); } - configFileNodeRef= l.get(0).getNodeRef(); + catch (FileExistsException fee) + { + Configuration.configFileNodeRef = + ts.fileFolderService.searchSimple(dataDictionaryNodeRef, "templating_configuration.xml"); + } + LOGGER.debug("loaded config file " + configFileNodeRef); + assert Configuration.configFileNodeRef != null : "unable to load templating_configuration.xml"; } - LOGGER.debug("loaded config file " + configFileNodeRef); - return configFileNodeRef; + return Configuration.configFileNodeRef; } /** @@ -119,30 +116,36 @@ public final class TemplatingService final TemplatingService ts = TemplatingService.INSTANCE; final NodeRef configFileNodeRef = getConfigFile(); FacesContext fc = FacesContext.getCurrentInstance(); - final InputStream contentIn = - ts.contentService.getReader(configFileNodeRef, - ContentModel.TYPE_CONTENT).getContentInputStream(); - final ObjectInputStream in = new ObjectInputStream(contentIn); - try + final ContentReader contentReader = ts.contentService.getReader(configFileNodeRef, + ContentModel.TYPE_CONTENT); + if (contentReader == null) + LOGGER.debug("templating_config.xml is empty"); + else { - while (true) - { - try + LOGGER.debug("parsing templating_config.xml"); + final InputStream contentIn = contentReader.getContentInputStream(); + final ObjectInputStream in = new ObjectInputStream(contentIn); + try + { + while (true) { - final TemplateType tt = (TemplateType)in.readObject(); - TemplatingService.INSTANCE.registerTemplateType(tt); + try + { + final TemplateType tt = (TemplateType)in.readObject(); + TemplatingService.INSTANCE.registerTemplateType(tt); + } + catch (EOFException eof) + { + break; + } + } - catch (EOFException eof) - { - break; - } - + in.close(); + } + catch (ClassNotFoundException cnfe) + { + TemplatingService.LOGGER.error(cnfe); } - in.close(); - } - catch (ClassNotFoundException cnfe) - { - TemplatingService.LOGGER.error(cnfe); } loaded = true; } diff --git a/source/web/WEB-INF/faces-config-beans.xml b/source/web/WEB-INF/faces-config-beans.xml index 8aa2677f2a..1e77863c63 100644 --- a/source/web/WEB-INF/faces-config-beans.xml +++ b/source/web/WEB-INF/faces-config-beans.xml @@ -2330,5 +2330,14 @@ #{ContentService} + + + + Bean that returns information on a node + + XFormsBean + org.alfresco.web.bean.ajax.XFormsBean + session +