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