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.components.treeprocessor.sitemap;
018:
019: import java.util.ArrayList;
020: import java.util.Collection;
021: import java.util.HashMap;
022: import java.util.HashSet;
023: import java.util.Iterator;
024: import java.util.List;
025: import java.util.Map;
026:
027: import org.apache.avalon.framework.configuration.Configuration;
028: import org.apache.avalon.framework.configuration.ConfigurationException;
029: import org.apache.cocoon.components.treeprocessor.AbstractProcessingNodeBuilder;
030: import org.apache.cocoon.components.treeprocessor.LinkedProcessingNodeBuilder;
031: import org.apache.cocoon.components.treeprocessor.ProcessingNode;
032: import org.apache.cocoon.components.treeprocessor.variables.VariableResolverFactory;
033:
034: /**
035: * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
036: * @version $Id: AggregateNodeBuilder.java 433543 2006-08-22 06:22:54Z crossley $
037: */
038: public class AggregateNodeBuilder extends AbstractProcessingNodeBuilder
039: implements LinkedProcessingNodeBuilder {
040:
041: /** The views for the aggregate element */
042: private Collection views;
043:
044: /** The built node */
045: private AggregateNode node;
046:
047: public ProcessingNode buildNode(Configuration config)
048: throws Exception {
049:
050: // Get root node data
051: this .node = new AggregateNode(VariableResolverFactory
052: .getResolver(config.getAttribute("element"),
053: this .manager), VariableResolverFactory
054: .getResolver(config.getAttribute("ns", ""),
055: this .manager), VariableResolverFactory
056: .getResolver(config.getAttribute("prefix", ""),
057: this .manager));
058: this .treeBuilder.setupNode(this .node, config);
059:
060: this .views = ((SitemapLanguage) this .treeBuilder)
061: .getViewsForStatement("", "", config);
062:
063: // Bug #7196 : ensure this.views is never null (see continuation of fix below)
064: if (this .views == null) {
065: this .views = new HashSet();
066: }
067:
068: // The sitemap builder
069: SitemapLanguage sitemap = (SitemapLanguage) this .treeBuilder;
070:
071: // All parts of the aggregate
072: List allParts = new ArrayList();
073:
074: // For each view that a part matches, the list of all parts that match it
075: Map viewParts = new HashMap();
076:
077: Configuration[] childConfigs = config.getChildren();
078: for (int i = 0; i < childConfigs.length; i++) {
079: Configuration childConfig = childConfigs[i];
080:
081: if (!"part".equals(childConfig.getName())) {
082: String msg = "Unknown element '"
083: + childConfig.getName() + " in aggregate ' at "
084: + childConfig.getLocation();
085: throw new ConfigurationException(msg);
086: }
087:
088: checkNamespace(childConfig);
089:
090: AggregateNode.Part currentPart = new AggregateNode.Part(
091: VariableResolverFactory.getResolver(childConfig
092: .getAttribute("src"), this .manager),
093: VariableResolverFactory.getResolver(childConfig
094: .getAttribute("element", ""), this .manager),
095: VariableResolverFactory.getResolver(childConfig
096: .getAttribute("ns", ""), this .manager),
097: VariableResolverFactory.getResolver(childConfig
098: .getAttribute("prefix", ""), this .manager),
099: VariableResolverFactory.getResolver(childConfig
100: .getAttribute("strip-root", "false"),
101: this .manager));
102:
103: allParts.add(currentPart);
104:
105: // Get the views for this part
106: Collection viewsForPart = sitemap.getViewsForStatement("",
107: "", childConfig);
108:
109: // Associate this part to all the views it belongs to
110: if (viewsForPart != null) {
111:
112: // Bug #7196 : add part view to aggregate views
113: this .views.addAll(viewsForPart);
114:
115: Iterator iter = viewsForPart.iterator();
116: while (iter.hasNext()) {
117: String currentView = (String) iter.next();
118:
119: // Get collection of parts for current view
120: Collection currentViewParts = (Collection) viewParts
121: .get(currentView);
122: if (currentViewParts == null) {
123: // None for now : create the collection
124: currentViewParts = new ArrayList();
125: viewParts.put(currentView, currentViewParts);
126: }
127:
128: // Add the current part to the parts list of the view
129: currentViewParts.add(currentPart);
130: }
131: }
132: }
133:
134: if (allParts.size() == 0) {
135: String msg = "There must be at least one part in map:aggregate at "
136: + config.getLocation();
137: throw new ConfigurationException(msg);
138: }
139:
140: // Now convert all Collections to Array for faster traversal
141: AggregateNode.Part[] allPartsArray = (AggregateNode.Part[]) allParts
142: .toArray(new AggregateNode.Part[allParts.size()]);
143:
144: Iterator iter = viewParts.entrySet().iterator();
145: while (iter.hasNext()) {
146: Map.Entry entry = (Map.Entry) iter.next();
147:
148: // Get collection of parts for this entry
149: Collection coll = (Collection) entry.getValue();
150:
151: // Convert to array and replace the entry value
152: entry.setValue(coll.toArray(new AggregateNode.Part[coll
153: .size()]));
154: }
155:
156: node.setParts(allPartsArray, viewParts);
157:
158: return node;
159:
160: }
161:
162: public void linkNode() throws Exception {
163:
164: // Give the AggregateNode a Node for each view
165: SitemapLanguage sitemap = (SitemapLanguage) this.treeBuilder;
166:
167: this.node.setViewNodes(sitemap.getViewNodes(this.views));
168: }
169: }
|