| /* |
| * 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); |
| } |
| } |
| } |