577405af48951932d1be5e77a315b07a1ea9c2ee
[idea/community.git] / platform / util / src / com / intellij / util / UniqueResultsQuery.java
1 /*
2  * Copyright 2000-2009 JetBrains s.r.o.
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
17 package com.intellij.util;
18
19 import com.intellij.util.containers.ConcurrentHashSet;
20 import gnu.trove.TObjectHashingStrategy;
21 import org.jetbrains.annotations.NotNull;
22
23 import java.util.Collection;
24 import java.util.Iterator;
25 import java.util.Set;
26
27 /**
28  * @author max
29  */
30 public class UniqueResultsQuery<T, M> implements Query<T> {
31   private final Query<T> myOriginal;
32   private final TObjectHashingStrategy<M> myHashingStrategy;
33   private final Function<T, M> myMapper;
34
35   public final static Function ID = new Function() {
36     public Object fun(Object o) {
37       return o;
38     }
39   };
40
41   public UniqueResultsQuery(final Query<T> original) {
42     //noinspection unchecked
43     this(original, TObjectHashingStrategy.CANONICAL, ID);
44   }
45
46   public UniqueResultsQuery(final Query<T> original, TObjectHashingStrategy<M> hashingStrategy) {
47     //noinspection unchecked
48     this(original, hashingStrategy, ID);
49   }
50
51   public UniqueResultsQuery(final Query<T> original, TObjectHashingStrategy<M> hashingStrategy, Function<T, M> mapper) {
52     myOriginal = original;
53     myHashingStrategy = hashingStrategy;
54     myMapper = mapper;
55   }
56
57   public T findFirst() {
58     return myOriginal.findFirst();
59   }
60
61   public boolean forEach(@NotNull final Processor<T> consumer) {
62     final Set<M> processedElements = new ConcurrentHashSet<M>(myHashingStrategy);
63     return myOriginal.forEach(new Processor<T>() {
64       public boolean process(final T t) {
65         return !processedElements.add(myMapper.fun(t)) || consumer.process(t);
66       }
67     });
68   }
69
70   @NotNull
71   public Collection<T> findAll() {
72     final CommonProcessors.CollectProcessor<T> processor = new CommonProcessors.CollectProcessor<T>();
73     forEach(processor);
74     return processor.getResults();
75   }
76
77   public T[] toArray(final T[] a) {
78     return findAll().toArray(a);
79   }
80
81   public Iterator<T> iterator() {
82     return findAll().iterator();
83   }
84 }