1/*
2 * Copyright (C) 2012 The Guava Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.google.common.collect;
18
19import com.google.common.annotations.GwtCompatible;
20
21import java.util.Comparator;
22import java.util.Iterator;
23import java.util.NavigableSet;
24import java.util.Set;
25
26/**
27 * A skeleton implementation of a descending multiset.  Only needs
28 * {@code forwardMultiset()} and {@code entryIterator()}.
29 *
30 * @author Louis Wasserman
31 */
32@GwtCompatible(emulated = true)
33abstract class DescendingMultiset<E> extends ForwardingMultiset<E>
34    implements SortedMultiset<E> {
35  abstract SortedMultiset<E> forwardMultiset();
36
37  private transient Comparator<? super E> comparator;
38
39  @Override public Comparator<? super E> comparator() {
40    Comparator<? super E> result = comparator;
41    if (result == null) {
42      return comparator =
43          Ordering.from(forwardMultiset().comparator()).<E>reverse();
44    }
45    return result;
46  }
47
48  private transient NavigableSet<E> elementSet;
49
50  @Override public NavigableSet<E> elementSet() {
51    NavigableSet<E> result = elementSet;
52    if (result == null) {
53      return elementSet = new SortedMultisets.NavigableElementSet<E>(this);
54    }
55    return result;
56  }
57
58  @Override public Entry<E> pollFirstEntry() {
59    return forwardMultiset().pollLastEntry();
60  }
61
62  @Override public Entry<E> pollLastEntry() {
63    return forwardMultiset().pollFirstEntry();
64  }
65
66  @Override public SortedMultiset<E> headMultiset(E toElement,
67      BoundType boundType) {
68    return forwardMultiset().tailMultiset(toElement, boundType)
69        .descendingMultiset();
70  }
71
72  @Override public SortedMultiset<E> subMultiset(E fromElement,
73      BoundType fromBoundType, E toElement, BoundType toBoundType) {
74    return forwardMultiset().subMultiset(toElement, toBoundType, fromElement,
75        fromBoundType).descendingMultiset();
76  }
77
78  @Override public SortedMultiset<E> tailMultiset(E fromElement,
79      BoundType boundType) {
80    return forwardMultiset().headMultiset(fromElement, boundType)
81        .descendingMultiset();
82  }
83
84  @Override protected Multiset<E> delegate() {
85    return forwardMultiset();
86  }
87
88  @Override public SortedMultiset<E> descendingMultiset() {
89    return forwardMultiset();
90  }
91
92  @Override public Entry<E> firstEntry() {
93    return forwardMultiset().lastEntry();
94  }
95
96  @Override public Entry<E> lastEntry() {
97    return forwardMultiset().firstEntry();
98  }
99
100  abstract Iterator<Entry<E>> entryIterator();
101
102  private transient Set<Entry<E>> entrySet;
103
104  @Override public Set<Entry<E>> entrySet() {
105    Set<Entry<E>> result = entrySet;
106    return (result == null) ? entrySet = createEntrySet() : result;
107  }
108
109  Set<Entry<E>> createEntrySet() {
110    return new Multisets.EntrySet<E>() {
111      @Override Multiset<E> multiset() {
112        return DescendingMultiset.this;
113      }
114
115      @Override public Iterator<Entry<E>> iterator() {
116        return entryIterator();
117      }
118
119      @Override public int size() {
120        return forwardMultiset().entrySet().size();
121      }
122    };
123  }
124
125  @Override public Iterator<E> iterator() {
126    return Multisets.iteratorImpl(this);
127  }
128
129  @Override public Object[] toArray() {
130    return standardToArray();
131  }
132
133  @Override public <T> T[] toArray(T[] array) {
134    return standardToArray(array);
135  }
136
137  @Override public String toString() {
138    return entrySet().toString();
139  }
140}