package org.ovirt.engine.ui.uicommonweb.models.tags; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; import org.ovirt.engine.core.common.action.TagsActionParametersBase; import org.ovirt.engine.core.common.action.TagsOperationParameters; import org.ovirt.engine.core.common.action.VdcActionType; import org.ovirt.engine.core.common.action.VdcReturnValueBase; import org.ovirt.engine.core.common.businessentities.Tags; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.ui.frontend.Frontend; import org.ovirt.engine.ui.uicommonweb.UICommand; import org.ovirt.engine.ui.uicommonweb.dataprovider.AsyncDataProvider; import org.ovirt.engine.ui.uicommonweb.help.HelpTag; import org.ovirt.engine.ui.uicommonweb.models.ConfirmationModel; import org.ovirt.engine.ui.uicommonweb.models.EntityModel; import org.ovirt.engine.ui.uicommonweb.models.SearchableListModel; import org.ovirt.engine.ui.uicommonweb.models.SystemTreeModel; import org.ovirt.engine.ui.uicommonweb.models.common.SelectionTreeNodeModel; import org.ovirt.engine.ui.uicompat.ConstantsManager; import org.ovirt.engine.ui.uicompat.Event; import org.ovirt.engine.ui.uicompat.EventArgs; import org.ovirt.engine.ui.uicompat.EventDefinition; import org.ovirt.engine.ui.uicompat.PropertyChangedEventArgs; public class TagListModel extends SearchableListModel<Void, TagModel> { public static final EventDefinition resetRequestedEventDefinition; private Event<EventArgs> privateResetRequestedEvent; public Event<EventArgs> getResetRequestedEvent() { return privateResetRequestedEvent; } private void setResetRequestedEvent(Event<EventArgs> value) { privateResetRequestedEvent = value; } private UICommand privateNewCommand; public UICommand getNewCommand() { return privateNewCommand; } private void setNewCommand(UICommand value) { privateNewCommand = value; } private UICommand privateEditCommand; @Override public UICommand getEditCommand() { return privateEditCommand; } private void setEditCommand(UICommand value) { privateEditCommand = value; } private UICommand privateRemoveCommand; public UICommand getRemoveCommand() { return privateRemoveCommand; } private void setRemoveCommand(UICommand value) { privateRemoveCommand = value; } private UICommand privateResetCommand; public UICommand getResetCommand() { return privateResetCommand; } private void setResetCommand(UICommand value) { privateResetCommand = value; } @Override public TagModel getSelectedItem() { return super.getSelectedItem(); } public void setSelectedItem(TagModel value) { super.setSelectedItem(value); } @Override public void setItems(Collection<TagModel> value) { if (items != value) { itemsChanging(value, items); items = value; itemsChanged(); getItemsChangedEvent().raise(this, EventArgs.EMPTY); onPropertyChanged(new PropertyChangedEventArgs("Items")); //$NON-NLS-1$ } } private ArrayList<SelectionTreeNodeModel> selectionNodeList; public ArrayList<SelectionTreeNodeModel> getSelectionNodeList() { return selectionNodeList; } public void setSelectionNodeList(ArrayList<SelectionTreeNodeModel> value) { if (selectionNodeList != value) { selectionNodeList = value; onPropertyChanged(new PropertyChangedEventArgs("SelectionNodeList")); //$NON-NLS-1$ } } private Map<Guid, Boolean> attachedTagsToEntities; public Map<Guid, Boolean> getAttachedTagsToEntities() { return attachedTagsToEntities; } public void setAttachedTagsToEntities(Map<Guid, Boolean> value) { if (attachedTagsToEntities != value) { attachedTagsToEntities = value; attachedTagsToEntitiesChanged(); onPropertyChanged(new PropertyChangedEventArgs("AttachedTagsToEntities")); //$NON-NLS-1$ } } static { resetRequestedEventDefinition = new EventDefinition("ResetRequested", SystemTreeModel.class); //$NON-NLS-1$ } public TagListModel() { setResetRequestedEvent(new Event<>(resetRequestedEventDefinition)); setNewCommand(new UICommand("New", this)); //$NON-NLS-1$ setEditCommand(new UICommand("Edit", this)); //$NON-NLS-1$ setRemoveCommand(new UICommand("Remove", this)); //$NON-NLS-1$ setResetCommand(new UICommand("Reset", this)); //$NON-NLS-1$ setIsTimerDisabled(true); getSearchCommand().execute(); updateActionAvailability(); // Initialize SelectedItems property with empty collection. setSelectedItems(new ArrayList<TagModel>()); setSelectionNodeList(new ArrayList<SelectionTreeNodeModel>()); } @Override protected void syncSearch() { super.syncSearch(); AsyncDataProvider.getInstance().getRootTag(new AsyncQuery<>(returnValue -> { TagModel rootTag = tagToModel(returnValue); rootTag.getName().setEntity(ConstantsManager.getInstance().getConstants().rootTag()); rootTag.setType(TagModelType.Root); rootTag.setIsChangeable(false); setItems(new ArrayList<>(Arrays.asList(new TagModel[] { rootTag }))); })); } @Override protected void itemsChanged() { super.itemsChanged(); if (getSelectionNodeList() != null && getSelectionNodeList().isEmpty() && getAttachedTagsToEntities() != null) { attachedTagsToEntitiesChanged(); } } protected void attachedTagsToEntitiesChanged() { ArrayList<TagModel> tags = (ArrayList<TagModel>) getItems(); if (tags != null) { TagModel root = tags.get(0); if (getAttachedTagsToEntities() != null) { recursiveSetSelection(root, getAttachedTagsToEntities()); } if (getSelectionNodeList().isEmpty()) { setSelectionNodeList(new ArrayList<>(Arrays.asList(new SelectionTreeNodeModel[]{createTree(root)}))); } } } public void recursiveSetSelection(TagModel tagModel, Map<Guid, Boolean> attachedEntities) { if (attachedEntities.containsKey(tagModel.getId()) && attachedEntities.get(tagModel.getId())) { tagModel.setSelection(true); } else { tagModel.setSelection(false); } if (tagModel.getChildren() != null) { for (TagModel subModel : tagModel.getChildren()) { recursiveSetSelection(subModel, attachedEntities); } } } public SelectionTreeNodeModel createTree(TagModel tag) { SelectionTreeNodeModel node = new SelectionTreeNodeModel(); node.setDescription(tag.getName().getEntity()); node.setIsSelectedNullable(tag.getSelection()); node.setIsChangeable(tag.getIsChangable()); node.setIsSelectedNotificationPrevent(true); node.setEntity(tag); node.getPropertyChangedEvent().addListener(this); if (tag.getChildren().isEmpty()) { getSelectionNodeList().add(node); return node; } for (TagModel childTag : tag.getChildren()) { SelectionTreeNodeModel childNode = createTree(childTag); childNode.setParent(node); node.getChildren().add(childNode); } return node; } public TagModel cloneTagModel(TagModel tag) { ArrayList<TagModel> children = new ArrayList<>(); for (TagModel child : tag.getChildren()) { children.add(cloneTagModel(child)); } TagModel model = new TagModel(); model.setId(tag.getId()); model.setName(tag.getName()); model.setDescription(tag.getDescription()); model.setType(tag.getType()); model.setSelection(tag.getSelection()); model.setParentId(tag.getParentId()); model.setChildren(children); model.getSelectionChangedEvent().addListener(this); for (TagModel child : children) { child.setParent(model); } return model; } public TagModel tagToModel(Tags tag) { EntityModel<String> tempVar = new EntityModel<>(); tempVar.setEntity(tag.getTagName()); EntityModel<String> name = tempVar; EntityModel<String> tempVar2 = new EntityModel<>(); tempVar2.setEntity(tag.getDescription()); EntityModel<String> description = tempVar2; ArrayList<TagModel> children = new ArrayList<>(); for (Tags a : tag.getChildren()) { children.add(tagToModel(a)); } TagModel model = new TagModel(); model.setId(tag.getTagId()); model.setName(name); model.setDescription(description); model.setType((tag.getIsReadonly() == null ? false : tag.getIsReadonly()) ? TagModelType.ReadOnly : TagModelType.Regular); model.setSelection(false); model.setParentId(tag.getParentId() == null ? Guid.Empty : tag.getParentId()); model.setChildren(children); for (TagModel child : children) { child.setParent(model); } model.getSelectionChangedEvent().addListener(this); return model; } @Override public void eventRaised(Event<? extends EventArgs> ev, Object sender, EventArgs args) { super.eventRaised(ev, sender, args); if (ev.matchesDefinition(TagModel.selectionChangedEventDefinition)) { onTagSelectionChanged(sender, args); } } @Override protected void entityPropertyChanged(Object sender, PropertyChangedEventArgs e) { super.entityPropertyChanged(sender, e); if (e.propertyName.equals("IsSelectedNullable")) { //$NON-NLS-1$ SelectionTreeNodeModel selectionTreeNodeModel = (SelectionTreeNodeModel) sender; TagModel tagModel = (TagModel) selectionTreeNodeModel.getEntity(); tagModel.setSelection(selectionTreeNodeModel.getIsSelectedNullable()); onTagSelectionChanged(tagModel, e); } } private void onTagSelectionChanged(Object sender, EventArgs e) { TagModel model = (TagModel) sender; List<TagModel> list = new ArrayList<>(); if (getSelectedItems() != null) { for (Object item : getSelectedItems()) { list.add((TagModel) item); } } if (model.getSelection() == null ? false : model.getSelection()) { list.add(model); } else { list.remove(model); } setSelectedItems(list); } private void reset() { setSelectedItems(new ArrayList<TagModel>()); if (getItems() != null) { for (Object item : getItems()) { resetInternal((TagModel) item); } } // Async tag search will cause tree selection to be cleared // Search(); getResetRequestedEvent().raise(this, EventArgs.EMPTY); } private void resetInternal(TagModel root) { root.setSelection(false); for (TagModel item : root.getChildren()) { resetInternal(item); } } public void remove() { if (getWindow() != null) { return; } ConfirmationModel model = new ConfirmationModel(); setWindow(model); model.setTitle(ConstantsManager.getInstance().getConstants().removeTagsTitle()); model.setHelpTag(HelpTag.remove_tag); model.setHashName("remove_tag"); //$NON-NLS-1$ ArrayList<String> items = new ArrayList<>(); items.add(getSelectedItem().getName().getEntity()); model.setItems(items); model.setNote(ConstantsManager.getInstance().getConstants().noteRemovingTheTagWillAlsoRemoveAllItsDescendants()); UICommand tempVar = UICommand.createDefaultOkUiCommand("OnRemove", this); //$NON-NLS-1$ model.getCommands().add(tempVar); UICommand tempVar2 = UICommand.createCancelUiCommand("Cancel", this); //$NON-NLS-1$ model.getCommands().add(tempVar2); } public void onRemove() { ConfirmationModel model = (ConfirmationModel) getWindow(); if (model.getProgress() != null) { return; } model.startProgress(); Frontend.getInstance().runAction(VdcActionType.RemoveTag, new TagsActionParametersBase(getSelectedItem().getId()), result -> { TagListModel tagListModel = (TagListModel) result.getState(); VdcReturnValueBase returnVal = result.getReturnValue(); boolean success = returnVal != null && returnVal.getSucceeded(); if (success) { tagListModel.getSearchCommand().execute(); } tagListModel.cancel(); tagListModel.stopProgress(); }, this); } public void edit() { if (getWindow() != null) { return; } TagModel model = new TagModel(); setWindow(model); model.setTitle(ConstantsManager.getInstance().getConstants().editTagTitle()); model.setHelpTag(HelpTag.edit_tag); model.setHashName("edit_tag"); //$NON-NLS-1$ model.setIsNew(false); model.getName().setEntity(getSelectedItem().getName().getEntity()); model.getDescription().setEntity(getSelectedItem().getDescription().getEntity()); model.setParent(getSelectedItem()); model.setParentId(getSelectedItem().getParentId()); UICommand tempVar = UICommand.createDefaultOkUiCommand("OnSave", this); //$NON-NLS-1$ model.getCommands().add(tempVar); UICommand tempVar2 = UICommand.createCancelUiCommand("Cancel", this); //$NON-NLS-1$ model.getCommands().add(tempVar2); } public void newEntity() { if (getWindow() != null) { return; } TagModel model = new TagModel(); setWindow(model); model.setTitle(ConstantsManager.getInstance().getConstants().newTagTitle()); model.setHelpTag(HelpTag.new_tag); model.setHashName("new_tag"); //$NON-NLS-1$ model.setIsNew(true); UICommand tempVar = UICommand.createDefaultOkUiCommand("OnSave", this); //$NON-NLS-1$ model.getCommands().add(tempVar); UICommand tempVar2 = UICommand.createCancelUiCommand("Cancel", this); //$NON-NLS-1$ model.getCommands().add(tempVar2); } public void onSave() { TagModel model = (TagModel) getWindow(); if (model.getProgress() != null) { return; } if (!model.validate()) { return; } Tags tempVar = new Tags(); tempVar.setTagId(model.getIsNew() ? Guid.Empty : getSelectedItem().getId()); tempVar.setParentId(model.getIsNew() ? getSelectedItem().getId() : getSelectedItem().getParentId()); tempVar.setTagName(model.getName().getEntity()); tempVar.setDescription(model.getDescription().getEntity()); Tags tag = tempVar; model.startProgress(); Frontend.getInstance().runAction(model.getIsNew() ? VdcActionType.AddTag : VdcActionType.UpdateTag, new TagsOperationParameters(tag), result -> { TagListModel localModel = (TagListModel) result.getState(); localModel.postOnSave(result.getReturnValue()); }, this); } public void postOnSave(VdcReturnValueBase returnValue) { TagModel model = (TagModel) getWindow(); model.stopProgress(); if (returnValue != null && returnValue.getSucceeded()) { cancel(); getSearchCommand().execute(); } } public void cancel() { setWindow(null); } @Override protected void onSelectedItemChanged() { super.onSelectedItemChanged(); updateActionAvailability(); } private void updateActionAvailability() { getNewCommand().setIsExecutionAllowed(getSelectedItem() != null); getEditCommand().setIsExecutionAllowed(getSelectedItem() != null && getSelectedItem().getType() == TagModelType.Regular); getRemoveCommand().setIsExecutionAllowed(getSelectedItem() != null && getSelectedItem().getType() == TagModelType.Regular); } @Override public void executeCommand(UICommand command) { super.executeCommand(command); if (command == getResetCommand()) { reset(); } else if (command == getNewCommand()) { newEntity(); } else if (command == getEditCommand()) { edit(); } else if (command == getRemoveCommand()) { remove(); } else if ("Cancel".equals(command.getName())) { //$NON-NLS-1$ cancel(); } else if ("OnSave".equals(command.getName())) { //$NON-NLS-1$ onSave(); } else if ("OnRemove".equals(command.getName())) { //$NON-NLS-1$ onRemove(); } } @Override protected String getListName() { return "TagListModel"; //$NON-NLS-1$ } public TagModel getRootNode() { return getItems().iterator().next(); } }