001: /*
002: * $Id: XmlDefinition.java 471754 2006-11-06 14:55:09Z husted $
003: *
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021:
022: package org.apache.struts.tiles.xmlDefinition;
023:
024: import java.util.Iterator;
025:
026: import org.apache.commons.logging.Log;
027: import org.apache.commons.logging.LogFactory;
028: import org.apache.struts.tiles.ComponentDefinition;
029: import org.apache.struts.tiles.NoSuchDefinitionException;
030:
031: /**
032: *A definition read from an XML definitions file.
033: */
034: public class XmlDefinition extends ComponentDefinition {
035: /**
036: * Extends attribute value.
037: */
038: private String inherit;
039:
040: /** Commons Logging instance. */
041: protected static Log log = LogFactory.getLog(XmlDefinition.class);
042:
043: /**
044: * Used for resolving inheritance.
045: */
046: private boolean isVisited = false;
047:
048: /**
049: * Constructor.
050: */
051: public XmlDefinition() {
052: super ();
053: //if(debug)
054: //System.out.println( "create definition" );
055: }
056:
057: /**
058: * Add an attribute to this component.
059: *
060: * @param attribute Attribute to add.
061: */
062: public void addAttribute(XmlAttribute attribute) {
063: putAttribute(attribute.getName(), attribute.getValue());
064: }
065:
066: /**
067: * Set extends.
068: *
069: * @param name Name of the extended definition.
070: */
071: public void setExtends(String name) {
072: inherit = name;
073: }
074:
075: /**
076: * Get extends.
077: *
078: * @return Name of the extended definition.
079: */
080: public String getExtends() {
081: return inherit;
082: }
083:
084: /**
085: * Get extends flag.
086: *
087: */
088: public boolean isExtending() {
089: return inherit != null;
090: }
091:
092: /**
093: * Set isVisited.
094: *
095: */
096: public void setIsVisited(boolean isVisited) {
097: this .isVisited = isVisited;
098: }
099:
100: /**
101: * Resolve inheritance.
102: * First, resolve parent's inheritance, then set path to the parent's path.
103: * Also copy attributes setted in parent, and not set in child
104: * If instance doesn't extend anything, do nothing.
105: * @throws NoSuchDefinitionException If an inheritance can not be solved.
106: */
107: public void resolveInheritance(XmlDefinitionsSet definitionsSet)
108: throws NoSuchDefinitionException {
109: // Already done, or not needed ?
110: if (isVisited || !isExtending())
111: return;
112:
113: if (log.isDebugEnabled())
114: log.debug("Resolve definition for child name='" + getName()
115: + "' extends='" + getExtends() + "'.");
116:
117: // Set as visited to avoid endless recurisvity.
118: setIsVisited(true);
119:
120: // Resolve parent before itself.
121: XmlDefinition parent = definitionsSet
122: .getDefinition(getExtends());
123: if (parent == null) { // error
124: String msg = "Error while resolving definition inheritance: child '"
125: + getName()
126: + "' can't find its ancestor '"
127: + getExtends()
128: + "'. Please check your description file.";
129: log.error(msg);
130: // to do : find better exception
131: throw new NoSuchDefinitionException(msg);
132: }
133:
134: parent.resolveInheritance(definitionsSet);
135:
136: // Iterate on each parent's attribute and add it if not defined in child.
137: Iterator parentAttributes = parent.getAttributes().keySet()
138: .iterator();
139: while (parentAttributes.hasNext()) {
140: String name = (String) parentAttributes.next();
141: if (!getAttributes().containsKey(name))
142: putAttribute(name, parent.getAttribute(name));
143: }
144: // Set path and role if not setted
145: if (path == null)
146: setPath(parent.getPath());
147: if (role == null)
148: setRole(parent.getRole());
149: if (controller == null) {
150: setController(parent.getController());
151: setControllerType(parent.getControllerType());
152: }
153: }
154:
155: /**
156: * Overload this definition with passed child.
157: * All attributes from child are copied to this definition. Previous
158: * attributes with same name are disguarded.
159: * Special attribute 'path','role' and 'extends' are overloaded if defined
160: * in child.
161: * @param child Child used to overload this definition.
162: */
163: public void overload(XmlDefinition child) {
164: if (child.getPath() != null) {
165: path = child.getPath();
166: }
167: if (child.getExtends() != null) {
168: inherit = child.getExtends();
169: }
170: if (child.getRole() != null) {
171: role = child.getRole();
172: }
173: if (child.getController() != null) {
174: controller = child.getController();
175: controllerType = child.getControllerType();
176: }
177: // put all child attributes in parent.
178: attributes.putAll(child.getAttributes());
179: }
180: }
|