mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
initial checkin of wcm forms management using xforms implemented by chiba. this currently uses chiba-web but will soon be replaced by our own uigenerator implemented by dojo!
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/WCM-DEV2/root@3444 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -570,7 +570,10 @@ public class CheckinCheckoutBean
|
||||
// navigate to appropriate screen
|
||||
FacesContext fc = FacesContext.getCurrentInstance();
|
||||
this.navigator.setupDispatchContext(node);
|
||||
fc.getApplication().getNavigationHandler().handleNavigation(fc, null, "editTextInline");
|
||||
String s = (MimetypeMap.MIMETYPE_XML.equals(mimetype)
|
||||
? "editXmlInline"
|
||||
: "editTextInline");
|
||||
fc.getApplication().getNavigationHandler().handleNavigation(fc, null, s);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@@ -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.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
@@ -18,6 +35,7 @@ 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;
|
||||
|
||||
@@ -29,11 +47,13 @@ import org.apache.commons.logging.LogFactory;
|
||||
public class CreateContentWizard extends BaseContentWizard
|
||||
{
|
||||
protected String content = null;
|
||||
|
||||
protected String templateType;
|
||||
protected List<SelectItem> createMimeTypes;
|
||||
|
||||
private static Log logger = LogFactory.getLog(CreateContentWizard.class);
|
||||
|
||||
public static final org.alfresco.service.namespace.QName TT_QNAME =
|
||||
org.alfresco.service.namespace.QName.createQName(org.alfresco.service.namespace.NamespaceService.CONTENT_MODEL_1_0_URI, "tt");
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// Wizard implementation
|
||||
|
||||
@@ -41,8 +61,10 @@ public class CreateContentWizard extends BaseContentWizard
|
||||
protected String finishImpl(FacesContext context, String outcome)
|
||||
throws Exception
|
||||
{
|
||||
saveContent(null, this.content);
|
||||
|
||||
saveContent(null, this.content);
|
||||
if (templateType != null)
|
||||
this.nodeService.setProperty(createdNode, TT_QNAME, templateType);
|
||||
|
||||
// return the default outcome
|
||||
return outcome;
|
||||
}
|
||||
@@ -54,6 +76,7 @@ public class CreateContentWizard extends BaseContentWizard
|
||||
|
||||
this.content = null;
|
||||
this.inlineEdit = true;
|
||||
this.templateType = null;
|
||||
this.mimeType = MimetypeMap.MIMETYPE_HTML;
|
||||
}
|
||||
|
||||
@@ -116,6 +139,19 @@ public class CreateContentWizard extends BaseContentWizard
|
||||
{
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public List<SelectItem> getCreateTemplateTypes()
|
||||
{
|
||||
List<TemplateType> ttl = TemplatingService.getInstance().getTemplateTypes();
|
||||
List<SelectItem> sil = new ArrayList<SelectItem>(ttl.size());
|
||||
Iterator it = ttl.iterator();
|
||||
while (it.hasNext())
|
||||
{
|
||||
TemplateType tt = (TemplateType)it.next();
|
||||
sil.add(new SelectItem(tt.getName(), tt.getName()));
|
||||
}
|
||||
return sil;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns a list of mime types to allow the user to select from
|
||||
@@ -165,6 +201,19 @@ public class CreateContentWizard extends BaseContentWizard
|
||||
|
||||
return this.createMimeTypes;
|
||||
}
|
||||
|
||||
public String getTemplateType()
|
||||
{
|
||||
return this.templateType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param templateType Sets the currently selected template type
|
||||
*/
|
||||
public void setTemplateType(String templateType)
|
||||
{
|
||||
this.templateType = templateType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the summary data for the wizard.
|
||||
|
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
* 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.io.*;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.event.ValueChangeEvent;
|
||||
import javax.faces.model.SelectItem;
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.alfresco.config.Config;
|
||||
import org.alfresco.config.ConfigElement;
|
||||
import org.alfresco.config.ConfigService;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.web.app.AlfrescoNavigationHandler;
|
||||
import org.alfresco.web.app.Application;
|
||||
import org.alfresco.web.bean.FileUploadBean;
|
||||
import org.alfresco.web.bean.repository.Node;
|
||||
import org.alfresco.web.data.IDataContainer;
|
||||
import org.alfresco.web.data.QuickSort;
|
||||
import org.alfresco.web.ui.common.Utils;
|
||||
import org.alfresco.web.templating.*;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
|
||||
/**
|
||||
* Bean implementation for the "Create Content Wizard" dialog
|
||||
*
|
||||
* @author arielb
|
||||
*/
|
||||
public class CreateXmlContentTypeWizard extends BaseContentWizard
|
||||
{
|
||||
|
||||
private final static Log logger = LogFactory.getLog(CreateXmlContentTypeWizard.class);
|
||||
private TemplateType tt;
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// Wizard implementation
|
||||
|
||||
@Override
|
||||
protected String finishImpl(FacesContext context, String outcome)
|
||||
throws Exception
|
||||
{
|
||||
|
||||
saveContent(this.getSchemaFile(), null);
|
||||
final TemplatingService ts = TemplatingService.getInstance();
|
||||
ts.registerTemplateType(tt);
|
||||
// return the default outcome
|
||||
return outcome;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Map<String, String> parameters)
|
||||
{
|
||||
super.init(parameters);
|
||||
|
||||
this.mimeType = "text/xml";
|
||||
this.clearUpload();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String cancel()
|
||||
{
|
||||
this.clearUpload();
|
||||
return super.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getNextButtonDisabled()
|
||||
{
|
||||
// TODO: Allow the next button state to be configured so that
|
||||
// wizard implementations don't have to worry about
|
||||
// checking step numbers
|
||||
|
||||
boolean disabled = false;
|
||||
int step = Application.getWizardManager().getCurrentStep();
|
||||
switch(step)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
disabled = (this.fileName == null || this.fileName.length() == 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return disabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doPostCommitProcessing(FacesContext context, String outcome)
|
||||
{
|
||||
// as we were successful, go to the set properties dialog if asked
|
||||
// to otherwise just return
|
||||
if (this.showOtherProperties)
|
||||
{
|
||||
// we are going to immediately edit the properties so we need
|
||||
// to setup the BrowseBean context appropriately
|
||||
this.browseBean.setDocument(new Node(this.createdNode));
|
||||
|
||||
return getDefaultFinishOutcome() + AlfrescoNavigationHandler.OUTCOME_SEPARATOR +
|
||||
"dialog:setContentProperties";
|
||||
}
|
||||
else
|
||||
{
|
||||
return outcome;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Action handler called when the user wishes to remove an uploaded file
|
||||
*/
|
||||
public String removeUploadedFile()
|
||||
{
|
||||
clearUpload();
|
||||
|
||||
// refresh the current page
|
||||
return null;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// Bean Getters and Setters
|
||||
|
||||
private FileUploadBean getFileUploadBean()
|
||||
{
|
||||
final FacesContext ctx = FacesContext.getCurrentInstance();
|
||||
final Map sessionMap = ctx.getExternalContext().getSessionMap();
|
||||
return (FileUploadBean)sessionMap.get(FileUploadBean.FILE_UPLOAD_BEAN_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the name of the file
|
||||
*/
|
||||
public String getFileName()
|
||||
{
|
||||
// try and retrieve the file and filename from the file upload bean
|
||||
// representing the file we previously uploaded.
|
||||
final FileUploadBean fileBean = this.getFileUploadBean();
|
||||
if (fileBean != null)
|
||||
this.fileName = fileBean.getFileName();
|
||||
return this.fileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fileName The name of the file
|
||||
*/
|
||||
public void setFileName(String fileName)
|
||||
{
|
||||
this.fileName = fileName;
|
||||
|
||||
// we also need to keep the file upload bean in sync
|
||||
final FileUploadBean fileBean = this.getFileUploadBean();
|
||||
if (fileBean != null)
|
||||
fileBean.setFileName(this.fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the schema file or <tt>null</tt>
|
||||
*/
|
||||
public File getSchemaFile()
|
||||
{
|
||||
// try and retrieve the file and filename from the file upload bean
|
||||
// representing the file we previously uploaded.
|
||||
final FileUploadBean fileBean = this.getFileUploadBean();
|
||||
return fileBean != null ? fileBean.getFile() : null;
|
||||
}
|
||||
|
||||
public void setSchemaFile(File f)
|
||||
{
|
||||
// we also need to keep the file upload bean in sync
|
||||
final FileUploadBean fileBean = this.getFileUploadBean();
|
||||
if (fileBean != null)
|
||||
fileBean.setFile(f);
|
||||
}
|
||||
/**
|
||||
* @return Returns the schema file or <tt>null</tt>
|
||||
*/
|
||||
public String getSchemaFileName()
|
||||
{
|
||||
// try and retrieve the file and filename from the file upload bean
|
||||
// representing the file we previously uploaded.
|
||||
return getFileName();
|
||||
}
|
||||
|
||||
public void setSchemaFileName(String s)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public String getFormURL()
|
||||
{
|
||||
try
|
||||
{
|
||||
final TemplatingService ts = TemplatingService.getInstance();
|
||||
final String rootTagName =
|
||||
this.getSchemaFileName().replaceAll("([^\\.])\\..+", "$1");
|
||||
final Document d = ts.parseXML(this.getSchemaFile());
|
||||
this.tt = ts.newTemplateType(rootTagName, d);
|
||||
final TemplateInputMethod tim = tt.getInputMethods()[0];
|
||||
return tim.getInputURL(tt.getSampleXml(rootTagName), tt);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
t.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String getSchemaFormURL()
|
||||
{
|
||||
try
|
||||
{
|
||||
final TemplatingService ts = TemplatingService.getInstance();
|
||||
final String rootTagName =
|
||||
this.getSchemaFileName().replaceAll("([^\\.])\\..+", "$1");
|
||||
final Document d = ts.parseXML(this.getSchemaFile());
|
||||
this.tt = ts.newTemplateType(rootTagName, d);
|
||||
final TemplateInputMethod tim = tt.getInputMethods()[0];
|
||||
return tim.getSchemaInputURL(tt);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
t.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the summary data for the wizard.
|
||||
*/
|
||||
public String getSummary()
|
||||
{
|
||||
ResourceBundle bundle = Application.getBundle(FacesContext.getCurrentInstance());
|
||||
|
||||
// TODO: show first few lines of content here?
|
||||
return buildSummary(
|
||||
new String[] {bundle.getString("file_name"),
|
||||
bundle.getString("type"),
|
||||
bundle.getString("content_type")},
|
||||
new String[] {this.fileName, getSummaryObjectType(),
|
||||
getSummaryMimeType(this.mimeType)});
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// Action event handlers
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// Service Injection
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// Helper Methods
|
||||
|
||||
/**
|
||||
*/
|
||||
protected void clearUpload()
|
||||
{
|
||||
// remove the file upload bean from the session
|
||||
FacesContext ctx = FacesContext.getCurrentInstance();
|
||||
FileUploadBean fileBean = (FileUploadBean)ctx.getExternalContext().getSessionMap().
|
||||
get(FileUploadBean.FILE_UPLOAD_BEAN_NAME);
|
||||
if (fileBean != null)
|
||||
fileBean.setFile(null);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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.templating;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
public interface TemplateInputMethod
|
||||
{
|
||||
public String getInputURL(final Document xmlContent,
|
||||
final TemplateType tt);
|
||||
|
||||
public String getSchemaInputURL(final TemplateType tt);
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.templating;
|
||||
|
||||
import java.io.Writer;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
public interface TemplateOutputMethod
|
||||
{
|
||||
|
||||
public void generate(final Document xmlContent,
|
||||
final TemplateType tt,
|
||||
final Writer out);
|
||||
}
|
33
source/java/org/alfresco/web/templating/TemplateType.java
Normal file
33
source/java/org/alfresco/web/templating/TemplateType.java
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.templating;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
public interface TemplateType
|
||||
{
|
||||
|
||||
public String getName();
|
||||
|
||||
public Document getSchema();
|
||||
|
||||
public Document getSampleXml(final String rootTagName);
|
||||
|
||||
public TemplateInputMethod[] getInputMethods();
|
||||
|
||||
public TemplateOutputMethod[] getOutputMethods();
|
||||
}
|
125
source/java/org/alfresco/web/templating/TemplatingService.java
Normal file
125
source/java/org/alfresco/web/templating/TemplatingService.java
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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.templating;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.parsers.*;
|
||||
|
||||
import javax.xml.transform.*;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import org.alfresco.web.templating.xforms.*;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
public class TemplatingService
|
||||
{
|
||||
private final static TemplatingService INSTANCE = new TemplatingService();
|
||||
|
||||
private ArrayList<TemplateType> templateTypes =
|
||||
new ArrayList<TemplateType>();
|
||||
|
||||
private TemplatingService()
|
||||
{
|
||||
}
|
||||
|
||||
public static TemplatingService getInstance()
|
||||
{
|
||||
return TemplatingService.INSTANCE;
|
||||
}
|
||||
|
||||
public List<TemplateType> getTemplateTypes()
|
||||
{
|
||||
return this.templateTypes;
|
||||
}
|
||||
|
||||
public TemplateType getTemplateType(final String name)
|
||||
{
|
||||
final Iterator it = this.templateTypes.iterator();
|
||||
while (it.hasNext())
|
||||
{
|
||||
final TemplateType tt = (TemplateType)it.next();
|
||||
if (tt.getName().equals(name))
|
||||
return tt;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void registerTemplateType(final TemplateType tt)
|
||||
{
|
||||
this.templateTypes.add(tt);
|
||||
}
|
||||
|
||||
public TemplateType newTemplateType(final String name,
|
||||
final Document schema)
|
||||
{
|
||||
return new TemplateTypeImpl(name, schema);
|
||||
}
|
||||
|
||||
public void writeXML(final Node d, final File output)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.out.println("writing out a document for " + d.getNodeName() +
|
||||
" to " + output);
|
||||
final TransformerFactory tf = TransformerFactory.newInstance();
|
||||
final Transformer t = tf.newTransformer();
|
||||
t.transform(new DOMSource(d), new StreamResult(output));
|
||||
}
|
||||
catch (TransformerException te)
|
||||
{
|
||||
te.printStackTrace();
|
||||
assert false : te.getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
public Document parseXML(final String source)
|
||||
throws ParserConfigurationException,
|
||||
SAXException,
|
||||
IOException
|
||||
{
|
||||
return this.parseXML(new ByteArrayInputStream(source.getBytes()));
|
||||
}
|
||||
|
||||
public Document parseXML(final File source)
|
||||
throws ParserConfigurationException,
|
||||
SAXException,
|
||||
IOException
|
||||
{
|
||||
return this.parseXML(new FileInputStream(source));
|
||||
}
|
||||
|
||||
public Document parseXML(final InputStream source)
|
||||
throws ParserConfigurationException,
|
||||
SAXException,
|
||||
IOException
|
||||
{
|
||||
final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
dbf.setNamespaceAware(true);
|
||||
dbf.setValidating(false);
|
||||
final DocumentBuilder db = dbf.newDocumentBuilder();
|
||||
final Document result = db.parse(source);
|
||||
source.close();
|
||||
return result;
|
||||
}
|
||||
}
|
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* 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.templating.xforms;
|
||||
|
||||
import java.io.*;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.alfresco.util.TempFileProvider;
|
||||
import org.alfresco.web.templating.*;
|
||||
import org.alfresco.web.templating.xforms.schemabuilder.FormBuilderException;
|
||||
|
||||
import org.apache.xmlbeans.*;
|
||||
import org.apache.xmlbeans.impl.xsd2inst.SampleXmlUtil;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
public class TemplateTypeImpl
|
||||
implements TemplateType
|
||||
{
|
||||
|
||||
private final Document schema;
|
||||
private final String name;
|
||||
|
||||
public TemplateTypeImpl(final String name,
|
||||
final Document schema)
|
||||
{
|
||||
this.name = name;
|
||||
this.schema = schema;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public Document getSchema()
|
||||
{
|
||||
return this.schema;
|
||||
}
|
||||
|
||||
public Document getSampleXml(final String rootTagName)
|
||||
{
|
||||
XmlOptions xmlOptions = new XmlOptions();
|
||||
xmlOptions = xmlOptions.setLoadLineNumbers().setLoadMessageDigest();
|
||||
final XmlObject[] schemas = new XmlObject[1];
|
||||
try
|
||||
{
|
||||
final File schemaFile = TempFileProvider.createTempFile("alfresco", ".schema");
|
||||
TemplatingService.getInstance().writeXML(this.schema, schemaFile);
|
||||
schemas[0] = XmlObject.Factory.parse(schemaFile, xmlOptions);
|
||||
schemaFile.delete();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("Can not load schema file: " + schema + ": ");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
final XmlOptions compileOptions = new XmlOptions();
|
||||
compileOptions.setCompileDownloadUrls();
|
||||
compileOptions.setCompileNoPvrRule();
|
||||
compileOptions.setCompileNoUpaRule();
|
||||
|
||||
SchemaTypeSystem sts = null;
|
||||
try
|
||||
{
|
||||
sts = XmlBeans.compileXsd(schemas,
|
||||
XmlBeans.getBuiltinTypeSystem(),
|
||||
compileOptions);
|
||||
}
|
||||
catch (XmlException xmle)
|
||||
{
|
||||
xmle.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
if (sts == null)
|
||||
{
|
||||
throw new NullPointerException("No Schemas to process.");
|
||||
}
|
||||
final SchemaType[] globalElems = sts.documentTypes();
|
||||
SchemaType elem = null;
|
||||
for (int i = 0; i < globalElems.length; i++)
|
||||
{
|
||||
if (rootTagName.equals(globalElems[i].getDocumentElementName().getLocalPart()))
|
||||
{
|
||||
elem = globalElems[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (elem == null)
|
||||
throw new NullPointerException("Could not find a global element with name \"" + rootTagName + "\"");
|
||||
|
||||
final String result = SampleXmlUtil.createSampleForType(elem);
|
||||
try
|
||||
{
|
||||
final TemplatingService ts = TemplatingService.getInstance();
|
||||
return ts.parseXML(new ByteArrayInputStream(result.getBytes()));
|
||||
}
|
||||
catch (ParserConfigurationException pce)
|
||||
{
|
||||
assert false : pce.getMessage();
|
||||
return null;
|
||||
}
|
||||
catch (SAXException saxe)
|
||||
{
|
||||
assert false : saxe.getMessage();
|
||||
return null;
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
assert false : ioe.getMessage();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public TemplateInputMethod[] getInputMethods()
|
||||
{
|
||||
return new TemplateInputMethod[] {
|
||||
new XFormsInputMethod()
|
||||
};
|
||||
}
|
||||
|
||||
public TemplateOutputMethod[] getOutputMethods()
|
||||
{
|
||||
return new TemplateOutputMethod[0];
|
||||
}
|
||||
}
|
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* 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.templating.xforms;
|
||||
|
||||
import java.io.*;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.alfresco.util.TempFileProvider;
|
||||
import org.alfresco.web.templating.*;
|
||||
import org.alfresco.web.templating.xforms.schemabuilder.*;
|
||||
import org.chiba.xml.util.DOMUtil;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
public class XFormsInputMethod
|
||||
implements TemplateInputMethod
|
||||
{
|
||||
|
||||
public XFormsInputMethod()
|
||||
{
|
||||
}
|
||||
|
||||
public String getInputURL(final Document xmlContent, final TemplateType tt)
|
||||
{
|
||||
try
|
||||
{
|
||||
final Document xform = this.getXForm(xmlContent, tt);
|
||||
final String id = getDocumentElementNameNoNS(xmlContent);
|
||||
// this.saveInChiba(id, xform);
|
||||
final File xformFile = TempFileProvider.createTempFile("alfresco", ".xform");
|
||||
final TemplatingService ts = TemplatingService.getInstance();
|
||||
ts.writeXML(xform, xformFile);
|
||||
final FacesContext fc = FacesContext.getCurrentInstance();
|
||||
final String cp =
|
||||
fc.getExternalContext().getRequestContextPath();
|
||||
return cp + "/XFormsServlet?form=" + xformFile.toURI().toString();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String getSchemaInputURL(final TemplateType tt)
|
||||
{
|
||||
try
|
||||
{
|
||||
// final Document xform = this.getXFormForSchema(tt);
|
||||
// final File xformFile = TempFileProvider.createTempFile("alfresco", ".xform");
|
||||
// final TemplatingService ts = TemplatingService.getInstance();
|
||||
// ts.writeXML(tt.getSchema(), xformFile);
|
||||
// final FacesContext fc = FacesContext.getCurrentInstance();
|
||||
// final String cp =
|
||||
// fc.getExternalContext().getRequestContextPath();
|
||||
// return cp + "/XFormsServlet?form=" + xformFile.toURI().toString();
|
||||
return null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static String getDocumentElementNameNoNS(final Document d)
|
||||
{
|
||||
final Node n = d.getDocumentElement();
|
||||
String name = n.getNodeName();
|
||||
return name;
|
||||
// String prefix = n.getPrefix();
|
||||
// String namespace = n.getNamespaceURI();
|
||||
// System.out.println("name " + name + " prefix " + prefix + " ns uri " + namespace);
|
||||
// return name.replaceAll(".+\\:", "");
|
||||
}
|
||||
|
||||
// public Document getXFormForSchema(final TemplateType tt)
|
||||
// throws FormBuilderException
|
||||
// {
|
||||
// final TemplatingService ts = TemplatingService.getInstance();
|
||||
//
|
||||
// final File schemaFile = TempFileProvider.createTempFile("alfresco", ".schema");
|
||||
// ts.writeXML(tt.getSchema(), schemaFile);
|
||||
// final FacesContext fc = FacesContext.getCurrentInstance();
|
||||
// final String cp =
|
||||
// fc.getExternalContext().getRequestContextPath();
|
||||
//
|
||||
// final SchemaFormBuilder builder =
|
||||
// new BaseSchemaFormBuilder("schema",
|
||||
// schemaFile.toURI().toString(),
|
||||
// cp + "/jsp/content/xforms/form/debug-instance.jsp",
|
||||
// "post",
|
||||
// new XHTMLWrapperElementsBuilder(),
|
||||
// null,
|
||||
// null,
|
||||
// true);
|
||||
// System.out.println("building xform for schema " + schemaFile.getPath());
|
||||
// final Document result = builder.buildForm("/Users/arielb/Documents/alfresco/xsd/XMLSchema.xsd");
|
||||
// // xmlContentFile.delete();
|
||||
// // schemaFile.delete();
|
||||
// return result;
|
||||
// }
|
||||
|
||||
public Document getXForm(final Document xmlContent, final TemplateType tt)
|
||||
throws FormBuilderException
|
||||
{
|
||||
final TemplatingService ts = TemplatingService.getInstance();
|
||||
final File schemaFile = TempFileProvider.createTempFile("alfresco", ".schema");
|
||||
ts.writeXML(tt.getSchema(), schemaFile);
|
||||
|
||||
final FacesContext fc = FacesContext.getCurrentInstance();
|
||||
final String cp =
|
||||
fc.getExternalContext().getRequestContextPath();
|
||||
|
||||
final SchemaFormBuilder builder =
|
||||
new BaseSchemaFormBuilder(getDocumentElementNameNoNS(xmlContent),
|
||||
xmlContent,
|
||||
"http://localhost:8080" + cp + "/jsp/content/xforms/debug-instance.jsp",
|
||||
"post",
|
||||
new XHTMLWrapperElementsBuilder(),
|
||||
null,
|
||||
null,
|
||||
true);
|
||||
System.out.println("building xform for schema " + schemaFile.getPath());
|
||||
final Document result = builder.buildForm(schemaFile.getPath());
|
||||
// xmlContentFile.delete();
|
||||
// schemaFile.delete();
|
||||
return result;
|
||||
}
|
||||
|
||||
// private void saveInChiba(final String fileName, final Document d)
|
||||
// throws IOException
|
||||
// {
|
||||
// final ServletContext myContext = (ServletContext)
|
||||
// FacesContext.getCurrentInstance().getExternalContext().getContext();
|
||||
// final ServletContext chiba = myContext.getContext("/chiba");
|
||||
// final File outputFile = new File(new File(chiba.getRealPath("/forms")),
|
||||
// fileName + ".xhtml");
|
||||
// TemplatingService.getInstance().writeXML(d.getDocumentElement(), outputFile);
|
||||
// }
|
||||
}
|
@@ -0,0 +1,127 @@
|
||||
package org.alfresco.web.templating.xforms.flux;
|
||||
|
||||
import org.chiba.xml.util.DOMUtil;
|
||||
import org.chiba.xml.xforms.XFormsConstants;
|
||||
import org.chiba.xml.xforms.events.XFormsEvent;
|
||||
import org.chiba.xml.xforms.events.XFormsEventFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* EventLog logs all events happening in XForms processor and build a DOM
|
||||
* document which represent those events.
|
||||
*
|
||||
* @author Joern Turner
|
||||
* @version $Id: EventLog.java,v 1.6 2005/12/21 22:59:27 unl Exp $
|
||||
*/
|
||||
public class EventLog {
|
||||
private static List HELPER_ELEMENTS =
|
||||
Arrays.asList(new String[]
|
||||
{
|
||||
XFormsConstants.LABEL,
|
||||
XFormsConstants.HELP,
|
||||
XFormsConstants.HINT,
|
||||
XFormsConstants.ALERT,
|
||||
XFormsConstants.VALUE
|
||||
});
|
||||
|
||||
private static List SELECTOR_ELEMENTS =
|
||||
Arrays.asList(new String[]
|
||||
{
|
||||
XFormsConstants.SELECT1,
|
||||
XFormsConstants.SELECT
|
||||
});
|
||||
|
||||
private final Document doc;
|
||||
private final Element root;
|
||||
private Element selector;
|
||||
|
||||
public EventLog() {
|
||||
this.doc = DOMUtil.newDocument(false, false);
|
||||
this.root = this.doc.createElement("eventlog");
|
||||
this.root.setAttribute("id", "eventlog");
|
||||
this.doc.appendChild(this.root);
|
||||
}
|
||||
|
||||
public Element getLog() {
|
||||
return (Element) this.root.cloneNode(true);
|
||||
}
|
||||
|
||||
public void add(XFormsEvent event) {
|
||||
// get target properties
|
||||
String type = event.getType();
|
||||
Element target = (Element) event.getTarget();
|
||||
String targetId = target.getAttributeNS(null, "id");
|
||||
String targetName = target.getLocalName();
|
||||
|
||||
// create event element
|
||||
Element element;
|
||||
|
||||
if (XFormsEventFactory.CHIBA_STATE_CHANGED.equals(type) && SELECTOR_ELEMENTS.contains(targetName)) {
|
||||
// selector events are always appended to the end of the log
|
||||
// to ensure their items' labels and values are updated before
|
||||
element = insert(null, type, targetId, targetName);
|
||||
if (this.selector == null)
|
||||
this.selector = element;
|
||||
}
|
||||
else
|
||||
{
|
||||
// all other events are inserted before any selector events
|
||||
element = insert(this.selector, type, targetId, targetName);
|
||||
}
|
||||
|
||||
if (XFormsEventFactory.CHIBA_STATE_CHANGED.equals(type) && HELPER_ELEMENTS.contains(targetName))
|
||||
{
|
||||
// parent id is needed for updating all helper elements cause they
|
||||
// are identified by '<parentId>-label' etc. rather than their own id
|
||||
String parentId = ((Element) target.getParentNode()).getAttributeNS(null, "id");
|
||||
addProperty(element, "parentId", parentId);
|
||||
}
|
||||
|
||||
// add event params
|
||||
Iterator iterator = event.getPropertyNames().iterator();
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
String name = (String) iterator.next();
|
||||
addProperty(element, name, event.getContextInfo(name).toString());
|
||||
}
|
||||
}
|
||||
|
||||
public Element add(String type, String targetId, String targetName){
|
||||
return insert(this.selector, type, targetId, targetName);
|
||||
}
|
||||
|
||||
public Element addProperty(Element element, String name, String value) {
|
||||
Element property = this.doc.createElement("property");
|
||||
property.setAttribute("name", name);
|
||||
property.appendChild(this.doc.createTextNode(value));
|
||||
element.appendChild(property);
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
private Element insert(Element ref, String type, String targetId, String targetName)
|
||||
{
|
||||
// create event element
|
||||
Element element = this.doc.createElement("event");
|
||||
this.root.insertBefore(element, ref);
|
||||
|
||||
// add target properties
|
||||
element.setAttribute("type", type);
|
||||
element.setAttribute("targetId", targetId);
|
||||
element.setAttribute("targetName", targetName);
|
||||
return element;
|
||||
}
|
||||
|
||||
|
||||
// clean the log
|
||||
public void flush()
|
||||
{
|
||||
DOMUtil.removeAllChildren(this.root);
|
||||
this.selector = null;
|
||||
}
|
||||
}
|
@@ -0,0 +1,265 @@
|
||||
package org.alfresco.web.templating.xforms.flux;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.chiba.adapter.AbstractChibaAdapter;
|
||||
import org.chiba.adapter.ChibaEvent;
|
||||
import org.alfresco.web.templating.xforms.servlet.HttpRequestHandler;
|
||||
import org.alfresco.web.templating.xforms.servlet.ServletAdapter;
|
||||
import org.alfresco.web.templating.xforms.servlet.ChibaServlet;
|
||||
import org.chiba.xml.xforms.events.XFormsEvent;
|
||||
import org.chiba.xml.xforms.events.XFormsEventFactory;
|
||||
import org.chiba.xml.xforms.exception.XFormsException;
|
||||
import org.chiba.xml.xforms.ui.Repeat;
|
||||
import org.chiba.xml.util.DOMUtil;
|
||||
import org.w3c.dom.events.Event;
|
||||
import org.w3c.dom.events.EventListener;
|
||||
import org.w3c.dom.events.EventTarget;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Adapter for processing DWR calls and building appropriate responses. This
|
||||
* class is not exposed through DWR. Instead a Facadeclass 'FluxFacade' will be
|
||||
* exposed that only allows to use the dispatch method. All other methods will
|
||||
* be hidden for security.
|
||||
*
|
||||
* @author Joern Turner
|
||||
* @version $Id: FluxAdapter.java,v 1.15 2005/12/21 22:59:27 unl Exp $
|
||||
*/
|
||||
public class FluxAdapter extends AbstractChibaAdapter implements EventListener {
|
||||
private static final Log LOGGER = LogFactory.getLog(FluxAdapter.class);
|
||||
|
||||
private final HttpSession session;
|
||||
private EventLog eventLog;
|
||||
private EventTarget root;
|
||||
|
||||
|
||||
public FluxAdapter(HttpSession session) {
|
||||
this.chibaBean = createXFormsProcessor();
|
||||
this.context = new HashMap();
|
||||
chibaBean.setContext(this.context);
|
||||
this.eventLog = new EventLog();
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
/**
|
||||
* initialize the Adapter. This is necessary cause often the using
|
||||
* application will need to configure the Adapter before actually using it.
|
||||
*
|
||||
* @throws org.chiba.xml.xforms.exception.XFormsException
|
||||
*/
|
||||
public void init() throws XFormsException {
|
||||
try {
|
||||
// get docuent root as event target in order to capture all events
|
||||
this.root = (EventTarget) this.chibaBean.getXMLContainer().getDocumentElement();
|
||||
|
||||
// interaction events my occur during init so we have to register before
|
||||
this.root.addEventListener(XFormsEventFactory.CHIBA_LOAD_URI, this, true);
|
||||
this.root.addEventListener(XFormsEventFactory.CHIBA_RENDER_MESSAGE, this, true);
|
||||
this.root.addEventListener(XFormsEventFactory.CHIBA_REPLACE_ALL, this, true);
|
||||
|
||||
// init processor
|
||||
this.chibaBean.init();
|
||||
|
||||
// todo: add getter for event log
|
||||
setContextParam("EVENT-LOG", this.eventLog);
|
||||
|
||||
// register for notification events
|
||||
this.root.addEventListener(XFormsEventFactory.CHIBA_STATE_CHANGED, this, true);
|
||||
this.root.addEventListener(XFormsEventFactory.CHIBA_PROTOTYPE_CLONED, this, true);
|
||||
this.root.addEventListener(XFormsEventFactory.CHIBA_ID_GENERATED, this, true);
|
||||
this.root.addEventListener(XFormsEventFactory.CHIBA_ITEM_INSERTED, this, true);
|
||||
this.root.addEventListener(XFormsEventFactory.CHIBA_ITEM_DELETED, this, true);
|
||||
this.root.addEventListener(XFormsEventFactory.CHIBA_INDEX_CHANGED, this, true);
|
||||
this.root.addEventListener(XFormsEventFactory.CHIBA_SWITCH_TOGGLED, this, true);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new XFormsException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch a ChibaEvent to trigger some XForms processing such as updating
|
||||
* of values or execution of triggers.
|
||||
*
|
||||
* @param event an application specific event
|
||||
* @throws org.chiba.xml.xforms.exception.XFormsException
|
||||
* @see org.chiba.adapter.DefaultChibaEventImpl
|
||||
*/
|
||||
public void dispatch(ChibaEvent event) throws XFormsException {
|
||||
LOGGER.debug("dispatching " + event);
|
||||
this.eventLog.flush();
|
||||
String targetId = event.getId();
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Event " + event.getEventName() + " dispatched");
|
||||
LOGGER.debug("Event target: " + targetId);
|
||||
// try
|
||||
// {
|
||||
// DOMUtil.prettyPrintDOM(this.chibaBean.getXMLContainer(), System.out);
|
||||
// } catch (TransformerException e) {
|
||||
// throw new XFormsException(e);
|
||||
// }
|
||||
}
|
||||
|
||||
if (event.getEventName().equals(FluxFacade.FLUX_ACTIVATE_EVENT))
|
||||
chibaBean.dispatch(targetId, XFormsEventFactory.DOM_ACTIVATE);
|
||||
else if (event.getEventName().equals("SETINDEX")) {
|
||||
int position = Integer.parseInt((String) event.getContextInfo());
|
||||
Repeat repeat = (Repeat) this.chibaBean.lookup(targetId);
|
||||
repeat.setIndex(position);
|
||||
}
|
||||
else if (event.getEventName().equals("SETVALUE")) {
|
||||
if (LOGGER.isDebugEnabled())
|
||||
LOGGER.debug("Event contextinfo: " + event.getContextInfo());
|
||||
this.chibaBean.updateControlValue(targetId, (String) event.getContextInfo());
|
||||
}
|
||||
else if (event.getEventName().equalsIgnoreCase("http-request")) {
|
||||
// todo: make request handler member of web adapter
|
||||
HttpRequestHandler httpRequestHandler = new HttpRequestHandler(this.chibaBean);
|
||||
httpRequestHandler.execute(event);
|
||||
}
|
||||
else {
|
||||
throw new XFormsException("Unknown or illegal event type");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* listen to processor and add a DefaultChibaEventImpl object to the
|
||||
* EventQueue.
|
||||
*
|
||||
* @param event the handled DOMEvent
|
||||
*/
|
||||
public void handleEvent(Event event)
|
||||
{
|
||||
LOGGER.debug("handleEvent(" + event + ")");
|
||||
try {
|
||||
if (event instanceof XFormsEvent)
|
||||
{
|
||||
XFormsEvent xformsEvent = (XFormsEvent) event;
|
||||
String type = xformsEvent.getType();
|
||||
if (XFormsEventFactory.CHIBA_REPLACE_ALL.equals(type))
|
||||
{
|
||||
// get event context and store it in session
|
||||
Map submissionResponse = new HashMap();
|
||||
submissionResponse.put("header", xformsEvent.getContextInfo("header"));
|
||||
submissionResponse.put("body", xformsEvent.getContextInfo("body"));
|
||||
this.session.setAttribute(ChibaServlet.CHIBA_SUBMISSION_RESPONSE, submissionResponse);
|
||||
|
||||
// get event properties
|
||||
Element target = (Element) event.getTarget();
|
||||
String targetId = target.getAttributeNS(null, "id");
|
||||
String targetName = target.getLocalName();
|
||||
|
||||
// add event properties to log
|
||||
this.eventLog.add(type, targetId, targetName);
|
||||
}
|
||||
else
|
||||
{
|
||||
// add event to log
|
||||
this.eventLog.add(xformsEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
System.out.println("**** " + e.getMessage());
|
||||
LOGGER.debug("error " + e.getMessage() + " while handling event " + event);
|
||||
try {
|
||||
this.chibaBean.getContainer().handleEventException(e);
|
||||
}
|
||||
catch (XFormsException xfe) {
|
||||
xfe.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* terminates the XForms processing. right place to do cleanup of
|
||||
* resources.
|
||||
*
|
||||
* @throws org.chiba.xml.xforms.exception.XFormsException
|
||||
*/
|
||||
public void shutdown() throws XFormsException {
|
||||
try {
|
||||
// deregister for notification events
|
||||
this.root.removeEventListener(XFormsEventFactory.CHIBA_STATE_CHANGED, this, true);
|
||||
this.root.removeEventListener(XFormsEventFactory.CHIBA_PROTOTYPE_CLONED, this, true);
|
||||
this.root.removeEventListener(XFormsEventFactory.CHIBA_ID_GENERATED, this, true);
|
||||
this.root.removeEventListener(XFormsEventFactory.CHIBA_ITEM_INSERTED, this, true);
|
||||
this.root.removeEventListener(XFormsEventFactory.CHIBA_ITEM_DELETED, this, true);
|
||||
this.root.removeEventListener(XFormsEventFactory.CHIBA_INDEX_CHANGED, this, true);
|
||||
this.root.removeEventListener(XFormsEventFactory.CHIBA_SWITCH_TOGGLED, this, true);
|
||||
|
||||
// shutdown processor
|
||||
this.chibaBean.shutdown();
|
||||
this.chibaBean = null;
|
||||
|
||||
// deregister for interaction events
|
||||
this.root.removeEventListener(XFormsEventFactory.CHIBA_LOAD_URI, this, true);
|
||||
this.root.removeEventListener(XFormsEventFactory.CHIBA_RENDER_MESSAGE, this, true);
|
||||
this.root.removeEventListener(XFormsEventFactory.CHIBA_REPLACE_ALL, this, true);
|
||||
|
||||
this.root = null;
|
||||
|
||||
System.gc();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new XFormsException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set the upload location. This string represents the destination
|
||||
* (data-sink) for uploads.
|
||||
*
|
||||
* @param destination a String representing the location where to store
|
||||
* uploaded files/data.
|
||||
*/
|
||||
public void setUploadDestination(String destination) {
|
||||
this.uploadDestination = destination;
|
||||
//todo: this should be moved to parent class. it's duplicated in both Adapters
|
||||
setContextParam(ServletAdapter.HTTP_UPLOAD_DIR, this.uploadDestination);
|
||||
}
|
||||
|
||||
protected String escape(String string) {
|
||||
if (string == null) {
|
||||
return string;
|
||||
}
|
||||
|
||||
StringBuffer buffer = new StringBuffer(string.length());
|
||||
char c;
|
||||
for (int index = 0; index < string.length(); index++) {
|
||||
c = string.charAt(index);
|
||||
switch (c) {
|
||||
case '\n':
|
||||
buffer.append('\\').append('n');
|
||||
break;
|
||||
case '\r':
|
||||
buffer.append('\\').append('r');
|
||||
break;
|
||||
case '\t':
|
||||
buffer.append('\\').append('t');
|
||||
break;
|
||||
case '\'':
|
||||
buffer.append('\\').append('\'');
|
||||
break;
|
||||
case '\"':
|
||||
buffer.append('\\').append('\"');
|
||||
break;
|
||||
default:
|
||||
buffer.append(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
}
|
||||
// end of class
|
@@ -0,0 +1,23 @@
|
||||
package org.alfresco.web.templating.xforms.flux;
|
||||
|
||||
/**
|
||||
* Used for signalling problems with Flux execution
|
||||
*
|
||||
* @author Joern Turner
|
||||
* @version $Id: FluxException.java,v 1.1 2005/11/08 17:34:07 joernt Exp $
|
||||
*/
|
||||
public class FluxException extends Exception{
|
||||
|
||||
public FluxException() {
|
||||
}
|
||||
|
||||
public FluxException(String string) {
|
||||
super(string);
|
||||
}
|
||||
|
||||
public FluxException(Throwable throwable) {
|
||||
super(throwable);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,144 @@
|
||||
package org.alfresco.web.templating.xforms.flux;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.chiba.adapter.ChibaAdapter;
|
||||
import org.chiba.adapter.ChibaEvent;
|
||||
import org.chiba.adapter.DefaultChibaEventImpl;
|
||||
import org.alfresco.web.templating.xforms.servlet.ChibaServlet;
|
||||
import org.chiba.xml.util.DOMUtil;
|
||||
import org.chiba.xml.xforms.exception.XFormsException;
|
||||
import org.w3c.dom.Element;
|
||||
import uk.ltd.getahead.dwr.ExecutionContext;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
import javax.xml.transform.TransformerException;
|
||||
|
||||
/**
|
||||
* AJAX Facade class to hide the full functionality from the web-client.
|
||||
*
|
||||
* @author Joern Turner
|
||||
* @version $Id: FluxFacade.java,v 1.9 2005/12/21 19:06:55 unl Exp $
|
||||
*/
|
||||
public class FluxFacade
|
||||
{
|
||||
|
||||
//this is a custom event to activate a trigger in XForms.
|
||||
private static final Log LOGGER = LogFactory.getLog(FluxFacade.class);
|
||||
public static final String FLUX_ACTIVATE_EVENT = "flux-action-event";
|
||||
ChibaAdapter adapter = null;
|
||||
private HttpSession session;
|
||||
|
||||
|
||||
/**
|
||||
* grabs the actual adapter from the session.
|
||||
*/
|
||||
public FluxFacade() {
|
||||
session = ExecutionContext.get().getSession();
|
||||
adapter = (ChibaAdapter) session.getAttribute(ChibaServlet.CHIBA_ADAPTER);
|
||||
}
|
||||
|
||||
/**
|
||||
* executes a trigger
|
||||
*
|
||||
* @param id the id of the trigger to execute
|
||||
* @return the list of events that may result through this action
|
||||
* @throws FluxException
|
||||
*/
|
||||
public Element fireAction(String id) throws FluxException {
|
||||
LOGGER.debug("fireAction " + id);
|
||||
ChibaEvent chibaActivateEvent = new DefaultChibaEventImpl();
|
||||
chibaActivateEvent.initEvent(FLUX_ACTIVATE_EVENT, id, null);
|
||||
return dispatch(chibaActivateEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the value of a control in the processor.
|
||||
*
|
||||
* @param id the id of the control in the host document
|
||||
* @param value the new value
|
||||
* @return the list of events that may result through this action
|
||||
* @throws FluxException
|
||||
*/
|
||||
public Element setXFormsValue(String id, String value) throws FluxException {
|
||||
LOGGER.debug("setXFormsValue(" + id + ", " + value + ")");
|
||||
ChibaEvent event = new DefaultChibaEventImpl();
|
||||
event.initEvent("SETVALUE", id, value);
|
||||
return dispatch(event);
|
||||
}
|
||||
|
||||
public Element setRepeatIndex(String id, String position) throws FluxException {
|
||||
LOGGER.debug("setRepeatPosition(" + id + ", " + position + ")");
|
||||
ChibaEvent event = new DefaultChibaEventImpl();
|
||||
event.initEvent("SETINDEX", id, position);
|
||||
return dispatch(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* fetches the progress of a running upload.
|
||||
*
|
||||
* @param id id of the upload control in use
|
||||
* @param filename filename for uploaded data
|
||||
* @return a array containing two elements for evaluation in browser. First
|
||||
* param is the upload control id and second will be the current
|
||||
* progress of the upload.
|
||||
*/
|
||||
public Element fetchProgress(String id, String filename) {
|
||||
String progress = "0";
|
||||
|
||||
if (session.getAttribute(filename) != null) {
|
||||
progress = ((Integer) session.getAttribute(filename)).toString();
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Percent completed: " + progress);
|
||||
}
|
||||
}
|
||||
|
||||
EventLog eventLog = (EventLog) adapter.getContextParam("EVENT-LOG");
|
||||
if (eventLog == null) {
|
||||
eventLog = new EventLog();
|
||||
}
|
||||
Element eventlogElement = eventLog.getLog();
|
||||
eventLog.flush();
|
||||
|
||||
Element progressEvent = eventLog.add("upload-progress-event", id, "upload");
|
||||
eventLog.addProperty(progressEvent, "progress", progress);
|
||||
return eventlogElement;
|
||||
}
|
||||
|
||||
private Element dispatch(ChibaEvent event) throws FluxException {
|
||||
LOGGER.debug("dispatching " + event);
|
||||
if (adapter != null) {
|
||||
try {
|
||||
adapter.dispatch(event);
|
||||
}
|
||||
catch (XFormsException e) {
|
||||
throw new FluxException(e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//session expired or cookie got lost
|
||||
throw new FluxException("Session expired. Please start again.");
|
||||
}
|
||||
EventLog eventLog = (EventLog) adapter.getContextParam("EVENT-LOG");
|
||||
Element eventlogElement = eventLog.getLog();
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
try
|
||||
{
|
||||
DOMUtil.prettyPrintDOM(eventlogElement, System.out);
|
||||
}
|
||||
catch (TransformerException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return eventlogElement;
|
||||
}
|
||||
|
||||
public String getInfo()
|
||||
{
|
||||
return "FluxFacade using " + adapter.toString();
|
||||
}
|
||||
}
|
||||
|
||||
// end of class
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,650 @@
|
||||
/*
|
||||
* 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.templating.xforms.schemabuilder;
|
||||
|
||||
import org.apache.xerces.xs.*;
|
||||
import org.chiba.util.StringUtil;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Text;
|
||||
|
||||
import javax.xml.transform.Source;
|
||||
import java.util.Vector;
|
||||
|
||||
/*
|
||||
* Search for TODO for things remaining to-do in this implementation.
|
||||
*
|
||||
* TODO: i18n/l10n of messages, hints, captions. Possibly leverage org.chiba.i18n classes.
|
||||
* TODO: When Chiba supports itemset, use schema keyref and key constraints for validation.
|
||||
* TODO: Add support for default and fixed values.
|
||||
* TODO: Add support for use=prohibited.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A concrete base implementation of the SchemaFormBuilder interface allowing
|
||||
* an XForm to be automatically generated for an XML Schema definition.
|
||||
*
|
||||
* @author Brian Dueck
|
||||
* @version $Id: BaseSchemaFormBuilder.java,v 1.19 2005/03/29 14:24:34 unl Exp $
|
||||
*/
|
||||
public class BaseSchemaFormBuilder
|
||||
extends AbstractSchemaFormBuilder
|
||||
implements SchemaFormBuilder {
|
||||
/**
|
||||
* Creates a new instance of BaseSchemaForBuilder
|
||||
*/
|
||||
public BaseSchemaFormBuilder(String rootTagName) {
|
||||
super(rootTagName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new BaseSchemaFormBuilder object.
|
||||
*
|
||||
* @param rootTagName __UNDOCUMENTED__
|
||||
* @param instanceSource __UNDOCUMENTED__
|
||||
* @param action __UNDOCUMENTED__
|
||||
* @param submitMethod __UNDOCUMENTED__
|
||||
* @param wrapper __UNDOCUMENTED__
|
||||
* @param stylesheet __UNDOCUMENTED__
|
||||
*/
|
||||
public BaseSchemaFormBuilder(String rootTagName,
|
||||
Source instanceSource,
|
||||
String action,
|
||||
String submitMethod,
|
||||
WrapperElementsBuilder wrapper,
|
||||
String stylesheet,
|
||||
String base,
|
||||
boolean userSchemaTypes) {
|
||||
super(rootTagName,
|
||||
instanceSource,
|
||||
action,
|
||||
submitMethod,
|
||||
wrapper,
|
||||
stylesheet,
|
||||
base,
|
||||
userSchemaTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new BaseSchemaFormBuilder object.
|
||||
*
|
||||
* @param rootTagName __UNDOCUMENTED__
|
||||
* @param instanceSource __UNDOCUMENTED__
|
||||
* @param action __UNDOCUMENTED__
|
||||
* @param submitMethod __UNDOCUMENTED__
|
||||
* @param wrapper __UNDOCUMENTED__
|
||||
* @param stylesheet __UNDOCUMENTED__
|
||||
*/
|
||||
public BaseSchemaFormBuilder(String rootTagName,
|
||||
Document instanceDocument,
|
||||
String action,
|
||||
String submitMethod,
|
||||
WrapperElementsBuilder wrapper,
|
||||
String stylesheet,
|
||||
String base,
|
||||
boolean userSchemaTypes) {
|
||||
super(rootTagName,
|
||||
instanceDocument,
|
||||
action,
|
||||
submitMethod,
|
||||
wrapper,
|
||||
stylesheet,
|
||||
base,
|
||||
userSchemaTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new BaseSchemaFormBuilder object.
|
||||
*
|
||||
* @param rootTagName __UNDOCUMENTED__
|
||||
* @param instanceHref __UNDOCUMENTED__
|
||||
* @param action __UNDOCUMENTED__
|
||||
* @param submitMethod __UNDOCUMENTED__
|
||||
* @param wrapper __UNDOCUMENTED__
|
||||
* @param stylesheet __UNDOCUMENTED__
|
||||
*/
|
||||
public BaseSchemaFormBuilder(String rootTagName,
|
||||
String instanceHref,
|
||||
String action,
|
||||
String submitMethod,
|
||||
WrapperElementsBuilder wrapper,
|
||||
String stylesheet,
|
||||
String base,
|
||||
boolean userSchemaTypes) {
|
||||
super(rootTagName,
|
||||
instanceHref,
|
||||
action,
|
||||
submitMethod,
|
||||
wrapper,
|
||||
stylesheet,
|
||||
base,
|
||||
userSchemaTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* __UNDOCUMENTED__
|
||||
*
|
||||
* @param text __UNDOCUMENTED__
|
||||
* @return __UNDOCUMENTED__
|
||||
*/
|
||||
public String createCaption(String text) {
|
||||
return StringUtil.capitalizeIdentifier(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* __UNDOCUMENTED__
|
||||
*
|
||||
* @param attribute __UNDOCUMENTED__
|
||||
* @return __UNDOCUMENTED__
|
||||
*/
|
||||
public String createCaption(XSAttributeDeclaration attribute) {
|
||||
// TODO: Improve i18n/l10n of caption - may have to use
|
||||
// a custom <appinfo> element in the XML Schema to do this.
|
||||
//
|
||||
return createCaption(attribute.getName());
|
||||
}
|
||||
|
||||
public String createCaption(XSAttributeUse attribute) {
|
||||
// TODO: Improve i18n/l10n of caption - may have to use
|
||||
// a custom <appinfo> element in the XML Schema to do this.
|
||||
//
|
||||
return createCaption(attribute.getAttrDeclaration().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* __UNDOCUMENTED__
|
||||
*
|
||||
* @param element __UNDOCUMENTED__
|
||||
* @return __UNDOCUMENTED__
|
||||
*/
|
||||
public String createCaption(XSElementDeclaration element) {
|
||||
// TODO: Improve i18n/l10n of caption - may have to use
|
||||
// a custom <appinfo> element in the XML Schema to do this.
|
||||
//
|
||||
return createCaption(element.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* __UNDOCUMENTED__
|
||||
*
|
||||
* @param element __UNDOCUMENTED__
|
||||
* @return __UNDOCUMENTED__
|
||||
*/
|
||||
public String createCaption(XSObject element) {
|
||||
// TODO: Improve i18n/l10n of caption - may have to use
|
||||
// a custom <appinfo> element in the XML Schema to do this.
|
||||
//
|
||||
if (element instanceof XSElementDeclaration) {
|
||||
return createCaption(((XSElementDeclaration) element).getName());
|
||||
} else if (element instanceof XSAttributeDeclaration) {
|
||||
return createCaption(((XSAttributeDeclaration) element).getName());
|
||||
} else if (element instanceof XSAttributeUse) {
|
||||
return createCaption(((XSAttributeUse) element).getAttrDeclaration().getName());
|
||||
} else
|
||||
LOGGER.warn("WARNING: createCaption: element is not an attribute nor an element: "
|
||||
+ element.getClass().getName());
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* __UNDOCUMENTED__
|
||||
*
|
||||
* @param xForm __UNDOCUMENTED__
|
||||
* @param caption __UNDOCUMENTED__
|
||||
* @param controlType __UNDOCUMENTED__
|
||||
* @return __UNDOCUMENTED__
|
||||
*/
|
||||
public Element createControlForAnyType(Document xForm,
|
||||
String caption,
|
||||
XSTypeDefinition controlType) {
|
||||
Element control =
|
||||
xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "textarea");
|
||||
this.setXFormsId(control);
|
||||
control.setAttributeNS(CHIBA_NS, getChibaNSPrefix() + "height", "3");
|
||||
|
||||
//label
|
||||
Element captionElement =
|
||||
(Element) control.appendChild(xForm.createElementNS(XFORMS_NS,
|
||||
getXFormsNSPrefix() + "label"));
|
||||
this.setXFormsId(captionElement);
|
||||
captionElement.appendChild(xForm.createTextNode(caption));
|
||||
|
||||
return control;
|
||||
}
|
||||
|
||||
/**
|
||||
* __UNDOCUMENTED__
|
||||
*
|
||||
* @param xForm __UNDOCUMENTED__
|
||||
* @param caption __UNDOCUMENTED__
|
||||
* @param controlType __UNDOCUMENTED__
|
||||
* @return __UNDOCUMENTED__
|
||||
*/
|
||||
public Element createControlForAtomicType(Document xForm,
|
||||
String caption,
|
||||
XSSimpleTypeDefinition controlType) {
|
||||
Element control;
|
||||
|
||||
//remove while select1 do not work correctly in repeats
|
||||
if ((controlType.getName() != null)
|
||||
&& controlType.getName().equals("boolean")) {
|
||||
control =
|
||||
xForm.createElementNS(XFORMS_NS,
|
||||
getXFormsNSPrefix() + "select1");
|
||||
control.setAttributeNS(XFORMS_NS,
|
||||
getXFormsNSPrefix() + "appearance",
|
||||
"full");
|
||||
this.setXFormsId(control);
|
||||
|
||||
Element item_true =
|
||||
xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "item");
|
||||
this.setXFormsId(item_true);
|
||||
Element label_true =
|
||||
xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "label");
|
||||
this.setXFormsId(label_true);
|
||||
Text label_true_text = xForm.createTextNode("true");
|
||||
label_true.appendChild(label_true_text);
|
||||
item_true.appendChild(label_true);
|
||||
|
||||
Element value_true =
|
||||
xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "value");
|
||||
this.setXFormsId(value_true);
|
||||
Text value_true_text = xForm.createTextNode("true");
|
||||
value_true.appendChild(value_true_text);
|
||||
item_true.appendChild(value_true);
|
||||
control.appendChild(item_true);
|
||||
|
||||
Element item_false =
|
||||
xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "item");
|
||||
this.setXFormsId(item_false);
|
||||
Element label_false =
|
||||
xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "label");
|
||||
this.setXFormsId(label_false);
|
||||
Text label_false_text = xForm.createTextNode("false");
|
||||
label_false.appendChild(label_false_text);
|
||||
item_false.appendChild(label_false);
|
||||
|
||||
Element value_false =
|
||||
xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "value");
|
||||
this.setXFormsId(value_false);
|
||||
Text value_false_text = xForm.createTextNode("false");
|
||||
value_false.appendChild(value_false_text);
|
||||
item_false.appendChild(value_false);
|
||||
control.appendChild(item_false);
|
||||
} else {
|
||||
control =
|
||||
xForm.createElementNS(XFORMS_NS, getXFormsNSPrefix() + "input");
|
||||
this.setXFormsId(control);
|
||||
}
|
||||
|
||||
//label
|
||||
Element captionElement =
|
||||
(Element) control.appendChild(xForm.createElementNS(XFORMS_NS,
|
||||
getXFormsNSPrefix() + "label"));
|
||||
this.setXFormsId(captionElement);
|
||||
captionElement.appendChild(xForm.createTextNode(caption));
|
||||
|
||||
return control;
|
||||
}
|
||||
|
||||
/**
|
||||
* __UNDOCUMENTED__
|
||||
*
|
||||
* @param xForm __UNDOCUMENTED__
|
||||
* @param controlType __UNDOCUMENTED__
|
||||
* @param caption __UNDOCUMENTED__
|
||||
* @param bindElement __UNDOCUMENTED__
|
||||
* @return __UNDOCUMENTED__
|
||||
*/
|
||||
public Element createControlForEnumerationType(Document xForm,
|
||||
XSSimpleTypeDefinition controlType,
|
||||
String caption,
|
||||
Element bindElement) {
|
||||
// TODO: Figure out an intelligent or user determined way to decide between
|
||||
// selectUI style (listbox, menu, combobox, radio) (radio and listbox best apply)
|
||||
// Possibly look for special appInfo section in the schema and if not present default to comboBox...
|
||||
//
|
||||
// For now, use radio if enumValues < DEFAULT_LONG_LIST_MAX_SIZE otherwise use combobox
|
||||
//
|
||||
StringList enumFacets = controlType.getLexicalEnumeration();
|
||||
int nbFacets = enumFacets.getLength();
|
||||
if (nbFacets > 0) {
|
||||
Vector enumValues = new Vector();
|
||||
|
||||
Element control =
|
||||
xForm.createElementNS(XFORMS_NS,
|
||||
getXFormsNSPrefix() + "select1");
|
||||
this.setXFormsId(control);
|
||||
|
||||
//label
|
||||
Element captionElement1 =
|
||||
(Element) control.appendChild(xForm.createElementNS(XFORMS_NS,
|
||||
getXFormsNSPrefix() + "label"));
|
||||
this.setXFormsId(captionElement1);
|
||||
captionElement1.appendChild(xForm.createTextNode(caption));
|
||||
|
||||
Element choices =
|
||||
xForm.createElementNS(XFORMS_NS,
|
||||
getXFormsNSPrefix() + "choices");
|
||||
this.setXFormsId(choices);
|
||||
|
||||
for (int i = 0; i < nbFacets; i++) {
|
||||
String facet = enumFacets.item(i);
|
||||
enumValues.add(facet);
|
||||
}
|
||||
|
||||
if (nbFacets
|
||||
< Long.parseLong(getProperty(SELECTONE_LONG_LIST_SIZE_PROP))) {
|
||||
control.setAttributeNS(XFORMS_NS,
|
||||
getXFormsNSPrefix() + "appearance",
|
||||
getProperty(SELECTONE_UI_CONTROL_SHORT_PROP));
|
||||
} else {
|
||||
control.setAttributeNS(XFORMS_NS,
|
||||
getXFormsNSPrefix() + "appearance",
|
||||
getProperty(SELECTONE_UI_CONTROL_LONG_PROP));
|
||||
|
||||
// add the "Please select..." instruction item for the combobox
|
||||
// and set the isValid attribute on the bind element to check for the "Please select..."
|
||||
// item to indicate that is not a valid value
|
||||
//
|
||||
{
|
||||
String pleaseSelect = "[Select1 " + caption + "]";
|
||||
Element item =
|
||||
xForm.createElementNS(XFORMS_NS,
|
||||
getXFormsNSPrefix() + "item");
|
||||
this.setXFormsId(item);
|
||||
choices.appendChild(item);
|
||||
|
||||
Element captionElement =
|
||||
xForm.createElementNS(XFORMS_NS,
|
||||
getXFormsNSPrefix() + "label");
|
||||
this.setXFormsId(captionElement);
|
||||
item.appendChild(captionElement);
|
||||
captionElement.appendChild(xForm.createTextNode(pleaseSelect));
|
||||
|
||||
Element value =
|
||||
xForm.createElementNS(XFORMS_NS,
|
||||
getXFormsNSPrefix() + "value");
|
||||
this.setXFormsId(value);
|
||||
item.appendChild(value);
|
||||
value.appendChild(xForm.createTextNode(pleaseSelect));
|
||||
|
||||
// not(purchaseOrder/state = '[Choose State]')
|
||||
//String isValidExpr = "not(" + bindElement.getAttributeNS(XFORMS_NS,"nodeset") + " = '" + pleaseSelect + "')";
|
||||
// ->no, not(. = '[Choose State]')
|
||||
String isValidExpr = "not( . = '" + pleaseSelect + "')";
|
||||
|
||||
//check if there was a constraint
|
||||
String constraint =
|
||||
bindElement.getAttributeNS(XFORMS_NS, "constraint");
|
||||
|
||||
if ((constraint != null) && !constraint.equals("")) {
|
||||
constraint = constraint + " and " + isValidExpr;
|
||||
} else {
|
||||
constraint = isValidExpr;
|
||||
}
|
||||
|
||||
bindElement.setAttributeNS(XFORMS_NS,
|
||||
getXFormsNSPrefix() + "constraint",
|
||||
constraint);
|
||||
}
|
||||
}
|
||||
|
||||
control.appendChild(choices);
|
||||
|
||||
addChoicesForSelectControl(xForm, choices, enumValues);
|
||||
|
||||
return control;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* __UNDOCUMENTED__
|
||||
*
|
||||
* @param xForm __UNDOCUMENTED__
|
||||
* @param listType __UNDOCUMENTED__
|
||||
* @param caption __UNDOCUMENTED__
|
||||
* @param bindElement __UNDOCUMENTED__
|
||||
* @return __UNDOCUMENTED__
|
||||
*/
|
||||
public Element createControlForListType(Document xForm,
|
||||
XSSimpleTypeDefinition listType,
|
||||
String caption,
|
||||
Element bindElement) {
|
||||
XSSimpleTypeDefinition controlType = listType.getItemType();
|
||||
|
||||
StringList enumFacets = controlType.getLexicalEnumeration();
|
||||
int nbFacets = enumFacets.getLength();
|
||||
if (nbFacets > 0) {
|
||||
Element control =
|
||||
xForm.createElementNS(XFORMS_NS,
|
||||
getXFormsNSPrefix() + "select");
|
||||
this.setXFormsId(control);
|
||||
|
||||
//label
|
||||
Element captionElement =
|
||||
(Element) control.appendChild(xForm.createElementNS(XFORMS_NS,
|
||||
getXFormsNSPrefix() + "label"));
|
||||
this.setXFormsId(captionElement);
|
||||
captionElement.appendChild(xForm.createTextNode(caption));
|
||||
|
||||
Vector enumValues = new Vector();
|
||||
for (int i = 0; i < nbFacets; i++) {
|
||||
String facet = enumFacets.item(i);
|
||||
enumValues.add(facet);
|
||||
}
|
||||
|
||||
// TODO: Figure out an intelligent or user determined way to decide between
|
||||
// selectUI style (listbox, menu, combobox, radio) (radio and listbox best apply)
|
||||
// Possibly look for special appInfo section in the schema and if not present default to checkBox...
|
||||
//
|
||||
// For now, use checkbox if there are < DEFAULT_LONG_LIST_MAX_SIZE items, otherwise use long control
|
||||
//
|
||||
if (enumValues.size()
|
||||
< Long.parseLong(getProperty(SELECTMANY_LONG_LIST_SIZE_PROP))) {
|
||||
control.setAttributeNS(XFORMS_NS,
|
||||
getXFormsNSPrefix() + "appearance",
|
||||
getProperty(SELECTMANY_UI_CONTROL_SHORT_PROP));
|
||||
} else {
|
||||
control.setAttributeNS(XFORMS_NS,
|
||||
getXFormsNSPrefix() + "appearance",
|
||||
getProperty(SELECTMANY_UI_CONTROL_LONG_PROP));
|
||||
}
|
||||
|
||||
Element choices =
|
||||
xForm.createElementNS(XFORMS_NS,
|
||||
getXFormsNSPrefix() + "choices");
|
||||
this.setXFormsId(choices);
|
||||
control.appendChild(choices);
|
||||
|
||||
addChoicesForSelectControl(xForm, choices, enumValues);
|
||||
|
||||
return control;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* __UNDOCUMENTED__
|
||||
*
|
||||
* @param xForm __UNDOCUMENTED__
|
||||
* @param node __UNDOCUMENTED__
|
||||
* @return __UNDOCUMENTED__
|
||||
*/
|
||||
public Element createHint(Document xForm, XSObject node) {
|
||||
XSAnnotation annotation = null;
|
||||
if (node instanceof XSElementDeclaration)
|
||||
annotation = ((XSElementDeclaration) node).getAnnotation();
|
||||
else if (node instanceof XSAttributeDeclaration)
|
||||
annotation = ((XSAttributeDeclaration) node).getAnnotation();
|
||||
else if (node instanceof XSAttributeUse)
|
||||
annotation =
|
||||
((XSAttributeUse) node).getAttrDeclaration().getAnnotation();
|
||||
|
||||
if (annotation != null)
|
||||
return addHintFromDocumentation(xForm, annotation);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* __UNDOCUMENTED__
|
||||
*
|
||||
* @param bindElement __UNDOCUMENTED__
|
||||
*/
|
||||
public void endBindElement(Element bindElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* __UNDOCUMENTED__
|
||||
*
|
||||
* @param controlElement __UNDOCUMENTED__
|
||||
* @param controlType __UNDOCUMENTED__
|
||||
*/
|
||||
public void endFormControl(Element controlElement,
|
||||
XSTypeDefinition controlType,
|
||||
int minOccurs,
|
||||
int maxOccurs) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* __UNDOCUMENTED__
|
||||
*
|
||||
* @param groupElement __UNDOCUMENTED__
|
||||
*/
|
||||
public void endFormGroup(Element groupElement,
|
||||
XSTypeDefinition controlType,
|
||||
int minOccurs,
|
||||
int maxOccurs,
|
||||
Element modelSection) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* __UNDOCUMENTED__
|
||||
*
|
||||
* @param bindElement __UNDOCUMENTED__
|
||||
* @param controlType __UNDOCUMENTED__
|
||||
* @param minOccurs __UNDOCUMENTED__
|
||||
* @param maxOccurs __UNDOCUMENTED__
|
||||
* @return __UNDOCUMENTED__
|
||||
*/
|
||||
public Element startBindElement(Element bindElement,
|
||||
XSTypeDefinition controlType,
|
||||
int minOccurs,
|
||||
int maxOccurs) {
|
||||
// START WORKAROUND
|
||||
// Due to a Chiba bug, anyType is not a recognized type name.
|
||||
// so, if this is an anyType, then we'll just skip the type
|
||||
// setting.
|
||||
//
|
||||
// type.getName() may be 'null' for anonymous types, so compare against
|
||||
// static string (see bug #1172541 on sf.net)
|
||||
if (!("anyType").equals(controlType.getName())) {
|
||||
Element enveloppe = bindElement.getOwnerDocument().getDocumentElement();
|
||||
String typeName = this.getXFormsTypeName(enveloppe, controlType);
|
||||
if (typeName != null && !typeName.equals(""))
|
||||
bindElement.setAttributeNS(XFORMS_NS,
|
||||
getXFormsNSPrefix() + "type",
|
||||
typeName);
|
||||
}
|
||||
|
||||
if (minOccurs == 0) {
|
||||
bindElement.setAttributeNS(XFORMS_NS,
|
||||
getXFormsNSPrefix() + "required",
|
||||
"false()");
|
||||
} else {
|
||||
bindElement.setAttributeNS(XFORMS_NS,
|
||||
getXFormsNSPrefix() + "required",
|
||||
"true()");
|
||||
}
|
||||
|
||||
//no more minOccurs & maxOccurs element: add a constraint if maxOccurs>1:
|
||||
//count(.) <= maxOccurs && count(.) >= minOccurs
|
||||
String minConstraint = null;
|
||||
String maxConstraint = null;
|
||||
|
||||
if (minOccurs > 1) {
|
||||
//if 0 or 1 -> no constraint (managed by "required")
|
||||
minConstraint = "count(.) >= " + minOccurs;
|
||||
}
|
||||
|
||||
if (maxOccurs > 1) {
|
||||
//if 1 or unbounded -> no constraint
|
||||
maxConstraint = "count(.) <= " + maxOccurs;
|
||||
}
|
||||
|
||||
String constraint = null;
|
||||
|
||||
if ((minConstraint != null) && (maxConstraint != null)) {
|
||||
constraint = minConstraint + " and " + maxConstraint;
|
||||
} else if (minConstraint != null) {
|
||||
constraint = minConstraint;
|
||||
} else {
|
||||
constraint = maxConstraint;
|
||||
}
|
||||
|
||||
if ((constraint != null) && !constraint.equals("")) {
|
||||
bindElement.setAttributeNS(XFORMS_NS,
|
||||
getXFormsNSPrefix() + "constraint",
|
||||
constraint);
|
||||
}
|
||||
|
||||
/*if (minOccurs != 1) {
|
||||
bindElement.setAttributeNS(XFORMS_NS,getXFormsNSPrefix() + "minOccurs",String.valueOf(minOccurs));
|
||||
}
|
||||
if (maxOccurs != 1) {
|
||||
bindElement.setAttributeNS(XFORMS_NS,getXFormsNSPrefix() + "maxOccurs",maxOccurs == -1 ? "unbounded" : String.valueOf((maxOccurs)));
|
||||
}*/
|
||||
return bindElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* __UNDOCUMENTED__
|
||||
*
|
||||
* @param controlElement __UNDOCUMENTED__
|
||||
* @param controlType __UNDOCUMENTED__
|
||||
* @return __UNDOCUMENTED__
|
||||
*/
|
||||
public Element startFormControl(Element controlElement,
|
||||
XSTypeDefinition controlType) {
|
||||
return controlElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* __UNDOCUMENTED__
|
||||
*
|
||||
* @param groupElement __UNDOCUMENTED__
|
||||
* @param schemaElement __UNDOCUMENTED__
|
||||
* @return __UNDOCUMENTED__
|
||||
*/
|
||||
public Element startFormGroup(Element groupElement,
|
||||
XSElementDeclaration schemaElement) {
|
||||
//groupElement.setAttributeNS(CHIBA_NS,getChibaNSPrefix() + "box-align",getProperty(GROUP_BOX_ALIGN_PROP));
|
||||
//groupElement.setAttributeNS(CHIBA_NS,getChibaNSPrefix() + "box-orient",getProperty(GROUP_BOX_ORIENT_PROP));
|
||||
//groupElement.setAttributeNS(CHIBA_NS,getChibaNSPrefix() + "caption-width",getProperty(GROUP_CAPTION_WIDTH_PROP));
|
||||
//groupElement.setAttributeNS(CHIBA_NS,getChibaNSPrefix() + "width",getProperty(GROUP_WIDTH_PROP));
|
||||
//groupElement.setAttributeNS(CHIBA_NS,getChibaNSPrefix() + "border",getProperty(GROUP_BORDER_PROP));
|
||||
return groupElement;
|
||||
}
|
||||
}
|
@@ -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.templating.xforms.schemabuilder;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Basic implementation of WrapperElementsBuilder, with no additional design
|
||||
*
|
||||
* @author - Sophie Ramel
|
||||
*/
|
||||
public class BaseWrapperElementsBuilder implements WrapperElementsBuilder {
|
||||
/**
|
||||
* Creates a new instance of BaseWrapperElementsBuilder
|
||||
*/
|
||||
public BaseWrapperElementsBuilder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* create the wrapper element of the different controls
|
||||
*
|
||||
* @param controlElement the control element (input, select, repeat, group, ...)
|
||||
* @return the wrapper element, already containing the control element
|
||||
*/
|
||||
public Element createControlsWrapper(Element controlElement) {
|
||||
return controlElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* creates the global enveloppe of the resulting document, and puts it in the document
|
||||
*
|
||||
* @return the enveloppe
|
||||
*/
|
||||
public Element createEnvelope(Document xForm) {
|
||||
Element envelopeElement = xForm.createElement("envelope");
|
||||
|
||||
//Element envelopeElement = xForm.createElementNS(CHIBA_NS, this.getChibaNSPrefix()+"envelope");
|
||||
xForm.appendChild(envelopeElement);
|
||||
|
||||
return envelopeElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* create the wrapper element of the form
|
||||
*
|
||||
* @param enveloppeElement the form element (chiba:form or other)
|
||||
* @return the wrapper element
|
||||
*/
|
||||
|
||||
public Element createFormWrapper(Element enveloppeElement) {
|
||||
//add a "body" element without NS
|
||||
Document doc = enveloppeElement.getOwnerDocument();
|
||||
Element body = doc.createElement("body");
|
||||
//body.appendChild(formElement);
|
||||
enveloppeElement.appendChild(body);
|
||||
return body;
|
||||
}
|
||||
|
||||
/**
|
||||
* create the element that will contain the content of the group (or repeat) element
|
||||
*
|
||||
* @param groupElement the group or repeat element
|
||||
* @return the wrapper element, already containing the content of the group element
|
||||
*/
|
||||
public Element createGroupContentWrapper(Element groupElement) {
|
||||
return groupElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* create the wrapper element of the xforms:model element
|
||||
*
|
||||
* @param modelElement the xforms:model element
|
||||
* @return the wrapper element, already containing the model
|
||||
*/
|
||||
public Element createModelWrapper(Element modelElement) {
|
||||
return modelElement;
|
||||
}
|
||||
}
|
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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.templating.xforms.schemabuilder;
|
||||
|
||||
|
||||
/**
|
||||
* This exception is thrown when implementations of <code>SchemaFormBuilder</code> encounters an
|
||||
* error building a form.
|
||||
*
|
||||
* @author Brian Dueck
|
||||
* @version $Id: FormBuilderException.java,v 1.4 2005/01/31 22:49:31 joernt Exp $
|
||||
*/
|
||||
public class FormBuilderException extends java.lang.Exception {
|
||||
private Exception cause = null;
|
||||
|
||||
/**
|
||||
* Creates a new instance of <code>FormBuilderException</code> without detail message.
|
||||
*/
|
||||
public FormBuilderException() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of <code>FormBuilderException</code> with the specified detail message.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
*/
|
||||
public FormBuilderException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of <code>FormBuilderException</code> with the specified root exception.
|
||||
*
|
||||
* @param x The root exception.
|
||||
*/
|
||||
public FormBuilderException(Exception x) {
|
||||
//THIS DOES NOT WORK WITH JDK 1.3 CAUSE THIS IS NEW IN JDK 1.4
|
||||
//super(x);
|
||||
super(x.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
$Log: FormBuilderException.java,v $
|
||||
Revision 1.4 2005/01/31 22:49:31 joernt
|
||||
added copyright notice
|
||||
|
||||
Revision 1.3 2004/08/15 14:14:07 joernt
|
||||
preparing release...
|
||||
-reformatted sources to fix mixture of tabs and spaces
|
||||
-optimized imports on all files
|
||||
|
||||
Revision 1.2 2003/10/02 15:15:49 joernt
|
||||
applied chiba jalopy settings to whole src tree
|
||||
|
||||
Revision 1.1 2003/07/12 12:22:48 joernt
|
||||
package refactoring: moved from xforms.builder
|
||||
Revision 1.1.1.1 2003/05/23 14:54:08 unl
|
||||
no message
|
||||
Revision 1.2 2003/02/19 09:09:15 soframel
|
||||
print the exception's message
|
||||
Revision 1.1 2002/12/11 14:50:42 soframel
|
||||
transferred the Schema2XForms generator from chiba2 to chiba1
|
||||
Revision 1.3 2002/06/11 17:13:03 joernt
|
||||
commented out jdk 1.3 incompatible constructor-impl
|
||||
Revision 1.2 2002/06/11 14:06:31 joernt
|
||||
commented out the jdk 1.4 constructor
|
||||
Revision 1.1 2002/05/22 22:24:34 joernt
|
||||
Brian's initial version of schema2xforms builder
|
||||
*/
|
@@ -0,0 +1,420 @@
|
||||
/*
|
||||
* 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.templating.xforms.schemabuilder;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.xerces.xs.*;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import javax.xml.transform.Source;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* An object that implements this interface can build an XForm that conforms to
|
||||
* the elements and attributes declared in an XML Schema.
|
||||
*
|
||||
* @author Brian Dueck
|
||||
* @version $Id: SchemaFormBuilder.java,v 1.16 2005/02/10 13:24:57 joernt Exp $
|
||||
*/
|
||||
public interface SchemaFormBuilder {
|
||||
|
||||
public final static Log LOGGER =
|
||||
LogFactory.getLog(SchemaFormBuilder.class);
|
||||
|
||||
/**
|
||||
* XMLSchema Instance Namespace declaration
|
||||
*/
|
||||
public static final String XMLSCHEMA_INSTANCE_NAMESPACE_URI = "http://www.w3.org/2001/XMLSchema-instance";
|
||||
|
||||
/**
|
||||
* XMLNS Namespace declaration.
|
||||
*/
|
||||
public static final String XMLNS_NAMESPACE_URI =
|
||||
"http://www.w3.org/2000/xmlns/";
|
||||
|
||||
/**
|
||||
* XML Namespace declaration
|
||||
*/
|
||||
public static final String XML_NAMESPACE_URI =
|
||||
"http://www.w3.org/XML/1998/namespace";
|
||||
|
||||
/**
|
||||
* XForms namespace declaration.
|
||||
*/
|
||||
public static final String XFORMS_NS = "http://www.w3.org/2002/xforms";
|
||||
|
||||
/**
|
||||
* Chiba namespace declaration.
|
||||
*/
|
||||
public static final String CHIBA_NS =
|
||||
"http://chiba.sourceforge.net/xforms";
|
||||
|
||||
/**
|
||||
* XLink namespace declaration.
|
||||
*/
|
||||
public static final String XLINK_NS = "http://www.w3.org/1999/xlink";
|
||||
|
||||
/**
|
||||
* XML Events namsepace declaration.
|
||||
*/
|
||||
public static final String XMLEVENTS_NS = "http://www.w3.org/2001/xml-events";
|
||||
|
||||
/**
|
||||
* Chiba prefix
|
||||
*/
|
||||
public static final String chibaNSPrefix = "chiba:";
|
||||
|
||||
/**
|
||||
* XForms prefix
|
||||
*/
|
||||
public static final String xformsNSPrefix = "xforms:";
|
||||
|
||||
/**
|
||||
* Xlink prefix
|
||||
*/
|
||||
public static final String xlinkNSPrefix = "xlink:";
|
||||
|
||||
/**
|
||||
* XMLSchema instance prefix *
|
||||
*/
|
||||
public static final String xmlSchemaInstancePrefix = "xsi:";
|
||||
|
||||
/**
|
||||
* XML Events prefix
|
||||
*/
|
||||
public static final String xmleventsNSPrefix = "ev:";
|
||||
|
||||
/**
|
||||
* __UNDOCUMENTED__
|
||||
*
|
||||
* @return __UNDOCUMENTED__
|
||||
*/
|
||||
public String getAction();
|
||||
|
||||
/**
|
||||
* __UNDOCUMENTED__
|
||||
*
|
||||
* @return __UNDOCUMENTED__
|
||||
*/
|
||||
public String getInstanceHref();
|
||||
|
||||
/**
|
||||
* __UNDOCUMENTED__
|
||||
*
|
||||
* @return __UNDOCUMENTED__
|
||||
*/
|
||||
public int getInstanceMode();
|
||||
|
||||
/**
|
||||
* __UNDOCUMENTED__
|
||||
*
|
||||
* @return __UNDOCUMENTED__
|
||||
*/
|
||||
public Source getInstanceSource();
|
||||
|
||||
/**
|
||||
* __UNDOCUMENTED__
|
||||
*
|
||||
* @return __UNDOCUMENTED__
|
||||
*/
|
||||
public Document getInstanceDocument();
|
||||
|
||||
/**
|
||||
* Get the current set of properties used by implementations of SchemaFormBuilder.
|
||||
*
|
||||
* @return The list of properties.
|
||||
*/
|
||||
public Properties getProperties();
|
||||
|
||||
/**
|
||||
* Sets the property to the specified value. If the property exists, its value is overwritten.
|
||||
*
|
||||
* @param key The implementation defined property key.
|
||||
* @param value The value for the property.
|
||||
*/
|
||||
public void setProperty(String key, String value);
|
||||
|
||||
/**
|
||||
* Gets the value for the specified property.
|
||||
*
|
||||
* @param key The implementation defined property key.
|
||||
* @return The property value if found, or null if the property cannot be located.
|
||||
*/
|
||||
public String getProperty(String key);
|
||||
|
||||
/**
|
||||
* Gets the value for the specified property, with a default if the property cannot be located.
|
||||
*
|
||||
* @param key The implementation defined property key.
|
||||
* @param defaultValue This value will be returned if the property does not exists.
|
||||
* @return The property value if found, or defaultValue if the property cannot be located.
|
||||
*/
|
||||
public String getProperty(String key, String defaultValue);
|
||||
|
||||
/**
|
||||
* Properties choosed by the user
|
||||
*/
|
||||
public String getRootTagName();
|
||||
|
||||
/**
|
||||
* __UNDOCUMENTED__
|
||||
*
|
||||
* @return __UNDOCUMENTED__
|
||||
*/
|
||||
public String getStylesheet();
|
||||
|
||||
/**
|
||||
* __UNDOCUMENTED__
|
||||
*
|
||||
* @return __UNDOCUMENTED__
|
||||
*/
|
||||
public String getSubmitMethod();
|
||||
|
||||
/**
|
||||
* Generate the XForm based on a user supplied XML Schema.
|
||||
*
|
||||
* @param inputURI The document source for the XML Schema.
|
||||
* @return The Document containing the XForm.
|
||||
* @throws org.chiba.tools.schemabuilder.FormBuilderException
|
||||
* If an error occurs building the XForm.
|
||||
*/
|
||||
public Document buildForm(String inputURI) throws FormBuilderException;
|
||||
|
||||
/**
|
||||
* Creates a caption for the provided text extracted from the XML Schema.
|
||||
* The implementation is responsible for reformatting the provided string to make it
|
||||
* suitable to be displayed to users of the XForm. This typically includes translating
|
||||
* XML tag name style identifiers (e.g. customerStreetAddress) into more reader friendly
|
||||
* captions (e.g. Customer Street Address).
|
||||
*
|
||||
* @param text The string value to be reformatted for use as a caption.
|
||||
* @return The caption.
|
||||
*/
|
||||
public String createCaption(String text);
|
||||
|
||||
/**
|
||||
* Creates a caption for the provided XML Schema attribute.
|
||||
* The implementation is responsible for providing an appropriate caption
|
||||
* suitable to be displayed to users of the XForm. This typically includes translating
|
||||
* XML tag name style identifiers (e.g. customerStreetAddress) into more reader friendly
|
||||
* captions (e.g. Customer Street Address).
|
||||
*
|
||||
* @param attribute The XML schema attribute for which a caption is required.
|
||||
* @return The caption.
|
||||
*/
|
||||
public String createCaption(XSAttributeDeclaration attribute);
|
||||
|
||||
/**
|
||||
* Creates a caption for the provided XML Schema element.
|
||||
* The implementation is responsible for providing an appropriate caption
|
||||
* suitable to be displayed to users of the XForm. This typically includes translating
|
||||
* XML tag name style identifiers (e.g. customerStreetAddress) into more reader friendly
|
||||
* captions (e.g. Customer Street Address).
|
||||
*
|
||||
* @param element The XML schema element for which a caption is required.
|
||||
* @return The caption.
|
||||
*/
|
||||
public String createCaption(XSElementDeclaration element);
|
||||
|
||||
/**
|
||||
* Creates a form control for an XML Schema any type.
|
||||
* <p/>
|
||||
* This method is called when the form builder determines a form control is required for
|
||||
* an any type.
|
||||
* The implementation of this method is responsible for creating an XML element of the
|
||||
* appropriate type to receive a value for <b>controlType</b>. The caller is responsible
|
||||
* for adding the returned element to the form and setting caption, bind, and other
|
||||
* standard elements and attributes.
|
||||
*
|
||||
* @param xForm The XForm document.
|
||||
* @param controlType The XML Schema type for which the form control is to be created.
|
||||
* @return The element for the form control.
|
||||
*/
|
||||
public Element createControlForAnyType(Document xForm,
|
||||
String caption,
|
||||
XSTypeDefinition controlType);
|
||||
|
||||
/**
|
||||
* Creates a form control for an XML Schema simple atomic type.
|
||||
* <p/>
|
||||
* This method is called when the form builder determines a form control is required for
|
||||
* an atomic type.
|
||||
* The implementation of this method is responsible for creating an XML element of the
|
||||
* appropriate type to receive a value for <b>controlType</b>. The caller is responsible
|
||||
* for adding the returned element to the form and setting caption, bind, and other
|
||||
* standard elements and attributes.
|
||||
*
|
||||
* @param xForm The XForm document.
|
||||
* @param controlType The XML Schema type for which the form control is to be created.
|
||||
* @return The element for the form control.
|
||||
*/
|
||||
public Element createControlForAtomicType(Document xForm,
|
||||
String caption,
|
||||
XSSimpleTypeDefinition controlType);
|
||||
|
||||
/**
|
||||
* Creates a form control for an XML Schema simple type restricted by an enumeration.
|
||||
* This method is called when the form builder determines a form control is required for
|
||||
* an enumerated type.
|
||||
* The implementation of this method is responsible for creating an XML element of the
|
||||
* appropriate type to receive a value for <b>controlType</b>. The caller is responsible
|
||||
* for adding the returned element to the form and setting caption, bind, and other
|
||||
* standard elements and attributes.
|
||||
*
|
||||
* @param xForm The XForm document.
|
||||
* @param controlType The XML Schema type for which the form control is to be created.
|
||||
* @param caption The caption for the form control. The caller The purpose of providing the caption
|
||||
* is to permit the implementation to add a <b>[Select1 .... ]</b> message that involves the caption.
|
||||
* @param bindElement The bind element for this control. The purpose of providing the bind element
|
||||
* is to permit the implementation to add a isValid attribute to the bind element that prevents
|
||||
* the <b>[Select1 .... ]</b> item from being selected.
|
||||
* @return The element for the form control.
|
||||
*/
|
||||
public Element createControlForEnumerationType(Document xForm,
|
||||
XSSimpleTypeDefinition controlType,
|
||||
String caption,
|
||||
Element bindElement);
|
||||
|
||||
/**
|
||||
* Creates a form control for an XML Schema simple list type.
|
||||
* <p/>
|
||||
* This method is called when the form builder determines a form control is required for
|
||||
* a list type.
|
||||
* The implementation of this method is responsible for creating an XML element of the
|
||||
* appropriate type to receive a value for <b>controlType</b>. The caller is responsible
|
||||
* for adding the returned element to the form and setting caption, bind, and other
|
||||
* standard elements and attributes.
|
||||
*
|
||||
* @param xForm The XForm document.
|
||||
* @param listType The XML Schema list type for which the form control is to be created.
|
||||
* @param caption The caption for the form control. The caller The purpose of providing the caption
|
||||
* is to permit the implementation to add a <b>[Select1 .... ]</b> message that involves the caption.
|
||||
* @param bindElement The bind element for this control. The purpose of providing the bind element
|
||||
* is to permit the implementation to add a isValid attribute to the bind element that prevents
|
||||
* the <b>[Select1 .... ]</b> item from being selected.
|
||||
* @return The element for the form control.
|
||||
*/
|
||||
public Element createControlForListType(Document xForm,
|
||||
XSSimpleTypeDefinition listType,
|
||||
String caption,
|
||||
Element bindElement);
|
||||
|
||||
/**
|
||||
* Creates a hint XML Schema annotated node (AttributeDecl or ElementDecl).
|
||||
* The implementation is responsible for providing an xforms:hint element for the
|
||||
* specified schemaNode suitable to be dsipalayed to users of the XForm. The caller
|
||||
* is responsible for adding the returned element to the form.
|
||||
* This typically includes extracting documentation from the element/attribute's
|
||||
* annotation/documentation elements and/or extracting the same information from the
|
||||
* element/attribute's type annotation/documentation.
|
||||
*
|
||||
* @param schemaNode The string value to be reformatted for use as a caption.
|
||||
* @return The xforms:hint element. If a null value is returned a hint is not added.
|
||||
*/
|
||||
public Element createHint(Document xForm, XSObject schemaNode);
|
||||
|
||||
/**
|
||||
* This method is invoked after the form builder is finished creating and processing
|
||||
* a bind element. Implementations may choose to use this method to add/inspect/modify
|
||||
* the bindElement prior to the builder moving onto the next bind element.
|
||||
*
|
||||
* @param bindElement The bind element being processed.
|
||||
*/
|
||||
public void endBindElement(Element bindElement);
|
||||
|
||||
/**
|
||||
* This method is invoked after the form builder is finished creating and processing
|
||||
* a form control. Implementations may choose to use this method to add/inspect/modify
|
||||
* the controlElement prior to the builder moving onto the next control.
|
||||
*
|
||||
* @param controlElement The form control element that was created.
|
||||
* @param controlType The XML Schema type for which <b>controlElement</b> was created.
|
||||
*/
|
||||
public void endFormControl(Element controlElement,
|
||||
XSTypeDefinition controlType,
|
||||
int minOccurs,
|
||||
int maxOccurs);
|
||||
|
||||
/**
|
||||
* __UNDOCUMENTED__
|
||||
*
|
||||
* @param groupElement __UNDOCUMENTED__
|
||||
*/
|
||||
public void endFormGroup(Element groupElement,
|
||||
XSTypeDefinition controlType,
|
||||
int minOccurs,
|
||||
int maxOccurs,
|
||||
Element modelSection);
|
||||
|
||||
/**
|
||||
* Reset the SchemaFormBuilder to default values.
|
||||
*/
|
||||
public void reset();
|
||||
|
||||
/**
|
||||
* This method is invoked after an xforms:bind element is created for the specified SimpleType.
|
||||
* The implementation is responsible for setting setting any/all bind attributes
|
||||
* except for <b>id</b> and <b>ref</b> - these have been automatically set
|
||||
* by the caller (and should not be touched by implementation of startBindElement)
|
||||
* prior to invoking startBindElement.
|
||||
* The caller automatically adds the returned element to the model section of
|
||||
* the form.
|
||||
*
|
||||
* @param bindElement The bindElement being processed.
|
||||
* @param controlType XML Schema type of the element/attribute this bind is for.
|
||||
* @param minOccurs The minimum number of occurences for this element/attribute.
|
||||
* @param maxOccurs The maximum number of occurences for this element/attribute.
|
||||
* @return The bind Element to use in the XForm - bindElement or a replacement.
|
||||
*/
|
||||
public Element startBindElement(Element bindElement,
|
||||
XSTypeDefinition controlType,
|
||||
int minOccurs,
|
||||
int maxOccurs);
|
||||
|
||||
/**
|
||||
* This method is invoked after the form builder creates a form control
|
||||
* via a createControlForXXX() method but prior to decorating the form control
|
||||
* with common attributes such as a caption, hint, help text elements,
|
||||
* bind attributes, etc.
|
||||
* The returned element is used in the XForm in place of controlElement.
|
||||
* Implementations may choose to use this method to substitute controlElement
|
||||
* with a different element, or perform any other processing on controlElement
|
||||
* prior to it being added to the form.
|
||||
*
|
||||
* @param controlElement The form control element that was created.
|
||||
* @param controlType The XML Schema type for which <b>controlElement</b> was created.
|
||||
* @return The Element to use in the XForm - controlElement or a replacement.
|
||||
*/
|
||||
public Element startFormControl(Element controlElement,
|
||||
XSTypeDefinition controlType);
|
||||
|
||||
/**
|
||||
* This method is invoked after an xforms:group element is created for the specified
|
||||
* ElementDecl. A group is created whenever an element is encountered in the XML Schema
|
||||
* that contains other elements and attributes (complex types or mixed content types).
|
||||
* The caller automatically adds the returned element to the XForm.
|
||||
*
|
||||
* @param groupElement The groupElement being processed.
|
||||
* @param schemaElement The schemaElement for the group.
|
||||
* @return The group Element to use in the XForm - groupElement or a replacement. If a null
|
||||
* value is returned, the group is not created.
|
||||
*/
|
||||
public Element startFormGroup(Element groupElement,
|
||||
XSElementDeclaration schemaElement);
|
||||
}
|
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.templating.xforms.schemabuilder;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* This interface provides methods to create the "wrappers" elements that will contain the XForms document.
|
||||
* These elements can be:
|
||||
* - the first "enveloppe" element
|
||||
* - other elements specific to a destination language or platform (ex: XHTML tags)
|
||||
*
|
||||
* @author Sophie Ramel
|
||||
*/
|
||||
public interface WrapperElementsBuilder {
|
||||
/**
|
||||
* create the wrapper element of the form (exemple_ "body" for HTML)
|
||||
*
|
||||
* @param enveloppeElement the containing enveloppe
|
||||
* @return the wrapper element, already added in the enveloppe
|
||||
*/
|
||||
public Element createFormWrapper(Element enveloppeElement);
|
||||
|
||||
/**
|
||||
* create the wrapper element of the different controls
|
||||
*
|
||||
* @param controlElement the control element (input, select, repeat, group, ...)
|
||||
* @return the wrapper element, already containing the control element
|
||||
*/
|
||||
public Element createControlsWrapper(Element controlElement);
|
||||
|
||||
/**
|
||||
* creates the global enveloppe of the resulting document, and puts it in the document
|
||||
*
|
||||
* @return the enveloppe
|
||||
*/
|
||||
public Element createEnvelope(Document xForm);
|
||||
|
||||
/**
|
||||
* create the element that will contain the content of the group (or repeat) element
|
||||
*
|
||||
* @param groupElement the group or repeat element
|
||||
* @return - the wrapper element, already containing the content of the group element
|
||||
*/
|
||||
public Element createGroupContentWrapper(Element groupElement);
|
||||
|
||||
/**
|
||||
* create the wrapper element of the xforms:model element
|
||||
*
|
||||
* @param modelElement the xforms:model element
|
||||
* @return - the wrapper element, already containing the model
|
||||
*/
|
||||
public Element createModelWrapper(Element modelElement);
|
||||
}
|
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* 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.templating.xforms.schemabuilder;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Text;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Iterator;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* XHTML implementation of WrapperElementsBuilder: allows to wrap the XForm document in XHTML tags.
|
||||
*
|
||||
* @author Sophie Ramel
|
||||
*/
|
||||
public class XHTMLWrapperElementsBuilder implements WrapperElementsBuilder {
|
||||
|
||||
private final static String XHTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
private final static String XHTML_PREFIX = "xhtml";
|
||||
// private final static String XHTML_NS = "http://www.w3.org/2002/06/xhtml2";
|
||||
// private final static String XHTML_PREFIX = "html";
|
||||
|
||||
private String title;
|
||||
private final Vector links = new Vector();
|
||||
private final Vector meta = new Vector();
|
||||
private final Hashtable namespaces = new Hashtable();
|
||||
|
||||
/**
|
||||
* Creates a new instance of XHTMLWrapperElementsBuilder
|
||||
*/
|
||||
public XHTMLWrapperElementsBuilder() { }
|
||||
|
||||
/**
|
||||
* add a tag "title" in the header of the HTML document
|
||||
*/
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
/**
|
||||
* add a tag "link" in the header of the HTML document
|
||||
*
|
||||
* @param href the "href" parameter of the "link" tag
|
||||
* @param type the "type" parameter of the "link" tag
|
||||
* @param rel the "rel" parameter of the "link" tag
|
||||
*/
|
||||
public void addLink(String href, String type, String rel) {
|
||||
String[] l = { href, type, rel };
|
||||
links.add(l);
|
||||
}
|
||||
|
||||
/**
|
||||
* add a tag "meta" in the header of the HTML document
|
||||
*
|
||||
* @param http_equiv the "http-equiv" parameter of the "META" tag
|
||||
* @param name the "name" parameter of the "META" tag
|
||||
* @param content the "content" parameter of the "META" tag
|
||||
* @param scheme the "scheme" parameter of the "META" tag
|
||||
*/
|
||||
public void addMeta(String http_equiv,
|
||||
String name,
|
||||
String content,
|
||||
String scheme) {
|
||||
String[] s = new String[] { http_equiv, name, content, scheme};
|
||||
meta.add(s);
|
||||
}
|
||||
|
||||
public void addNamespaceDeclaration(String prefix, String url) {
|
||||
namespaces.put(prefix, url);
|
||||
}
|
||||
|
||||
/**
|
||||
* create the wrapper element of the different controls
|
||||
*
|
||||
* @param controlElement the control element (input, select, repeat, group, ...)
|
||||
* @return the wrapper element, already containing the control element
|
||||
*/
|
||||
public Element createControlsWrapper(Element controlElement) {
|
||||
return controlElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* creates the global enveloppe of the resulting document, and puts it in the document
|
||||
*
|
||||
* @return the enveloppe
|
||||
*/
|
||||
public Element createEnvelope(Document doc) {
|
||||
Element html = doc.createElementNS(XHTML_NS, XHTML_PREFIX + ":html");
|
||||
//set namespace attribute
|
||||
html.setAttributeNS(SchemaFormBuilder.XMLNS_NAMESPACE_URI,
|
||||
"xmlns:" + XHTML_PREFIX,
|
||||
XHTMLWrapperElementsBuilder.XHTML_NS);
|
||||
doc.appendChild(html);
|
||||
|
||||
//other namespaces
|
||||
Enumeration enumeration = namespaces.keys();
|
||||
while (enumeration.hasMoreElements()) {
|
||||
String prefix = (String) enumeration.nextElement();
|
||||
String ns = (String) namespaces.get(prefix);
|
||||
html.setAttributeNS(SchemaFormBuilder.XMLNS_NAMESPACE_URI,
|
||||
"xmlns:" + prefix,
|
||||
ns);
|
||||
|
||||
}
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
/**
|
||||
* create the element that will contain the content of the group (or repeat) element
|
||||
*
|
||||
* @param groupElement the group or repeat element
|
||||
* @return the wrapper element
|
||||
*/
|
||||
public Element createGroupContentWrapper(Element groupElement) {
|
||||
return groupElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* create the wrapper element of the form
|
||||
*
|
||||
* @param enveloppeElement the form element (chiba:form or other)
|
||||
* @return the wrapper element
|
||||
*/
|
||||
|
||||
public Element createFormWrapper(Element enveloppeElement) {
|
||||
Document doc = enveloppeElement.getOwnerDocument();
|
||||
Element body = doc.createElementNS(XHTML_NS, XHTML_PREFIX + ":body");
|
||||
//body.appendChild(formElement);
|
||||
enveloppeElement.appendChild(body);
|
||||
return body;
|
||||
}
|
||||
|
||||
/**
|
||||
* create the wrapper element of the xforms:model element
|
||||
*
|
||||
* @param modelElement the xforms:model element
|
||||
* @return the wrapper element, already containing the model
|
||||
*/
|
||||
public Element createModelWrapper(Element modelElement) {
|
||||
Document doc = modelElement.getOwnerDocument();
|
||||
Element head = doc.createElementNS(XHTML_NS, XHTML_PREFIX + ":head");
|
||||
head.appendChild(modelElement);
|
||||
|
||||
//eventually add other info
|
||||
if ((title != null) && !title.equals("")) {
|
||||
Element title_el = doc.createElementNS(XHTML_NS, XHTML_PREFIX + ":title");
|
||||
Text title_text = doc.createTextNode(title);
|
||||
title_el.appendChild(title_text);
|
||||
head.appendChild(title_el);
|
||||
}
|
||||
|
||||
if ((meta != null) && !meta.isEmpty()) {
|
||||
Iterator it = meta.iterator();
|
||||
|
||||
while (it.hasNext()) {
|
||||
String[] m = (String[]) it.next();
|
||||
String http_equiv = m[0];
|
||||
String name = m[1];
|
||||
String content = m[2];
|
||||
String scheme = m[3];
|
||||
|
||||
Element meta_el = doc.createElementNS(XHTML_NS, XHTML_PREFIX + ":META");
|
||||
head.appendChild(meta_el);
|
||||
|
||||
//attributes
|
||||
if ((http_equiv != null) && !http_equiv.equals("")) {
|
||||
meta_el.setAttributeNS(XHTML_NS, XHTML_PREFIX + ":http-equiv", http_equiv);
|
||||
}
|
||||
|
||||
if ((name != null) && !name.equals("")) {
|
||||
meta_el.setAttributeNS(XHTML_NS, XHTML_PREFIX + ":name", name);
|
||||
}
|
||||
|
||||
if ((content != null) && !content.equals("")) {
|
||||
meta_el.setAttributeNS(XHTML_NS, XHTML_PREFIX + ":content", content);
|
||||
}
|
||||
|
||||
if ((scheme != null) && !scheme.equals("")) {
|
||||
meta_el.setAttributeNS(XHTML_NS, XHTML_PREFIX + ":scheme", scheme);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((links != null) && !links.isEmpty()) {
|
||||
Iterator it = links.iterator();
|
||||
|
||||
while (it.hasNext()) {
|
||||
String[] l = (String[]) it.next();
|
||||
String href = l[0];
|
||||
String type = l[1];
|
||||
String rel = l[2];
|
||||
|
||||
Element link_el = doc.createElementNS(XHTML_NS, XHTML_PREFIX + ":LINK");
|
||||
head.appendChild(link_el);
|
||||
|
||||
//attributes
|
||||
if ((href != null) && !href.equals("")) {
|
||||
link_el.setAttributeNS(XHTML_NS, XHTML_PREFIX + ":href", href);
|
||||
}
|
||||
|
||||
if ((type != null) && !type.equals("")) {
|
||||
link_el.setAttributeNS(XHTML_NS, XHTML_PREFIX + ":type", type);
|
||||
}
|
||||
|
||||
if ((rel != null) && !rel.equals("")) {
|
||||
link_el.setAttributeNS(XHTML_NS, XHTML_PREFIX + ":rel", rel);
|
||||
}
|
||||
}
|
||||
}
|
||||
return head;
|
||||
}
|
||||
}
|
@@ -0,0 +1,472 @@
|
||||
package org.alfresco.web.templating.xforms.servlet;
|
||||
|
||||
import org.alfresco.web.app.Application;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.commons.httpclient.Cookie;
|
||||
import org.chiba.adapter.ChibaAdapter;
|
||||
import org.alfresco.web.templating.xforms.flux.FluxAdapter;
|
||||
import org.chiba.tools.xslt.StylesheetLoader;
|
||||
import org.chiba.tools.xslt.UIGenerator;
|
||||
import org.chiba.tools.xslt.XSLTGenerator;
|
||||
import org.chiba.xml.xforms.config.Config;
|
||||
import org.chiba.xml.xforms.exception.XFormsException;
|
||||
import org.chiba.xml.xforms.connector.http.AbstractHTTPConnector;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.*;
|
||||
import java.io.*;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The ChibaServlet handles all interactions between client and
|
||||
* form-processor (ChibaBean) for the whole lifetime of a form-filling session.
|
||||
* <br>
|
||||
* The Processor will be started through a Get-request from the client
|
||||
* pointing to the desired form-container. The Processor instance will
|
||||
* be stored in a Session-object.<br>
|
||||
* <br>
|
||||
* All further interaction will be handled through Post-requests.
|
||||
* Incoming request params will be mapped to data and action-handlers.
|
||||
*
|
||||
* @author Joern Turner
|
||||
* @author Ulrich Nicolas Lissé
|
||||
* @author William Boyd
|
||||
* @version $Id: ChibaServlet.java,v 1.14 2005/12/21 22:59:27 unl Exp $
|
||||
*/
|
||||
public class ChibaServlet extends HttpServlet {
|
||||
//init-params
|
||||
private static Log logger = LogFactory.getLog(ChibaServlet.class);
|
||||
|
||||
|
||||
private static final String FORM_PARAM_NAME = "form";
|
||||
private static final String XSL_PARAM_NAME = "xslt";
|
||||
private static final String CSS_PARAM_NAME = "css";
|
||||
private static final String ACTIONURL_PARAM_NAME = "action_url";
|
||||
|
||||
public static final String CHIBA_ADAPTER = "chiba.adapter";
|
||||
public static final String CHIBA_UI_GENERATOR = "chiba.ui.generator";
|
||||
public static final String CHIBA_SUBMISSION_RESPONSE = "chiba.submission.response";
|
||||
|
||||
/*
|
||||
* It is not thread safe to modify these variables once the
|
||||
* init(ServletConfig) method has been called
|
||||
*/
|
||||
// the absolute path to the Chiba config-file
|
||||
protected String configPath = null;
|
||||
|
||||
// the rootdir of this app; forms + documents fill be searched under this root
|
||||
protected String contextRoot = null;
|
||||
|
||||
// where uploaded files are stored
|
||||
protected String uploadDir = null;
|
||||
|
||||
protected String stylesPath = null;
|
||||
|
||||
protected String agent;
|
||||
|
||||
|
||||
/**
|
||||
* Returns a short description of the servlet.
|
||||
*
|
||||
* @return - Returns a short description of the servlet.
|
||||
*/
|
||||
public String getServletInfo() {
|
||||
return "Servlet Controller for Chiba XForms Processor";
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys the servlet.
|
||||
*/
|
||||
public void destroy() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the servlet.
|
||||
*
|
||||
* @param config - the ServletConfig object
|
||||
* @throws javax.servlet.ServletException
|
||||
*/
|
||||
public void init(ServletConfig config) throws ServletException {
|
||||
super.init(config);
|
||||
|
||||
logger.info("--------------- initing ChibaServlet... ---------------");
|
||||
//read some params from web-inf
|
||||
contextRoot = getServletConfig().getServletContext().getRealPath("");
|
||||
if (contextRoot == null)
|
||||
contextRoot = getServletConfig().getServletContext().getRealPath(".");
|
||||
|
||||
//get the relative path to the chiba config-file
|
||||
String path = getServletConfig().getInitParameter("chiba.config");
|
||||
|
||||
//get the real path for the config-file
|
||||
if (path != null) {
|
||||
configPath = getServletConfig().getServletContext().getRealPath(path);
|
||||
}
|
||||
|
||||
//get the path for the stylesheets
|
||||
path = getServletConfig().getServletContext().getInitParameter("chiba.xforms.stylesPath");
|
||||
|
||||
//get the real path for the stylesheets and configure a new StylesheetLoader with it
|
||||
if (path != null) {
|
||||
stylesPath = getServletConfig().getServletContext().getRealPath(path);
|
||||
logger.info("stylesPath: " + stylesPath);
|
||||
}
|
||||
|
||||
//uploadDir = contextRoot + "/" + getServletConfig().getServletContext().getInitParameter("chiba.upload");
|
||||
uploadDir = getServletConfig().getServletContext().getInitParameter("chiba.upload");
|
||||
|
||||
//Security constraint
|
||||
if (uploadDir != null) {
|
||||
if (uploadDir.toUpperCase().indexOf("WEB-INF") >= 0) {
|
||||
throw new ServletException("Chiba security constraint: uploadDir '" + uploadDir + "' not allowed");
|
||||
}
|
||||
}
|
||||
|
||||
//user-agent mappings
|
||||
agent = getServletConfig().getServletContext().getInitParameter("chiba.useragent.ajax.path");
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a new form-editing session.<br>
|
||||
* <p/>
|
||||
* The default value of a number of settings can be overridden as follows:
|
||||
* <p/>
|
||||
* 1. The uru of the xform to be displayed can be specified by using a param name of 'form' and a param value
|
||||
* of the location of the xform file as follows, which will attempt to load the current xforms file.
|
||||
* <p/>
|
||||
* http://localhost:8080/chiba-0.9.3/XFormsServlet?form=/forms/hello.xhtml
|
||||
* <p/>
|
||||
* 2. The uru of the CSS file used to style the form can be specified using a param name of 'css' as follows:
|
||||
* <p/>
|
||||
* http://localhost:8080/chiba-0.9.3/XFormsServlet?form=/forms/hello.xhtml&css=/chiba/my.css
|
||||
* <p/>
|
||||
* 3. The uri of the XSLT file used to generate the form can be specified using a param name of 'xslt' as follows:
|
||||
* <p/>
|
||||
* http://localhost:8080/chiba-0.9.3/XFormsServlet?form=/forms/hello.xhtml&xslt=/chiba/my.xslt
|
||||
* <p/>
|
||||
* 4. Besides these special params arbitrary other params can be passed via the GET-string and will be available
|
||||
* in the context map of ChibaBean. This means they can be used as instance data (with the help of ContextResolver)
|
||||
* or to set params for URI resolution.
|
||||
*
|
||||
* @param request servlet request
|
||||
* @param response servlet response
|
||||
* @throws javax.servlet.ServletException
|
||||
* @throws java.io.IOException
|
||||
* @see org.chiba.xml.xforms.connector.context.ContextResolver
|
||||
* @see org.chiba.xml.xforms.connector.ConnectorFactory
|
||||
*/
|
||||
protected void doGet(HttpServletRequest request,
|
||||
HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
|
||||
ChibaAdapter adapter = null;
|
||||
HttpSession session = request.getSession(true);
|
||||
|
||||
logger.info("--------------- new XForms session ---------------");
|
||||
try {
|
||||
//kill everything that may have lived before
|
||||
session.removeAttribute(CHIBA_ADAPTER);
|
||||
session.removeAttribute(CHIBA_UI_GENERATOR);
|
||||
|
||||
// determine Form to load
|
||||
String formURI = /*getRequestURI(request) +*/ request.getParameter(FORM_PARAM_NAME);
|
||||
logger.info("formURI: " + formURI);
|
||||
String xslFile = request.getParameter(XSL_PARAM_NAME);
|
||||
String css = request.getParameter(CSS_PARAM_NAME);
|
||||
String actionURL = getActionURL(request, response,true);
|
||||
logger.info("setting up adapeter");
|
||||
|
||||
//setup Adapter
|
||||
adapter = setupAdapter(new FluxAdapter(session), session, formURI);
|
||||
setContextParams(request, adapter);
|
||||
storeCookies(request, adapter);
|
||||
adapter.init();
|
||||
|
||||
if (load(adapter, response)) return;
|
||||
if (replaceAll(adapter, response)) return;
|
||||
|
||||
response.setContentType("text/html");
|
||||
PrintWriter out = response.getWriter();
|
||||
|
||||
logger.info("generating ui");
|
||||
|
||||
UIGenerator uiGenerator = createUIGenerator(request, actionURL, xslFile, css);
|
||||
uiGenerator.setInputNode(adapter.getXForms());
|
||||
uiGenerator.setOutput(out);
|
||||
uiGenerator.generate();
|
||||
|
||||
//store adapter in session
|
||||
session.setAttribute(CHIBA_ADAPTER, adapter);
|
||||
session.setAttribute(CHIBA_UI_GENERATOR,uiGenerator);
|
||||
|
||||
out.close();
|
||||
logger.info("done!");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
shutdown(adapter, session, e, response, request);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* configures the an Adapter for interacting with the XForms processor (ChibaBean). The Adapter itself
|
||||
* will create the XFormsProcessor (ChibaBean) and configure it for processing.
|
||||
*
|
||||
* If you'd like to use a different source of XForms documents e.g. DOM you should extend this class and
|
||||
* overwrite this method. Please take care to also set the baseURI of the processor to a reasonable value
|
||||
* cause this will be the fundament for all URI resolutions taking place.
|
||||
*
|
||||
* @param adapter the ChibaAdapter implementation to setup
|
||||
* @param session - the Servlet session
|
||||
* @param formPath - the relative location where forms are stored
|
||||
* @return ServletAdapter
|
||||
*/
|
||||
protected ChibaAdapter setupAdapter(ChibaAdapter adapter,
|
||||
HttpSession session,
|
||||
String formPath)
|
||||
throws XFormsException, URISyntaxException {
|
||||
|
||||
adapter.createXFormsProcessor();
|
||||
|
||||
if ((configPath != null) && !(configPath.equals(""))) {
|
||||
adapter.setConfigPath(configPath);
|
||||
}
|
||||
adapter.setXForms(new URI(formPath));
|
||||
adapter.setBaseURI(formPath);
|
||||
adapter.setUploadDestination(uploadDir);
|
||||
|
||||
Map servletMap = new HashMap();
|
||||
servletMap.put(ChibaAdapter.SESSION_ID, session.getId());
|
||||
adapter.setContextParam(ChibaAdapter.SUBMISSION_RESPONSE, servletMap);
|
||||
|
||||
return adapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* stores cookies that may exist in request and passes them on to processor for usage in
|
||||
* HTTPConnectors. Instance loading and submission then uses these cookies. Important for
|
||||
* applications using auth.
|
||||
*
|
||||
* @param request the servlet request
|
||||
* @param adapter the Chiba adapter instance
|
||||
*/
|
||||
protected void storeCookies(HttpServletRequest request,ChibaAdapter adapter){
|
||||
javax.servlet.http.Cookie[] cookiesIn = request.getCookies();
|
||||
if (cookiesIn != null) {
|
||||
Cookie[] commonsCookies = new org.apache.commons.httpclient.Cookie[cookiesIn.length];
|
||||
for (int i = 0; i < cookiesIn.length; i += 1) {
|
||||
javax.servlet.http.Cookie c = cookiesIn[i];
|
||||
Cookie newCookie = new Cookie(c.getDomain(),
|
||||
c.getName(),
|
||||
c.getValue(),
|
||||
c.getPath(),
|
||||
c.getMaxAge(),
|
||||
c.getSecure());
|
||||
commonsCookies[i] = newCookie;
|
||||
}
|
||||
adapter.setContextParam(AbstractHTTPConnector.REQUEST_COOKIE,commonsCookies);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* creates and configures the UI generating component.
|
||||
* @param request
|
||||
* @param actionURL
|
||||
* @param xslFile
|
||||
* @param css
|
||||
* @return
|
||||
* @throws XFormsException
|
||||
*/
|
||||
protected UIGenerator createUIGenerator(HttpServletRequest request,
|
||||
String actionURL,
|
||||
String xslFile,
|
||||
String css)
|
||||
throws XFormsException {
|
||||
StylesheetLoader stylesheetLoader = new StylesheetLoader(stylesPath);
|
||||
if (xslFile != null){
|
||||
stylesheetLoader.setStylesheetFile(xslFile);
|
||||
}
|
||||
UIGenerator uiGenerator = new XSLTGenerator(stylesheetLoader);
|
||||
|
||||
//set parameters
|
||||
uiGenerator.setParameter("contextroot",request.getContextPath());
|
||||
uiGenerator.setParameter("action-url",actionURL);
|
||||
uiGenerator.setParameter("debug-enabled", true /*String.valueOf(logger.isDebugEnabled()) */);
|
||||
String selectorPrefix = Config.getInstance().getProperty(HttpRequestHandler.SELECTOR_PREFIX_PROPERTY,
|
||||
HttpRequestHandler.SELECTOR_PREFIX_DEFAULT);
|
||||
uiGenerator.setParameter("selector-prefix", selectorPrefix);
|
||||
String removeUploadPrefix = Config.getInstance().getProperty(HttpRequestHandler.REMOVE_UPLOAD_PREFIX_PROPERTY,
|
||||
HttpRequestHandler.REMOVE_UPLOAD_PREFIX_DEFAULT);
|
||||
uiGenerator.setParameter("remove-upload-prefix", removeUploadPrefix);
|
||||
if (css != null) {
|
||||
uiGenerator.setParameter("css-file", css);
|
||||
}
|
||||
String dataPrefix = Config.getInstance().getProperty("chiba.web.dataPrefix");
|
||||
uiGenerator.setParameter("data-prefix", dataPrefix);
|
||||
|
||||
String triggerPrefix = Config.getInstance().getProperty("chiba.web.triggerPrefix");
|
||||
uiGenerator.setParameter("trigger-prefix", triggerPrefix);
|
||||
|
||||
uiGenerator.setParameter("user-agent", request.getHeader("User-Agent"));
|
||||
|
||||
uiGenerator.setParameter("scripted","true");
|
||||
|
||||
return uiGenerator;
|
||||
}
|
||||
|
||||
/**
|
||||
* this method is responsible for passing all context information needed by the Adapter and Processor from
|
||||
* ServletRequest to ChibaContext. Will be called only once when the form-session is inited (GET).
|
||||
*
|
||||
* @param request the ServletRequest
|
||||
* @param chibaAdapter the ChibaAdapter to use
|
||||
*/
|
||||
protected void setContextParams(HttpServletRequest request, ChibaAdapter chibaAdapter) {
|
||||
|
||||
//[1] pass user-agent to Adapter for UI-building
|
||||
chibaAdapter.setContextParam(ServletAdapter.USERAGENT, request.getHeader("User-Agent"));
|
||||
|
||||
//[2] read any request params that are *not* Chiba params and pass them into the context map
|
||||
Enumeration params = request.getParameterNames();
|
||||
while (params.hasMoreElements()) {
|
||||
String s = (String) params.nextElement();
|
||||
//store all request-params we don't use in the context map of ChibaBean
|
||||
if (!(s.equals(FORM_PARAM_NAME) ||
|
||||
s.equals(XSL_PARAM_NAME) ||
|
||||
s.equals(CSS_PARAM_NAME) ||
|
||||
s.equals(ACTIONURL_PARAM_NAME))) {
|
||||
String value = request.getParameter(s);
|
||||
//servletAdapter.setContextProperty(s, value);
|
||||
chibaAdapter.setContextParam(s, value);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("added request param '" + s + "' added to context");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated should be re-implemented using chiba events on adapter
|
||||
*/
|
||||
protected boolean load(ChibaAdapter adapter, HttpServletResponse response) throws XFormsException, IOException {
|
||||
if (adapter.getContextParam(ChibaAdapter.LOAD_URI) != null) {
|
||||
String redirectTo = (String) adapter.removeContextParam(ChibaAdapter.LOAD_URI);
|
||||
adapter.shutdown();
|
||||
response.sendRedirect(response.encodeRedirectURL(redirectTo));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated should be re-implemented using chiba events on adapter
|
||||
*/
|
||||
protected boolean replaceAll(ChibaAdapter chibaAdapter, HttpServletResponse response)
|
||||
throws XFormsException, IOException {
|
||||
if (chibaAdapter.getContextParam(ChibaAdapter.SUBMISSION_RESPONSE) != null) {
|
||||
Map forwardMap = (Map) chibaAdapter.removeContextParam(ChibaAdapter.SUBMISSION_RESPONSE);
|
||||
if (forwardMap.containsKey(ChibaAdapter.SUBMISSION_RESPONSE_STREAM)) {
|
||||
forwardResponse(forwardMap, response);
|
||||
chibaAdapter.shutdown();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private String getActionURL(HttpServletRequest request, HttpServletResponse response, boolean scripted) {
|
||||
String defaultActionURL = getRequestURI(request) + agent;
|
||||
String encodedDefaultActionURL = response.encodeURL(defaultActionURL);
|
||||
int sessIdx = encodedDefaultActionURL.indexOf(";jsession");
|
||||
String sessionId = null;
|
||||
if (sessIdx > -1) {
|
||||
sessionId = encodedDefaultActionURL.substring(sessIdx);
|
||||
}
|
||||
String actionURL = request.getParameter(ACTIONURL_PARAM_NAME);
|
||||
if (null == actionURL) {
|
||||
actionURL = encodedDefaultActionURL;
|
||||
} else if (null != sessionId) {
|
||||
actionURL += sessionId;
|
||||
}
|
||||
|
||||
logger.info("actionURL: " + actionURL);
|
||||
// encode the URL to allow for session id rewriting
|
||||
return response.encodeURL(actionURL);
|
||||
}
|
||||
|
||||
private String getRequestURI(HttpServletRequest request){
|
||||
StringBuffer buffer = new StringBuffer(request.getScheme());
|
||||
buffer.append("://");
|
||||
buffer.append(request.getServerName());
|
||||
buffer.append(":");
|
||||
buffer.append(request.getServerPort()) ;
|
||||
buffer.append(request.getContextPath());
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
private void forwardResponse(Map forwardMap, HttpServletResponse response) throws IOException {
|
||||
// fetch response stream
|
||||
InputStream responseStream = (InputStream) forwardMap.remove(ChibaAdapter.SUBMISSION_RESPONSE_STREAM);
|
||||
|
||||
// copy header information
|
||||
Iterator iterator = forwardMap.keySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
|
||||
String name = (String) iterator.next();
|
||||
|
||||
if ("Transfer-Encoding".equalsIgnoreCase(name)) {
|
||||
// Some servers (e.g. WebSphere) may set a "Transfer-Encoding"
|
||||
// with the value "chunked". This may confuse the client since
|
||||
// ChibaServlet output is not encoded as "chunked", so this
|
||||
// header is ignored.
|
||||
continue;
|
||||
}
|
||||
String value = (String) forwardMap.get(name);
|
||||
response.setHeader(name, value);
|
||||
}
|
||||
|
||||
// copy stream content
|
||||
OutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
|
||||
for (int b = responseStream.read();
|
||||
b > -1;
|
||||
b = responseStream.read()) {
|
||||
outputStream.write(b);
|
||||
}
|
||||
|
||||
// close streams
|
||||
responseStream.close();
|
||||
outputStream.close();
|
||||
}
|
||||
|
||||
protected void shutdown(ChibaAdapter chibaAdapter,
|
||||
HttpSession session,
|
||||
Exception e,
|
||||
HttpServletResponse response,
|
||||
HttpServletRequest request)
|
||||
throws IOException,
|
||||
ServletException {
|
||||
// attempt to shutdown processor
|
||||
if (chibaAdapter != null) {
|
||||
try {
|
||||
chibaAdapter.shutdown();
|
||||
} catch (XFormsException xfe) {
|
||||
xfe.printStackTrace();
|
||||
}
|
||||
}
|
||||
Application.handleServletError(this.getServletContext(),
|
||||
request,
|
||||
response,
|
||||
e,
|
||||
logger,
|
||||
null);
|
||||
}
|
||||
}
|
||||
|
||||
// end of class
|
@@ -0,0 +1,101 @@
|
||||
package org.alfresco.web.templating.xforms.servlet;
|
||||
|
||||
import org.apache.commons.fileupload.FileUpload;
|
||||
import org.apache.log4j.Category;
|
||||
import org.chiba.adapter.ChibaAdapter;
|
||||
import org.chiba.adapter.ChibaEvent;
|
||||
import org.chiba.adapter.DefaultChibaEventImpl;
|
||||
import org.chiba.xml.xforms.config.Config;
|
||||
import org.chiba.tools.xslt.UIGenerator;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Provides extra functionality that's not easily handled with AJAX. This helper servlet will only be triggered in
|
||||
* in one of two situations:<br>
|
||||
* 1. an upload<br>
|
||||
* for an file upload to happen the browser has to submit the file as multipart-request. In this case the browser
|
||||
* form must be submitted cause there's no way to get the file content from javascript to send an AJAX request.<br><br>
|
||||
* 2. for a submission replace="all"<br>
|
||||
* This mode requires that the response will be directly streamed back to the client, replacing the existing viewport.
|
||||
* To maintain the correct location of that response in the location bar of the browser there seems no way but to
|
||||
* also let the browser do the request/response handling itself by the use of a normal form submit.
|
||||
*
|
||||
* @author Joern Turner
|
||||
* @version $Version: $
|
||||
*/
|
||||
public class FluxHelperServlet extends ChibaServlet {
|
||||
//init-params
|
||||
private static Category cat = Category.getInstance(FluxHelperServlet.class);
|
||||
|
||||
|
||||
/**
|
||||
* Returns a short description of the servlet.
|
||||
*
|
||||
* @return - Returns a short description of the servlet.
|
||||
*/
|
||||
public String getServletInfo() {
|
||||
return "Ajax Servlet Controller for Chiba XForms Processor";
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys the servlet.
|
||||
*/
|
||||
public void destroy() {
|
||||
}
|
||||
|
||||
/**
|
||||
* handles all interaction with the user during a form-session.
|
||||
*
|
||||
* Note: this method is only triggered if the
|
||||
* browser has javascript turned off.
|
||||
*
|
||||
* @param request servlet request
|
||||
* @param response servlet response
|
||||
* @throws javax.servlet.ServletException
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
protected void doPost(HttpServletRequest request,
|
||||
HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
HttpSession session = request.getSession(true);
|
||||
ChibaAdapter chibaAdapter =null;
|
||||
|
||||
response.setContentType("text/html");
|
||||
|
||||
try {
|
||||
chibaAdapter = (ChibaAdapter) session.getAttribute(CHIBA_ADAPTER);
|
||||
if (chibaAdapter == null) {
|
||||
throw new ServletException(Config.getInstance().getErrorMessage("session-invalid"));
|
||||
}
|
||||
ChibaEvent chibaEvent = new DefaultChibaEventImpl();
|
||||
chibaEvent.initEvent("http-request",null,request);
|
||||
chibaAdapter.dispatch(chibaEvent);
|
||||
|
||||
boolean isUpload = FileUpload.isMultipartContent(request);
|
||||
|
||||
if(isUpload){
|
||||
ServletOutputStream out = response.getOutputStream();
|
||||
out.println("<html><head><title>status</title></head><body><div id='upload-status-ok' style='width:10px;height:10px;background:green'> </div></body></html>");
|
||||
out.close();
|
||||
}else{
|
||||
if(!replaceAll(chibaAdapter, response)){
|
||||
UIGenerator uiGenerator = (UIGenerator) session.getAttribute(CHIBA_UI_GENERATOR);
|
||||
uiGenerator.setInputNode(chibaAdapter.getXForms());
|
||||
uiGenerator.setOutput(response.getWriter());
|
||||
uiGenerator.generate();
|
||||
response.getWriter().close();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
shutdown(chibaAdapter, session, e, response, request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// end of class
|
@@ -0,0 +1,439 @@
|
||||
package org.alfresco.web.templating.xforms.servlet;
|
||||
|
||||
import org.apache.commons.fileupload.DiskFileUpload;
|
||||
import org.apache.commons.fileupload.FileItem;
|
||||
import org.apache.commons.fileupload.FileUpload;
|
||||
import org.apache.commons.fileupload.FileUploadException;
|
||||
import org.apache.log4j.Category;
|
||||
import org.chiba.xml.xforms.ChibaBean;
|
||||
import org.chiba.xml.xforms.config.Config;
|
||||
import org.chiba.xml.xforms.events.XFormsEventFactory;
|
||||
import org.chiba.xml.xforms.exception.XFormsException;
|
||||
import org.chiba.xml.xforms.ui.Repeat;
|
||||
import org.chiba.adapter.ChibaEvent;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.File;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Default implementation for handling http servlet requests.
|
||||
*
|
||||
* @author joern turner
|
||||
* @version $Id: HttpRequestHandler.java,v 1.7 2005/10/27 23:10:31 joernt Exp $
|
||||
*/
|
||||
public class HttpRequestHandler {
|
||||
private static final Category LOGGER = Category.getInstance(HttpRequestHandler.class);
|
||||
public static final String DATA_PREFIX_PROPERTY = "chiba.web.dataPrefix";
|
||||
public static final String TRIGGER_PREFIX_PROPERTY = "chiba.web.triggerPrefix";
|
||||
public static final String SELECTOR_PREFIX_PROPERTY = "chiba.web.selectorPrefix";
|
||||
public static final String REMOVE_UPLOAD_PREFIX_PROPERTY = "chiba.web.removeUploadPrefix";
|
||||
public static final String DATA_PREFIX_DEFAULT = "d_";
|
||||
public static final String TRIGGER_PREFIX_DEFAULT = "t_";
|
||||
public static final String SELECTOR_PREFIX_DEFAULT = "s_";
|
||||
public static final String REMOVE_UPLOAD_PREFIX_DEFAULT = "ru_";
|
||||
|
||||
private ChibaBean chibaBean;
|
||||
|
||||
private String dataPrefix;
|
||||
private String selectorPrefix;
|
||||
private String triggerPrefix;
|
||||
private String removeUploadPrefix;
|
||||
private String uploadRoot;
|
||||
|
||||
|
||||
public HttpRequestHandler(ChibaBean chibaBean) {
|
||||
this.chibaBean = chibaBean;
|
||||
}
|
||||
|
||||
/**
|
||||
* executes this handler.
|
||||
*
|
||||
* @throws XFormsException
|
||||
*/
|
||||
public void execute(ChibaEvent event) throws XFormsException {
|
||||
//HttpServletRequest request = (HttpServletRequest) this.chibaBean.getContext().get(ServletAdapter.HTTP_SERVLET_REQUEST);
|
||||
HttpServletRequest request= (HttpServletRequest) event.getContextInfo();
|
||||
|
||||
String contextRoot = request.getSession().getServletContext().getRealPath("");
|
||||
if (contextRoot == null) {
|
||||
contextRoot = request.getSession().getServletContext().getRealPath(".");
|
||||
}
|
||||
|
||||
String uploadDir = (String) this.chibaBean.getContext().get(ServletAdapter.HTTP_UPLOAD_DIR);
|
||||
this.uploadRoot = new File(contextRoot, uploadDir).getAbsolutePath();
|
||||
|
||||
handleRequest(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* checks whether we have multipart or urlencoded request and processes it accordingly. After updating
|
||||
* the data, a reacalculate, revalidate refresh sequence is fired and the found trigger is executed.
|
||||
*
|
||||
* @param request Servlet request
|
||||
* @throws org.chiba.xml.xforms.exception.XFormsException
|
||||
* todo: implement action block behaviour
|
||||
*/
|
||||
protected void handleRequest(HttpServletRequest request) throws XFormsException {
|
||||
String trigger = null;
|
||||
|
||||
// Check that we have a file upload request
|
||||
boolean isMultipart = FileUpload.isMultipartContent(request);
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("request isMultipart: " + isMultipart);
|
||||
LOGGER.debug("base URI: " + this.chibaBean.getBaseURI());
|
||||
LOGGER.debug("user agent: " + request.getHeader("User-Agent"));
|
||||
}
|
||||
|
||||
if (isMultipart) {
|
||||
trigger = processMultiPartRequest(request, trigger);
|
||||
} else {
|
||||
trigger = processUrlencodedRequest(request, trigger);
|
||||
}
|
||||
|
||||
// finally activate trigger if any
|
||||
if (trigger != null) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("trigger '" + trigger + "'");
|
||||
}
|
||||
|
||||
this.chibaBean.dispatch(trigger, XFormsEventFactory.DOM_ACTIVATE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param request Servlet request
|
||||
* @param trigger Trigger control
|
||||
* @return the calculated trigger
|
||||
* @throws XFormsException If an error occurs
|
||||
*/
|
||||
protected String processMultiPartRequest(HttpServletRequest request, String trigger) throws XFormsException {
|
||||
DiskFileUpload upload = new DiskFileUpload();
|
||||
|
||||
String encoding = request.getCharacterEncoding();
|
||||
if (encoding == null) {
|
||||
encoding = "ISO-8859-1";
|
||||
}
|
||||
|
||||
upload.setRepositoryPath(this.uploadRoot);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("root dir for uploads: " + this.uploadRoot);
|
||||
}
|
||||
|
||||
List items;
|
||||
try {
|
||||
items = upload.parseRequest(request);
|
||||
} catch (FileUploadException fue) {
|
||||
throw new XFormsException(fue);
|
||||
}
|
||||
|
||||
Map formFields = new HashMap();
|
||||
Iterator iter = items.iterator();
|
||||
while (iter.hasNext()) {
|
||||
FileItem item = (FileItem) iter.next();
|
||||
String itemName = item.getName();
|
||||
String fieldName = item.getFieldName();
|
||||
String id = fieldName.substring(Config.getInstance().getProperty("chiba.web.dataPrefix").length());
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Multipart item name is: " + itemName
|
||||
+ " and fieldname is: " + fieldName
|
||||
+ " and id is: " + id);
|
||||
LOGGER.debug("Is formfield: " + item.isFormField());
|
||||
}
|
||||
|
||||
if (item.isFormField()) {
|
||||
|
||||
// check for upload-remove action
|
||||
if (fieldName.startsWith(getRemoveUploadPrefix())) {
|
||||
id = fieldName.substring(getRemoveUploadPrefix().length());
|
||||
// if data is null, file will be removed ...
|
||||
// TODO: remove the file from the disk as well
|
||||
chibaBean.updateControlValue(id, "", "", null);
|
||||
continue;
|
||||
}
|
||||
|
||||
// It's a field name, it means that we got a non-file
|
||||
// form field. Upload is not required. We must treat it as we
|
||||
// do in processUrlencodedRequest()
|
||||
processMultipartParam(formFields, fieldName, item, encoding);
|
||||
} else {
|
||||
|
||||
String uniqueFilename = new File(getUniqueParameterName("file"),
|
||||
new File(itemName).getName()).getPath();
|
||||
|
||||
File savedFile = new File(this.uploadRoot, uniqueFilename);
|
||||
|
||||
byte[] data = null;
|
||||
|
||||
data = processMultiPartFile(item, id, savedFile, encoding, data);
|
||||
|
||||
// if data is null, file will be removed ...
|
||||
// TODO: remove the file from the disk as well
|
||||
chibaBean.updateControlValue(id, item.getContentType(),
|
||||
itemName, data);
|
||||
}
|
||||
|
||||
// handle regular fields
|
||||
if (formFields.size() > 0) {
|
||||
|
||||
Iterator it = formFields.keySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
|
||||
fieldName = (String) it.next();
|
||||
String[] values = (String[]) formFields.get(fieldName);
|
||||
|
||||
// [1] handle data
|
||||
handleData(fieldName, values);
|
||||
|
||||
// [2] handle selector
|
||||
handleSelector(fieldName, values[0]);
|
||||
|
||||
// [3] handle trigger
|
||||
trigger = handleTrigger(trigger, fieldName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return trigger;
|
||||
}
|
||||
|
||||
protected String processUrlencodedRequest(HttpServletRequest request, String trigger) throws XFormsException {
|
||||
// iterate request parameters
|
||||
Enumeration names = request.getParameterNames();
|
||||
while (names.hasMoreElements()) {
|
||||
String paramName = names.nextElement().toString();
|
||||
String[] values = request.getParameterValues(paramName);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(this + " parameter-name: " + paramName);
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
LOGGER.debug(this + " value: " + values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// [1] handle data
|
||||
handleData(paramName, values);
|
||||
|
||||
// [2] handle selector
|
||||
handleSelector(paramName, values[0]);
|
||||
|
||||
// [3] handle trigger
|
||||
trigger = handleTrigger(trigger, paramName);
|
||||
}
|
||||
return trigger;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* @throws XFormsException
|
||||
*/
|
||||
protected void handleData(String name, String[] values)
|
||||
throws XFormsException {
|
||||
if (name.startsWith(getDataPrefix())) {
|
||||
String id = name.substring(getDataPrefix().length());
|
||||
|
||||
// assemble new control value
|
||||
String newValue;
|
||||
|
||||
if (values.length > 1) {
|
||||
StringBuffer buffer = new StringBuffer(values[0]);
|
||||
|
||||
for (int i = 1; i < values.length; i++) {
|
||||
buffer.append(" ").append(values[i]);
|
||||
}
|
||||
|
||||
newValue = trim( buffer.toString() );
|
||||
} else {
|
||||
newValue = trim( values[0] );
|
||||
}
|
||||
|
||||
this.chibaBean.updateControlValue(id, newValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* patch to handle linefeed duplication in textareas with some browsers.
|
||||
*
|
||||
* @param value the value where linebreaks will be trimmed
|
||||
* @return returns a cleaned up version of the value
|
||||
*/
|
||||
|
||||
protected String trim(String value) {
|
||||
if (value != null && value.length() > 0) {
|
||||
value = value.replaceAll("\r\n", "\r");
|
||||
value = value.trim();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* @throws XFormsException
|
||||
*/
|
||||
protected void handleSelector(String name, String value) throws XFormsException {
|
||||
if (name.startsWith(getSelectorPrefix())) {
|
||||
int separator = value.lastIndexOf(':');
|
||||
|
||||
String id = value.substring(0, separator);
|
||||
int index = Integer.valueOf(value.substring(separator + 1)).intValue();
|
||||
|
||||
Repeat repeat = (Repeat) this.chibaBean.lookup(id);
|
||||
repeat.setIndex(index);
|
||||
}
|
||||
}
|
||||
|
||||
protected String handleTrigger(String trigger, String name) {
|
||||
if ((trigger == null) && name.startsWith(getTriggerPrefix())) {
|
||||
String parameter = name;
|
||||
int x = parameter.lastIndexOf(".x");
|
||||
int y = parameter.lastIndexOf(".y");
|
||||
|
||||
if (x > -1) {
|
||||
parameter = parameter.substring(0, x);
|
||||
}
|
||||
|
||||
if (y > -1) {
|
||||
parameter = parameter.substring(0, y);
|
||||
}
|
||||
|
||||
// keep trigger id
|
||||
trigger = name.substring(getTriggerPrefix().length());
|
||||
}
|
||||
return trigger;
|
||||
}
|
||||
|
||||
private byte[] processMultiPartFile(FileItem item, String id, File savedFile, String encoding, byte[] data)
|
||||
throws XFormsException {
|
||||
// some data uploaded ...
|
||||
if (item.getSize() > 0) {
|
||||
|
||||
if (chibaBean.storesExternalData(id)) {
|
||||
|
||||
// store data to file and create URI
|
||||
try {
|
||||
savedFile.getParentFile().mkdir();
|
||||
item.write(savedFile);
|
||||
} catch (Exception e) {
|
||||
throw new XFormsException(e);
|
||||
}
|
||||
// content is URI in this case
|
||||
try {
|
||||
data = savedFile.toURI().toString().getBytes(encoding);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new XFormsException(e);
|
||||
}
|
||||
|
||||
} else {
|
||||
// content is the data
|
||||
data = item.get();
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
private void processMultipartParam(Map formFields, String fieldName, FileItem item, String encoding) throws XFormsException {
|
||||
String values[] = (String[]) formFields.get(fieldName);
|
||||
String formFieldValue = null;
|
||||
try {
|
||||
formFieldValue = item.getString(encoding);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new XFormsException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
if (values == null) {
|
||||
formFields.put(fieldName, new String[]{formFieldValue});
|
||||
} else {
|
||||
// not very effective, but not many duplicate values
|
||||
// expected either ...
|
||||
String[] tmp = new String[values.length + 1];
|
||||
System.arraycopy(values, 0, tmp, 0, values.length);
|
||||
tmp[values.length] = formFieldValue;
|
||||
formFields.put(fieldName, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* returns the prefix which is used to identify trigger parameters.
|
||||
*
|
||||
* @return the prefix which is used to identify trigger parameters
|
||||
*/
|
||||
protected final String getTriggerPrefix() {
|
||||
if (this.triggerPrefix == null) {
|
||||
try {
|
||||
this.triggerPrefix =
|
||||
Config.getInstance().getProperty(TRIGGER_PREFIX_PROPERTY, TRIGGER_PREFIX_DEFAULT);
|
||||
} catch (Exception e) {
|
||||
this.triggerPrefix = TRIGGER_PREFIX_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
return this.triggerPrefix;
|
||||
}
|
||||
|
||||
protected final String getDataPrefix() {
|
||||
if (this.dataPrefix == null) {
|
||||
try {
|
||||
this.dataPrefix = Config.getInstance().getProperty(DATA_PREFIX_PROPERTY, DATA_PREFIX_DEFAULT);
|
||||
} catch (Exception e) {
|
||||
this.dataPrefix = DATA_PREFIX_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
return this.dataPrefix;
|
||||
}
|
||||
|
||||
protected final String getRemoveUploadPrefix() {
|
||||
if (this.removeUploadPrefix == null) {
|
||||
try {
|
||||
this.removeUploadPrefix = Config.getInstance().getProperty(REMOVE_UPLOAD_PREFIX_PROPERTY, REMOVE_UPLOAD_PREFIX_DEFAULT);
|
||||
} catch (Exception e) {
|
||||
this.removeUploadPrefix = REMOVE_UPLOAD_PREFIX_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
return this.removeUploadPrefix;
|
||||
}
|
||||
|
||||
|
||||
private String getUniqueParameterName(String prefix) {
|
||||
return prefix + Integer.toHexString((int) (Math.random() * 10000));
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the configured prefix which identifies 'selector' parameters. These are used to transport
|
||||
* the state of repeat indices via http.
|
||||
*
|
||||
* @return the prefix for selector parameters from the configuration
|
||||
*/
|
||||
public final String getSelectorPrefix() {
|
||||
if (this.selectorPrefix == null) {
|
||||
try {
|
||||
this.selectorPrefix =
|
||||
Config.getInstance().getProperty(SELECTOR_PREFIX_PROPERTY,
|
||||
SELECTOR_PREFIX_DEFAULT);
|
||||
} catch (Exception e) {
|
||||
this.selectorPrefix = SELECTOR_PREFIX_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
return this.selectorPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of chibaBean.
|
||||
*
|
||||
* @return the value of chibaBean
|
||||
*/
|
||||
public ChibaBean getChibaBean() {
|
||||
return this.chibaBean;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// end of class
|
||||
|
||||
|
@@ -0,0 +1,167 @@
|
||||
package org.alfresco.web.templating.xforms.servlet;
|
||||
|
||||
import org.apache.log4j.Category;
|
||||
import org.chiba.adapter.AbstractChibaAdapter;
|
||||
import org.chiba.adapter.ChibaEvent;
|
||||
import org.chiba.xml.xforms.events.XFormsEvent;
|
||||
import org.chiba.xml.xforms.events.XFormsEventFactory;
|
||||
import org.chiba.xml.xforms.exception.XFormsException;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.events.Event;
|
||||
import org.w3c.dom.events.EventListener;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* integrates XForms Processor into Web-applications and handles request
|
||||
* processing. This is the default implementation of ChibaAdapter and besides
|
||||
* handling the interaction it also manages a UIGenerator to build the rendered
|
||||
* output for the browser.
|
||||
*
|
||||
* @author joern turner
|
||||
* @version $Id: ServletAdapter.java,v 1.8 2005/12/15 11:45:38 unl Exp $
|
||||
*/
|
||||
public class ServletAdapter extends AbstractChibaAdapter implements EventListener {
|
||||
|
||||
private static final Category LOGGER = Category.getInstance(ServletAdapter.class);
|
||||
public static final String HTTP_SERVLET_REQUEST = "chiba.web.request";
|
||||
//public static final String HTTP_SESSION_OBJECT = "chiba.web.session";
|
||||
public static final String HTTP_UPLOAD_DIR = "chiba.web.uploadDir";
|
||||
|
||||
//private ChibaBean chibaBean = null;
|
||||
//private String formURI = null;
|
||||
//private String actionUrl = null;
|
||||
//private String CSSFile = null;
|
||||
//private String stylesheet = null;
|
||||
//private UIGenerator generator = null;
|
||||
//private String stylesheetPath = null;
|
||||
//private HashMap context = null;
|
||||
public static final String USERAGENT = "chiba.useragent";
|
||||
private HttpRequestHandler handler;
|
||||
public static final Object XSLT_PATH = "xslt-path";
|
||||
|
||||
/**
|
||||
* Creates a new ServletAdapter object.
|
||||
*/
|
||||
public ServletAdapter() {
|
||||
}
|
||||
|
||||
/**
|
||||
* place to put application-specific params or configurations before
|
||||
* actually starting off the XFormsProcessor. It's the responsibility of
|
||||
* this method to call chibaBean.init() to finish up the processor setup.
|
||||
*
|
||||
* @throws XFormsException If an error occurs
|
||||
*/
|
||||
public void init() throws XFormsException {
|
||||
this.chibaBean.init();
|
||||
this.handler = getNewInteractionHandler();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ServletAdapter knows and executes only one ChibaEvent: 'http-request'
|
||||
* which will contain the HttpServletRequest as contextInfo.
|
||||
*
|
||||
* @param event only events of type 'http-request' will be handled
|
||||
* @throws XFormsException
|
||||
*/
|
||||
public void dispatch(ChibaEvent event) throws XFormsException {
|
||||
if (event.getEventName().equals("http-request")) {
|
||||
this.handler.execute(event);
|
||||
}
|
||||
else {
|
||||
LOGGER.warn("unknown event: '" + event.getEventName() + "' - ignoring");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* terminates the XForms processing. right place to do cleanup of
|
||||
* resources.
|
||||
*
|
||||
* @throws org.chiba.xml.xforms.exception.XFormsException
|
||||
*/
|
||||
public void shutdown() throws XFormsException {
|
||||
this.chibaBean.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs the application environment to forward the given response.
|
||||
*
|
||||
* @param response a map containing at least a response stream and optional
|
||||
* header information.
|
||||
*/
|
||||
public void forward(Map response) {
|
||||
this.chibaBean.getContext().put(SUBMISSION_RESPONSE, response);
|
||||
}
|
||||
|
||||
// todo: should be set by servlet
|
||||
|
||||
/**
|
||||
* return a new InteractionHandler.
|
||||
* <p/>
|
||||
* This method returns a new HttpRequestHandler.
|
||||
*
|
||||
* @return returns a new
|
||||
*/
|
||||
protected HttpRequestHandler getNewInteractionHandler()
|
||||
throws XFormsException {
|
||||
return new HttpRequestHandler(this.chibaBean);
|
||||
}
|
||||
|
||||
public void setUploadDestination(String uploadDir) {
|
||||
super.setUploadDestination(uploadDir);
|
||||
//HttpRequestHandler uses this
|
||||
// todo: should be a member of request handler and set directly
|
||||
setContextParam(HTTP_UPLOAD_DIR, uploadDir);
|
||||
}
|
||||
|
||||
// event handling
|
||||
// todo: should be moved up to base class
|
||||
|
||||
/**
|
||||
* This method is called whenever an event occurs of the type for which the
|
||||
* <code> EventListener</code> interface was registered.
|
||||
*
|
||||
* @param event The <code>Event</code> contains contextual information about
|
||||
* the event. It also contains the <code>stopPropagation</code> and
|
||||
* <code>preventDefault</code> methods which are used in determining the
|
||||
* event's flow and default action.
|
||||
*/
|
||||
public void handleEvent(Event event) {
|
||||
String type = event.getType();
|
||||
String targetId = ((Element) event.getTarget()).getAttributeNS(null, "id");
|
||||
XFormsEvent xformsEvent = (XFormsEvent) event;
|
||||
|
||||
if (XFormsEventFactory.CHIBA_LOAD_URI.equals(type)) {
|
||||
handleLoadURI(targetId, (String) xformsEvent.getContextInfo("uri"), (String) xformsEvent.getContextInfo("show"));
|
||||
return;
|
||||
}
|
||||
if (XFormsEventFactory.CHIBA_RENDER_MESSAGE.equals(type)) {
|
||||
handleMessage(targetId, (String) xformsEvent.getContextInfo("message"), (String) xformsEvent.getContextInfo("level"));
|
||||
return;
|
||||
}
|
||||
if (XFormsEventFactory.CHIBA_REPLACE_ALL.equals(type)) {
|
||||
handleReplaceAll(targetId, (Map) xformsEvent.getContextInfo("header"), xformsEvent.getContextInfo("body"));
|
||||
return;
|
||||
}
|
||||
|
||||
// unknown event ignored
|
||||
}
|
||||
|
||||
// todo: *either* move up these three methods as abstract template methods *or* use event log ?
|
||||
public void handleLoadURI(String targetId, String uri, String show) {
|
||||
// todo
|
||||
}
|
||||
|
||||
public void handleMessage(String targetId, String message, String level) {
|
||||
// todo
|
||||
}
|
||||
|
||||
public void handleReplaceAll(String targetId, Map header, Object body) {
|
||||
// todo
|
||||
}
|
||||
}
|
||||
|
||||
// end of class
|
@@ -0,0 +1,84 @@
|
||||
package org.alfresco.web.templating.xforms.servlet;
|
||||
|
||||
import org.chiba.adapter.ChibaAdapter;
|
||||
import org.chiba.xml.xforms.exception.XFormsException;
|
||||
import org.apache.log4j.Category;
|
||||
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Returns a submission response exactly once.
|
||||
*
|
||||
* @author Ulrich Nicolas Lissé
|
||||
* @version $Id: SubmissionResponseServlet.java,v 1.1 2005/12/21 22:59:27 unl Exp $
|
||||
*/
|
||||
public class SubmissionResponseServlet extends HttpServlet {
|
||||
private static Category LOGGER = Category.getInstance(SubmissionResponseServlet.class);
|
||||
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
// lookup session
|
||||
HttpSession session = request.getSession(false);
|
||||
if (session != null) {
|
||||
// lookup attribute containing submission response map
|
||||
Map submissionResponse = (Map) session.getAttribute(ChibaServlet.CHIBA_SUBMISSION_RESPONSE);
|
||||
if (submissionResponse != null) {
|
||||
// shutdown form session
|
||||
ChibaAdapter adapter = (ChibaAdapter) session.getAttribute(ChibaServlet.CHIBA_ADAPTER);
|
||||
if (adapter != null) {
|
||||
try {
|
||||
adapter.shutdown();
|
||||
}
|
||||
catch (XFormsException e) {
|
||||
LOGGER.error("xforms shutdown failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
// remove session attributes
|
||||
session.removeAttribute(ChibaServlet.CHIBA_ADAPTER);
|
||||
session.removeAttribute(ChibaServlet.CHIBA_SUBMISSION_RESPONSE);
|
||||
|
||||
// copy header fields
|
||||
Map headerMap = (Map) submissionResponse.get("header");
|
||||
Iterator iterator = headerMap.keySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
final String name = (String) iterator.next();
|
||||
if (name.equalsIgnoreCase("Transfer-Encoding")) {
|
||||
// Some servers (e.g. WebSphere) may set a "Transfer-Encoding"
|
||||
// with the value "chunked". This may confuse the client since
|
||||
// ChibaServlet output is not encoded as "chunked", so this
|
||||
// header is ignored.
|
||||
continue;
|
||||
}
|
||||
|
||||
final String value = (String) headerMap.get(name);
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("added header: " + name + "=" + value);
|
||||
}
|
||||
|
||||
response.setHeader(name, value);
|
||||
}
|
||||
|
||||
// copy body stream
|
||||
InputStream bodyStream = (InputStream) submissionResponse.get("body");
|
||||
OutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
|
||||
for (int b = bodyStream.read(); b > -1; b = bodyStream.read()) {
|
||||
outputStream.write(b);
|
||||
}
|
||||
|
||||
// close streams
|
||||
bodyStream.close();
|
||||
outputStream.close();
|
||||
}
|
||||
}
|
||||
// response.sendError(HttpServletResponse.SC_FORBIDDEN, "no submission response available");
|
||||
}
|
||||
}
|
@@ -0,0 +1,5 @@
|
||||
# Tokens
|
||||
chiba-version=1.0.0
|
||||
baseurl.host=localhost
|
||||
baseurl.port=8080
|
||||
|
@@ -0,0 +1 @@
|
||||
@version.major@ [build @version.build@]
|
Reference in New Issue
Block a user