1 /**
2 * Copyright 2005-2012 The Kuali Foundation
3 *
4 * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php
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 package org.kuali.rice.core.api.mo;
17
18 import org.apache.commons.collections.CollectionUtils;
19
20 import java.util.ArrayList;
21 import java.util.Collection;
22 import java.util.Collections;
23 import java.util.HashMap;
24 import java.util.HashSet;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Set;
28
29 /**
30 * A set of simple utilities to assist with common idioms in immutable model objects and their builders.
31 *
32 * @author Kuali Rice Team (rice.collab@kuali.org)
33 */
34 public class ModelObjectUtils {
35
36 /**
37 * Takes the given list of {@code ModelBuilder} objects and invokes the
38 * {@link org.kuali.rice.core.api.mo.ModelBuilder#build()} method on each of them, adding them to a new list and
39 * return an unmodifiable copy. If the given list is empty or null, will return an empty and unmodifiable list.
40 *
41 * @param builderList the list of builders to build and add to resulting list, may be empty or null
42 * @param <T> the type of the object that is built by the builders in the list, it is up to the caller of this
43 * method to ensure they define the proper parameterized list for the return type.
44 * @return an unmodifiable list containing objects built from the given list of model builders
45 */
46 public static <T> List<T> buildImmutableCopy(List<? extends ModelBuilder> builderList) {
47 if (CollectionUtils.isEmpty(builderList)) {
48 return Collections.emptyList();
49 }
50 List<T> copy = new ArrayList<T>();
51 for (ModelBuilder builder : builderList) {
52 // since ModelBuilder is not parameterized, this code must assume that the appropriate type of object is built
53 @SuppressWarnings("unchecked")
54 T built = (T)builder.build();
55 copy.add(built);
56 }
57 return Collections.unmodifiableList(copy);
58 }
59
60 @SuppressWarnings("unchecked")
61 public static <B> Set<B> buildImmutableCopy(Set<? extends ModelBuilder> toConvert) {
62 if (CollectionUtils.isEmpty(toConvert)) {
63 return Collections.emptySet();
64 } else {
65 Set<B> results = new HashSet<B>(toConvert.size());
66 for (ModelBuilder elem : toConvert) {
67 results.add((B)elem.build());
68 }
69 return Collections.unmodifiableSet(results);
70 }
71 }
72
73 /**
74 * Takes the given list and returns an unmodifiable copy of that list containing the same elements as the original
75 * list. This method handles a null list being passed to it by returning an unmodifiable empty list.
76 *
77 * @param listToCopy the list to copy
78 * @param <T> the type of the elements in the given list
79 *
80 * @return an unmodifiable copy containing the same elements as the given list
81 */
82 public static <T> List<T> createImmutableCopy(List<T> listToCopy) {
83 if (CollectionUtils.isEmpty(listToCopy)) {
84 return Collections.emptyList();
85 }
86 return Collections.unmodifiableList(new ArrayList<T>(listToCopy));
87 }
88
89 /**
90 * Takes the given set and returns an unmodifiable copy of that set containing the same elements as the original
91 * set. This method handles a null set being passed to it by returning an unmodifiable empty set.
92 *
93 * @param setToCopy the set to copy
94 * @param <T> the type of the elements in the given set
95 *
96 * @return an unmodifiable copy containing the same elements as the given set
97 */
98 public static <T> Set<T> createImmutableCopy(Set<T> setToCopy) {
99 if (CollectionUtils.isEmpty(setToCopy)) {
100 return Collections.emptySet();
101 }
102 return Collections.unmodifiableSet(new HashSet<T>(setToCopy));
103 }
104
105 /**
106 * Takes the given map and returns an unmodifiable copy of that map containing the same entries as the original
107 * map. This method handles a null map being passed to it by returning an unmodifiable empty map.
108 *
109 * @param mapToCopy the map to copy
110 * @param <K, V> the type of the key and value elements in the given map
111 *
112 * @return an unmodifiable copy containing the same elements as the given set
113 */
114 public static <K, V> Map<K, V> createImmutableCopy(Map<K, V> mapToCopy) {
115 if (mapToCopy == null || mapToCopy.isEmpty()) {
116 return Collections.emptyMap();
117 }
118 return Collections.unmodifiableMap(new HashMap<K, V>(mapToCopy));
119 }
120
121 /**
122 * This method is useful for converting a List<? extends BlahContract> to a
123 * List<Blah.Builder>. You'll just need to implement Transformer to use it.
124 *
125 * @param <A>
126 * @param <B>
127 * @param toConvert
128 * @param xform
129 * @return
130 */
131 public static <A,B> List<B> transform(Collection<? extends A> toConvert, Transformer<A,B> xform) {
132 if (CollectionUtils.isEmpty(toConvert)) {
133 return new ArrayList<B>();
134 } else {
135 List<B> results = new ArrayList<B>(toConvert.size());
136 for (A elem : toConvert) {
137 results.add(xform.transform(elem));
138 }
139 return results;
140 }
141 }
142
143 /**
144 * This method is useful for converting a Set<? extends BlahContract> to a
145 * Set<Blah.Builder>. You'll just need to implement Transformer to use it.
146 *
147 * @param <A>
148 * @param <B>
149 * @param toConvert
150 * @param xform
151 * @return
152 */
153 public static <A,B> Set<B> transformSet(Collection<? extends A> toConvert, Transformer<A,B> xform) {
154 if (CollectionUtils.isEmpty(toConvert)) {
155 return new HashSet<B>();
156 } else {
157 Set<B> results = new HashSet<B>(toConvert.size());
158 for (A elem : toConvert) {
159 results.add(xform.transform(elem));
160 }
161 return results;
162 }
163 }
164
165 public interface Transformer<A,B> {
166 public B transform(A input);
167 }
168
169 private ModelObjectUtils() {
170 throw new UnsupportedOperationException("Do not call.");
171 }
172
173 }