- removing templating config file

- renamed create xml content type to create form
- writing xsds and xsls into the data dictionary
- using search to implement TemplatingService.getTempalteTypes()
- adding fields to create form screen for the root tag name to use within the schema and for a display name within the dropdown (friendly non file name name)
- using aspects from the wcmModel to categorize and relate templates and templateoutputmethods 



git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/WCM-DEV2/root@4014 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Ariel Backenroth
2006-10-04 05:04:35 +00:00
parent cea94661de
commit 76fa148539
8 changed files with 255 additions and 270 deletions

View File

@@ -238,7 +238,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
create_xml_content_type=Create Form
add_multiple_files=Add Multiple Files
import_directory=Import Directory
advanced_space_wizard=Advanced Space Wizard
@@ -641,12 +641,14 @@ 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_title=Create Form Wizard
create_xml_content_type_desc=Create Form
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.
schema=Schema
schema_root_tag_name=Root Tag
edit_xml_schema=Edit XML Schema
template_type=Template Type
configure_presentation_templates=Configure Presentation Templates

View File

@@ -27,6 +27,7 @@ import org.alfresco.config.Config;
import org.alfresco.config.ConfigElement;
import org.alfresco.config.ConfigService;
import org.alfresco.model.ContentModel;
import org.alfresco.model.WCMModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.ContentService;
@@ -60,6 +61,8 @@ public class CreateXmlContentTypeWizard extends BaseWizardBean
private final static Log LOGGER =
LogFactory.getLog(CreateXmlContentTypeWizard.class);
private String schemaRootTagName;
private String templateName;
private String presentationTemplateType;
protected ContentService contentService;
@@ -70,19 +73,16 @@ public class CreateXmlContentTypeWizard extends BaseWizardBean
protected String finishImpl(FacesContext context, String outcome)
throws Exception
{
final TemplatingService ts = TemplatingService.getInstance();
// get the node ref of the node that will contain the content
NodeRef containerNodeRef;
String nodeId = this.navigator.getCurrentNodeId();
if (nodeId == null)
{
containerNodeRef = this.nodeService.getRootNode(Repository.getStoreRef());
}
else
{
containerNodeRef = new NodeRef(Repository.getStoreRef(), nodeId);
}
final NodeRef contentFormsNodeRef = ts.getContentFormsNodeRef();
FileInfo fileInfo = this.fileFolderService.create(containerNodeRef,
final FileInfo folderInfo =
this.fileFolderService.create(contentFormsNodeRef,
this.getTemplateName(),
ContentModel.TYPE_FOLDER);
FileInfo fileInfo =
this.fileFolderService.create(folderInfo.getNodeRef(),
this.getSchemaFileName(),
ContentModel.TYPE_CONTENT);
final NodeRef schemaFileNodeRef = fileInfo.getNodeRef();
@@ -92,14 +92,15 @@ public class CreateXmlContentTypeWizard extends BaseWizardBean
this.getSchemaFileName());
// get a writer for the content and put the file
ContentWriter writer = contentService.getWriter(schemaFileNodeRef,
ContentModel.PROP_CONTENT, true);
ContentWriter writer = this.contentService.getWriter(schemaFileNodeRef,
ContentModel.PROP_CONTENT,
true);
// set the mimetype and encoding
writer.setMimetype("text/xml");
writer.setEncoding("UTF-8");
writer.putContent(this.getSchemaFile());
fileInfo = this.fileFolderService.create(containerNodeRef,
fileInfo = this.fileFolderService.create(folderInfo.getNodeRef(),
this.getPresentationTemplateFileName(),
ContentModel.TYPE_CONTENT);
final NodeRef presentationTemplateFileNodeRef = fileInfo.getNodeRef();
@@ -109,22 +110,29 @@ public class CreateXmlContentTypeWizard extends BaseWizardBean
this.getPresentationTemplateFileName());
// get a writer for the content and put the file
writer = contentService.getWriter(presentationTemplateFileNodeRef,
ContentModel.PROP_CONTENT, true);
writer = this.contentService.getWriter(presentationTemplateFileNodeRef,
ContentModel.PROP_CONTENT,
true);
// set the mimetype and encoding
writer.setMimetype("text/xml");
writer.setEncoding("UTF-8");
writer.putContent(this.getPresentationTemplateFile());
final TemplatingService ts = TemplatingService.getInstance();
final String rootTagName =
this.getSchemaFileName().replaceAll("([^\\.])\\..+", "$1");
final TemplateType tt = ts.newTemplateType(rootTagName, schemaFileNodeRef);
if (this.getPresentationTemplateFile() != null)
{
tt.addOutputMethod(new XSLTOutputMethod(presentationTemplateFileNodeRef));
}
ts.registerTemplateType(tt);
Map<QName, Serializable> props = new HashMap<QName, Serializable>(3, 1.0f);
props.put(WCMModel.PROP_SCHEMA_ROOT_TAG_NAME, this.getSchemaRootTagName());
props.put(WCMModel.ASSOC_TEMPLATE_OUTPUT_METHODS, presentationTemplateFileNodeRef);
this.nodeService.addAspect(schemaFileNodeRef, WCMModel.ASPECT_TEMPLATE, props);
// apply the titled aspect - title and description
props = new HashMap<QName, Serializable>(3, 1.0f);
props.put(ContentModel.PROP_TITLE, this.getTemplateName());
props.put(ContentModel.PROP_DESCRIPTION, "");
this.nodeService.addAspect(schemaFileNodeRef, ContentModel.ASPECT_TITLED, props);
props = new HashMap<QName, Serializable>(3, 1.0f);
props.put(WCMModel.PROP_TEMPLATE_OUTPUT_METHOD_TYPE, this.getPresentationTemplateType());
props.put(WCMModel.PROP_TEMPLATE_SOURCE, schemaFileNodeRef);
this.nodeService.addAspect(presentationTemplateFileNodeRef, WCMModel.ASPECT_TEMPLATE_OUTPUT_METHOD, props);
// return the default outcome
return outcome;
@@ -137,6 +145,8 @@ public class CreateXmlContentTypeWizard extends BaseWizardBean
this.removeUploadedSchemaFile();
this.removeUploadedPresentationTemplateFile();
this.schemaRootTagName = null;
this.templateName = null;
}
@Override
@@ -300,6 +310,42 @@ public class CreateXmlContentTypeWizard extends BaseWizardBean
return this.getFile("pt");
}
/**
* Sets the root tag name to use when processing the schema.
*/
public void setSchemaRootTagName(final String schemaRootTagName)
{
this.schemaRootTagName = schemaRootTagName;
}
/**
* @return the root tag name to use when processing the schema.
*/
public String getSchemaRootTagName()
{
return (this.schemaRootTagName == null && this.getSchemaFileName() != null
? this.getSchemaFileName().replaceAll("([^\\.])\\..+", "$1")
: this.schemaRootTagName);
}
/**
* Sets the human friendly name for this template.
*/
public void setTemplateName(final String templateName)
{
this.templateName = templateName;
}
/**
* @return the human friendly name for this template.
*/
public String getTemplateName()
{
return (this.templateName == null && this.getSchemaFileName() != null
? this.getSchemaFileName().replaceAll("(.+)\\..*", "$1")
: this.templateName);
}
/**
* @return Returns a list of mime types to allow the user to select from
*/

View File

@@ -20,7 +20,6 @@ import org.w3c.dom.Document;
import java.util.List;
import java.net.URI;
import java.io.Serializable;
//import org.alfresco.service.cmr.repository.NodeRef;
/**
* Encapsulation of a template type.
@@ -32,15 +31,12 @@ public interface TemplateType
/** the name of the template, which must be unique within the TemplatingService */
public String getName();
/** the root tag to use within the schema */
public String getRootTagName();
/** the xml schema for this template type */
public Document getSchema();
// public String /* URI */ getSchemaURI();
// public void setSchemaNodeRef(final NodeRef nodeRef);
//
// public NodeRef getSchemaNodeRef();
//XXXarielb not used currently and not sure if it's necessary...
// public void addInputMethod(final TemplateInputMethod in);

View File

@@ -36,11 +36,12 @@ import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.model.ContentModel;
import org.alfresco.model.WCMModel;
import org.alfresco.util.TempFileProvider;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.search.*;
import org.alfresco.service.cmr.model.*;
import org.alfresco.service.namespace.NamespaceService;
import javax.faces.context.FacesContext;
@@ -52,121 +53,6 @@ import org.alfresco.web.bean.repository.Repository;
*/
public final class TemplatingService implements Serializable
{
////////////////////////////////////////////////////////////////////////////
/**
* Encapsulation of configuration file management.
*/
private static class Configuration
{
/** 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
* <tt>templating_config.xml</tt> at the root of the data dictionary.
*
* @return the configuration file, which is currently all the
* <tt>TemplateTypes</tt> serialized using object serialization.
*/
private static NodeRef getConfigFile()
{
if (configFileNodeRef == null)
{
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<NodeRef> 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
{
Configuration.configFileNodeRef =
ts.fileFolderService.create(dataDictionaryNodeRef,
"templating_configuration.xml",
ContentModel.TYPE_CONTENT).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";
}
return Configuration.configFileNodeRef;
}
/**
* Load the configuration file into the templating service.
*/
public static void load()
throws IOException
{
final TemplatingService ts = TemplatingService.INSTANCE;
final NodeRef configFileNodeRef = getConfigFile();
FacesContext fc = FacesContext.getCurrentInstance();
final ContentReader contentReader = ts.contentService.getReader(configFileNodeRef,
ContentModel.TYPE_CONTENT);
if (contentReader == null)
LOGGER.debug("templating_config.xml is empty");
else
{
LOGGER.debug("parsing templating_config.xml");
final InputStream contentIn = contentReader.getContentInputStream();
final ObjectInputStream in = new ObjectInputStream(contentIn);
try
{
while (true)
{
try
{
final TemplateType tt = (TemplateType)in.readObject();
TemplatingService.INSTANCE.registerTemplateType(tt);
}
catch (EOFException eof)
{
break;
}
}
in.close();
}
catch (ClassNotFoundException cnfe)
{
TemplatingService.LOGGER.error(cnfe);
}
}
loaded = true;
}
/**
* Save the current state of the templating service to the configuration file.
*/
public static void save()
throws IOException
{
final TemplatingService ts = TemplatingService.INSTANCE;
FacesContext fc = FacesContext.getCurrentInstance();
final NodeRef configFileNodeRef = getConfigFile();
final OutputStream contentOut = ts.contentService.getWriter(configFileNodeRef, ContentModel.TYPE_CONTENT, true).getContentOutputStream();
final ObjectOutputStream out = new ObjectOutputStream(contentOut);
for (TemplateType tt : TemplatingService.INSTANCE.getTemplateTypes())
{
out.writeObject(tt);
}
out.close();
}
}
////////////////////////////////////////////////////////////////////////////
/**
* temporary location of the property on nodes that are xml files created
@@ -197,6 +83,8 @@ public final class TemplatingService implements Serializable
private final NamespaceService namespaceService;
private final SearchService searchService;
private NodeRef contentFormsNodeRef;
/** instantiated using spring */
public TemplatingService(final ContentService contentService,
final NodeService nodeService,
@@ -218,46 +106,78 @@ public final class TemplatingService implements Serializable
/** Provides the templating service instance, loads config if necessary */
public static TemplatingService getInstance()
{
if (!Configuration.loaded)
{
LOGGER.debug("loading configuration");
try
{
Configuration.load();
}
catch (Throwable t)
{
LOGGER.error(t);
t.printStackTrace();
}
return TemplatingService.INSTANCE;
}
return TemplatingService.INSTANCE;
/**
* @return the cached reference to the WCM Content Forms folder
*/
public NodeRef getContentFormsNodeRef()
{
if (this.contentFormsNodeRef == null)
{
final FacesContext fc = FacesContext.getCurrentInstance();
final String xpath = (Application.getRootPath(fc) + "/" +
Application.getGlossaryFolderName(fc) + "/" +
Application.getContentFormsFolderName(fc));
LOGGER.debug("locating content forms at " + xpath);
final List<NodeRef> results =
searchService.selectNodes(nodeService.getRootNode(Repository.getStoreRef()),
xpath,
null,
namespaceService,
false);
this.contentFormsNodeRef = (results != null && results.size() == 1 ? results.get(0) : null);
}
return this.contentFormsNodeRef;
}
/** returns all registered template types */
public Collection<TemplateType> getTemplateTypes()
{
return this.templateTypes.values();
try
{
final SearchParameters sp = new SearchParameters();
sp.addStore(Repository.getStoreRef());
sp.setLanguage(SearchService.LANGUAGE_LUCENE);
final String q = "ASPECT:\"" + WCMModel.ASPECT_TEMPLATE + "\"";
sp.setQuery(q);
LOGGER.debug("running query [" + q + "]");
final ResultSet rs = this.searchService.query(sp);
LOGGER.debug("received " + rs.length() + " results");
final Collection<TemplateType> result = new LinkedList<TemplateType>();
for (ResultSetRow row : rs)
{
final NodeRef nodeRef = row.getNodeRef();
result.add(this.newTemplateType(nodeRef));
}
return result;
}
catch (RuntimeException re)
{
LOGGER.error(re);
throw re;
}
}
/** return the template type by name or <tt>null</tt> if not found */
public TemplateType getTemplateType(final String name)
{
return this.templateTypes.get(name);
}
/** registers a template type. if one exists with the same name, it is replaced */
public void registerTemplateType(final TemplateType tt)
{
this.templateTypes.put(tt.getName(), tt);
try
{
Configuration.save();
final SearchParameters sp = new SearchParameters();
sp.addStore(Repository.getStoreRef());
sp.setLanguage(SearchService.LANGUAGE_LUCENE);
sp.setQuery("ASPECT:\"" + WCMModel.ASPECT_TEMPLATE +
"\" AND @" + Repository.escapeQName(ContentModel.PROP_TITLE) +
":\"" + name + "\"");
final ResultSet rs = this.searchService.query(sp);
return (rs.length() == 1 ? this.newTemplateType(rs.getNodeRef(0)) : null);
}
catch (IOException ioe)
catch (RuntimeException re)
{
LOGGER.error(ioe);
LOGGER.error(re);
throw re;
}
}
@@ -267,10 +187,21 @@ public final class TemplatingService implements Serializable
* the template type implementation can be configured for the system,
* or specified in the gui.
*/
public TemplateType newTemplateType(final String name,
final NodeRef schemaNodeRef)
private TemplateType newTemplateType(final NodeRef schemaNodeRef)
{
return new TemplateTypeImpl(name, schemaNodeRef);
LOGGER.debug("creating template type for " + schemaNodeRef);
final String title = (String)
this.nodeService.getProperty(schemaNodeRef, ContentModel.PROP_TITLE);
LOGGER.debug("title is " + title);
final String schemaRootTagName = (String)
this.nodeService.getProperty(schemaNodeRef, WCMModel.PROP_SCHEMA_ROOT_TAG_NAME);
LOGGER.debug("root tag name is " + schemaRootTagName);
TemplateType tt = new TemplateTypeImpl(title, schemaNodeRef, schemaRootTagName);
final NodeRef xslNodeRef = (NodeRef)
this.nodeService.getProperty(schemaNodeRef, WCMModel.ASSOC_TEMPLATE_OUTPUT_METHODS);
LOGGER.debug("xsl noderef is " + xslNodeRef);
tt.addOutputMethod(new XSLTOutputMethod(xslNodeRef));
return tt;
}
/** utility function for creating a document */

View File

@@ -36,6 +36,7 @@ public class TemplateTypeImpl
private transient Document schema;
private final NodeRef schemaNodeRef;
private final String name;
private final String rootTagName;
private final LinkedList<TemplateOutputMethod> outputMethods =
new LinkedList<TemplateOutputMethod>();
private final static LinkedList<TemplateInputMethod> INPUT_METHODS =
@@ -47,10 +48,12 @@ public class TemplateTypeImpl
}
public TemplateTypeImpl(final String name,
final NodeRef schemaNodeRef)
final NodeRef schemaNodeRef,
final String rootTagName)
{
this.name = name;
this.schemaNodeRef = schemaNodeRef;
this.rootTagName = rootTagName;
}
public String getName()
@@ -58,19 +61,9 @@ public class TemplateTypeImpl
return this.name;
}
public String /* URI */ getSchemaURI()
public String getRootTagName()
{
final javax.faces.context.FacesContext fc =
javax.faces.context.FacesContext.getCurrentInstance();
final javax.servlet.http.HttpSession session = (javax.servlet.http.HttpSession)
fc.getExternalContext().getSession(true);
org.alfresco.web.bean.repository.User user = (org.alfresco.web.bean.repository.User)
session.getAttribute(org.alfresco.web.app.servlet.AuthenticationHelper.AUTHENTICATION_USER);
String result = DownloadContentServlet.generateDownloadURL(this.schemaNodeRef, this.name + ".xsd");
result += "?ticket=" + user.getTicket();
return result;
return this.rootTagName;
}
public Document getSchema()

View File

@@ -301,7 +301,7 @@ public class XFormsBean
LOGGER.debug("building xform for schema " + tt.getName());
final Document result = builder.buildForm(xmlContent,
schemaDocument,
tt.getName());
tt.getRootTagName());
LOGGER.debug("generated xform: " + result);
// LOGGER.debug(ts.writeXMLToString(result));
return result;

View File

@@ -2076,6 +2076,14 @@
<property-name>fileFolderService</property-name>
<value>#{FileFolderService}</value>
</managed-property>
<managed-property>
<property-name>searchService</property-name>
<value>#{SearchService}</value>
</managed-property>
<managed-property>
<property-name>namespaceService</property-name>
<value>#{NamespaceService}</value>
</managed-property>
<managed-property>
<property-name>navigator</property-name>
<value>#{NavigationBean}</value>

View File

@@ -84,10 +84,10 @@
<h:panelGrid id="panel_grid_2"
columns="3" cellpadding="3" cellspacing="3" border="0">
<h:graphicImage id="required_image_schema"
<h:graphicImage id="graphic_image_schema"
value="/images/icons/required_field.gif" alt="Required Field" />
<h:outputText id="output_text_schema"
value="Schema:"/>
value="#{msg.schema}:"/>
<h:column id="column_schema">
<%
FileUploadBean upload = (FileUploadBean)
@@ -111,11 +111,20 @@ if (upload == null || upload.getFile() == null)
<a:actionLink id="action_link_remove_schema"
image="/images/icons/delete.gif"
value="#{msg.remove}"
action="#{WizardManager.bean.removeUploadedFile}"
action="#{WizardManager.bean.removeUploadedSchemaFile}"
showLink="false"
target="top"/>
<%
}
%>
</h:column>
<h:graphicImage id="graphic_image_root_tag_name"
value="/images/icons/required_field.gif" alt="Required Field" />
<h:outputText id="output_text_root_tag_name" value="#{msg.schema_root_tag_name}:"/>
<h:inputText id="schema-root-tag-name" value="#{WizardManager.bean.schemaRootTagName}"
maxlength="1024" size="35"/>
<h:graphicImage id="graphic_image_name" value="/images/icons/required_field.gif" alt="Required Field" />
<h:outputText id="output_text_name" value="#{msg.name}:"/>
<h:inputText id="file-name" value="#{WizardManager.bean.templateName}"
maxlength="1024" size="35"/>
</h:panelGrid>