/*
* Lokomo OneCMDB - An Open Source Software for Configuration
* Management of Datacenter Resources
*
* Copyright (C) 2006 Lokomo Systems AB
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* Lokomo Systems AB can be contacted via e-mail: info@lokomo.com or via
* paper mail: Lokomo Systems AB, Sv�rdv�gen 27, SE-182 33
* Danderyd, Sweden.
*
*/
package org.onecmdb.ui.gwt.desktop.client.widget;
import java.util.ArrayList;
import java.util.List;
import org.onecmdb.ui.gwt.desktop.client.WindowFactory;
import org.onecmdb.ui.gwt.desktop.client.mvc.CMDBEvents;
import org.onecmdb.ui.gwt.desktop.client.service.CMDBAsyncCallback;
import org.onecmdb.ui.gwt.desktop.client.service.content.ContentData;
import org.onecmdb.ui.gwt.desktop.client.service.model.AttributeModel;
import org.onecmdb.ui.gwt.desktop.client.service.model.CIModel;
import org.onecmdb.ui.gwt.desktop.client.service.model.CMDBPermissions;
import org.onecmdb.ui.gwt.desktop.client.service.model.CMDBSession;
import org.onecmdb.ui.gwt.desktop.client.service.model.ModelServiceFactory;
import org.onecmdb.ui.gwt.desktop.client.service.model.StoreResult;
import org.onecmdb.ui.gwt.desktop.client.service.model.grid.CIModelCollection;
import org.onecmdb.ui.gwt.desktop.client.utils.PermissionMenu;
import org.onecmdb.ui.gwt.desktop.client.widget.form.CIIdentityForm;
import org.onecmdb.ui.gwt.desktop.client.widget.grid.AttributeGrid;
import org.onecmdb.ui.gwt.desktop.client.widget.grid.CIPropertyPanel;
import org.onecmdb.ui.gwt.desktop.client.widget.grid.EditableCIInstanceGrid;
import org.onecmdb.ui.gwt.desktop.client.widget.grid.EditableSingleCIGrid;
import org.onecmdb.ui.gwt.desktop.client.widget.tree.CITemplateBrowser;
import org.onecmdb.ui.gwt.desktop.client.widget.tree.CITemplateReferenceTree;
import com.extjs.gxt.ui.client.Events;
import com.extjs.gxt.ui.client.Style.LayoutRegion;
import com.extjs.gxt.ui.client.Style.Scroll;
import com.extjs.gxt.ui.client.data.BaseModel;
import com.extjs.gxt.ui.client.event.BaseEvent;
import com.extjs.gxt.ui.client.event.ComponentEvent;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.MessageBoxEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.event.TreeEvent;
import com.extjs.gxt.ui.client.event.WindowEvent;
import com.extjs.gxt.ui.client.util.Margins;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.Dialog;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.extjs.gxt.ui.client.widget.TabItem;
import com.extjs.gxt.ui.client.widget.TabPanel;
import com.extjs.gxt.ui.client.widget.Window;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.button.IconButton;
import com.extjs.gxt.ui.client.widget.layout.BorderLayout;
import com.extjs.gxt.ui.client.widget.layout.BorderLayoutData;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.layout.RowData;
import com.extjs.gxt.ui.client.widget.layout.RowLayout;
import com.extjs.gxt.ui.client.widget.toolbar.AdapterToolItem;
import com.extjs.gxt.ui.client.widget.toolbar.FillToolItem;
import com.extjs.gxt.ui.client.widget.toolbar.SeparatorToolItem;
import com.extjs.gxt.ui.client.widget.toolbar.TextToolItem;
import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
import com.extjs.gxt.ui.client.widget.tree.TreeItem;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.rpc.AsyncCallback;
public class CIModelInternalBrowser extends LayoutContainer {
private ContentData mdr;
private ContentPanel center;
private AttributeGrid attributeGrid;
private EditableSingleCIGrid defaultValueGrid;
private CIModel modelLocal;
private CIModel modelBase;
private TreeItem currentTreeItem;
private CITemplateBrowser browser;
private List<String> roots;
private CMDBPermissions permission;
private TextToolItem removeTemplate;
private String rootType;
private String rootReferenceType;
public CIModelInternalBrowser(ContentData mdr, List<String> roots, String rootType, String rootReferenceType) {
this.mdr = mdr;
this.roots = roots;
this.rootType = rootType;
this.rootReferenceType = rootReferenceType;
}
@Override
protected void onRender(Element parent, int index) {
super.onRender(parent, index);
init();
}
public void init() {
setLayout(new BorderLayout());
browser = new CITemplateBrowser(mdr, roots);
//final CIInstanceBrowser center = new CIInstanceBrowser(mdr);
center = new ContentPanel();
center.setLayout(new FitLayout());
center.setLayoutOnChange(true);
//center.setScrollMode(Scroll.AUTO);
browser.setSelectionListsner(new Listener<TreeEvent>() {
public void handleEvent(TreeEvent te) {
TreeItem item = te.tree.getSelectedItem();
if (item != null) {
if (item.getModel() instanceof CIModel) {
currentTreeItem = item;
CIModel model = (CIModel)item.getModel();
updateModel(model);
}
//Info.display("Selection Changed", "The '{0}' item was selected", item.getText());
}
}
});
ContentPanel left = new ContentPanel();
//left.setScrollMode(Scroll.AUTO);
left.setHeading("Template Hierarchy");
left.setLayout(new FitLayout());
left.setLayoutOnChange(true);
PermissionMenu menu = new PermissionMenu(permission, PermissionMenu.READONLY_MASK|PermissionMenu.EDIT_MASK|PermissionMenu.DELETE_MASK);
menu.addListener(CMDBEvents.PERMISSION_CHANGED, new Listener<BaseEvent>() {
public void handleEvent(BaseEvent be) {
if (currentTreeItem != null) {
CIModel model = (CIModel)currentTreeItem.getModel();
updateModel(model);
}
}
});
ToolBar toolBar = new ToolBar();
toolBar.add(new FillToolItem());
toolBar.add(menu);
left.setTopComponent(toolBar);
left.add(browser);
BorderLayoutData centerData = new BorderLayoutData(LayoutRegion.CENTER);
centerData.setMargins(new Margins(5, 0, 5, 0));
BorderLayoutData westData = new BorderLayoutData(LayoutRegion.WEST, 200);
westData.setSplit(true);
westData.setCollapsible(true);
westData.setMargins(new Margins(5));
add(left, westData);
add(center, centerData);
layout();
}
protected void updateModel(CIModel model) {
this.modelBase = model.copy();
this.modelLocal = model;
center.removeAll();
center.setHeading("Template " + model.getAlias());
TabPanel panel = new TabPanel();
center.add(panel);
{
TabItem attr = new TabItem("Attributes");
attr.setLayout(new RowLayout());
attr.add(getToolBar(), new RowData(1,-1));
CIIdentityForm idForm = new CIIdentityForm(model);
idForm.setPermission(permission);
attr.add(idForm, new RowData(1, -1));
attributeGrid = new AttributeGrid(mdr, model, rootType, rootReferenceType);
attributeGrid.setPermission(permission);
attr.add(attributeGrid, new RowData(1, 1));
ContentPanel defaultPanel = new ContentPanel();
defaultPanel.setHeading("Default values for " + model.getAlias());
defaultPanel.setLayout(new FitLayout());
defaultValueGrid = new EditableSingleCIGrid(mdr, model);
defaultValueGrid.setPermissions(permission);
defaultPanel.setHeight(120);
defaultPanel.add(defaultValueGrid);
attr.add(defaultPanel, new RowData(1,-1));
panel.add(attr);
}
{
TabItem refs = new TabItem("References");
refs.setLayout(new FitLayout());
CITemplateReferenceTree tree = new CITemplateReferenceTree(mdr, modelBase);
tree.setPermission(permission);
refs.add(tree);
panel.add(refs);
}
center.layout();
layout();
}
private ToolBar getToolBar() {
ToolBar bar = new ToolBar();
if (isEditAllowed()) {
TextToolItem addAttribute = new TextToolItem("Add Attribute", "add-attribute-icon");
addAttribute.addSelectionListener(getAddAttributeSelection());
addAttribute.setToolTip("Add Attribute");
addAttribute.setEnabled(isEditAllowed());
bar.add(addAttribute);
bar.add(new SeparatorToolItem());
}
if (isDeleteAllowed()) {
TextToolItem deleteAttribute = new TextToolItem("Delete Attribute", "delete-icon");
deleteAttribute.addSelectionListener(getDeleteAttributeSelection());
deleteAttribute.setToolTip("Delete Selected Attributes");
deleteAttribute.setEnabled(isDeleteAllowed());
bar.add(deleteAttribute);
bar.add(new SeparatorToolItem());
}
if (isEditAllowed()) {
TextToolItem restore = new TextToolItem("Undo", "restore-icon");
restore.addSelectionListener(getUndoSelection());
restore.setToolTip("Undo");
restore.setEnabled(isEditAllowed());
bar.add(restore);
bar.add(new SeparatorToolItem());
TextToolItem save = new TextToolItem("Save", "save-icon");
save.addSelectionListener(getSaveSelection());
save.setToolTip("Save");
save.setEnabled(isEditAllowed());
bar.add(save);
bar.add(new SeparatorToolItem());
TextToolItem addTemplate = new TextToolItem("New Template", "add-icon");
addTemplate.addSelectionListener(getNewSelection());
addTemplate.setToolTip("Create new template derived from current template");
addTemplate.setEnabled(isEditAllowed());
bar.add(addTemplate);
bar.add(new SeparatorToolItem());
}
if (isDeleteAllowed()) {
removeTemplate = new TextToolItem("Delete Template", "delete-icon");
removeTemplate.addSelectionListener(getRemoveSelection());
removeTemplate.setToolTip("Delete current template");
removeTemplate.setEnabled(isDeleteAllowed());
bar.add(removeTemplate);
bar.add(new SeparatorToolItem());
}
TextToolItem propertiesTemplate = new TextToolItem("Properties", "property-icon");
propertiesTemplate.addSelectionListener(getPropertySelection());
propertiesTemplate.setToolTip("Show properties for this template");
bar.add(propertiesTemplate);
return(bar);
}
private SelectionListener getPropertySelection() {
SelectionListener<ComponentEvent> selection = new SelectionListener<ComponentEvent>() {
@Override
public void componentSelected(ComponentEvent ce) {
CIModelCollection dataCol = new CIModelCollection();
dataCol.addCIModel("offspring", modelLocal);
String rootCI = "Ci";
if (roots.contains("Root")) {
rootCI = "Root";
}
final CIPropertyPanel panel = new CIPropertyPanel(mdr, dataCol, rootCI);
panel.setPermissions(permission);
Window w = WindowFactory.getWindow("Properties for " + dataCol.getCIModels().get(0).getDisplayName(), panel);
w.addListener(Events.Close, new Listener<BaseEvent>() {
public void handleEvent(BaseEvent be) {
if (panel.isModelChanged()) {
reloadModel();
}
}
});
w.show();
w.layout();
w.toFront();
}
};
return(selection);
}
private SelectionListener getRemoveSelection() {
SelectionListener selection = new SelectionListener<ComponentEvent>() {
public void componentSelected(ComponentEvent ce) {
final MessageBox box = MessageBox.confirm("Delete template " + modelBase.getAlias(), "Are you sure ?", new Listener<WindowEvent>() {
public void handleEvent(WindowEvent be) {
Dialog dialog = (Dialog) be.component;
Button btn = dialog.getButtonPressed();
if (!btn.getItemId().equals(Dialog.YES)) {
return;
}
List<CIModel> base = new ArrayList<CIModel>();
List<CIModel> local = new ArrayList<CIModel>();
base.add(modelBase);
// Call create.
final MessageBox deleteInfo = MessageBox.wait("Progress",
"Delete, please wait...", "Deleting...");
ModelServiceFactory.get().store(mdr, CMDBSession.get().getToken(), local, base, new AsyncCallback<StoreResult>() {
public void onFailure(Throwable caught) {
deleteInfo.close();
ExceptionErrorDialog.showError("Can't Delete", caught);
//loader.load();
}
public void onSuccess(StoreResult result) {
deleteInfo.close();
if (result.isRejected()) {
MessageBox.alert("Delete Failed", result.getRejectCause(), null);
return;
}
center.removeAll();
center.setHeading("");
// TODO: Check errors on storeResult...
TreeItem parent = currentTreeItem.getParentItem();
if (parent == null) {
browser.reload();
return;
}
if (parent.getModel() instanceof CIModel) {
browser.reloadChildren((CIModel)parent.getModel());
}
}
});
}
});
}
};
return(selection);
}
private SelectionListener getNewSelection() {
SelectionListener selection = new SelectionListener<ComponentEvent>() {
public void componentSelected(ComponentEvent ce) {
//final CIModel model = (CIModel) item.getModel();
// InputDialog for new AliasName.
final MessageBox box = MessageBox.prompt("Name",
"<a style='font-size:smaller;'>" +
"<i>Note: Alias needs to be unique and no special<br/>" +
"characters including space is allowed.</i></a><br/><br/>" +
"Please enter template alias:");
box.addCallback(new Listener<MessageBoxEvent>() {
public void handleEvent(MessageBoxEvent be) {
//be.buttonClicked.
if (be.value == null || be.value.length() == 0) {
return;
}
final MessageBox createInfo = MessageBox.wait("Progress",
"Create, please wait...", "Creating...");
// Create new template.
final CIModel newTemplate = new CIModel();
newTemplate.setAlias(be.value);
newTemplate.setDerivedFrom(modelBase.getAlias());
newTemplate.setTemplate(true);
List<CIModel> base = new ArrayList<CIModel>();
List<CIModel> local = new ArrayList<CIModel>();
local.add(newTemplate);
// Call create.
ModelServiceFactory.get().store(mdr, CMDBSession.get().getToken(), local, base, new AsyncCallback<StoreResult>() {
public void onFailure(Throwable caught) {
createInfo.close();
ExceptionErrorDialog.showError("Can't Create", caught);
//loader.load();
}
public void onSuccess(StoreResult result) {
if (result.isRejected()) {
createInfo.close();
MessageBox.alert("Create Failed", result.getRejectCause(), null);
return;
}
// Load CiModel again....
List<String> aliases = new ArrayList<String>();
aliases.add(newTemplate.getAlias());
ModelServiceFactory.get().getCIModel(CMDBSession.get().getToken(), mdr, aliases, new CMDBAsyncCallback<List<CIModel>>() {
@Override
public void onFailure(Throwable t) {
createInfo.close();
super.onFailure(t);
}
@Override
public void onSuccess(final List<CIModel> arg0) {
createInfo.close();
if (arg0.size() == 1) {
DeferredCommand.addCommand(new Command() {
public void execute() {
CIModel parent = modelBase;
browser.reloadChildren(parent, arg0.get(0));
updateModel(arg0.get(0));
}
});
}
}
});
}
});
}
});
}
};
return(selection);
}
private boolean isEditAllowed() {
if (permission != null) {
return(permission.getCurrentState().equals(CMDBPermissions.PermissionState.EDIT));
}
return false;
}
private boolean isDeleteAllowed() {
if (permission != null) {
return(permission.getCurrentState().equals(CMDBPermissions.PermissionState.DELETE));
}
return false;
}
private SelectionListener getDeleteAttributeSelection() {
return(new SelectionListener<ComponentEvent>() {
@Override
public void componentSelected(ComponentEvent ce) {
List<AttributeModel> deleteAttributes = attributeGrid.getDeleteAttributes();
final MessageBox box = MessageBox.confirm("Delete " + deleteAttributes.size() + " Attributes", "Are you sure ?", new Listener<WindowEvent>() {
public void handleEvent(WindowEvent be) {
if (!be.buttonClicked.getItemId().equals(Dialog.YES)) {
return;
}
if (!attributeGrid.commitDelete()) {
return;
}
final MessageBox saveInfo = MessageBox.wait("Progress",
"Deleting your data, please wait...", "Deleting...");
List<CIModel> local = new ArrayList<CIModel>();
List<CIModel> base = new ArrayList<CIModel>();
local.add(modelLocal);
base.add(modelBase);
ModelServiceFactory.get().store(mdr, CMDBSession.get().getToken(), local, base, new AsyncCallback<StoreResult>() {
public void onFailure(Throwable caught) {
// Error.
saveInfo.close();
ExceptionErrorDialog.showError("Can't Delete", caught);
}
public void onSuccess(StoreResult result) {
saveInfo.close();
// saved
if (result.isRejected()) {
MessageBox.alert("Delete Failed", result.getRejectCause(), new Listener<WindowEvent>() {
public void handleEvent(WindowEvent be) {
reloadModel();
}
});
return;
} else {
reloadModel();
}
}
});
}
});
}
});
}
private SelectionListener getSaveSelection() {
return(new SelectionListener<ComponentEvent>() {
@Override
public void componentSelected(ComponentEvent ce) {
if (!attributeGrid.commitSave()) {
return;
}
if (!defaultValueGrid.commit()) {
return;
}
final MessageBox saveInfo = MessageBox.wait("Progress",
"Saving your data, please wait...", "Saving...");
List<CIModel> local = new ArrayList<CIModel>();
List<CIModel> base = new ArrayList<CIModel>();
local.add(modelLocal);
base.add(modelBase);
ModelServiceFactory.get().store(mdr, CMDBSession.get().getToken(), local, base, new AsyncCallback<StoreResult>() {
public void onFailure(Throwable caught) {
// Error.
saveInfo.close();
ExceptionErrorDialog.showError("Can't Save", caught);
}
public void onSuccess(StoreResult result) {
saveInfo.close();
// saved
if (result.isRejected()) {
MessageBox.alert("Save Failed", result.getRejectCause(), new Listener<WindowEvent>() {
public void handleEvent(WindowEvent be) {
reloadModel();
}
});
return;
} else {
reloadModel();
}
}
});
}
});
}
private void reloadModel() {
//browser.reload();
List<String> aliases = new ArrayList<String>();
aliases.add(modelBase.getAlias());
ModelServiceFactory.get().getCIModel(CMDBSession.get().getToken(), mdr, aliases, new AsyncCallback<List<CIModel>>() {
public void onFailure(Throwable caught) {
ExceptionErrorDialog.showError("ReLoad CI Failed", caught);
return;
}
public void onSuccess(List<CIModel> result) {
/**
if (currentTreeItem != null) {
currentTreeItem.getModel()
}
*/
if (result.size() == 1) {
updateModel(result.get(0));
browser.updateStore(result.get(0));
}
}
});
}
private SelectionListener getUndoSelection() {
return(new SelectionListener<ComponentEvent>() {
@Override
public void componentSelected(ComponentEvent ce) {
attributeGrid.restore();
defaultValueGrid.restore();
}
});
}
private SelectionListener getAddAttributeSelection() {
return(new SelectionListener<ComponentEvent>() {
@Override
public void componentSelected(ComponentEvent ce) {
attributeGrid.addAttribute();
}
});
}
public void setPermission(CMDBPermissions permissions) {
this.permission = permissions;
}
}