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