/**
* This file is part of the JCROM project.
* Copyright (C) 2008-2014 - All rights reserved.
* Authors: Olafur Gauti Gudmundsson, Nicolas Dos Santos
*
* Licensed 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.jcrom.util;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.jcr.Node;
/**
*
* @author Olafur Gauti Gudmundsson
* @author Nicolas Dos Santos
*/
public class NodeFilter implements Serializable {
private static final long serialVersionUID = 1L;
public static final int DEPTH_INFINITE = -1;
public static final String INCLUDE_ALL = "*";
public static final String EXCLUDE_ALL = "none";
public static final String PROPERTY_PREFIX = "prop:";
protected final NameFilter nameFilter;
protected final int maxDepth;
protected final int filterDepth;
private final List<String> nodeNameStack = new ArrayList<String>();
/**
*
* @param fieldNameFilter comma separated list of names of child nodes / references to load
* ("*" loads all, while "none" loads none, and a prefix of "-" excludes the named nodes)
* @param maxDepth the maximum depth of loaded child nodes (0 means no child nodes are loaded,
* while a negative value means that no restrictions are set on the depth).
* @param filterDepth the depth down to which the filter applies. If we are deeper than this,
* then the filter will be ignored. This is useful for example when you want to filter immediate children,
* but then load everything below unfiltered.
*/
public NodeFilter(String fieldNameFilter, int maxDepth, int filterDepth) {
this.nameFilter = new NameFilter(fieldNameFilter);
this.maxDepth = maxDepth;
this.filterDepth = filterDepth;
}
public NodeFilter(String fieldNameFilter, int maxDepth) {
this(fieldNameFilter, maxDepth, DEPTH_INFINITE);
}
public NodeFilter(String fieldNameFilter) {
this(fieldNameFilter, DEPTH_INFINITE, DEPTH_INFINITE);
}
public NodeFilter(int maxDepth) {
this(INCLUDE_ALL, maxDepth, DEPTH_INFINITE);
}
public boolean isIncluded(String name, int depth) {
// return isDepthIncluded(depth) && isNameIncluded(name);
boolean isIncluded = isDepthIncluded(depth) && isNameIncluded(name);
if (isIncluded) {
int size = nodeNameStack.size();
if (depth < size) {
List<String> tmp = new ArrayList<String>();
for (int i = 0; i < depth; i++) {
tmp.add(nodeNameStack.get(i));
}
tmp.add(name);
nodeNameStack.clear();
nodeNameStack.addAll(tmp);
} else if (depth == size) {
nodeNameStack.add(name);
} else {
throw new IndexOutOfBoundsException("Could not add node name: Index: " + depth + ", Size: " + size);
}
}
return isIncluded;
}
public boolean isIncluded(String propName, Node parentNode, int depth) {
boolean isIncluded = isDepthPropertyIncluded(depth) && isNameIncluded(propName);
if (!isIncluded) {
try {
Node rootNode = parentNode.getSession().getRootNode();
Node parent = parentNode;
while (parent != null && !rootNode.getIdentifier().equals(parent.getIdentifier())) {
String parentName = parent.getName();
// Check whether one of parent node is included
for (String nodeName : nodeNameStack) {
if (nodeName.equals(parentName)) {
isIncluded = true;
break;
}
}
parent = parent.getParent();
}
} catch (Exception e) {
System.err.println(e.getMessage());
e.printStackTrace();
}
}
return isIncluded;
}
public boolean isDepthIncluded(int depth) {
if (filterDepth > DEPTH_INFINITE && depth > filterDepth) {
return true;
} else {
return maxDepth == DEPTH_INFINITE || depth < maxDepth;
}
}
public boolean isDepthPropertyIncluded(int depth) {
if (filterDepth > DEPTH_INFINITE && depth >= filterDepth) {
return true;
} else {
return maxDepth == DEPTH_INFINITE || depth <= maxDepth;
}
}
public boolean isNameIncluded(String name) {
return nameFilter.isIncluded(name);
}
public int getFilterDepth() {
return filterDepth;
}
public int getMaxDepth() {
return maxDepth;
}
public NameFilter getNameFilter() {
return nameFilter;
}
}