001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.apache.commons.proxy2.interceptor;
019
020import java.io.Serializable;
021import java.util.List;
022import java.util.concurrent.CopyOnWriteArrayList;
023
024import org.apache.commons.lang3.tuple.ImmutablePair;
025import org.apache.commons.lang3.tuple.Pair;
026import org.apache.commons.proxy2.Interceptor;
027import org.apache.commons.proxy2.Invocation;
028import org.apache.commons.proxy2.interceptor.matcher.InvocationMatcher;
029
030/**
031 * A {@link SwitchInterceptor} maintains a list of
032 * {@link org.apache.commons.proxy2.interceptor.matcher.InvocationMatcher}/{@link Interceptor} pairs. Each invocation
033 * will be checked against the registered InvocationMatchers. If one matches the current invocation, then the
034 * corresponding Interceptor will be called. If no InvocationMatchers match, the
035 * {@link org.apache.commons.proxy2.Invocation#proceed()} method is called with no interception.
036 */
037public class SwitchInterceptor implements Interceptor, Serializable
038{
039    //******************************************************************************************************************
040    // Fields
041    //******************************************************************************************************************
042
043    private static final long serialVersionUID = 1L;
044
045    private final List<Pair<InvocationMatcher, Interceptor>> cases
046        = new CopyOnWriteArrayList<Pair<InvocationMatcher, Interceptor>>();
047
048    //******************************************************************************************************************
049    // Constructors
050    //******************************************************************************************************************
051
052    public SwitchInterceptor()
053    {
054    }
055
056    //******************************************************************************************************************
057    // Interceptor Implementation
058    //******************************************************************************************************************
059
060    @Override
061    public Object intercept(Invocation invocation) throws Throwable
062    {
063        for (Pair<InvocationMatcher, Interceptor> currentCase : cases)
064        {
065            if (currentCase.getLeft().matches(invocation))
066            {
067                return currentCase.getRight().intercept(invocation);
068            }
069        }
070        return invocation.proceed();
071    }
072
073    //******************************************************************************************************************
074    // Other Methods
075    //******************************************************************************************************************
076
077    public CaseBuilder when(InvocationMatcher matcher)
078    {
079        return new CaseBuilder(matcher);
080    }
081
082    //******************************************************************************************************************
083    // Inner Classes
084    //******************************************************************************************************************
085
086    public class CaseBuilder
087    {
088        private final InvocationMatcher matcher;
089
090        private CaseBuilder(InvocationMatcher matcher)
091        {
092            this.matcher = matcher;
093        }
094
095        public SwitchInterceptor then(Interceptor interceptor)
096        {
097            cases.add(new ImmutablePair<InvocationMatcher, Interceptor>(matcher, interceptor));
098            return SwitchInterceptor.this;
099        }
100    }
101}