blob: 16d26e3814e8c89c18b49bae57a1885a4cad6882 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cocoon.woody.formmodel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
// TODO: Refine and i18n the exception messages.
/**
* Helper class for the Definition implementation of widgets containing
* other widgets.
*
* @version $Id$
*/
public class ContainerDefinitionDelegate {
private List widgetDefinitions = new ArrayList();
private Map widgetDefinitionsById = new HashMap();
private WidgetDefinition definition;
private boolean resolving;
private ListIterator definitionsIt = widgetDefinitions.listIterator();
/**
* @param definition the widget definition to which this container delegate belongs
*/
public ContainerDefinitionDelegate(WidgetDefinition definition) {
this.definition = definition;
resolving = false;
}
public void addWidgetDefinition(WidgetDefinition widgetDefinition) throws DuplicateIdException {
String id = widgetDefinition.getId();
// Do not add NewDefinition id's hash.
if (!(widgetDefinition instanceof NewDefinition)) {
if (widgetDefinitionsById.containsKey(id)) {
String duplicateLocation = widgetDefinition.getLocation();
String containerLocation = definition.getLocation();
String firstLocation = getWidgetDefinition(id).getLocation();
throw new DuplicateIdException(
"Duplicate widget id \"" + id + "\" detected at " + duplicateLocation + ".\n" +
"Container widget \"" + definition.getId() + "\" at " + containerLocation + "\n" +
"already contains a widget with id \"" + id + "\" at " + firstLocation + ".");
}
widgetDefinitionsById.put(widgetDefinition.getId(), widgetDefinition);
}
this.definitionsIt.add(widgetDefinition);
}
public List getWidgetDefinitions() {
return widgetDefinitions;
}
public boolean hasWidget(String id) {
return widgetDefinitionsById.containsKey(id);
}
public WidgetDefinition getWidgetDefinition(String id) {
return (WidgetDefinition)widgetDefinitionsById.get(id);
}
public boolean isResolving() {
return resolving;
}
public void resolve(List parents, WidgetDefinition parent) throws Exception {
if (!resolving) {
resolving = true;
this.definitionsIt = widgetDefinitions.listIterator();
parents.add(definition);
while (this.definitionsIt.hasNext()) {
WidgetDefinition widgetDefinition = (WidgetDefinition)this.definitionsIt.next();
// ClassDefinition's get resolved by NewDefinition rather than here.
if (!(widgetDefinition instanceof ClassDefinition)) {
if (widgetDefinition instanceof NewDefinition) {
// Remove NewDefinition in preparation for its referenced class of widget definitions to be added.
this.definitionsIt.remove();
((NewDefinition)widgetDefinition).resolve(parents, definition);
} else {
if (widgetDefinition instanceof ContainerDefinition)
((ContainerDefinition)widgetDefinition).resolve(parents, definition);
}
}
}
parents.remove(parents.size()-1);
resolving = false;
} else {
// Non-terminating recursion detection
if (resolving == true) {
// Search up parent list in hopes of finding a "Union" before finding previous "New" for this "Class".
ListIterator parentsIt = parents.listIterator(parents.size());
while(parentsIt.hasPrevious()) {
WidgetDefinition widgetDefinition = (WidgetDefinition)parentsIt.previous();
if (widgetDefinition instanceof UnionDefinition) break;
if (widgetDefinition == definition) {
String location = definition.getLocation();
if (parent instanceof FormDefinition) {
throw new Exception("Container: Non-terminating recursion detected in form definition (" + location + ")");
} else {
throw new Exception("Container: Non-terminating recursion detected in widget definition: "
+ parent.getId() + " (" + location + ")");
}
}
}
}
}
}
public void createWidget(Widget parent, String id) {
WidgetDefinition widgetDefinition = (WidgetDefinition)widgetDefinitionsById.get(id);
if (widgetDefinition == null) {
throw new RuntimeException(definition.getId() + ": WidgetDefinition \"" + id +
"\" does not exist (" + definition.getLocation() + ")");
}
Widget widget = widgetDefinition.createInstance();
if (widget != null)
((ContainerWidget)parent).addWidget(widget);
}
public void createWidgets(Widget parent) {
Iterator definitionsIt = widgetDefinitions.iterator();
while (definitionsIt.hasNext()) {
WidgetDefinition widgetDefinition = (WidgetDefinition)definitionsIt.next();
Widget widget = widgetDefinition.createInstance();
if (widget != null)
((ContainerWidget)parent).addWidget(widget);
}
}
}