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