/**
*
* geo-platform
* Rich webgis framework
* http://geo-platform.org
* ====================================================================
*
* Copyright (C) 2008-2017 geoSDI Group (CNR IMAA - Potenza - ITALY).
*
* This program 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. 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 General Public License
* for more details. You should have received a copy of the GNU General
* Public License along with this program. If not, see http://www.gnu.org/licenses/
*
* ====================================================================
*
* Linking this library statically or dynamically with other modules is
* making a combined work based on this library. Thus, the terms and
* conditions of the GNU General Public License cover the whole combination.
*
* As a special exception, the copyright holders of this library give you permission
* to link this library with independent modules to produce an executable, regardless
* of the license terms of these independent modules, and to copy and distribute
* the resulting executable under terms of your choice, provided that you also meet,
* for each linked independent module, the terms and conditions of the license of
* that module. An independent module is a module which is not derived from or
* based on this library. If you modify this library, you may extend this exception
* to your version of the library, but you are not obligated to do so. If you do not
* wish to do so, delete this exception statement from your version.
*/
package org.geosdi.geoplatform.gui.client.widget.form;
import com.extjs.gxt.ui.client.Style.HorizontalAlignment;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.ComponentEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.store.Record;
import com.extjs.gxt.ui.client.store.Store;
import com.extjs.gxt.ui.client.widget.Window;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.form.CheckBox;
import com.extjs.gxt.ui.client.widget.form.StoreFilterField;
import com.extjs.gxt.ui.client.widget.grid.CellEditor;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.EditorGrid.ClicksToEdit;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.grid.RowEditor;
import com.extjs.gxt.ui.client.widget.layout.FormLayout;
import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
import com.google.common.collect.Lists;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.HasRpcToken;
import com.google.gwt.user.client.rpc.RpcTokenException;
import com.google.gwt.user.client.rpc.XsrfToken;
import com.google.gwt.user.client.rpc.XsrfTokenServiceAsync;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.user.client.ui.Widget;
import java.util.List;
import org.geosdi.geoplatform.gui.client.ServerWidgetResources;
import org.geosdi.geoplatform.gui.client.i18n.ServerModuleConstants;
import org.geosdi.geoplatform.gui.client.i18n.ServerModuleMessages;
import org.geosdi.geoplatform.gui.client.i18n.buttons.ButtonsConstants;
import org.geosdi.geoplatform.gui.client.i18n.windows.WindowsConstants;
import org.geosdi.geoplatform.gui.client.widget.DisplayServerWidget;
import org.geosdi.geoplatform.gui.configuration.GPSecureStringTextField;
import org.geosdi.geoplatform.gui.client.widget.SearchStatus.EnumSearchStatus;
import org.geosdi.geoplatform.gui.configuration.message.GeoPlatformMessage;
import org.geosdi.geoplatform.gui.global.security.GPAccountLogged;
import org.geosdi.geoplatform.gui.impl.view.LayoutManager;
import org.geosdi.geoplatform.gui.model.server.GPServerBeanModel;
import org.geosdi.geoplatform.gui.puregwt.oauth2.IGPOAuth2AddServerHandler;
import org.geosdi.geoplatform.gui.puregwt.oauth2.OAuth2HandlerManager;
import org.geosdi.geoplatform.gui.puregwt.oauth2.event.GPOAuth2GEBLoginEvent;
import org.geosdi.geoplatform.gui.service.gwt.xsrf.GPXsrfTokenService;
import org.geosdi.geoplatform.gui.service.server.GeoPlatformOGCRemote;
import org.geosdi.geoplatform.gui.service.server.GeoPlatformOGCRemoteAsync;
import org.geosdi.geoplatform.gui.utility.oauth2.EnumOAuth2;
/**
* @author Nazzareno Sileno - CNR IMAA geoSDI Group
* @email nazzareno.sileno@geosdi.org
*/
public class ManageServerWidget extends Window {
private static final XsrfTokenServiceAsync xsrf = GPXsrfTokenService.Util.getInstance();
private static final GeoPlatformOGCRemoteAsync geoPlatformOGCRemote = GeoPlatformOGCRemote.Util.getInstance();
//
private boolean initialized;
private final PerformOperation operation = new PerformOperation();
private ListStore<GPServerBeanModel> store = new ListStore<GPServerBeanModel>();
private final Button deleteServerButton = new Button(
ServerModuleConstants.INSTANCE.ManageServerWidget_deleteButtonText());
private final DisplayServerWidget displayServerWidget;
private GPCheckColumnConfig checkColumn;
private StoreFilterField<GPServerBeanModel> serverFilter;
public ManageServerWidget(DisplayServerWidget displayServerWidget,
boolean lazy) {
this.displayServerWidget = displayServerWidget;
this.store = displayServerWidget.getStore();
if (!lazy) {
init();
}
}
private Widget createServerFilter() {
this.serverFilter = new StoreFilterField<GPServerBeanModel>() {
@Override
protected boolean doSelect(Store<GPServerBeanModel> store,
GPServerBeanModel parent,
GPServerBeanModel record, String property, String filter) {
String serverAlias = record.getAlias().toString().toLowerCase();
String serverURL = record.getUrlServer().toString().toLowerCase();
if (serverAlias.contains(filter.toLowerCase()) || serverURL.contains(
filter.toLowerCase())) {
return Boolean.TRUE;
}
return Boolean.FALSE;
}
};
serverFilter.setEmptyText(ServerModuleConstants.INSTANCE.
ManageServerWidget_typeServerToSearchText());
serverFilter.bind(this.store);
serverFilter.setFieldLabel(ServerModuleConstants.INSTANCE.
ManageServerWidget_serverFilterText());
return this.serverFilter;
}
private void addComponentToForm() {
super.setIcon(AbstractImagePrototype.create(
ServerWidgetResources.ICONS.addServer()));
super.setLayout(new FormLayout());
List<ColumnConfig> configs = Lists.<ColumnConfig>newArrayList();
ColumnConfig aliasColumn = new ColumnConfig();
aliasColumn.setId("alias");
aliasColumn.setHeaderHtml(ServerModuleConstants.INSTANCE.
serverAliasText());
aliasColumn.setWidth(220);
GPSecureStringTextField aliasTextfield = new GPSecureStringTextField();
aliasTextfield.setAllowBlank(false);
aliasColumn.setEditor(new CellEditor(aliasTextfield));
configs.add(aliasColumn);
ColumnConfig urlColumn = new ColumnConfig();
urlColumn.setId("urlServer");
urlColumn.setHeaderHtml(ServerModuleConstants.INSTANCE.
serverURLText());
urlColumn.setWidth(400);
GPSecureStringTextField urlTextfield = new GPSecureStringTextField();
urlTextfield.setAllowBlank(false);
// urlTextfield.setEmptyText("http://");
urlColumn.setEditor(new CellEditor(urlTextfield));
configs.add(urlColumn);
checkColumn = new GPCheckColumnConfig("delete",
ButtonsConstants.INSTANCE.deleteText(), 55, store,
this.deleteServerButton);
CellEditor checkBoxEditor = new CellEditor(new CheckBox());
checkColumn.setEditor(checkBoxEditor);
//This is very important: add checkColumn to the zero position!
configs.add(0, checkColumn);
final ColumnModel columnModel = new ColumnModel(configs);
final Grid<GPServerBeanModel> grid = new Grid<GPServerBeanModel>(store,
columnModel);
RowEditor<GPServerBeanModel> rowEditor = new RowEditor<GPServerBeanModel>() {
@Override
protected void onEnter(ComponentEvent ce) {
System.out.println("Selected null: ");
System.out.println(grid.getSelectionModel().getSelectedItem());
Record record = store.getRecord(
grid.getSelectionModel().getSelectedItem());
record.reject(true);
super.onEnter(ce);
}
@Override
protected void onHide() {
super.onHide();
//System.out.println("Hiding row editor and verifing the check status");
checkColumn.manageDeleteButton();
}
};
rowEditor.setClicksToEdit(ClicksToEdit.TWO);
grid.setAutoExpandColumn("urlServer");
grid.setBorders(true);
grid.addPlugin(checkColumn);
grid.addPlugin(rowEditor);
grid.getAriaSupport().setLabelledBy(super.getHeader().getId() + "-label");
grid.setHeight(200);
super.add(grid);
super.add(this.createServerFilter());
this.addButtonsToTheWindow(rowEditor);
}
private void addButtonsToTheWindow(
final RowEditor<GPServerBeanModel> rowEditor) {
ToolBar toolBar = new ToolBar();
Button addServerButton = new Button(ServerModuleConstants.INSTANCE.
addServerText());
addServerButton.addSelectionListener(
new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(ButtonEvent ce) {
GPServerBeanModel server = new GPServerBeanModel();
// server.setUrlServer("http://");
rowEditor.stopEditing(false);
store.insert(server, 0);
Record record = store.getRecord(server);
record.set("alias", ServerModuleConstants.INSTANCE.
ManageServerWidget_newServerText());
record.set("urlServer", "");
store.update(server);
rowEditor.startEditing(store.indexOf(server), true);
}
});
toolBar.add(addServerButton);
deleteServerButton.setEnabled(false);
deleteServerButton.addSelectionListener(
new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(ButtonEvent ce) {
rowEditor.stopEditing(true);
List<GPServerBeanModel> serverList = store.getModels();
int i = 0;
for (GPServerBeanModel gPServerBeanModel : serverList) {
String check = checkColumn.getCheckState(
gPServerBeanModel,
"delete", i, 0);
if (check.equals("-on")) {
operation.deleteServer(gPServerBeanModel);
}
i++;
}
checkColumn.manageDeleteButton();
}
});
toolBar.add(deleteServerButton);
super.setTopComponent(toolBar);
super.setButtonAlign(HorizontalAlignment.RIGHT);
super.addButton(new Button(ButtonsConstants.INSTANCE.resetText(),
new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(ButtonEvent ce) {
rowEditor.stopEditing(true);
store.rejectChanges();
serverFilter.clear();
checkColumn.manageDeleteButton();
}
}));
super.addButton(new Button(ButtonsConstants.INSTANCE.saveText(),
new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(ButtonEvent ce) {
rowEditor.stopEditing(true);
List<Record> modifiedElements = store.getModifiedRecords();
if (!modifiedElements.isEmpty()) {
operation.setModifiedElementsNumber(
modifiedElements.size());
for (Record record : modifiedElements) {
operation.callSaveRecord(record);
}
}
}
}));
}
@Override
public void hide(Button buttonPressed) {
if (store.getModifiedRecords().isEmpty()) {
super.hide(buttonPressed);
this.displayServerWidget.loadServers();
} else {
GeoPlatformMessage.alertMessage(
WindowsConstants.INSTANCE.warningTitleText(),
WindowsConstants.INSTANCE.unsavedChangesToSaveOrResetText());
}
}
public void initSize() {
super.setModal(true);
super.setHeadingHtml(
ServerModuleConstants.INSTANCE.ManageServerWidget_headingText());
super.setBorders(false);
super.setSize(600, 325);
}
@Override
public void show() {
if (!initialized) {
this.init();
}
super.show();
// this.loadServers();
}
private void init() {
this.initSize();
this.addComponentToForm();
this.initialized = true;
}
/**
* Internal Class for Business Logic
*
*/
private class PerformOperation implements IGPOAuth2AddServerHandler {
private int modifiedElementsNumber;
private Record record;
public PerformOperation() {
OAuth2HandlerManager.addHandler(IGPOAuth2AddServerHandler.TYPE, this);
}
private void callSaveRecord(Record theRecord) {
record = theRecord;
updateInsertServer();
}
private void deleteServer(final GPServerBeanModel server) {
if (server.getId() != null) {
xsrf.getNewXsrfToken(new AsyncCallback<XsrfToken>() {
@Override
public void onFailure(Throwable caught) {
try {
throw caught;
} catch (RpcTokenException e) {
// Can be thrown for several reasons:
// - duplicate session cookie, which may be a sign of a cookie
// overwrite attack
// - XSRF token cannot be generated because session cookie isn't
// present
} catch (Throwable e) {
// unexpected
}
}
@Override
public void onSuccess(XsrfToken token) {
((HasRpcToken) geoPlatformOGCRemote).setRpcToken(token);
geoPlatformOGCRemote.deleteServer(server.getId(),
new AsyncCallback<Boolean>() {
@Override
public void onFailure(Throwable caught) {
GeoPlatformMessage.errorMessage(
ServerModuleConstants.INSTANCE.ManageServerWidget_errorDeletingTitleText(),
ServerModuleMessages.INSTANCE.ManageServerWidget_errorDeletingBodyMessage(
caught.getMessage(),
server.get(
"urlServer").toString()));
LayoutManager.getInstance().getStatusMap().setStatus(
ServerModuleMessages.INSTANCE.
ManageServerWidget_deleteServerErrorMessage(
caught.getMessage()),
EnumSearchStatus.STATUS_SEARCH_ERROR.toString());
}
@Override
public void onSuccess(Boolean result) {
store.remove(server);
checkColumn.manageDeleteButton();
LayoutManager.getInstance().getStatusMap().setStatus(
ServerModuleConstants.INSTANCE.
ManageServerWidget_statusServerDeletedSuccesfullyText(),
EnumSearchStatus.STATUS_SEARCH.toString());
//TODO: refresh the displayServerWidget
//displayServerWidget.addServer(server);
}
});
}
});
} else {
store.remove(server);
}
}
@Override
public void updateInsertServer() {
final GPServerBeanModel server = (GPServerBeanModel) record.getModel();
xsrf.getNewXsrfToken(new AsyncCallback<XsrfToken>() {
@Override
public void onFailure(Throwable caught) {
try {
throw caught;
} catch (RpcTokenException e) {
// Can be thrown for several reasons:
// - duplicate session cookie, which may be a sign of a cookie
// overwrite attack
// - XSRF token cannot be generated because session cookie isn't
// present
} catch (Throwable e) {
// unexpected
}
}
@Override
public void onSuccess(XsrfToken token) {
((HasRpcToken) geoPlatformOGCRemote).setRpcToken(token);
geoPlatformOGCRemote.saveServer(server.getId(),
record.get("alias").toString(),
record.get("urlServer").toString().trim(),
GPAccountLogged.getInstance().getOrganization(),
new AsyncCallback<GPServerBeanModel>() {
@Override
public void onFailure(Throwable caught) {
verifyEndOperation();
if (server.getUrlServer().contains(
EnumOAuth2.GEB_STRING.getValue())) {
GeoPlatformMessage.infoMessage(
ServerModuleConstants.INSTANCE.
googleSignOnRequiredTitleText(),
ServerModuleConstants.INSTANCE.
googleSignOnRequiredBodyText());
OAuth2HandlerManager.fireEvent(
new GPOAuth2GEBLoginEvent(
EnumOAuth2.ADD_SERVER.getValue()));
} else {
GeoPlatformMessage.errorMessage(
ServerModuleConstants.INSTANCE.
ManageServerWidget_errorSavingTitleText(),
caught.getMessage());
LayoutManager.getInstance().getStatusMap().setStatus(
ServerModuleMessages.INSTANCE.
AddServerWidget_saveServerErrorMessage(
caught.getMessage()),
EnumSearchStatus.STATUS_SEARCH_ERROR.toString());
}
}
@Override
public void onSuccess(
GPServerBeanModel serverSaved) {
verifyEndOperation();
store.remove(server);
store.insert(serverSaved, 0);
LayoutManager.getInstance().getStatusMap().setStatus(
ServerModuleConstants.INSTANCE.
ManageServerWidget_serverAddedSuccesfullyText(),
EnumSearchStatus.STATUS_SEARCH.toString());
}
});
}
});
}
private void verifyEndOperation() {
modifiedElementsNumber--;
if (modifiedElementsNumber <= 0) {
unmask();
}
}
public int getModifiedElementsNumber() {
return modifiedElementsNumber;
}
public void setModifiedElementsNumber(int modifiedElementsNumber) {
this.modifiedElementsNumber = modifiedElementsNumber;
}
}
}