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 }