View Javadoc

1   /*
2    * Copyright 2011 FatWire Corporation. All Rights Reserved.
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  
17  package com.fatwire.gst.foundation.controller.action.support;
18  
19  import org.apache.commons.lang.StringUtils;
20  import org.apache.commons.logging.Log;
21  import org.apache.commons.logging.LogFactory;
22  import org.springframework.util.Assert;
23  
24  import COM.FutureTense.Cache.CacheManager;
25  import COM.FutureTense.Interfaces.ICS;
26  
27  import com.fatwire.gst.foundation.controller.action.Action;
28  import com.fatwire.gst.foundation.controller.action.ActionLocator;
29  import com.fatwire.gst.foundation.controller.action.Factory;
30  import com.fatwire.gst.foundation.controller.action.Injector;
31  
32  /**
33   * ActionLocator with support for {@link Injector} and a fall back
34   * {@link ActionLocator} in case this ActionLocator is not designed or
35   * configured to create an action for that name.
36   * <p/>
37   * Objects are created via a {@link Factory}, that can be obtained via the
38   * <tt>FactoryFactory</tt>.
39   * 
40   * @author Dolf Dijkstra
41   * @since Apr 27, 2011
42   */
43  public abstract class AbstractActionLocator implements ActionLocator {
44  
45      protected static final Log LOG = LogFactory.getLog(AbstractActionLocator.class.getPackage().getName());
46      /**
47       * The default fallbackActionLocator in case no action is found.
48       */
49      private ActionLocator fallbackActionLocator;
50      private Injector injector;
51  
52      public AbstractActionLocator() {
53          super();
54      }
55  
56      public AbstractActionLocator(Injector injector) {
57          super();
58          if (injector == null)
59              throw new IllegalArgumentException("injector should not be null");
60          this.injector = injector;
61      }
62  
63      public AbstractActionLocator(ActionLocator fallbackActionLocator, Injector injector) {
64          super();
65          this.fallbackActionLocator = fallbackActionLocator;
66          this.injector = injector;
67      }
68  
69      /**
70       * This method selects the Action by calling the
71       * {@link #doFindAction(ICS, String)} method. If that method returns an
72       * Action, that Action will be dependency injected with the
73       * {@link #getInjector()}, otherwise the {@link #getFallbackActionLocator()}
74       * is called.
75       * <p/>
76       * It is the fall back ActionLocator that should inject its Action with
77       * services.
78       * <p/>
79       * Contract is that either the {@link #doFindAction(ICS, String)} method or
80       * the {@link #getFallbackActionLocator()} returns an Action, so that this
81       * method never returns null.
82       * 
83       * @see com.fatwire.gst.foundation.controller.action.ActionLocator#getAction(COM.FutureTense.Interfaces.ICS,
84       *      java.lang.String)
85       */
86      public final Action getAction(final ICS ics, final String name) {
87          Action action = null;
88          action = doFindAction(ics, name);
89          /*
90           * the if/else construct might be confusing here. The contract is that
91           * only if doFindAction() is returning an Action (aka THIS locator)
92           * Dependency Injection is happening, in other words, each locator
93           * itself is responsible for Dependency Injection. For all locators that
94           * subclass AbstractActionLocator this contract is met.
95           */
96          if (action == null) {
97              ActionLocator fabal = getFallbackActionLocator();
98              if (fabal == null)
99                  throw new IllegalStateException(
100                         "The doFindAction() method returned null and there is no fallback ActionLocator defined. This is an incorrect setup.");
101             if (LOG.isTraceEnabled())
102                 LOG.trace("No Action found in action locator " + getClass().getName()
103                         + ". Trying with fallback action locator: " + fabal.getClass().getName());
104             action = fabal.getAction(ics, name);
105         } else {
106             if (LOG.isTraceEnabled()) {
107                 LOG.trace("Action '" + name + "' maps to action " + action.getClass().getName());
108             }
109             injectDependencies(ics, action);
110             if (StringUtils.isNotBlank(name)) {
111                 CacheManager.RecordItem(ics, "gsf-action:" + name);
112             } else if (action != null) {
113                 CacheManager.RecordItem(ics, "gsf-action:" + action.getClass().getName());
114             }
115         }
116         return action;
117 
118     }
119 
120     /**
121      * Template Method for finding the Action for the custom ActionLocator. In
122      * case the Action is created through this method, it is expected to be
123      * fully injected and ready to use.
124      * 
125      * @param ics the Content Server context
126      * @param name the name of the action
127      * @return the Action if found, null is valid.
128      */
129     protected abstract Action doFindAction(final ICS ics, final String name);
130 
131     /**
132      * @param ics
133      * @param action
134      */
135     protected final void injectDependencies(final ICS ics, final Action action) {
136 
137         Injector injector = getInjector();
138         injector.inject(ics, action);
139 
140     }
141 
142     public Injector getInjector() {
143 
144         return injector;
145     }
146 
147     /**
148      * @return the fallbackActionLocator
149      */
150     public ActionLocator getFallbackActionLocator() {
151         return fallbackActionLocator;
152     }
153 
154     /**
155      * @param fallbackActionLocator the fallbackActionLocator to set
156      */
157     public void setFallbackActionLocator(final ActionLocator fallbackActionLocator) {
158         Assert.notNull(fallbackActionLocator);
159         this.fallbackActionLocator = fallbackActionLocator;
160     }
161 
162     public void setInjector(Injector injector) {
163         this.injector = injector;
164     }
165 
166 }