1 /*
2  * Copyright 2012, Google Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *     * Neither the name of Google Inc. nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 package org.jf.util;
33 
34 import com.google.common.collect.ImmutableList;
35 import com.google.common.collect.ImmutableSet;
36 import com.google.common.collect.ImmutableSortedSet;
37 
38 import javax.annotation.Nonnull;
39 import javax.annotation.Nullable;
40 import java.util.Comparator;
41 import java.util.Iterator;
42 import java.util.SortedSet;
43 
44 public abstract class ImmutableConverter<ImmutableItem, Item> {
isImmutable(@onnull Item item)45     protected abstract boolean isImmutable(@Nonnull Item item);
makeImmutable(@onnull Item item)46     @Nonnull protected abstract ImmutableItem makeImmutable(@Nonnull Item item);
47 
48     @Nonnull
toList(@ullable final Iterable<? extends Item> iterable)49     public ImmutableList<ImmutableItem> toList(@Nullable final Iterable<? extends Item> iterable) {
50         if (iterable == null) {
51             return ImmutableList.of();
52         }
53 
54         boolean needsCopy = false;
55         if (iterable instanceof ImmutableList) {
56             for (Item element: iterable) {
57                 if (!isImmutable(element)) {
58                     needsCopy = true;
59                     break;
60                 }
61             }
62         } else {
63             needsCopy = true;
64         }
65 
66         if (!needsCopy) {
67             return (ImmutableList<ImmutableItem>)iterable;
68         }
69 
70         final Iterator<? extends Item> iter = iterable.iterator();
71 
72         return ImmutableList.copyOf(new Iterator<ImmutableItem>() {
73             @Override public boolean hasNext() { return iter.hasNext(); }
74             @Override public ImmutableItem next() { return makeImmutable(iter.next()); }
75             @Override public void remove() { iter.remove(); }
76         });
77     }
78 
79     @Nonnull
80     public ImmutableSet<ImmutableItem> toSet(@Nullable final Iterable<? extends Item> iterable) {
81         if (iterable == null) {
82             return ImmutableSet.of();
83         }
84 
85         boolean needsCopy = false;
86         if (iterable instanceof ImmutableSet) {
87             for (Item element: iterable) {
88                 if (!isImmutable(element)) {
89                     needsCopy = true;
90                     break;
91                 }
92             }
93         } else {
94             needsCopy = true;
95         }
96 
97         if (!needsCopy) {
98             return (ImmutableSet<ImmutableItem>)iterable;
99         }
100 
101         final Iterator<? extends Item> iter = iterable.iterator();
102 
103         return ImmutableSet.copyOf(new Iterator<ImmutableItem>() {
104             @Override public boolean hasNext() { return iter.hasNext(); }
105             @Override public ImmutableItem next() { return makeImmutable(iter.next()); }
106             @Override public void remove() { iter.remove(); }
107         });
108     }
109 
110     @Nonnull
111     public ImmutableSortedSet<ImmutableItem> toSortedSet(@Nonnull Comparator<? super ImmutableItem> comparator,
112                                                          @Nullable final Iterable<? extends Item> iterable) {
113         if (iterable == null) {
114             return ImmutableSortedSet.of();
115         }
116 
117         boolean needsCopy = false;
118         if (iterable instanceof ImmutableSortedSet &&
119                 ((ImmutableSortedSet)iterable).comparator().equals(comparator)) {
120             for (Item element: iterable) {
121                 if (!isImmutable(element)) {
122                     needsCopy = true;
123                     break;
124                 }
125             }
126         } else {
127             needsCopy = true;
128         }
129 
130         if (!needsCopy) {
131             return (ImmutableSortedSet<ImmutableItem>)iterable;
132         }
133 
134         final Iterator<? extends Item> iter = iterable.iterator();
135 
136 
137         return ImmutableSortedSet.copyOf(comparator, new Iterator<ImmutableItem>() {
138             @Override public boolean hasNext() { return iter.hasNext(); }
139             @Override public ImmutableItem next() { return makeImmutable(iter.next()); }
140             @Override public void remove() { iter.remove(); }
141         });
142     }
143 
144     @Nonnull
145     public SortedSet<ImmutableItem> toSortedSet(@Nonnull Comparator<? super ImmutableItem> comparator,
146                                                 @Nullable final SortedSet<? extends Item> sortedSet) {
147         if (sortedSet == null || sortedSet.size() == 0) {
148             return ImmutableSortedSet.of();
149         }
150 
151         @SuppressWarnings("unchecked")
152         ImmutableItem[] newItems = (ImmutableItem[])new Object[sortedSet.size()];
153         int index = 0;
154         for (Item item: sortedSet) {
155             newItems[index++] = makeImmutable(item);
156         }
157 
158         return ArraySortedSet.of(comparator, newItems);
159     }
160 }
161