    001// Copyright 2012 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.ioc.internal.services;
    016
    017import org.apache.tapestry5.ioc.MethodAdviceReceiver;
    018import org.apache.tapestry5.ioc.OperationTracker;
    019import org.apache.tapestry5.ioc.annotations.Operation;
    020import org.apache.tapestry5.ioc.annotations.PreventServiceDecoration;
    021import org.apache.tapestry5.ioc.internal.util.InternalUtils;
    022import org.apache.tapestry5.ioc.services.OperationAdvisor;
    023import org.apache.tapestry5.plastic.MethodAdvice;
    024import org.apache.tapestry5.plastic.MethodInvocation;
    025
    026import java.lang.reflect.Method;
    027
    028@PreventServiceDecoration
    029public class OperationAdvisorImpl implements OperationAdvisor
    030{
    031    private final OperationTracker tracker;
    032
    033    public OperationAdvisorImpl(OperationTracker tracker)
    034    {
    035        this.tracker = tracker;
    036    }
    037
    038    private Runnable toRunnable(final MethodInvocation invocation)
    039    {
    040        return new Runnable()
    041        {
    042            @Override
    043            public void run()
    044            {
    045                invocation.proceed();
    046            }
    047        };
    048    }
    049
    050    private class SimpleAdvice implements MethodAdvice
    051    {
    052        private final String description;
    053
    054        SimpleAdvice(String description)
    055        {
    056            this.description = description;
    057        }
    058
    059        @Override
    060        public void advise(MethodInvocation invocation)
    061        {
    062            tracker.run(description, toRunnable(invocation));
    063        }
    064    }
    065
    066    private class FormattedAdvice implements MethodAdvice
    067    {
    068        private final String format;
    069
    070        FormattedAdvice(String format)
    071        {
    072            this.format = format;
    073        }
    074
    075        @Override
    076        public void advise(MethodInvocation invocation)
    077        {
    078            Object[] parameters = extractParameters(invocation);
    079
    080            String description = String.format(format, parameters);
    081
    082            tracker.run(description, toRunnable(invocation));
    083        }
    084
    085        private Object[] extractParameters(MethodInvocation invocation)
    086        {
    087            int count = invocation.getMethod().getParameterTypes().length;
    088
    089            Object[] result = new Object[count];
    090
    091            for (int i = 0; i < count; i++)
    092            {
    093                result[i] = invocation.getParameter(i);
    094            }
    095
    096            return result;
    097        }
    098    }
    099
    100    @Override
    101    public void addOperationAdvice(MethodAdviceReceiver receiver)
    102    {
    103        for (Method m : receiver.getInterface().getMethods())
    104        {
    105
    106            Operation annotation = receiver.getMethodAnnotation(m, Operation.class);
    107
    108            if (annotation != null)
    109            {
    110                String value = annotation.value();
    111
    112                receiver.adviseMethod(m, createAdvice(value));
    113            }
    114        }
    115    }
    116
    117    @Override
    118    public MethodAdvice createAdvice(String description)
    119    {
    120        assert InternalUtils.isNonBlank(description);
    121
    122        if (description.contains("%"))
    123        {
    124            return new FormattedAdvice(description);
    125        }
    126
    127        return new SimpleAdvice(description);
    128    }
    129}