blob: 92b3cb70602f4b2ab46ac0ee9ff89c97ecdef085 [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;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import org.apache.jackrabbit.vault.fs.PropertyValueArtifact;
import org.apache.jackrabbit.vault.fs.SerializerArtifact;
import org.apache.jackrabbit.vault.fs.api.Artifact;
import org.apache.jackrabbit.vault.fs.api.ArtifactIterator;
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.ItemFilter;
import org.apache.jackrabbit.vault.fs.api.ItemFilterSet;
import org.apache.jackrabbit.vault.fs.io.Serializer;
/**
* Implements a set of artifacts. The artifacts can be retrieved via an
* {@link ArtifactIterator}. Special artifacts like {@link ArtifactType#PRIMARY}
* and {@link ArtifactType#DIRECTORY} can be retrieved individually. This set
* only allows one of those artifacts per type.
*
* All modifications to this set have no influence on the persisted data.
*
*/
public class ArtifactSetImpl implements Dumpable, ArtifactSet {
/**
* the list of artifacts
*/
private final List<Artifact> artifacts = new LinkedList<Artifact>();
/**
* the list of removed
*/
private List<Artifact> removed;
/**
* Set of artifacts that are only allowed once
*/
private final Map<ArtifactType, Artifact> single = new EnumMap<ArtifactType, Artifact>(ArtifactType.class);
/**
* list of hint artifacts
*/
private Set<Artifact> hints;
/**
* The item filter set that defines the coverage of this artifact set
*/
private ItemFilterSet coverageFilter = (ItemFilterSet) new ItemFilterSet().addInclude(ItemFilter.ALL);
public ItemFilterSet getCoverage() {
return coverageFilter;
}
/**
* Sets the item filter set that defines the coverage of the items in
* this artifact set.
* @param filter the item filter set.
*/
public void setCoverage(ItemFilterSet filter) {
this.coverageFilter = filter;
}
public void addAll(Collection<? extends Artifact> artifacts) {
for (Artifact artifact: artifacts) {
add(artifact);
}
}
public void addAll(ArtifactSet artifacts) {
addAll(((ArtifactSetImpl) artifacts).artifacts);
}
public void add(Artifact artifact) {
ArtifactType type = artifact.getType();
if (type == ArtifactType.PRIMARY || type == ArtifactType.DIRECTORY) {
if (single.containsKey(type)) {
throw new IllegalArgumentException("Only 1 " + type + " artifact allowed.");
}
single.put(type, artifact);
artifacts.add(artifact);
} else if (type == ArtifactType.HINT) {
if (hints == null) {
hints = new HashSet<Artifact>();
}
hints.add(artifact);
} else {
artifacts.add(artifact);
}
}
/**
* Adds an {@link SerializerArtifact} with the given name, type and
* serializer.
*
* @param parent the parent artifact
* @param name the name of the artifact
* @param ext the extension of the artifact
* @param type the type of the artifact
* @param ser the serializer of the artifact
* @param lastModified the last modified date
* @return the added artifact
*/
public SerializerArtifact add(Artifact parent, String name, String ext,
ArtifactType type, Serializer ser,
long lastModified) {
SerializerArtifact a = new SerializerArtifact(parent, name, ext, type, ser, lastModified);
add(a);
return a;
}
/**
* Adds an {@link PropertyValueArtifact} with the given name, type and
* serializer
*
* @param parent parent artifact
* @param relPath the name of the artifact
* @param ext the extension
* @param type the type of the artifact
* @param prop the property of the artifact
* @param lastModified the last modified date. can be 0.
*
* @return a collection of artifacts
* @throws RepositoryException if an error occurs.
*/
public Collection<PropertyValueArtifact> add(Artifact parent, String relPath,
String ext, ArtifactType type, Property prop, long lastModified)
throws RepositoryException {
Collection<PropertyValueArtifact> a =
PropertyValueArtifact.create(parent, relPath, ext, type, prop, lastModified);
addAll(a);
return a;
}
public Artifact getPrimaryData() {
return single.get(ArtifactType.PRIMARY);
}
public Artifact getDirectory() {
return single.get(ArtifactType.DIRECTORY);
}
public boolean isEmpty() {
return artifacts.isEmpty();
}
public int size() {
return artifacts.size();
}
/**
* Removes the artifact from this set.
*
* @param a the artifact to remove
* @return <code>true</code> if the artifact was removed.
*/
public boolean remove(Artifact a) {
if (artifacts.remove(a)) {
single.remove(a.getType());
if (removed == null) {
removed = new LinkedList<Artifact>();
removed.add(a);
}
return true;
} else {
return false;
}
}
/**
* Puts the given artifact to this set. In comparison to the add operations,
* an already existing artifact is replaced. If the type of the newly
* artifact is {@link ArtifactType#BINARY} it equivalent with the
* same name is replaced.
*
* @param a the artifact to put
* @return the previous artifact or <code>null</code>
*/
public Artifact put(Artifact a) {
Artifact prev = null;
int idx = artifacts.indexOf(a);
if (idx >=0) {
prev = artifacts.remove(idx);
}
single.put(a.getType(), a);
artifacts.add(a);
return prev;
}
/**
* Returns the number of artifacts in this set that have the given type.
* @param type the artifact type
* @return the number of artifacts in this set that have the given type.
*/
public int size(ArtifactType type) {
int num = 0;
if (type == ArtifactType.HINT) {
num = hints == null ? 0 : hints.size();
} else {
for (Artifact a: artifacts) {
if (a.getType() == type) {
num++;
}
}
}
return num;
}
/**
* Returns a collection of all artifacts that have the given type.
* @param type the type of the artifacts to return
* @return the artifacts
*/
public Collection<Artifact> values(ArtifactType type) {
List<Artifact> ret = new LinkedList<Artifact>();
if (type == ArtifactType.HINT) {
if (hints != null) {
ret.addAll(hints);
}
} else {
for (Artifact a: artifacts) {
if (type == null || a.getType() == type) {
ret.add(a);
}
}
}
return ret;
}
/**
* Returns a collection of all artifacts
* @return the artifacts
*/
public Collection<Artifact> values() {
return Collections.unmodifiableList(artifacts);
}
/**
* Returns the collection of removed artifacts
* @return the removed artifacts
*/
public Collection<Artifact> removed() {
if (removed == null) {
return Collections.emptyList();
} else {
return Collections.unmodifiableList(removed);
}
}
/**
* {@inheritDoc}
*/
public String toString() {
StringBuilder buf = new StringBuilder("ArtifactSet={");
Iterator<Artifact> iter = artifacts.iterator();
while (iter.hasNext()) {
buf.append(iter.next());
if (iter.hasNext()) {
buf.append(", ");
}
}
buf.append('}');
return buf.toString();
}
/**
* Returns the artifact with the given path or <code>null</code> if it does
* not exist.
* @param path the name of the artifact.
* @return the desired artifact or <code>null</code>
*/
public Artifact getArtifact(String path) {
for (Artifact a: artifacts) {
if (a.getRelativePath().equals(path)) {
return a;
}
}
return null;
}
/**
* {@inheritDoc}
*/
public void dump(DumpContext ctx, boolean isLast) {
ctx.println(isLast, "Artifacts");
ctx.indent(isLast);
for (Artifact a: artifacts) {
a.dump(ctx, false);
}
ctx.println(true, "Coverage");
ctx.indent(true);
coverageFilter.dump(ctx, true);
ctx.outdent();
ctx.outdent();
}
}