001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.woody.formmodel;
018:
019: import java.util.ArrayList;
020: import java.util.HashMap;
021: import java.util.Iterator;
022: import java.util.List;
023: import java.util.ListIterator;
024: import java.util.Map;
025:
026: // TODO: Refine and i18n the exception messages.
027: /**
028: * Helper class for the Definition implementation of widgets containing
029: * other widgets.
030: *
031: * @version $Id: ContainerDefinitionDelegate.java 433543 2006-08-22 06:22:54Z crossley $
032: */
033: public class ContainerDefinitionDelegate {
034: private List widgetDefinitions = new ArrayList();
035: private Map widgetDefinitionsById = new HashMap();
036: private WidgetDefinition definition;
037: private boolean resolving;
038: private ListIterator definitionsIt = widgetDefinitions
039: .listIterator();
040:
041: /**
042: * @param definition the widget definition to which this container delegate belongs
043: */
044: public ContainerDefinitionDelegate(WidgetDefinition definition) {
045: this .definition = definition;
046: resolving = false;
047: }
048:
049: public void addWidgetDefinition(WidgetDefinition widgetDefinition)
050: throws DuplicateIdException {
051: String id = widgetDefinition.getId();
052: // Do not add NewDefinition id's hash.
053: if (!(widgetDefinition instanceof NewDefinition)) {
054: if (widgetDefinitionsById.containsKey(id)) {
055: String duplicateLocation = widgetDefinition
056: .getLocation();
057: String containerLocation = definition.getLocation();
058: String firstLocation = getWidgetDefinition(id)
059: .getLocation();
060: throw new DuplicateIdException("Duplicate widget id \""
061: + id + "\" detected at " + duplicateLocation
062: + ".\n" + "Container widget \""
063: + definition.getId() + "\" at "
064: + containerLocation + "\n"
065: + "already contains a widget with id \"" + id
066: + "\" at " + firstLocation + ".");
067: }
068: widgetDefinitionsById.put(widgetDefinition.getId(),
069: widgetDefinition);
070: }
071: this .definitionsIt.add(widgetDefinition);
072: }
073:
074: public List getWidgetDefinitions() {
075: return widgetDefinitions;
076: }
077:
078: public boolean hasWidget(String id) {
079: return widgetDefinitionsById.containsKey(id);
080: }
081:
082: public WidgetDefinition getWidgetDefinition(String id) {
083: return (WidgetDefinition) widgetDefinitionsById.get(id);
084: }
085:
086: public boolean isResolving() {
087: return resolving;
088: }
089:
090: public void resolve(List parents, WidgetDefinition parent)
091: throws Exception {
092: if (!resolving) {
093: resolving = true;
094: this .definitionsIt = widgetDefinitions.listIterator();
095: parents.add(definition);
096: while (this .definitionsIt.hasNext()) {
097: WidgetDefinition widgetDefinition = (WidgetDefinition) this .definitionsIt
098: .next();
099: // ClassDefinition's get resolved by NewDefinition rather than here.
100: if (!(widgetDefinition instanceof ClassDefinition)) {
101: if (widgetDefinition instanceof NewDefinition) {
102: // Remove NewDefinition in preparation for its referenced class of widget definitions to be added.
103: this .definitionsIt.remove();
104: ((NewDefinition) widgetDefinition).resolve(
105: parents, definition);
106: } else {
107: if (widgetDefinition instanceof ContainerDefinition)
108: ((ContainerDefinition) widgetDefinition)
109: .resolve(parents, definition);
110: }
111: }
112: }
113: parents.remove(parents.size() - 1);
114: resolving = false;
115: } else {
116: // Non-terminating recursion detection
117: if (resolving == true) {
118: // Search up parent list in hopes of finding a "Union" before finding previous "New" for this "Class".
119: ListIterator parentsIt = parents.listIterator(parents
120: .size());
121: while (parentsIt.hasPrevious()) {
122: WidgetDefinition widgetDefinition = (WidgetDefinition) parentsIt
123: .previous();
124: if (widgetDefinition instanceof UnionDefinition)
125: break;
126: if (widgetDefinition == definition) {
127: String location = definition.getLocation();
128: if (parent instanceof FormDefinition) {
129: throw new Exception(
130: "Container: Non-terminating recursion detected in form definition ("
131: + location + ")");
132: } else {
133: throw new Exception(
134: "Container: Non-terminating recursion detected in widget definition: "
135: + parent.getId() + " ("
136: + location + ")");
137: }
138: }
139: }
140: }
141: }
142: }
143:
144: public void createWidget(Widget parent, String id) {
145: WidgetDefinition widgetDefinition = (WidgetDefinition) widgetDefinitionsById
146: .get(id);
147: if (widgetDefinition == null) {
148: throw new RuntimeException(definition.getId()
149: + ": WidgetDefinition \"" + id
150: + "\" does not exist (" + definition.getLocation()
151: + ")");
152: }
153: Widget widget = widgetDefinition.createInstance();
154: if (widget != null)
155: ((ContainerWidget) parent).addWidget(widget);
156: }
157:
158: public void createWidgets(Widget parent) {
159: Iterator definitionsIt = widgetDefinitions.iterator();
160: while (definitionsIt.hasNext()) {
161: WidgetDefinition widgetDefinition = (WidgetDefinition) definitionsIt
162: .next();
163: Widget widget = widgetDefinition.createInstance();
164: if (widget != null)
165: ((ContainerWidget) parent).addWidget(widget);
166: }
167: }
168: }
|