/**
* Copyright (c) 2009-2014 Câmara dos Deputados. Todos os direitos reservados.
*
* e-Democracia é um software livre; você pode redistribuí-lo e/ou modificá-lo dentro
* dos termos da Licença Pública Geral Menor GNU como publicada pela Fundação do
* Software Livre (FSF); na versão 2.1 da Licença, ou (na sua opinião) qualquer versão.
*
* Este programa é distribuído na esperança de que possa ser útil, mas SEM NENHUMA GARANTIA;
* sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou APLICAÇÃO EM PARTICULAR.
* Veja a Licença Pública Geral Menor GNU para maiores detalhes.
*/
package br.gov.camara.edemocracia.portlets.wikilegis.ui.panels;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.MarkupContainer;
import org.apache.wicket.RequestCycle;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.ajax.markup.html.form.AjaxFallbackButton;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.WebComponent;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextArea;
import org.apache.wicket.markup.html.link.ExternalLink;
import org.apache.wicket.markup.html.panel.EmptyPanel;
import org.apache.wicket.markup.html.panel.Fragment;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.parser.XmlTag;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.RefreshingView;
import org.apache.wicket.model.ComponentPropertyModel;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.protocol.http.WebRequest;
import br.gov.camara.edemocracia.portlets.wikilegis.ArtigoDisplay;
import br.gov.camara.edemocracia.portlets.wikilegis.model.Artigo;
import br.gov.camara.edemocracia.portlets.wikilegis.service.WikiLegisServiceUtil;
import br.gov.camara.edemocracia.portlets.wikilegis.ui.components.LinkToAnchor;
import br.gov.camara.edemocracia.portlets.wikilegis.ui.components.UserImage;
import br.gov.camara.edemocracia.portlets.wikilegis.ui.model.ComentarioDisplay;
import br.gov.camara.edemocracia.portlets.wikilegis.ui.model.ComentarioDisplayItemReuseStrategy;
import br.gov.camara.edemocracia.portlets.wikilegis.ui.model.ComentarioDisplayModel;
import br.gov.camara.edemocracia.portlets.wikilegis.ui.util.UIUtils;
import com.google.common.collect.Iterators;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.util.ListUtil;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.portal.kernel.workflow.WorkflowConstants;
import com.liferay.portal.security.permission.ActionKeys;
import com.liferay.portal.service.UserLocalServiceUtil;
import com.liferay.portal.theme.ThemeDisplay;
import com.liferay.portlet.messageboards.model.MBMessage;
import com.liferay.portlet.messageboards.model.MBMessageConstants;
import com.liferay.portlet.messageboards.model.MBMessageDisplay;
import com.liferay.portlet.messageboards.service.MBMessageLocalServiceUtil;
import com.liferay.portlet.messageboards.util.comparator.MessageCreateDateComparator;
/**
* @author rpdmiranda
*
*/
public class ComentariosPanel extends Panel {
private static final long serialVersionUID = 1L;
private static final Log LOG = LogFactoryUtil
.getLog(ComentariosPanel.class);
public ComentariosPanel(String id, IModel<ArtigoDisplay> artigo) {
super(id, artigo);
init();
initOcultarComentarios();
}
private WebMarkupContainer comentariosContainer;
private AjaxLink<Void> adicionarComentario;
private AjaxLink<Void> cancelar;
private RefreshingView<ComentarioDisplay> comentarios;
private AjaxLink<Void> ocultarComentarios;
private WebMarkupContainer comentarioVazio;
/**
* Fragmento para edição de comentários
*
* @author robson
*
*/
private class ComentarioFragment extends Fragment {
private static final long serialVersionUID = 1L;
private Form<Void> form;
private TextArea<String> comentario;
/**
* @param id
* @param model
*/
public ComentarioFragment(String id, IModel<Long> model) {
super(id, "comentarioForm", ComentariosPanel.this, model);
form = new Form<Void>("form");
form.setOutputMarkupId(true);
form.setOutputMarkupPlaceholderTag(true);
add(form);
initComentario();
initComentar();
initCancelar();
}
public ComentarioFragment(String id, ComentarioDisplay comentario) {
super(id, "comentarioForm", ComentariosPanel.this, Model
.of(comentario));
form = new Form<Void>("form");
form.setOutputMarkupId(true);
form.setOutputMarkupPlaceholderTag(true);
add(form);
initComentario();
initComentar();
initCancelar();
}
private void removeFragmento() {
// Remove o fragmento da classe pai
MarkupContainer parent = getParent();
String id = getId();
remove();
// Acrescenta um painel vazio no pai
parent.add(new EmptyPanel(id).setVisible(false));
}
/**
* Textarea
*/
private void initComentario() {
Object obj = ComentarioFragment.this.getDefaultModelObject();
String texto = "";
if (obj instanceof ComentarioDisplay)
texto = ((ComentarioDisplay) obj).getBody();
comentario = new TextArea<String>("comentario", Model.of(texto));
form.add(comentario);
}
/**
* Botão "Gravar"
*/
private void initComentar() {
AjaxFallbackButton comentar = new AjaxFallbackButton("comentar",
form) {
private static final long serialVersionUID = 1L;
@Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
Object obj = ComentarioFragment.this
.getDefaultModelObject();
if (obj instanceof Long) {
gravaComentario(comentario.getModelObject(), (Long) obj);
} else {
atualizarComentario(comentario.getModelObject(),
((ComentarioDisplay) obj).getMessageId(),
((ComentarioDisplay) obj).getSenderId());
}
comentario.setDefaultModelObject("");
removeFragmento();
if (target != null)
target.addComponent(comentariosContainer);
onComentariosChanged(target);
}
};
form.add(comentar);
}
/**
* Botão para cancelar a edição do comentário
*/
private void initCancelar() {
cancelar = new AjaxLink<Void>("cancelar") {
private static final long serialVersionUID = 1L;
@Override
public void onClick(AjaxRequestTarget target) {
removeFragmento();
if (target != null)
target.addComponent(comentariosContainer);
}
};
form.add(cancelar);
}
}
// //////////////////////////////////////
// Componentes
// //////////////////////////////////////
private void init() {
comentariosContainer = new WebMarkupContainer("comentariosContainer");
comentariosContainer.setOutputMarkupId(true);
add(comentariosContainer);
initAdicionarComentario();
comentariosContainer.add(new EmptyPanel("comentarioRaiz"));
initComentarios();
}
/**
* ,final Item<ComentarioDisplay> item Lista de comentários
*/
private void initComentarios() {
comentarioVazio = new WebMarkupContainer("comentarioVazio") {
@Override
protected void onConfigure() {
super.onConfigure();
setVisible(!listaMensagens().hasNext());
}
};
comentariosContainer.add(comentarioVazio);
comentarios = new RefreshingView<ComentarioDisplay>("comentarios") {
private static final long serialVersionUID = 1L;
@Override
protected Iterator<IModel<ComentarioDisplay>> getItemModels() {
return listaMensagens();
}
@Override
protected void populateItem(final Item<ComentarioDisplay> item) {
WebComponent postagem = new WebComponent("postagem") {
/**
* @see org.apache.wicket.Component#onComponentTag(org.apache.wicket.markup.ComponentTag)
*/
@Override
protected void onComponentTag(ComponentTag tag) {
super.onComponentTag(tag);
tag.setType(XmlTag.OPEN);
}
};
postagem.add(new AttributeModifier("name",
new ComponentPropertyModel<String>("anchor")));
String urlToUserProfile = getUserProfileURL(item
.getModelObject().getSenderId());
item.add(postagem);
item.add(new ExternalLink("senderProfile", urlToUserProfile)
.add(new UserImage("senderId")));
item.add(new ExternalLink("senderName", urlToUserProfile, item
.getModelObject().getSenderName()));
item.add(new Label("body").setEscapeModelStrings(false));
item.add(new Label("when"));
item.add(new AjaxLink<Long>("responder",
new ComponentPropertyModel<Long>("messageId")) {
private static final long serialVersionUID = 1L;
@Override
protected void onConfigure() {
super.onConfigure();
setVisible(UIUtils
.possuiPermissoes(ActionKeys.ADD_DISCUSSION));
}
@Override
public void onClick(AjaxRequestTarget target) {
adicionarComentario("resposta", item, getModelObject());
if (target != null)
target.addComponent(comentariosContainer);
}
});
item.add(new LinkToAnchor("linkArtigo",
new PropertyModel<String>(ComentariosPanel.this
.getDefaultModel(), "nodeName")));
item.add(new AjaxLink<Long>("alterar",
new ComponentPropertyModel<Long>("messageId")) {
private static final long serialVersionUID = 1L;
@Override
protected void onConfigure() {
super.onConfigure();
if (!(UIUtils
.possuiPermissoes(ActionKeys.UPDATE_DISCUSSION) || UIUtils
.isOwner(item.getModelObject().getSenderId(),
ActionKeys.UPDATE_DISCUSSION)))
setVisible(false);
}
@Override
public void onClick(AjaxRequestTarget target) {
editarComentario("resposta", item,
item.getModelObject());
if (target != null)
target.addComponent(comentariosContainer);
}
});
item.add(new AjaxLink<Void>("exclui") {
private static final long serialVersionUID = 1L;
@Override
protected void onConfigure() {
super.onConfigure();
if (!(UIUtils
.possuiPermissoes(ActionKeys.DELETE_DISCUSSION) || UIUtils
.isOwner(item.getModelObject().getSenderId(),
ActionKeys.DELETE_DISCUSSION)))
setVisible(false);
}
@Override
public void onClick(AjaxRequestTarget target) {
excluiComentario(item.getModelObject());
if (target != null)
target.addComponent(comentariosContainer);
onComentariosChanged(target);
}
});
LinkToAnchor parentMessageName = new LinkToAnchor(
"parentMessageName");
item.add(parentMessageName);
Label inReplyTo = new Label("inReplyToName") {
@Override
public boolean isVisible() {
return getDefaultModelObject() != null
&& getDefaultModelObjectAsString().length() > 0;
}
};
parentMessageName.add(inReplyTo);
item.add(new EmptyPanel("resposta"));
item.setVisible(item.getModelObject() != null);
}
private String getUserProfileURL(long userId) {
try {
return UserLocalServiceUtil.getUser(userId).getDisplayURL(
UIUtils.getThemeDisplay());
} catch (PortalException e) {
// ignore
} catch (SystemException e) {
// ignore
}
return "#";
}
};
comentarios.setItemReuseStrategy(ComentarioDisplayItemReuseStrategy
.getInstance());
comentariosContainer.add(comentarios);
}
/**
* Link para adicionar comentário
*/
private void initAdicionarComentario() {
adicionarComentario = new AjaxLink<Void>("adicionarComentario") {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public void onClick(AjaxRequestTarget target) {
adicionarComentario("comentarioRaiz", comentariosContainer,
MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID);
if (target != null)
target.addComponent(comentariosContainer);
}
@Override
protected void onConfigure() {
super.onConfigure();
setVisible(UIUtils.possuiPermissoes(ActionKeys.ADD_DISCUSSION));
}
};
comentariosContainer.add(adicionarComentario);
}
/**
* Acrescenta o campo
*
* @param id
* @param container
* @param parentMessageId
*/
private void adicionarComentario(String id, WebMarkupContainer container,
long parentMessageId) {
container.remove(id);
ComentarioFragment frag = new ComentarioFragment(id,
Model.of(parentMessageId));
container.add(frag);
}
/**
* Acrescenta o comentário para edição
*
* @param id
* @param container
* @param comentario
*/
private void editarComentario(String id, WebMarkupContainer container,
ComentarioDisplay comentario) {
container.remove(id);
ComentarioFragment frag = new ComentarioFragment(id, comentario);
container.add(frag);
}
private void gravaComentario(String body, long parentMessageId) {
try {
long artigoId = ((ArtigoDisplay) getDefaultModelObject()).getId();
WikiLegisServiceUtil.postaComentario(artigoId, parentMessageId,
body);
} catch (PortalException ex) {
LOG.error("Erro ao gravar comentário", ex);
} catch (SystemException ex) {
LOG.error("Erro ao gravar comentário", ex);
}
}
private void atualizarComentario(String body, long messageId, long userId) {
try {
long artigoId = ((ArtigoDisplay) getDefaultModelObject()).getId();
WikiLegisServiceUtil.atualizaComentario(body, artigoId, messageId,
userId);
} catch (PortalException e) {
LOG.error("Erro ao atualizar comentário");
} catch (SystemException e) {
LOG.error("Erro ao atualizar comentário");
}
}
/**
* @return
* @throws PortalException
* @throws SystemException
*/
private Iterator<IModel<ComentarioDisplay>> listaMensagens() {
try {
MBMessageDisplay md = getDisplayMessage();
List<MBMessage> messages = md.getTreeWalker().getMessages();
messages.remove(md.getTreeWalker().getRoot());
messages = ListUtil.sort(messages, new MessageCreateDateComparator(
true));
HttpServletRequest req = ((WebRequest) RequestCycle.get()
.getRequest()).getHttpServletRequest();
ThemeDisplay td = (ThemeDisplay) req
.getAttribute(WebKeys.THEME_DISPLAY);
DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT,
td.getLocale());
df.setTimeZone(td.getTimeZone());
ArrayList<IModel<ComentarioDisplay>> retorno = new ArrayList<IModel<ComentarioDisplay>>();
for (MBMessage message : messages)
retorno.add(new CompoundPropertyModel<ComentarioDisplay>(
new ComentarioDisplayModel(message, df)));
return retorno.iterator();
} catch (SystemException e) {
LOG.error("Erro ao obter mensagens de comentário. ", e);
return Iterators.emptyIterator();
} catch (PortalException e) {
LOG.error("Erro ao obter mensagens de comentário. ", e);
return Iterators.emptyIterator();
}
}
/**
* Exclui o comentário especificado
*
* @param comentario
*/
private void excluiComentario(ComentarioDisplay comentario) {
try {
long messageId = comentario.getMessageId();
long artigoId = ((ArtigoDisplay) getDefaultModelObject()).getId();
WikiLegisServiceUtil.excluiComentario(artigoId, messageId);
} catch (Exception e) {
LOG.error("Erro ao excluir mensagem", e);
}
}
/**
* @return
* @throws PortalException
* @throws SystemException
*/
private MBMessageDisplay getDisplayMessage() throws PortalException,
SystemException {
String className = Artigo.class.getName();
long idArtigo = ((ArtigoDisplay) getDefaultModelObject()).getId();
HttpServletRequest req = ((WebRequest) RequestCycle.get().getRequest())
.getHttpServletRequest();
ThemeDisplay td = (ThemeDisplay) req
.getAttribute(WebKeys.THEME_DISPLAY);
long userId = td.getUserId();
long groupId = td.getScopeGroupId();
MBMessageDisplay md = MBMessageLocalServiceUtil
.getDiscussionMessageDisplay(userId, groupId, className,
idArtigo, WorkflowConstants.STATUS_ANY);
return md;
}
private void initOcultarComentarios() {
ocultarComentarios = new AjaxLink<Void>("ocultarComentarios") {
private static final long serialVersionUID = 1L;
@Override
public void onClick(AjaxRequestTarget target) {
MarkupContainer parent = getParent();
while (parent != null
&& !(parent instanceof WikiLegisArtigoPanel))
parent = parent.getParent();
if (parent != null)
((WikiLegisArtigoPanel) parent).ocultaComentarios(target);
}
};
add(ocultarComentarios);
}
/**
* Chamado quando há mudança nos comentários (exclusão/inclusão)
*
* @param target
*/
protected void onComentariosChanged(AjaxRequestTarget target) {
}
}