    001// Copyright 2006, 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.EventContext;
    019import org.apache.tapestry5.internal.structure.ComponentPageElementResources;
    020import org.apache.tapestry5.model.ComponentModel;
    021import org.apache.tapestry5.runtime.ComponentEvent;
    022import org.slf4j.Logger;
    023
    024public class ComponentEventImpl extends EventImpl implements ComponentEvent
    025{
    026    private final String eventType;
    027
    028    private final String originatingComponentId;
    029
    030    private final EventContext context;
    031
    032    private final ComponentPageElementResources elementResources;
    033
    034    private final boolean exactParameterCountMatch;
    035
    036    /**
    037     * @param eventType
    038     *            non blank string used to identify the type of event that was triggered
    039     * @param originatingComponentId
    040     *            the id of the component that triggered the event
    041     * @param context
    042     *            provides access to parameter values
    043     * @param handler
    044     *            invoked when a non-null return value is obtained from an event handler method
    045     * @param elementResources
    046     *            provides access to common resources and services
    047     * @param exactParameterCountMatch
    048     *            the {@link org.apache.tapestry5.ioc.annotations.Symbol} indicating an exact match
    049     *            on parameter count in the {@link EventContext}.
    050     * @param model
    051     *            the {@link ComponentModel} of the component originating the event.
    052     * @param logger
    053     *            used to log method invocations
    054     */
    055    public ComponentEventImpl(String eventType, String originatingComponentId, EventContext context,
    056            ComponentEventCallback handler, ComponentPageElementResources elementResources,
    057            boolean exactParameterCountMatch, ComponentModel model, Logger logger)
    058    {
    059        super(handler, logger, elementResources);
    060
    061        this.eventType = eventType;
    062        this.originatingComponentId = originatingComponentId;
    063        this.elementResources = elementResources;
    064        this.context = context;
    065        this.exactParameterCountMatch = exactParameterCountMatch && !model.handleActivationEventContext();
    066    }
    067
    068    @Override
    069    public String toString()
    070    {
    071        return String.format("ComponentEvent[%s from %s]", eventType, originatingComponentId.length() == 0 ? "(self)"
    072                : originatingComponentId);
    073    }
    074
    075    public boolean matches(String eventType, String componentId, int parameterCount)
    076    {
    077        if (isAborted())
    078            return false;
    079
    080        boolean parameterCountMatch = exactParameterCountMatch ?
    081                context.getCount() == parameterCount : context.getCount() >= parameterCount;
    082
    083        return this.eventType.equalsIgnoreCase(eventType) && parameterCountMatch
    084                 && (originatingComponentId.equalsIgnoreCase(componentId) || componentId.equals(""));
    085    }
    086
    087    @SuppressWarnings("unchecked")
    088    public Object coerceContext(int index, String desiredTypeName)
    089    {
    090        if (index >= context.getCount())
    091            throw new IllegalArgumentException(String.format("Method %s has more parameters than there are context values for this component event.", getMethodDescription()));
    092        try
    093        {
    094            Class desiredType = elementResources.toClass(desiredTypeName);
    095
    096            return context.get(desiredType, index);
    097        }
    098        catch (Exception ex)
    099        {
    100            throw new IllegalArgumentException(String.format("Exception in method %s, parameter #%d: %s", getMethodDescription(), index + 1, ex), ex);
    101        }
    102    }
    103
    104    public Object[] getContext()
    105    {
    106        int count = context.getCount();
    107
    108        Object[] result = new Object[count];
    109
    110        for (int i = 0; i < count; i++)
    111            result[i] = context.get(Object.class, i);
    112
    113        return result;
    114    }
    115
    116    public EventContext getEventContext()
    117    {
    118        return context;
    119    }
    120}