View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.orchestra.annotation;
20  
21  import java.lang.reflect.Method;
22  import java.util.HashMap;
23  import java.util.Map;
24  
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  import org.apache.myfaces.orchestra.conversation.annotations.ConversationName;
28  import org.apache.myfaces.orchestra.conversation.annotations.ConversationRequire;
29  import org.apache.myfaces.orchestra.viewController.annotations.InitView;
30  import org.apache.myfaces.orchestra.viewController.annotations.PreProcess;
31  import org.apache.myfaces.orchestra.viewController.annotations.PreRenderView;
32  import org.apache.myfaces.orchestra.viewController.annotations.ViewController;
33  
34  /**
35   * Inspects a class for Orchestra annotations, and if found then caches this information
36   * for later access.
37   * <p>
38   * The processing of Class objects is expected to happen only at application startup.
39   * <p>
40   * Note that annotation scanning is driven by the dependency-injection framework, i.e.
41   * only classes declared to the framework are scanned. 
42   */
43  public class AnnotationInfoManager
44  {
45      private final Log log = LogFactory.getLog(AnnotationInfoManager.class);
46  
47      private Map<String, AnnotationInfo> annotationsInfoByName = new HashMap<String, AnnotationInfo>();
48      private Map<String, AnnotationInfo> annotationsInfoByViewId = new HashMap<String, AnnotationInfo>();
49  
50      protected void addAnnotationsInfo(AnnotationInfo annotationInfo)
51      {
52          if (annotationsInfoByName.containsKey(annotationInfo.getBeanName()))
53          {
54              log.info("duplicate bean definition: " + annotationInfo.getBeanName());
55          }
56  
57          annotationsInfoByName.put(annotationInfo.getBeanName(), annotationInfo);
58  
59          ViewController viewController = annotationInfo.getViewController();
60          if (viewController != null)
61          {
62              String[] viewIds = viewController.viewIds();
63              for (int i = 0; i<viewIds.length; i++)
64              {
65                  String viewId = viewIds[i];
66  
67                  if (annotationsInfoByViewId.containsKey(annotationInfo.getBeanName()))
68                  {
69                      log.info("duplicate viewId definition: " + annotationInfo.getBeanName());
70                  }
71  
72                  annotationsInfoByViewId.put(viewId, annotationInfo);
73              }
74          }
75      }
76  
77      public AnnotationInfo getAnnotationInfoByBeanName(String beanName)
78      {
79          return annotationsInfoByName.get(beanName);
80      }
81  
82      public AnnotationInfo getAnnotationInfoByViewId(String viewId)
83      {
84          return annotationsInfoByViewId.get(viewId);
85      }
86  
87      /**
88       * Inspect the provided class for annotations, and if found then cache the info
89       * keyed by the specified beanName.
90       * <p>
91       * Currently the class-level annotations looked for are:
92       * <ul>
93       * <li>ConversationName
94       * <li>ConversationRequire
95       * <li>ViewController
96       * </ul>
97       * <p>
98       * If the ViewController annotation is present, then the class is also scanned
99       * for related annotations on class methods.
100      */
101     public void processBeanAnnotations(String beanName, Class<?> clazz)
102     {
103         ConversationName conversationName = (ConversationName) clazz.getAnnotation(ConversationName.class);
104         ViewController viewController = (ViewController) clazz.getAnnotation(ViewController.class);
105         ConversationRequire conversationRequire = (ConversationRequire) clazz.getAnnotation(ConversationRequire.class);
106 
107         if (conversationName == null && viewController == null && conversationRequire == null)
108         {
109             return;
110         }
111 
112         AnnotationInfo annotationInfo = new AnnotationInfo(beanName, clazz);
113         annotationInfo.setConversationName(conversationName);
114         annotationInfo.setConversationRequire(conversationRequire);
115         
116         if (viewController != null)
117         {
118             annotationInfo.setViewController(viewController);
119             Method[] methods = clazz.getMethods();
120             for (int i = 0; i<methods.length; i++)
121             {
122                 Method method = methods[i];
123                 if (method.isAnnotationPresent(InitView.class))
124                 {
125                     annotationInfo.setInitViewMethod(method);
126                 }
127                 if (method.isAnnotationPresent(PreProcess.class))
128                 {
129                     annotationInfo.setPreProcessMethod(method);
130                 }
131                 if (method.isAnnotationPresent(PreRenderView.class))
132                 {
133                     annotationInfo.setPreRenderViewMethod(method);
134                 }
135             }
136         }
137 
138         addAnnotationsInfo(annotationInfo);
139     }
140 }