View Javadoc
1   /*
2    * $Id$
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.struts.tiles.xmlDefinition;
23  
24  import org.apache.struts.tiles.ComponentDefinition;
25  import org.apache.struts.tiles.NoSuchDefinitionException;
26  import org.slf4j.Logger;
27  import org.slf4j.LoggerFactory;
28  
29  /**
30    *A definition read from an XML definitions file.
31    */
32  public class XmlDefinition extends ComponentDefinition
33  {
34    private static final long serialVersionUID = -5843791058928194033L;
35  
36    /**
37     * Extends attribute value.
38     */
39    private String inherit;
40  
41    /**
42     * The {@code Log} instance for this class.
43     */
44    private transient final Logger log =
45      LoggerFactory.getLogger(XmlDefinition.class);
46  
47    /**
48     * Used for resolving inheritance.
49     */
50    private boolean isVisited=false;
51  
52  
53       /**
54        * Constructor.
55        */
56     public XmlDefinition()
57     {
58     super();
59     //if(debug)
60       //System.out.println( "create definition" );
61     }
62  
63    /**
64     * Add an attribute to this component.
65     *
66     * @param attribute Attribute to add.
67     */
68    public void addAttribute( XmlAttribute attribute)
69      {
70      putAttribute( attribute.getName(), attribute.getValue() );
71      }
72  
73    /**
74     * Set extends.
75     *
76     * @param name Name of the extended definition.
77     */
78    public void setExtends(String name)
79      {
80      inherit = name;
81      }
82  
83    /**
84     * Get extends.
85     *
86     * @return Name of the extended definition.
87     */
88    public String getExtends()
89      {
90      return inherit;
91      }
92  
93    /**
94     * Get extends flag.
95     *
96     */
97    public boolean isExtending( )
98      {
99      return inherit!=null;
100     }
101 
102   /**
103    * Set isVisited.
104    *
105    */
106   public void setIsVisited( boolean isVisited )
107     {
108     this.isVisited = isVisited;
109     }
110 
111     /**
112      * Resolve inheritance.
113      * First, resolve parent's inheritance, then set path to the parent's path.
114      * Also copy attributes setted in parent, and not set in child
115      * If instance doesn't extend anything, do nothing.
116      * @throws NoSuchDefinitionException If an inheritance can not be solved.
117      */
118   public void resolveInheritance( XmlDefinitionsSet definitionsSet )
119     throws NoSuchDefinitionException
120     {
121       // Already done, or not needed ?
122     if( isVisited || !isExtending() )
123       return;
124 
125     log.debug("Resolve definition for child name='{}' extends='{}'.",
126       getName(), getExtends());
127 
128       // Set as visited to avoid endless recurisvity.
129     setIsVisited( true );
130 
131       // Resolve parent before itself.
132     XmlDefinition parent = definitionsSet.getDefinition( getExtends() );
133     if( parent == null )
134       { // error
135       String msg = "Error while resolving definition inheritance: child '"
136                            + getName() +    "' can't find its ancestor '"
137                            + getExtends() +
138                            "'. Please check your description file.";
139       log.error( msg );
140         // to do : find better exception
141       throw new NoSuchDefinitionException( msg );
142       }
143 
144     parent.resolveInheritance( definitionsSet );
145 
146       // Iterate on each parent's attribute and add it if not defined in child.
147     for( String name : parent.getAttributes().keySet() )
148       {
149       if( !getAttributes().containsKey(name) )
150         putAttribute( name, parent.getAttribute(name) );
151       }
152       // Set path and role if not setted
153     if( path == null )
154       setPath( parent.getPath() );
155     if( role == null )
156       setRole( parent.getRole() );
157     if( controller==null )
158       {
159       setController( parent.getController());
160       setControllerType( parent.getControllerType());
161       }
162     }
163 
164   /**
165    * Overload this definition with passed child.
166    * All attributes from child are copied to this definition. Previous
167    * attributes with same name are disguarded.
168    * Special attribute 'path','role' and 'extends' are overloaded if defined
169    * in child.
170    * @param child Child used to overload this definition.
171    */
172   public void overload( XmlDefinition child )
173     {
174     if( child.getPath() != null )
175       {
176       path = child.getPath();
177       }
178     if( child.getExtends() != null )
179       {
180       inherit = child.getExtends();
181       }
182     if( child.getRole() != null )
183       {
184       role = child.getRole();
185       }
186     if( child.getController()!=null )
187       {
188       controller = child.getController();
189       controllerType =  child.getControllerType();
190       }
191       // put all child attributes in parent.
192     attributes.putAll( child.getAttributes());
193     }
194 }