/*
* Copyright (C) 2013 Google Inc.
*
* 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 interactivespaces.resource;
import com.google.common.collect.Lists;
import java.util.List;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentSkipListMap;
/**
* A collection of versioned resources.
*
* <p>
* This does not mean that everything in the collection implements {@link VersionedResource}. This allows the class to
* be used for anything.
*
* <p>
* This class is thread safe.
*
* @param <T>
* type of data in the collection
*
* @author Keith M. Hughes
*/
public class VersionedResourceCollection<T> {
/**
* Create a new versioned resource collection in a generic way.
*
* @param <T>
* the type of elements stored in the collection
*
* @return an empty resource collection
*/
public static <T> VersionedResourceCollection<T> newVersionedResourceCollection() {
return new VersionedResourceCollection<T>();
}
/**
* The resources in the collection.
*/
private final ConcurrentSkipListMap<Version, T> resources = new ConcurrentSkipListMap<Version, T>();
/**
* Add in a new resource for a given version.
*
* @param version
* the version of the resource
* @param resource
* the resource
*
* @return the old resource with that version, or {@code null} if none
*/
public T addResource(Version version, T resource) {
return resources.put(version, resource);
}
/**
* Get the resource with the given version, if any.
*
* @param version
* the version
*
* @return the resource with the version or {@code null} if none
*/
public T getResource(Version version) {
return resources.get(version);
}
/**
* Get the highest version of the collection that fits in the specified range.
*
* @param range
* the range
*
* @return the highest version in the range or {@code null} if there are no elements in the range
*/
public T getResource(VersionRange range) {
Entry<Version, T> result;
Version maximum = range.getMaximum();
if (maximum != null) {
// If inclusive, get the largest maximum that can also equal the maximum.
// Otherwise is exclusive so get the largest maximum that is less than the maximum.
result = range.isInclusive() ? resources.floorEntry(maximum) : resources.lowerEntry(maximum);
} else {
// Hard to be equal to infinity, so would always be the last entry.
result = resources.lastEntry();
}
if (result != null) {
if (range.getMinimum().lessThanOrEqual(result.getKey())) {
return result.getValue();
}
}
return null;
}
/**
* Get the highest version from the collection.
*
* @return the highest version or {@code null} if the collection is empty
*/
public T getHighestEntry() {
return resources.lastEntry().getValue();
}
/**
* Remove the resource for a given version.
*
* @param version
* the version of the resource
*
* @return the old resource with that version, or {@code null} if none
*/
public T removeResource(Version version) {
return resources.remove(version);
}
/**
* Get a list of all resources, ordered by version number.
*
* @return a newly constructed list
*/
public List<T> getAllResources() {
return Lists.newArrayList(resources.values());
}
}