Home » commons-chain-1.2-src » org.apache.commons » chain » generic » [javadoc | source]
    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.chain.generic;
   18   
   19   
   20   import org.apache.commons.chain.Catalog;
   21   import org.apache.commons.chain.CatalogFactory;
   22   import org.apache.commons.chain.Command;
   23   import org.apache.commons.chain.Context;
   24   import org.apache.commons.chain.Filter;
   25   
   26   
   27   /**
   28    * <p>Look up a specified {@link Command} (which could also be a
   29    * {@link org.apache.commons.chain.Chain})
   30    * in a {@link Catalog}, and delegate execution to it.  If the delegated-to
   31    * {@link Command} is also a {@link Filter}, its <code>postprocess()</code>
   32    * method will also be invoked at the appropriate time.</p>
   33    *
   34    * <p>The name of the {@link Command} can be specified either directly (via
   35    * the <code>name</code> property) or indirectly (via the <code>nameKey</code>
   36    * property).  Exactly one of these must be set.</p>
   37    *
   38    * <p>If the <code>optional</code> property is set to <code>true</code>,
   39    * failure to find the specified command in the specified catalog will be
   40    * silently ignored.  Otherwise, a lookup failure will trigger an
   41    * <code>IllegalArgumentException</code>.</p>
   42    *
   43    * @author Craig R. McClanahan
   44    * @version $Revision: 532951 $ $Date: 2007-04-27 04:59:00 +0100 (Fri, 27 Apr 2007) $
   45    */
   46   
   47   public class LookupCommand implements Filter {
   48   
   49   
   50       // -------------------------------------------------------------- Constructors
   51   
   52       /**
   53        * Create an instance, setting its <code>catalogFactory</code> property to the
   54        * value of <code>CatalogFactory.getInstance()</code>.
   55        *
   56        * @since Chain 1.1
   57        */
   58       public LookupCommand() {
   59           this(CatalogFactory.getInstance());
   60       }
   61   
   62       /**
   63        * Create an instance and initialize the <code>catalogFactory</code> property
   64        * to given <code>factory</code>/
   65        *
   66        * @param factory The Catalog Factory.
   67        *
   68        * @since Chain 1.1
   69        */
   70       public LookupCommand(CatalogFactory factory) {
   71           this.catalogFactory = factory;
   72       }
   73   
   74   
   75       // -------------------------------------------------------------- Properties
   76   
   77       private CatalogFactory catalogFactory = null;
   78   
   79       /**
   80        * <p>Set the {@link CatalogFactory} from which lookups will be
   81        * performed.</p>
   82        *
   83        * @param catalogFactory The Catalog Factory.
   84        *
   85        * @since Chain 1.1
   86        */
   87       public void setCatalogFactory(CatalogFactory catalogFactory) {
   88           this.catalogFactory = catalogFactory;
   89       }
   90   
   91       /**
   92        * Return the {@link CatalogFactory} from which lookups will be performed.
   93        * @return The Catalog factory.
   94        *
   95        * @since Chain 1.1
   96        */
   97       public CatalogFactory getCatalogFactory() {
   98   
   99           return this.catalogFactory;
  100       }
  101   
  102   
  103       private String catalogName = null;
  104   
  105       /**
  106        * <p>Return the name of the {@link Catalog} to be searched, or
  107        * <code>null</code> to search the default {@link Catalog}.</p>
  108        * @return The Catalog name.
  109        */
  110       public String getCatalogName() {
  111   
  112           return (this.catalogName);
  113   
  114       }
  115   
  116   
  117       /**
  118        * <p>Set the name of the {@link Catalog} to be searched, or
  119        * <code>null</code> to search the default {@link Catalog}.</p>
  120        *
  121        * @param catalogName The new {@link Catalog} name or <code>null</code>
  122        */
  123       public void setCatalogName(String catalogName) {
  124   
  125           this.catalogName = catalogName;
  126   
  127       }
  128   
  129   
  130       private String name = null;
  131   
  132   
  133       /**
  134        * <p>Return the name of the {@link Command} that we will look up and
  135        * delegate execution to.</p>
  136        * @return The name of the Command.
  137        */
  138       public String getName() {
  139   
  140           return (this.name);
  141   
  142       }
  143   
  144   
  145       /**
  146        * <p>Set the name of the {@link Command} that we will look up and
  147        * delegate execution to.</p>
  148        *
  149        * @param name The new command name
  150        */
  151       public void setName(String name) {
  152   
  153           this.name = name;
  154   
  155       }
  156   
  157   
  158       private String nameKey = null;
  159   
  160   
  161       /**
  162        * <p>Return the context attribute key under which the {@link Command}
  163        * name is stored.</p>
  164        * @return The context key of the Command.
  165        */
  166       public String getNameKey() {
  167   
  168           return (this.nameKey);
  169   
  170       }
  171   
  172   
  173       /**
  174        * <p>Set the context attribute key under which the {@link Command}
  175        * name is stored.</p>
  176        *
  177        * @param nameKey The new context attribute key
  178        */
  179       public void setNameKey(String nameKey) {
  180   
  181           this.nameKey = nameKey;
  182   
  183       }
  184   
  185   
  186       private boolean optional = false;
  187   
  188   
  189       /**
  190        * <p>Return <code>true</code> if locating the specified command
  191        * is optional.</p>
  192        * @return <code>true</code> if the Command is optional.
  193        */
  194       public boolean isOptional() {
  195   
  196           return (this.optional);
  197   
  198       }
  199   
  200   
  201       /**
  202        * <p>Set the optional flag for finding the specified command.</p>
  203        *
  204        * @param optional The new optional flag
  205        */
  206       public void setOptional(boolean optional) {
  207   
  208           this.optional = optional;
  209   
  210       }
  211   
  212       private boolean ignoreExecuteResult = false;
  213   
  214       /**
  215        * <p>Return <code>true</code> if this command should ignore
  216        * the return value from executing the looked-up command.
  217        * Defaults to <code>false</code>, which means that the return result
  218        * of executing this lookup will be whatever is returned from that
  219        * command.</p>
  220        * @return <code>true</code> if result of the looked up Command
  221        * should be ignored.
  222        *
  223        * @since Chain 1.1
  224        */
  225       public boolean isIgnoreExecuteResult() {
  226           return ignoreExecuteResult;
  227       }
  228   
  229       /**
  230        * <p>Set the rules for whether or not this class will ignore or
  231        * pass through the value returned from executing the looked up
  232        * command.</p>
  233        * <p>If you are looking up a chain which may be "aborted" and
  234        * you do not want this class to stop chain processing, then this
  235        * value should be set to <code>true</code></p>
  236        * @param ignoreReturn <code>true</code> if result of the
  237        * looked up Command should be ignored.
  238        *
  239        * @since Chain 1.1
  240        */
  241       public void setIgnoreExecuteResult(boolean ignoreReturn) {
  242           this.ignoreExecuteResult = ignoreReturn;
  243       }
  244   
  245       private boolean ignorePostprocessResult = false;
  246   
  247       /**
  248        * <p>Return <code>true</code> if this command is a Filter and
  249        * should ignore the return value from executing the looked-up Filter's
  250        * <code>postprocess()</code> method.
  251        * Defaults to <code>false</code>, which means that the return result
  252        * of executing this lookup will be whatever is returned from that
  253        * Filter.</p>
  254        * @return <code>true</code> if result of the looked up Filter's
  255        * <code>postprocess()</code> method should be ignored.
  256        *
  257        * @since Chain 1.1
  258        */
  259       public boolean isIgnorePostprocessResult() {
  260           return ignorePostprocessResult;
  261       }
  262   
  263       /**
  264        * <p>Set the rules for whether or not this class will ignore or
  265        * pass through the value returned from executing the looked up
  266        * Filter's <code>postprocess()</code> method.</p>
  267        * <p>If you are looking up a Filter which may be "aborted" and
  268        * you do not want this class to stop chain processing, then this
  269        * value should be set to <code>true</code></p>
  270        * @param ignorePostprocessResult <code>true</code> if result of the
  271        * looked up Filter's <code>postprocess()</code> method should be ignored.
  272        *
  273        * @since Chain 1.1
  274        */
  275       public void setIgnorePostprocessResult(boolean ignorePostprocessResult) {
  276           this.ignorePostprocessResult = ignorePostprocessResult;
  277       }
  278       // ---------------------------------------------------------- Filter Methods
  279   
  280   
  281       /**
  282        * <p>Look up the specified command, and (if found) execute it.
  283        * Unless <code>ignoreExecuteResult</code> is set to <code>true</code>,
  284        * return the result of executing the found command.  If no command
  285        * is found, return <code>false</code>, unless the <code>optional</code>
  286        * property is <code>false</code>, in which case an <code>IllegalArgumentException</code>
  287        * will be thrown.
  288        * </p>
  289        *
  290        * @param context The context for this request
  291        *
  292        * @exception IllegalArgumentException if no such {@link Command}
  293        *  can be found and the <code>optional</code> property is set
  294        *  to <code>false</code>
  295        * @return the result of executing the looked-up command, or
  296        * <code>false</code> if no command is found or if the command
  297        * is found but the <code>ignoreExecuteResult</code> property of this
  298        * instance is <code>true</code>
  299        * @throws Exception if and error occurs in the looked-up Command.
  300        */
  301       public boolean execute(Context context) throws Exception {
  302   
  303           Command command = getCommand(context);
  304           if (command != null) {
  305               boolean result = (command.execute(context));
  306               if (isIgnoreExecuteResult()) {
  307                   return false;
  308               }
  309               return result;
  310           } else {
  311               return (false);
  312           }
  313   
  314       }
  315   
  316   
  317       /**
  318        * <p>If the executed command was itself a {@link Filter}, call the
  319        * <code>postprocess()</code> method of that {@link Filter} as well.</p>
  320        *
  321        * @param context The context for this request
  322        * @param exception Any <code>Exception</code> thrown by command execution
  323        *
  324        * @return the result of executing the <code>postprocess</code> method
  325        * of the looked-up command, unless <code>ignorePostprocessResult</code> is
  326        * <code>true</code>.  If no command is found, return <code>false</code>,
  327        * unless the <code>optional</code> property is <code>false</code>, in which
  328        * case <code>IllegalArgumentException</code> will be thrown.
  329        */
  330       public boolean postprocess(Context context, Exception exception) {
  331   
  332           Command command = getCommand(context);
  333           if (command != null) {
  334               if (command instanceof Filter) {
  335                   boolean result = (((Filter) command).postprocess(context, exception));
  336                   if (isIgnorePostprocessResult()) {
  337                       return false;
  338                   }
  339                   return result;
  340               }
  341           }
  342           return (false);
  343   
  344       }
  345   
  346   
  347       // --------------------------------------------------------- Private Methods
  348   
  349   
  350       /**
  351        * <p>Return the {@link Catalog} to look up the {@link Command} in.</p>
  352        *
  353        * @param context {@link Context} for this request
  354        * @return The catalog.
  355        * @exception IllegalArgumentException if no {@link Catalog}
  356        *  can be found
  357        *
  358        * @since Chain 1.2
  359        */
  360       protected Catalog getCatalog(Context context) {
  361           CatalogFactory lookupFactory = this.catalogFactory;
  362           if (lookupFactory == null) {
  363               lookupFactory = CatalogFactory.getInstance();
  364           }
  365   
  366           String catalogName = getCatalogName();
  367           Catalog catalog = null;
  368           if (catalogName == null) {
  369               // use default catalog
  370               catalog = lookupFactory.getCatalog();
  371           } else {
  372               catalog = lookupFactory.getCatalog(catalogName);
  373           }
  374           if (catalog == null) {
  375               if (catalogName == null) {
  376                   throw new IllegalArgumentException
  377                       ("Cannot find default catalog");
  378               } else {
  379                   throw new IllegalArgumentException
  380                       ("Cannot find catalog '" + catalogName + "'");
  381               }
  382           }
  383   
  384           return catalog;
  385       }
  386   
  387       /**
  388        * <p>Return the {@link Command} instance to be delegated to.</p>
  389        *
  390        * @param context {@link Context} for this request
  391        * @return The looked-up Command.
  392        * @exception IllegalArgumentException if no such {@link Command}
  393        *  can be found and the <code>optional</code> property is set
  394        *  to <code>false</code>
  395        */
  396       protected Command getCommand(Context context) {
  397   
  398           Catalog catalog = getCatalog(context);
  399   
  400           Command command = null;
  401           String name = getCommandName(context);
  402           if (name != null) {
  403               command = catalog.getCommand(name);
  404               if ((command == null) && !isOptional()) {
  405                   if (catalogName == null) {
  406                       throw new IllegalArgumentException
  407                           ("Cannot find command '" + name
  408                            + "' in default catalog");
  409                   } else {
  410                       throw new IllegalArgumentException
  411                           ("Cannot find command '" + name
  412                            + "' in catalog '" + catalogName + "'");
  413                   }
  414               }
  415               return (command);
  416           } else {
  417               throw new IllegalArgumentException("No command name");
  418           }
  419   
  420       }
  421   
  422       /**
  423        * <p>Return the name of the {@link Command} instance to be delegated to.</p>
  424        *
  425        * @param context {@link Context} for this request
  426        * @return The name of the {@link Command} instance
  427        *
  428        * @since Chain 1.2
  429        */
  430       protected String getCommandName(Context context) {
  431   
  432           String name = getName();
  433           if (name == null) {
  434               name = (String) context.get(getNameKey());
  435           }
  436           return name;
  437   
  438       }
  439   
  440   }

Save This Page
Home » commons-chain-1.2-src » org.apache.commons » chain » generic » [javadoc | source]