/* * org.openmicroscopy.shoola.env.data.views.MockDSCallEventListener * *------------------------------------------------------------------------------ * Copyright (C) 2006 University of Dundee. All rights reserved. * * * 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. * *------------------------------------------------------------------------------ */ package org.openmicroscopy.shoola.env.data.views; //Java imports //Third-party libraries //Application-internal dependencies import org.openmicroscopy.shoola.env.data.events.DSCallFeedbackEvent; import org.openmicroscopy.shoola.env.data.events.DSCallOutcomeEvent; import org.openmicroscopy.shoola.env.event.AgentEvent; import org.openmicroscopy.shoola.env.event.MockAgentEventListener; /** * Extends {@link MockAgentEventListener} to have <code>DSCall</code> events * considered equal if they hold the same state. * When testing the execution of a {@link BatchCallTree}, we want to use a * mock listener to verify that execution events are properly delivered. * However a problem arises: those events are generated internally by the * {@link BatchCallMonitor}, so the mock mustn't rely on object identity to * verify that the expected events (specified in set up mode) correspond to * the actual ones delivered by the {@link BatchCallMonitor} during execution. * An immediate solution would be to override the <code>equals</code> method * of {@link DSCallFeedbackEvent} and {@link DSCallOutcomeEvent}, but this is * not desirable because, in general, identity must be maintained for events * — even though two event object may have exaclty the same state, they * represent different occurrences. * This general rule doesn't apply in our test set up though — an event * specified in set up mode should be considered the same as one received in * verification mode if they hold the same state. For this reason, this class * wraps the events specified in set up mode and those received in verification * mode with equality wrappers that consider two objects equal if they hold the * same state. Obviously enough for this to be sound, the test must be * designed such that no two events specified in set up mode carry the same * state. * * @author Jean-Marie Burel      * <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a> * @author <br>Andrea Falconi      * <a href="mailto:a.falconi@dundee.ac.uk"> * a.falconi@dundee.ac.uk</a> * @version 2.2 * <small> * (<b>Internal version:</b> $Revision$ $Date$) * </small> * @since OME2.2 */ public class MockDSCallEventListener extends MockAgentEventListener { /** * Tells whether <code>p1</code> and <code>p2</code> may be considered to * be the same object. * * @param p1 The first object. * @param p2 The second object. * @return <code>true</code> if the passed objects hold the same state, * <code>false</code> otherwise. */ private static boolean isSameObject(Object p1, Object p2) { boolean b = (p1 == p2); if (!b) { if (p1 == null) //Then p2 can't be null. b = false; else //Both p1 and p2 are not null. b = p2.equals(p1); } return b; } //Equality wrapper for DSCallFeedbackEvent. private class FeedbackWrapper extends AgentEvent { DSCallFeedbackEvent event; FeedbackWrapper(DSCallFeedbackEvent event) { this.event = event; } public boolean equals(Object o) { if (o == null || !(o instanceof FeedbackWrapper)) return false; DSCallFeedbackEvent x = ((FeedbackWrapper) o).event; if (x.getPercentDone() == event.getPercentDone() && isSameObject(x.getStatus(), event.getStatus())) return true; return false; } public String toString() { return "FE[perc: "+event.getPercentDone()+", status: "+ event.getStatus()+"]"; } } //Equality wrapper for DSCallOutcomeEvent. private class OutcomeWrapper extends AgentEvent { DSCallOutcomeEvent event; OutcomeWrapper(DSCallOutcomeEvent event) { this.event = event; } public boolean equals(Object o) { if (o == null || !(o instanceof OutcomeWrapper)) return false; DSCallOutcomeEvent x = ((OutcomeWrapper) o).event; if (x.wasCancelled() == event.wasCancelled() && isSameObject(x.getException(), event.getException()) && isSameObject(x.getResult(), event.getResult())) return true; return false; } public String toString() { return "OE[cancelled: "+event.wasCancelled()+", exc: "+ event.getException()+", result: "+ event.getResult()+"]"; } } private AgentEvent convert(AgentEvent ae) { if (ae != null) { if (ae instanceof DSCallFeedbackEvent) ae = new FeedbackWrapper((DSCallFeedbackEvent) ae); else if (ae instanceof DSCallOutcomeEvent) ae = new OutcomeWrapper((DSCallOutcomeEvent) ae); } return ae; } //Used in set up mode. If re != null, then it will be //thrown in verification mode. public void eventFired(AgentEvent ae, RuntimeException re) { super.eventFired(convert(ae), re); } //Used in verification mode. public void eventFired(AgentEvent ae) { super.eventFired(convert(ae)); } }