001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 *
010 *        http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License.
018 */
019
020package org.apache.isis.core.progmodel.facets.actions.invoke.event;
021
022import java.lang.reflect.Field;
023import java.lang.reflect.Method;
024
025import org.apache.isis.applib.FatalException;
026import org.apache.isis.applib.Identifier;
027import org.apache.isis.applib.services.eventbus.ActionInvokedEvent;
028import org.apache.isis.applib.services.eventbus.CollectionAddedToEvent;
029import org.apache.isis.applib.services.eventbus.EventBusService;
030import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
031import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
032import org.apache.isis.core.metamodel.adapter.util.AdapterUtils;
033import org.apache.isis.core.metamodel.facetapi.FacetHolder;
034import org.apache.isis.core.metamodel.facets.ImperativeFacet;
035import org.apache.isis.core.metamodel.facets.actions.event.PostsActionInvokedEventFacet;
036import org.apache.isis.core.metamodel.runtimecontext.RuntimeContext;
037import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
038import org.apache.isis.core.metamodel.spec.ObjectSpecification;
039import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
040import org.apache.isis.core.progmodel.facets.actions.invoke.ActionInvocationFacetViaMethod;
041
042public class PostsActionInvokedEventFacetAnnotation 
043        extends ActionInvocationFacetViaMethod 
044        implements ImperativeFacet, PostsActionInvokedEventFacet {
045        
046        private ServicesInjector servicesInjector;
047        private Class<? extends ActionInvokedEvent<?>> eventType;
048
049        private EventBusService eventBusService;
050        private boolean searchedForEventBusService = false;
051        
052    public PostsActionInvokedEventFacetAnnotation(
053            final Method method, 
054            final ObjectSpecification onType, 
055            final ObjectSpecification returnType, 
056            final FacetHolder holder, 
057            final RuntimeContext runtimeContext, 
058            final AdapterManager adapterManager, 
059            final ServicesInjector servicesInjector,
060                        final Class<? extends ActionInvokedEvent<?>> eventType) {
061        super(method, onType, returnType, holder, runtimeContext, adapterManager, servicesInjector);
062        
063        this.servicesInjector = servicesInjector;
064        
065        this.eventType = eventType;
066    }
067
068    @Override
069    public ObjectAdapter invoke(
070            final ObjectAction owningAction, 
071            final ObjectAdapter targetAdapter, 
072            final ObjectAdapter[] arguments) {
073
074        final InvocationResult invocationResult = this.internalInvoke(owningAction, targetAdapter, arguments);
075        
076        // Perhaps the Action was not properly invoked (i.e. an exception was raised).
077        if (invocationResult.getWhetherInvoked()) {
078                // If invoked, then send the ActionInvokedEvent to the EventBus.
079                postEvent(owningAction, targetAdapter, arguments);
080        }
081        
082        return invocationResult.getAdapter();
083    }
084    
085        @SuppressWarnings({ "rawtypes" })
086        private void postEvent(
087            final ObjectAction owningAction, 
088            final ObjectAdapter targetAdapter, 
089            final ObjectAdapter[] argumentAdapters) {
090            
091                try {
092                        final Class type = eventType;
093                        Identifier actionIdentifier = owningAction.getIdentifier();
094                final Object source = AdapterUtils.unwrap(targetAdapter);
095                        final Object[] arguments = AdapterUtils.unwrap(argumentAdapters);
096            @SuppressWarnings("unchecked")
097            final ActionInvokedEvent<?> event = org.apache.isis.core.metamodel.facets.actions.event.PostsActionInvokedEventFacet.Util.newEvent(type, source, actionIdentifier, arguments);
098                        getEventBusService().post(event);
099                } catch (Exception e) {
100                        throw new FatalException(e);
101                }
102        }
103
104        private EventBusService getEventBusService() {
105                if (!searchedForEventBusService) {
106                        eventBusService = this.servicesInjector.lookupService(EventBusService.class);
107                }
108                searchedForEventBusService = true;
109                return eventBusService;
110        }
111
112}