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}