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.matcher.argument;
019
020import org.apache.commons.lang3.ObjectUtils;
021import org.apache.commons.lang3.StringUtils;
022import org.apache.commons.lang3.Validate;
023import org.apache.commons.proxy2.interceptor.matcher.ArgumentMatcher;
024
025public final class ArgumentMatcherUtils
026{
027    //******************************************************************************************************************
028    // Static Methods
029    //******************************************************************************************************************
030
031    public static <T> ArgumentMatcher<T> any()
032    {
033        return new AnyMatcher<T>();
034    }
035
036    public static ArgumentMatcher<String> endsWith(String suffix)
037    {
038        return new EndsWithMatcher(Validate.notNull(suffix));
039    }
040
041    public static <T> ArgumentMatcher<T> eq(final T value)
042    {
043        return new EqualsMatcher<T>(value);
044    }
045
046    public static <C extends Comparable<C>> ArgumentMatcher<C> gt(C comparable)
047    {
048        return new GreaterThanMatcher<C>(comparable);
049    }
050
051    public static <C extends Comparable<C>> ArgumentMatcher<C> gte(C comparable)
052    {
053        return new GreaterThanOrEqualMatcher<C>(comparable);
054    }
055
056    public static <T> ArgumentMatcher<T> isA(final Class<?> type)
057    {
058        return new InstanceOfMatcher<T>(type);
059    }
060
061    public static <T> ArgumentMatcher<T> isNull()
062    {
063        return new IsNullMatcher<T>();
064    }
065
066    public static <C extends Comparable<C>> ArgumentMatcher<C> lt(C comparable)
067    {
068        return new LessThanMatcher<C>(comparable);
069    }
070
071    public static <C extends Comparable<C>> ArgumentMatcher<C> lte(C comparable)
072    {
073        return new LessThanOrEqualMatcher<C>(comparable);
074    }
075
076    public static ArgumentMatcher<String> matches(String regex)
077    {
078        return new RegexMatcher(Validate.notNull(regex));
079    }
080
081    public static <T> ArgumentMatcher<T> notNull()
082    {
083        return new NotNullMatcher<T>();
084    }
085
086    public static ArgumentMatcher<String> startsWith(String prefix)
087    {
088        return new StartsWithMatcher(Validate.notNull(prefix));
089    }
090
091    //******************************************************************************************************************
092    // Constructors
093    //******************************************************************************************************************
094
095    private ArgumentMatcherUtils()
096    {
097
098    }
099
100    //******************************************************************************************************************
101    // Inner Classes
102    //******************************************************************************************************************
103
104    private static final class AnyMatcher<T> implements ArgumentMatcher<T>
105    {
106        @Override
107        public boolean matches(T argument)
108        {
109            return true;
110        }
111    }
112
113    private abstract static class ComparatorMatcher<C extends Comparable<C>> implements ArgumentMatcher<C>
114    {
115        private final C comparable;
116
117        protected ComparatorMatcher(C comparable)
118        {
119            this.comparable = Validate.notNull(comparable);
120        }
121
122        protected abstract boolean evaluate(int comparison);
123
124        @Override
125        public boolean matches(C argument)
126        {
127            if (argument == null)
128            {
129                return false;
130            }
131            final int comparison = (comparable).compareTo(argument);
132            return evaluate(comparison);
133        }
134    }
135
136    public static class EndsWithMatcher implements ArgumentMatcher<String>
137    {
138        private final String suffix;
139
140        public EndsWithMatcher(String suffix)
141        {
142            this.suffix = suffix;
143        }
144
145        @Override
146        public boolean matches(String argument)
147        {
148            return StringUtils.endsWith(argument, suffix);
149        }
150    }
151
152    private static final class EqualsMatcher<T> implements ArgumentMatcher<T>
153    {
154        private final T value;
155
156        public EqualsMatcher(T value)
157        {
158            this.value = value;
159        }
160
161        @SuppressWarnings("deprecation")
162        @Override
163        public boolean matches(T argument)
164        {
165            return ObjectUtils.equals(argument, value);
166        }
167    }
168
169    private static final class GreaterThanMatcher<C extends Comparable<C>> extends ComparatorMatcher<C>
170    {
171        private GreaterThanMatcher(C comparable)
172        {
173            super(comparable);
174        }
175
176        @Override
177        protected boolean evaluate(int comparison)
178        {
179            return comparison < 0;
180        }
181    }
182
183    private static final class GreaterThanOrEqualMatcher<C extends Comparable<C>> extends ComparatorMatcher<C>
184    {
185        private GreaterThanOrEqualMatcher(C comparable)
186        {
187            super(comparable);
188        }
189
190        @Override
191        protected boolean evaluate(int comparison)
192        {
193            return comparison <= 0;
194        }
195    }
196
197    private static final class InstanceOfMatcher<T> implements ArgumentMatcher<T>
198    {
199        private final Class<?> type;
200
201        public InstanceOfMatcher(Class<?> type)
202        {
203            this.type = Validate.notNull(type, "type");
204        }
205
206        @Override
207        public boolean matches(T argument)
208        {
209            return type.isInstance(argument);
210        }
211    }
212
213    private static final class IsNullMatcher<T> implements ArgumentMatcher<T>
214    {
215        @Override
216        public boolean matches(T argument)
217        {
218            return argument == null;
219        }
220    }
221
222    private static final class LessThanMatcher<C extends Comparable<C>> extends ComparatorMatcher<C>
223    {
224        private LessThanMatcher(C comparable)
225        {
226            super(comparable);
227        }
228
229        @Override
230        protected boolean evaluate(int comparison)
231        {
232            return comparison > 0;
233        }
234    }
235
236    private static final class LessThanOrEqualMatcher<C extends Comparable<C>> extends ComparatorMatcher<C>
237    {
238        private LessThanOrEqualMatcher(C comparable)
239        {
240            super(comparable);
241        }
242
243        @Override
244        protected boolean evaluate(int comparison)
245        {
246            return comparison >= 0;
247        }
248    }
249
250    private static final class NotNullMatcher<T> implements ArgumentMatcher<T>
251    {
252        @Override
253        public boolean matches(T argument)
254        {
255            return argument != null;
256        }
257    }
258
259    public static class RegexMatcher implements ArgumentMatcher<String>
260    {
261        private final String regex;
262
263        public RegexMatcher(String regex)
264        {
265            this.regex = regex;
266        }
267
268        @Override
269        public boolean matches(String argument)
270        {
271            return argument != null && argument.matches(regex);
272        }
273    }
274
275    private static final class StartsWithMatcher implements ArgumentMatcher<String>
276    {
277        private final String prefix;
278
279        private StartsWithMatcher(String prefix)
280        {
281            this.prefix = prefix;
282        }
283
284        @Override
285        public boolean matches(String argument)
286        {
287            return StringUtils.startsWith(argument, prefix);
288        }
289    }
290}