001// Copyright 2007, 2008, 2010, 2011 The Apache Software Foundation
002//
003// Licensed under the Apache License, Version 2.0 (the "License");
004// you may not use this file except in compliance with the License.
005// You may obtain a copy of the License at
006//
007//     http://www.apache.org/licenses/LICENSE-2.0
008//
009// Unless required by applicable law or agreed to in writing, software
010// distributed under the License is distributed on an "AS IS" BASIS,
011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012// See the License for the specific language governing permissions and
013// limitations under the License.
014
015package org.apache.tapestry5.internal.services;
016
017import org.apache.tapestry5.ComponentEventCallback;
018import org.apache.tapestry5.TapestryMarkers;
019import org.apache.tapestry5.ioc.Invokable;
020import org.apache.tapestry5.ioc.OperationTracker;
021import org.apache.tapestry5.runtime.Event;
022import org.slf4j.Logger;
023
024@SuppressWarnings("all")
025public class EventImpl implements Event
026{
027    private boolean aborted;
028
029    private String methodDescription;
030
031    private final ComponentEventCallback handler;
032
033    private final Logger logger;
034
035    private final boolean debugEnabled;
036
037    protected final OperationTracker tracker;
038
039    /**
040     * @param handler informed of return values from methods, deems when the event is aborted
041     * @param logger  used to log method invocations
042     * @param tracker
043     */
044    public EventImpl(ComponentEventCallback handler, Logger logger, OperationTracker tracker)
045    {
046        this.tracker = tracker;
047        assert handler != null;
048        this.handler = handler;
049        this.logger = logger;
050
051        // TAP5-471: Thousands of calls to isDebugEnabled() do add up
052        debugEnabled = logger.isDebugEnabled();
053    }
054
055    public boolean isAborted()
056    {
057        return aborted;
058    }
059
060    public void setMethodDescription(String methodDescription)
061    {
062        if (debugEnabled)
063            logger.debug(TapestryMarkers.EVENT_HANDLER_METHOD, "Invoking: " + methodDescription);
064
065        this.methodDescription = methodDescription;
066    }
067
068    @SuppressWarnings("unchecked")
069    public boolean storeResult(final Object result)
070    {
071        // Given that this method is *only* invoked from code
072        // that is generated at runtime and proven to be correct,
073        // this should never, ever happen. But what the hell,
074        // let's check anyway.
075
076        if (aborted)
077        {
078            throw new IllegalStateException(String.format("Can not store result from invoking method %s, because an event result value has already been obtained from some other event handler method.", methodDescription));
079        }
080
081
082        if (result != null)
083        {
084            boolean handleResult =
085                    tracker.invoke("Handling result from method " + methodDescription + '.', new Invokable<Boolean>()
086                    {
087                        public Boolean invoke()
088                        {
089                            return handler.handleResult(result);
090                        }
091                    });
092
093            aborted |= handleResult;
094        }
095
096        return aborted;
097    }
098
099    protected String getMethodDescription()
100    {
101        return methodDescription;
102    }
103}