blob: 2121bfde61831e802c1d502349ea39e77fbf575d [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.forms.formmodel.tree;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.apache.avalon.framework.CascadingRuntimeException;
import org.apache.cocoon.util.WildcardMatcherHelper;
import org.apache.excalibur.source.SourceException;
import org.apache.excalibur.source.SourceResolver;
import org.apache.excalibur.source.TraversableSource;
/**
* A {@link TreeModel} that builds a hierarchy of <code>TraversableSource</code>s.
*
* @version $Id$
*/
public class SourceTreeModel implements TreeModel {
private TreeModelHelper helper = new TreeModelHelper(this);
private List fileIncludePatterns;
private List fileExcludePatterns;
private List dirIncludePatterns;
private List dirExcludePatterns;
/** optimization hint: don't filter child collections if there are no patterns */
private boolean hasPatterns = false;
private TraversableSource rootSource;
private String rootURL;
private SourceResolver resolver;
public SourceTreeModel(SourceResolver resolver, String rootURL) {
this.resolver = resolver;
this.rootURL = rootURL;
}
public SourceTreeModel(SourceTreeModelDefinition definition) {
this.rootURL = definition.getRootURL();
this.resolver = definition.getResolver();
this.fileIncludePatterns = definition.getFileIncludePatterns();
this.fileExcludePatterns = definition.getFileExcludePatterns();
this.dirIncludePatterns = definition.getDirectoryIncludePatterns();
this.dirExcludePatterns = definition.getDirectoryExcludePatterns();
this.hasPatterns = this.fileIncludePatterns != null || this.fileExcludePatterns != null ||
this.dirIncludePatterns != null || this.dirExcludePatterns != null;
}
public Object getRoot() {
if (this.rootSource == null) {
try {
this.rootSource = (TraversableSource) this.resolver.resolveURI(this.rootURL);
} catch (Exception e) {
throw new CascadingRuntimeException("Cannot resolve " + this.rootURL, e);
}
}
return this.rootSource;
}
public Collection getChildren(Object parent) {
if (parent instanceof TraversableSource) {
TraversableSource dir = (TraversableSource)parent;
try {
// Return children if it's a collection, null otherwise
return dir.isCollection() ? filterChildren(dir.getChildren()) : null;
} catch (SourceException e) {
throw new CascadingRuntimeException("getChildren", e);
}
} else {
return null;
}
}
private Collection filterChildren(Collection coll) {
if (!this.hasPatterns) {
return coll;
}
ArrayList result = new ArrayList();
Iterator iter = coll.iterator();
while(iter.hasNext()) {
TraversableSource src = (TraversableSource)iter.next();
// Does it match the patterns?
boolean matches = true;
if (src.isCollection()) {
matches = matches(src, this.dirIncludePatterns, this.dirExcludePatterns);
} else {
matches = matches(src, this.fileIncludePatterns, this.fileExcludePatterns);
}
if (matches) {
result.add(src);
}
}
return result;
}
private boolean matches(TraversableSource src, List includes, List excludes) {
boolean matches = true;
final String name = src.getName();
// check include patterns
if (includes != null && includes.size() > 0) {
matches = false;
check: for (int i = 0; i < includes.size(); i++) {
if (WildcardMatcherHelper.match((String)includes.get(i), name) != null) {
matches = true;
break check;
}
}
}
// check exclude patterns
if (matches && excludes != null && excludes.size() > 0) {
check: for (int i = 0; i < excludes.size(); i++) {
if (WildcardMatcherHelper.match((String)excludes.get(i), name) != null) {
matches = false;
break check;
}
}
}
return matches;
}
public boolean isLeaf(Object obj) {
return !(obj instanceof TraversableSource) || !((TraversableSource)obj).isCollection();
}
public String getChildKey(Object parent, Object child) {
return ((TraversableSource)child).getName();
}
public Object getChild(Object parent, String key) {
try {
return ((TraversableSource)parent).getChild(key);
} catch (SourceException e) {
throw new CascadingRuntimeException("getChild", e);
}
}
public void setRootURL(String url) {
if (this.rootSource != null) {
this.resolver.release(this.rootSource);
this.rootSource = null;
}
this.rootURL = url;
helper.fireTreeStructureChanged(TreePath.ROOT_PATH);
}
public void setRootSource(TraversableSource src) {
this.rootSource = src;
helper.fireTreeStructureChanged(TreePath.ROOT_PATH);
}
public void addTreeModelListener(TreeModelListener l) {
helper.addTreeModelListener(l);
}
public void removeTreeModelListener(TreeModelListener l) {
helper.removeTreeModelListener(l);
}
public Object getNode(TreePath path) {
// FIXME: can be heavily optimized by building a new URL from the path elements.
return helper.getNode(path);
}
}