blob: d769cca280b0ccef642390b199c42aa786bf444b [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.jackrabbit.vault.fs.impl.aggregator;
import java.util.Collection;
import javax.jcr.Node;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import org.apache.jackrabbit.vault.fs.api.Aggregate;
import org.apache.jackrabbit.vault.fs.api.Aggregator;
import org.apache.jackrabbit.vault.fs.api.Artifact;
import org.apache.jackrabbit.vault.fs.api.ArtifactSet;
import org.apache.jackrabbit.vault.fs.api.ArtifactType;
import org.apache.jackrabbit.vault.fs.api.DumpContext;
import org.apache.jackrabbit.vault.fs.api.Dumpable;
import org.apache.jackrabbit.vault.fs.api.ImportInfo;
import org.apache.jackrabbit.vault.fs.api.ItemFilterSet;
import org.apache.jackrabbit.vault.fs.impl.ArtifactSetImpl;
import org.apache.jackrabbit.vault.fs.impl.DirectoryArtifact;
import org.apache.jackrabbit.vault.fs.impl.io.DocViewSerializer;
import org.apache.jackrabbit.vault.fs.impl.io.ImportInfoImpl;
import org.apache.jackrabbit.vault.fs.io.Serializer;
import org.apache.jackrabbit.vault.fs.spi.ACLManagement;
import org.apache.jackrabbit.vault.fs.spi.ServiceProviderFactory;
import org.apache.jackrabbit.vault.util.Constants;
import org.apache.jackrabbit.vault.util.PathUtil;
/**
*/
public class GenericAggregator implements Aggregator, Dumpable {
/**
* name hint for the aggregator
*/
private String name;
/**
* flag indicating if this aggregator aggregates children
*/
private boolean fullCoverage = false;
/**
* filter that regulates what to be included in the aggregate
*/
private final ItemFilterSet contentFilter = new ItemFilterSet();
/**
* filter that regulates if this aggregator is to be used
*/
private final ItemFilterSet matchFilter = new ItemFilterSet();
/**
* the 'default' aggregator flag
*/
private boolean isDefault = false;
/**
* acl management
*/
private ACLManagement aclManagement;
private ACLManagement getAclManagement() {
if (aclManagement == null) {
aclManagement = ServiceProviderFactory.getProvider().getACLManagement();
}
return aclManagement;
}
/**
* {@inheritDoc}
*/
public boolean hasFullCoverage() {
return fullCoverage;
}
public void setHasFullCoverage(String hasFullCoverage) {
this.fullCoverage = Boolean.valueOf(hasFullCoverage);
}
/**
* {@inheritDoc}
*/
public boolean isDefault() {
return isDefault;
}
/**
* Sets the default flag
* @param aDefault the default flag
*/
public void setIsDefault(String aDefault) {
isDefault = Boolean.valueOf(aDefault);
}
/**
* Returns the name of this aggregator
* @return the name
*/
public String getName() {
return name;
}
/**
* Sets the name of this aggregator
* @param name the name
*/
public void setName(String name) {
this.name = name;
}
/**
* Sets the flag indicating if this aggregator aggregates children
*
* @param fullCoverage {@code true} if this aggregator aggregates
* children
*/
public void setFullCoverage(String fullCoverage) {
this.fullCoverage = Boolean.valueOf(fullCoverage);
}
/**
* Returns the content filter
* @return the content filter
*/
public ItemFilterSet getContentFilter() {
return contentFilter;
}
/**
* Returns the match filter
* @return the match filter
*/
public ItemFilterSet getMatchFilter() {
return matchFilter;
}
/**
* {@inheritDoc}
*/
public boolean includes(Node root, Node node, String path) throws RepositoryException {
if (path == null) {
path = node.getPath();
}
return contentFilter.contains(node, path, PathUtil.getDepth(path) - root.getDepth());
}
/**
* {@inheritDoc}
*/
public boolean matches(Node node, String path) throws RepositoryException {
return matchFilter.contains(node, path, 0);
}
/**
* {@inheritDoc}
*/
public boolean includes(Node root, Node parent, Property property, String path) throws RepositoryException {
if (path == null) {
path = property.getPath();
}
return contentFilter.contains(property, path, PathUtil.getDepth(path) - root.getDepth());
}
/**
* {@inheritDoc}
*/
public ArtifactSet createArtifacts(Aggregate aggregate) throws RepositoryException {
ArtifactSetImpl artifacts = new ArtifactSetImpl();
// set coverage filter to artifacts
artifacts.setCoverage(getContentFilter());
// add directory
ArtifactType type = ArtifactType.PRIMARY;
String name = aggregate.getName();
String ext = ".xml";
Artifact parent = null;
if (!hasFullCoverage()) {
parent = new DirectoryArtifact(name);
artifacts.add(parent);
name = "";
ext = Constants.DOT_CONTENT_XML;
// special optimization if only nt:folder
if ("nt:folder".equals(aggregate.getNode().getPrimaryNodeType().getName())
&& aggregate.getNode().getMixinNodeTypes().length == 0) {
return artifacts;
}
}
// add extra
Serializer ser = new DocViewSerializer(aggregate);
artifacts.add(parent, name, ext, type, ser, 0);
// add binaries
Collection<Property> bins = aggregate.getBinaries();
if (bins != null && !bins.isEmpty()) {
if (hasFullCoverage()) {
assert parent == null;
parent = new DirectoryArtifact(aggregate.getName());
artifacts.add(parent);
}
int pathLen = aggregate.getPath().length();
if (pathLen > 1) {
pathLen++;
}
for (Property prop: bins) {
String relPath = prop.getPath().substring(pathLen);
artifacts.add(parent, relPath, ".binary", ArtifactType.BINARY, prop, 0);
}
}
return artifacts;
}
/**
* {@inheritDoc}
*
* Throws an exception if this aggregator allows children but
* {@code recursive} is {@code false}.
*/
public ImportInfo remove(Node node, boolean recursive, boolean trySave)
throws RepositoryException {
if (fullCoverage && !recursive) {
// todo: allow smarter removal
throw new RepositoryException("Unable to remove content since aggregation has children and recursive is not set.");
}
ImportInfo info = new ImportInfoImpl();
info.onDeleted(node.getPath());
Node parent = node.getParent();
if (getAclManagement().isACLNode(node)) {
getAclManagement().clearACL(parent);
} else {
node.remove();
}
if (trySave) {
parent.getSession().save();
}
return info;
}
/**
* {@inheritDoc}
*/
public void dump(DumpContext ctx, boolean isLast) {
ctx.println(isLast, getClass().getSimpleName());
ctx.indent(isLast);
ctx.printf(false, "name: %s", getName());
ctx.printf(false, "fullCoverage: %b", hasFullCoverage());
ctx.printf(false, "default: %b", isDefault());
ctx.println(false, "Content Filter");
ctx.indent(false);
getContentFilter().dump(ctx, true);
ctx.outdent();
ctx.println(true, "Match Filter");
ctx.indent(true);
getMatchFilter().dump(ctx, true);
ctx.outdent();
ctx.outdent();
}
}