UNPKG

@openui5/sap.ui.core

Version:

OpenUI5 Core Library sap.ui.core

487 lines (445 loc) 15.5 kB
/*! * OpenUI5 * (c) Copyright 2009-2023 SAP SE or an SAP affiliate company. * Licensed under the Apache License, Version 2.0 - see LICENSE.txt. */ // Provides the implementation for a MessageManager sap.ui.define([ "./ControlMessageProcessor", "./Message", "sap/base/Log", "sap/base/util/deepEqual", "sap/base/util/merge", "sap/ui/base/EventProvider", "sap/ui/base/ManagedObject", "sap/ui/core/Configuration", "sap/ui/core/message/MessageProcessor", "sap/ui/model/message/MessageModel" ], function (ControlMessageProcessor, Message, Log, deepEqual, merge, EventProvider, ManagedObject, Configuration, MessageProcessor, MessageModel) { "use strict"; /*global Map */ /** * * @namespace * @name sap.ui.core.message * @public */ /** * Constructor for a new MessageManager. * * @class * * @extends sap.ui.base.EventProvider * * @author SAP SE * @version 1.111.5 * * @public * @alias sap.ui.core.message.MessageManager */ var MessageManager = EventProvider.extend("sap.ui.core.message.MessageManager", /** @lends sap.ui.core.message.MessageManager.prototype */ { constructor : function () { EventProvider.apply(this, arguments); this.mProcessors = {}; this.mObjects = {}; this.mMessages = {}; var bHandleValidation = Configuration.getHandleValidation(); if (bHandleValidation) { sap.ui.getCore().attachValidationSuccess(bHandleValidation, this._handleSuccess, this); sap.ui.getCore().attachValidationError(bHandleValidation, this._handleError, this); sap.ui.getCore().attachParseError(bHandleValidation, this._handleError, this); sap.ui.getCore().attachFormatError(bHandleValidation, this._handleError, this); } }, metadata : { publicMethods : [ // methods "addMessages", "removeMessages", "removeAllMessages", "registerMessageProcessor", "unregisterMessageProcessor", "registerObject", "unregisterObject", "getMessageModel", "destroy" ] } }); /** * handle validation/parse/format error * * @param {object} oEvent The Event object * @private */ MessageManager.prototype._handleError = function(oEvent, bHandleValidation) { if (!this.oControlMessageProcessor) { this.oControlMessageProcessor = new ControlMessageProcessor(); } if (bHandleValidation) { var oElement = oEvent.getParameter("element"); var sProperty = oEvent.getParameter("property"); var sTarget = oElement.getId() + '/' + sProperty; var sProcessorId = this.oControlMessageProcessor.getId(); var bTechnical = oEvent.sId === "formatError"; if (this.mMessages[sProcessorId] && this.mMessages[sProcessorId][sTarget]) { this._removeMessages(this.mMessages[sProcessorId][sTarget], true); } var oReference = {}; oReference[oElement.getId()] = { properties:{}, fieldGroupIds: oElement.getFieldGroupIds ? oElement.getFieldGroupIds() : undefined }; oReference[oElement.getId()].properties[sProperty] = true; var oMessage = new Message({ type: sap.ui.core.MessageType.Error, message: oEvent.getParameter("message"), target: sTarget, processor: this.oControlMessageProcessor, technical: bTechnical, references: oReference, validation: true }); this.addMessages(oMessage); } oEvent.cancelBubble(); }; /** * handle validation success * * @param {object} oEvent The Event object * @private */ MessageManager.prototype._handleSuccess = function(oEvent, bHandleValidation) { if (!this.oControlMessageProcessor) { this.oControlMessageProcessor = new ControlMessageProcessor(); } if (bHandleValidation) { var oElement = oEvent.getParameter("element"); var sProperty = oEvent.getParameter("property"); var sTarget = oElement.getId() + '/' + sProperty; var sProcessorId = this.oControlMessageProcessor.getId(); if (this.mMessages[sProcessorId] && this.mMessages[sProcessorId][sTarget]) { this._removeMessages(this.mMessages[sProcessorId][sTarget], true); } } oEvent.cancelBubble(); }; /** * Add messages to MessageManager * * @param {sap.ui.core.message.Message|sap.ui.core.message.Message[]} vMessages Array of sap.ui.core.message.Message or single sap.ui.core.message.Message * @public */ MessageManager.prototype.addMessages = function(vMessages) { var oMessage = vMessages, mProcessors = this.getAffectedProcessors(vMessages); if (!vMessages) { return; } else if (Array.isArray(vMessages)) { for (var i = 0; i < vMessages.length; i++) { oMessage = vMessages[i]; this._importMessage(oMessage); } } else { this._importMessage(vMessages); } this._updateMessageModel(mProcessors); }; /** * import message to internal map of messages * @private */ MessageManager.prototype._importMessage = function(oMessage) { var oProcessor = oMessage.getMessageProcessor(), sProcessorId = oProcessor && oProcessor.getId(), aTargets = oMessage.getTargets(), that = this; if (!this.mMessages[sProcessorId]) { this.mMessages[sProcessorId] = {}; } if (!aTargets.length) { // unbound message => add it to undefined entry aTargets = [undefined]; } aTargets.forEach(function (sTarget) { var aMessages = that.mMessages[sProcessorId][sTarget] ? that.mMessages[sProcessorId][sTarget] : []; aMessages.push(oMessage); that.mMessages[sProcessorId][sTarget] = aMessages; }); }; /** * push messages to registered MessageProcessors * @param {Object<string,sap.ui.core.message.MessageProcessor>} mProcessors A map containing the affected processor IDs * @private */ MessageManager.prototype._pushMessages = function(mProcessors) { var oProcessor, sId; for (sId in mProcessors) { oProcessor = mProcessors[sId]; var vMessages = this.mMessages[sId] ? this.mMessages[sId] : {}; this._sortMessages(vMessages); //push a copy vMessages = Object.keys(vMessages).length === 0 ? null : merge({}, vMessages); oProcessor.setMessages(vMessages); } }; /** * Sort messages by type as specified in {@link sap.ui.core.message.Message#compare}. * * @param {Object<string,sap.ui.core.message.Message[]>|sap.ui.core.message.Message[]} vMessages * Map or array of Messages to be sorted (in order of severity) by their type property * @private */ MessageManager.prototype._sortMessages = function(vMessages) { var sTarget, aMessages; if (Array.isArray(vMessages)) { vMessages = { "ignored": vMessages }; } for (sTarget in vMessages) { aMessages = vMessages[sTarget]; if (aMessages.length > 1) { aMessages.sort(Message.compare); } } }; /** * update MessageModel * @param {Object<string,sap.ui.core.message.MessageProcessor>} mProcessors A map containing the affected processor IDs * @private */ MessageManager.prototype._updateMessageModel = function(mProcessors) { var mAllMessages = new Map(), sProcessorId, oMessageModel = this.getMessageModel(), sTarget; function setMessage(oMessage) { mAllMessages.set(oMessage, true); } for (sProcessorId in this.mMessages) { for (sTarget in this.mMessages[sProcessorId]) { this.mMessages[sProcessorId][sTarget].forEach(setMessage); } } this._pushMessages(mProcessors); oMessageModel.setData(Array.from(mAllMessages.keys())); }; /** * Remove all messages * @public */ MessageManager.prototype.removeAllMessages = function() { var mProcessors = {}; for (var sProcessorId in this.mMessages) { //use the first Message/Message array to get the processor for the update var sFirstKey = Object.keys(this.mMessages[sProcessorId])[0]; var vMessages = this.mMessages[sProcessorId][sFirstKey]; Object.assign(mProcessors, this.getAffectedProcessors(vMessages)); } this.aMessages = []; this.mMessages = {}; this._updateMessageModel(mProcessors); }; /** * Remove given Messages * * @param {sap.ui.core.message.Message|sap.ui.core.message.Message[]} vMessages - The message(s) to be removed. * @public */ MessageManager.prototype.removeMessages = function(vMessages) { // Do not expose bOnlyValidationMessages to public API return this._removeMessages.apply(this, arguments); }; /** * Like sap.ui.core.message.MessageManager#removeMessage but with an additional argument to only remove validation * messages. * * @param {sap.ui.core.message.Message|sap.ui.core.message.Message[]} vMessages - The message(s) to be removed. * @param {boolean} bOnlyValidationMessages - If set to true only messages that have been added due to validation * errors are removed. * @private */ MessageManager.prototype._removeMessages = function(vMessages, bOnlyValidationMessages) { var mProcessors = this.getAffectedProcessors(vMessages); if (!vMessages || (Array.isArray(vMessages) && vMessages.length == 0)) { return; } else if (Array.isArray(vMessages)) { // We need to work on a copy since the messages reference is changed by _removeMessage() var aOriginalMessages = vMessages.slice(0); for (var i = 0; i < aOriginalMessages.length; i++) { if (!bOnlyValidationMessages || aOriginalMessages[i].validation) { this._removeMessage(aOriginalMessages[i]); } } } else if (vMessages instanceof Message && (!bOnlyValidationMessages || vMessages.validation)){ this._removeMessage(vMessages); } else { //map with target as key for (var sTarget in vMessages) { this._removeMessages(vMessages[sTarget], bOnlyValidationMessages); } } this._updateMessageModel(mProcessors); }; /** * remove Message * * @param {sap.ui.core.message.Message} oMessage The Message to remove * @private */ MessageManager.prototype._removeMessage = function(oMessage) { var oProcessor = oMessage.getMessageProcessor(), sProcessorId = oProcessor && oProcessor.getId(), mMessages = this.mMessages[sProcessorId], aTargets; if (!mMessages) { return; } aTargets = oMessage.getTargets(); if (!aTargets.length) { // unbound message => remove it from undefined entry aTargets = [undefined]; } aTargets.forEach(function (sTarget) { var aMessages = mMessages[sTarget]; if (aMessages) { for (var i = 0; i < aMessages.length; i++) { var oMsg = aMessages[i]; if (deepEqual(oMsg, oMessage)) { aMessages.splice(i,1); --i; // Decrease counter as one element has been removed } } // delete empty message array if (mMessages[sTarget].length === 0) { delete mMessages[sTarget]; } } }); }; /** * message change handler * @private */ MessageManager.prototype.onMessageChange = function(oEvent) { var aOldMessages = oEvent.getParameter('oldMessages'); var aNewMessages = oEvent.getParameter('newMessages'); this.removeMessages(aOldMessages); this.addMessages(aNewMessages); }; /** * Register MessageProcessor * * @param {sap.ui.core.message.MessageProcessor} oProcessor The MessageProcessor * @public */ MessageManager.prototype.registerMessageProcessor = function(oProcessor) { var sProcessorId = oProcessor.getId(), mProcessors = {}; if (!this.mProcessors[sProcessorId]) { this.mProcessors[sProcessorId] = sProcessorId; oProcessor.attachMessageChange(this.onMessageChange, this); if (sProcessorId in this.mMessages) { mProcessors[sProcessorId] = oProcessor; this._pushMessages(mProcessors); } } }; /** * Deregister MessageProcessor * * @param {sap.ui.core.message.MessageProcessor} oProcessor The MessageProcessor * @public */ MessageManager.prototype.unregisterMessageProcessor = function(oProcessor) { this.removeMessagesByProcessor(oProcessor.getId()); delete this.mProcessors[oProcessor.getId()]; oProcessor.detachMessageChange(this.onMessageChange, this); }; /** * When using the databinding type system, the validation/parsing of a new property value could fail. * In this case, a validationError/parseError event is fired. These events bubble up to the core. * For registered ManagedObjects, the MessageManager attaches to these events and creates a * <code>sap.ui.core.message.Message</code> (bHandleValidation=true) for each of these errors * and cancels the event bubbling. * * @param {sap.ui.base.ManagedObject} oObject The sap.ui.base.ManagedObject * @param {boolean} bHandleValidation Handle validationError/parseError events for this object. If set to true, * the MessageManager creates a Message for each validation/parse error. The event bubbling is canceled in every case. * @public */ MessageManager.prototype.registerObject = function(oObject, bHandleValidation) { if (!(oObject instanceof ManagedObject)) { Log.error(this + " : " + oObject.toString() + " is not an instance of sap.ui.base.ManagedObject"); } else { oObject.attachValidationSuccess(bHandleValidation, this._handleSuccess, this); oObject.attachValidationError(bHandleValidation, this._handleError, this); oObject.attachParseError(bHandleValidation, this._handleError, this); oObject.attachFormatError(bHandleValidation, this._handleError, this); } }; /** * Unregister ManagedObject * * @param {sap.ui.base.ManagedObject} oObject The sap.ui.base.ManagedObject * @public */ MessageManager.prototype.unregisterObject = function(oObject) { if (!(oObject instanceof ManagedObject)) { Log.error(this + " : " + oObject.toString() + " is not an instance of sap.ui.base.ManagedObject"); } else { oObject.detachValidationSuccess(this._handleSuccess, this); oObject.detachValidationError(this._handleError, this); oObject.detachParseError(this._handleError, this); oObject.detachFormatError(this._handleError, this); } }; /** * Destroy MessageManager * @deprecated As of version 1.32, do not call <code>destroy()</code> on a <code>MessageManager</code>. * @public */ MessageManager.prototype.destroy = function() { Log.warning("Deprecated: Do not call destroy on a MessageManager"); }; /** * Get the MessageModel * @return {sap.ui.model.message.MessageModel} oMessageModel The Message Model * @public */ MessageManager.prototype.getMessageModel = function() { if (!this.oMessageModel) { this.oMessageModel = new MessageModel(this); this.oMessageModel.setData([]); } return this.oMessageModel; }; /** * getAffectedProcessors * @param {sap.ui.core.message.Message|sap.ui.core.message.Message[]} vMessages Array of sap.ui.core.message.Message or single sap.ui.core.message.Message * @return {Object<string,sap.ui.core.message.MessageProcessor>} mProcessors A map containing the affected processor IDs * @private */ MessageManager.prototype.getAffectedProcessors = function(vMessages) { var oProcessor, sProcessorId, mProcessors = {}; if (vMessages) { if (!Array.isArray(vMessages)) { vMessages = [vMessages]; } vMessages.forEach(function(oMessage) { oProcessor = oMessage.getMessageProcessor(); if (oProcessor instanceof MessageProcessor) { sProcessorId = oProcessor.getId(); mProcessors[sProcessorId] = oProcessor; } }); } return mProcessors; }; /** * Removes all Messages for the given Processor Id. This function * is used only during deregistration of a MessageProcessor. No * further 'pushMessages' needed. * * @param {string} sProcessorId The Id of a MessageProcessor * @private */ MessageManager.prototype.removeMessagesByProcessor = function(sProcessorId) { delete this.mMessages[sProcessorId]; this._updateMessageModel({}); }; return MessageManager; });