Coverage Report - org.apache.commons.functor.core.algorithm.RecursiveEvaluation
 
Classes in this File Line Coverage Branch Coverage Complexity
RecursiveEvaluation
65%
15/23
42%
6/14
3
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  *
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.apache.commons.functor.core.algorithm;
 18  
 
 19  
 import java.io.Serializable;
 20  
 
 21  
 import org.apache.commons.functor.Function;
 22  
 
 23  
 /**
 24  
  * Tail recursion for {@link Function functions}. If the {@link Function}
 25  
  * returns another function of type <code>functionType</code>, that function
 26  
  * is executed. Functions are executed until a non function value or a
 27  
  * function of a type other than that expected is returned.
 28  
  */
 29  
 public class RecursiveEvaluation implements Function<Object>, Serializable {
 30  
     /**
 31  
      * serialVersionUID declaration.
 32  
      */
 33  
     private static final long serialVersionUID = -7992078213921938619L;
 34  
     private final Class<?> functionType;
 35  
     private Function<?> function;
 36  
 
 37  
     /**
 38  
      * Create a new RecursiveEvaluation. Recursion will continue while the
 39  
      * returned value is of the same runtime class as <code>function</code>.
 40  
      * @param function initial, potentially recursive Function
 41  
      */
 42  
     public RecursiveEvaluation(Function<?> function) {
 43  96
         this(function, getClass(function));
 44  96
     }
 45  
 
 46  
     /**
 47  
      * Create a new RecursiveEvaluation.
 48  
      * @param function initial, potentially recursive Function
 49  
      * @param functionType as long as result is an instance, keep processing.
 50  
      */
 51  96
     public RecursiveEvaluation(Function<?> function, Class<?> functionType) {
 52  96
         if (function == null) {
 53  0
             throw new IllegalArgumentException("Function argument was null");
 54  
         }
 55  96
         if (functionType == null || !Function.class.isAssignableFrom(functionType)) {
 56  0
             throw new IllegalArgumentException(Function.class + " is not assignable from " + functionType);
 57  
         }
 58  96
         this.function = function;
 59  96
         this.functionType = functionType;
 60  96
     }
 61  
 
 62  
     /**
 63  
      * {@inheritDoc}
 64  
      */
 65  
     public final Object evaluate() {
 66  96
         Object result = null;
 67  
         // if the function returns another function, execute it. stop executing
 68  
         // when the result is not of the expected type.
 69  
         while (true) {
 70  492
             result = function.evaluate();
 71  492
             if (functionType.isInstance(result)) {
 72  396
                 function = (Function<?>) result;
 73  396
                 continue;
 74  
             } else {
 75  
                 break;
 76  
             }
 77  
         }
 78  96
         return result;
 79  
     }
 80  
 
 81  
     /**
 82  
      * {@inheritDoc}
 83  
      */
 84  
     public final boolean equals(Object obj) {
 85  0
         if (obj == this) {
 86  0
             return true;
 87  
         }
 88  0
         if (!(obj instanceof RecursiveEvaluation)) {
 89  0
             return false;
 90  
         }
 91  0
         return ((RecursiveEvaluation) obj).function.equals(function);
 92  
     }
 93  
 
 94  
     /**
 95  
      * {@inheritDoc}
 96  
      */
 97  
     public int hashCode() {
 98  0
         return "RecursiveEvaluation".hashCode() << 2 ^ function.hashCode();
 99  
     }
 100  
 
 101  
     /**
 102  
      * Get the class of the specified object, or <code>null</code> if <code>o</code> is <code>null</code>.
 103  
      * @param o Object to check
 104  
      * @return Class found
 105  
      */
 106  
     private static <T> Class<?> getClass(Function<?> f) {
 107  96
         return f == null ? null : f.getClass();
 108  
     }
 109  
 }