/*******************************************************************************
* Copyright 2009, 2010 Innovation Gate GmbH. All Rights Reserved.
*
* This file is part of the OpenWGA server platform.
*
* OpenWGA is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* In addition, a special exception is granted by the copyright holders
* of OpenWGA called "OpenWGA plugin exception". You should have received
* a copy of this exception along with OpenWGA in file COPYING.
* If not, see <http://www.openwga.com/gpl-plugin-exception>.
*
* OpenWGA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenWGA in file COPYING.
* If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package de.innovationgate.wgpublisher.webtml;
import java.io.UnsupportedEncodingException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.Dom4JDriver;
import de.innovationgate.utils.Zipper;
import de.innovationgate.webgate.api.WGAPIException;
import de.innovationgate.webgate.api.WGContent;
import de.innovationgate.webgate.api.WGDatabase;
import de.innovationgate.webgate.api.WGDocument;
import de.innovationgate.webgate.api.WGRelationData;
import de.innovationgate.wga.common.beans.csconfig.v1.CSConfig;
import de.innovationgate.wgpublisher.WGACore;
import de.innovationgate.wgpublisher.webtml.utils.FieldReg;
import de.innovationgate.wgpublisher.webtml.utils.FormInfo;
import de.innovationgate.wgpublisher.webtml.utils.TMLAction;
import de.innovationgate.wgpublisher.webtml.utils.TMLContext;
import de.innovationgate.wgpublisher.webtml.utils.TMLException;
import de.innovationgate.wgpublisher.webtml.utils.TMLForm;
import de.innovationgate.wgpublisher.webtml.utils.TMLFormField;
import de.innovationgate.wgpublisher.webtml.utils.TMLPortlet;
import de.innovationgate.wgpublisher.webtml.utils.TMLUserProfile;
/**
* base class for form functions
* tml:form and tml:item (BI-customeditor) needs the same functionality and
* extends this class
*
*/
public class FormBase extends Base {
private String source;
private String onsubmit;
private String persist;
private String cssclass;
private String cssstyle;
private String htmlinput;
private String mode;
private String defaultaction;
private String contentclass;
public static class FormStatus extends BaseTagStatus implements FormInputRegistrator {
protected FormInfo formInfo;
protected TMLForm thisForm;
private String source;
protected String mode;
public String getFormMode() {
return formInfo.getMode();
}
public void addFormValidation(String condition, String message, List ifnoerrorList, List cleariferrorList) {
formInfo.addFormValidation(condition, message, ifnoerrorList, cleariferrorList);
}
public void addField(FieldReg fieldReg, Object value) {
// put new fields in formInfo
formInfo.addOrMergeFieldReg(fieldReg);
try {
// put field in tmlForm, so that it can be accessed by tmlscript just in renderTime
thisForm.setfield(fieldReg.getName(), value);
} catch (ParseException e) {
this.addWarning(e.getMessage(), false);
}
}
/* (non-Javadoc)
* @see de.innovationgate.wgpublisher.webtml.FormInputRegistrator#getFieldValue(java.lang.String, boolean, java.lang.String)
*/
public List getFieldValue(String fieldname, boolean meta, Object defaultvalue, boolean useRelation) throws WGAPIException {
// Look in form object (when form was posted previously)
if (thisForm != null && thisForm.hasfield(fieldname)) {
return thisForm.getEnteredOrParsedValues(fieldname);
}
// retrieve fieldvalue from source
if (source.equals("content")) {
WGDocument doc = tmlContext.getdocument();
return FormBase.getFieldValue(doc, tmlContext, formInfo, fieldname, meta, defaultvalue, useRelation);
}
else if (source.equals("profile")) {
TMLUserProfile profile = tmlContext.getprofile();
return FormBase.getFieldValue(profile, tmlContext, formInfo, fieldname, meta, defaultvalue);
}
else if (source.equals("portlet")) {
TMLPortlet portlet = tmlContext.getportlet();
return FormBase.getFieldValue(portlet, tmlContext, formInfo, fieldname, meta, defaultvalue);
}
else if (source.equals("none") || source.equals("newcontent")) {
if (defaultvalue != null) {
if (defaultvalue instanceof List) {
return (List) defaultvalue;
}
else {
return Collections.singletonList(defaultvalue);
}
}
else {
return tmlContext.db().getNoItemBehaviour().getForTMLFormEmptyFieldList();
}
}
else {
return null;
}
}
public String getId() {
return id;
}
public void registerHashedPasswordField(String fieldname, String hashedValue) {
TMLFormField field = new TMLFormField(fieldname);
field.addValue(hashedValue);
formInfo.addHashedPasswordField(field);
}
@Override
public void initAttributeDelegates(Base tag) {
FormBase formBase = (FormBase) tag;
this.mode = formBase.getMode();
this.source = formBase.getSource();
super.initAttributeDelegates(tag);
}
}
public FormStatus getFormStatus() {
return (FormStatus) getStatus();
}
private String keeponvalidate;
public void tmlStartTag() throws TMLException, WGAPIException {
// Look if eventually posted form is this form, or form was persisted
FormStatus status = (FormStatus) getStatus();
TMLForm form = this.getTMLContext().tmlformbyid(this.getId());
if (form != null) {
status.thisForm = form;
status.thisForm.setDocumentPath(getTMLContext().getpath());
// use existing formInfo
status.formInfo = form.getforminfo();
//this.formInfoKey = form.getFormInfoKey();
// clear last rendered form fields
//this.formInfo.clearLastRenderedFormFields();
// update default action if neccessary
updateDefaultAction(status.formInfo);
}
else {
// inititalize new formInfo
status.formInfo = new FormInfo(this.getId(), this.getHtmlinput(), stringToBoolean(this.getPersist()));
status.formInfo.setSource(status.source);
status.formInfo.setTrim(stringToBoolean(this.getTrim()));
status.formInfo.setKeepOnValidate(stringToBoolean(this.getKeeponvalidate()));
status.formInfo.setTargetContextPath(getTMLContext().getpath());
status.formInfo.setContentClass(getContentclass());
status.formInfo.setDefinitionModule(getStatus().getTMLModuleName());
status.formInfo.setDefinitionDatabase(getDesignDBKey());
WGDatabase designDB = getCore().getContentdbs().get(getDesignDBKey());
if (designDB != null) { // May be in StaticTML
CSConfig csConfig = (CSConfig) designDB.getAttribute(WGACore.DBATTRIB_CSCONFIG);
if (csConfig != null) {
status.formInfo.setVersionCompliance(csConfig.getVersionCompliance());
}
}
updateDefaultAction(status.formInfo);
// Immediately create new form object, so TMLScript can access the form object
status.thisForm = getTMLContext().createform(status.formInfo);
}
getPageContext().getRequest().setAttribute(WGACore.ATTRIB_LASTFORM, status.thisForm);
}
private void updateDefaultAction(FormInfo info) throws WGAPIException {
String defaultActionID = getDefaultaction();
if (defaultActionID != null) {
TMLAction defaultAction = getTMLContext().getActionByID(defaultActionID, getDesignDBKey());
if (defaultAction != null) {
List params = new ArrayList();
// Dunno what to add to params. Neccessary data should be retrievable from tmlfrom object
info.setDefaultAction(defaultAction.createActionLink(params, getTMLContext()).getEncodedString(getCore()));
}
else {
addWarning("Unknown default action '" + defaultActionID + "'");
}
}
}
public boolean isFormEditable() {
if (getFormStatus().formInfo.getMode().equals(FormInfo.EDIT_MODE)) {
return true;
} else {
return false;
}
}
/* (non-Javadoc)
* @see de.innovationgate.wgpublisher.webtml.FormInputRegistrator#addField(de.innovationgate.wgpublisher.webtml.utils.FieldReg, java.lang.Object)
*/
static List getFieldValue(TMLPortlet portlet, TMLContext context, FormInfo formInfo, String fieldname, boolean meta, Object defaultvalue) throws WGAPIException {
if (portlet == null) {
return Collections.singletonList("");
} else if (meta) {
return portlet.metalist(fieldname);
} else if (portlet.hasitem(fieldname)) {
return portlet.itemlist(fieldname);
} else if (formInfo.getMode().equals(FormInfo.EDIT_MODE)) {
if (defaultvalue != null) {
return Collections.singletonList(defaultvalue);
}
else {
return context.db().getNoItemBehaviour().getForTMLFormEmptyFieldList();
}
} else {
return Collections.EMPTY_LIST;
}
}
static List getFieldValue(TMLUserProfile profile, TMLContext context, FormInfo formInfo, String fieldname, boolean meta, Object defaultvalue) throws WGAPIException {
if (profile == null) {
return Collections.singletonList("");
} else if (meta) {
return profile.metalist(fieldname);
} else if (profile.hasitem(fieldname)) {
return profile.itemlist(fieldname);
} else if (formInfo.getMode().equals(FormInfo.EDIT_MODE)) {
if (defaultvalue != null) {
return Collections.singletonList(defaultvalue);
}
else {
return context.db().getNoItemBehaviour().getForTMLFormEmptyFieldList();
}
} else {
return Collections.EMPTY_LIST;
}
}
/**
* returns the fieldvalue of the given document or the defaultvalue
* if no default is present or the form is not in EDIT_MODE an empty list is returned
* the searchorder for fieldvalue is as follows
* - doc.item
* - tmlVariable
* - defaultvalue
* @param doc
* @param context
* @param fieldname
* @param meta
* @param defaultvalue
* @return
* @throws WGAPIException
*/
static List getFieldValue(WGDocument doc, TMLContext context, FormInfo formInfo, String fieldname, boolean meta, Object defaultvalue, boolean useRelation) throws WGAPIException {
if (useRelation && doc instanceof WGContent) {
WGContent content = (WGContent)doc;
List<String> values = new ArrayList<String>();
WGRelationData relationData = content.getRelationData(fieldname);
if (relationData != null) {
values.add(relationData.getTargetStructkey().toString());
}
else {
for (WGRelationData relData : content.getRelationsDataOfGroup(fieldname)) {
values.add(relData.getTargetStructkey().toString());
}
}
return values;
} else if (meta) {
return doc.getMetaDataList(fieldname);
}
else if (doc.hasItem(fieldname)) {
return doc.getItemValueList(fieldname);
}
else if (context.hasVariable(fieldname) || context.hasMappedItemValue(fieldname)) {
return context.itemlist(fieldname);
}
else if (formInfo.getMode().equals(FormInfo.EDIT_MODE)) {
if (defaultvalue != null) {
return Collections.singletonList(defaultvalue);
}
else {
return doc.getDatabase().getNoItemBehaviour().getForTMLFormEmptyFieldList();
}
}
else {
return Collections.EMPTY_LIST;
}
}
/**
* Returns the source.
* @return String
*/
public String getSource() {
return this.getTagAttributeValue("source", source, "content");
}
/**
* Sets the source.
* @param source The source to set
*/
public void setSource(String source) {
this.source = source;
}
/**
* @return
*/
public String getOnsubmit() {
return this.getTagAttributeValue("onsubmit", onsubmit, "");
}
/**
* @param string
*/
public void setOnsubmit(String string) {
this.onsubmit = string;
}
/**
* @return
*/
public String getPersist() {
return this.getTagAttributeValue("persist", persist, "false");
}
/**
* @param string
*/
public void setPersist(String string) {
persist = string;
}
/**
* Returns the cssstyle.
* @return String
*/
public String getCssstyle() {
return this.getTagAttributeValue("cssstyle", cssstyle, null);
}
/**
* Sets the cssstyle.
* @param cssstyle The cssstyle to set
*/
public void setCssstyle(String cssstyle) {
this.cssstyle = cssstyle;
}
/**
* Returns the cssClass.
* @return String
*/
public String getCssclass() {
return this.getTagAttributeValue("cssclass", cssclass, null);
}
/**
* Sets the cssClass.
* @param cssClass The cssClass to set
*/
public void setCssclass(String cssClass) {
this.cssclass = cssClass;
}
public String getHtmlinput() {
return this.getTagAttributeValue("htmlinput", htmlinput, "false");
}
public void setHtmlinput(String htmlinput) {
this.htmlinput = htmlinput;
}
public String getMode() {
return this.getTagAttributeValue("mode", mode, null);
}
public void setMode(String mode) {
this.mode = mode;
}
public String getKeeponvalidate() {
return this.getTagAttributeValue("keeponvalidate", keeponvalidate, "true");
}
public void setKeeponvalidate(String keeponvalidate) {
this.keeponvalidate = keeponvalidate;
}
protected String renderFormStartTag(String id, String onsubmit, String cssStyle, String cssClass) {
StringBuffer buf = new StringBuffer();
buf.append("<form method=\"POST\" name=\"" + id + "\" id=\"" + id + "\" enctype=\"multipart/form-data\"");
if (onsubmit != null) {
if(!onsubmit.equalsIgnoreCase("")){
buf.append(" onsubmit=\"");
buf.append(onsubmit);
buf.append("\"");
}
}
if(cssStyle !=null){
buf.append(" style=\"" + cssStyle + "\"");
}
if(cssClass!=null){
buf.append(" class=\"" + cssClass + "\"");
}
//F000037B2
if (getCore().getCharacterEncoding() != null) {
buf.append(" accept-charset=\"" + getCore().getCharacterEncoding() + "\"");
}
buf.append(">\n");
buf.append("<script type=\"text/javascript\">if (typeof(WGA) != 'undefined') {WGA.b4submit.reset(\"" + this.getId() + "\")};</script>");
return buf.toString();
}
protected String renderAdditionHiddenFormFields() {
StringBuffer additionalFields = new StringBuffer();
additionalFields.append("<input type=\"hidden\" name=\"$formaction\" value=\"\">");
additionalFields.append("<input type=\"hidden\" name=\"$ajaxcallid\" value=\"\">");
additionalFields.append("<input type=\"hidden\" name=\"$ajaxgraydiv\" value=\"\">");
additionalFields.append("<input type=\"hidden\" name=\"$ajaxmode\" value=\"\">");
return additionalFields.toString();
}
protected String renderFormInfo(FormInfo formInfo, TMLContext context) {
try {
String serializedInfo = serializeFormInfo(formInfo, context);
if (serializedInfo != null) {
return "<input type=\"hidden\" name=\"$forminfo\" value=\"" + serializedInfo + "\">";
} else {
return "";
}
}
catch (UnsupportedEncodingException e) {
addWarning("Unable to render form info bc. of unsupported encoding: " + e.getMessage(), true);
return "";
}
}
static String serializeFormInfo(FormInfo info, TMLContext context) throws UnsupportedEncodingException {
// optimze formInfo
info.optimize();
// serialize FormInfo
String serFormInfo = new XStream(new Dom4JDriver()).toXML(info);
byte[] zipped = Zipper.zip(serFormInfo);
if (zipped != null) {
// encrypt
return context.getwgacore().getDesEncrypter().encrypt(zipped);
}
return null;
}
protected String renderFormEndTag() {
return "</form>";
}
public String getDefaultaction() {
return getTagAttributeValue("defaultaction", defaultaction, null);
}
public void setDefaultaction(String defaultaction) {
this.defaultaction = defaultaction;
}
public String getContentclass() {
return getTagAttributeValue("contentclass", contentclass, null);
}
public void setContentclass(String contentclass) {
this.contentclass = contentclass;
}
@Override
protected BaseTagStatus createTagStatus() {
return new FormStatus();
}
}