This project has retired. For details please refer to its Attic page.
DefinitionsImpl xref
View Javadoc

1   /*
2    * $Id: DefinitionsImpl.java 791161 2009-07-04 18:53:36Z apetrelli $
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;
23  
24  import java.util.HashMap;
25  import java.util.HashSet;
26  import java.util.Locale;
27  import java.util.Map;
28  import java.util.Set;
29  
30  import org.apache.tiles.Attribute;
31  import org.apache.tiles.Definition;
32  import org.slf4j.Logger;
33  import org.slf4j.LoggerFactory;
34  
35  /***
36   * @version $Rev: 791161 $ $Date: 2009-07-04 20:53:36 +0200 (sab, 04 lug 2009) $
37   *
38   * @deprecated This class is, in fact, part of the implementation of
39   * {@link UrlDefinitionsFactory} and
40   * {@link org.apache.tiles.definition.dao.ResolvingLocaleUrlDefinitionDAO}.
41   */
42  @Deprecated
43  public class DefinitionsImpl implements Definitions {
44  
45      /***
46       * Commons Logging instance.
47       */
48      private final Logger log = LoggerFactory.getLogger(DefinitionsImpl.class);
49  
50      /***
51       * The base set of Definition objects not discriminated by locale.
52       */
53      private Map<String, Definition> baseDefinitions;
54      /***
55       * The locale-specific set of definitions objects.
56       */
57      private Map<Locale, Map<String, Definition>> localeSpecificDefinitions;
58  
59      /***
60       * Creates a new instance of DefinitionsImpl.
61       */
62      public DefinitionsImpl() {
63          baseDefinitions = new HashMap<String, Definition>();
64          localeSpecificDefinitions =
65              new HashMap<Locale, Map<String, Definition>>();
66      }
67  
68      /***
69       * Creates a new instance of DefinitionsImpl to be used as a wrapper.
70       *
71       * @param baseDefinitions The base definitions to use.
72       * @param localeSpecificDefinitions Maps a locale to a map of definitions.
73       */
74      public DefinitionsImpl(Map<String, Definition> baseDefinitions,
75              Map<Locale, Map<String, Definition>> localeSpecificDefinitions) {
76          this.baseDefinitions = baseDefinitions;
77          this.localeSpecificDefinitions = localeSpecificDefinitions;
78      }
79  
80      /***
81       * Returns a Definition object that matches the given name.
82       *
83       * @param name The name of the Definition to return.
84       * @return the Definition matching the given name or null if none
85       *         is found.
86       */
87      public Definition getDefinition(String name) {
88          return baseDefinitions.get(name);
89      }
90  
91      /***
92       * Adds new Definition objects to the internal collection and
93       * resolves inheritance attraibutes.
94       *
95       * @param defsMap The new definitions to add.
96       * @throws NoSuchDefinitionException If something goes wrong during
97       * addition.
98       */
99      public void addDefinitions(Map<String, Definition> defsMap) {
100         this.baseDefinitions.putAll(defsMap);
101         resolveInheritances();
102     }
103 
104     /***
105      * Adds new locale-specific Definition objects to the internal
106      * collection and resolves inheritance attraibutes.
107      *
108      * @param defsMap The new definitions to add.
109      * @param locale  The locale to add the definitions to.
110      * @throws NoSuchDefinitionException If something goes wrong during
111      * inheritance resolution.
112      */
113     public void addDefinitions(Map<String, Definition> defsMap,
114             Locale locale) {
115         localeSpecificDefinitions.put(locale, defsMap);
116         resolveInheritances(locale);
117     }
118 
119     /***
120      * Returns a Definition object that matches the given name and locale.
121      *
122      * @param name   The name of the Definition to return.
123      * @param locale The locale to use to resolve the definition.
124      * @return the Definition matching the given name or null if none
125      *         is found.
126      */
127     public Definition getDefinition(String name, Locale locale) {
128         Definition definition = null;
129 
130         if (locale != null) {
131             Map<String, Definition> localeSpecificMap =
132                 localeSpecificDefinitions.get(locale);
133             if (localeSpecificMap != null) {
134                 definition = localeSpecificMap.get(name);
135             }
136         }
137 
138         if (definition == null) {
139             definition = getDefinition(name);
140         }
141 
142         return definition;
143     }
144 
145     /***
146      * Resolve extended instances.
147      *
148      * @throws NoSuchDefinitionException If a parent definition is not found.
149      */
150     public void resolveInheritances() {
151         Set<String> alreadyResolvedDefinitions = new HashSet<String>();
152 
153         for (Definition definition : baseDefinitions.values()) {
154             resolveInheritance(definition, null, alreadyResolvedDefinitions);
155         }  // end loop
156     }
157 
158     /***
159      * Resolve locale-specific extended instances.
160      *
161      * @param locale The locale to use.
162      * @throws NoSuchDefinitionException If a parent definition is not found.
163      */
164     public void resolveInheritances(Locale locale) {
165         resolveInheritances();
166 
167         Map<String, Definition> map = localeSpecificDefinitions.get(locale);
168         if (map != null) {
169             Set<String> alreadyResolvedDefinitions = new HashSet<String>();
170             for (Definition definition : map.values()) {
171                 resolveInheritance(definition, locale,
172                         alreadyResolvedDefinitions);
173             }  // end loop
174         }
175     }
176 
177     /***
178      * Clears definitions.
179      */
180     public void reset() {
181         this.baseDefinitions = new HashMap<String, Definition>();
182         this.localeSpecificDefinitions =
183             new HashMap<Locale, Map<String, Definition>>();
184     }
185 
186     /***
187      * Returns base definitions collection.
188      *
189      * @return The base (i.e. not depending on any locale) definitions map.
190      */
191     public Map<String, Definition> getBaseDefinitions() {
192         return baseDefinitions;
193     }
194 
195     /***
196      * Searches for a definition specified as an attribute.
197      *
198      * @param attr   The attribute to use.
199      * @param locale The locale to search into.
200      * @return The required definition if found, otherwise it returns
201      *         <code>null</code>.
202      */
203     protected Definition getDefinitionByAttribute(
204         Attribute attr, Locale locale) {
205         Definition retValue = null;
206 
207         Object attrValue = attr.getValue();
208         if (attrValue instanceof String) {
209             retValue = this.getDefinition((String) attr
210                 .getValue(), locale);
211         }
212 
213         return retValue;
214     }
215 
216     /***
217      * Resolve locale-specific inheritance.
218      * First, resolve parent's inheritance, then set template to the parent's
219      * template.
220      * Also copy attributes setted in parent, and not set in child
221      * If instance doesn't extend anything, do nothing.
222      *
223      * @param definition The definition to resolve
224      * @param locale The locale to use.
225      * @param alreadyResolvedDefinitions The set of the definitions that have
226      * been already resolved.
227      * @throws NoSuchDefinitionException If an inheritance can not be solved.
228      */
229     protected void resolveInheritance(Definition definition, Locale locale,
230             Set<String> alreadyResolvedDefinitions) {
231         // Already done, or not needed ?
232         if (!definition.isExtending()
233                 || alreadyResolvedDefinitions.contains(definition.getName())) {
234             return;
235         }
236 
237         if (log.isDebugEnabled()) {
238             log.debug("Resolve definition for child name='"
239                 + definition.getName()
240                 + "' extends='" + definition.getExtends() + "'.");
241         }
242 
243         // Set as visited to avoid endless recurisvity.
244         alreadyResolvedDefinitions.add(definition.getName());
245 
246         // Resolve parent before itself.
247         Definition parent = getDefinition(definition.getExtends(),
248             locale);
249         if (parent == null) { // error
250             String msg = "Error while resolving definition inheritance: child '"
251                 + definition.getName()
252                 + "' can't find its ancestor '"
253                 + definition.getExtends()
254                 + "'. Please check your description file.";
255             log.error(msg);
256             // to do : find better exception
257             throw new NoSuchDefinitionException(msg);
258         }
259 
260         resolveInheritance(parent, locale, alreadyResolvedDefinitions);
261 
262         definition.inherit(parent);
263     }
264 
265     /***
266      * Overloads a child definition with a given parent.
267      * All attributes present in child are kept. All missing attributes are
268      * copied from the parent.
269      * Special attribute 'template','role' and 'extends' are overloaded in child
270      * if not defined
271      *
272      * @param parent The parent definition.
273      * @param child  The child that will be overloaded.
274      * @deprecated Use {@link Definition#inherit(org.apache.tiles.AttributeContext)}.
275      */
276     @Deprecated
277     protected void overload(Definition parent, Definition child) {
278         child.inherit(parent);
279     }
280 }