Coverage Report - org.apache.tiles.definition.dao.ResolvingLocaleUrlDefinitionDAO
 
Classes in this File Line Coverage Branch Coverage Complexity
ResolvingLocaleUrlDefinitionDAO
97%
36/37
81%
13/16
2.429
 
 1  
 /*
 2  
  * $Id: ResolvingLocaleUrlDefinitionDAO.java 1297705 2012-03-06 20:44:30Z nlebas $
 3  
  *
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  * http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 package org.apache.tiles.definition.dao;
 23  
 
 24  
 import java.util.HashSet;
 25  
 import java.util.LinkedHashMap;
 26  
 import java.util.Locale;
 27  
 import java.util.Map;
 28  
 import java.util.Set;
 29  
 
 30  
 import org.apache.tiles.Definition;
 31  
 import org.apache.tiles.definition.NoSuchDefinitionException;
 32  
 import org.apache.tiles.request.ApplicationContext;
 33  
 import org.slf4j.Logger;
 34  
 import org.slf4j.LoggerFactory;
 35  
 
 36  
 /**
 37  
  * <p>
 38  
  * A definitions DAO (loading URLs and using Locale as a customization key) that
 39  
  * caches definitions that have been loaded and resolves inheritances.
 40  
  * </p>
 41  
  * <p>
 42  
  * It can check if the URLs change, but by default this feature is turned off.
 43  
  * </p>
 44  
  *
 45  
  * @version $Rev: 1297705 $ $Date: 2012-03-07 07:44:30 +1100 (Wed, 07 Mar 2012) $
 46  
  * @since 2.1.0
 47  
  */
 48  
 public class ResolvingLocaleUrlDefinitionDAO extends
 49  
         CachingLocaleUrlDefinitionDAO {
 50  
 
 51  
     /**
 52  
      * The logging object.
 53  
      */
 54  15
     private final Logger log = LoggerFactory.getLogger(ResolvingLocaleUrlDefinitionDAO.class);
 55  
 
 56  
     public ResolvingLocaleUrlDefinitionDAO(ApplicationContext applicationContext) {
 57  15
         super(applicationContext);
 58  15
     }
 59  
 
 60  
     /** {@inheritDoc} */
 61  
     @Override
 62  
     protected Map<String, Definition> loadParentDefinitions(Locale parentLocale) {
 63  0
         return loadRawDefinitionsFromResources(parentLocale);
 64  
     }
 65  
 
 66  
     @Override
 67  
     protected Map<String, Definition> loadDefinitions(Locale customizationKey) {
 68  14
         Map<String, Definition> localeDefsMap = super.loadDefinitions(customizationKey);
 69  14
         Map<String, Definition> defsMap = definitionResolver
 70  
                 .storeDefinitionPatterns(copyDefinitionMap(localeDefsMap),
 71  
                         customizationKey);
 72  14
         resolveInheritances(defsMap, customizationKey);
 73  14
         locale2definitionMap.put(customizationKey, defsMap);
 74  14
         return defsMap;
 75  
     }
 76  
 
 77  
     /** {@inheritDoc} */
 78  
     @Override
 79  
     protected Definition getDefinitionFromResolver(String name,
 80  
             Locale customizationKey) {
 81  5
         Definition retValue = super.getDefinitionFromResolver(name, customizationKey);
 82  5
         if (retValue != null && retValue.getExtends() != null) {
 83  1
             Definition parent = getDefinition(retValue.getExtends(), customizationKey);
 84  1
             retValue.inherit(parent);
 85  
         }
 86  
 
 87  5
         return retValue;
 88  
     }
 89  
 
 90  
     /**
 91  
      * Resolve locale-specific extended instances.
 92  
      *
 93  
      * @param map The definition map containing the definitions to resolve.
 94  
      * @param locale The locale to use.
 95  
      * @throws NoSuchDefinitionException If a parent definition is not found.
 96  
      * @since 2.1.0
 97  
      */
 98  
     protected void resolveInheritances(Map<String, Definition> map, Locale locale) {
 99  14
         if (map != null) {
 100  14
             Set<String> alreadyResolvedDefinitions = new HashSet<String>();
 101  14
             for (Definition definition : map.values()) {
 102  79
                 resolveInheritance(definition, map, locale,
 103  
                         alreadyResolvedDefinitions);
 104  79
             }  // end loop
 105  
         }
 106  14
     }
 107  
 
 108  
     /**
 109  
      * Resolve locale-specific inheritance. First, resolve parent's inheritance,
 110  
      * then set template to the parent's template. Also copy attributes setted
 111  
      * in parent, and not set in child If instance doesn't extend anything, do
 112  
      * nothing.
 113  
      *
 114  
      * @param definition The definition to resolve
 115  
      * @param definitions The definitions to take when obtaining a parent
 116  
      * definition.
 117  
      * @param locale The locale to use.
 118  
      * @param alreadyResolvedDefinitions The set of the definitions that have
 119  
      * been already resolved.
 120  
      * @throws NoSuchDefinitionException If an inheritance can not be solved.
 121  
      * @since 2.1.0
 122  
      */
 123  
     protected void resolveInheritance(Definition definition,
 124  
             Map<String, Definition> definitions, Locale locale,
 125  
             Set<String> alreadyResolvedDefinitions) {
 126  
         // Already done, or not needed ?
 127  87
         if (!definition.isExtending()
 128  
                 || alreadyResolvedDefinitions.contains(definition.getName())) {
 129  79
             return;
 130  
         }
 131  
 
 132  8
         log.debug("Resolve definition for child name='{}' extends='{}.",
 133  
                 definition.getName(), definition.getExtends());
 134  
 
 135  
         // Set as visited to avoid endless recursivity.
 136  8
         alreadyResolvedDefinitions.add(definition.getName());
 137  
 
 138  
         // Resolve parent before itself.
 139  8
         Definition parent = definitions.get(definition.getExtends());
 140  8
         if (parent == null) { // error
 141  1
             String msg = "Error while resolving definition inheritance: child '"
 142  
                 + definition.getName()
 143  
                 + "' can't find its ancestor '"
 144  
                 + definition.getExtends()
 145  
                 + "'. Please check your description file.";
 146  
             // to do : find better exception
 147  1
             throw new NoSuchDefinitionException(msg);
 148  
         }
 149  
 
 150  7
         resolveInheritance(parent, definitions, locale,
 151  
                 alreadyResolvedDefinitions);
 152  
 
 153  7
         definition.inherit(parent);
 154  7
     }
 155  
 
 156  
     /**
 157  
      * Copies the definition map to be passed to a higher level of customization
 158  
      * key.
 159  
      *
 160  
      * @param localeDefsMap The map of definition to be copied.
 161  
      * @return The copy of the definition map. This particular implementation
 162  
      * deep-copies the <code>localeDefsMap</code> into a {@link LinkedHashMap}.
 163  
      * @since 2.1.4
 164  
      */
 165  
     @Override
 166  
     protected Map<String, Definition> copyDefinitionMap(
 167  
             Map<String, Definition> localeDefsMap) {
 168  28
         Map<String, Definition> retValue = new LinkedHashMap<String, Definition>(
 169  
                 localeDefsMap.size());
 170  
 
 171  28
         for (Map.Entry<String, Definition> entry : localeDefsMap.entrySet()) {
 172  182
             Definition definition = new Definition(entry.getValue());
 173  182
             retValue.put(entry.getKey(), definition);
 174  182
         }
 175  
 
 176  28
         return retValue;
 177  
     }
 178  
 }