All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.permazen.util.ConvertedNavigableSet Maven / Gradle / Ivy

The newest version!

/*
 * Copyright (C) 2015 Archie L. Cobbs. All rights reserved.
 */

package io.permazen.util;

import com.google.common.base.Converter;
import com.google.common.base.Preconditions;
import com.google.common.collect.Iterators;

import java.util.Comparator;
import java.util.Iterator;
import java.util.NavigableSet;
import java.util.NoSuchElementException;
import java.util.Spliterator;
import java.util.stream.Stream;

/**
 * Provides a transformed view of a wrapped {@link NavigableSet} using a strictly invertable {@link Converter}.
 *
 * 

* Supplied {@link Converter}s may throw {@link ClassCastException} or {@link IllegalArgumentException} * if given an objects whose runtime type does not match the expected type. * * @param element type of this set * @param element type of the wrapped set */ public class ConvertedNavigableSet extends AbstractNavigableSet { private final NavigableSet set; private final Converter converter; /** * Constructor. * * @param set wrapped set * @param converter element converter * @throws IllegalArgumentException if either parameter is null */ public ConvertedNavigableSet(NavigableSet set, Converter converter) { this(set, converter, new Bounds<>()); } /** * Internal constructor. * * @param set wrapped set * @param converter element converter * @throws IllegalArgumentException if any parameter is null */ ConvertedNavigableSet(NavigableSet set, Converter converter, Bounds bounds) { super(bounds); Preconditions.checkArgument(set != null, "null set"); Preconditions.checkArgument(converter != null, "null converter"); this.set = set; this.converter = converter; } /** * Get the wrapped {@link NavigableSet}. * * @return the wrapped {@link NavigableSet}. */ public NavigableSet getWrappedNavigableSet() { return this.set; } /** * Get the {@link Converter} associated with this instance. * * @return associated {@link Converter} */ public Converter getConverter() { return this.converter; } @Override public Comparator comparator() { return new ConvertedComparator(this.set.comparator(), this.converter); } @Override @SuppressWarnings("unchecked") public boolean contains(Object obj) { W wobj = null; if (obj != null) { try { wobj = this.converter.convert((E)obj); } catch (IllegalArgumentException | ClassCastException e) { return false; } } return this.set.contains(wobj); } @Override public CloseableIterator iterator() { final Iterator wrappedIterator = this.set.iterator(); final Iterator convertedIterator = Iterators.transform(wrappedIterator, this.converter.reverse()); return wrappedIterator instanceof CloseableIterator ? CloseableIterator.wrap(convertedIterator, (CloseableIterator)wrappedIterator) : CloseableIterator.wrap(convertedIterator); } @Override public Spliterator spliterator() { return new ConvertedSpliterator(this.set.spliterator(), this.converter.reverse()); } @Override public Stream stream() { return this.set.stream().map(this.converter.reverse()::convert); } @Override public boolean add(E obj) { return this.set.add(obj != null ? this.converter.convert(obj) : null); } @Override @SuppressWarnings("unchecked") public boolean remove(Object obj) { W wobj = null; if (obj != null) { try { wobj = this.converter.convert((E)obj); } catch (IllegalArgumentException | ClassCastException e) { return false; } } return this.set.remove(wobj); } @Override public void clear() { this.set.clear(); } @Override public boolean isEmpty() { return this.set.isEmpty(); } @Override public int size() { return this.set.size(); } @Override protected E searchBelow(E elem, boolean inclusive) { try { return super.searchBelow(elem, inclusive); } catch (IllegalArgumentException e) { // handle case where elem is out of bounds final E last; try { last = this.last(); } catch (NoSuchElementException e2) { return null; } return this.getComparator(false).compare(elem, last) > 0 ? last : null; } } @Override protected E searchAbove(E elem, boolean inclusive) { try { return super.searchAbove(elem, inclusive); } catch (IllegalArgumentException e) { // handle case where elem is out of bounds final E first; try { first = this.first(); } catch (NoSuchElementException e2) { return null; } return this.getComparator(false).compare(elem, first) < 0 ? first : null; } } @Override protected NavigableSet createSubSet(boolean reverse, Bounds newBounds) { final E lower = newBounds.getLowerBound(); final E upper = newBounds.getUpperBound(); final W wlower = newBounds.getLowerBoundType() != BoundType.NONE && lower != null ? this.converter.convert(lower) : null; final W wupper = newBounds.getUpperBoundType() != BoundType.NONE && upper != null ? this.converter.convert(upper) : null; NavigableSet subSet = reverse ? this.set.descendingSet() : this.set; if (newBounds.getLowerBoundType() != BoundType.NONE && newBounds.getUpperBoundType() != BoundType.NONE) { subSet = subSet.subSet( wlower, newBounds.getLowerBoundType().isInclusive(), wupper, newBounds.getUpperBoundType().isInclusive()); } else if (newBounds.getLowerBoundType() != BoundType.NONE) subSet = subSet.tailSet(wlower, newBounds.getLowerBoundType().isInclusive()); else if (newBounds.getUpperBoundType() != BoundType.NONE) subSet = subSet.headSet(wupper, newBounds.getUpperBoundType().isInclusive()); return new ConvertedNavigableSet<>(subSet, this.converter, newBounds); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy