You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tiles.apache.org by ap...@apache.org on 2008/06/05 20:53:08 UTC

svn commit: r663697 - in /tiles/framework/trunk/tiles-core/src: main/java/org/apache/tiles/definition/ test/java/org/apache/tiles/definition/

Author: apetrelli
Date: Thu Jun  5 11:53:08 2008
New Revision: 663697

URL: http://svn.apache.org/viewvc?rev=663697&view=rev
Log:
TILES-89
Moved DefinitionsImpl code to UrlDefinitionsFactory.

Removed:
    tiles/framework/trunk/tiles-core/src/test/java/org/apache/tiles/definition/MockDefinitions.java
    tiles/framework/trunk/tiles-core/src/test/java/org/apache/tiles/definition/MockPublicUrlDefinitionsFactory.java
    tiles/framework/trunk/tiles-core/src/test/java/org/apache/tiles/definition/TestDefinitions.java
Modified:
    tiles/framework/trunk/tiles-core/src/main/java/org/apache/tiles/definition/Definitions.java
    tiles/framework/trunk/tiles-core/src/main/java/org/apache/tiles/definition/DefinitionsImpl.java
    tiles/framework/trunk/tiles-core/src/main/java/org/apache/tiles/definition/UrlDefinitionsFactory.java
    tiles/framework/trunk/tiles-core/src/test/java/org/apache/tiles/definition/TestUrlDefinitionsFactory.java

Modified: tiles/framework/trunk/tiles-core/src/main/java/org/apache/tiles/definition/Definitions.java
URL: http://svn.apache.org/viewvc/tiles/framework/trunk/tiles-core/src/main/java/org/apache/tiles/definition/Definitions.java?rev=663697&r1=663696&r2=663697&view=diff
==============================================================================
--- tiles/framework/trunk/tiles-core/src/main/java/org/apache/tiles/definition/Definitions.java (original)
+++ tiles/framework/trunk/tiles-core/src/main/java/org/apache/tiles/definition/Definitions.java Thu Jun  5 11:53:08 2008
@@ -27,15 +27,19 @@
 import org.apache.tiles.Definition;
 
 /**
- * Interface for managing collections of {@link Definition} objects.
- * <p/>
- * <p>The Definitions interface provides a pattern for managing
- * Definition objects.  Implementations will provide a means to append
- * new Definitions to the collection, add and retrieve lcale-specific
- * Definitions objects, and reset the collections.</p>
+ * Interface for managing collections of {@link Definition} objects. <p/>
+ * <p>
+ * The Definitions interface provides a pattern for managing Definition objects.
+ * Implementations will provide a means to append new Definitions to the
+ * collection, add and retrieve lcale-specific Definitions objects, and reset
+ * the collections.
+ * </p>
  *
  * @version $Rev$ $Date$
+ * @deprecated This interface is never used, except in the deprecated class
+ * {@link DefinitionsImpl}.
  */
+@Deprecated
 public interface Definitions {
 
     /**

Modified: tiles/framework/trunk/tiles-core/src/main/java/org/apache/tiles/definition/DefinitionsImpl.java
URL: http://svn.apache.org/viewvc/tiles/framework/trunk/tiles-core/src/main/java/org/apache/tiles/definition/DefinitionsImpl.java?rev=663697&r1=663696&r2=663697&view=diff
==============================================================================
--- tiles/framework/trunk/tiles-core/src/main/java/org/apache/tiles/definition/DefinitionsImpl.java (original)
+++ tiles/framework/trunk/tiles-core/src/main/java/org/apache/tiles/definition/DefinitionsImpl.java Thu Jun  5 11:53:08 2008
@@ -34,7 +34,11 @@
 
 /**
  * @version $Rev$ $Date$
+ *
+ * @deprecated This class is, in fact, part of the implementation of
+ * {@link UrlDefinitionsFactory}.
  */
+@Deprecated
 public class DefinitionsImpl implements Definitions {
 
     /**
@@ -61,6 +65,18 @@
     }
 
     /**
+     * Creates a new instance of DefinitionsImpl to be used as a wrapper.
+     *
+     * @param baseDefinitions The base definitions to use.
+     * @param localeSpecificDefinitions Maps a locale to a map of definitions.
+     */
+    public DefinitionsImpl(Map<String, Definition> baseDefinitions,
+            Map<Locale, Map<String, Definition>> localeSpecificDefinitions) {
+        this.baseDefinitions = baseDefinitions;
+        this.localeSpecificDefinitions = localeSpecificDefinitions;
+    }
+
+    /**
      * Returns a Definition object that matches the given name.
      *
      * @param name The name of the Definition to return.

Modified: tiles/framework/trunk/tiles-core/src/main/java/org/apache/tiles/definition/UrlDefinitionsFactory.java
URL: http://svn.apache.org/viewvc/tiles/framework/trunk/tiles-core/src/main/java/org/apache/tiles/definition/UrlDefinitionsFactory.java?rev=663697&r1=663696&r2=663697&view=diff
==============================================================================
--- tiles/framework/trunk/tiles-core/src/main/java/org/apache/tiles/definition/UrlDefinitionsFactory.java (original)
+++ tiles/framework/trunk/tiles-core/src/main/java/org/apache/tiles/definition/UrlDefinitionsFactory.java Thu Jun  5 11:53:08 2008
@@ -38,6 +38,7 @@
 import java.net.URLConnection;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -107,9 +108,14 @@
 
 
     /**
-     * The definitions holder object.
+     * The base set of Definition objects not discriminated by locale.
      */
-    private Definitions definitions;
+    private Map<String, Definition> baseDefinitions;
+
+    /**
+     * The locale-specific set of definitions objects.
+     */
+    private Map<Locale, Map<String, Definition>> localeSpecificDefinitions;
 
     /**
      * The locale resolver object.
@@ -195,9 +201,11 @@
      * Returns the definitions holder object.
      *
      * @return The definitions holder.
+     * @deprecated Do not use! Deprecated with no replacement.
      */
+    @Deprecated
     protected Definitions getDefinitions() {
-        return definitions;
+        return new DefinitionsImpl(baseDefinitions, localeSpecificDefinitions);
     }
 
 
@@ -214,19 +222,16 @@
     public Definition getDefinition(String name,
             TilesRequestContext tilesContext) {
 
-        Definitions definitions = getDefinitions();
         Locale locale = null;
 
         if (tilesContext != null) {
             locale = localeResolver.resolveLocale(tilesContext);
             if (!isContextProcessed(tilesContext)) {
-                synchronized (definitions) {
-                    addDefinitions(definitions, tilesContext);
-                }
+                addDefinitions(tilesContext);
             }
         }
 
-        return definitions.getDefinition(name, locale);
+        return getDefinition(name, locale);
     }
 
     /**
@@ -267,9 +272,24 @@
      * @param definitions  The Definitions object to append to.
      * @param tilesContext The requested locale.
      * @throws DefinitionsFactoryException if an error occurs reading definitions.
+     * @deprecated Use {@link #addDefinitions(TilesRequestContext)}.
      */
     protected void addDefinitions(Definitions definitions,
             TilesRequestContext tilesContext) {
+        addDefinitions(tilesContext);
+    }
+
+    /**
+     * Appends locale-specific {@link Definition} objects to existing
+     * definitions set by reading locale-specific versions of the applied
+     * sources.
+     *
+     * @param tilesContext The requested locale.
+     * @throws DefinitionsFactoryException if an error occurs reading
+     * definitions.
+     * @since 2.1.0
+     */
+    protected synchronized void addDefinitions(TilesRequestContext tilesContext) {
 
         Locale locale = localeResolver.resolveLocale(tilesContext);
 
@@ -318,8 +338,8 @@
 
         // At the end of definitions loading, they can be assigned to
         // Definitions implementation, to allow inheritance resolution.
-        definitions.addDefinitions(localeDefsMap, localeResolver
-                .resolveLocale(tilesContext));
+        localeSpecificDefinitions.put(locale, localeDefsMap);
+        resolveInheritances(locale);
     }
 
     /**
@@ -334,7 +354,7 @@
     @Deprecated
     public Definitions readDefinitions() {
         loadDefinitions();
-        return definitions;
+        return new DefinitionsImpl(baseDefinitions, localeSpecificDefinitions);
     }
 
     /**
@@ -358,7 +378,9 @@
      * to provide your custom instance of Definitions.
      *
      * @return A new instance of <code>Definitions</code>.
+     * @deprecated Do not use! Deprecated with no replacement.
      */
+    @Deprecated
     protected Definitions createDefinitions() {
         return new DefinitionsImpl();
     }
@@ -391,19 +413,15 @@
     }
 
     /**
-     * Creates a {@link Definitions} set by reading
-     * configuration data from the applied sources.
+     * Creates a base set by reading configuration data from the applied
+     * sources.
      *
      * @throws DefinitionsFactoryException if an error occurs reading the
      * sources.
      * @since 2.1.0
      */
     protected synchronized void loadDefinitions() {
-        if (definitions == null) {
-            definitions = createDefinitions();
-        } else {
-            definitions.reset();
-        }
+        reset();
 
         try {
             for (URL source : sourceURLs) {
@@ -413,7 +431,8 @@
                     connection.getLastModified());
                 Map<String, Definition> defsMap = reader
                         .read(connection.getInputStream());
-                definitions.addDefinitions(defsMap);
+                baseDefinitions.putAll(defsMap);
+                resolveInheritances();
             }
         } catch (IOException e) {
             throw new DefinitionsFactoryException("I/O error accessing source.", e);
@@ -586,4 +605,124 @@
         }
         return filenames;
     }
+
+    /**
+     * Clears definitions.
+     *
+     * @since 2.1.0
+     */
+    protected void reset() {
+        this.baseDefinitions = new HashMap<String, Definition>();
+        this.localeSpecificDefinitions =
+            new HashMap<Locale, Map<String, Definition>>();
+    }
+
+    /**
+     * Resolve extended instances.
+     *
+     * @throws NoSuchDefinitionException If a parent definition is not found.
+     * @since 2.1.0
+     */
+    protected void resolveInheritances() {
+        Set<String> alreadyResolvedDefinitions = new HashSet<String>();
+
+        for (Definition definition : baseDefinitions.values()) {
+            resolveInheritance(definition, null, alreadyResolvedDefinitions);
+        }  // end loop
+    }
+
+    /**
+     * Resolve locale-specific extended instances.
+     *
+     * @param locale The locale to use.
+     * @throws NoSuchDefinitionException If a parent definition is not found.
+     * @since 2.1.0
+     */
+    protected void resolveInheritances(Locale locale) {
+        resolveInheritances();
+
+        Map<String, Definition> map = localeSpecificDefinitions.get(locale);
+        if (map != null) {
+            Set<String> alreadyResolvedDefinitions = new HashSet<String>();
+            for (Definition definition : map.values()) {
+                resolveInheritance(definition, locale,
+                        alreadyResolvedDefinitions);
+            }  // end loop
+        }
+    }
+
+    /**
+     * Resolve locale-specific inheritance.
+     * First, resolve parent's inheritance, then set template to the parent's
+     * template.
+     * Also copy attributes setted in parent, and not set in child
+     * If instance doesn't extend anything, do nothing.
+     *
+     * @param definition The definition to resolve
+     * @param locale The locale to use.
+     * @param alreadyResolvedDefinitions The set of the definitions that have
+     * been already resolved.
+     * @throws NoSuchDefinitionException If an inheritance can not be solved.
+     * @since 2.1.0
+     */
+    protected void resolveInheritance(Definition definition, Locale locale,
+            Set<String> alreadyResolvedDefinitions) {
+        // Already done, or not needed ?
+        if (!definition.isExtending()
+                || alreadyResolvedDefinitions.contains(definition.getName())) {
+            return;
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("Resolve definition for child name='"
+                + definition.getName()
+                + "' extends='" + definition.getExtends() + "'.");
+        }
+
+        // Set as visited to avoid endless recurisvity.
+        alreadyResolvedDefinitions.add(definition.getName());
+
+        // Resolve parent before itself.
+        Definition parent = getDefinition(definition.getExtends(),
+            locale);
+        if (parent == null) { // error
+            String msg = "Error while resolving definition inheritance: child '"
+                + definition.getName()
+                + "' can't find its ancestor '"
+                + definition.getExtends()
+                + "'. Please check your description file.";
+            // to do : find better exception
+            throw new NoSuchDefinitionException(msg);
+        }
+
+        resolveInheritance(parent, locale, alreadyResolvedDefinitions);
+
+        definition.inherit(parent);
+    }
+
+    /**
+     * Returns a Definition object that matches the given name and locale.
+     *
+     * @param name The name of the Definition to return.
+     * @param locale The locale to use to resolve the definition.
+     * @return the Definition matching the given name or null if none is found.
+     * @since 2.1.0
+     */
+    protected Definition getDefinition(String name, Locale locale) {
+        Definition definition = null;
+
+        if (locale != null) {
+            Map<String, Definition> localeSpecificMap =
+                localeSpecificDefinitions.get(locale);
+            if (localeSpecificMap != null) {
+                definition = localeSpecificMap.get(name);
+            }
+        }
+
+        if (definition == null) {
+            definition = baseDefinitions.get(name);
+        }
+
+        return definition;
+    }
 }

Modified: tiles/framework/trunk/tiles-core/src/test/java/org/apache/tiles/definition/TestUrlDefinitionsFactory.java
URL: http://svn.apache.org/viewvc/tiles/framework/trunk/tiles-core/src/test/java/org/apache/tiles/definition/TestUrlDefinitionsFactory.java?rev=663697&r1=663696&r2=663697&view=diff
==============================================================================
--- tiles/framework/trunk/tiles-core/src/test/java/org/apache/tiles/definition/TestUrlDefinitionsFactory.java (original)
+++ tiles/framework/trunk/tiles-core/src/test/java/org/apache/tiles/definition/TestUrlDefinitionsFactory.java Thu Jun  5 11:53:08 2008
@@ -50,13 +50,13 @@
     /**
      * The definitions factory.
      */
-    private MockPublicUrlDefinitionsFactory factory;
+    private UrlDefinitionsFactory factory;
 
     /** {@inheritDoc} */
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        factory = new MockPublicUrlDefinitionsFactory();
+        factory = new UrlDefinitionsFactory();
     }
 
     /**
@@ -124,12 +124,12 @@
                 + "org/apache/tiles/config/defs3.xml");
         factory.init(params);
 
-        // Parse files.
-        Definitions definitions = factory.getDefinitions();
-
-        assertNotNull("test.def1 definition not found.", definitions.getDefinition("test.def1"));
-        assertNotNull("test.def2 definition not found.", definitions.getDefinition("test.def2"));
-        assertNotNull("test.def3 definition not found.", definitions.getDefinition("test.def3"));
+        assertNotNull("test.def1 definition not found.", factory.getDefinition(
+                "test.def1", (TilesRequestContext) null));
+        assertNotNull("test.def2 definition not found.", factory.getDefinition(
+                "test.def2", (TilesRequestContext) null));
+        assertNotNull("test.def3 definition not found.", factory.getDefinition(
+                "test.def3", (TilesRequestContext) null));
     }
 
     /**
@@ -269,27 +269,28 @@
         factory.init(params);
 
         // Parse files.
-        Definitions definitions = factory.getDefinitions();
-        factory.addDefinitions(definitions,
-                new MockOnlyLocaleTilesContext(Locale.US));
-        factory.addDefinitions(definitions,
-                new MockOnlyLocaleTilesContext(Locale.FRENCH));
-
-        assertNotNull("test.def1 definition not found.", definitions.getDefinition("test.def1"));
-        assertNotNull("test.def1 US definition not found.", definitions.getDefinition("test.def1", Locale.US));
-        assertNotNull("test.def1 France definition not found.", definitions.getDefinition("test.def1", Locale.FRENCH));
-        assertNotNull("test.def1 China should return default.", definitions.getDefinition("test.def1", Locale.CHINA));
-
-        assertEquals("Incorrect default country value", "default", definitions
-                .getDefinition("test.def1").getAttribute("country").getValue());
-        assertEquals("Incorrect US country value", "US", definitions
-                .getDefinition("test.def1", Locale.US).getAttribute("country")
-                .getValue());
-        assertEquals("Incorrect France country value", "France", definitions
+        factory.addDefinitions(new MockOnlyLocaleTilesContext(Locale.US));
+        factory.addDefinitions(new MockOnlyLocaleTilesContext(Locale.FRENCH));
+
+        assertNotNull("test.def1 definition not found.", factory.getDefinition(
+                "test.def1", (Locale) null));
+        assertNotNull("test.def1 US definition not found.", factory
+                .getDefinition("test.def1", Locale.US));
+        assertNotNull("test.def1 France definition not found.", factory
+                .getDefinition("test.def1", Locale.FRENCH));
+        assertNotNull("test.def1 China should return default.", factory
+                .getDefinition("test.def1", Locale.CHINA));
+
+        assertEquals("Incorrect default country value", "default", factory
+                .getDefinition("test.def1", (Locale) null).getAttribute(
+                        "country").getValue());
+        assertEquals("Incorrect US country value", "US", factory.getDefinition(
+                "test.def1", Locale.US).getAttribute("country").getValue());
+        assertEquals("Incorrect France country value", "France", factory
                 .getDefinition("test.def1", Locale.FRENCH).getAttribute(
                         "country").getValue());
         assertEquals("Incorrect Chinese country value (should default)",
-                "default", definitions.getDefinition("test.def1", Locale.CHINA)
+                "default", factory.getDefinition("test.def1", Locale.CHINA)
                         .getAttribute("country").getValue());
     }
 
@@ -320,13 +321,12 @@
         factory.init(params);
 
         // Parse files.
-        Definitions definitions = factory.getDefinitions();
         TilesRequestContext tilesContext =
                 new MockOnlyLocaleTilesContext(Locale.US);
         assertFalse("Locale should not be processed.",
                 factory.isContextProcessed(tilesContext));
 
-        factory.addDefinitions(definitions, tilesContext);
+        factory.addDefinitions(tilesContext);
         assertTrue("Locale should be processed.",
                 factory.isContextProcessed(tilesContext));
     }