View Javadoc

1   /*
2    * Copyright 2013 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.callbackparams.internal.template;
17  
18  import java.lang.reflect.Method;
19  import java.util.IdentityHashMap;
20  import java.util.Map;
21  import org.callbackparams.support.ClassWrapper;
22  import org.callbackparams.support.DefaultValue;
23  import org.callbackparams.support.JdkVersion;
24  
25  /**
26   * Digests all callback return-values during the overall callback-invocation and
27   * chooses what value to return from the overall callback-invocation.
28   * Also keeps track of which arguments to pass to the callback.
29   *
30   * @author Henrik Kaipe
31   */
32  public class ReturnValueDigester {
33  
34      private static final ClassWrapper implClass =
35              JdkVersion.compatibleImplementationOf(ReturnValueDigester.class);
36  
37      private static final Object
38              NO_RETURN_VALUE_HAS_BEEN_DIGESTED_YET = new Object();
39  
40      private Class returnType;
41      private boolean returnTypeAndFirstArgumentTypeAreSame;
42      private Object[] args;
43      private Object currentReturnValue = NO_RETURN_VALUE_HAS_BEEN_DIGESTED_YET;
44      private Map returnValuesSoFar = new IdentityHashMap();
45  
46      static ReturnValueDigester newInstance(Method m, Object[] args) {
47          ReturnValueDigester instance =
48                  (ReturnValueDigester) implClass.newInstance();
49          instance.init(m, args);
50          return instance;
51      }
52  
53      /**
54       * Not for direct use - use factory-method
55       * {@link #newInstance(java.lang.reflect.Method, java.lang.Object[])}
56       * instead!
57       */
58      protected ReturnValueDigester() {}
59  
60      private void init(Method m, Object[] args) {
61          this.returnType = m.getReturnType();
62          this.returnTypeAndFirstArgumentTypeAreSame =
63                  returnTypeAndFirstArgumentTypeAreSame(m);
64          this.args = null == args ? null : (Object[]) args.clone();
65          this.currentReturnValue = this.returnTypeAndFirstArgumentTypeAreSame
66                  ? args[0]
67                  : NO_RETURN_VALUE_HAS_BEEN_DIGESTED_YET;
68      }
69  
70      void digestNext(Object callbackRecordElement, Object returnValue) {
71          returnValuesSoFar.put(callbackRecordElement, returnValue);
72  
73          if (this.returnTypeAndFirstArgumentTypeAreSame) {
74              this.args[0] = this.currentReturnValue = returnValue;
75  
76          } else if (NO_RETURN_VALUE_HAS_BEEN_DIGESTED_YET == this.currentReturnValue
77                  || null == returnValue
78                  || returnValue.equals(this.currentReturnValue)) {
79              this.currentReturnValue = returnValue;
80  
81          } else {
82              this.currentReturnValue = DefaultValue.forType(this.returnType);
83          }
84      }
85  
86      void updateLatestCallbackResultsInCallbackControlPanel(Map latestResults) {
87          latestResults.clear();
88          latestResults.putAll(returnValuesSoFar);
89      }
90  
91      Object returnValue() {
92          return NO_RETURN_VALUE_HAS_BEEN_DIGESTED_YET == currentReturnValue
93                  ? DefaultValue.forType(this.returnType)
94                  : this.currentReturnValue;
95      }
96  
97      protected boolean returnTypeAndFirstArgumentTypeAreSame(Method m) {
98          Class[] methodParams = m.getParameterTypes();
99          return 1 <= methodParams.length
100                 && m.getReturnType() == methodParams[0];
101     }
102 
103     Object[] getArguments() {
104         return this.args;
105     }
106 }