/*
This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your option) any
later version.
This program 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along
with this program; if not, see http://www.gnu.org/licenses or write to the Free
Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
*/
package com.servoy.j2db.server.headlessclient.dataui;
import java.text.ParseException;
import java.util.Iterator;
import java.util.List;
import javax.swing.text.Document;
import org.apache.wicket.Component;
import org.apache.wicket.Page;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.MarkupStream;
import org.apache.wicket.markup.html.IHeaderContributor;
import org.apache.wicket.markup.html.IHeaderResponse;
import org.apache.wicket.model.IComponentInheritedModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.IWrapModel;
import org.apache.wicket.util.convert.IConverter;
import org.apache.wicket.util.value.IValueMap;
import com.servoy.base.util.ITagResolver;
import com.servoy.j2db.IApplication;
import com.servoy.j2db.component.ComponentFormat;
import com.servoy.j2db.dataprocessing.IDisplayData;
import com.servoy.j2db.dataprocessing.IEditListener;
import com.servoy.j2db.dataprocessing.TagResolver;
import com.servoy.j2db.server.headlessclient.MainPage;
import com.servoy.j2db.server.headlessclient.dataui.StripHTMLTagsConverter.StrippedText;
import com.servoy.j2db.ui.IDisplayTagText;
import com.servoy.j2db.ui.scripting.AbstractRuntimeBaseComponent;
import com.servoy.j2db.ui.scripting.IFormatScriptComponent;
import com.servoy.j2db.util.Debug;
import com.servoy.j2db.util.HtmlUtils;
import com.servoy.j2db.util.Text;
import com.servoy.j2db.util.Utils;
import com.servoy.j2db.util.text.ServoyMaskFormatter;
/**
* Represents a label in the browser that displays data (has a dataprovider) and on on action event.
*
* @author jcompagner
*/
public class WebDataSubmitLink extends WebBaseSubmitLink implements IDisplayData, IDisplayTagText, IHeaderContributor
{
private static final long serialVersionUID = 1L;
private final static String CSS_OPEN_TAG = "<style type=\"text/css\"><!--/*--><![CDATA[/*><!--*/\n"; //$NON-NLS-1$
private final static String CSS_CLOSE_TAG = "\n/*-->]]>*/</style>\n"; //$NON-NLS-1$
private boolean needEntireState;
private String dataProviderID;
private String tagText;
//private String tooltip;
private String inputId;
private boolean hasHTML;
private StrippedText strippedText = new StripHTMLTagsConverter.StrippedText();
protected ITagResolver resolver;
private String bodyText;
public WebDataSubmitLink(IApplication application, AbstractRuntimeBaseComponent scriptable, String id)
{
super(application, scriptable, id);
}
@Override
public void setText(String txt)
{
//ignore, we don't want a model as created in super class, but data from record
}
@Override
protected IModel< ? > initModel()
{
// Search parents for CompoundPropertyModel
for (Component current = getParent(); current != null; current = current.getParent())
{
// Get model
IModel< ? > model = current.getDefaultModel();
if (model instanceof IWrapModel< ? >)
{
model = ((IWrapModel< ? >)model).getWrappedModel();
}
if (model instanceof IComponentInheritedModel< ? >)
{
// we turn off versioning as we share the model with another
// ct that is the owner of the model (that component
// has to decide whether to version or not
setVersioned(false);
// return the shared inherited
model = ((IComponentInheritedModel< ? >)model).wrapOnInheritance(this);
return model;
}
}
// No model for this component!
return null;
}
@Override
public IConverter getConverter(Class< ? > cls)
{
return getApplication().getConverterLocator().getConverter(cls);
}
public void setTagResolver(ITagResolver resolver)
{
this.resolver = resolver;
}
/**
* @see org.apache.wicket.markup.html.link.AbstractLink#onBeforeRender()
*/
@Override
protected void onBeforeRender()
{
super.onBeforeRender();
strippedText = new StripHTMLTagsConverter.StrippedText();
IModel< ? > model = getInnermostModel();
hasHTML = false;
bodyText = null;
if (needEntireState && model instanceof RecordItemModel)
{
if (dataProviderID != null)
{
Object value = getDefaultModelObject();
if (value instanceof byte[])
{
setIcon((byte[])value);
if (model instanceof RecordItemModel)
{
((RecordItemModel)model).updateRenderedValue(this);
}
return;
}
if (icon != null) setIcon(null);
if (value instanceof String)
{
ComponentFormat cf = getComponentFormat();
if (cf == null)
{
bodyText = Text.processTags((String)value, resolver);
}
else
{
try
{
bodyText = Text.processTags(
TagResolver.formatObject(value, application.getLocale(), cf.parsedFormat,
(cf.parsedFormat.getDisplayFormat() != null ? new ServoyMaskFormatter(cf.parsedFormat.getDisplayFormat(), true) : null)),
resolver);
}
catch (ParseException e)
{
Debug.error(e);
}
}
}
else
{
bodyText = getDefaultModelObjectAsString();
}
}
else
{
bodyText = Text.processTags(tagText, resolver);
}
}
else
{
Object modelObject = getDefaultModelObject();
if (modelObject instanceof byte[])
{
setIcon((byte[])modelObject);
}
else if (icon != null)
{
setIcon(null);
}
else
{
ComponentFormat cf = getComponentFormat();
if (cf == null)
{
bodyText = Text.processTags(getDefaultModelObjectAsString(), resolver);
}
else
{
try
{
bodyText = TagResolver.formatObject(modelObject, application.getLocale(), cf.parsedFormat,
(cf.parsedFormat.getDisplayFormat() != null ? new ServoyMaskFormatter(cf.parsedFormat.getDisplayFormat(), true) : null));
}
catch (ParseException e)
{
Debug.error(e);
}
}
}
}
if (HtmlUtils.startsWithHtml(bodyText))
{
strippedText = StripHTMLTagsConverter.convertBodyText(this, bodyText, application.getFlattenedSolution());
hasHTML = true;
}
else
{
strippedText.setBodyTxt(bodyText);
}
if (model instanceof RecordItemModel)
{
((RecordItemModel)model).updateRenderedValue(this);
}
}
protected ComponentFormat getComponentFormat()
{
if (getScriptObject() instanceof IFormatScriptComponent)
{
return ((IFormatScriptComponent)getScriptObject()).getComponentFormat();
}
return null;
}
/**
* @see org.apache.wicket.markup.html.IHeaderContributor#renderHead(org.apache.wicket.markup.html.IHeaderResponse)
*/
public void renderHead(IHeaderResponse response)
{
List<CharSequence> lst = strippedText.getJavascriptUrls();
for (int i = 0; i < lst.size(); i++)
{
response.renderJavascriptReference(lst.get(i).toString());
}
lst = strippedText.getJavascriptScripts();
for (int i = 0; i < lst.size(); i++)
{
response.renderJavascript(lst.get(i), "js_" + getMarkupId() + lst.get(i).hashCode()); //$NON-NLS-1$
}
lst = strippedText.getLinkTags();
for (int i = 0; i < lst.size(); i++)
{
response.renderString(lst.get(i));
}
lst = strippedText.getStyles();
for (CharSequence style : lst)
{
response.renderString(CSS_OPEN_TAG + style + CSS_CLOSE_TAG);
}
IValueMap map = strippedText.getBodyAttributes();
if (map != null && map.size() > 0)
{
String onLoad = null;
Iterator<String> iterator = map.keySet().iterator();
while (iterator.hasNext())
{
String attributeName = iterator.next();
if (attributeName.equalsIgnoreCase("onload")) //$NON-NLS-1$
{
onLoad = map.getString(attributeName);
iterator.remove();
break;
}
}
if (onLoad != null)
{
response.renderOnLoadJavascript(onLoad);
}
Page findPage = findPage();
if (findPage instanceof MainPage)
{
((MainPage)findPage).addBodyAttributes(map);
}
}
}
/**
* @see com.servoy.j2db.server.headlessclient.dataui.WebBaseSubmitLink#onComponentTagBody(wicket.markup.MarkupStream, wicket.markup.ComponentTag)
*/
@Override
protected void onComponentTagBody(MarkupStream markupStream, ComponentTag openTag)
{
CharSequence bodyText = strippedText.getBodyTxt();
instrumentAndReplaceBody(markupStream, openTag, bodyText);
}
@Override
protected boolean hasHtmlOrImage()
{
return hasHTML || super.hasHtmlOrImage() || getDefaultModelObject() instanceof byte[];
}
@Override
protected CharSequence getBodyText()
{
return strippedText.getBodyTxt();
}
/**
* @see wicket.markup.html.form.FormComponent#getInputName()
*/
@Override
public String getInputName()
{
if (inputId == null)
{
Page page = findPage();
if (page instanceof MainPage)
{
inputId = ((MainPage)page).nextInputNameId();
}
else
{
return super.getInputName();
}
}
return inputId;
}
public Object getValueObject()
{
return getDefaultModelObject();
}
public void setValueObject(Object value)
{
if (dataProviderID == null && needEntireState)
{
CharSequence current = Text.processTags(tagText, resolver);
if (current != null && bodyText != null)
{
if (!Utils.equalObjects(bodyText.toString(), current.toString())) getScriptObject().getChangesRecorder().setChanged();
}
else if (current != null || bodyText != null)
{
getScriptObject().getChangesRecorder().setChanged();
}
}
else
{
((ChangesRecorder)getScriptObject().getChangesRecorder()).testChanged(this, value);
}
}
public boolean needEditListener()
{
return false;
}
public void addEditListener(IEditListener l)
{
}
public boolean needEntireState()
{
return needEntireState;
}
public void setNeedEntireState(boolean needEntireState)
{
this.needEntireState = needEntireState;
}
public String getDataProviderID()
{
return dataProviderID;
}
public void setDataProviderID(String dataProviderID)
{
this.dataProviderID = dataProviderID;
}
public Document getDocument()
{
return null;
}
public void notifyLastNewValueWasChange(Object oldVal, Object newVal)
{
// ignore
}
public boolean isValueValid()
{
return true;
}
public void setValueValid(boolean valid, Object oldVal)
{
// ignore
}
public void setValidationEnabled(boolean b)
{
}
public boolean stopUIEditing(boolean looseFocus)
{
return true;
}
public void setTagText(String tagText)
{
this.tagText = tagText;
}
public String getTagText()
{
return tagText;
}
public boolean isReadOnly()
{
return !isEnabled();
}
}