/* * 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.tree; import java.util.ArrayList; import java.util.List; import org.onecmdb.ui.gwt.desktop.client.fixes.MyTreeTableBinder; 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.LoadConfigModelItem; import org.onecmdb.ui.gwt.desktop.client.service.model.ModelItem; 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.ValueListModel; import org.onecmdb.ui.gwt.desktop.client.service.model.ValueModel; import org.onecmdb.ui.gwt.desktop.client.service.model.grid.CIModelCollection; import org.onecmdb.ui.gwt.desktop.client.service.model.group.GroupDescription; import org.onecmdb.ui.gwt.desktop.client.service.model.tree.RelationCollectionModel; import org.onecmdb.ui.gwt.desktop.client.service.model.tree.RelationTypeModel; import org.onecmdb.ui.gwt.desktop.client.utils.LoaderProxy; import org.onecmdb.ui.gwt.desktop.client.utils.StoreAction; import org.onecmdb.ui.gwt.desktop.client.widget.ExceptionErrorDialog; import org.onecmdb.ui.gwt.desktop.client.widget.multi.MultiSelectCI; import com.extjs.gxt.ui.client.Events; import com.extjs.gxt.ui.client.Style.SelectionMode; import com.extjs.gxt.ui.client.data.BaseModelStringProvider; import com.extjs.gxt.ui.client.data.BaseTreeLoader; import com.extjs.gxt.ui.client.data.ModelData; import com.extjs.gxt.ui.client.data.ModelStringProvider; import com.extjs.gxt.ui.client.data.RpcProxy; import com.extjs.gxt.ui.client.event.BaseEvent; import com.extjs.gxt.ui.client.event.ComponentEvent; import com.extjs.gxt.ui.client.event.FieldEvent; import com.extjs.gxt.ui.client.event.KeyListener; import com.extjs.gxt.ui.client.event.Listener; import com.extjs.gxt.ui.client.event.MenuEvent; import com.extjs.gxt.ui.client.event.SelectionListener; import com.extjs.gxt.ui.client.event.ToolBarEvent; import com.extjs.gxt.ui.client.event.WindowEvent; import com.extjs.gxt.ui.client.store.Store; import com.extjs.gxt.ui.client.store.StoreSorter; import com.extjs.gxt.ui.client.store.TreeStore; import com.extjs.gxt.ui.client.widget.ContentPanel; import com.extjs.gxt.ui.client.widget.LayoutContainer; import com.extjs.gxt.ui.client.widget.MessageBox; import com.extjs.gxt.ui.client.widget.PagingToolBar; import com.extjs.gxt.ui.client.widget.Window; import com.extjs.gxt.ui.client.widget.Window.CloseAction; 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.form.CheckBox; import com.extjs.gxt.ui.client.widget.form.LabelField; import com.extjs.gxt.ui.client.widget.form.TextField; import com.extjs.gxt.ui.client.widget.layout.FillLayout; import com.extjs.gxt.ui.client.widget.layout.FitLayout; import com.extjs.gxt.ui.client.widget.menu.CheckMenuItem; import com.extjs.gxt.ui.client.widget.menu.Menu; import com.extjs.gxt.ui.client.widget.menu.MenuItem; import com.extjs.gxt.ui.client.widget.menu.SeparatorMenuItem; 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.extjs.gxt.ui.client.widget.treetable.TreeTable; import com.extjs.gxt.ui.client.widget.treetable.TreeTableColumn; import com.extjs.gxt.ui.client.widget.treetable.TreeTableColumnModel; 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; import com.google.gwt.user.client.ui.KeyboardListener; public class CIInstanceReferenceTree extends LayoutContainer { public static final int CI_SELECTED_EVENT = 50000; public static final int CI_TOOLBAR_AVAIL = 50001; private ContentData mdr; private CIModel root; public static final int DETAIL_REFRENCE_DISPLAY = 0x1; public static final int COMPACT_REFRENCE_DISPLAY = 0x2; public static int INBOUND_MODE = 0x1; public static int OUTBOUND_MODE = 0x2; public static int INBOUND_OUTBOUND_MODE = 0x3; private int displayMode = COMPACT_REFRENCE_DISPLAY; private int relTypeMode = INBOUND_OUTBOUND_MODE; private BaseTreeLoader loader; /* private boolean readonly; private boolean deletable; */ private TextField<String> searchField; private LoaderProxy lP; private CMDBPermissions permissions; class RelationSpanningTree { public void addChildren(CIModel instance, List<? extends ModelItem> result) { for (ModelItem item : result) { List<String> parentList = instance.get("path", new ArrayList<String>()); if (item instanceof CIModel) { CIModel child = (CIModel)item; List<String >childList = new ArrayList<String>(parentList); childList.add(child.getAlias()); item.set("path", childList); } } } public boolean isAlreadyInPath(CIModel model) { List<String> path = model.get("path", new ArrayList<String>()); int count = 0; for (String item : path) { if (item.equals(model.getAlias())) { count++; } } return(count > 1); } public void setRoots(List<? extends ModelData> result) { for (ModelData data : result) { if (data instanceof CIModel) { ArrayList<String> list = new ArrayList<String>(); list.add(((CIModel)data).getAlias()); data.set("path", list); } } } } private RelationSpanningTree spanningTree = new RelationSpanningTree(); private TextField<String> pageSizeField; private Listener<MenuEvent> refDisplListener; private Listener<MenuEvent> refTypeListener; private PagingToolBar pageingToolBar; private ToolBar toolBar; private LoadConfigModelItem cfg; private MyTreeTableBinder binder; private GroupDescription groupDescription; private TreeStore store; public CIInstanceReferenceTree(ContentData mdr, CIModel model) { this.mdr = mdr; setRoot(model); } private void setRoot(CIModel model) { this.root = model; } public void setGroupDescription(GroupDescription desc) { this.groupDescription = desc; } /* public boolean isReadonly() { return readonly; } public void setReadonly(boolean readonly) { this.readonly = readonly; } public boolean isDeletable() { return deletable; } public void setDeletable(boolean deletable) { this.deletable = deletable; } */ @Override protected void onRender(Element parent, int index) { super.onRender(parent, index); init(); } public void init() { setLayout(new FitLayout()); List<TreeTableColumn> columns = new ArrayList<TreeTableColumn>(); TreeTableColumn column = new TreeTableColumn("name", "Display Name", 0.99f); columns.add(column); TreeTableColumnModel cm = new TreeTableColumnModel(columns); final TreeTable table = new TreeTable(cm); table.setAnimate(false); table.addListener(Events.SelectionChange, new Listener<BaseEvent>() { public void handleEvent(BaseEvent be) { TreeItem item = table.getSelectedItem(); if (item == null) { return; } if (item.getModel() instanceof CIModel) { fireEvent(item.getModel()); } } }); final Menu menu = new Menu(); table.setContextMenu(menu); table.addListener(Events.ContextMenu, new Listener<BaseEvent>() { public void handleEvent(BaseEvent be) { TreeItem item = table.getSelectedItem(); updateMenu(item, menu); } }); //table.setItemIconStyle("icon-page"); RpcProxy<? extends ModelData, List<? extends ModelData>> proxy = new RpcProxy<ModelData, List<? extends ModelData>>() { @Override protected void load(final ModelData loadConfig, final AsyncCallback<List<? extends ModelData>> callback) { if (loadConfig instanceof LoadConfigModelItem) { ((LoadConfigModelItem)loadConfig).setQuery(searchField.getValue()); ((LoadConfigModelItem)loadConfig).getChildren(mdr, new CMDBAsyncCallback<List<? extends ModelData>>() { public void onFailure(Throwable caught) { super.onFailure(caught); callback.onFailure(caught); } public void onSuccess(List<? extends ModelData> result) { spanningTree.setRoots(result); callback.onSuccess(result); } }); } if (loadConfig instanceof CIModel) { ModelServiceFactory.get().loadRelationTypes(CMDBSession.get().getToken(), mdr, (CIModel)loadConfig, groupDescription, new CMDBAsyncCallback<RelationCollectionModel>() { public void onFailure(Throwable arg0) { super.onFailure(arg0); callback.onFailure(arg0); } public void onSuccess(RelationCollectionModel arg0) { List<RelationTypeModel> types = new ArrayList<RelationTypeModel>(); for (RelationTypeModel type : arg0.getRelationTypes()) { // Add all if ((relTypeMode & INBOUND_OUTBOUND_MODE) == INBOUND_OUTBOUND_MODE) { types.add(type); continue; } if (type.isOutbound() && ((relTypeMode & OUTBOUND_MODE) == OUTBOUND_MODE)) { types.add(type); continue; } if (!type.isOutbound() && ((relTypeMode & INBOUND_MODE) == INBOUND_MODE)) { types.add(type); continue; } } callback.onSuccess(types); } }); } if (loadConfig instanceof RelationTypeModel) { ModelServiceFactory.get().loadRelations(CMDBSession.get().getToken(), mdr, (RelationTypeModel)loadConfig, new CMDBAsyncCallback<List<? extends ModelItem>>() { public void onFailure(Throwable arg0) { super.onFailure(arg0); callback.onFailure(arg0); } public void onSuccess(List<? extends ModelItem> result) { spanningTree.addChildren(((RelationTypeModel)loadConfig).getInstance(), result); callback.onSuccess(result); } }); } } }; loader = new BaseTreeLoader(proxy) { @Override public boolean hasChildren(ModelData parent) { if (parent instanceof ModelItem) { //return(((ModelItem)parent).hasChildren()); } if (parent instanceof CIModel) { if (spanningTree.isAlreadyInPath(((CIModel)parent))) { return(false); } } return(true); } @Override public boolean loadChildren(ModelData parent) { // Need to convert the parent (CIModel) to a // Tree Load config. // TODO Auto-generated method stub return super.loadChildren(parent); } }; // trees store store = new TreeStore(loader); store.setMonitorChanges(true); store.setStoreSorter(new StoreSorter<ModelData>() { @Override public int compare(Store store, ModelData m1, ModelData m2, String property) { return super.compare(store, m1, m2, property); } }); binder = new MyTreeTableBinder(table, store); binder.setDisplayProperty(null); binder.setCaching(false); binder.setStringProvider(new BaseModelStringProvider<ModelData>() { @Override public String getStringValue(ModelData model, String property) { if (model instanceof CIModel) { if (spanningTree.isAlreadyInPath(((CIModel)model))) { return("<i>" + model.get(CIModel.CI_DISPLAYNAME) + "</i>"); } return(model.get(CIModel.CI_DISPLAYNAME)); } if (model instanceof RelationTypeModel) { RelationTypeModel rel = (RelationTypeModel)model; switch (displayMode) { case DETAIL_REFRENCE_DISPLAY: CIModel type = null; if (rel.isOutbound()) { type = rel.getTargetType(); return(rel.getAttributeAlias() + " " + model.get(CIModel.CI_DISPLAYNAME) + " " + type.getNameAndIcon()); } else { type = rel.getSourceType(); return(model.get(CIModel.CI_DISPLAYNAME) + " " + type.getNameAndIcon() + " " + rel.getAttributeAlias()); } case COMPACT_REFRENCE_DISPLAY: if (rel.isOutbound()) { type = rel.getTargetType(); return(type.getNameAndIcon()); } else { type = rel.getSourceType(); return(type.getNameAndIcon()); } } //return(rel.getAttributeAlias() + " " + model.get(CIModel.CI_DISPLAYNAME) + " " + type.getNameAndIcon()); } return(model.toString()); //return super.getStringValue(model, property); } }); binder.setIconProvider(new ModelStringProvider<ModelData>() { public String getStringValue(ModelData model, String property) { String icon = model.get(CIModel.CI_ICON_PATH); if (icon != null) { return(CMDBSession.get().getContentRepositoryURL() + "/" + icon); } return(null); } }); //editPanel.add(editForm); pageingToolBar = new PagingToolBar(50); lP = new LoaderProxy(null); lP.setBaseTreeLoader(loader); pageingToolBar.bind(lP); cfg = new LoadConfigModelItem(root); //cfg.setGroupDescription(this.groupDescription); cfg.setLimit(lP.getLimit()); lP.useLoadConfig(cfg); toolBar = new ToolBar(); searchField = new TextField<String>(); searchField.setToolTip("Search"); searchField.setWidth(60); searchField.addKeyListener(new KeyListener() { @Override public void componentKeyUp(ComponentEvent event) { if (event.getKeyCode() == KeyboardListener.KEY_ENTER) { reload(); } } }); toolBar.add(new AdapterToolItem(searchField)); IconButton searchButton = new IconButton("search-icon");; searchButton.addSelectionListener(new SelectionListener<ComponentEvent>() { @Override public void componentSelected(ComponentEvent ce) { reload(); } }); toolBar.add(new AdapterToolItem(searchButton)); TextToolItem optionItem = new TextToolItem("Options"); Menu rootMenu = new Menu(); optionItem.setMenu(rootMenu); { Menu refMenu = new Menu(); MenuItem referenceItem = new MenuItem("Reference Direction"); CheckMenuItem outboundItem = new CheckMenuItem("Outbound References"); outboundItem.setGroup("refDirection"); outboundItem.addListener(Events.CheckChange, getRefDirectionListener()); outboundItem.setData("value", OUTBOUND_MODE); refMenu.add(outboundItem); CheckMenuItem inboundItem = new CheckMenuItem("Inbound References"); inboundItem.setGroup("refDirection"); inboundItem.setData("value", INBOUND_MODE); inboundItem.addListener(Events.CheckChange, getRefDirectionListener()); refMenu.add(inboundItem); CheckMenuItem outinboundItem = new CheckMenuItem("In/Outbound References"); outinboundItem.setGroup("refDirection"); outinboundItem.setChecked(true); outinboundItem.setData("value", INBOUND_OUTBOUND_MODE); outinboundItem.addListener(Events.CheckChange, getRefDirectionListener()); refMenu.add(outinboundItem); referenceItem.setSubMenu(refMenu); rootMenu.add(referenceItem); } { Menu displayMenu = new Menu(); MenuItem displayOp = new MenuItem("Reference Display"); { CheckMenuItem item = new CheckMenuItem("Advanced"); item.setGroup("refDispl"); item.setData("value", DETAIL_REFRENCE_DISPLAY); item.addListener(Events.CheckChange, getRefDisplListener()); displayMenu.add(item); } { CheckMenuItem item = new CheckMenuItem("Simple"); item.setGroup("refDispl"); item.setChecked(true); item.setData("value", COMPACT_REFRENCE_DISPLAY); item.addListener(Events.CheckChange, getRefDisplListener()); displayMenu.add(item); } displayOp.setSubMenu(displayMenu); rootMenu.add(displayOp); } toolBar.add(optionItem); toolBar.add(new SeparatorToolItem()); pageSizeField = new TextField<String>(); pageSizeField.setWidth(30); pageSizeField.setValue("50"); pageSizeField.addKeyListener(new KeyListener() { @Override public void componentKeyUp(ComponentEvent event) { if (event.getKeyCode() == KeyboardListener.KEY_ENTER) { reload(); } } }); toolBar.add(new AdapterToolItem(pageSizeField)); toolBar.add(new AdapterToolItem(new LabelField("Page Size"))); final CheckBox check = new CheckBox(); check.setBoxLabel("All children"); check.setToolTip("If checked, ALL instances that is derived<br/> " + "from the selected template is shown.<br/>" + "Else instances directly derived from <br/>" + "the selected template is shown" ); check.setValue(Boolean.TRUE); cfg.setAllChildren(check.getValue()); AdapterToolItem allInstances = new AdapterToolItem(check); toolBar.add(allInstances); check.addListener(Events.Change, new Listener<FieldEvent>() { public void handleEvent(FieldEvent be) { cfg.setAllChildren(check.getValue()); //pageToolBar.getLoadConfig().setAllChildren(check.getValue()); } }); toolBar.add(new SeparatorToolItem()); if (!permissions.getCurrentState().equals(CMDBPermissions.PermissionState.READONLY)) { TextToolItem add = new TextToolItem("Add", "add-icon"); add.addSelectionListener(new SelectionListener<ToolBarEvent>() { @Override public void componentSelected(ToolBarEvent ce) { doNew(); } }); toolBar.add(add); } ContentPanel cp = new ContentPanel(); //cp.setHeading(root.getNameAndIcon()); cp.setHeaderVisible(false); cp.setFrame(true); //cp.setSize("100%", "100%"); cp.setLayout(new FitLayout()); cp.add(table); cp.setTopComponent(toolBar); cp.setBottomComponent(pageingToolBar); add(cp); layout(); reload(); } private Listener<MenuEvent> getRefDisplListener() { if (refDisplListener == null) { refDisplListener = new Listener<MenuEvent>() { public void handleEvent(MenuEvent be) { CheckMenuItem item = (CheckMenuItem) be.item; if (item.isChecked()) { setDisplayMode((Integer) item.getData("value")); } } }; } return(refDisplListener); } private void reload() { // Need to update the page size. int pageSize = 50; try { pageSize = Integer.parseInt(pageSizeField.getValue()); } catch (Throwable t) { // Ignore } pageingToolBar.setPageSize(pageSize); cfg.setLimit(lP.getLimit()); lP.load(); } private Listener<MenuEvent> getRefDirectionListener() { if (refTypeListener == null) { refTypeListener = new Listener<MenuEvent>() { public void handleEvent(MenuEvent be) { CheckMenuItem item = (CheckMenuItem) be.item; if (item.isChecked()) { setRelTypeMode((Integer) item.getData("value")); } } }; } return(refTypeListener); } protected void doNew() { // InputDialog for new AliasName. /* final MessageBox box = MessageBox.prompt("Name", "Please enter instance alias:"); box.addCallback(new Listener<MessageBoxEvent>() { public void handleEvent(MessageBoxEvent be) { //be.buttonClicked. if (be.value == null || be.value.length() == 0) { return; } */ // Create new template. CIModel newInstance = root.newInstance(); //newInstance.setAlias(be.value); List<CIModel> base = new ArrayList<CIModel>(); List<CIModel> local = new ArrayList<CIModel>(); local.add(newInstance); // Call create. ModelServiceFactory.get().store(mdr, CMDBSession.get().getToken(), local, base, new AsyncCallback<StoreResult>() { public void onFailure(Throwable caught) { ExceptionErrorDialog.showError("Can't Create", caught); //loader.load(); } public void onSuccess(StoreResult result) { if (result.isRejected()) { MessageBox.alert("Create Failed", result.getRejectCause(), null); return; } DeferredCommand.addCommand(new Command() { public void execute() { lP.load(); } }); } }); /* } }); */ } protected void fireEvent(ModelData model) { BaseEvent be = new BaseEvent(model); //be.source = model; super.fireEvent(CI_SELECTED_EVENT, be); } private void updateMenu(TreeItem item, Menu menu) { final ModelData model = item.getModel(); menu.removeAll(); if (!permissions.getCurrentState().equals(CMDBPermissions.PermissionState.READONLY)) { if (model instanceof RelationTypeModel) { MenuItem addRelation = new MenuItem("Add Relation", "add-icon"); addRelation.addSelectionListener(getAddRelation((CIModel)item.getParentItem().getModel(), (RelationTypeModel)model)); MenuItem newRelation = new MenuItem("New Relation", "new-icon"); newRelation.addSelectionListener(getNewRelation((CIModel)item.getParentItem().getModel(), (RelationTypeModel)model)); menu.add(addRelation); //menu.add(newRelation); menu.add(new SeparatorMenuItem()); } if (model instanceof CIModel) { boolean insert = false; if (!(item.getParentItem().getParentItem() == null)) { MenuItem deleteRel = new MenuItem("Delete Relation", "delete-relation-icon"); CIModel parent = (CIModel) item.getParentItem().getParentItem().getModel(); CIModel child = (CIModel)model; RelationTypeModel relation = (RelationTypeModel)item.getParentItem().getModel(); deleteRel.addSelectionListener(getDeleteRelation(parent, relation, child)); menu.add(deleteRel); insert = true; } if (permissions.getCurrentState().equals(CMDBPermissions.PermissionState.DELETE)) { MenuItem deleteCI = new MenuItem("Delete CI", "delete-icon"); deleteCI.addSelectionListener(getDeleteCI((CIModel)model)); menu.add(deleteCI); insert = true; } if (insert) { menu.add(new SeparatorMenuItem()); } } } MenuItem refresh = new MenuItem("Referesh", "refresh-icon"); refresh.addSelectionListener(new SelectionListener<ComponentEvent>() { @Override public void componentSelected(ComponentEvent ce) { reloadChildren((ModelItem)model); } }); menu.add(refresh); } private SelectionListener getDeleteCI(final CIModel model) { return(new SelectionListener<ComponentEvent>() { @Override public void componentSelected(ComponentEvent ce) { ArrayList<CIModel> local = new ArrayList<CIModel>(); ArrayList<CIModel> base = new ArrayList<CIModel>(); base.add(model); StoreAction.store(mdr, local, base, new CMDBAsyncCallback<StoreResult>() { public void onSuccess(StoreResult result) { if (result.isRejected()) { MessageBox.alert("Failed", "Delete rejected, cause " + result.getRejectCause(), null); return; } lP.load(); } }); } }); } private SelectionListener getDeleteRelation(final CIModel parent, final RelationTypeModel relation, final CIModel child) { return(new SelectionListener<ComponentEvent>() { @Override public void componentSelected(ComponentEvent ce) { // TODO Auto-generated method stub List<CIModel> local = new ArrayList<CIModel>(); List<CIModel> base = new ArrayList<CIModel>(); CIModel source = null; CIModel target = null; AttributeModel aM = null; if (relation.isOutbound()) { source = parent; target = child; aM = relation.getSourceType().getAttribute(relation.getAttributeAlias()); } else { source = child; target = parent; aM = relation.getTargetType().getAttribute(relation.getAttributeAlias()); } base.add(source.copy()); local.add(source); // Validate if we remove value or reset value... ValueModel vM = parent.getValue(relation.getAttributeAlias()); if (vM instanceof ValueListModel) { ValueListModel vListM = (ValueListModel)vM; List<ValueModel> values = vListM.getValues(); ValueModel realValue = null; for (ValueModel v : values) { if (target.getAlias().equals(v.getValue())) { realValue = v; break; } } if (realValue != null) { int minOccurs = Integer.parseInt(aM.getMinOccur()); if (minOccurs == 0 || values.size() > minOccurs) { // Remove value vListM.removeValue(realValue); } else { // Reset value. realValue.setValue(null); } } } else { if (aM.getMinOccur().equals("0")) { // remove value source.removeValue(vM); } else { // reset value vM.setValue(null); } } StoreAction.store(mdr, local, base, new CMDBAsyncCallback<StoreResult>() { public void onSuccess(StoreResult result) { if (result.isRejected()) { MessageBox.alert("Failed", "Delete relation rejected, cause " + result.getRejectCause(), null); return; } reloadChildren(relation); } }); } }); } private void addRelation(final CIModel ci, final RelationTypeModel relation, List objects, boolean newObjects) { List<CIModel> local = new ArrayList<CIModel>(); List<CIModel> base = new ArrayList<CIModel>(); if (relation.isOutbound()) { base.add(ci.copy()); } for (Object o : objects) { CIModel relCI = null; if (o instanceof CIModelCollection) { CIModelCollection col = (CIModelCollection)o; relCI = col.getCIModel("offspring"); } if (o instanceof CIModel) { relCI = (CIModel)o; } if (relCI == null) { continue; } String attrAlias = relation.get(RelationTypeModel.REL_ATTRIBUTE_ALIAS); if (relation.isOutbound()) { ValueModel v = ci.getValue(attrAlias); if (v == null) { v = new ValueModel(); v.setAlias(attrAlias); v.setIsComplex(true); ci.setValue(attrAlias, v); } if (v instanceof ValueListModel) { // Check if w have empty slots ValueListModel vListM = (ValueListModel)v; ValueModel nV = null; for (ValueModel eV : vListM.getValues()) { if (eV.getValue() == null || eV.getValue().length() == 0) { nV = eV; break; } } if (nV == null) { nV = new ValueModel(); nV.setAlias(attrAlias); ((ValueListModel)v).addValue(nV); } nV.setIsComplex(true); nV.setValue(relCI.getAlias()); } else { v.setValue(relCI.getAlias()); } local.add(ci); if (newObjects) { local.add(relCI); } } else { if (!newObjects) { base.add(relCI.copy()); } ValueModel v = relCI.getValue(attrAlias); if (v == null) { v = new ValueModel(); v.setAlias(attrAlias); v.setIsComplex(true); relCI.setValue(attrAlias, v); } if (v instanceof ValueListModel) { ValueModel nV = new ValueModel(); nV.setAlias(attrAlias); nV.setValue(ci.getAlias()); nV.setIsComplex(true); ((ValueListModel)v).addValue(nV); } else { v.setValue(ci.getAlias()); } local.add(relCI); } } // TODO: Save local, base... final MessageBox saveInfo = MessageBox.wait("Progress", "Saving your data, please wait...", "Saving..."); ModelServiceFactory.get().store(mdr, CMDBSession.get().getToken(), local, base, new CMDBAsyncCallback<StoreResult>() { 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) { } }); return; } else { // Update ci. List<String> aliases = new ArrayList<String>(); aliases.add(ci.getAlias()); ModelServiceFactory.get().getCIModel(CMDBSession.get().getToken(), mdr, aliases, new CMDBAsyncCallback<List<CIModel>>() { @Override public void onSuccess(List<CIModel> arg0) { if (arg0.size() > 0) { CIModel newCi = arg0.get(0); store.update(newCi); } reloadChildren(relation); } }); } } }); } public void reloadChildren(ModelItem model) { loader.loadChildren(model); } public void reload(ModelItem model) { TreeItem item = (TreeItem) binder.findItem(model); if (item == null) { return; } TreeItem parent = item.getParentItem(); if (parent == null) { lP.load(); return; } if (parent.isRoot()) { lP.load(); return; } if (parent.getModel() != null) { loader.loadChildren(parent.getModel()); } } private SelectionListener getAddRelation(final CIModel ci, final RelationTypeModel relation) { return(new SelectionListener<ComponentEvent>() { @Override public void componentSelected(ComponentEvent ce) { final Window w = new Window(); w.setCloseAction(CloseAction.CLOSE); w.setMinimizable(false); w.setMaximizable(true); w.setIconStyle("accordion"); //w.setHeading(); w.setWidth(600); w.setHeight(400); w.setLayout(new FitLayout()); CIModel source = relation.getSourceType(); AttributeModel aModel = source.getAttribute((String)relation.get(RelationTypeModel.REL_ATTRIBUTE_ALIAS)); SelectionMode selMod = SelectionMode.MULTI; if (relation.isOutbound() && aModel.getMaxOccur().equals("1")) { selMod = SelectionMode.SINGLE; } CIModel type = relation.getSourceType(); if (relation.isOutbound()) { type = relation.getTargetType(); } final MultiSelectCI select = new MultiSelectCI(mdr, type, selMod, null, permissions); ContentPanel cp = new ContentPanel(); cp.setLayout(new FillLayout()); String multiStr = "1"; String many = ""; if (!"1".equals(aModel.getMaxOccur())) { multiStr = aModel.getMaxOccur(); many = "s"; } cp.setHeading("Select " + multiStr + " " + type.getAlias() + many); cp.add(select); TextToolItem cancelButton = new TextToolItem("Cancel", "cancel-icon"); cancelButton.addSelectionListener(new SelectionListener<ComponentEvent>() { @Override public void componentSelected(ComponentEvent ce) { w.setVisible(false); } }); TextToolItem selectButton = new TextToolItem("Select", "select-icon"); selectButton.addSelectionListener(new SelectionListener<ComponentEvent>() { @Override public void componentSelected(ComponentEvent ce) { w.setVisible(false); List objects = select.getSelection(); addRelation(ci, relation, objects, false); } }); ToolBar bar = new ToolBar(); bar.add(new FillToolItem()); bar.add(selectButton); bar.add(cancelButton); cp.setBottomComponent(bar); w.add(cp); w.setVisible(true); } }); } private SelectionListener getNewRelation(final CIModel ci, final RelationTypeModel relation) { return(new SelectionListener<ComponentEvent>() { @Override public void componentSelected(ComponentEvent ce) { String derivedFrom = relation.getSourceType().getAlias(); if (relation.isOutbound()) { derivedFrom = relation.getTargetType().getAlias(); } // Select SubTypes. List<String> roots = new ArrayList<String>(); roots.add(derivedFrom); final CITemplateBrowser browser = new CITemplateBrowser(mdr, roots); final Window w = new Window(); w.setCloseAction(CloseAction.CLOSE); w.setMinimizable(false); w.setMaximizable(true); w.setIconStyle("accordion"); //w.setHeading(); w.setWidth(600); w.setHeight(400); w.setLayout(new FitLayout()); w.add(browser); ContentPanel cp = new ContentPanel(); cp.setLayout(new FillLayout()); cp.setHeading("Select..."); cp.add(browser); Button cancelButton = new Button("Cancel"); cancelButton.addSelectionListener(new SelectionListener<ComponentEvent>() { @Override public void componentSelected(ComponentEvent ce) { w.setVisible(false); } }); Button selectButton = new Button("Select"); selectButton.addSelectionListener(new SelectionListener<ComponentEvent>() { @Override public void componentSelected(ComponentEvent ce) { w.setVisible(false); TreeItem item = browser.getSelected(); if (item == null) { return; } if (item.getModel() instanceof CIModel) { CIModel model = (CIModel) item.getModel(); CIModel newCI = model.newInstance(); List objects = new ArrayList(); objects.add(newCI); addRelation(ci, relation, objects, true); } } }); cp.addButton(selectButton); cp.addButton(cancelButton); w.add(cp); w.setVisible(true); } }); } public void setPermission(CMDBPermissions permissions) { this.permissions = permissions; } public int getDisplayMode() { return displayMode; } public void setDisplayMode(int displayMode) { this.displayMode = displayMode; } public int getRelTypeMode() { return relTypeMode; } public void setRelTypeMode(int relTypeMode) { this.relTypeMode = relTypeMode; } }