/*
* Copyright (C) 2003-2017 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.exoplatform.management.uiextension;
import org.exoplatform.commons.utils.LazyPageList;
import org.exoplatform.commons.utils.ListAccessImpl;
import org.exoplatform.management.uiextension.comparison.NodeComparison;
import org.exoplatform.management.uiextension.comparison.NodeComparisonState;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.web.application.ApplicationMessage;
import org.exoplatform.webui.application.WebuiRequestContext;
import org.exoplatform.webui.config.annotation.ComponentConfig;
import org.exoplatform.webui.config.annotation.ComponentConfigs;
import org.exoplatform.webui.config.annotation.EventConfig;
import org.exoplatform.webui.core.UIGrid;
import org.exoplatform.webui.core.UIPopupComponent;
import org.exoplatform.webui.core.lifecycle.UIFormLifecycle;
import org.exoplatform.webui.core.model.SelectItemOption;
import org.exoplatform.webui.event.Event;
import org.exoplatform.webui.event.EventListener;
import org.exoplatform.webui.form.UIForm;
import org.exoplatform.webui.form.UIFormDateTimeInput;
import org.exoplatform.webui.form.UIFormSelectBox;
import org.exoplatform.webui.form.UIFormStringInput;
import org.exoplatform.webui.form.input.UICheckBoxInput;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;
import java.util.ResourceBundle;
/**
* The Class SelectNodesComponent.
*
* @author <a href="mailto:bkhanfir@exoplatform.com">Boubaker Khanfir</a>
* @version $Revision$
*/
@ComponentConfigs({
@ComponentConfig(type = UIGrid.class, id = "uiSelectedNodesGrid", template = "classpath:groovy/webui/component/explorer/popup/staging/UISelectedNodesGrid.gtmpl"),
@ComponentConfig(type = UIGrid.class, id = "selectNodesGrid", template = "classpath:groovy/webui/component/explorer/popup/staging/UISelectNodesGrid.gtmpl"),
@ComponentConfig(lifecycle = UIFormLifecycle.class, template = "classpath:groovy/webui/component/explorer/popup/staging/SelectContents.gtmpl", events = {
@EventConfig(listeners = SelectNodesComponent.FilterActionListener.class), @EventConfig(listeners = SelectNodesComponent.SelectActionListener.class),
@EventConfig(listeners = SelectNodesComponent.SelectAllActionListener.class), @EventConfig(listeners = SelectNodesComponent.DeleteAllActionListener.class),
@EventConfig(listeners = SelectNodesComponent.DeleteActionListener.class) }) })
public class SelectNodesComponent extends UIForm implements UIPopupComponent {
/** The Constant LOG. */
private static final Log LOG = ExoLogger.getLogger(SelectNodesComponent.class.getName());
/** The Constant CONTENT_STATE_FIELD_NAME. */
public static final String CONTENT_STATE_FIELD_NAME = "contentState";
/** The Constant FILTER_CONTENT_FIELD_NAME. */
public static final String FILTER_CONTENT_FIELD_NAME = "filter";
/** The Constant PUBLICATION_DATE_FIELD_NAME. */
public static final String PUBLICATION_DATE_FIELD_NAME = "modifiedAfter";
/** The Constant PUBLISHED_CONTENT_ONLY_FIELD_NAME. */
public static final String PUBLISHED_CONTENT_ONLY_FIELD_NAME = "publishedContentOnly";
/** The comparison bean field. */
public static String[] COMPARISON_BEAN_FIELD = { "title", "path", "published", "sourceModificationDate", "targetModificationDate", "stateLocalized" };
/** The comparison bean action. */
public static String[] COMPARISON_BEAN_ACTION = { "Select" };
/** The selected comparison bean field. */
public static String[] SELECTED_COMPARISON_BEAN_FIELD = { "title", "path", "actionLocalized" };
/** The selected comparison bean action. */
public static String[] SELECTED_COMPARISON_BEAN_ACTION = { "Delete" };
/** The nodes grid. */
private UIGrid nodesGrid;
/** The selected nodes grid. */
private UIGrid selectedNodesGrid;
/** The filter field. */
protected UIFormStringInput filterField;
/** The state select box input. */
protected UIFormSelectBox stateSelectBoxInput;
/** The published check box input. */
protected UICheckBoxInput publishedCheckBoxInput;
/** The from date modified. */
UIFormDateTimeInput fromDateModified = null;
/** The push content popup component. */
private PushContentPopupComponent pushContentPopupComponent;
/** The state string. */
String stateString = null;
/** The modified date filter. */
Calendar modifiedDateFilter = null;
/** The filter string. */
String filterString = null;
/** The published content only. */
boolean publishedContentOnly = false;
/** The comparisons. */
private List<NodeComparison> comparisons;
/** The filtered comparison. */
private List<NodeComparison> filteredComparison;
/**
* Instantiates a new select nodes component.
*
* @throws Exception the exception
*/
public SelectNodesComponent() throws Exception {
ResourceBundle resourceBundle = WebuiRequestContext.getCurrentInstance().getApplicationResourceBundle();
List<SelectItemOption<String>> options = new ArrayList<SelectItemOption<String>>();
options.add(new SelectItemOption<String>(resourceBundle.getString("PushContent.state.all"), ""));
options.add(new SelectItemOption<String>(NodeComparisonState.MODIFIED_ON_SOURCE.getLabel(resourceBundle), NodeComparisonState.MODIFIED_ON_SOURCE.getKey()));
options.add(new SelectItemOption<String>(NodeComparisonState.MODIFIED_ON_TARGET.getLabel(resourceBundle), NodeComparisonState.MODIFIED_ON_TARGET.getKey()));
options.add(new SelectItemOption<String>(NodeComparisonState.SAME.getLabel(resourceBundle), NodeComparisonState.SAME.getKey()));
options.add(new SelectItemOption<String>(NodeComparisonState.UNKNOWN.getLabel(resourceBundle), NodeComparisonState.UNKNOWN.getKey()));
stateSelectBoxInput = new UIFormSelectBox(CONTENT_STATE_FIELD_NAME, CONTENT_STATE_FIELD_NAME, options);
addUIFormInput(stateSelectBoxInput);
stateSelectBoxInput.setHTMLAttribute("style", "width:120px;");
publishedCheckBoxInput = new UICheckBoxInput(PUBLISHED_CONTENT_ONLY_FIELD_NAME, PUBLISHED_CONTENT_ONLY_FIELD_NAME, false);
publishedCheckBoxInput.setLabel("publishedContentOnly");
publishedCheckBoxInput.setChecked(true);
addUIFormInput(publishedCheckBoxInput);
filterField = new UIFormStringInput(FILTER_CONTENT_FIELD_NAME, FILTER_CONTENT_FIELD_NAME, "");
addUIFormInput(filterField);
filterField.setHTMLAttribute("style", "width:90px;");
fromDateModified = new UIFormDateTimeInput(PUBLICATION_DATE_FIELD_NAME, PUBLICATION_DATE_FIELD_NAME, null, false);
addUIFormInput(fromDateModified);
fromDateModified.setHTMLAttribute("style", "width:135px;");
nodesGrid = addChild(UIGrid.class, "selectNodesGrid", "selectNodesGrid");
nodesGrid.configure("path", COMPARISON_BEAN_FIELD, COMPARISON_BEAN_ACTION);
nodesGrid.getUIPageIterator().setId("UISelectNodesGridIterator");
selectedNodesGrid = addChild(UIGrid.class, "uiSelectedNodesGrid", "uiSelectedNodesGrid");
selectedNodesGrid.configure("path", SELECTED_COMPARISON_BEAN_FIELD, SELECTED_COMPARISON_BEAN_ACTION);
selectedNodesGrid.getUIPageIterator().setId("UISelectedNodesGridIterator");
}
/**
* Inits the.
*
* @throws Exception the exception
*/
public void init() throws Exception {
String fieldJavascriptAction = event("Filter", null).replace("javascript:", "");
filterField.setHTMLAttribute("onblur", fieldJavascriptAction);
filterField.setHTMLAttribute("onkeypress", "if(event.keyCode == 13){" + fieldJavascriptAction + ";event.preventDefault();}");
fromDateModified.setHTMLAttribute("onblur", "var textField = this; setTimeout(function(){ " + fieldJavascriptAction + "}, 200);");
fromDateModified.setHTMLAttribute("oninput", "var textField = this; setTimeout(function(){ " + fieldJavascriptAction + "}, 200);");
fromDateModified.setHTMLAttribute("onkeypress", "if(event.keyCode == 13)event.preventDefault()");
publishedCheckBoxInput.setOnChange("Filter");
stateSelectBoxInput.setOnChange("Filter");
this.stateString = pushContentPopupComponent.stateString;
stateSelectBoxInput.setValue(this.stateString);
this.modifiedDateFilter = pushContentPopupComponent.modifiedDateFilter;
fromDateModified.setCalendar(this.modifiedDateFilter);
this.filterString = pushContentPopupComponent.filterString;
filterField.setValue(this.filterString);
this.publishedContentOnly = pushContentPopupComponent.publishedContentOnly;
publishedCheckBoxInput.setChecked(this.publishedContentOnly);
}
/**
* Sets the comparisons.
*
* @param comparisons the new comparisons
*/
public void setComparisons(List<NodeComparison> comparisons) {
this.comparisons = comparisons;
filteredComparison = new ArrayList<NodeComparison>(comparisons);
computeComparisons();
}
/**
* Compute comparisons.
*/
public void computeComparisons() {
List<NodeComparison> alreadySelectedNodes = pushContentPopupComponent.getSelectedNodes();
filteredComparison.clear();
pushContentPopupComponent.filterString = filterString = filterField.getValue();
pushContentPopupComponent.modifiedDateFilter = modifiedDateFilter = fromDateModified.getCalendar();
pushContentPopupComponent.stateString = stateString = stateSelectBoxInput.getValue();
pushContentPopupComponent.publishedContentOnly = publishedContentOnly = publishedCheckBoxInput.getValue();
for (NodeComparison nodeComparison : comparisons) {
if (!alreadySelectedNodes.contains(nodeComparison) && checkFilter(nodeComparison)) {
filteredComparison.add(nodeComparison);
}
}
nodesGrid.getUIPageIterator().setPageList(new LazyPageList<NodeComparison>(new ListAccessImpl<NodeComparison>(NodeComparison.class, filteredComparison), 5));
if (pushContentPopupComponent.getSelectedNodes().isEmpty()) {
selectedNodesGrid.getUIPageIterator().setPageList(new LazyPageList<NodeComparison>(new ListAccessImpl<NodeComparison>(NodeComparison.class, pushContentPopupComponent.getDefaultSelection()), 5));
} else {
selectedNodesGrid.getUIPageIterator().setPageList(new LazyPageList<NodeComparison>(new ListAccessImpl<NodeComparison>(NodeComparison.class, pushContentPopupComponent.getSelectedNodes()), 5));
}
}
/**
* The listener interface for receiving filterAction events.
* The class that is interested in processing a filterAction
* event implements this interface, and the object created
* with that class is registered with a component using the
* component's <code>addFilterActionListener</code> method. When
* the filterAction event occurs, that object's appropriate
* method is invoked.
*
*/
public static class FilterActionListener extends EventListener<SelectNodesComponent> {
/**
* {@inheritDoc}
*/
@Override
public void execute(Event<SelectNodesComponent> event) throws Exception {
SelectNodesComponent selectNodesComponent = event.getSource();
selectNodesComponent.computeComparisons();
event.getRequestContext().addUIComponentToUpdateByAjax(selectNodesComponent.getNodesGrid());
}
}
/**
* The listener interface for receiving selectAction events.
* The class that is interested in processing a selectAction
* event implements this interface, and the object created
* with that class is registered with a component using the
* component's <code>addSelectActionListener</code> method. When
* the selectAction event occurs, that object's appropriate
* method is invoked.
*
*/
public static class SelectActionListener extends EventListener<SelectNodesComponent> {
/**
* {@inheritDoc}
*/
@Override
public void execute(Event<SelectNodesComponent> event) throws Exception {
SelectNodesComponent selectNodesComponent = event.getSource();
PushContentPopupComponent pushContentPopupComponent = selectNodesComponent.getPushContentPopupComponent();
String path = event.getRequestContext().getRequestParameter(OBJECTID);
Iterator<NodeComparison> comparisons = selectNodesComponent.getComparisons().iterator();
NodeComparison selectedNodeComparison = null;
while (selectedNodeComparison == null && comparisons.hasNext()) {
NodeComparison tmpNodeComparison = comparisons.next();
if (path.equals(tmpNodeComparison.getPath())) {
selectedNodeComparison = tmpNodeComparison;
break;
}
}
pushContentPopupComponent.addSelection(selectedNodeComparison);
selectNodesComponent.computeComparisons();
event.getRequestContext().addUIComponentToUpdateByAjax(selectNodesComponent);
}
}
/**
* The listener interface for receiving deleteAllAction events.
* The class that is interested in processing a deleteAllAction
* event implements this interface, and the object created
* with that class is registered with a component using the
* component's <code>addDeleteAllActionListener</code> method. When
* the deleteAllAction event occurs, that object's appropriate
* method is invoked.
*
*/
public static class DeleteAllActionListener extends EventListener<SelectNodesComponent> {
/**
* {@inheritDoc}
*/
@Override
public void execute(Event<SelectNodesComponent> event) throws Exception {
SelectNodesComponent selectNodesComponent = event.getSource();
selectNodesComponent.getSelectedNodesGrid().getUIPageIterator().setPageList(new LazyPageList<NodeComparison>(new ListAccessImpl<NodeComparison>(NodeComparison.class, selectNodesComponent.getPushContentPopupComponent().getDefaultSelection()), 5));
selectNodesComponent.getPushContentPopupComponent().getSelectedNodes().clear();
selectNodesComponent.computeComparisons();
event.getRequestContext().addUIComponentToUpdateByAjax(selectNodesComponent.getNodesGrid());
event.getRequestContext().addUIComponentToUpdateByAjax(selectNodesComponent.getSelectedNodesGrid());
}
}
/**
* The listener interface for receiving deleteAction events.
* The class that is interested in processing a deleteAction
* event implements this interface, and the object created
* with that class is registered with a component using the
* component's <code>addDeleteActionListener</code> method. When
* the deleteAction event occurs, that object's appropriate
* method is invoked.
*
*/
static public class DeleteActionListener extends EventListener<UIForm> {
/**
* {@inheritDoc}
*/
public void execute(Event<UIForm> event) throws Exception {
UIForm uiForm = event.getSource();
PushContentPopupComponent pushContentPopupComponent = null;
if (uiForm instanceof PushContentPopupComponent) {
pushContentPopupComponent = (PushContentPopupComponent) uiForm;
} else if (uiForm instanceof SelectNodesComponent) {
pushContentPopupComponent = ((SelectNodesComponent) uiForm).getPushContentPopupComponent();
}
String path = event.getRequestContext().getRequestParameter(OBJECTID);
try {
Iterator<NodeComparison> comparisons = pushContentPopupComponent.getSelectedNodes().iterator();
boolean removed = false;
while (!removed && comparisons.hasNext()) {
NodeComparison comparison = comparisons.next();
if (path.equals(comparison.getPath())) {
comparisons.remove();
removed = true;
}
}
if (removed) {
if (pushContentPopupComponent.getSelectedNodes().isEmpty()) {
pushContentPopupComponent.getSelectNodesComponent().getSelectedNodesGrid().getUIPageIterator().setPageList(new LazyPageList<NodeComparison>(new ListAccessImpl<NodeComparison>(NodeComparison.class, pushContentPopupComponent.getDefaultSelection()), 5));
} else {
pushContentPopupComponent.getSelectNodesComponent().getSelectedNodesGrid().getUIPageIterator().setPageList(new LazyPageList<NodeComparison>(new ListAccessImpl<NodeComparison>(NodeComparison.class, pushContentPopupComponent.getSelectedNodes()), 5));
}
}
if (pushContentPopupComponent.getSelectNodesComponent().isRendered()) {
pushContentPopupComponent.getSelectNodesComponent().computeComparisons();
event.getRequestContext().addUIComponentToUpdateByAjax(pushContentPopupComponent.getSelectNodesComponent());
}
} catch (Exception ex) {
ApplicationMessage message = new ApplicationMessage("PushContent.msg.synchronizationError", null, ApplicationMessage.ERROR);
message.setResourceBundle(PushContentPopupComponent.getResourceBundle());
pushContentPopupComponent.getUIFormInputInfo(PushContentPopupComponent.INFO_FIELD_NAME).setValue(message.getMessage());
LOG.error("Error while deleting '" + path + "' from selected contents:", ex);
}
}
}
/**
* The listener interface for receiving selectAllAction events.
* The class that is interested in processing a selectAllAction
* event implements this interface, and the object created
* with that class is registered with a component using the
* component's <code>addSelectAllActionListener</code> method. When
* the selectAllAction event occurs, that object's appropriate
* method is invoked.
*
*/
public static class SelectAllActionListener extends EventListener<SelectNodesComponent> {
/**
* {@inheritDoc}
*/
@Override
public void execute(Event<SelectNodesComponent> event) throws Exception {
SelectNodesComponent selectNodesComponent = event.getSource();
PushContentPopupComponent pushContentPopupComponent = selectNodesComponent.getPushContentPopupComponent();
List<NodeComparison> comparisons = selectNodesComponent.getFilteredComparison();
for (NodeComparison nodeComparison : comparisons) {
if (nodeComparison.getState().equals("unknown")) {
continue;
}
pushContentPopupComponent.addSelection(nodeComparison);
}
selectNodesComponent.computeComparisons();
event.getRequestContext().addUIComponentToUpdateByAjax(selectNodesComponent.getNodesGrid());
event.getRequestContext().addUIComponentToUpdateByAjax(selectNodesComponent.getSelectedNodesGrid());
}
}
/**
* {@inheritDoc}
*/
@Override
public void activate() {}
/**
* {@inheritDoc}
*/
@Override
public void deActivate() {}
/**
* Gets the selected nodes grid.
*
* @return the selected nodes grid
*/
public UIGrid getSelectedNodesGrid() {
return selectedNodesGrid;
}
/**
* Gets the nodes grid.
*
* @return the nodes grid
*/
public UIGrid getNodesGrid() {
return nodesGrid;
}
/**
* Gets the comparisons.
*
* @return the comparisons
*/
public List<NodeComparison> getComparisons() {
return comparisons;
}
/**
* Gets the filtered comparison.
*
* @return the filtered comparison
*/
public List<NodeComparison> getFilteredComparison() {
return filteredComparison;
}
/**
* Sets the push content popup component.
*
* @param pushContentPopupComponent the new push content popup component
*/
public void setPushContentPopupComponent(PushContentPopupComponent pushContentPopupComponent) {
this.pushContentPopupComponent = pushContentPopupComponent;
}
/**
* Gets the push content popup component.
*
* @return the push content popup component
*/
public PushContentPopupComponent getPushContentPopupComponent() {
return pushContentPopupComponent;
}
/**
* Check filter.
*
* @param nodeComparison the node comparison
* @return true, if successful
*/
private boolean checkFilter(NodeComparison nodeComparison) {
boolean isMatch = filterString == null || filterString.isEmpty() || nodeComparison.getTitle().toLowerCase().contains(filterString.toLowerCase());
if (isMatch) {
isMatch = modifiedDateFilter == null || nodeComparison.getSourceModificationDateCalendar() == null || modifiedDateFilter.before(nodeComparison.getSourceModificationDateCalendar());
}
NodeComparisonState state = nodeComparison.getState();
if (state != null && state.equals(NodeComparisonState.NOT_FOUND_ON_TARGET)) {
state = NodeComparisonState.MODIFIED_ON_SOURCE;
} else if (state != null && state.equals(NodeComparisonState.NOT_FOUND_ON_SOURCE)) {
state = NodeComparisonState.MODIFIED_ON_TARGET;
}
if (isMatch) {
isMatch = stateString == null || stateString.isEmpty() || state.getKey().equals(stateString);
}
if (isMatch) {
isMatch = !publishedContentOnly || nodeComparison.isPublished();
}
return isMatch;
}
/**
* Checks if is default entry.
*
* @param path the path
* @return true, if is default entry
*/
public boolean isDefaultEntry(String path) {
for (NodeComparison comparison : pushContentPopupComponent.getDefaultSelection()) {
if (path.equals(comparison.getPath())) {
return true;
}
}
return false;
}
}