2009/05/20 - Apache Shale has been retired.

For more information, please explore the Attic.

Coverage Report - org.apache.shale.tiger.view.faces.ViewControllerCallbacks2
 
Classes in this File Line Coverage Branch Coverage Complexity
ViewControllerCallbacks2
100%
31/31
N/A
0
 
 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  
 
 18  
 package org.apache.shale.tiger.view.faces;
 19  
 
 20  
 import java.lang.reflect.InvocationTargetException;
 21  
 import java.lang.reflect.Method;
 22  
 import java.util.HashMap;
 23  
 import java.util.Map;
 24  
 import javax.faces.context.FacesContext;
 25  
 import org.apache.shale.tiger.view.Preprocess;
 26  
 import org.apache.shale.tiger.view.Prerender;
 27  
 import org.apache.shale.tiger.view.View;
 28  
 import org.apache.shale.view.ViewController;
 29  
 import org.apache.shale.view.faces.ViewControllerCallbacks;
 30  
 
 31  
 /**
 32  
  * <p>Utility class to perform the event callbacks specified by the
 33  
  * {@link ViewController} interface.  This version will call through
 34  
  * to ViewController methods if the bean class actually implements this
 35  
  * interface, or ituses annotations to identify the relevant methods.</p>
 36  
  *
 37  
  * <p><strong>NOTE</strong> - The annotated callback methods must be
 38  
  * public, and take no arguments.  They may exist on the class of the
 39  
  * instance being passed in, or be inherited from a superclass.</p>
 40  
  *
 41  
  * $Id: ViewControllerCallbacks2.java 465074 2006-10-17 22:05:53Z rahul $
 42  
  *
 43  
  * @since 1.0.1
 44  
  */
 45  20
 public class ViewControllerCallbacks2 extends ViewControllerCallbacks {
 46  
 
 47  
 
 48  
     // ------------------------------------------------------------ Constructors
 49  
 
 50  
 
 51  
     // ------------------------------------------------------ Instance Variables
 52  
 
 53  
 
 54  
     // ---------------------------------------------------------- Public Methods
 55  
 
 56  
 
 57  
     /**
 58  
      * <p>Perform the <code>preprocess</code> callback on the specified
 59  
      * instance.</p>
 60  
      *
 61  
      * @param instance Bean instance on which to perform this callback
 62  
      */
 63  
     public void preprocess(Object instance) {
 64  
 
 65  1
         if (instance instanceof ViewController) {
 66  
             try {
 67  
                 ((ViewController) instance).preprocess();
 68  
             } catch (Exception e) {
 69  
                 handleException(FacesContext.getCurrentInstance(), e);
 70  
             }
 71  
             return;
 72  
         }
 73  
 
 74  1
         Method method = method(instance, Preprocess.class);
 75  1
         if (method != null) {
 76  
             try {
 77  1
                 method.invoke(instance, new Object[0]);
 78  
             } catch (IllegalAccessException e) {
 79  
                 handleException(FacesContext.getCurrentInstance(), e);
 80  
             } catch (InvocationTargetException e) {
 81  
                 handleException(FacesContext.getCurrentInstance(), (Exception) e.getCause());
 82  1
             }
 83  
         }
 84  
 
 85  1
     }
 86  
 
 87  
 
 88  
     /**
 89  
      * <p>Perform the <code>prerender</code> callback on the specified
 90  
      * instance.</p>
 91  
      *
 92  
      * @param instance Bean instance on which to perform this callback
 93  
      */
 94  
     public void prerender(Object instance) {
 95  
 
 96  1
         if (instance instanceof ViewController) {
 97  
             try {
 98  
                 ((ViewController) instance).prerender();
 99  
             } catch (Exception e) {
 100  
                 handleException(FacesContext.getCurrentInstance(), e);
 101  
             }
 102  
             return;
 103  
         }
 104  
 
 105  1
         Method method = method(instance, Prerender.class);
 106  1
         if (method != null) {
 107  
             try {
 108  1
                 method.invoke(instance, new Object[0]);
 109  
             } catch (IllegalAccessException e) {
 110  
                 handleException(FacesContext.getCurrentInstance(), e);
 111  
             } catch (InvocationTargetException e) {
 112  
                 handleException(FacesContext.getCurrentInstance(), (Exception) e.getCause());
 113  1
             }
 114  
         }
 115  
 
 116  1
     }
 117  
 
 118  
 
 119  
     // --------------------------------------------------------- Private Methods
 120  
 
 121  
 
 122  
     /**
 123  
      * <p>The set of method annotations for callbacks of interest.</p>
 124  
      */
 125  1
     private static final Class[] annotations =
 126  
     { Preprocess.class, Prerender.class };
 127  
 
 128  
 
 129  
 
 130  
     /**
 131  
      * <p>Data structure to maintain information about annotated
 132  
      * methods.  In this map, the key is the Class being analyzed,
 133  
      * and the value is an inner map.  In the inner map, the key
 134  
      * is an Annotation class, and the value is the corresponding
 135  
      * Method instance.</p>
 136  
      */
 137  20
     private transient Map<Class,Map<Class,Method>> maps =
 138  
       new HashMap<Class,Map<Class,Method>>();
 139  
 
 140  
 
 141  
     /**
 142  
      * <p>Return the <code>Method</code> to be called for the specified
 143  
      * annotation on the specified instance, if any.  If there is no such
 144  
      * method, return <code>null</code>.</p>
 145  
      *
 146  
      * @param instance Instance on which callbacks will be performed
 147  
      * @param annotation Annotation for which to return a method
 148  
      */
 149  
     private Method method(Object instance, Class annotation) {
 150  
 
 151  
         // Does the underlying class implement the View annotation?
 152  
         // If not, exit early
 153  2
         Class clazz = instance.getClass();
 154  2
         if (clazz.getAnnotation(View.class) == null) {
 155  
             return null;
 156  
         }
 157  
 
 158  2
         synchronized (maps) {
 159  
 
 160  
             // If we have seen this Class already, simply return the
 161  
             // previously located Method (if any)
 162  2
             Map<Class,Method> map = maps.get(clazz);
 163  2
             if (map != null) {
 164  1
                 return map.get(annotation);
 165  
             }
 166  
 
 167  
             // Construct and cache a new Map identifying the
 168  
             // methods of interest for these callbacks
 169  1
             map = new HashMap<Class,Method>();
 170  1
             Method[] methods = clazz.getMethods();
 171  15
             for (int i = 0; i < methods.length; i++) {
 172  14
                 if (methods[i].getParameterTypes().length > 0) {
 173  3
                     continue;
 174  
                 }
 175  33
                 for (int j = 0; j < annotations.length; j++) {
 176  22
                     if (methods[i].getAnnotation(annotations[j]) != null) {
 177  2
                         map.put(annotations[j], methods[i]);
 178  
                     }
 179  
                 }
 180  
             }
 181  1
             maps.put(clazz, map);
 182  1
             return map.get(annotation);
 183  
 
 184  
         }
 185  
 
 186  
     }
 187  
 
 188  
 
 189  
 }